OmniAICreator/Qiita-1.07M huggingface dataset:
VCF/vCard の連絡先を Excel シートに保存する目的と便利なソリューション

<p>ユーザー データは、多くの場合、仮想連絡先ファイル (略して VCF) に保存されます。その一例として、vCard が挙げられます。これは、Internal Mail Consortium によって作成されたもので、vCard ファイルは連絡先の交換にのみ使用されます。保存されるデータには、名前、電話番号、電子メール アドレス、場所、写真などがあります。一方、Excel スプレッドシートは Microsoft Corporation によって作成されました。これは、データ分析、視覚化、管理に広く使用されています。Excel は Microsoft Office の一部であり、さまざまなファイル形式でデータ、計算、表示を管理するための効果的なツールです。</p>
<h2><strong>Excel vCard エクスポートの動機</strong></h2>
<ul>
    <li>Excel を使用すると、すべての連絡先情報を含む単一のデータベースを作成できるため、アクセスと管理が簡単になります。</li>
    <li>名前、メール アドレス、電話番号、会社などの属性を使用して vCard ファイル内の連絡先を並べ替えたりフィルター処理したりすることは困難ですが、Excel では可能です。</li>
    <li>ピボット テーブルやグラフなどの Excel の強力な分析機能を利用して、連絡先データを調べ、有用なデータを導き出すことができます。</li>
    <li>vCard を Excel に変換することで、連絡先データの流行や方法を見つけることができ、ビジネス オプションの作成や計画の策定に役立ちます。</li>
    <li>vCard ファイル内の各連絡先を手動で更新するよりも、Excel を使用して連絡先情報を一括で変更および更新する方がはるかに効率的です。</li>
</ul>
<h2><strong>ユーザーはなぜ手動の方法を選択しないのでしょうか?</strong></h2>
<ul>
    <li>ただし、vCard ファイルに複雑な情報や詳細な情報が大量に含まれている場合は、変換プロセス中にデータが破損したり失われたりする可能性があります。</li>
    <li>フィールドを手動で変換すると、書式設定の問題が発生する可能性があり、一部のフィールドは Excel で正しくマッピングまたは表示されません。</li>
    <li>手動の手法では、データ マッピング、フィールドの適応、またはバッチ処理の適切なオプションがなく、基本的な変換機能しか提供されません。</li>
    <li>vCard ファイル内のカスタム フィールドは、手動でさらに変更しないと Excel に正しく読み込まれなかったり、適切に動作しなかったりする可能性があります。</li>
    <li>変換前に複数の vCard ファイルを 1 つのファイルに結合するのは困難で、エラーが発生しやすい場合があります。</li>
</ul>
<h3><strong>実証済みの方法を使用して vCard を Excel に変換するにはどうすればよいでしょうか?</strong></h3>
<p><a target="_blank" rel="noopener noreferrer" href="https://www.softaken.com/jp/vcf-csv"><strong>最も信頼性が高く、最も効果的な方法で vCard を Excel に一括インポートする方法</strong></a> を探している場合は、<strong>Softaken VCF から CSV へのコンバーター</strong> ツールの使用をお勧めします。レイアウトを管理しながら、1 つまたは複数の VCF ファイルを一度に変換できます。このプログラムは完全に開発されており、出力構造は最新の状態に保たれ、堅牢なアルゴリズムを備えています。</p>
<h3><strong>vCard から Excel への変換の簡単な手順</strong></h3>
<ul>
    <li>ウィザードをダウンロードしたら、PC で起動します。</li>
    <li>VCF ファイルをスキャンしてプログラムに含めます。</li>
    <li>エクスポート オプション リストで、Outlook と互換性のある PST ファイルをタップします。</li>
    <li>最後に、コースを選択して保存すると、結果がすぐに得られます。</li>
</ul>
<h3><strong>検証済みの専門家によるアプローチの利点</strong></h3>
<ul>
    <li>vCard ファイルから個々の連絡先の写真、電話番号、および電子メール アドレスを抽出できます。</li>
    <li>このプログラムは、技術的な専門知識を必要とせずに簡単に使用できる直接的な視覚的なユーザー インターフェイスを提供します。</li>
    <li>さらに、高度なフィルター ツールを使用して、特定の時間、日付範囲、件名、宛先、受信者、およびその他の多くの基準に従って、特定の vCard 連絡先を変換できます。</li>
    <li>このプログラムを使用して、2、1、3.0、4.0 など、すべての vCard ファイル バージョンを変換できます。</li>
    <li>このプログラムのもう 1 つの素晴らしい機能は、古い VCF ファイルまたはバージョンを現在のバージョンに更新できることです。</li>
</ul>
<h3><strong>最後までやり遂げましょう。</strong></h3>
<p>このブログ記事では、vCard を Excel に変換するさまざまな方法について説明しました。この技術的な理由が、十分な知識を与えてくれたことを願っています。また、vCard を Excel にエクスポートする可能性のあるいくつかの理由についても説明しました。それに続いて、VCF から Excel へのインポートの 4 つの実用的な方法についても説明しました。これらのうちのどれかがニーズに適していると思われる場合は、自由に選択できます。</p>
Bun: Docker上のMongoDBのデータを削除 (Delete)

## プログラム

```ts:mongo_delete.ts
// ----------------------------------------------------------------
//      mongo_update.ts
//
//                                              Jun/28/2024
// ----------------------------------------------------------------
import mongoose from 'mongoose'

// ----------------------------------------------------------------
console.error("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI:string = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', () => {
  console.log('MongoDBに接続しました')
})

const citySchema = new mongoose.Schema<CitySchema>({
  id: String,
  name: String,
  population: Number,
  date_mod: Date,
})

// モデルの作成
const City = mongoose.model<CitySchema>('City', citySchema, 'saitama')

const deleteCities = async (id_in: string) => {
  try {
    console.log('*** updateCities bbb ***')

    await City.deleteOne({ id: id_in })
  } catch (error) {
    console.error('データの更新に失敗しました', error)
  } finally {
    // 接続の切断
    mongoose.connection.close()
    console.error('*** 終了 ***')
  }
}

// ----------------------------------------------------------------
const id:string = process.argv[2]
console.log(id)
deleteCities(id)
// ----------------------------------------------------------------
```

## 実行コマンド

```bash
bun run mongo_delete.ts t1165
```
Bun: Docker上のMongoDBのデータを更新 (Update)

## プログラム

```ts:mongo_update.ts
// ----------------------------------------------------------------
//      mongo_update.ts
//
//                                              Jun/28/2024
// ----------------------------------------------------------------
import mongoose from 'mongoose'

// ----------------------------------------------------------------
function get_current_date_proc(): string {
  const today = new Date()
  const ddx =
    today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate()
  return ddx
}

// ----------------------------------------------------------------
console.error("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI:string = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', () => {
  console.log('MongoDBに接続しました')
})

const citySchema = new mongoose.Schema<CitySchema>({
  id: String,
  name: String,
  population: Number,
  date_mod: Date,
})

// モデルの作成
const City = mongoose.model<CitySchema>('City', citySchema, 'saitama')

const updateCities = async (id_in: string, population_in: number) => {
  try {
    console.log('*** updateCities bbb ***')
    const ddx:string = get_current_date_proc()

    await City.updateOne({ id: id_in }, {
      population: population_in,
      date_mod: new Date(ddx),
    })
  } catch (error) {
    console.error('データの更新に失敗しました', error)
  } finally {
    // 接続の切断
    mongoose.connection.close()
    console.error('*** 終了 ***')
  }
}

// ----------------------------------------------------------------
const id:string = process.argv[2]
const population_in:number = parseInt(process.argv[3])
console.log(id + '\t' + population_in)
updateCities(id, population_in)
// ----------------------------------------------------------------
```

## 実行コマンド

```bash
bun run mongo_update.ts t1167 9120000
```
Bun: Docker上のMongoDBのデータを読む (Read)

## プログラム

```ts:mongo_read.ts
// ----------------------------------------------------------------
//	  mongo_read.ts
//
//						  Jun/28/2024
// ----------------------------------------------------------------
import mongoose from 'mongoose'

console.error("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI:string = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', () => {
  console.log('MongoDBに接続しました')
})


const citySchema = new mongoose.Schema<CitySchema>({
  id: String,
  name: String,
  population: Number,
  date_mod: Date,
})

// モデルの作成
const City = mongoose.model<CitySchema>('City', citySchema, 'saitama')

// データの取得
const getCities = async () => {
  try {
	const cities = await City.find()
	for (const city of cities) {
	  const str_out:string =
		city.id + '\t' + city.name + '\t' + city.population + '\t' + city.date_mod
	  console.log(str_out)
	}
  } catch (error) {
	console.error('データの取得に失敗しました', error)
  } finally {
	// 接続の切断
	mongoose.connection.close()
	console.error("*** 終了 ***")
  }
}
// ----------------------------------------------------------------
getCities()
// ----------------------------------------------------------------
```

## 実行コマンド

```bash
bun run mongo_read.ts
```
Bun: Docker上のMongoDBのデータを作成 (Create)

## プログラム

```ts:mongo_create.ts
// ----------------------------------------------------------------
//      mongo_create.ts
//
//                                      Jun/28/2024
//
// ----------------------------------------------------------------
import mongoose from 'mongoose'

// ----------------------------------------------------------------
function dict_append_proc(dict_aa: any, id_in: string, name_in: string, population_in: number, date_mod_in: string) {
  var unit_aa = {}
  unit_aa['name'] = name_in
  unit_aa['population'] = population_in
  unit_aa['date_mod'] = new Date(date_mod_in)

  dict_aa[id_in] = unit_aa

  return dict_aa
}
// ----------------------------------------------------------------
function data_prepare_proc() {
  var dict_aa = {}

  dict_aa = dict_append_proc(dict_aa, 't1161', 'さいたま', 83154, '1950-7-23')
  dict_aa = dict_append_proc(dict_aa, 't1162', '所沢', 18657, '1950-5-25')
  dict_aa = dict_append_proc(dict_aa, 't1163', '越谷', 97421, '1950-10-2')
  dict_aa = dict_append_proc(dict_aa, 't1164', '久喜', 31864, '1950-6-18')
  dict_aa = dict_append_proc(dict_aa, 't1165', '熊谷', 49358, '1950-8-14')
  dict_aa = dict_append_proc(dict_aa, 't1166', '秩父', 65712, '1950-9-12')
  dict_aa = dict_append_proc(dict_aa, 't1167', '川越', 37256, '1950-7-5')
  dict_aa = dict_append_proc(dict_aa, 't1168', '和光', 72318, '1950-3-20')
  dict_aa = dict_append_proc(dict_aa, 't1169', '新座', 86197, '1950-5-14')

  return dict_aa
}

// ----------------------------------------------------------------
async function loop_insert_proc(dict_aa: any, City: mongoose.Model<any>) {
  for (var key in dict_aa) {
    console.log(key)
    var unit_aa = dict_aa[key]
    unit_aa['id'] = key
    const city1 = new City(unit_aa)
    await city1.save()
  }
}

// ----------------------------------------------------------------
const assert = require('assert')

console.error('*** 開始 ***')

const dict_aa = data_prepare_proc()

const mongoURI:string = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', () => {
  console.log('MongoDBに接続しました')
})

const citySchema = new mongoose.Schema<CitySchema>({
  id: String,
  name: String,
  population: Number,
  date_mod: Date,
})

// モデルの作成
const City = mongoose.model<CitySchema>('City', citySchema, 'saitama')

// データの保存
const saveCities = async () => {
  try {
    await loop_insert_proc(dict_aa, City)
  } catch (error) {
    console.error('データの保存に失敗しました', error)
  } finally {
    // 接続の切断
    mongoose.connection.close()
    console.error('*** 終了 ***')
  }
}

// ----------------------------------------------------------------
saveCities()
// ----------------------------------------------------------------
```

## 実行コマンド

```bash
bun run mongo_create.ts
```
特定のフォルダ以下のタイプミスを一括で検知するシェルスクリプト作った


## 背景
grep使ってよくあるタイプミスを一括で探したいな

# 作りました。


## スクリプト

```sh typo_check.sh
#!/bin/bash

# 検索対象のフォルダ
FOLDER_PATH="/{path}/"

# よくあるスペルミスのリスト (大文字小文字別々に設定)
typos=("recieve" "adress" "definately" "occured" "seperate")
# 正しいスペルのリスト (typosと対応)
correct_spelling=("receive" "address" "definitely" "occurred" "separate")

# フォルダ以下のすべてのファイルを再帰的に走査
find "$FOLDER_PATH" -type f | while read -r file; do
    echo "Checking file: $file"
    for i in "${!typos[@]}"; do
        typo="${typos[$i]}"
        correct="${correct_spelling[$i]}"
        # スペルミスをgrepで検索
        grep -n -H --color=always "$typo" "$file" && echo "Correct spelling should be: $correct"
    done
done
```

```txt input.txt
recieve
address
definitely
occured
seperate
```

## 実行結果

```log
$ sh typo_check.sh

Checking file: /{path}/typo_input.txt
/{path}/typo_input.txt:1:recieve
Correct spelling should be: receive
/{path}/typo_input.txt:4:occured
Correct spelling should be: occurred
/{path}/typo_input.txt:5:seperate
Correct spelling should be: separate
```

※実際に実行すると、検知された単語に色が付きます。

## おわりに

出来た。
チェックしたい文字列を追加してチェックしてみてください。
WaniCTF2024 Forensics writeup level:beginner

## tiny_usb
前提：macを使用
1. zipをダウンロード
2. 解凍する
3. ダブルクリックでマウントする
3. pngがあるので開いてそのまま答え

## codebreaker
1. zipを落としてきて解凍
2. 壊れたQRコードが見れる
3. [この記事](https://merri.cx/qrazybox/help/examples/basic-example.html)を参考に復元していく 
4. まずは4箇所見て、合うパターンを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403392/1a4a9cb1-8837-0347-f31a-d48316580649.png)
5. 可能な限り埋める
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403392/41a4bf31-86cd-849f-ea8f-28f76ee9478f.png)
6. メニューバーのToolからReed-Solomon Decoder
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403392/86ed5a09-9106-1389-42b7-72111062f29e.png)
7. Decodeしておわり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2403392/4241906a-ab8c-685f-21ed-cb37f3585045.png)
EloquentのwithCountメソッドでリレーション先のレコード数を取得する方法

## はじめに
「リレーション先のレコードは使わないけど、取得したレコードの数は見たい」という状況が稀にあります
自分はリレーション先のカラムをidにしView側でCountしていましたが、これをModelだけで実現できる`withCount`メソッドに感動したので解説していきます

## withCountメソッドの基本
`withCount`メソッドは、リレーションシップのレコード数をカウントし、結果に追加するために使用されます
例えば、Userモデルが複数の投稿（posts）を持っている場合、各ユーザーの投稿数をカウントして取得できます
これは非常に便利です

## 基本的なwithCountの使用
ユーザーモデルとポストモデルが１対多の関係にある場合、以下のように`withCount`メソッドを使用します

モデルの定義
```User.php
public function posts()
{
  return $this->hasMany(Post::class);
}
```

クエリの使用例
```php
$users = User::withCount('posts')->get();

foreach ($users as $user) {
  echo $user->name . ' has ' . $user->posts_count . 'posts.';
}
```

このクエリにより、**各ユーザーの`posts_count`プロパティに投稿数が格納されます**

## 複数リレーションシップのカウント
`withCount`メソッドは、複数のリレーションシップを同時にカウントすることもできます

```php
$users = User::withCount(['posts', 'comments'])->get();

foreach ($users as $user) {
  echo $user->name . ' has ' . $user->posts_count . ' posts and ' . $user->comments_count . ' comments.';
```
このクエリでは、**各ユーザーの`posts_count`と`comments_count`プロパティに、それぞれの投稿数とコメント数が格納されます

## 条件付きカウント
特定の条件に基づいてカウントすることも可能です

```php
$users = User::withCount(['posts' => function ($query) {
  $query->where('status', 'published');
}])->get();

foreach ($users as $user) {
  echo $user->name . ' has ' . $user->posts_count . ' published posts';
}
```

このクエリでは、**`status`が`published`の投稿のみをカウントします**

## まとめ
`withCount`メソッドを使用することで、Eloquentモデルにおける関連データのカウントが非常に簡単になります
このメソッドは、データの分析や表示において強力なツールとなり、クエリの効率性を向上させます
すくなくともViewでCountさせるという手間は省けると思います
ぜひプロジェクトで活用してみてください

## 参考リンク
https://readouble.com/laravel/8.x/ja/eloquent-relationships.html

https://laratech.jp/posts/laravel-withcount/
Open WebUI + Gemma 2 (27B)をMacで動かしてみた

この記事では、ニュースが出てきたので、速攻でGemma 2の270億パラメータ版をインストールします。

この記事は、前に、Zennに書いた記事「Open WebUI + Llama3 (8B)をMacで動かしてみた」の追加編をQiitaに投稿したものです。
先に前編をお読み下さい。

https://zenn.dev/techcat56/articles/5863fa5ec41fe3

## 追記
**2024/06/28 13:58:** Ollamaを最新版にアップデートしないと、Gemma 2は動かないようです。

## 環境
蒸し暑い気温 (???)
Mac mini (M2 Pro, 10コアCPU, 32GBメモリ)
内蔵ディスクから起動

## 用語

### Open WebUIとは
Llama3やGemma 2などを簡単に動かせるようにした「Ollama」を、
画面で操作できるようにするソフトです。

インストール方法は前編をお読み下さい。

**なんと前回よりも賢い、いろんな機能が追加されていました！**

### Gemma 2とは
Googleが発表して、なんと**オープンソース**で公開されているAIです。
90億パラメータ版と270億パラメータ版があります。
本記事の「:27b」と書いてあるところを消すと、90億パラメータ版に対応させられます。

## 結論 (先取り)
異次元。

## 使う

### 準備する

前編を読み、`AIのモデルをダウンロードする (モデルごとに初回のみ)`の前まで進めて下さい。

### AIのモデルをダウンロードする (モデルごとに初回のみ)

#### Admin Panel

メニューからAdmin Panelを開きます。

![](https://storage.googleapis.com/zenn-user-upload/c7ac9dfdaaf6-20240628.png)

#### Settings/Models

Settingsにアクセスし...

![](https://storage.googleapis.com/zenn-user-upload/67379b5db867-20240628.png)

Modelsを開きます。

![](https://storage.googleapis.com/zenn-user-upload/a66c2afcb75c-20240628.png)

#### モデル名を入力

赤線のところにgemma2:27bと入力します！

![](https://storage.googleapis.com/zenn-user-upload/d86f5fd885fc-20240628.png)

### いざ会話！
会話してみます！

![](https://storage.googleapis.com/zenn-user-upload/dc2f60c5ae82-20240628.png)

**...え？**
日本語できてるぅー！

**では質問「Rustを使ってフィボナッチ数列を各コードを書いて下さい。」**
無理でしょうね。

![](https://storage.googleapis.com/zenn-user-upload/b303d2cf21cd-20240628.png)

![](https://storage.googleapis.com/zenn-user-upload/dbf89d89c21f-20240628.png)

![](https://storage.googleapis.com/zenn-user-upload/4e71dd976962-20240628.png)

![](https://storage.googleapis.com/zenn-user-upload/b27d2369418f-20240628.png)

(...まだあります)

**...えーーーー！**
(270億パラメータだと遅いけれど、しっかりしてる)

## 感想
ローカルで動くものではないと思う。

## 結論
異次元。
visionOSアプリ開発ドキュメントの公式日本語翻訳が良い感じに充実してる件について

こんにちは。Apple Vision Proが日本で発売される前にvisionOSアプリを5つリリースした個人デベロッパの者です。

私は英語が不得手であり、公式日本語翻訳は非常にありがたい存在です。WWDC23でApple Vision Proがお披露目された当初からvisionOSアプリ開発ドキュメントの公式日本語翻訳が充実していました。そのおかげで非常にスムーズなアプリ開発が実現しました。

本記事では「visionOSアプリ開発ドキュメントの公式日本語翻訳が良い感じに充実してるぞ」という話をします。

![visionOS ランディングページ 日本語.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/7ebc330c-fc04-63c0-9188-dcafcc4df452.png)

## 前書き
- あくまで私が認識している範囲内での解説です。
- Unity関連は(私が詳しくないので)省略します。
- 2024年6月末の現時点での情報です。


## そもそも
Appleさんはアメリカの企業であり、基本的に英語を使っています。開発ツールや開発ドキュメントはもちろん英語です。ただ、重要度の高いドキュメントに関しては一部の外国語(日本語や中国語など)向けに公式で翻訳しています。機械翻訳ではなく人力で翻訳しているようです。翻訳の品質は高いです。


## 公式ドキュメントの全体図
![全体図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/68f24513-bc5f-d572-9616-25c1bb054b1f.jpeg)

一部を除き、多くのドキュメントに公式日本語翻訳があります。


## 補足: 「ドキュメント」とは
Webサイトのdeveloper.apple.com/documentationの下で開発者向け資料(APIリファレンス/記事/サンプルコード)を公開しています。この一連の資料をApple自身は**ドキュメント**と(多くのケースで)呼んでいます。Xcodeから直接参照できます。本記事ではこの資料のことを鉤括弧付きで「ドキュメント」と表記します。


## 「ドキュメント」には公式日本語翻訳が無いけど意外と困らない
「ドキュメント」には公式日本語翻訳が全く無いですが、意外と困りませんでした。その理由はApple独自の情報公開プロセスにあります。

![デベロッパがドキュメントを追う一般的な流れ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/aa50cbfa-a423-28a5-8346-2805f0f1e425.jpeg)

AppleはWWDCで基調講演やPlatforms State of the Union、セッションビデオを通してデベロッパに開発情報を最初にまとめてプレゼンします。その後にデベロッパは「ドキュメント」を読んで理解を深めたり、実際のアプリ開発に向き合ったりします。

日本人デベロッパはWWDCのビデオを日本語字幕で視聴し、要点をしっかり理解した状態で「ドキュメント」を読むことになるので、「ドキュメント」が英語のみであろうともあまり苦労しないでしょう。(少なくとも自分はそうでした。)


## セッションビデオの日本語字幕が公開されるタイミングについて
公式日本語翻訳が出るタイミングは基本的に「オリジナルと同時」か「数日後」のパターンが多いです。

ただし、WWDCのセッションビデオは少し違います。公開時には日本語字幕は無く、不定期で数個ずつ日本語字幕が付いていき、数ヶ月(2〜4ヶ月?)くらいかけて全てのセッションビデオに日本語字幕が付きます。


## 他にも色々と気が利いてる
### 日本語ページへの誘導
公式日本語翻訳が存在する場合、オリジナルページ(英語)の上部に「日本語で表示」ヘッダーが表示されます。

![「日本語で表示」ヘッダー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/a12614a3-f235-c126-d0ca-f3010e2d4362.jpeg)

### 分かりやすいURL設計
オリジナルページ(英語)と日本語ページは別々のURLです。URLに**jp**があるかどうかだけが異なるシンプルな仕様です。そのためブックマークで管理しやすく、比較もしやすいです。また「英語/日本語間で勝手にリダイレクトする」といったありがちな余計なお世話機能も無くて良い感じです。

![URL jp 差分](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/d50955eb-1283-c09c-411c-2b7b80c3d35e.jpeg)

### リンク先が英語のみの場合、「(英語)」と書いてある
公式日本語ドキュメントから英語のみのページへのリンクには「(英語)」と書き添えてあります。

![リンク先が英語のみの場合、「(英語)」と書いてある](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564662/d6376356-3445-6326-592f-9f1ce85b5d4b.png)


## まとめ
- Appleの公式日本語翻訳は高品質で充実！英語不得手な人も安心！
- 「どのコンテンツを翻訳するか」や「翻訳したコンテンツをどう配置するか」などの運用体制が良い感じ！
- visionOS関連は「ドキュメント」以外はほぼ全て公式日本語翻訳あり！
- Appleの日本語翻訳チームに感謝！ありがとう！


## 補足: 昔は「ドキュメント」も一部は日本語翻訳してた
2022年前半頃までは「ドキュメント」の一部(UIKitやCore MLなど)を日本語翻訳していたようですが、最近は「ドキュメント」を日本語翻訳しない方針のようです。

https://developer.apple.com/jp/documentation/


## 補足: 機械翻訳サービスの比較(「ドキュメント」想定)
### Safariのビルドイン翻訳機能
- 文章が乱れがちであまり実用的ではない
- コードブロックの英語を翻訳せずにそのまま表示する

### DeepLのブラウザ拡張
- 文章はそれなりに正確で十分に実用的である
- コードブロックが崩れて残念
- コードブロック内の英語が翻訳されて残念
- Safari向けの公式プラグインが無くて残念


## リンクまとめ
https://qiita.com/mjnfhbuvwebwfiejcnw/items/96b64d2474b6886ddd88

* * *

## 余談: Swift言語ドキュメントの有志日本語訳サイトについて
Swift言語ドキュメントの(Apple公式ではなく)有志による日本語訳サイトが良い感じです。

https://www.swiftlangjp.com
# 乙４受験対策ポイント

# 内容
乙４を受験したのでその攻略について。

# 教材
最初に教材として有名なものを並べておく。
①公論出版の過去問集（535題とか書いてあるやつ）
②10日で受かる! 乙種第4類危険物取扱者すい~っと合格
③ネット上の予想問題集
　http://www.universe-research.com/test.html
　https://otsu4demo.cla-ss.com/
 
# ネット上の定説
ネット上でよく見かける方法は
　①赤本、すいーっと本で概要を掴む
　②公論出版過去問を繰り返す
という学習方法。

結果として私もこれは半分正しいとは思いました。
ただ、
　・この方法の信頼性（要領のいい人の話かも？）
　・順調に理解できているか分からない
　・どの程度の点数ラインに達しているか？（現状の到達点、習熟度を知りたい）
という面で不安がありました。

著名な資格でありながら、過去問持ち帰り禁止で正式な過去問傾向がイマイチ分からない乙４。なので、他の資格試験に比べて習熟度が全く分かりません。これが乙４の最大の敵だと思いました。

# 学習ゾーン
受験、合格してみて肌で感じた習熟度段階をランクを分けしてみました。

|ランク | レベル感  |次にやること  |
|---|---|---|
|ルーキー  |法令、物化、性状の３項目あることが分かる。テキストを購入して見出しだけパラパラ読んだ。  |覚えることはやめ、全体像を把握するように力を抜いてテキストを読む  |
|ブロンズ  |テキストを一通り読んだ。指定数量や分類について覚えられてはいない。  |ここが大事。過去問をやってみる。まだ覚えてないので、１日の量を決めて少しづつ行う。難しいときは★付き問題がおおよそ分かるくらいまで粘る。  |
|シルバー  |過去問を１通りやった。指定数量や分類などの主要なものは覚え始めた。  |理解の壁は突破したので、あとはひたすら過去問を行う。  |
|ゴールド  |過去問を２周以上行い、簡単な問題と難しい問題を区別できる。過去問は7～8割でき、簡単な問題はほぼ間違えない |忘れるかも知れないので安心はしない。よく間違える問題をピックアップする段階。  |
|プラチナ  |よく間違える問題をピックアップし、直前に復習するものを定めてある。  |直前の復習で精度を上げる。忘れないように復習は行う。  |
|マスター  |過去問はほぼ間違えない、マニアックな物質の性状も自信を持って解答できる。  |体調管理のみ  |


ブロンズ～シルバーに壁があり、ここの突破は余裕を持って1～2か月程度みた方がよいと感じました。
学生時代の遺産で物化が分かる人はもっと簡単かも知れません。
ただ、法令でモチベーションが下がりハマってしまうことも大いにあり得ます。
やはり1～2か月は安心に繋がります。

※地方は開催回数が少ないので、落ちないよう計画的に行う必要があります。


# 実際に受験して
私は公論出版の過去問を３周程度し、ゴールドレベルで受験しました。
（公論8割、ネット過去問もそこそこやったが、7割を下回らないくらい）

実際に受けた感想、覚え書き。

▼法令▼
公論でカバーできていないようなものが７問くらい（問題文の言い回しがみたことないもの）。自信アリが６問程度。ほとんどの問題は2択まで追い込めているので、期待値は合格だが、あとは運。

※法令は非常に面倒なので過去問ベースでやりすぎた感。かなり意表をつかれてしまった。
※厳密には公論の過去問より遡ったらあるような問題だったかも知れないが、ちょっと不明。

▼物化▼
公論過去問では見かけないものが３問。
どれがエステルに該当しないか？という問題もあり。
それ以外は公論過去問でカバーできた。おそらくクリア。

▼性状▼
アセトアルデヒド、酢酸プロピレンなどの覚えたくないような性状が３問。
それ以外は公論過去問でカバーできた。おそらくクリア。



# 結果
とりあえず合格（ネット上で合格者一覧にあり、点数はまだ不明）


# まとめ
乙４は難化傾向とは聞いていたがその通りでした。ネット上の簡単は鵜呑みにしてはダメだと思います。

予想問題集もよく出るものを集めたものに過ぎないので、傾向を掴むことができるものではないです。（都合よくマニアックな問題が省いてるので、９割取れてしまう）

公論の過去問を周回する方法は実際に勝負にはなりはしましたが、それだけでは全く安全とはいえません。私は不合格も十分あり得るという心情で合格までの３週間を過ごしました。

法令は特に範囲が広いので大変ですが、過去問を解けるようになってからも、より精度を高める必要があるでしょう。細かい数値もなるべく覚えた方がいいです。

おそらく、
~~~~~~~~~~~~~~~~~
(1)過去問ベースでざっと覚える（部分的、あるいはパターン認識のレベルに過ぎない）
↓
(2)正しく全体を覚える（どの製造所等が該当するかなど、しっかり全体を書き出せるような）
~~~~~~~~~~~~~~~~~

があるべき姿で、あたかも(1)で楽勝のような風説が流布しているのが現状と思います。

“絶対に舐めてはいけない”
“毎日少しづつ、２か月くらいかける”
というのがこの試験かと思いました。
SheetJS(xlsx)を安全に使う方法

### はじめに
NodeJSでExcelファイル(xlsx)の読み書きを行うためのライブラリのうち、一番人気[^1]だと思われるSheetJS(xlsx)を安全に使う方法を解説します。

他のnpmで公開されているライブラリのように `npm install` でインストール可能ですが、脆弱性が見つかっているバージョンがインストールされてしまいます。

```
➜ npm install xlsx

added 9 packages in 735ms
```
```
❯ npm list
sheetjs@ /Users/arikawa/Documents/git/sheetjs
└── xlsx@0.18.5
```
```
➜ npm audit
# npm audit report

xlsx  *
Severity: high
Prototype Pollution in sheetJS - https://github.com/advisories/GHSA-4r6h-8v6p-xvw6
SheetJS Regular Expression Denial of Service (ReDoS) - https://github.com/advisories/GHSA-5pgg-2g8v-p4x9
No fix available
node_modules/xlsx

1 high severity vulnerability

Some issues need review, and may require choosing

```

SheetJSは数年前にnpmでの公開をやめており、現在は公式サイトだけで最新バージョンが配布されています。
公開を辞めた経緯は私も詳しくは理解していませんが、 https://github.com/SheetJS/sheetjs/issues/2667 などに情報があります。

次項でnpmコマンドを使って最新バージョンをインストールする方法を解説します。

### SheetJSのインストール方法
基本的には公式サイトの
https://docs.sheetjs.com/docs/getting-started/installation/nodejs/#legacy-endpoints
の通りにやればOKです。

1. 古いバージョンのSheetJSの削除
    ```
    ➜ npm rm xlsx
    
    removed 9 packages, and audited 1 package in 172ms
    
    found 0 vulnerabilities
    
    ```

1. 最新バージョンのSheetJSをURL指定でインストール
    ```
    ❯ npm install https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
    
    added 1 package, and audited 2 packages in 607ms
    
    found 0 vulnerabilities
    ```

1. SheetJSに依存するライブラリのために依存関係を手動で追加
    URL指定でインストールしたライブラリはバージョン情報が存在しないため依存関係の解決がうまくいきません。そのため、 package.jsonに下記のoverrides指定を記述します。
    ```
    "overrides": {
        "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
    }
    ```

### インストール手順実行後の状態
- package.json
    ```
    ➜ cat package.json
    {
      "dependencies": {
        "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
      },
      "overrides": {
        "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
      }
    }
    ```
- `npm audit`の実行結果
    ```
    ➜ npm audit
    found 0 vulnerabilities
    ```
    →ちゃんと脆弱性0件になりました。

### 参考
- https://qiita.com/yamatai12/items/2691e4594eac4ae1b1a9

[^1]: https://www.npmjs.com/search?ranking=popularity&q=xlsx
Azure Data Factory の Salesforce コネクターにて operation パラメータを queryAll に設定する方法

## 概要

Azure Data Factory の Salesforce コネクターにて、Bulk API における operation パラメータを queryAll に設定するには、`includeDeletedObjects`（`削除されたオブジェクトを含める`）を `True`に設定ことで可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/228a5f0e-d649-c527-0f34-b9891fca3ee6.png)

引用元：[Salesforce との間でデータをコピーする - Azure Data Factory & Azure Synapse | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/data-factory/connector-salesforce?tabs=data-factory#salesforce-as-a-source-type)

Salesforce にて削除されたレコード（削除後に一定期間保持されるレコード）も含めて連携するには、 Bukl API v2 のパラメータとして operation パラメータに queryAll を指定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7c062327-4bf7-ff9f-87b9-004acd1a3c77.png)

引用元：[クエリジョブの作成 | Bulk API 2.0 および Bulk API 開発者ガイド | Salesforce Developers](https://developer.salesforce.com/docs/atlas.ja-jp.api_asynch.meta/api_asynch/query_create_job.htm)

Azure Data Factory ではパラメータの指定はできませんが、とても親切なことに`includeDeletedObjects`（`削除されたオブジェクトを含める`）という設定値を用意してくれているようです。その設定により  operation パラメータにおける queryAll と query の切り替えと同等のことが実施できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ab201d42-2d7b-4afe-da47-fd5541c69f07.png)

## 検証手順と結果

### 事前準備

- Salesforce 環境の準備を行い、接続アプリを作成
- Salesforce にてカスタムオブジェクトを作成し、2 行のレコードを追加した上で片方のレコードを削除 *1
- Azure Data Factory にて Salesforce をソースとしたコピーアクティビティを柵瀬い

*1 `insert01`というレコードと`delete01`レコードを追加後に、`delete01`レコードを削除。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a528b2bf-8c27-6c22-e9e4-b8330fc408d9.png)


### `includeDeletedObjects`（`削除されたオブジェクトを含める`）が False のときの動作確認

削除されたレコードは表示されず、現在有効なレコードのみ表示されたため、想定通りに動作していることを確認できました。

```sql
SELECT Id, Name, IsDeleted FROM Delete_Test_01__c
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a7d77887-2eb6-b97b-709e-181b7fe9456f.png)


### `includeDeletedObjects`（`削除されたオブジェクトを含める`）が True のときの動作確認

削除されたレコードと現在有効なレコードのみ表示されたため、想定通りに動作していることを確認できました。

```sql
SELECT Id, Name, IsDeleted FROM Delete_Test_01__c
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fb50da95-d20e-720b-cf66-f23bdf247cf5.png)
WSL2上のUbuntuでETE Toolkitの環境を構築する

## ETE Toolkitとは
ETE(Environment for Tree Exploration)は、系統樹の構築、分析、可視化をpythonで操作できる計算フレームワークです。これまで、ETEのバージョン3であるete3が使用されてきましたが、この環境構築は[公式ページ](http://etetoolkit.org/download/)の方法に従っても上手くいきません(私の環境では)。最近はete4が新しく開発されているようなので、ete4の環境構築を試しました。

## 動作環境
- Windows11 + WSL2
- Ubuntu
- python 3.9.19

## 環境構築フロー
1. 仮想環境の準備
2. パッケージのインストール

## 仮想環境の準備
私は普段anacondaを使っていましたが、ete4はpipで提供されています。condaとpipは併用したくないので、venvで系統樹解析用の環境を新しく用意することにしました。

```bash:Ubuntu
$ mkdir tree_analysis #系統樹解析を実施するディレクトリを用意
$ cd tree_analysis #系統樹解析を実施するディレクトリに移動
$ python -m venv venv #仮想環境を作成
$ source venv/bin/activate #仮想環境を起動
(venv)$
```

## パッケージのインストール
パッケージは以下の二つをインストールします。
```bash:Ubuntu
(venv)$ pip install https://github.com/etetoolkit/ete/archive/ete4.zip
(venv)$ pip install pyqt6
```

## 動作確認
ete4の使用方法はこの[ドキュメント](https://etetoolkit.github.io/ete/)にまとまっています。試しに、このドキュメントに紹介されたプログラムの一つをtest.pyとして実行します(`python test.py`)。

```python:test.py
from ete4 import Tree
from ete4.treeview import faces, AttrFace, TreeStyle, NodeStyle


def layout(node):
    if node.is_leaf:
        N = AttrFace('name', fsize=30)
        faces.add_face_to_node(N, node, 0, position='aligned')


def get_example_tree():
    # Set dashed blue lines in all leaves.
    nst1 = NodeStyle()
    nst1['bgcolor'] = 'LightSteelBlue'
    nst2 = NodeStyle()
    nst2['bgcolor'] = 'Moccasin'
    nst3 = NodeStyle()
    nst3['bgcolor'] = 'DarkSeaGreen'
    nst4 = NodeStyle()
    nst4['bgcolor'] = 'Khaki'

    t = Tree('((((a1,a2),a3), ((b1,b2),(b3,b4))), ((c1,c2),c3));')
    for n in t.traverse():
        n.dist = 0

    n1 = t.common_ancestor(['a1', 'a2', 'a3'])
    n1.set_style(nst1)
    n2 = t.common_ancestor(['b1', 'b2', 'b3', 'b4'])
    n2.set_style(nst2)
    n3 = t.common_ancestor(['c1', 'c2', 'c3'])
    n3.set_style(nst3)
    n4 = t.common_ancestor(['b3', 'b4'])
    n4.set_style(nst4)
    ts = TreeStyle()
    ts.layout_fn = layout
    ts.show_leaf_name = False

    ts.mode = 'c'
    ts.root_opening_factor = 1
    return t, ts


if __name__ == '__main__':
    t, ts = get_example_tree()
    t.show(tree_style=ts)
    # Or save it with:
    #   t.render('node_background.png', w=400, tree_style=ts)

```

以下のような出力が得られ、系統樹のレンダリングに成功しました。

![ete4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602355/9bd3deac-7cd6-a4f2-9866-0e3727a635fc.png)
【小ネタ】Ubuntuで apt upgrade による自動再起動を無効にする

# はじめに

apt upgradeっと。。。
あれ？なんか勝手に再起動されている。。。なんでなんや

# 無効にする設定

とりあえず、作業するファイルをバックアップ

```terminal
$ sudo cp /etc/apt/apt.conf.d/50unattended-upgrades ~/50unattended-upgrades
```

vim で編集します。nanoでもいいです。

```terminal
$ sudo vim /etc/apt/apt.conf.d/50unattended-upgrades
```

以下の行の `true` を `false` に変更します。

```
Unattended-Upgrade::Automatic-Reboot "true";
```

修正後はこんな感じ

```terminal
$ diff ~/50unattended-upgrades /etc/apt/apt.conf.d/50unattended-upgrades
94c94
< Unattended-Upgrade::Automatic-Reboot "true";
---
> Unattended-Upgrade::Automatic-Reboot "false";
```

# さいごに

かんたんでしたね
Scratchのすゝめ

## はじめに
こんにちは、プログラミングを学ぶ順番を盛大に間違えていたbockringです。そんなことはどうでもいいのですが、やはり
　**プログラムの構造を学ぶにはScratchが良い**
というのがあります。私はArduinoやPythonなどを経験してからのScratchでしたが、
- 条件分岐
- 繰り返し処理
- 変数
などを学ぶのに適していると感じました。逆にそれを学ぶのに注意点もあります。

## Scratchとは？
皆さんご存知でしょうが、
**マサチューセッツ工科大学(MIT)が公開しているビジュアルプログラミングプラットフォーム**
です。ブロックの接続の処理などはGoogle Blockyをベースにしていますが、ブロックのデザインは独自のものですし、そもそもBlockyは横方向接続ですが、Scratchは縦方向接続です。Scratch 2.0以前はAdobe Flash Playerが必要でしたが、Scratch 3.0以降はHTML5での動作になります。外部ソフトは不要です。

これについてはどのサイトにも言えますが個人的に**Firefoxブラウザは推奨しません**。Firefoxは動作が遅めであり、Google Chromeブラウザを推奨します。

## はじめよう

https://scratch.mit.edu/

アカウントの作成は任意です。作成しなくてもScratch 3.0プロジェクトファイル(.sb3)をローカルに保存、そして参照することでプロジェクトデータを保持できます。

なお、アカウントの作成には
- 誕生日
- 年齢
- メールアドレス
- 性別(選択拒否可能)

が求められます。なお、教員の方には教員用のアカウントもありますが、教師アカウントの作成には上記に加えて
- 本名
- 電話番号

などの個人情報が求められます。その点は理解しましょう。とはいえ、悪用はされないので大丈夫でしょうが。

## 基本操作
ここではログアウト状態で説明をします。他の書籍やサイトでも説明されているので、分かりにくかったら他を見てください。

### ホーム画面
![IMG_1507.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/7a27b23c-7e42-52e5-def9-5bf5c9a99eb7.jpeg)
画面の横幅が十分であれば、上の方に画像の通り8項目のツールバーが表示されます。役割は

Scratch:Scratchのトップページを開く
作る:新しくエディターを開く
見る:公開された作品を見る
Scratchについて:言葉の通り
検索ボックス:公開された作品から、条件を指定し検索する
Scratchに参加しよう:アカウントを作成する
サインイン:既成のアカウントでサインインする

です。ここでは作っていきましょう。

### エディター画面
エディターを開くと最初はチュートリアルが表示されると思います。これはバツで消しましょう。
![IMG_1508.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/4e262e0b-5423-05e8-97a5-e23677c0823f.jpeg)

エディターの構成は以下のようになります。
![IMG_1509.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/5da2ab13-24f5-acfd-b212-6c07715fc69c.jpeg)
赤:ブロックパレットの種類の選択
橙:ブロックパレット
緑:スクリプト編集部
青:スプライトの編集
濃青:ステージ(実行するところ)

となります。見たままですね。

ブロックパレットの種類を選択して、ブロックをドラック&ドロップでプログラムを作る… を繰り返し、**緑色の旗**を押して実行です。

## プログラムを作ってみよう
ここからは本を読んで… いやScratchの趣旨的には感覚でとにかく「作ろう」と思ったものを頑張って作るだけです。最初は下手で普通です。そのうち慣れて素早く作れるようになります(なりました)。

なぜ私が放り出すのか。それは面倒だからではなく、Scratchは視覚的にプログラムを作るものです。枠にハマって学習しても意味がありません。**試行錯誤して**いつの間にか覚えてたってなるのが1番良い流れです。数ヶ月もすれば慣れるでしょう。

## おわりに
Scratchを勧めてきましたが、Scratchは
- 繰り返し処理
- 条件分岐
- 並列処理
- 変数

などを学ぶのに強みがあります。プログラミングを投げ出してきた方、もう1回やってみてはいかがでしょうか。

それではまた
【小ネタ】Ubuntuで再起動が必要な状態かどうか確認する

# はじめに

sudo apt update && sudo apt upgrade -y っと。
あれ、再起動いるかどうかでてたのに確認するのわすれた。。。

# 確認する方法

## 別のTerminalでログインする

再起動が必要な場合は、`*** System restart required ***`とログイン時に表示されているはずです。

## `/var/run/reboot-required`　を確認する

ログイン時に表示されているファイルの内容を直接見ます。

```terminal
$ sudo cat /var/run/reboot-required
*** System restart required ***
```

# さいごに

かんたんでしたね
Elasticsearch7から8に上げた時に変更した設定

elasticsearch-rails gemが先月Elasticsearch v8系に対応したv8.0.0をリリースしました。

https://github.com/elastic/elasticsearch-rails/releases/tag/v8.0.0

手元にあったElasticsearch v7系を動かせるRailsアプリケーションでElasticsearch8系を動かそうとしてみたところ、いくつか変更の必要があったのでそちらを紹介します。


## Elasticsearch側

いくつか設定の変更・廃止が存在します。

### action.destructive_requires_name

インデックスを削除するときに、インデックス名を指定する必要があるかどうかというオプションです。
こちらは7以前からも存在するオプションですが、8系ではデフォルト値がtrueになっています。
自分は開発環境ではデータをリセットする時に、`/_all`を使って消し飛ばしたかったのでfalseを明示的に指定しています。
逆に本番環境では、必要がなければtrueにしておくのが良いでしょう。

## gateway.expected_nodes
クラスター内で予想されるノードの数に関するオプションですが、こちらは8系では廃止されました。
`gateway.expected_data_nodes`は残っているので、必要ならこちらを利用しましょう。
gateway関係は他にも8系で廃止になっているオプションがあるので、公式ドキュメントと自身の設定を確認するのが良いでしょう。

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-gateway.html

## node.max_local_storage_nodes

1インスタンス内にいくつノードを起動できるかの設定です。
こちらも8系で廃止となってしまいましたが。元々1に設定しており複雑なことはしていなかったので`elasticsearch.yml`から記述を消すのみにしています。

## xpack.monitoring

Elasticsearch Monitoring プラグインを使用して監視データを収集および送信するための設定です。
こちらも8系で廃止になったのですが、そもそも利用しておらず`xpack.monitoring.enabled = false`のみが記述されていたため、`elasticsearch.yml`から記述を消すのみにしています。

## discovery.zen.minimum_master_nodes

6系以前ではマスター適格ノード数をユーザー側で指定する必要がありましたが、7系でその必要がなくなり8系で完全に設定が削除されています。素直に設定の記述を消せばOKです。

https://www.elastic.co/jp/blog/a-new-era-for-cluster-coordination-in-elasticsearch

## Rails側
Elasticsearch関連の各Gemをv7からv8にすれば動きます。
例外があるとすれば、elasticsearch-transport gemがelastic-transportとして独立しました。

https://github.com/elastic/elastic-transport-ruby

こちらの変更により、クラス名が`Elasticsearch::Transport`から`Elastic::Transport`に変更されています。
もしElasticsearch::Transportを直接呼び出している場合は変更しておきましょう。

```diff_ruby
def search
  # 何かしらの検索処理
+ rescue Elastic::Transport::Transport::Errors::BadRequest => e
- rescue Elasticsearch::Transport::Transport::Errors::BadRequest => e
    # 例外処理
  end
end
```

## まとめ
以前[Qiitaの検索システムを5系から7系](https://qiita.com/WakameSun/items/4d46f99a03f2abdc9eba)に上げた経験がありますが、ユーザーが頑張る必要のある変更は少なくなった印象です。
後輩にどやされてvimを使い始めた

# はじめに
みなさんこんにちは．今回は新しくサークルに入ってきた後輩がvim信者で「まだIDEなんか使ってるんすか？やっぱvimですよ」とどやしてきたので，熱くvimの良さを教えてくれたので，使ってみました．わたしはMacユーザーなので，コマンドは全部Mac使用となっているのでご注意ください．

# vimの導入
neovimというものをインストールするみたい
```
brew install nvim
```

https://neovim.io/

# Astronvimのインストール
neovimの拡張Astronvimをいれるみたい，一気にかっこよくなります
ターミナルで`nvim`入力するだけで見られるので見てください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748983/a64e70e9-f50c-2229-0977-3612c8115ba8.png)


https://astronvim.com/

# vimの基本操作
vimにはおよそ3つのモードがあり，**normalモード**,**visualモード**,**insertモード**です．それらについて説明していきます．

### normal
- 名前の通り，Vimを起動したときのデフォルトのモードです
- このモードでは、キーボードの入力はコマンドとして解釈されます
- カーソル移動、テキストの削除、コピー、ペーストなどの操作を行うことができます
- ノーマルモードでは、テキストを直接入力することはできません
- 他のモードからノーマルモードに戻るには、通常はEscキーを押します

### visual
- このモードでは、テキストの選択を行うことができます
- vキーを押すことでビジュアルモードに入ります
- カーソルを移動することで、テキストの選択範囲を拡大または縮小できます
- 選択されたテキストに対して、削除、コピー、ペーストなどの操作を行うことができます
- Shift+vを押すことで、行単位のビジュアルモード（Visual Line mode）に入ります
- Ctrl+vを押すことで、ブロック単位のビジュアルモード（Visual Block mode）に入ります

### insert
- このモードでは、キーボードの入力がテキストとして直接挿入されます
- i、a、oなどのキーを押すことでインサートモードに入ります
- iは現在のカーソル位置の前に、aは現在のカーソル位置の後に、oは現在の行の下に新しい行を挿入します
- インサートモードでは、通常のテキストエディタと同じように文字を入力することができます

## 基本コマンド
### 1. カーソル移動:
h: 左に移動
j: 下に移動
k: 上に移動
l: 右に移動
w: 次の単語の先頭に移動
b: 前の単語の先頭に移動
0: 行の先頭に移動
$: 行の末尾に移動

### 2. モード切り替え:
i: カーソル位置の前にテキストを挿入
a: カーソル位置の後にテキストを挿入
o: カーソル位置の下に新しい行を挿入
v: visualモードを開始
Esc: 現在のモードからnormalモードに戻る

### 3.テキストの編集:
x: カーソル位置・選択範囲の文字を削除
dd: 現在の行を削除
yy: 現在の行をコピー（ヤンク）
p: カーソル位置の後にテキストをペースト
u: 直前の操作を元に戻す（undo）
Ctrl+r: 取り消した操作をやり直す（redo）

### 4.ファイル操作:
:w: ファイルを保存
:q: Vimを終了
:wq または :x: ファイルを保存してVimを終了
:q!: 変更を保存せずにVimを終了

# AstroNvimの基本操作
Soace + q:操作を中止する

ファイルツリー:
Space + e: ファイルツリーを開く/閉じる
a: 新しいファイルを作成
r: ファイルの名前を変更
d: ファイルを削除

タブ操作:
Ctrl+t: 新しいバッファを開く
Ctrl+w: バッファを閉じる
Shift+h: 前のバッファに移動
Shift+l: 次のバッファに移動

### 検索:
Space + f + f: ファイル検索
Space + f + g: Gitファイル検索
Space + f + b: バッファ検索
Space + f + h: ヘルプタグ検索


# おわりに
これからvimを使い慣れていけたらいいなと思っていますので，ぜひともコメントにおすすめの拡張機能，コマンド操作など書いてくれたら嬉しいです
それではみなさん，いいエンジニアライフを〜👋
mongoose: Docker上のMongoDBのデータを削除 (Delete)

## プログラム

```js:mongo_delete.js
// ----------------------------------------------------------------
//	mongo_delete.js
//
//						Jun/28/2024
// ----------------------------------------------------------------
const mongoose = require('mongoose')

// ----------------------------------------------------------------
console.error ("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', function() {
	console.log('MongoDBに接続しました')
})

// データのスキーマ定義
const citySchema = new mongoose.Schema({
	id: String,
	name: String,
	population: Number,
	date_mod: Date
})

// モデルの作成
const City = mongoose.model('City', citySchema, 'saitama')

const deleteCities = async (id_in) => {
	try {
		console.log("*** deleteCities ccc ***")

		await City.deleteOne({ id: id_in })

	} catch (error) {
		console.error('データの取得に失敗しました', error)
	} finally {
		// 接続の切断
		mongoose.connection.close()
		console.error ("*** 終了 ***")
	}
}

// ----------------------------------------------------------------

const id=process.argv[2]
console.log(id)
deleteCities(id)
// ----------------------------------------------------------------
```

## 実行

コマンド

```bash:go_delete.sh
export NODE_PATH=/usr/local/lib/node_modules
node mongo_delete.js t1164
```

実行結果

```text
$ ./go_delete.sh 
*** 開始 ***
t1164
*** deleteCities ccc ***
MongoDBに接続しました
*** 終了 ***
```
【Python】selfが一度も使われてないクラスならクラスメソッドやスタティックメソッドにするといいかも


偉い人「このクラス一度もselfを使って無くない？」

```python
class MyClass:
    def __init__(self, value):
        self.value = value

    def instance_method(self, arg):
        return self.value + arg
```

偉い人「じゃあわざわざインスタンスにしないでも、クラスメソッドやスタティックメソッドにするといいかも」
俺「はえー」

### インスタンスとは？

インスタンスとは、クラスを基に生成された具体的なオブジェクトのこと。例えば、「車」というクラスがある場合、特定の「車の実体」（例えば「私の車」）がインスタンスとなる。

内部的には、「これ俺の車なんすよ笑」と言うと、「んじゃ場所とっときますね」とメモリを確保している。

Pythonでは、クラスを呼び出すことでインスタンスが作成される。

```python
class Car:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

my_car = Car("Toyota", "Corolla")  # my_carはCarクラスのインスタンス
```

何でもかんでも「これ俺の車なんすよ（笑）」ってやらなくても「あ、はい、車クラスですね。わかりました」というのだけで話が済むことがある。
メンテナンス性とコードの読みやすさが向上する。
具体的には、どこでインスタンス化するか気にしなくていいので、「main.pyでやってたっけ？それともその先だっけ？」みたいな焦りがなくなって結構便利。

とはいえインスタンスにしていても動きはするので、意識していないと難しかったリする。

## 実装の例

- クラスメソッドにするならこう

```python
class MyClass:
    class_variable = 0

    @classmethod
    def class_method(cls, arg):
        cls.class_variable += arg
        return cls.class_variable
```

- スタティックメソッドにするならこう

```python
class MyClass:
    @staticmethod
    def static_method(arg1, arg2):
        return arg1 + arg2
```



# どの手段を使うべきか？
### インスタンスメソッド
インスタンス変数やインスタンスの状態にアクセスする必要がある場合。

- 例：ユーザーアカウントクラスなど

```python
class UserAccount:
    def __init__(self, username, email):
        self.username = username
        self.email = email

    def display_user_info(self):
        return f'Username: {self.username}, Email: {self.email}'
```

### クラスメソッド
クラス自体に関連する操作を行う場合や、クラス変数を操作する必要がある場合。

- 例：設定管理クラスなど
```python
class Config:
    _settings = {}

    @classmethod
    def set_setting(cls, key, value):
        cls._settings[key] = value

    @classmethod
    def get_setting(cls, key):
        return cls._settings.get(key, None)
```

### スタティックメソッド
クラスやインスタンスの状態に依存しない汎用的な操作を行う場合。

- 例：計算などをさせるユーティリティクラスなど
```python
class MathUtilities:
    @staticmethod
    def add(a, b):
        return a + b

    @staticmethod
    def multiply(a, b):
        return a * b
```

この例だと単なる足し算なので嬉しさがわかりづらいが、例えば「消費税計算のためにまず軽減税率が適用される対象かどうかを判別して消費税の計算を……」みたいな「すごい面倒な計算をさせるだけ」って時に便利。

# 参考
https://docs.python.org/ja/3/library/functions.html#classmethod

https://docs.python.org/ja/3/library/functions.html#staticmethod
【ChatGPT＋DALL-E3】多重露光で描く。


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

　今回は、多重露光で描画してみます。

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

　まずは、ニュース。

　OpenAIが
　　TIME誌との提携に
　　　合意したそうです。
　　　　[OpenAIポスト](https://x.com/OpenAI/status/1806335381283189220?t=tUX_RODgFGS80QrBYnCZ7g&s=19)

　TIME誌といえば、
　　アメリカのニュース雑誌。
　　　創業100年の
　　　　老舗企業だ。

　それだけの
　　知識がChatGPTによって
　　　アクセス可能になる。
　　　　これは素晴らしいことですね。
***
　お次は、
　　OpenAIが
　　　ChatGPTの精度向上を
　　　　目指す新技術
　　　　　「CriticGPT」を発表。

　詳しくは、以下を参照。
　　[ITmedia NEWS](https://www.itmedia.co.jp/news/spv/2406/28/news113.html)

　CriticGPTは、
　　ChatGPTが出力した
　　　コードの誤りを見つける能力を
　　　　備えているモデルだとか。

　開発者には
　　ありがたいモデルですかね。

　これまでのChatGPTは
　　コードは書けても
　　　エラーするのが
　　　　当たり前でしたからね😅
***
　さて、本題です。

　“多重露光”をご存知でしょうか？

　ChatGPTさんに尋ねてみました。
***
***ChatGPT 3.5***
多重露光（たじゅうろこう）とは、写真撮影技法の一つで、複数のシーンや動きを同じフィルムやセンサーに重ねて撮影することです。主に以下のような特徴があります：

1. **重ね合わせ効果**: 複数の写真が重なることで、一つの画像に異なる時間や場面が重ねられるため、アート的な効果や表現が生まれます。
   
2. **露出の調整**: 各シーンの露出時間や光の量を調整することで、被写体の透明感や重なり方をコントロールできます。

3. **テクニックとしての応用**: 多重露光は、芸術的な写真表現やクリエイティブな実験に使われることが多く、写真家の個性や技術の一環として重要です。

多重露光はデジタルカメラでも可能ですが、フィルムカメラの時代から存在する伝統的なテクニックでもあります。露光時間やカメラの設定によって、その効果や見え方は大きく異なります。
***

　簡単にわかるように説明しますと、
　　複数の画像を重ねて、
　　　ひとつの画像にすることです。

　光の三原色は赤緑青ですよね。

　それぞれは一色ですが、
　　すべてを重ねると、
　　　白になります。

　多重露光は
　　色の重ね合わせではなく、
　　　画像の重ね合わせなのです。

　カメラの初期の時代からある
　　撮影技術です。

　一枚撮影したら
　　シャッターを開けたまま
　　　レンズにフタをする。

　もう一枚、もう一枚と
　　同じことをしていく。
　　　そうすることで、
　　　　多重露光は
　　　　　行なわれてきました。

　現在のデジカメ（スマホ含む）でも
　　できるそうですが、
　　　私はやったことがありません😅
　　　　被写体を撮るのが主だから。
***
　さて、
　　実際にやってみましょう。

　やり取りをどうぞ。
***
***user***
浮世絵、盆栽、和服の女性。多重露光。アスペクト比は正方形で描画

***ChatGPT***
![A_detailed_multi-exposure_image_featuring_elements_converted.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/86e96810-2b97-7c0f-06e8-5388dd854a02.jpeg)

***user***
ドラゴン、月、城。多重露光。アスペクト比は正方形で描画

***ChatGPT***
![1719542867497.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/3032a127-6d42-cb85-5d13-ca9667ad91d3.jpeg)

***

　今回は、
　　三つの対象物を指定しましたが、
　　　もっと違ったやり方は
　　　　あるかと思います。

　いろいろと
　　試してみてください。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
mongoose: Docker上のMongoDBのデータを更新 (Update)

## プログラム

```js:mongo_update.js
// ----------------------------------------------------------------
//	mongo_update.js
//
//						Jun/28/2024
// ----------------------------------------------------------------
const mongoose = require('mongoose')

// ----------------------------------------------------------------
function get_current_date_proc()
{
	const today = new Date ()
	var ddx = today.getFullYear () + "-" + (today.getMonth () +1)
	ddx += "-" + today.getDate ()

	return ddx
}

// ----------------------------------------------------------------
console.error ("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', function() {
	console.log('MongoDBに接続しました')
})

// データのスキーマ定義
const citySchema = new mongoose.Schema({
	id: String,
	name: String,
	population: Number,
	date_mod: Date
})

// モデルの作成
const City = mongoose.model('City', citySchema, 'saitama')

const updateCities = async (id_in,population_in) => {
	try {
		console.log("*** updateCities bbb ***")
		const ddx = get_current_date_proc()

		await City.updateOne({ id: id_in }, {
			population: population_in, date_mod: ddx
			})

	} catch (error) {
		console.error('データの取得に失敗しました', error)
	} finally {
		// 接続の切断
		mongoose.connection.close()
		console.error ("*** 終了 ***")
	}
}

// ----------------------------------------------------------------

const id=process.argv[2]
const population_in=parseInt(process.argv[3])
console.log(id + "\t" + population_in)
updateCities(id,population_in)
// ----------------------------------------------------------------
```

## 実行

コマンド

```bash:go_update.sh
export NODE_PATH=/usr/local/lib/node_modules
node mongo_update.js t1166 9876500
```

実行結果

```text
$ ./go_update.sh 
*** 開始 ***
t1166	9876500
*** updateCities bbb ***
MongoDBに接続しました
*** 終了 ***
```

## 確認した環境

```text
$ node --version
v22.3.0
```
個人開発で指定した日付のドル円相場がわかるwebアプリつくってみた

## はじめに

諸事情あって、いちいちググらなくても過去のある日のドル円相場をパッと知りたいなあと思ったのですが、良い感じの既存のサービスが見つかりませんでした。

というわけで、「ほな、自分で作るか」と思ったのでちょっとやってみました。

## 欲しいもの(要件？)
- 過去のドル円相場を、日付を指定したら表示してほしい
- カレンダーでポチポチ選べると良さそう
- 利用頻度は多くても月に10回程度
- デスクトップアプリじゃない方がいい(ブラウザのブックマークから開きたい)

## フレームワーク

自分がC#に慣れているので、C#ベースでwebアプリを開発できるBlazorを利用してみることにしました。
Microsoft公式のチュートリアルをひたすら参考にしましたが、最初の方は画面更新すらできず結構苦労しました。(`StateHasChanged()`の呼び忘れでした……。)

## ドル円相場の取得

無料で使い放題のAPIは無かったので、「月に10回程度なら無料で利用できる」・「過去のドル円相場が無料で取得できる」ことを条件として探し、以下を選定しました。
https://currencyapi.com/

APIの呼び出し回数の制限が300回/月なので、よほど連打しなければ使い切ることはないはず。

なお、公式からC#のSDKが公開されていたのですが、ソースコードを見に行ったところ「クエリパラメータでAPIキーを指定するとアクセスログなどからAPIキーがバレるので、HTTPのリクエストヘッダーに指定した方がいいよ！」と公式のドキュメントに書いてあるにもかかわらずクエリパラメータで指定する実装になっているようでした。
そのため、SDKは使わず、入力されたAPIキーをリクエストヘッダに突っ込んでAPIを呼び出すような実装を自前でしました。

## UXについて(うまくいっていないこと・できていないことが多め)

### APIキー
登録制のAPIを利用する以上、APIキーの入力と認証は避けられませんでした。
また、回数制限があるので、本当は残り回数を画面で表示すべきなのですが、できていません。

### 日付選択
本当はカレンダーをポチポチすると即表示される……という風にしたかったのですが、APIの呼び出し回数に制限があるので、むやみな呼び出しを避けるために結局カレンダーで選択→ボタン押下 でドル円相場を表示するようにしました。

### 履歴の表示

APIの呼び出し回数に制限があり、かつ一度の呼び出しで1日ぶんのドル円相場しか取得できないため、一度表示した日付のドル円相場は画面上に履歴として表示するようにしました。
また、一度表示していて履歴に存在する日付をカレンダーで選択してボタンを押した場合は、APIを改めて呼んでしまわないようにガードをかけています。

### レイアウト
各コントロールの配置・マージンがだいぶ詰まっているので直したかったのですが、やれていません。

## 公開方法
google firebaseを利用し、以下の記事を参考にデプロイしました。
https://qiita.com/kimuradesu/items/3d70d5f4f1370764aa39

## 作ったもの

以下です。(CurrencyAPIに登録してAPIキーを入手しないと動きません。)
https://exchangeappproject.web.app

動かすとこのような感じです。
![ドル円相場表示アプリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062427/60f35db2-afda-27ea-dea3-a839ead12dae.png)

## さいごに

機能としては小さなものですし、特にUX周りが本当によろしくないのですが(見栄えが悪すぎる……)、個人開発でアプリを初めて公開まで持っていけたのは良かったです。
またネタがあれば(欲しいものができれば？)個人開発やってみたいなと思います。
SPAのすすめ

## SPA(Single Page Application)とは
- サーバとはデータのみやり取りし、HTMLの書き換えはブラウザ上でやる手法
- AJAXに近いが、ブラウザのURLや履歴を制御することでよりリッチな体験を提供する
- HTMLが１枚のみ、それも超シンプルなものになるので、Single Pageと呼ばれる


----
## 歴史
- 世界の度肝を抜いた**Googleマップ**と**Gmail**
- 想像してみてください：これらのアプリが操作の度に画面全体を書き換えてたとしたら、使い勝手はどうなりますか？
（昔の地図サイトやWebメールはそういう作りだった！）

----
## 翻って、現代
- もはやSPAは当たり前！
- Webアプリの情報量は増える一方。SPAでないとユーザ体験は向上しない
（例えば、いいね！を押したら画面全体がリフレッシュされるYouTube・・・使い物になると思いますか？）


----
## SPAの利点
- 通信量の削減
  データ量が減る（HTMLが混じらないので）
  キャッシュを効かせやすくなる
- ユーザ体験を向上させやすい：ページ全体が書き換わる、という体験からの脱却

----
## SPAを作ってみるには
- フロントエンドフレームワーク：React/AngularJS/Vue/**Elm**など
- バンドラ：Webpack/**Parcel**など
- 静的ホスティングサービス：Azure SWA/AWS Amplify/Google Firebaseなど

----
## SPAを作っていて感じること
- 一番の利点は「分割統治」と感じる
  関心のあることのみ実装すればOK（SSRだとこれが難しい）

----
## SPAの弱点
- JS／CSSファイルの肥大化
  キャッシュ／SSR

----
## SPAを始めてみよう
- React＋Vite or Parcelで始めてみよう
  サーバ側を考えなければ、これで充分に遊べる
- サーバを自前で立てるのは面倒なので、Firebase(Google製)やAmpliry(AWS製)の利用がおすすめ
  Firebaseは独自仕様のストレージ
  AWSはGraphQL
  ※SWAはDBのサポートが少し弱めなので「ちょっと試してみる」にはおすすめしません
【WordPress】date関数を使うと９時間のズレ問題の解決方法

## 主な想定読者
WordPressサイトを運営、制作している方
WordPressテーマやプラグインの開発者

## 概要
WordPressの「設定」の「一般」でタイムゾーンの設定を「東京」にも関わらず、
WordPressでPHPの`date`関数を使用すると、デフォルトではUTC（世界標準時）で時間が表示されます。
JST(日本時間)に変更する方法について説明します。WordPressの機能を活用する方法を説明します。

## 解決方法

WordPressでは、`date`関数の代わりに`wp_date`関数を使用することが推奨されます。`wp_date`関数は、WordPressの設定に基づいたタイムゾーンを自動的に使用します。これにより、日本時間を正確に表示することができます。
`date_default_timezone_set`関数でタイムゾーンを変えてしまう方法もありますが、プラグインなどの影響を考えるとwp_date関数がオススメです。

```php

wp_date('Y-m-d H:i:s')
//2026-06-28 18:00:00

```

このコードでは、WordPressの管理画面で設定された日付と時間のフォーマットに従って、現在の時間を日本時間で表示します。



## まとめ

WordPressで時間を日本時間に設定する方法として、`wp_date`関数を使用することを推奨します。
`wp_date`関数は、WordPressのタイムゾーン設定を自動的に反映するため、最も簡単で正確な方法です。また、`date_default_timezone_set`関数を使用する方法もありますが、WordPressの標準機能を活用する方が管理が容易です。
９時間ズレているなって時はこの記事を思い出してください。
Ubuntuのはじめ方　〜Windowsからの移行〜

## はじめに
こんにちは。今更感しかない記事を書くbockringです。

かなり前(2022年10月5日)からWindows 11へのアップグレードが有償化されましたよね。別にそれだけなら良いのですが、まだ使ってる方も多いであろうWindows 10は2025年10月14日にサポートを終了します。つまりもう1年半も無い訳です。しかし、Windowsは高いという問題もあります。ということでUbuntuに移行しよう、という内容です。

ちなみになぜUbuntuかと言われれば**安全で完全無料、そして扱いやすいから**ですね。企業向けの一部のバージョンは有料ですが、基本的には無料です。

:::note info
この記事は移行の方法などを知りたい方向けです。

PCの知識をお持ちの方(コマンドプロンプトをハードに使用している方やディレクトリエディタをご使用の方など)はこんな記事なんて見ないで**DebianのClient版に**でもしてしまいましょう。
:::

## Ubuntuとは
UbuntuはLinux系のOSで、Debianがベースになっています。Linuxと聞くと
　**「コマンドなんて私にはとても扱えないわ！　ｷｬｯ」**
という方も多いのでは無いでしょうか。なんなら
　**「Linux? 何それ。でもなんか難しいんでしょ？」**
って方もいるかもしれません。

ご安心ください。UbuntuはGUIの強化や利便性の強化などがされており、**コマンドとは無縁のまま**使用が可能なOSです。

ネット上ではチラホラ言われていますが、**Windowsからの移行はLinux**とも言われ始めているほど、Linuxの需要が高くなっています。

## WindowsとUbuntuの違い
もちろん、中身は違うので操作感も違うところがあります。それは
- .exeファイルが使用できない(例外あり)
- タスクバーの位置
- 入れられるアプリケーションの種類

など、違いはあります。しかし、アイコンが大きいので**老眼でも安心**です。

ちなみに、**Microsoft 365**(旧Office 365)は使用できません。でも大丈夫です、Ubuntuには標準で**Libre Office**がインストールされています。操作感はあまり変わりません。ご安心ください。Chromeも使えます(Chromiumも殆ど同じものです)。

先ほど、exeは使用できないと述べましたが、その代替ソフトがあることも多いですし、exeファイルも**Wine**を通せば一応動作します。そして、**「どうせソフトのインストールはコマンドなんでしょ？」** とか思ったそこの貴方、大丈夫です。Windowsで言うMicrosoft ストアに代わる**Gnome Software**という視覚的にインストールが可能なソフトが標準でインストールされています。

そして何より、Windowsよりも幅広いデバイスで使用可能、つまり連携がしやすくなっています(Googleアカウントなどに結びつけることも可能・後述)。これができるのは**多くの企業から「Ubuntuは安全だ」と認められている**と捉えることもできます。

## インストール方法
インストールは至って簡単。

①[Ubuntuのファイルをダウンロード](https://releases.ubuntu.com/24.04/ubuntu-24.04-desktop-amd64.iso?_ga=2.3876786.348901850.1719539044-1815155030.1719539044)する
②Etcher(書き込みソフト)をインストールする。※書き込みソフトであれば何でも構いません。
[Windows用](https://github.com/balena-io/etcher/releases/download/v1.19.21/balenaEtcher-1.19.21.Setup.exe)をダウンロードする
③Etcherを開き、**Select Image**を選択し、Ubuntuのファイルを指定する。(amd64.isoで終わるファイルです)
④USBメモリーを挿し、**Select Drive**からUSBメモリーを指定する。
⑤**Flash!** を選択し、書き込む。
⑥完了後、USBメモリーを抜く。

:::note alert
残したいファイルはこの先に進む前に書き込んだUSBメモリーとは別の保存媒体(SDカードやUSBメモリーなど)に保存をしてください。ここで保存をしていないと、ファイルは全て消えてしまいます。
:::
⑦PCのメーカーサイトで**USBブートの方法**を検索する
⑧電源を切る
⑨USBメモリー(Ubuntu)を挿し、電源を入れる。
　**電源を入れたらBIOSを起動し、USBブートを有効にすること。**
 ⑩画面の指示に従いインストール
　+
必要があればデータの移行をする

これだけです。文字を打つのは**ユーザー名の指定**と**パスワードの設定**と**Wi-Fiの接続**ぐらいです。

## おわりに
Ubuntu、使いやすいでしょ？(圧)

ということでUbuntuの使用をすヽめてきましたが、Ubuntuの良いところは開発が継続されているので、アップデートもしっかりできます。Windowsのようなデバイス制限もかなり緩いですし、幅広いデバイスで使用可能なことがメリットです。

それではまた〜