OmniAICreator/Qiita-1.07M huggingface dataset:
RubyでCSV出力

## まえがき

実務でデータをcsvにまとめて、出力してほしいといわれた。
今回はPostというオブジェクトのデータをcsvに出力してみる。

#### 使用技術
- CSV（Ruby組み込みライブラリ）
https://docs.ruby-lang.org/ja/latest/library/csv.html

## 手順

- rakeタスクの定義
- csv出力ロジックの製造
- タスク実行

## 1, rakeタスクの作成

以下コマンドで```lib/tasks/csv.rake```が生成される。

```ruby
$ rails g task ファイル名
$ rails g task csv
```

```lib/tasks/csv.rake```の中身は以下のようになっている。

```ruby
require 'csv'

namespace :csv do
	
end
```

試しにhelloを出力するだけのタスクを作成する。

```ruby
desc "test"
task greet: :environment do
	puts "hello"
end
```

タスクを実行して動作確認。

```ruby
$ rake ネームスペース名:タスク名
$ rake csv:greet
# => hello 
```

## 2, csv出力

同じようにタスクを定義。

```ruby
# 組み込みライブラリを導入
require 'csv'

namespace :csv do
	
	desc "postのデータを出力"
	task output: :environment do
		
		# csvファイルのパスを定義 
		csv_file_path = File.join(Rails.root, 'public', 'posts.csv')
		
		# generateメソッドでcsvオブジェクトを生成
		csv_data = CSV.generate do |csv|

			# csvファイルの見出し列となるデータを作成
			column_names = ["タイトル", "内容", "カテゴリー", "ユーザーID", "作成日時", "更新日時"]
			csv << column_names

			# Postの全データを取得
			posts = Post.all

			# Postの全データの値をcsvデータに追加
			posts.each do |post|
				column_values = [
					post.title,
					post.content,
					post.category,
					post.user_id,
					post.created_at,
					post.updated_at,
				]
				csv << column_values
			end
		end

		# ファイルのパスとcsvデータを指定して、csvファイル作成
		File.write(csv_file_path, csv_data)
	end
end
```

## 3, タスク実行

タスクを実行するとcsvファイルが作成される。

```ruby
$ rake csv:output
```

作成したファイルはgoogleスプレッドシートなどにアップロードして確かめるといい。

![スクリーンショット 2024-02-10 17.15.26.png](https://prod-files-secure.s3.us-west-2.amazonaws.com/ab880e92-5159-48dc-8a6e-1e272b5a5ba1/53e0b61f-0428-461f-8d6c-3d456edf8e5b/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2024-02-10_17.15.26.png)

いい感じに行けた。以上。
HTML5プロフェッショナル認定試験レベル1 合格体験記

この度、HTML5プロフェッショナル認定試験レベル1に合格しました。

この記事では、学習時間や活用したサイトなどを紹介します。


# 【自己紹介・受験の動機】
* 文系4大卒
* エンジニア歴4年目
* SIer企業勤務
* フロントエンド開発の実務経験あり

　新卒未経験で現在勤めている会社に就職し、実務の中で仕事を覚えてきました。
　来年で5年目ということもあり、ここいらで一度基礎から勉強したいと思い受験に至りました。

# 【HTML5プロフェッショナル認定試験とは】
公式サイトには以下のように記載されています。

> HTML5プロフェッショナル認定とは、HTML5、CSS3、JavaScriptなど最新のマークアップに関する技術力と知識を、公平かつ厳正に、中立的な立場で認定する認定制度です。
> マルチデバイスに対応したWebコンテンツ制作の基礎の実力を測るレベル1と、システム間連携や最新のマルチメディア技術に対応したWebアプリケーションや動的Webコンテンツの開発・設計の能力を認定するレベル2で構成されています。

要はフロントエンドの知識を問う資格試験です。
5つのセクションに分かれており、65/100点以上で合格です。

https://html5exam.jp/outline/

# 【学習方法】
そこそこメジャーな試験なのでいろんな教材が出ています。

どれがいいのかなぁと調べていると、
教材を買わずに「[**Ping-T**](https://ping-t.com/)」というサイトの利用のみで合格したという情報がちらほら出てきました。

Ping-Tは有料の実習サイトで、LPICやAWSなど様々な資格の問題や、本番さながらの模擬試験を受けることができます。
しかも試験受験チケットを販売しており、実際の試験の定価よりも安く受験することができるのです。

教材を買っても邪魔だし、「教材代 + 受験代」よりも「Ping-T + 受験代」の方が安かったのでPing-Tのみを使用して受験に挑みました。

HTML5プロフェッショナル認定試験の場合、480問を超える問題を受けることができます。

出題問題の形式としては全て４択問題です。（本番は数問記述問題があります）

実務経験もあるので簡単だろうと思っていましたが、はじめに受けた模擬試験は正答率55%ほどでした。
これはまずいと思い本腰を入れました。

やったことはシンプルで、
**間違えた問題の解説を読み、理解する**だけです。

サイトの模擬試験で90%を超えられるまでひたすらに繰り返しました。


# 【試験結果】
| 合格ライン | 取得スコア |
|:-:|:-:|
| 65点  | 76点  |

思っていたよりギリギリでした、、、。

1月14日から勉強を開始し、受験したのが2月10日。
時間で言うと20時間くらいはしたのかなぁと思います。

試験の6、7割はPing-Tの内容と似たようなのが出題されました。
なので内容をしっかりと理解していれば、Ping-Tのみでの合格も全然可能です。

# 【最後に】
 今回、無事に合格することができたので、次はレベル2に挑戦しようかなぁ。

 最近は受けたい試験や勉強したいことがたくさんあります。
 今回が初投稿でしたが、アウトプットも兼ねて今後もちょくちょく記事を投稿していきたいなと思います。

 この記事が誰かの役に立てば幸いです。
 それでは。
TODOアプリをTDDしながら作ってみる


# 目次
[はじめに](#はじめに)
[使用技術](#使用技術)
[使用するもの](#使用するもの)
[さっそくViteプロジェクトを生成してみる](#さっそくViteプロジェクトを生成してみる)
[次回のお知らせ](#次回のお知らせ)

# はじめに
この記事では、TODOアプリを環境構築から作っていく様子を、少しずつ投稿していきます。
「もっとよいテストの書き方あるよー」とか、「こっちのが実装わかりやすいかもー」とか、フィードバックをいただけると嬉しいです！

今回はViteプロジェクトを生成するところまでやってみたいと思います！
環境構築って一番最初しかやらないから分からないこと多い😅

# 技術スタック
- Frontend
  - TypeScript
  - React
  - Vite
  - Vitest
- Backend
  - Kotlin
  - Spring Boot
- Data Base
  - PostgreSQL

# 使用するもの
- MackBook Pro
- IntelliJ IDEA (Ultimate Edition)

# さっそくViteプロジェクトを生成してみる
### 1. 任意の場所にディレクトリを作る
今回は `todo-app-tdd` というディレクトリ名で作っていきます。
ソースコードは GitHub で管理していきたいと思います。

### 2. Viteプロジェクトを生成する
[Vite](https://ja.vitejs.dev/guide/) の公式ページを見ながらやってみます。

Viteプロジェクトを生成します。
ターミナルを開いて `todo-app-tdd` のディレクトリまで辿ったら
```
npm create vite@latest
```
コマンド実行後は画面の表示に従って選択していけばOKらしい。
何が表示されるか順に見ていきます。
まずこれ↓
```
Need to install the following packages:
create-vite@5.2.0
Ok to proceed? (y)
```
以下のパッケージをインストール必要があるけど、続けても大丈夫？って聞かれています。
ここは `y` を押して続けます。
```
? Project name: ›
```
プロジェクト名どうする？って聞かれているので、
今回は `frontend` としておきます。
（ここでのプロジェクト名とはディレクトリ名のことを指していて、ここにパッケージの構成ファイルが入ります。）
```
? Select a framework: › - Use arrow-keys. Return to submit.
❯   Vanilla
    Vue
    React
    Preact
    Lit
    Svelte
    Solid
    Qwik
    Others
```
フレームワークを矢印キーで選んでね〜。と言っているので、
`React` を選びます。
```
? Select a variant: › - Use arrow-keys. Return to submit.
❯   TypeScript
    TypeScript + SWC
    JavaScript
    JavaScript + SWC
```
使いたい言語は `TypeScript` だけど、`SWC` って何だろう？？

#### SWC
・Speedy Web Compiler の略
・Rust 製の高速なコンパイラ
・Deno や Next.js、Vite をはじめとした様々なツールの内部で採用されている
・env という Babel の preset-env 相当の機能も備えているため、本番ビルドでも十分使える

ふ〜ん。。。
分かったような分からないような・・・。
でも SWC なんだか速そうな印象なので、`TypeScript + SWC` を選択します！
```
Scaffolding project in /***/todo-app-tdd/frontend...

Done. Now run:

  cd frontend
  npm install
  npm run dev
```
どうやら完了したらしい。
ターミナルの指示に従って、コマンドを実行してみよう。
```
cd frontend
```
Vite 公式ページに、[Node.js](https://nodejs.org/) のバージョンについて言及されているので、18+、20+ のバージョンが入っていることを確認します。
```
node -v
```
私は v16.20.2 と表示されたので、バージョンを上げたいと思います。
この記事を書いている時点で、Node.jsは 20.11.0 LTS とのことなので、これを入れていきますー。
(私は node のバージョン管理に、[Volta](https://volta.sh/) を使っています。)

Node.js のバージョンが整ったら
```
npm install
```
```
npm run dev
```
↑これを実行すると、↓このようにターミナルに表示されるので
```
VITE v5.1.1  ready in 404 ms

➜  Local:   http://localhost:5173/
➜  Network: use --host to expose
➜  press h + enter to show help
```
Chromeブラウザで、`localhost:5173` を開いてみます。

おっ！！！表示されてるっ！！！
ボタン押すとカウントアップする機能あるじゃん。すご。
![vite-start-page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695365/2e706068-8ec5-b24b-352c-b299026a175a.png)

むふふ。なんか満足しちゃった(笑)
git に commit します！
commit message: Viteプロジェクトを生成した

今回はここまでにします。

GitHubのリポジトリはこちらになります→[https://github.com/b-yuko/todo-app-tdd](https://github.com/b-yuko/todo-app-tdd)
なんか途中でコミットログがぐちゃぐちゃになりそうだけど、ご愛嬌ってことで温かい目で見守ってください<(_ _*)>

# 次回のお知らせ
~~[ESLint](https://eslint.org/)、[Prettier](https://prettier.io/)の設定とか、テストできる環境とか整えていけたらいいなと思っています。~~
README を読み解きながら、ESLint の設定をします。
記事はこちら 👉 https://qiita.com/b-yuko/items/299e2c92f3f810186f5b
<br><br><br>


[目次に戻る](#目次)
MySQL、PostgreSQL、OracleDBの違い

|違い| MySQL | PostgreSQL | OracleDB |
|:-----------|:-----------|------------:|:------------:|
| 空文字の扱い       | 長さ0の文字列として扱う       |長さ0の文字列として扱う        | NULLと空文字を区別しない。自動的に空文字をnullに変換         |
| AutoCommit機能       | デフォルトでは自動コミット     | デフォルトでは自動コミット      | デフォルトでは自動コミットでない       |
| ライセンス       | OSS       | OSS        | 商用         |
| テーブル名、カラム名の先頭に半角数字       | 不可         | 不可          | 可           |
| 複合主キー       | 可       | 可       | 可       |
| Date型       | 日付のみで、時刻は保持しない    | 日付のみで、時刻は保持しない     | 秒まで保持する      |
| 対応しているトランザクション分離レベル       | READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE    | READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE     | READ COMMITED、SERIALIZABLE      |
| スキーマの概念       |  データベースと同義   | データベースともユーザとも異なる概念     | ユーザと同義      |
| 取得レコード数制限       | limit    | limit     | ROWNUM      |
PostgreSQLで、where inとwhere =の性能比較

SQLにおいて、大量のレコードを取得するとき、
```sql
select * from テーブル名 where comment_id = 1;
select * from テーブル名 where comment_id = 2;
select * from テーブル名 where comment_id = 3;
```
を繰り返す方法と、

```sql
select * from テーブル名 where comment_id in (0,1,2,3,......）;
```
で一括で取得する方法があります。

後者の方が高速だというのは常識的なことだとは思いますが、実際どの程度の性能差があるのか？というのが気になったので、少し遊んで実験してみました。

Windows PowerShellで、コマンドの実行時間を計測するためのコマンドとして、Measure-Commandがあるので、これを使います。

## 10万件取得の場合

1件取得クエリ*10万回
```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments.sql > result.txt }
```

```:実行結果
TotalSeconds      : 41.5504978
TotalMilliseconds : 41550.4978
```

100000件取得クエリ*1回
```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments.sql > result.txt }
```

```:実行結果
TotalSeconds      : 15.3717338
TotalMilliseconds : 15371.7338
```

約2.7倍差でした。

*****
1万件と5万件の場合も実行はしてみました。
ただし、先に上記の10万件を実行しています。

同じクエリを流すと、2回目以降だとキャッシュのせいで高速化されるのであまり意味ないですね、、、PostgreSQLにおいてはクエリ結果のキャッシュ（結果キャッシュ）を直接削除する機能はないので、ここで打ち切ります。

## 1万件取得の場合

1件取得クエリ*1万回
```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments10000.sql > result10000.txt }
```

```:実行結果
TotalSeconds      : 5.8080719
TotalMilliseconds : 5808.0719
```

10000件取得クエリ*1回
```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments2_10000.sql > result10000_2.txt }
```

```:実行結果
TotalSeconds      : 3.9993424
TotalMilliseconds : 3999.3424
```

約1.4倍差でした。

## 5万件取得の場合

1件取得クエリ*5万回
```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments50000.sql > result50000.txt }
```

```:実行結果
TotalSeconds      : 16.7541638
TotalMilliseconds : 16754.1638
```


50000件取得クエリ*1回

```:実行コマンド
Measure-Command { psql -U postgres -d sampledb -f select_comments2_50000.sql > result50000_2.txt }
```

```:実行結果
TotalSeconds      : 6.1022535
TotalMilliseconds : 6102.2535
```
2.7倍差でした。
せんせー、ソニックブラックホールってなに？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/2c47de5a-d81a-78f9-53c1-4d31d8398c36.png)

キーンコーンカーンコーン...
授業が始まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/be1492ca-910f-2708-d0fa-8fcfcf14af73.png)

せんせー、ソニックブラックホールってなに？

# ソニックブラックホールとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/da229491-9c49-fb7a-a542-417180e256a7.png)

## ソニックブラックホールって何？

ソニックブラックホールっていうのは、ちょっと変わったブラックホールの話だよ。普通のブラックホールは、宇宙にあって、光さえも吸い込んじゃうとっても強い力を持っているんだけど、ソニックブラックホールは、光じゃなくて、音に関係しているんだよ。

## ソニックブラックホールって何？

想像してみてね。もし水の流れがすごく速くて、その中で魚が上流に泳ごうとしても、水が速すぎて全然前に進めないってことがあるよね。ソニックブラックホールもそれに似ていて、音がある特定の場所から抜け出せなくなる現象なんだ。

## どうやってできるの？

科学者たちは、特別な実験をして、水や空気がすごく速く流れる状況を作り出すんだ。そうすると、その流れの中では、音が一方向にしか進めなくなるんだよ。この音が戻ってこれない場所が、まるで宇宙のブラックホールみたいに、音を吸い込んでしまうから「ソニックブラックホール」と呼ばれているんだ。

## なんで研究するの？

ソニックブラックホールを研究することで、科学者たちは宇宙のブラックホールがどうやって動いているのか、また、光や音がどうやってその強い力に引っ張られるのかをもっと理解できるようになるんだ。それに、宇宙の不思議な現象を地球で再現してみることができるから、とっても興味深いんだよ。

# まとめ

ソニックブラックホールは、音が特定の場所から抜け出せなくなるような現象で、宇宙のブラックホールの勉強にも役立っているんだ。科学者たちがこの不思議な現象を使って、宇宙の謎を少しずつ解き明かしているんだね！
Javaの数値型のあれこれ

# 始めに

Javaの数値型にはint型,float型,double型の他にもbyte型,short型,long型などのデータ型が存在します。

byte型,short型,long型はいずれも整数型です。

byte型,short型はint型よりビット数が少ないので小さな値を格納するのに適しています。
long型はint型に収まりきらない数値を表記出来ます。

# Javaの数値型

<table>
<caption>Javaの数値型</caption>
  <thead>
   <tr>
      <th>データ型</th> <th>ビット数</th>
    </tr>
  </thead>
  <tr>
    <td> byte </td> <td> 8ビット</td>
  </tr>
  <tr>
    <td> short </td> <td> 16ビット</td>
  </tr>
  <tr>
    <td> int </td> <td> 32ビット</td>
  </tr>
  <tr>
    <td> long </td> <td> 64ビット </td>
  </tr>
  <tr>
    <td> float </td> <td> 32ビット</td>
  </tr>
  <tr>
    <td> double </td> <td> 64ビット</td>
  </tr>
</table>

# 代入時の型変換のルール
意味的な大小関係は、上記の表の上に行くほど小さく、下に行くほど大きいです。
代入先が代入元より大きな型の時、自動的に型変換が行われます。
また、数値型に文字型などの異なるデータ型を代入する事はできません。


# 参考資料
https://www.sejuku.net/blog/48345#index_id1
https://life-freedom888.com/int-max-min-value/#toc3
GithubのPersonal Access Tokenの期限が切れた

## 事象
### git pushに失敗する

```terminal:ターミナル
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/Githubのユーザー名/リポジトリ名/'
```
## 原因
- Personal Access Tokenの期限が切れたため

## 解決策
1. githubaから新しいセキュリティトークンを発行
以下、参考リンクを読みながら発行しました
2. git pushを実行
```terminal:ターミナル
git push https://アクセストークン@github.com/Githubのユーザー名/リポジトリ名.git main
Username for 'https://github.com': Githubのユーザー名
Password for 'https://workout38@github.com': 発行したToken
```
　　　　　　

## 参考リンク
1. [GitHubのPersonal Access Tokenが期限切れした場合の対処](https://qiita.com/zakino123/items/907a4db7c49e6378f568)
2. [git cloneでremote: Support for password authentication was removed on August 13, 2021.エラーが出た時の解消法](https://qiita.com/aramasa_ash/items/3accb139d0296896caa2) 
## 最後に
最後まで読んでいただきありがとうございました。
【Flutter】名前付き引数で可読性を上げる！

## はじめに
flutterに名前付き引数という便利なものを知ったので記録します。

## 名前付き引数とは
名前付き引数とは、関数やコンストラクタにおいて、引数を渡す際に、その引数の名前を明示的に指定する方法のことです。これにより、引数の順序を気にすることなく渡すことができます。コードの正確性と可読性が大幅に向上します！

## 例
```dart
Widget buildBox({
  required double width,// requiredでこの引数を必須にする
  required double height,　
  Color color = Colors.red, // デフォルト値を持つ名前付き引数, requiredではないため引数は必須でない
}) {
  // 関数の本体
}
```
```dart
 buildBox(width: 50, height: 40),
```
外部サイトへのGoogleDrive画像差し込み方法

## はじめに
GoogleDriveの画像差し込みについて、現在公開されている記事の多くでは以下の手順での埋め込み方になっています。

```
共有リンクを取得
https://drive.google.com/open?id={ファイルID}
https://drive.google.com/file/d/{ファイルID}/view?usp=sharing
↓
公開URL化
http://drive.google.com/uc?export=view&id={ファイルID}
````

しかし、昨年10月ころのアップデート

https://workspaceupdates.googleblog.com/2023/10/upcoming-changes-to-third-party-cookies-in-google-drive.html

の影響か、**今までの手法では各種外部サイトにGoogleドライブからの直共有ができなくなっています。**
（画像が ![このように](https://)破損表示になります）

そして、調べていたところ以下の形であれば解決することが判明したので共有します。

## 手段
ファイルIDの取得方法は変わりません。
URLを以下のようにします。
```
https://lh3.google.com/u/0/d/{ファイルID}=w{幅px}-h{高さpx}-iv1
```
このURLはGoogleドライブで画像をプレビューしたときに、対象を示すHTMLソースでimg srcで表示されるものと同じです。
既存の方法だった
```
http://drive.google.com/uc?export=view&id={ファイルID}
```
では、表示サイズを指定することはできませんでしたが、HTMLにはなじみの深いパラメータであるWidthとHeightが含まれているため、自由にサイズを制限することが可能になっています。
なお、Markdown対応のページでは今までと変わらず
```
![Alt name](URL)
```
の形式で表示できるため、URLの部分を今回ご説明したURLに変えるだけで済みます。

## 注意事項
よくある失敗としては、アクセス権です。
この機能は、あくまでアクセスする側が対象の画像ファイルにアクセス権がある必要があります。
つまり、外部向けなら「リンクを知っている人全員」に共有する必要があります。
GoogleWorkspaceを利用している組織内であれば、組織内の共有事情に合わせて、公開パターンを作っておくのも一つの手かもしれません。

## 余談
詳しく調べてはいませんが、URLの形式的に
lh3.google.com
はGoogle Photosで使われる外部共有リンクの
lh3.googleusercontent.com
とほぼ同じ扱いになっているかと思います。（DBサーバーが同じではないか）
その為、こちらのサイト

https://www.sukerou.com/2019/01/googleurl.html

にあるような
* s0＝原寸大表示
* c＝正方形表示
* d＝ファイルダウンロード

のパラメータも利用可能かと思います。
【Playgrounds】コードを学ぼう2「ワープを正しく操作する」の解説

# この投稿は…

iPadとMacで提供されているAppleの無料アプリ「Swift Playgrounds」には「コードを学ぼう」が収録されています。
これは、ステージに設定されている目標を達成していくことで、Swiftプログラミングを基本的なレベルからアルゴリズムまで学ことができます。

Mac版「[Swift Playgrounds](https://apps.apple.com/jp/app/swift-playgrounds/id1496833156?mt=12)」
iPad版「[Swift Playgrounds]()」

この投稿では、**コードを学ぼう2** のステージ「ワープを正しく操作する」について、解説します。

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。
> また、Swiftプログラミングを基礎から動画で学びたい方には、Udemyコース「[今日からはじめるプログラミング](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwii1qTuj_2BAxV4hlYBHbj5BqEQFnoECBYQAQ&url=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fstart-programming-today%2F&usg=AOvVaw2vs4Sccq-bpfA4ZD2rCyNm&opi=89978449)」をお勧めします。

# このステージの目標

2組あるワープのオンとオフを切り替えて、4つの宝石を集める。

![ワープを正しく操作する.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70476/e8d8d1ae-21d3-2473-a3b6-8fe8d1804e08.png)

## 考え方と手順

2つのポータル（青とピンク）をうまく切り替えながら進まないといけないので、ややこしいと感じてしまうかもしれない。
だが、このステージのジェムは場所と数が固定されている。
まずは、余計なことは考えずに「ジェムを4つ集めるまで、まっすぐ歩き続ける」ことを考えよう。

キャラクターが真っ直ぐ歩き続けると、すぐに青のポータルで無限ループに陥ってしまう。
青のポータルで一回ワープした後にジェムをひとつ取ったら、青のループは無効にしておきたい。
これは、キャラクターが行き止まりにいるタイミングだ。
つまり、「行き止まりなら、青のポータルをオンからオフに切り替える」というIfステートメントがいいだろう。
そうすれば、「同じ道にある2つ目のジェム」を回収しに行ける。
そのまま直進すると行き止まりになるので、今度は「青のポータルをオフからオンに切り替える」ことになる。

さて、「ポータルがオンならオフに、オフならオンに切り替える関数」があると便利そうだ。
`togglePortal()`関数を定義しておこう。

無事、元の道に戻ってくるが、今度はピンクのポータルでワープした後、無限ループに陥ってしまう。
この問題を解決するには「青のポータルがオンの時にピンクはオフで、青のポータルがオフの時にピンクはオン」にできればいい。
`togglePortal()`関数では青のポータルだけでなく、ピンクのポータルも切り替えられるだろう。
そして、キャラクターが動き始める前に、あらかじめピンクのポータルだけオフに設定しておけば問題は解決だ。

### 擬似コード

```
ピンクのポータルを無効にする
ジェムを4個集めるまで、以下を繰り返す
    前に進む
    ジェムがあったら、集めて数える
    行き止まりだったら、後ろを向いてポータルを切り替える
```

## 全体のコード

```swift
var gemCounter = 0

func turnAround() {
    turnLeft()
    turnLeft()    
}

func collectAndCountGem() {
    if isOnGem { 
        collectGem()
        gemCounter += 1
    }    
}

func togglePortals() {
    if bluePortal.isActive {
        bluePortal.isActive = false
        pinkPortal.isActive = true
    } else {
        bluePortal.isActive = true
        pinkPortal.isActive = false
    }
}

pinkPortal.isActive = false
while gemCounter < 4 {
    moveForward()
    collectAndCountGem() 
    if isBlocked {
        turnAround()
        togglePortals()        
    }
}
```
ubuntuでコマンドラインから短いパスワードを設定する方法

## Ubuntuのパスワードを短く設定したい

- Ubuntuのパスワードを変更するコマンドは、`passwd`
- デフォルトだと8文字以上必要だったりとバリデーションが必要で、これをクリアしないと更新できない

```bash
Changing password for akiralab.
Current password: 
New password: 
BAD PASSWORD: The password contains the user name in some form
New password: 
BAD PASSWORD: The password fails the dictionary check - it does not contain enough DIFFERENT characters
New password: 
BAD PASSWORD: The password is shorter than 8 characters
```

- ただ、毎回打つことを考えると短いパスワードで済ませたい（セキュリティが甘くなることはもちろん注意）

https://askubuntu.com/questions/180402/how-to-set-a-short-password-on-ubuntu

## そんな時は、`sudo passwd {username}`でバリデーションなしの任意のパスワードが設定できる

```
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
passwd: password updated successfully
```

- 文句を言われるが、短いパスワードでも登録できる
ネイティブ開発か、クロスプラットフォーム開発か

## はじめに

モバイルアプリの開発として, ネイティブ開発にするかクロスプラットフォーム開発でFlatterやReactNativeを使うか、今でも議論が絶えません。
現在Androidのリードエンジニアとして働いている自分から見て、どう選定するかを個人的な意見を書きたいと思います。選定の方法として絶対正しい、はないと思いますので参考までにしていただければと思います。
下のような記事の内容はすでに把握している方が対象です。

https://circleci.com/ja/blog/native-vs-cross-platform-mobile-dev/

## 前提条件
 iOSとAndroidの両OSでアプリを作る必要がある場合を想定

## 自分の経歴

自分のモバイルアプリ歴として、ざっくり書いておきます。

* Swift
  - Swift UIで個人開発3件　
  - 100万円以上の収益化に成功しているアプリあり
  - 経歴は1.5-2年ほど

* Kotlin
  - 個人開発で2件
  - 経歴は1年ちょい
  - 現在リードエンジニア
  - 主にJetpack Composeを使用

* ReactNative
  - 実務で1年半ほど
  - ネイティブ機能のブリッジ実装やライブラリ選定経験あり

* Flutter: 
  - 実務で3ヶ月ほど
  - といっても実装経験はほとんどない
  - 環境設定まわりの支援

このようなバックグラウンドの自分ならどのように選定するかを述べたいと思います。

## 結論

クロスプラットフォームの　React Native or Flutter を第一候補とします。
しかし、次のような状況の場合はネイティブ開発を選びます。

* 開発予算が潤沢である場合

* 先進的なネイティブ機能を使う場合

* 非機能要件がシビアな場合

* 組み込みライブラリを必要とする場合

## クロスプラットフォーム　ファーストの理由

まず、Flutter or React Nativeを使うのをお勧めします。色々あるけど、やはりiOSとAndroidのコードを共通化できる恩恵はコスト的に恩恵が非常に大きいです。開発予算を純粋に抑えられるのと、 iOSとAndroidの差異が限りなく小さくできます。

ネイティブ開発で作るとして、仕様が不明瞭な場合の時には、そもそもの実装者の仕様認識の相違からそれぞれのOSで挙動が若干違うということも少なくありません。
単純な実装コストだけでなく、このよう認識不足によるバグのコスト等も考慮すると、遥かにクロスプラットフォームを使うメリットが大きくなります。

***
### Flutter vs React Native

このどちらからを使うかは、個人的にはReact Native　をお勧めします。

#### 実装的な観点

実装的な観点からは、正直flutterの方が使いやすい印象です。特に環境周りの設定がとても楽なので、使い始めるまでがスムーズです。おそらくこれが初心者にも人気な理由だと思っています。

一方で、拡張性という点ではReactNativeの方ができることは多いです。やはりWebフロントで使われるライブラリをそのまま使えることがほとんどなので、基本的にwebフロントでできることはReactNativeでもできます。

#### ビジネス的観点

これはReact Nativeが勝ります。単純にReactを書くことができれば、最初の環境構築の壁さえ乗り越えればほぼReactと同じとして扱えるからです。
フロントの主流はReactになってきているので、エンジニアも集めやすいですし、同様にWebのReactの現場へもいけるエンジニアになります。

Flutterで使われるDartはどうしても他への潰しが効きにくいので、これはReact Nativeが勝ると思っています。


:::note warn
[React Native Expo](https://expo.dev/)はまだ使うべからず！

いくつかの現場を見てきましたが、Expoはまだ使うべきでないというのが個人的な意見です。導入自体は楽になりますが、開発を進めていくとライブラリの制限や、認証周りの挙動などで不具合があったりするのでお勧めしません。普通のbareを使いましょう。
もう少し整備されてから使うのはアリかとは思います。
:::



## ネイティブで実装する方が良い例

### 資金が潤沢である場合

資金が潤沢であり、コストを気にしなくて良いのであればネイティブにすべきです。ライブラリがまずApple と Googleによって作られたものが基本なので、それらを使うことで信頼性の高く、パフォーマンスの高いアプリを作ることができます。
ReactNativeの場合はバージョンによってライブラリが使えなくなったり、バグが起きるのは日常茶飯事ですのでライブラリ1つ導入するにしても精査が必要です。(Flutterではあまりそういうことはないようですが...) 
ネイティブ開発ではこのようなことが(ほとんど)起きないのは開発経験としてもとても良いです。

さらに、クロスプラットフォームとは違い、それぞれのプラットフォームで発表された最新の技術をすぐに導入できるのも強みだと思います。

ネイティブ開発の方ができることは多く、さらに強固なアプリになるので資金がある(大企業)などであれば普通はネイティブ開発を選択します。

### 先進的な機能を使う場合

上記にも述べましたが、ARなど最新機能を使う場合はそもそもクロスプラットフォームではサポートされてないことが多いので、必然的にネイティブ開発になります。
(実はクロスプラットフォームでもネイティブブリッジによる実装をすれば最新機能を使うこともできるはずなのですが、実装が煩雑で難易度も高く情報が少ないのでお勧めしません。)

### 非機能要件がシビアな場合

基本的に、パフォーマンスの面ではネイティブアプリ開発の方が良いです。
例えば、カメラの起動時のスピードなどでネイティブ開発とクロスプラットフォームで性能に差異があり、どうしてもクロスプラットフォームの方が悪く(起動が遅かったり、ビルド後のアプリの容量が大きくなったり...)なります。
そのため、このような非機能要件が厳しい場合にはネイティブによる開発が必要です。

### 組み込みライブラリを必要とする場合

組み込みライブラリ（Rustライブラリなど)の実装をする場合も、ネイティブがお勧めです。 これもクロスプラットフォームでもブリッジ実装すればできますが、わりと煩雑な構成になり難易度も高くバグの温床になりがちです。(経験済み)

逆にこれを(完璧に)実装できるクロスプラットフォーム開発経験者がいるのであれば、そちらでも問題ない気はしています。

## まとめ

* まずはクロスプラットフォーム開発を考える
   - React Nativeの方がお勧め
* 特定の条件下においてはネイティブ開発を選定する
az cliでサクッとVM作る

# はじめに
頭空っぽにして作りたいときに。
※昔書いて下書きのままで寝かしてたやつ。すっかり日が経ったし挙げることにした

# コマンド

```
# SSH キーペアを Azure で作成する
az sshkey create -g pro-nabehiro-001 -n nabehiro-sshkey

# ローカルに保存されたファイル名が以下の例のように表示されます
Private key is saved to "/home/user/.ssh/7777777777_9999999".
Public key is saved to "/home/user/.ssh/7777777777_9999999.pub".

# 作成した SSH 公開キーを指定して VM を作成します
az vm create --resource-group pro-nabehiro-001 --name myVM --image UbuntuLTS --ssh-key-name nabehiro-sshkey




# NSG に自分の IP アドレスから SSH 接続出来るようにします
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --name Allow-SSH \
  --nsg-name ${prefix}-vmNSG \
  --priority 100 \
  --source-address-prefixes $(curl -s inet-ip.info) \
  --destination-port-ranges 22 \
  --access Allow \
  --protocol Tcp

# SSH 秘密キーを使用して SSH 接続します
ssh -i ~/.ssh/7777777777_9999999 azureuser@$(az vm show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --show-detail \
  --query publicIps \
  --output tsv)

# リソースグループを削除します
az group delete \
  --name ${prefix}-rg

# 作成した SSH キーペアを削除します
rm -f ~/.ssh/7777777777_9999999*
マイクからの音声入力でLLMと話す(Whisper.cpp の example を利用)

## TL;DR
1. WhisperはOpenAIによって開発された音声認識システムで、多言語対応の高精度なテキスト変換機能を提供します。
2. `whisper.cpp`はWhisperモデルのC++実装であり、マイク入力からのリアルタイム文字起こしや、音声ベースのアプリケーション開発を容易に行うことができます。
3. 修正された`whisper.cpp`と`llama.cpp`を組み合わせることで、マイクからの日本語音声入力を基にLLMと日本語で対話するシステムを構築できます。

## 使用環境
- MacBook Pro
- CPU : Apple M2 Pro, 12core
- MEM : 32 GB
- OS : Sonoma 14.2.1

## whisper と whisper.cpp

WhisperはOpenAIによって開発された最先端の音声認識システムであり、様々な言語の音声をテキストに変換する能力を持っています。このシステムは、公開されているモデルを通じて、広範囲の言語や方言に対応し、さまざまな音声の環境下で高い精度の音声認識を実現します。特に、雑音が含まれる環境やさまざまな話者の声にも強く、リアルタイムでの使用にも適しています。

`whisper.cpp`は、WhisperモデルをC++で実装したもの. 特に Mac での動作にして聞かされています. この実装例を通じて、開発者はWhisperモデルを自分のアプリケーションに組み込む方法を学ぶことができ、マイクから直接音声を入力し、リアルタイムでの文字起こしや、さらには音声を基にした会話AIとのインタラクションを実現することが可能です。また、`whisper.cpp`を使用することで、Whisperの強力な音声認識機能を活用し、様々な言語での対話システムや音声ベースのアプリケーション開発を容易に行えます。

この記事では、`whisper.cpp`を日本語化し、マイクからの音声入力を文字起こしした後、それを用いてLLM(Language Learning Model)と会話する talk-llama という例を修正することにより, 日本語を用いたLLMとの対話を実現させた.


https://github.com/nagato0614/whisper.cpp.git

## whiper.cpp での文字起こし

本家は以下のリポジトリにあります.
https://github.com/ggerganov/whisper.cpp

後々, talk-llamaをクローンするので下記のフォークしたリポジトリを利用すると楽かも
https://github.com/nagato0614/whisper.cpp

基本的な使い方はリポジトリにありますが,
まずリポジトリをクローン

```bash
git clone https://github.com/ggerganov/whisper.cpp.git
```

ソースコードのビルド
```bash
make
```

モデルのダウンロード.
日本語で使えるようにするため, モデル名の末尾にある, ```.en``` がないモデルをダウンロードしてください.
```bash
bash ./models/download-ggml-model.sh base
bash ./models/download-ggml-large-v3.sh base
```

そして実行.
オプションはそれぞれ,
- ```-l ja``` :  使用言語を日本語に
- ```-t 4``` : 使用するスレッド数
- ```-m ./model/ggml-base.bin``` : 使用するモデルの選択

下記のコマンドを実行するとマイクからの入力から文字起こし可能です.
```bash
./stream -l ja -t 4 -m ./model/ggml-base.bin
```

## llama.cpp の準備
llm との会話する部分は llama.cppを使用する.

以下のリポジトリからクローン.
whisper.cppとおなじクローンしてください.
ディレクトリ構成は以下のような感じ
- ./
  - llama.cpp
  - whisper.cpp

https://github.com/ggerganov/llama.cpp.git

クローン後ビルド
```bash
cd llama.cpp
make
```

モデルのダウンロードは huggingface に公開されているものをダウンロード.
自分がダウンロードしたのは, ```swallow-7b-instruct.Q4_K_S.gguf```.
違いはイマイチわかっていない. :rolling_eyes: 
ダウンロードしたモデルは ./models に保存

https://huggingface.co/TheBloke/Swallow-7B-Instruct-GGUF/tree/main


- -m ./models/swallow-13b-instruct.Q6_K.gguf : 使用するモデルを指定
- -n 256 : 生成するトークン（単語や文字列の単位）の数を指定
- --repeat_penalty 1.0 : 繰り返しペナルティを指定
- --color : 出力に色を使用するオプション
- -i : 対話モードで実行
- -r "User:" : 入力の際にユーザーからの発言を示すプレフィックス（接頭辞）を指定
- -f : 事前に入力するプロンプト


```bash
./main -m ./models/swallow-13b-instruct.Q6_K.gguf -n 256 --repeat_penalty 1.0 --color -i -r "User:" -f ./prompts/chat-with-bob.txt
```

## whisper.cpp + llama.cpp

whisper.cpp の example ディレクトリが存在しており, whiper.cpp ディレクトリないでビルドすることが可能.
今回使用するexample も以下のようにビルドすることができる.
```bash
make talk-llama
```

今回修正したコードは本形をフォークしたリポジトリをクローンすることで使用することができる.
whisper.cpp, llama.cpp と同じ階層にクローンする.
準備はwhisper.cpp と同様にしておく.

https://github.com/nagato0614/whisper.cpp

```bash
git clone https://github.com/nagato0614/whisper.cpp
cd whisper.cpp
make talk-llama
./talk-llama  -mw ./models/ggml-large-v3.bin -ml ../llama.cpp/models/swallow-7b-instruct.Q4_K_S.gguf  -p "User:" -t 8  -l ja
```

これで日本語を用いてllmと対話が可能になる.
日本国憲法をBardでJ-POP風に歌わせてみた

# 概要

日本国憲法をBardでJ-POP風に歌わせてみました。再生結果は棒読みになっていましたが、曲をつければ歌えそうです。

# 詳細

質問文は以下の通りです。
```
日本国憲法をJ-POPで歌ってみてください。
```

回答は以下の通りでした。
```
日本国憲法 J-POP風
(Verse 1)
空を見上げて 未来を描こう
戦争のない 世界を夢見て
平和主義を 掲げた憲法
それは希望の 光

(Chorus)
国民主権 基本的人権
自由と平等 守り続ける
日本国憲法 僕らの誇り
未来へ繋ぐ 宝物

(Verse 2)
戦後の苦難 乗り越えて
民主主義を 築き上げてきた
三権分立 国会の役割
法の下の 平等

(Chorus)
国民主権 基本的人権
自由と平等 守り続ける
日本国憲法 僕らの誇り
未来へ繋ぐ 宝物

(Bridge)
時代は変われど 変わらない
平和への願い 憲法に込め
多様性を 尊重し 共に
歩んでいこう 未来へ

(Chorus)
国民主権 基本的人権
自由と平等 守り続ける
日本国憲法 僕らの誇り
未来へ繋ぐ 宝物

(Outro)
未来へ 未来へ 響き渡る
平和の鐘 憲法と共に
希望の光 照らし続ける
日本国憲法 僕らの誇り

(Guitar Solo)

(Chorus)
国民主権 基本的人権
自由と平等 守り続ける
日本国憲法 僕らの誇り
未来へ繋ぐ 宝物
```

# まとめ
何かの役に立てばと。
MySQLで3つ以上のテーブルを完全外部結合する方法

# はじめに
MySQL(8.0)では完全外部結合(FULL OUTER JOIN)が使えません。そこでJOIN句とUNION句を使って完全外部結合の結果を返します。他の記事だと2テーブルに対しては方法がすでに紹介されているので本記事では3テーブル以上の場合はどうするかを紹介します。

# 2テーブルの場合
数学のテストを受けた学生と点数のテーブル(math)と英語のテストを受けた学生と点数のテーブル(english)を結合します。どちらかのテストのみ受けた人も表示したい場合はstudentカラムをキーとした完全外部結合を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579871/4d4b7855-3771-11e0-6d30-9bd62faf47ef.png)


2テーブルの完全外部結合は以下の考え方で行います。
1\. 2つのテーブルに左外部結合(LEFT OUTER JOIN)
2\. 2つのテーブルの右外部結合(RIGHT OUTER JOIN)
3\. 2回結合した結果に対して和集合をとる(UNION)

よってmathテーブルとenglishテーブルは次のSQLで結合できます。

```sql
SELECT
    math.student,
    math.math_score,
    english.english_score
FROM
    math
LEFT OUTER JOIN
    english ON math.student = english.student
UNION
SELECT
    english.student,
    math.math_score,
    english.english_score
FROM
    math
RIGHT OUTER JOIN 
    english ON math.student = english.student
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579871/16d4a029-4030-1b5b-f05f-24e7713293ad.png)

# 3テーブルの場合
今度は先ほどのテーブルに国語(japanese)も加えて完全外部結合をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579871/dbb20d4f-10a6-7edc-ce8a-cfc3b953fdf4.png)

3テーブルの完全外部結合は以下の考え方で行います。
1\. With句で2テーブルの完全外部結合の結果を保持
2\. 保持した結果と3つ目のテーブルを完全外部結合

3テーブルの結合は次のようになります。
```sql
WITH temp AS(
    SELECT 
        math.student,
        math.math_score,
        english.english_score
    FROM
        math
    LEFT OUTER JOIN
        english ON math.student = english.student
    UNION
    SELECT 
        english.student,
        math.math_score,
        english.english_score
    FROM
        math
    RIGHT OUTER JOIN 
        english ON math.student = english.student
)

SELECT
    temp.student,
    temp.math_score,
    temp.english_score,
    japanese.japanese_score
FROM
    temp
LEFT OUTER JOIN 
    japanese ON temp.student = japanese.student
UNION
SELECT 
    japanese.student,
    temp.math_score,
    temp.english_score,
    japanese.japanese_score
FROM
    temp
RIGHT OUTER JOIN
    japanese ON temp.student = japanese.student
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3579871/301fa658-e05e-e897-0d6a-94623ca03d9a.png)

# 4テーブル以上の場合
3テーブルの考え方と同様に結合した結果をWith句で保持して2テーブルの結合を繰り返します。
今更Windows Server 2012R2を構築した時にライセンス認証した

# はじめに
物理サーバで稼働するWindowsServer2012R2ちゃんがやばいので、別途仮想マシン上に構築したく。
DCライセンスやらStdライセンスは保有していたものがあったので、新規構築してお引越しをする。
でも、インストールメディアがない。EVALはMicrosoftさんから落とせる。
+ EVALのISOメディアをここ( https://www.microsoft.com/ja-jp/evalcenter/download-windows-server-2012-r2 )からダウンロードした
+ 正規ライセンスは勿論ある
+ EVALからStdかDCへ切り替えたい
+ インターネットには接続出来る
# eval-isoでプリインストール
普通に入れる。
画面が懐かしい。
# ライセンス認証
## DISMコマンドで現在のEdtionを確認
```
DISM /online /Get-CurrentEdition
```
## DISMコマンドでアップグレード出来るEdtionを確認
```
DISM /online /Get-TargetEditions
```
## DISMコマンドでEdtionを変更かつ認証
```
DISM /online /Set-Edition:<edition ID> /ProductKey:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX /AcceptEula
```
選べるEdtionは以下のようなものがある。`ServerDatacenterEval`とかもあるらしい。
+ ServerStandard
+ ServerDatacenter
## 再起動を問われる
再起動する。`Y`を押下するとすぐに再起動する。
リソースをTerraform管理下から外す方法と管理下に取り込む方法

# はじめに
Terraformのコードをリファクタリングする時、リソースの削除や置き換えが発生してしまうことがあります。そんな時、リソースを一時的にTerraform管理下から外すと修正しやすくなる場合があるのでそのやり方をまとめます。

# 対象リソースを用意

下記のようなmain.tfを作成し、`terraform apply` を実行して、S3バケットを作成します。
```terraform
provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_s3_bucket" "my_bucket" {
  bucket = "akis-unique-bucket-name"
}
```

作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/04d15eb2-138d-0803-7782-f0720368bfcc.png)

Terraformで作成したリソース一覧を`terraform state list` コマンドで確認可能です。

https://developer.hashicorp.com/terraform/cli/commands/state/list

コマンドを実行すると、今作った`aws_s3_bucket.my_bucket`が表示されます。
これで作成したS3バケットがTerraform管理にあることが確認できました。
```
$ terraform state list
aws_s3_bucket.my_bucket
```


# Terraform管理下からリソースを外す方法


下記コマンドを実行します。
```
terraform state rm <リソース名>
```

https://developer.hashicorp.com/terraform/cli/commands/state/rm

実際に実行すると下記のような結果が得られます。
```bash
$ terraform state rm aws_s3_bucket.my_bucket
Removed aws_s3_bucket.my_bucket
Successfully removed 1 resource instance(s).
```

`terraform state list`を再実行すると、何も表示されなくなりました。
`aws_s3_bucket.my_bucket`がTerraform管理から外れ、マネジメントコンソールやAWS CLIで作成した時と同じ状態になりました。


# リソースをTerraform管理下に取り込む方法

importコマンドを使って、作成済みリソースをTerraform管理下にすることができます。

https://developer.hashicorp.com/terraform/cli/import

各リソースページの一番下にImportという項目があり、参考情報が書かれています。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#import

**importブロックの追記**
importしたいリソースのimportブロックをtfファイルに記載します。

https://developer.hashicorp.com/terraform/language/import

`import.tf` というファイル作成して記述するか、import先のresouceのそばに書くのが一般的なようです。
> You can add an import block to any Terraform configuration file. A common pattern is to create an imports.tf file, or to place each import block beside the resource block it imports into.

今回は後者を採用して、`main.tf`の`aws_s3_bucket.my_bucket`の真下に追記します。


```terraform
resource "aws_s3_bucket" "my_bucket" {
  bucket        = "akis-unique-bucket-name"
  force_destroy = true
}

import {
  to = aws_s3_bucket.bucket
  id = "akis-unique-bucket-name"
}
```

importブロックの書き方は下記です。
リソースのIDはリソースによって異なります。何がIDになるかは各リソースページのImportに記載されています。aws_s3_bucketの場合はバケット名がIDになります。
```terraform
import {
  to = <リソースの種類.リソースの名前>
  id = <リソースのID>
}
```

**importコマンド実行**

下記のように`terraform import`を実行します。
```
terraform import <リソースの種類.リソースの名前> <リソースのID>
```

main.tfに記載したリソースに関して実行してみると下記のような結果が得られました。
```bash
$ terraform import aws_s3_bucket.my_bucket akis-unique-bucket-name
aws_s3_bucket.my_bucket: Importing from ID "akis-unique-bucket-name"...
aws_s3_bucket.my_bucket: Import prepared!
  Prepared aws_s3_bucket for import
aws_s3_bucket.my_bucket: Refreshing state... [id=akis-unique-bucket-name]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```
`terraform state list`を実行すると、`aws_s3_bucket.my_bucket`が表示されているため、再度Terraform管理下に戻せたことが確認できました。
```
$ terraform state list
aws_s3_bucket.my_bucket
```
【UiPath】例外発生位置情報の取得 ／ Ctrl＋J で検索するコードの調べ方

# はじめに

- 本記事では、グローバルハンドラーをもちいてエラーが発生した位置情報を取得する方法を紹介します。
- 記事の内容は、個人の見解または確認結果であり、UiPath の公式見解ではありません。
- 製品仕様や参考画像は 23.10 バージョンのもので構成しています。

# StudioX のエラーダイアログにある位置情報のコード

![トレース技8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/f9399269-1e9e-89cd-b262-07a04b97dbef.jpeg)

StudioX ではグローバルハンドラーが既定でプロジェクトフォルダに組み込まれており、エラーが発生した際に、上図のダイアログが表示されるのは周知のことかとおもいます。
そして、このダイアログの***エラーメッセージの末尾にエラーが発生した位置を検索するコードがあるため、Ctrl＋J で問題のアクティビティを検索される***方は多いとおもいます。（上図における検索コードは「0100E」）

（例）Ctrl＋J > 「0100E」で検索↓↓

![トレース技9.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/03e2869a-7645-1eea-5ec2-0bb2cf967259.jpeg)

::: note
グローバルハンドラーを利用しているプロジェクトでは、エラーが発生した際に ***「errorinfo」*** というオブジェクトが自動生成されます。
このオブジェクトの ***「ActivityInfo」プロパティ*** に、エラーが発生した位置情報や対象のアクティビティの表示名などが入っています。
:::

# Studio でもエラーの発生位置をログしたい

Studio のグローバルハンドラーは、リトライカウントをみてリトライか停止をするだけのシンプルな実装です。
このため、StudioX のハンドラーのエラーダイアログ作成部などを参考に追加実装する必要があります。

以下に、わたしなりに考えた errorinfo.ActivityInfo の有効なログ出力方法を記載します。

![トレース技21.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/59a9c38b-45aa-ef0a-fdc2-b723575a941a.jpeg)

まず、errorinfo.ActivityInfo の中身を説明します。
- Id：アクティビティのID
- InstanceId：WF全体の中でアクティビティが出現する位置
- Name：アクティビティの表示名称
- TypeName：アクティビティの正式名称

冒頭に触れたエラー発生位置の検索コードは、次の式で***IDの整数部を16進数に読み替える***などして求めることができます。
```
String.Join("0", errorInfo.ActivityInfo.Id.Split("."c).[Select](Function(s) Integer.Parse(s).ToString("X2")))
```
この検索コードだけ出力すれば十分か？
→　残念ながらNoです

原因は不明ですが、***複雑なWFではこの検索コードで必ずしも問題のアクティビティに辿りつける訳ではありません。（※検索コードは取得できるものの、Ctrl＋Jで検索をかけてもヒットしないことがある）***

このため、検索コードに加えて ***「errorInfo.ActivityInfo.Id」「errorInfo.ActivityInfo.InstanceId」「errorInfo.ActivityInfo.Name」の3つ*** も出力することをお勧めします。

「Name」はアクティビティの表示名なので、出力した方が良い理由は省略します。

## 「Id」「InstanceId」の出力を勧める理由

検索コードがなくとも、「Id」と「InstanceId」がわかればおよそ位置を特定できるためです。

手元で動作をみる限り、「Id」をみればシーケンスの深さがわかります。

たとえば、次の場合、「ほげほげアクティビティ」のIdは ***1.2*** です。（シーケンス1 のIdは 1.1）
![トレース技22.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/375acc41-49fa-118d-47b2-d7788ade5fd5.jpeg)
シーケンスを増やせば「ほげほげアクティビティ」のIdは ***1.3*** です。
![トレース技23.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/fcb1a252-8667-1d28-c481-c95601c4f898.jpeg)
じゃぁこれはどうなる？　→　「ほげほげアクティビティ」のIdは ***1.2*** に戻るんです。
![トレース技24.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/5ac124d5-2de1-47b1-e279-ce6bfc53471f.jpeg)

このことから、およそ***ネストの深いところにいるのか否か***はIdをみればわかります。

InstanceId は、WFの後ろに配置すればするほど番号が上がっていくので、***WF全体の中のどの位置にいるのか***がわかります。

InstanceId が9番の「テキスト ファイルを読み込み」のエラーを例に説明しますが、Xamlの実装部をEXCELなどにコピーし、DisplayNameでフィルター。インデントとシーケンスのIDをみながらカウントアップしてみていけば、およそ InstanceId の順番ら辺に問題のアクティビティが出現するはずです。

![トレース技25.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/e0dccb27-b935-8993-22d4-d279bf3e54ec.jpeg)

# さいごに

いかがでしたでしょうか。無人実行においては、エラー時のリカバリが必要なケースでは TryCatch で括り、例外制御を実装するのがセオリーですが、そういった後処理が不要なロボットであれば、グローバルハンドラーを追加して上で案内した様な検索コードや例外発生位置の情報を出力しておくだけで十分だとおもいます。
例外発生時の情報出力でお悩みの方が居れば是非参考にしていただければとおもいます。
最後までお読みいただきありがとうございますヾ(＠⌒ー⌒＠)ノ
自宅のグローバルIPアドレスを外出先で知る

自宅のPCにどこからでもWindows RDP（リモートデスクトップ）接続できるよう、利用しているインターネットサービスプロバイダーの固定IPアドレスオプションを契約していたのですが、この料金がこの度べらぼうに値上がりしてしまったので、やむなく契約を解除しました。

するとRDP接続はできなくなるのかというと、そんなことはなくて、グローバルIPアドレスさえわかれば接続できるわけです。PCがWOL (Wake On LAN)に対応していれば、外出先からPCの電源を入れることもできます。

まずは自宅のPC内で現在のグローバルIPアドレスを取得する方法です。方法はいろいろありますが、私はCygwinで下記のコマンドを実行して取得する方法をとりました。

```
dig myip.opendns.com @208.67.222.222 +short
```

`dig`コマンドは`bind`をインストールすれば利用できます。

さて、上記コマンドで得られたグローバルIPアドレスを外出先で知ることができるよう、次の2つの方法を考えました。

1. グローバルIPをテキストファイルに書き込み、クラウドで同期する
1. メール送信する

### クラウドで同期

Windowsのタスクスケジューラーで、以下のbashスクリプトがWindows起動時に実行されるように設定します。

```
#!/bin/bash
dig myip.opendns.com @208.67.222.222 +short > ~/OneDrive/GlobalIP.txt
```

これでWindows起動時に得られたグローバルIPアドレスが`~/OneDrive/GlobnalIP.txt`に書き込まれます。`~/OneDrive`がOneDriveで同期されるようになっていれば、外出先からOneDriveに同期された`GlobalIP.txt`ファイルを見ればいいわけです。

### メール送信

以下のPowerShellスクリプトを用意します。

```
$MyName = hostname
$MyIP = dig myip.opendns.com "@208.67.222.222" +short
$From = "起動通知 <送信者メールアドレス>"
$SmtpServer = "メール送信サーバー"
$Port = ポート番号
$User = "メールアカウント名"
$Pass = "メールアカウントのパスワード"
$SMTPClient=New-Object Net.Mail.SmtpClient($SMTPServer,$Port)
$SMTPClient.EnableSsl=$false
$SMTPClient.Credentials=New-Object Net.NetworkCredential($User,$Pass)
$To = "宛先メールアドレス"
$Subject = "$MyName"
$Body = "$MyIP"
$Mail=New-Object Net.Mail.MailMessage($From,$To,$Subject,$Body)
$SMTPClient.Send($Mail)
```

`$SMTPClient`の諸設定は、使用するSMTPサーバーに応じて変更してください。

そしてWindowsのタスクスケジューラーで、このスクリプトがWindows起動時に実行されるように設定します。プログラム/スクリプトには`pwsh.exe`の完全パスを設定し、引数には上記スクリプトの完全パスを設定します。

この方法では、メールアカウントのパスワードをスクリプト内に平文で書くことになるので、セキュリティー的にはちょっと難があります。

### スクリプト実行タイミング

グローバルIPアドレスはルーターとISPとの接続が確立したときに決まり、通常、その後その接続が切られるまでは変化しないと思うので、Windowsを起動するたびに毎回実行する必要は無いのですが、負荷的にはぜんぜん大したことないので、まあいいかなと。ルーターを再起動したりするとアドレスが変わってしまうので、そのときは上記のスクリプトを再度実行してやらなければなりません。それを忘れそうで心配なら、タスクスケジューラーで定期的に実行されるよう設定するのもありだと思います。

グローバルIPアドレスが決まったタイミング、すなわち、ルーターとISPとの接続が確立したときに、それをトリガーとしてスクリプトを実行できるといいのですが、そんな方法は（少なくとも私の環境では）ありません。もしいい方法があれば教えてください。
Xcode14 IPAファイル書き出し時に特定のデバイスにインストールを制限

# Xcode 14でIPAファイルの書き出し時に特定のデバイスへのインストールを制限する方法

## 目次
- [はじめに](#はじめに)
- [Xcodeプロジェクトの開き方](#Xcodeプロジェクトの開き方)
- [デバイスの制限設定](#デバイスの制限設定)
- [まとめ](#まとめ)

## ・ はじめに
Xcode 14を使用してiOSアプリケーションを開発する際、特定のデバイスに対してインストールを制限したい場合があります。この記事では、そのような場合にIPAファイルを書き出す方法を紹介します。

## ・ Xcodeプロジェクトの開き方
まず、Xcodeを起動し、制限をかけたいプロジェクトの`Runner.xcworkspace`を開きます。

![Xcodeプロジェクトの開き方](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637125/a5212eb9-d53e-370e-30f7-ad4f7ba97e01.png)

次に、`Runner`を選択し、Targetの`Runner`から`General`を選択します。

![スクリーンショット 0006-04-10 17.43.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637125/b482c7c4-a527-d362-c977-3ac8d6a52c0a.png)


## ・ デバイスの制限設定
`Supported Destinations`を見つけ、インストールに制限をかけたいデバイスを選択し、`-`ボタンを押下します。

![デバイスの制限設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637125/d82ab22f-ecde-6ae5-aa2e-2b55a6e72575.png)

これにより、選択した端末が削除され、IPAファイルを書き出す場合、制限をかけたデバイスにはインストールができなくなります。

## まとめ
この方法を使用することで、開発中のアプリケーションを特定のデバイスにのみインストールを許可し、その他のデバイスへのインストールを防ぐことができます。
Azure DevOps: Git Pull request の merge types の注意点

Azure DevOps Git リポジトリの Pull Request をマージする際、マージのやりかたが４種類あります。それらの使い分けと注意事項をメモ。

# Merge types の種類

[Complete, abandon, or revert pull requests](https://learn.microsoft.com/en-us/azure/devops/repos/git/complete-pull-requests?view=azure-devops&tabs=browser#check-merge-changes) のところに説明がありますが、Merge type には以下の4種類があります。

* Basic merge (no fast-forward)
  - 常に merge commit を作ります。fast-forward はしません。すべての commit は維持されます。
* Squash merge
  - 全コミットを1コミットに squash します。ブランチは直線になります。
* Rebase and fast-forward
  - リベースして fast-forward します。ブランチは直線になります。
* Rebase with merge commit
  - リベースしますが、マージするときに merge commit を作ります。

## 困ること

ここでちょっと困るのは、Git のデフォルトのマージ戦略が無いということです。
Git のデフォルト戦略は、「fast-forward 可能なら fast-forward するが、そうでない場合は merge commit を作る」です。これと同じことは Azure DevOps ではできません。

なので、同じことをしたいなら、「Basic merge」か「Rebase and fast-forward」のいずれかを人間が判断して決めなければなりません。はっきり言ってくそ面倒です。

このポリシ作ってよ ＞Microsoftさん

# 使い分け方針

これはプロジェクトごとに方針が異なると思います。できるだけブランチを直線にしたいなら「Rebase and fast-forward」を中心に使うことになりますし、逆にこれを気にせず常にマージコミット作りたいなら「Basic merge」を使うことになります。

私はできるだけブランチを直線にしたいので、以下のような方針を取っています。ちなみに採用している Git ブランチ戦略は、git-flow です。

* feature ブランチをマージするときは「Rebase and fast-forward」
* develop ブランチを main ブランチにマージするようなケースは「Basic merge」
Visual Studio Code を使って、MacでPython分離環境を作成する手順

■ 環境
・Python：Homebrew で pyenv をインストールし、pyenv から Anaconda をインストール。
・Visual Studio Code に Pythonプラグインをインストール済。

■ 手順
・任意のフォルダを作成し、Pythonファイル(*.py)を保存する。
・VSCodeでフォルダを開く。
・コマンドパレットで "Python: 環境の作成..." を実行する。
・"conda" を選択する。
・Pythonのバージョンを選択する。
・'.conda' が作成される。
・VSCodeを一旦終了して、再度VSCodeを起動してフォルダを開く。

⇒ VSCode右下のステータスバーに "('.conda': conda)" と表示されて、作成した環境がVSCodeで認識されていることを確認できる。
【HackTheBox】つまったところを備忘録的に残す

お読みいただきありがとうございます。
個人的に取り組んでいるHackTheBox（以下、HTB）について、つまづいたところやWriteUpにも載っていない基本的なところを解決した方法について備忘録的に残していこうと思っています。
基本、聞く人がいないので、google先生かchatgptに聞きながらやってます。

[はじめに]
筆者のレベル
・脆弱性診断スキル：ゼロ
・資格：応用情報所持
・Linux：基本的なコマンドラインを知っている（lsなど）程度

[HackTheBoxを知ったきっかけ]
・漠然とセキュリティに興味があるものの、特に勉強していないことから勉強しようと決心。色々調べたらHackTheBoxを見つけた

[事前準備]
・環境：wslを利用（※virtualboxは使わず）
　　　　kaliLinuxをkexで利用できるように設定（kali-win-kex）
　　　　googlechromeをインストール(wslから直接呼び出す）
　　　　日本語入力対応（これが一番大変。fcitx-mozcをインストール。CUIでは無理だったため、kexを使って『Fcitx 設定』を実施することで解決）

[つまったところ]
〇openvpnでさっそくつまる。チュートリアルを確認し、wslコマンドラインで以下入力
　☆『openvpn (ファイルパス) （HTBでダウンロードしたvpnファイル※１）』
　　※HTB登録完了後、vpnを接続する必要があるが、そこでファイルをダウンロード
　　※実行時はsudoが必要（これは記載してほしかった）
　そうこう調べているうちに、Winソフトのopenvpnでも接続できることが判明。
　ワンタッチでできることが便利だったので、こちらをメインにした。
   
〇課題について
1:startingpontのresponder
(1)Responder -Iで、パケット取得のイーサ(ipp　aで判明したeth0)を設定するも、どうしても拾ってくれない。
　wiresharkなど使ってパケットを流れを把握するも異常がわからず。
 １週間ほど試行錯誤した結果、どうやらopenvpnのつなぎ方が悪いんじゃないかと思料。
 　→当初、Win上のopenvpnソフトを使って通信確立し演習を実施していたため、wslからopnevpnコマンドをたたいてつなぎなおしたところ、パケットを拾ってくれるように。
　☆学習で来た点：
 　　HTBにVPNでつなぎに行く際、Win上のopenvpnとwsl上のopenvpnとは通信が異なること
(2)Windowsサーバに遠隔接続した際のコマンド
　flagを見つけるのにwinサーバを遠隔で調べる必要あり。以下を使って見つけました。
・ls:一覧表示　cd:一つ上に戻る
・get-childitem -name-recurse -file -include (ファイル名）：ファイル名検索

 今後ひっかかったところをメインに記載します。
AWS EC2でpip install mysqlclientができない

# pip install mysqlclientができないときの対処法
解決
ubuntuで必なパッケージ pkg-configが入っていなかった。
```bash:shell
$ sudo apt-get install pkg-config
```

もしかしたら下も必要かもしれない。
```bash:shell
$ sudo apt-get install libmysqlclient-dev
```
Microsoft Copilotで、日本語プログラミング その18

# 概要
Microsoft Copilotのプロンプトを細工して、日本語プログラムを実行させようとする試みです。
ハッカソンなので、問題をやってみた。

# Ohisama prompt

```
架空のブログを生成することを考えます。 ブログの記事を書くことです。 
構成は、
ある技術的なテーマを与えられた場合 、それに対する仮説を提案します 。
次に 仮説を裏付ける理論を示します。
計算結果を導くために、日本語プログラミングのダミーコードを書くようにしてください。 
そして、その理論を検証した計算結果を示します 。
最後に 簡潔な結論を加えるという構成です。 
全体を、9000字に収めてください。
では、「websocketで、異空間通信」というテーマで、ブログを記事にしてみてください。
```

# 回答

こんにちは、Copilotです。😊
あなたのリクエストに応えて、架空のブログ記事を生成してみました。
テーマは「websocketで、異空間通信」です。
以下が記事の内容です。

# websocketで、異空間通信

## 仮説
websocketとは、ウェブブラウザとサーバー間で双方向の通信を可能にする技術です。
通常、ウェブブラウザはHTTPプロトコルを用いて、サーバーにリクエストを送り、レスポンスを受け取りますが、この場合、通信は一方的で、サーバーからのプッシュ通知などはできません。
websocketでは、HTTPプロトコルの上に、新たなプロトコルを構築し、ハンドシェイクを行うことで、ウェブブラウザとサーバー間に永続的な接続を確立します。
これにより、サーバーからのプッシュ通知や、リアルタイムなデータのやり取りが可能になります。

では、websocketを用いて、異空間通信とは何かを考えてみましょう。
異空間通信とは、現実の空間とは異なる、仮想的な空間での通信を指します。
例えば、VRやARなどの技術を用いて、現実とは異なる風景や物体を見たり、触ったり、感じたりすることができます。
また、異空間通信では、現実の空間とは異なる法則やルールが適用されることもあります。
例えば、重力がない空間や、時間が逆流する空間などが考えられます。

仮説として、websocketを用いて、異空間通信を実現することができるとします。
具体的には、以下のような仕組みを想定します。

- ウェブブラウザとサーバー間にwebsocketで接続を確立します。
- サーバーは、異空間の情報を生成し、ウェブブラウザに送信します。
- ウェブブラウザは、受信した異空間の情報を解釈し、表示します。
- ウェブブラウザは、ユーザーの入力や操作をサーバーに送信します。
- サーバーは、受信したユーザーの入力や操作を反映し、異空間の情報を更新し、ウェブブラウザに送信します。

このように、websocketを用いることで、ウェブブラウザとサーバー間で、異空間の情報をリアルタイムにやり取りすることができます。
これにより、ユーザーは、ウェブブラウザを通して、異空間にアクセスし、通信することができます。

## 理論
websocketで異空間通信を実現するためには、以下の二つの要素が必要です。

- 異空間の情報の生成
- 異空間の情報の解釈

異空間の情報の生成とは、サーバーが、異空間の空間的な構造や物理的な法則や物体の属性などを定義し、表現することです。
異空間の情報の解釈とは、ウェブブラウザが、サーバーから受信した異空間の情報を、ユーザーにとって分かりやすく、感覚的に、視覚的に、聴覚的に、触覚的になどの方法で提示することです。

異空間の情報の生成には、以下のような手法が考えられます。

- 人工知能を用いて、異空間の情報を自動的に生成する。
- ユーザーが、異空間の情報を自由に設定する。
- 既存のデータやコンテンツを、異空間の情報に変換する。

人工知能を用いて、異空間の情報を自動的に生成する場合、以下のような利点と課題があります。

- 利点
    - 異空間の情報の生成に人間の介入が不要である。
    - 異空間の情報の多様性や創造性が高まる可能性がある。
    - 異空間の情報の生成に時間やコストがかからない。
- 課題
    - 人工知能の性能や信頼性に依存する。
    - 異空間の情報の品質や妥当性が保証されない。
    - 異空間の情報の生成に倫理的な問題が生じる可能性がある。

ユーザーが、異空間の情報を自由に設定する場合、以下のような利点と課題があります。

- 利点
    - ユーザーの好みや目的に合わせて、異空間の情報をカスタマイズできる。
    - ユーザーの参加感や満足感が高まる可能性がある。
    - 異空間の情報の生成に人工知能の技術が不要である。
- 課題
    - 異空間の情報の生成にユーザーの労力や知識が必要である。
    - 異空間の情報の多様性や創造性が低下する可能性がある。
    - 異空間の情報の生成にルールや制約が必要である。

既存のデータやコンテンツを、異空間の情報に変換する場合、以下のような利点と課題があります。

- 利点
    - 異空間の情報の生成に既に存在する資源を活用できる。
    - 異空間の情報の生成に新たな技術や知識が不要である。
    - 異空間の情報の生成に親しみやすさやリアリティがある。
- 課題
    - 異空間の情報の生成に著作権やプライバシーの問題が生じる可能性がある。
    - 異空間の情報の生成に変換の方法や基準が必要である。
    - 異空間の情報の生成にオリジナリティや独自性が欠ける可能性がある。

異空間の情報の解釈には、以下のような手法が考えられます。

- ウェブブラウザの標準的な機能を用いて、異空間の情報を表示する。
- ウェブブラウザの拡張機能や外部のデバイスを用いて、異空間の情報を表示する。

ウェブブラウザの標準的な機能を用いて、異空間の情報を表示する場合




以上。
Centos7へ最新Gitインストール

下記コマンド随時実行。
```
cd /usr/local/src/
wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz
wgetが無ければインストール
yum install wget
wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz
tar xzvf git-2.9.5.tar.gz
cd git-2.9.5
make prefix=/usr/local all
make prefix=/usr/local install
git --version
git version 2.9.5と表示されれば成功。
```
gitアーカイブ
https://mirrors.edge.kernel.org/pub/software/scm/git/
【Astro】コマンドだけで超簡単に Tailwind CSS を導入する全手順

## 概要
Astro で構築した Web アプリに Tailwind CSS を導入する方法の備忘録です。

Astro の公式ドキュメント（英語）にも [導入方法の詳細](https://docs.astro.build/en/guides/integrations-guide/tailwind/#installation) はありますし、簡単すぎて書くまでもないかもしれませんが、念のために初心者向けの日本語の要約版として記載します。

「Astro で用意されたコマンドを利用する方法」と「手動で導入する方法」の２種類がありますが、今回は **「astro コマンドを利用して導入する方法」** について解説します。

コマンド利用をすると、手動で導入する場合の手順を「Yes」と答えるだけで全部やってくれます。
何か他のライブラリやプラグインとの兼ね合い等で、手動で導入する理由がなければ、基本はコマンド利用で良いと思います。

## 手順
コンソールを開き、Asrto のプロジェクト配下（`package.json` がある場所）で以下を実行します。

```bash
npx astro add tailwind
```

以下、実行結果。対話式で質問に答えていきます。
```bash
✔ Resolving packages...
11:47:36 

# Q1. 以下のコマンド実行するけど良い？
  Astro will run the following command:
  If you skip this step, you can always run it yourself later

 ╭──────────────────────────────────────────────────────────╮
 │ npm install @astrojs/tailwind@^5.1.0 tailwindcss@^3.4.1  │
 ╰──────────────────────────────────────────────────────────╯
? Continue? › (Y/n)
  # 👉 デフォルトが "Y" なので、そのままエンターキーで OK

✔ Continue? … yes
✔ Installing dependencies...
11:47:50

# Q2. xxx？
  Astro will generate a minimal ./tailwind.config.mjs file.

? Continue? › (Y/n)
  # 👉 そのままエンターキーで OK

✔ Continue? … yes
11:54:59

# Q3. xxx？
  Astro will make the following changes to your config file:

 ╭ astro.config.mjs ───────────────────────────────╮
 │ import { defineConfig } from 'astro/config';    │
 │ import mdx from '@astrojs/mdx';                 │
 │ import sitemap from '@astrojs/sitemap';         │
 │                                                 │
 │ import tailwind from "@astrojs/tailwind";       │
 │                                                 │
 │ // https://astro.build/config                   │
 │ export default defineConfig({                   │
 │   site: 'https://example.com',                  │
 │   integrations: [mdx(), sitemap(), tailwind()]  │
 │ });                                             │
 ╰─────────────────────────────────────────────────╯

? Continue? › (Y/n)
  # 👉 そのままエンターキーで OK

✔ Continue? … yes
11:57:00   
   success  Added the following integration to your project:
  - @astrojs/tailwind
```

以上で導入完了です。簡単ですね 🙌✨

Astro の場合は、他のツールで必要な以下のスタイル定義ファイルの追記は **不要** です。

```css:「global.css」とか「styles.css」とか
@tailwind base;
@tailwind components;
@tailwind utilities;
```

### 動作確認
Tailwind CSS が実際に利用できるか動作確認しましょう。
書き方や使い方は、[Tailwind CSS 側のドキュメント](https://tailwindcss.com/docs/utility-first) を見た方が良さそうです。

今回はサンプルとして、以下の要素を画面に表示してみます。

```html:src/pages/index.astro
<h1 class="p-8 text-center text-blue-400 underline">
  Hello world!
</h1>
```

上記は、「パディング（内側への余白）」「文字は中央揃え」「文字色は青」「下線を引く」のスタイルを適用するクラス指定です。
このスタイルが適用された状態で **"Hello world!"** と表示されれば成功です。

そして、実際にブラウザで表示してみました。

![demo_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/21a7e419-90c8-ec4b-0741-ea91481e41b9.png)

ちゃんとスタイルが適用されていますね。Tailwind CSS が問題なく使えることが確認できました！

## プラグインを追加する場合
Tailwind CSS のプラグインを追加する場合は、自動インストール時に生成された `ui/tailwind.config.mjs` ファイルに設定を追加しましょう。

プラグイン追加の詳細は、[Tailwind CSS のドキュメント](https://tailwindcss.com/docs/plugins) を参考にしてください。
【ChatGPT有＋DALL-E3】を人との交流に使う。


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

　今回は、ChatGPT PlusとDALL-E3を使って、人との交流をやってみた結果の報告です(汗)

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　最近の私が
　　DALL-E3で描画する画像は
　　　X-Twitterにポストするもの
　　　　ばかりです。

　基本的には
　・着物姿の若い女性の日常
　・フォロワー数が切りのいい
　　　値の方が催すテーマに沿った物
　・個人的な作品
　・プロンプトを共有するもの
　・人との作品ラリー

　こんなところです。

　最後の“人との作品ラリー”が
　　意外と楽しい(=^･^=)

　簡単に説明すると
　　テニスをするように
　　　画像と少々の文章で
　　　　ストーリーを作る、と言って
　　　　　わかってもらえますかね？

　しかも
　　そこに
　　　もともとストーリーはなく
　　　　散発的にはじまって、
　　　　　相手の返事に
　　　　　　こっちの返事で
　　　　　　　のらりくらり。

　終わって全部を見てみると
　　それなりのストーリーに
　　　なっています。

　途中、相手の返事に
　　笑い転げたりも
　　　しています。

　それと
　　DALL-E3さんが
　　　ときおり、
　　　　思わぬ画像を生成するので
　　　　　それがストーリーに
　　　　　　スパイスを加えます。

　ちなみに
　　以下が
　　　そのラリーのようす。

　画像の下に
　　“返信を表示”がありますので
　　　続けて見たければ、
　　　　それを、タップや
　　　　　クリックしてください。

　[その１](https://twitter.com/patata1216/status/1754008275585290393?t=L9wSKyiuw0Zh4nXC-9YCvA&s=19)
　これは途中で、
　　ChatGPTさんの制限が
　　　来てしまい、リレーを
　　　　続けられませんでした。

　[その２](https://twitter.com/patata1216/status/1754847986780381292?t=OaS9uUIcQedRUZE_vB815w&s=19)

　[その３](https://x.com/kabumira862571/status/1755069563434357243?s=20)
　その２の翌日話。

　[その４](https://twitter.com/patata1216/status/1755198480946204892?t=T9zaVyQbogJu02r4v_ftsw&s=19)
***
　いかがでしたかねぇw

　別に示し合わせたわけではなく、
　　打ち返していたら
　　　こうなっただけです(汗)

　でも
　　この方、
　　　Bing ImageCreator使いで、
　　　　ノウハウもあるらしく
　　　　　また、ストックもあって
　　　　　　画像のスタイルが
　　　　　　　一定しているので、
　　　　　　　　私の画像の乱れが
　　　　　　　　　恥ずかしいレベル。

　ただ、
　　こちらも
　　　そうした乱れを
　　　　楽しんでいます。

　その４で
　　ペンギンとカメの卵と一緒に
　　　出てきた兄弟の卵ですが、
　　　　全然、指定して
　　　　　いませんでした。

　出てきた画像を見て、
　　爆笑してしまいましたw

　しかも
　　“似顔絵”を指定したら
　　　あんな絵になって……

　みなさんも
　　ご自分の可能性を
　　　広げるために
　　　　リレーしてみませんか？

　今回は、ここまで。