OmniAICreator/Qiita-1.07M huggingface dataset:
Emacs Lisp 超初心者がコマンドを作ってみる 〜バッファーにコピー〜

前回の バッファーにカキコ は文字列をバッファーに書き込むものでしたが、今回の バッファーにコピー はカレントバッファーの範囲(start end)を指定して別のバッファーにコピーします。

::: note info
前回と同様、サンプルファイル rev-list-options.po を開いておきます。
:::

# プログラム

````common_lisp:po-ediff-previous-msgid.el
(defcustom po-ediff-previous-msgid-buffer-a-name "*pepm-previous-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)

(defcustom po-ediff-previous-msgid-buffer-b-name "*pepm-now-msgid*"
  "po-ediff-previous-msgid BUFFER A name. pepm is PoEdiffPreviousMsgid"
  :type 'string
  :require 'po-mode
  :group 'po)


(defun po-ediff-previous-msgid ()
  "Ediff previous msgid (marked #| ) and msgid."
  (po-find-span-of-entry)
  (let (
	(oldbuf (current-buffer))
	(msgid (po-get-msgid))
	(untranslated-regions (po-previous-untranslated-regions))
	)
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-ediff-previous-msgid-buffer-a-name))
      (erase-buffer)
      (dolist (region untranslated-regions)
	(insert-buffer-substring oldbuf (car region) (cdr region))
	)
      (restore-buffer-modified-p nil))
    (save-current-buffer
      (set-buffer (get-buffer-create
		   po-ediff-previous-msgid-buffer-b-name))
      (erase-buffer)
      (insert msgid)
      (setq buffer-read-only t))))
````

前回の バッファにカキコ では po-get-msgid で取得した「文字列」をバッファに書き込みました。

今回は前回の バッファにカキコに加えて、 カレントバッファの範囲 region を指定して、カレントバッファの指定範囲をコピーします。

書き込んだ *pepm-previous-msid* バッファを見ると previous msgid (#| でマークされた部分)が書き込まれています。 msgid と違って unquote されていません。これは(今回は)そのままコピーしたためです。これは今後 unquote 等していきます。

dolist untranslated-regions というリストの内容を1つずつ取り出して処理します。今回は全てバッファにコピーしますが、たいてい要素1つだけのリストのようです、が、リストです。

insert-buffer-substring で、指定のバッファ oldbuf から「カレントバッファに oldbuf の指定範囲をコピーします。

## 実行結果画面(参考)

バッファにカキコ した画面(参考)
![buffer-pepm-now-msgid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435164/a390c85a-a6b0-2291-2da8-332632eb7194.png)

バッファにコピー した画面(参考)
![buffer-pepm-previous-msgid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435164/de7b3605-7cb9-e0e3-a840-fde1dab86993.png)

今回はここまで。
ポートフォリオ作成時メモ　part9 ~Bladeテンプレートと?? 演算子の活用~

## はじめに
こんにちは、未経験からエンジニア転職を目指しているものです。  
オンラインスクールで本格的に学習して7ヶ月目に入りました。PHPとLaravelを学習しながらポートフォリオを作成中です。  
ポートフォリオ作成手順や学びを中心に記録していこうと思います。今回は、LaravelのBladeテンプレートで使用できる「?? 演算子」の仕組みと、その活用方法について解説します。

---

## 概要
Laravel Sailを使った開発環境で、Bladeテンプレートを用いてデータの表示を行いました。  
その際に役立ったのが「??（null合体演算子）」です。この演算子を利用することで、データが存在しない場合の代替表示を簡単に実現できます。

- **?? 演算子の概要**と仕組み
- **実際のコード例**での活用
- **動作の詳細解説**
- **従来のif文との比較**

---

## 経緯と問題点

### 活動場所データが存在しない場合の対応
開発中のポートフォリオで、ユーザーが活動場所の情報を登録していない場合でも、空白のまま表示されるのではなく、代替テキスト（例:「データなし」）を表示させたいと考えました。  

しかし、登録データがない場合にエラーが発生したり、適切な表示がされないことがあり、以下の方法を採用しました：
- **?? 演算子** を使用して、データがnullのときに代替テキストを表示。

---

## コード例

以下のコードを使用して、活動場所を表示する機能を実現しました。

```html
<!-- 活動場所の名前 -->
<div class="bg-gray-100 p-4 rounded-md">
    <h3 class="text-lg font-bold">活動場所の名前</h3>
    <p class="text-gray-700">{{ $mapInfo->activity_location ?? 'データなし' }}</p>
</div>
```

## ??演算子の動作と詳細

```php
{{ $mapInfo->activity_location ?? 'データなし' }}
```

**仕組み**
1. **mapInfo->activity_location**の値を確認
2. 存在し、かつnullではない場合：
    → $mapInfo->activity_locationの値を表示
3. 存在しない場合またはnullの場合：
    →　**データなし**　を表示

**動作の具体例**
$mapInfo->activity_locationが「新宿区」の場合：
```php
$mapInfo->activity_location = "新宿区";
```

表示結果：
```php
新宿区
```

$mapInfo->activity_locationがnullの場合：
```php
$mapInfo->activity_location = null;
```

表示結果：
```php
データなし
```

$mapInfo自体がnullの場合
```php
$mapInfo = null;
```

表示結果;
```php
データなし
```

## 従来のif文との比較
以下のif文と同じ意味を、??演算子で簡潔に表現すると以下になる
**従来の書き方**
```php
if (isset($mapInfo->activity_location) && $mapInfo->activity_location !== null) {
    echo $mapInfo->activity_location;
} else {
    echo 'データなし';
}
```

**演算子を使った書き方**
```php
{{ $mapInfo->activity_location ?? 'データなし' }}
```

メリット：
- コードが簡潔で読みやすくなる
- ネストが深くならず、テンプレート内での記述量が減少

## 最終的な成果
- ?? 演算子を使用することで、データがnullの場合でも代替テキストを表示できるようになった
- Laravel BladeテンプレートとTailwind CSSの組み合わせで、簡単に整ったUIを構築可能

## まとめ
今回の記事では、LaravelのBladeテンプレートにおける「?? 演算子」の基本的な使い方とその効果について整理しました。
この演算子を活用することで、データが存在しない場合でもエラーを防ぎ、視覚的な整合性を保つことが可能です。

最後までご覧いただきありがとうございました。
みんなが当たり前のようにやるのに、全然そうじゃないデータ補正

最近悩んでいることの一つであるデータ処理・補正...

実験データって、そのまま使えることは少ないですよね？
「何のデータか」にもよりますが、多くの場合、**補正**や**処理**を行った後に、可視化や解析を行います。

補正する方法って、例えば、内部標準物質で補正したり、中央値をそろえたり、スケーリングしたり（また何種類かもあるし）、総量で補正したり、log使ったり、QCで補正したりなど...
**え～無理 :disappointed_relieved: どんだけやればいいの？ 何がゴールなの？？**

という質問に、今回の記事で答えられたらと思います！

（ps.「質量分析のデータを扱う上で」という前提の文章が多いかもしれません）

## そもそもなんで補正するん？

実験を行う上で、データが１つしかない場合は、結果が良くても悪くても「本当なの？」と確信できないということが多いので、少なくとも **複数のレプリケート（繰り返しデータ）** を取得します。レプリケートが多くなればなるほどサンプル間の差が生じやすく、その差を補正するため、つまり、**手技的な差やデータの偏りを補うためにやるものが「補正」**。

例えば:
・同じサンプルでも測定条件の微妙なズレや機器の感度差で数値が異なる。
・細胞数が異なると、サンプル間の絶対値に差が出る。
・バッチ間で測定日の違いが誤差を生む。
これらの偏りや誤差を補正して、データの「信頼性」を高めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957799/6823fa9a-7527-d2c7-55b2-93c5694624ed.png)

## どうやって選ぶの？
選ぶには、自分がどのようなデータを用いていて、どこで誤差が出やすいかというのが大きく関係します。簡単に言えば、**目的に応じて**。。。

例えば、細胞のデータならサンプル間の細胞数が多少異なるため、目的に応じて細胞数や含まれるタンパク質か脂質の量で補正したり、内部標準物質の強度か面積で補正したり、解析時のバッチ補正にQCを使ったりすると思います。
補正方法は「どのデータを使っているか」「どこで誤差が出やすいか」によって異なります。

例えば：
目的: サンプルごとの総量差を補う。
方法: 脂質のデータなら、各サンプルの総脂質量で補正。

目的: 機器や手技の影響を補正。
方法: 測定時に添加した内部標準物質の強度を基準に補正。

目的: 測定値のばらつきをそろえる。
方法: 各サンプルの値を中央値で正規化する。

目的: 異なるスケールのデータを比較可能にする。
方法: zスコア（平均0、標準偏差1）やlog変換。

目的: バッチ間や経時変化の補正。
方法: 質量分析データでQCサンプルを使い、補正曲線を作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957799/f1560102-d986-3bac-6137-f4b259b459c4.png)

でもでも、分かっていて、分かっているものでやっても **「これでいいの？」** というのが出てこないです？:weary:

## どこが目標なの？何が補正できているのかの基準？

一番大事な部分の気がします！！というか今までずっと悩んでいた部分、、
ある程度見るものが決まっていて、そのための手技で実験していれば、特に必要がないと思いますが、それ以外の場合、**つまり、色々みたい！というときにはデータをどう補正するかによって見え方がめちゃくちゃ変わるー！**
なんでかというと、
データって多くなればなるほど分散するより、偏ってしまうケースも多いし、ものによって比較しづらかったりします。例えば、二種類のものをそのまま比較しようとすれば、スケールが異なるかも、そもそもめちゃくちゃあるものがめちゃくちゃ変化しているのに、それが少しだけあって、少しだけ変化していないものと同じく見えちゃうかもということです。

なので、データの偏りを補正するという意味で、データができるだけ分散するようにスケーリングなどで補正します。

具体例: データの偏りの補正
例えば、以下の2つの成分を比較するとします：

|成分|量の変化|測定結果|
|---|---|---|
|成分A（多い）|大きく変化|100 → 150|
|成分B（少ない）|小さく変化|5 → 6|

補正前のデータだと、成分Aの変化が圧倒的に目立ちます。
しかし、データのスケールが異なるため、成分Bの変化も重要な意味を持つかもしれません。

補正方法：スケーリング
データをスケーリング（例: zスコアやlog変換）すると、成分Bの変化も適切に反映され、比較がしやすくなります。

## データ補正のまとめ：正確で効率的な解析のために

データの補正は、手技や測定の誤差を最小限に抑え、正しく比較・解析するために行います。

**目的に応じた補正手法を選ぶ（総量、内部標準、QC補正など）**。
データの偏りやばらつきを適切に補正することで、「**正しい解釈**」 と 「**効率的な解析**」 が可能になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957799/29afcdd4-d24f-eb5f-3987-814d20fd4e3d.png)

豆知識になればうれしいです！
** *Holly, jolly, merry christmas! And wish you all the best in 2025! <3* **
【Athena】一度作ったテーブルの定義を変更する

## 概要
[【Athena】S3ファイルを参照するクエリを作成する](https://qiita.com/Shimooo_mutenka/items/40716fc23e84e3033c06)などしてAWS Athenaで作ったテーブルの定義は、直接編集する手段が無さそう。DDL文を出力・編集して再度実行するよう、対応します。

## 既存テーブルのDDL文を出力する
Athenaのクエリエディタにて、サイドバーからテーブルの「︙」マークをクリックし、`テーブルDDLを作成`を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/ce3d4051-05a8-a759-7cff-96c4deb92b9d.png)

クエリエディタに以下SQLを書いて実行しても同じ結果が得られます。
```sql
SHOW CREATE TABLE `t_something`; -- テーブル名は適宜、手元の内容に応じて変更のこと
```
上記により、クエリエディタの結果欄にCREATE TABLE文（DDL）が吐き出されているので、コピーします。後の手順でテーブルの削除を行うので、コピーしたDDL文はクエリエディタもしくは別途テキストエディタにペーストしておくと安心です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/382630c3-4780-31bd-72ac-f149b1acffb1.png)

今回の事例では、以下のようなDDL文が吐き出されたと仮定して進めます。
```sql
CREATE EXTERNAL TABLE `t_something`(
  `id` varchar(40), 
  `no` varchar(40)
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY ',' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://some-bucket/cleansing-data'
TBLPROPERTIES (
  'classification'='csv', 
  'transient_lastDdlTime'='1733349313')
```

## 既存テーブルを削除し、新しいDDL文を実行する
サイドバーから該当テーブルの「︙」マークをクリックするか、以下SQLをクエリエディタで実行して既存テーブルを削除します。
```sql
DROP TABLE `t_something`;
```

その後、クエリエディタにて必要なDDL文編集を行い、実行します。これにより、新しい定義にてテーブルが作成されます。たとえば以下SQLでは、先の手順で吐き出した既存テーブルのDDL文に対して、CSVヘッダ行をスキップするプロパティを追加しています。
```sql
CREATE EXTERNAL TABLE `t_something`(
  `id` varchar(40), 
  `no` varchar(40)
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY ',' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://some-bucket/cleansing-data'
TBLPROPERTIES (
  'classification'='csv', 
  'skip.header.line.count'='1', -- S3から読み込む際、ヘッダ行をスキップするプロパティを追加
  'transient_lastDdlTime'='1733349313')
```

ここまでの作業で、新しく作成されたテーブルにて、変更内容が反映されているはず。

## トラブルシューティング
### コピーしたDDL文を編集・再実行時にエラー　FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. AlreadyExistsException(message:Table table_name already exist)
DROP TABLEの実行忘れ。既存テーブルの削除を行ってから、改訂したDDL文を実行してください。
【Ruby】今日書いたコードの振り返り(繰り返し)#7

# はじめに
こんにちは！アメリカに住みながら独学でソフトウェアエンジニアを目指しているものです。
今回は「たのしいRuby」のアウトプットを兼ねて、ある問題を解いた内容を振り返り、その中で学んだことについて書きたいと思います。

## 問題の内容
与えられた整数 `n` に基づき、次のような数のパターンを繰り返し表示するプログラムを作成することが求められました。

例えば、`n = 5` の場合、次のように数字を表示します。
```ruby
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
```
`n = 3`の場合は、以下の通りです
```ruby
1
1 2
1 2 3
```

## 私の回答
最初に書いたコードでは、繰り返し処理の中で配列を毎回初期化し、数字を順番に追加してから表示する方法を取りました。
```ruby
def generate_pattern(n)
    ary = []
    n.times do |number|
        (number + 1 ).times do |i|　
            ary << i + 1
        end
        puts ary.join(" ")
        ary = [] # 出力したら初期化
    end
end

generate_pattern(5)
```
上記の出力例をみて、繰り返しの中でさらに繰り返しをしていると考えて2つ`times`メソッドをとってみようと思いました。

## このコードの問題点
* 毎回 `ary = []` を使って配列をリセットしている
配列をリセットするのは効率が悪く、ただ出力するためだけに配列を初期化しているのは冗長です。リセットする手間を省く方法を考えるべきでした。

* `times` メソッドを二重に使っている
`times` メソッドを使わなくても、 `(1..(number + 1))` のような範囲を使えば、もっとシンプルに書けるはずです。

## 改善したコード
次に、冗長な部分を改善し、よりシンプルなコードに変更しました。配列のリセットを避け、 `ary = (1..number + 1).to_a` を使って、最初から必要な数字を配列に格納するようにしました。

```ruby

def generate_pattern(n)
  n.times do |number|
    # 1からnumber+1までの範囲で繰り返し、配列に格納
    ary = (1..(number + 1)).to_a
    puts ary.join(" ")
  end
end

generate_pattern(5)
```

このコードでは、配列 ary を一度だけ作成し、その後必要な数をそのまま格納して出力する形にしています。
配列のリセットもなく、コードが簡潔になり、より効率的になりました。

## もうひとつの解答例
AIを使用して違い解答パターンを作成してもらいました。
`each` メソッドを使って、より直感的に n 回の繰り返し処理を行っています。
```ruby
# パターンを生成するメソッド
def generate_pattern(n)
  # 1からnまで繰り返し処理を行う
  (1..n).each do |i|
    # 1からiまでの数を配列として作成し、スペースで結合して表示
    puts (1..i).to_a.join(" ")
  end
end

# 実行例
generate_pattern(5)
```
このコードでは、繰り返し処理のシンプルさが際立っています。配列を作成してから `join(" ")` で結合し、表示する部分までが一貫して直感的に書かれており、非常に効率的です。


## 上記を通して学んだこと
* 冗長な初期化や重複処理を避ける
`(1..n)` や `(1..i)` のような範囲オブジェクトを使うことで、`times`メソッドを二重に使わず、スッキリと書けることを実感しました。
* `each` メソッドの有効活用
繰り返し処理には`each`メソッドが便利で、`while`や`二重times`を使わなくても簡潔に表現できる場合が多いことを再確認しました。

# まとめ
今回の問題を通じて、繰り返し処理における最適なアプローチについて学びました。最初に書いたコードには冗長な部分が多く、改善したコードを通して、より効率的でシンプルな方法にたどり着けました。今回の経験を元に、今後もコードを改善していく力を養いたいと思います。

また、今後もアウトプットに関する記事をどんどん書いていきたいと考えていますので、引き続きよろしくお願いします！
【QuickSight】QuickSightの初期設定

## 概要
QuickSightを利用するにあたり、必要な手順と設定内容を整理します。

## QuickSightを利用できるグループを作成
あらかじめ、QuickSightを利用できる許可セットを割り当てたグループを作成し、開発担当者のユーザーを割り当てておきます。ユーザー/グループ/許可セットの作成方法は[任意の権限を付与したユーザーを作成する（Identity Centerで管理）](https://qiita.com/Shimooo_mutenka/items/67cd955ec5da2be45393)を参照してください。

## QuickSightの初期設定
マネジメントコンソールからQuickSightサービスを検索し、有効化を始めます。

まずQuickSightアカウントの基本情報を設定します。以下画像を参考に設定を行ってください。QuickSightアカウントは、AWSアカウントやユーザー/グループとは別管理となっている模様。新規で名称を考えて記入します。画像に記載しているように、認証方法のラジオボタンを操作する前に、下部のリージョンをIdentity Centerのあるリージョンと同一にしないと、該当リージョンにIdentity Centerが存在しないとしてエラーになるので注意しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/5b2c017d-8c1c-a61b-dfcb-480220f166cc.png)

`設定`ボタンをクリックすると、後続の設定項目が開くので記入します。いったん、管理者グループにQuickSight利用許可セットを持つグループを割り当てました。おそらく、新規ダッシュボード作成や外部ユーザー利用に伴って、別途適切なグループの作成と割当が必要になりそうです。（今回やってません、、）　アクセス可能なサービスの選択を行い、ピクセルパーフェクトレポートのオプションは`OFF`にして先へ進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/2f99e4d1-2125-1398-93ce-06ae216a2caa.png)

サンプルダッシュボードの構築が行われ、サービスが利用できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/f074db96-8bff-8e3e-b586-96da5a21769c.png)

## 追加設定
ダッシュボードの一覧画面から、改めて設定画面を開いて追加の設定を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/d4f06e88-a120-bf7c-88fb-a164fc56180f.png)

ユーザーの管理 > ロールグループの管理　から、AWSグループ割り当てを変更できます。

SPICE容量では、`キャパシティを自動購入`がデフォルトで有効になっているので、不要であれば切っておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3906608/ac99884b-cf71-ae49-be38-a8870895c935.png)
【Git】手元の作業を前のコミットでやったことにする

## 概要
「〇〇の修正」つって自信満々でコミットしたのに、うっかり考慮漏れてたり要らん処理消し忘れてたりしたときの対処法。追加修正分を新たにコミットするのではなくて、最新のコミットに反映して1度でやったことにします。

## 注意事項
プロジェクトやチームの方針によっては、ミスや混乱のもとになるので禁止されてる場合があるので確認してからやってください。特にリモートリポジトリにpush済のコミット書換はご法度とされてる場合が多いです（既に別のメンバーがローカルにpullした内容が書き変わると大混乱になるため）

## 方法
### 前提条件
たとえばログイン画面を実装するタスクをこなしているとします。ログイン機能の実装が終わってコミットしたあと、パスワードを非表示にする処理を入れ忘れていたのに気づいた場合を想定します。

### 旧来の方法（正攻法）（新たにコミットする）
```bash
41d940b: ログイン機能追加
905d116: パスワードを非表示にする処理を追加
```

これだと、作業履歴と一致はするけど、`905d116`の作業内容は本来`41d940b`に含みたかったものなので、ちょっとカッコ悪いですね。くわえて、ログイン機能追加の反映分だけにフォーカスしてレビューするときに、複数のコミットを跨いで見ないといけないので、レビュアーに負荷がかかります。（1機能1プルリクエストで立ててれば、問題ない場合が多いけど）

### 手元の作業を前のコミットに押し込む方法（本題）
```bash
41d940b: ログイン機能追加
```

上記コミットが最新の状態で、パスワード非表示処理を実装した後、以下のコマンドを実行します。

```bash
git add -A # すべての変更をステージング もちろん追加のあったファイル個別にaddしても可
# 1つ前のコミットに作業内容を反映 コミットメッセージを維持したいか編集したいかで、以下から選んで実行
git commit --amend --no-edit # コミットメッセージはそのまま
git commit --amend --no-edit -m "コミットメッセージを上書きしたいときはこちら"
```

上記実行した時点でのコミット履歴は`41d940b: ログイン機能追加`が最新のままで、同コミットにパスワード非表示処理も入った状態になる。

### 既にリモートリポジトリに最新コミットをpushしていた場合
2つの作業が1つのコミットにまとまったら、あとはpushするだけ。ところが、ここでamend付きコミットをやる前の最新コミットが既にリモートリポジトリにpush済である場合、エラーになります。（同じコミットが既にpush済なのにローカルと差分が生まれているので、当たり前）

この場合、以下のコマンドを実行して、強制的にリモートリポジトリのコミットを書き換えます。
```bash
git push --force-with-lease origin <ブランチ名（feature/#12-enable-something など）>
```

これによって、リモートリポジトリの最新コミットも追加修正が反映された状態になります。リモートリポジトリの書換なので、くれぐれも用法・用量を守ってください。そのブランチが、絶対必ず何があっても間違いなく自分だけが触っている状況なら、やってもいい場合があります（その場合でもリーダーに確認はとってください）
【bat】設定情報を別ファイルに切り分ける

## 概要
DBの接続情報など、動作環境により変わる設定情報は、本体のbatと切り分けて管理し、実行時に読み込んで処理を続行できます。その方法を記載します。

| 項目               | 内容                                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------- |
| **取り扱う内容**   | • PostgreSQLの接続情報を題材に、別ファイルで設定情報を保持・読み込んで使う方法               |
| **解決できること** | • 設定情報を処理部に書かないことで、複数のbatから使いまわしが効く。Git差分管理上もラクになる |

### ディレクトリ構成
設定情報は`Env.bat`として`Env`フォルダ内に配置しました。処理本体を書いたbatと同じ階層に置いてもよいけれど、batの数が増えてくると埋もれるので、サブフォルダに配置としています。
```text
test/
  ├── task.bat
  ├── env/
  │   └── Env.bat
  └── logs/
```
設定情報を保持するだけなのに拡張子を`txt`ではなく`bat`としているのは、その方が変数へのセットが楽であるため。（txtからの読み込みだと、for文でループを回して変数へセットする手間が増える）

### 設定値を保持するbat（`Env.bat`）
設定値はダミーなので、実際の値に置き換えてください。今回はPostgreSQLの設定情報を保持する事例としていますが、とにかく実行環境により変更があり得る情報をここに集約すればOK。ポイントは、DB_PASSWORDの値にキャレット（`^`）で行っているエスケープ。特殊文字はこうやってエスケープしないと、不具合のもとになりますね。
```bash
@echo off
:: PostgreSQL settings
set PSQL_PATH=D:\Postgres15\bin
set DB_HOST=localhost
set DB_PORT=5432
set DB_NAME=testdb
set DB_USER=testuser
set DB_PASSWORD=sw^.^!^)v9^~7fNJJ^-v^!u^!wEB^(hB
set DB_ENCODING=encoding 'UTF8'
```

### 処理部を定義するbat（`task.bat`）
今回はPostgreSQLのfunctionを実行する例を記載すします。「環境設定ファイルの読み込み」のところで、先に定義した設定ファイルを読み込んでいます。処理実行時は、この`task.bat`をダブルクリック or タスクスケジューラから実行すればよいです。
```bash
@echo off
:: カレントディレクトリの設定
set cur_dir=%~dp0
:: ログディレクトリの設定
set log_dir=%cur_dir%logs

:: 環境設定ファイルの読み込み
if exist "%cur_dir%Env\Env.bat" (
    call "%cur_dir%Env\Env.bat"
) else (
    echo Error: Environment file not found at %cur_dir%Env\Env.bat
    exit /b 1
)

:: logsディレクトリの存在確認と作成
if not exist "%log_dir%" (
    mkdir "%log_dir%"
    echo Created logs directory: %log_dir% 
)

:: ログファイルパスの設定
set systemlog=%log_dir%\%date:~0,4%%date:~5,2%%date:~8,2%.system.log
set errorlog=%log_dir%\%date:~0,4%%date:~5,2%%date:~8,2%.error.log

:: ログヘッダーの記録
echo ========================================== >> %systemlog%
echo Start task_scheduler %date% %time% >> %systemlog%

:: 環境設定値のログ出力（デバッグ用なので本番環境では消す）
echo [Environment Variables] >> %systemlog%
echo   PSQL_PATH: %PSQL_PATH% >> %systemlog%
echo   DB_HOST: %DB_HOST% >> %systemlog%
echo   DB_PORT: %DB_PORT% >> %systemlog%
echo   DB_NAME: %DB_NAME% >> %systemlog%
echo   DB_USER: %DB_USER% >> %systemlog%
echo   DB_PASSWORD: %DB_PASSWORD% >> %systemlog%
echo   DB_ENCODING: %DB_ENCODING% >> %systemlog%

:: ログヘッダーの記録
echo ========================================== >> %systemlog%
echo Start task_scheduler %date% %time% >> %systemlog%

:: PostgreSQLパスの設定
set PATH=%PSQL_PATH%;%PATH%

:: PostgreSQL環境変数の設定
set PGPASSWORD=%DB_PASSWORD%

:: public.f_task()の実行
echo Start public.f_task() %date% %time% >> %systemlog%
:: 詳細なログ出力を有効化
psql -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -d %DB_NAME% -c "SELECT public.f_task()" 2>> %errorlog% 1>> %systemlog%
if errorlevel 1 (
    echo Error occurred during public.f_task() execution %date% %time% >> %errorlog%
)
echo End public.f_task() %date% %time% >> %systemlog%

echo End task_scheduler %date% %time% >> %systemlog%
```
yolo(ptファイル)をcoreMLに変換してもラベルが追加されない場合や検知しない場合について

## 原因
YOLOの学習の結果では分類・枠線表示などが出来ているが、coreMLの変換はできるが上手くモデルが働いてくれない人向けです。

### まずはxcodeなどでcoreMLを除いてclass labelsが設定されているか確認しよう
 ![スクリーンショット 2024-12-18 6.25.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3875272/bfd04cb3-4f98-aa7b-5b0a-f8ac9994d576.png)



## 対処法
### nms = True を付けよう 以上
```
model.export(format='coreml', nms=True)
```

変換するコードの全文
```
from ultralytics import YOLO
model = YOLO("your_model.pt") 
model.export(format='coreml', nms=True)
```
BTP ABAP EnvironmentをBASから利用するときの、意外な落とし穴

## はじめに
この記事は [SAP Advent Calendar 2024](https://adventar.org/calendars/10423) の12月7日分の記事として執筆しています。

**BTP ABAP Environment**とは、BTP上でABAP開発ができる環境です。トライアルアカウントでも使うことができます。BTP ABAP Environmentのトライアル環境で開発したODataサービスをBASから利用してアプリケーションを作る際、意外なつまづきがあったので共有します。

## 事象
BTP ABAP Environmentを使う場合、BASの認証はDefault Identity Providerを使う必要があります。IAS認証では、ODataサービスにアクセスできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9174e1f6-4a88-1812-d26c-87a0c74faf13.png)

IAS認証の場合、ABAP環境への認証が失敗する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/bfcc3a2c-0dd6-ec67-f8bc-5c4e408ff8c3.png)

Default Idenity Providerで認証の場合、サービスが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3fbb5c27-7386-4df4-0fe1-ee8b39147a48.png)

## 背景
BASで接続先システムにBTP ABAP Environmentを選択したとき、自動で`abap-cloud-default_abap-trial*`というDestinationが登録されます。このDestinationの認証タイプは**OAuth2UserTokenExchange**となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b8391d34-d8e2-6bbf-950b-a8867e5b2849.png)

これはBASにログインする際に使用したトークンが、XSUAAサービスによってBTP ABAP Environmentのトークンと交換されるということを意味しています（参考：[OAuth User Token Exchange Authentication](https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-user-token-exchange-authentication)）。IASで認証した場合、トークンの交換がうまくいっていないのではないかと推測します。

## 解決策
認証タイプ`OAuth2Password`のDestinationを使うと、IAS認証でも問題なく接続ができました。User、PasswordにはCloud Foundryログイン用の認証情報を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/7d968e0f-7c57-789a-9481-4f38bab82549.png)

でもこれって個人で使うにはいいけれど、業務ユーザが使うアプリケーションの場合はどうするのだろう…🤔
ルーティングなしSPAであっても素のReactでなくNext.jsやReact-Router v7(Remix)を使うべき理由

# この記事は何か？


React公式のこのページの内容を読んだメモです
https://ja.react.dev/learn/start-a-new-react-project


# 公式ドキュメントに書かれている見解


<b>ルーティングのないSPAであってもフレームワーク (Next.jsやRemixなど) を使うべき</b>
という見解が示されています


> React をフレームワークなしで使うことも確かに可能です。既存のページに React を追加する場合はそのようにします。しかし、新しいアプリやサイトをフルで React を使って構築する場合は、フレームワークを使用することをお勧めします。


SSRやSSG、pre-renderingをやろうと思ったら、あるいはSPAであってもルーティングをやろうと思ったらNext.jsやRemix、React Routerなどを選択するのが一般的だと思います。ですが、ルーティングなしのSPAであってもフレームワークを使うべきとしているのは何故でしょうか


# 理由


- 最初はルーティングやデータ取得が必要なくても、後になって必要になるケースがあるし、それをライブラリで追加してくとJavascriptバンドルが大きくなって煩雑になるし、後からフレームワークを適用するのも大変な労力が必要になる
- 当初はデータ取得の規模が小さい間は良くても、データ取得の要件が複雑になっていくと対応できなくなりアプリが非常に遅く感じられるようになる
- ネットワーク環境が悪いユーザーや端末スペックが低いユーザーが増えると後からサーバーサイドレンダリングが必要になるケースがある
- アプリが成長すると「アプリに必要な最小限のコードを 1 回のクライアント・サーバ間の往復で送信しつつ、並行してページ表示に必要なデータも送信したい」「ページが段階的に読み込まれ、JavaScript コードが実行すらされないうちから操作可能になるプログレッシブ・エンハンスメントのサポートが欲しい」「どこにでもホストでき JavaScript が無効になっていても動作する、マーケティングページのための完全に静的な HTML ファイルが入ったフォルダを生成したい」などというニーズが出てきてしまう
- 紹介されているReactフレームワークを使えばこれらの問題をデフォルトで解決している


# 結論


まとめると以下となりそうです
<b>最初は要らなくてもアプリが成長したらほしくなるんだから最初からつかっとけ</b>


# 感想


言われてみると確かにその通りなんだけど、覚えること多くて大変すぎんかフロントエンド
アプリが成長してから苦労するよりマシと言われたら完全同意


しょうもないメモを読んでくれてありがとね
【bat】配置したフォルダ以下のディレクトリ構成を文字列で表現する

## 概要
batを実行したら、配置フォルダ以下の階層を参照して、こういうやつ↓を出力するbatファイルの作り方。
```cmd
folder/
├── subfolder1/
│   ├── test.md
│   └── test2.txt
└── subfolder2/
    ├── sample.exe
    └── something.dll
```

## コード
bat名は任意で付与してよいです。bat自身の名称は出力しないようになっています。
```bash
@echo off
setlocal enabledelayedexpansion

rem バッチファイルの名前を取得
set "batch_name=%~nx0"

rem ルートフォルダ名を取得
for %%I in ("%CD%") do set "root_folder_name=%%~nxI"

echo ディレクトリ構造: %CD%
echo 現在のフォルダ名: %root_folder_name%
echo 作成日時: %date% %time%
echo.

rem ルートディレクトリ名を表示
echo %root_folder_name%/
rem インデントの初期化
set "indent=  "
call :treeProcess

echo.
echo 処理が完了しました。何かキーを押すと終了します。
pause >nul
goto :eof

rem ディレクトリ構造を再帰的に処理する関数
:treeProcess
set "last="
rem 最後のフォルダ or ファイルに当たるまでlast変数を上書きし続けて、最後のフォルダ or ファイルを取得
rem lastに値をセットするためだけのforループ
rem カレントディレクトリの階層のみ対象。サブディレクトリの中身までは、この時点では見ない
for /F "tokens=*" %%G in ('dir /B /A ^| findstr /v /i /x "%batch_name%"') do set "last=%%G"

rem カレントディレクトリの全フォルダ、ファイルに対して処理を行うforループ
for /F "tokens=*" %%G in ('dir /B /A ^| findstr /v /i /x "%batch_name%"') do (
    rem 今回ループで処理しているものが、最後のフォルダ/ファイルに当たるなら"└──"、それ以外は"├──"のプレフィックスを付与
    if "%%G"=="%last%" (
        set "prefix=└── "
        set "childIndent=    "
    ) else (
        set "prefix=├── "
        rem 上の階層を表現するための縦線記号つきインデント
        set "childIndent=│   "
    )
    rem 今回ループで処理しているものが、フォルダであるか判定（existsで、配下に何かあればフォルダと判定）
    if exist "%%G\*" (
        rem フォルダなら、プレフィックスとフォルダ名、スラッシュ記号を表示
        echo !indent!!prefix!%%G/
        rem フォルダ内に移動して、再帰的に同じ処理を行う
        pushd "%%G"
        rem インデントを長くして深い階層を表現
        set "indent=!indent!!childIndent!"
        rem 再帰処理
        call :treeProcess
        rem フォルダ内の処理が終わったら、元の階層に戻る
        popd
        rem インデントを短くする
        set "indent=!indent:~0,-4!"
    ) else (
        rem フォルダでないなら、素直にプレフィックスとファイル名を表示
        echo !indent!!prefix!%%G
    )
)
exit /b

:eof
endlocal
```

## 実行結果例
bat実行時のコマンドプロンプトに、以下表示されます。もちろん手を加えれば別ファイルに書き込むことも可能なはず。
```text
ディレクトリ構造: D:\dev\test\GUI_Tool\Tool\database
現在のフォルダ名: database
作成日時: 2024/12/18  6:14:37.28

database/
  ├── export_tools/
  │   ├── conf/
  │   │   └── Env.bat
  │   └── Export.bat
  ├── insert_tools/
  │   ├── conf/
  │   │   └── Env.bat
  │   ├── Insert.bat
  │   └── sql/
  │       ├── create_index/
  │       │   ├── index1.sql
  │       │   └── index2.sql
  │       └── drop_create_table/
  │           ├── table1.sql
  │           └── table2.sql
  └── docs/
      └── document.md
```
xcodeにて初回のボタンの反応(判定)が悪い場合について 

## 原因と対処法
xcodeのログで下の警告が発生している場合の解決方法です。

```
Failed to create 0x88 image slot (alpha=1 wide=1) (client=0xc49b7112) [0x5 (os/kern) failure]" in tap to button
```

原因としては、ナビゲーションバーとボタンの位置が重なっているため発生していました。
よってナビゲーションバーを非表示にする必要があるため、非表示にする下のコードを使う。

```
self.navigationController?.setNavigationBarHidden(true, animated: false)
```

画面関係である viewDidLoad・viewDidLayoutSubviews　などに付け足したらいいと思います。


## viewDidLoadやviewDidLayoutSubviewsなどの実行される順番や回数などについて
一度だけ実行されるやつ・画面遷移した際に実行されるやつ など色々あるため見る価値あり
[https://qiita.com/reo0612/items/1dc1a18a385622118bbb](https://qiita.com/reo0612/items/1dc1a18a385622118bbb)
LLMの「存在しません」という断言について


LLMで調べものをしていると、「〇〇は存在しません」と答えられることがあるが、一般にAが存在しないことを証明するのは難しいので、「私の知ってる限り」を前置きにするか、いや、それでも、日本語としておかしいので、「Aについては知りません」と答えるべきである。
LLMの知識データベースに載ってないだけの話ではないか。

インターネットを全て当たることが可能であるとしても、ネットと切り離された世界にAは存在するかも知れないし、どんな検索エンジンでも、インターネット全てを当たることは現時点では不可能である。「存在しない」ことを断言する場合は、理論的に確実な場合や、本当にユニークなもので、過去に存在し、今この世にないものを「存在しない」と言ってほしい。後者の場合、「存在しない」だけでは物足りないので、情報のある限り、「過去にはAが存在し、Bでした」と言ってほしい。

LLMは情報のないことは素直に「私は知りません」というべきである。
Amazon Redshiftのよくあるコスト最適化ポイント

## はじめに

みなさん、こんにちは。グローバルでは単なるクラウドの活用から先に進み、クラウドのビジネス価値を最大化するための取り組みである「FinOps」の実践が当たり前になりつつあります。

もちろんFinOpsの目指すべきゴールは、正しくはコスト削減ではないものの、今回はあえて削減の部分にフォーカス当てて紹介していきたいと思います。

## よくあるコスト最適化のポイント

まず前段として、クラウドにおける一般的なコスト最適化のポイントとしては以下のような項目が挙げられます。

- コンピューティングの適正化
- 未使用リソースの棚卸
- 料金プランの適正化
- ストレージ/ネットワークの適正化
- ライセンスの適正化、など

もちろんこれらの項目はRedshiftにも当てはまってくる部分があります。今回はこちらに沿ってRedshiftの最適化ポイントを紹介していきたいと思います。

![](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_4.jpg)

## コンピューティングの適正化

### 過剰なサイジングの見直し

机上でサイジングした結果をもとにインスタンスファミリーやサイズを選択し、そのまま使い続けているといったケースも少なからずあると思います。しかし、机上のサイジングでは安全係数をかけていることが多く、実際に必要なサイズよりも過剰になっていることが多いです。

そのため、CPU使用率、読み取りおよび書き取りIOPSなどのメトリクスをもとに、過剰なサイジングになっていないかを定期的に見直し、必要に応じてスケールイン/スケールダウンを行うことで過剰なリソース分に支払っている料金を節約できる可能性があります。

とくにPoC/開発環境などの場合は、性能試験のときに一時的にスケールアウト/スケールアップすればいいだけのことも多いため、定常的に用意しておくべきスペックになっているのか、改めて見直してみてください。

### 過剰な冗長構成の見直し

高可用性の必要ないPoC/開発環境などでマルチAZ構成を組んでいるリソースは、過剰な冗長構成となっている可能性があります。過剰な冗長構成を適正化し、シングルAZ構成かつシングルインスタンスにすることでコストを節約することができます。

とくにPoC/開発環境などの場合は、試験のときに一時的にマルチインスタンス、マルチAZにすればいいだけのことも多いため、定常的に冗長構成にしておかなければいけない構成なのか、改めて見直してみてください。

## 未使用リソースの棚卸

### アイドル状態のクラスターの棚卸

DB接続が長期間にわたって確立されていない状態（アイドル状態）のクラスターは、未使用リソースの可能性があるため、削除もしくはスケールイン/スケールダウンすることによってコストを削減できる可能性があります。

また、定常的にアクセスが少ないということであれば料金プランの変更を行うことでコストを削減できる可能性があります。詳細は「[Redshift Serverlessの活用](#redshift-serverlessの活用)」を参照ください。

### 不要な手動スナップショットの棚卸

取得してから長期間経過かつ保持期間を設定していない手動スナップショットについては、すでに不要となっていないかを確認し、不要であれば削除することによってコストを削減できる可能性があります。

## 料金プランの適正化

### リザーブドインスタンスの適用

24時間365日の稼働ではなくとも長時間稼働するリソースは、リザーブドインスタンス（RI）を適用することによってオンデマンド料金よりもコストを削減できる可能性があります。

RI購入によるコスト最適化の機会の気づきとして、AWS Billing and Cost ManagementのRIレコメンデーション機能が活用できます。稼働統計データを基にRI購入に関するレコメンデーションが提供された場合は、詳細調査を行った上でRIを追加購入できないか検討してみてください。​

https://docs.aws.amazon.com/ja_jp/cost-management/latest/userguide/ri-recommendations.html

### Redshift Serverlessの活用

定常的にアクセスが発生するようなユースケースではなく、ごくごくまれにアクセスが発生するといったようなケースでは、常にノードに料金を払いつづけるのではなく、サーバーレスにしてしまった方がコストを低減できる可能性があります。

## スケーリングの調整

### 未使用の時間帯はクラスターを自動停止

PoC/開発環境などの平日日中の業務時間帯のみに稼働するリソースは、スケジュールにあわせて確実にリソースの停止を実行することでリザーブドインスタンスを適用するよりもコストを抑えられる可能性があります。

https://aws.amazon.com/jp/blogs/news/lower-your-costs-with-the-new-pause-and-resume-actions-on-amazon-redshift/

## ストレージ/ネットワークの適正化

### ストレージサービスの見直し

一定期間を過ぎた古いデータのように常には使わないけどごくごくまれに参照するようなデータについては、マネージドストレージに保存しておくのではなく、より料金の安いS3へParquet形式で保存しておき、必要に応じてRedshift Spectrumを使って分析するといった形にした方がコストを抑えられる可能性があります。

## 最後に

もちろん今回紹介したもの以外にも最適化ポイントはあります。とはいえ、まずは今回紹介したような、よくある最適化ポイントから始めてみるのが良いのかなと思っています。

なお、一点注意していただきたいのですが、コスト削減に注力するがあまり、パフォーマンスを損なってしまうようでは本末転倒です。修正を加える際は、実際の環境への影響をしっかりと調査を行った上で実行するとともに仮に悪影響が出てしまった際には、すぐ切り戻せるようにしておくことも重要であることをご認識いただければと思います。

以上、Amazon Redshiftのよくあるコスト最適化ポイントのご紹介でした。今回の内容は基本的に使い古された情報ですが新たな気づきがひとつでもあったなら幸いです。

---

- AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
- その他、本資料に記述してある会社名、製品名は、各社の登録商品または商標です。
JSONとは

## はじめに
JSONとは「JavaScript Object Notation」の略で、「JavaScriptのオブジェクトの書き方を元にしたデータ定義方法」のことです。
軽量かつ柔軟なデータ交換フォーマットとして、現代の開発現場で広く利用されています。
本記事ではJSONの構造や特徴を含めてまとめてみました。

## JSONとは？

### 定義と特徴
JSON（JavaScript Object Notation） は、構造化データをテキスト形式で表現するフォーマットです。
主に以下の特徴を持ちます。

- 人間にも機械にも読みやすい
- 軽量でシンプルな構文
- プログラミング言語に依存しないため、多言語間でのデータ交換が可能

### 利用シーン
- Web APIでのデータ送受信
- 設定ファイル（例：package.json）
- 簡易データベースとしての利用

## JSONの基本構造
### データ型
JSONは以下の6つのデータ型をサポートします。

#### オブジェクト（{}）
キーと値のペアの集合。
```json:json
{
  "name": "John",
  "age": 30
}
```

#### 配列（[]）
値のリスト。
```json:json
["apple", "banana", "cherry"]
```
#### 文字列（""）
ダブルクオートで囲まれたテキスト。

#### 数値
整数および浮動小数点数。

#### 真偽値
true または false。

#### null
空の値。

### ネスト構造
JSONはネスト構造を持つことができます。
```json:json
{
  "user": {
    "name": "Alice",
    "details": {
      "age": 25,
      "hobbies": ["reading", "traveling"]
    }
  }
}
```

## JSONの使い方

### データ交換
JSONはWeb APIでリクエストやレスポンスのデータ形式として広く利用されます。

リクエスト：
```json:json
{
  "action": "login",
  "username": "user123",
  "password": "securePassword"
}
```
レスポンス：
```json:json
{
  "status": "success",
  "userId": 98765
}
```

### 設定ファイル
JSONは設定ファイル形式としても使われます。

例：package.json
```json:package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.17.1"
  }
}
```

### データ保存

小規模なデータベースの代わりとしてJSONファイルを利用するケースもあります。

## JSONの注意点

ダブルクオートやバックスラッシュを含む場合、エスケープが必要。
```json:json
{
  "text": "He said, \"Hello!\""
}
```

## 終わりに
読んでいただきありがとうございました！
マイクロソフトのブラウザ Edge の Workspace機能の便利さを試してみた

## はじめに

オンラインでリサーチや学習をしているとブラウザタブが無数に出来てしまい、管理が大変でした。便利なサイトを定期的に利用したいのですが、タブ管理が煩雑になると、タブを消してしまい、URL等を失念してしまうことがあります。

これを解消するために、マイクロソフトのブラウザ 「Edge」のワークスペース機能を試してみました。

簡単に、フォーカス出来るワークスペースが作れ、関連サイトをグループ化でき、自動的に立ち上がるので、Youtubeやオンライン講座を駆使して勉強している方には最適かと思います。

環境はWindows 11で最新のCPU (Core i7) 以上やメモリも16G以上程度と想定しています。

### Microsoft Edge
https://www.microsoft.com/ja-jp/edge/download?form=MA13FJ

GoogleのChromeエンジンをもとに作っているので、レンダリング等はChromeと同じです。インターフェイス部分だけ違います。

### Workspaceとは

関連するサイトを専用のウィンドウに分割でき、タブのページはリアルタイムで自動的に保存および更新されるため、複数サイトを立ち上げ、情報を閲覧している場合に役に立ちます。仕事、勉強、趣味、ブログ等のワークスペースが作成でき、専用のウィンドウで関連サイトを閲覧できます。

https://www.microsoft.com/ja-jp/edge/features/productivity?form=MA13GQ

## 作成方法

Edgeブラウザを立ち上げると以下のようなアイコンが表示されているので、クリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/7eb66cba-2b5f-1c8f-22f9-1d78d0546655.png)

そうすると、以下のようなプルダウンメニューが表示されるので、プラスサインをクリックして作成します。私の環境は既に授業のクラス名やプログラミング言語をワークスペースとして登録しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/e35a2ee7-d14c-a6c2-4f06-dd301942e8af.png)

ワークスペースの作成が完了すると、各サイトのタブを右クリックして、Move Tab to を選択し、ワークスペースを選択し、サイトをワークペースに登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/dbd2a541-36ae-dd0b-c05f-70fd1e124164.png)

ワークスペースの登録が終われば、アクセスしてみましょう。ここでは、Pythonのワークスペースを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/40f4cacc-f768-e1d1-35b9-cc212a8ff489.png)

以下のように登録済みのサイトが自動的に再表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/5a420354-c211-0675-3daa-f4c59e5e4faa.png)

## 終わりに

簡単な設定ですが、飛躍的に生産性が上がったように思えます。サイトURLの管理は別途しなければならないですが、フォーカスしたいオンラインサイトの立ち上げが自動になりとても便利です。

今回は以上になります。Happy Hacking!
mixi2は何の技術で作られてる？（Flutter製？）&初め方 &何これ？


まず疑問に浮かぶのが「テックスタックはなんぞ」かなと。

少し調べてみると興味深い言及もあったので紹介させて頂きます。

https://x.com/rdlabo/status/1868562359633219832

React NativeじゃなくてFlutterなんじゃないかとのことですが、どうなのでしょうね……？

mixi2はいまはアプリのみで、ウェブには対応していません。技術スタックによってはウェブ版に掛かる手間や実装の冗長性も変わるでしょうから、うーん。

## 始め方

mixi2は現状のところ完全招待制です。

Twitterで調べればいくらでも招待コードは出てきますが、期限が切れてたりユーザーがBANされてたりすると使えません。「誰のでもいい」という方はTwitterで調べるのをおすすめします。

私の個人アカウントからの招待を希望でしたらお気軽にどうぞ。気づいたらフォロバします。

https://mixi.social/invitations/@indoorkitsune/4KCE7FrkqruKiVg3rRqSTN

アプリは初めにインストールして、その後に招待URLを開きます。

> 「ページが見つかりませんでした」みたいに出たら期限切れになってます。
> アプリをインストールしてから、ChromeやSafariで上のURLを踏んで開くと、使えるようになります。

https://nonsense.buzz/shou/post/676136d584bbabc7cb3f1788?qt

## mixi2ってなんだ

mixi2をdiscordみたいって形容される方もいたり、blueskyとMisskeyを割ったような、と形容する方もおられたり、みたいです。

私は最初mixi2の投稿UIコンポーネントを見て、「Misskeyやん…」と思ってしまいました。
一部インスタンスのMastodonっぽさもあるのかもしれません。

現状、twitterの代替となり得たblueskyはイラストレーターさん達とファンの人達が多く占めている印象を受けています。

唐突すぎるmixi2の台頭。

今後のSNS市場、どうなっていくんでしょうか……
Javaで「パターンにマッチした文字列を置換する」の動作を確認してみた

# 概要

Javaで「パターンにマッチした文字列を置換する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/regex/index27.html

# 実装

以下のファイルを作成しました。
```JSample27_1.java
import java.util.regex.*;

class JSample27_1{
  public static void main(String[] args){
    String target = "DD AA CC BB EE";
    System.out.println(target);

    String regex = "AA|BB";
    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher(target);
    System.out.println(m.replaceFirst("FF"));
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample27_1.java 
$ java JSample27_1 
DD AA CC BB EE
DD FF CC BB EE
```

以下のファイルを作成しました。
```JSample27_2.java
import java.util.regex.*;

class JSample27_2{
  public static void main(String[] args){
    String target = "DD AA CC BB EE";
    System.out.println(target);

    String regex = "AA|BB";
    Pattern p = Pattern.compile(regex);

    Matcher m = p.matcher(target);
    System.out.println(m.replaceAll("FF"));
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample27_2.java 
$ java JSample27_2
DD AA CC BB EE
DD FF CC FF EE
```

# まとめ

何かの役に立てばと。
【ツール#2】RACS2 (ROS2 and cFS System)

[Advent Calendar 2024の企画として、Space ROS (Robot Operating System)について集中的に解説/紹介](https://qiita.com/advent-calendar/2024/space-ros)していきます。今日は関係する周辺プロジェクト（ツール）の１つということでRACS2 (ROS 2 and cFS System)についてです。

# RACS2 (ROS 2 and cFS System) とはなんですか？
[RACS2](https://drive.google.com/file/d/1VBsiUEW6Z8pG8LvbM7lEyZMRMz9w-sjX/view)とは、**JAXAが開発したROS 2 と cFS (Core Flight System)をつなぐツールで、GitHubで公開**されています：

https://github.com/jaxa/racs2_bridge 

[ROS 2](https://docs.ros.org/en/jazzy/index.html)はご存知のROS 2で、cFSは別記事で紹介されている通り、NASAが開発した宇宙コミュニティで先行して使われてきていたROSのPlumbing（接着）分の機能を有するミドルウェアであり、宇宙分野でのソフトウェアのモジュラー化、再利用を促すために作られました。

https://qiita.com/ttsto/items/bea14d8820544a2d42b7

つまり、平たく言うと、**RACS2とは、類似のPlumbing（接着）の機能を持つROS 2とcFSを接続し、宇宙でもROS 2が使えるようにするツール**となります。ROS 2が地上のロボティクスの分野のデファクトスタンダードではあるものの、さすがにROS 2をそのまま宇宙に飛ばすには安全性信頼性の観点で心配です。そのため、**宇宙分野で支持を得ていて高信頼性を誇るcFSと、ROS 2をくっつけて、宇宙でもロボット化を進めることがその目的**となります。

## RACS2 bridge

### RACS2 bridgeを用いたソフトウェアシステムのアーキテクチャ

以下にあるように**RACS2 bridgeはcFSとROS 2をアプリケーション層でブリッジする機能を有しています** *1。これにより、cFSのユーザアプリケーションとROS 2のユーザアプリケーションのトピック/メッセージのやり取りができるため、ROS 2ユーザはcFSのアプリケーションを使用することができるし、同様にcFSユーザがROS 2のライブラリやツールにもアクセスができるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517365/e5ea3131-30e3-78c8-89cd-f493f7f4a070.png) 

### RACS2 bridgeのソフトウェア要求仕様

[ここ](https://roscon.jp/presentations/05.pdf)のPage28以降にソフトウェア要求仕様の記載があります *2。 かなリ内容が細かいので詳細は割愛しますが、思想としては、**cFSとROS2のどちらのユーザにとってももともとのソフトウェアをRACS2専用に改変することなく再利用できる**ようになっていると読めます。また、現状は**計算機（ホスト）ごとにROS 2およびcFSと分離するトポロジーも、１つの計算機に共存できるトポロジーも対応可能**となっていますが、ROS 2を投入しようとするような（従来の宇宙アプリケーションの中では）比較的ソフトウェアヘビーなプロジェクトでの使用になってくると思うため、ROS 2およびcFSは計算機ごとに分離されるスキームが優勢になっていくと考えられます。

### Space ROSとRACS2 bridge

[RACS2 bridgeとSpace ROSのアーキテクチャの比較は以下](https://drive.google.com/file/d/1VBsiUEW6Z8pG8LvbM7lEyZMRMz9w-sjX/view) の通りです *1。**Space ROSは基本的にはROS 2を宇宙向けにする思想に対し、RACS2はROS 2を宇宙へ飛ばすのに既存のcFSと連携し、プログラム自体は最小限**に抑えられています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517365/30201e01-ecf7-6025-bdb4-b28a0edf7a99.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517365/15c691cc-5e5a-2602-eb3b-61dc1da07f39.png)

ROS 2がまるまる宇宙仕様化したSpace ROSが使えるのは世界観としては当然ど真ん中の目標になると思いますが、いずれにせよROS 2プロジェクトをまるまる宇宙化するのはそれなりの時間がかかるし、しかも維持を続けるのはそれなりの労力になっていくと考えられます。したがって、**少なくとも当面はRACS2のようにcFSも活用しながらROS 2を宇宙に打ち上げるという世界観は自然の流れ**だと考えられ、[RACS2がSpace ROSに取り込まれようとする動きが進んでいます →12/18現在。更新します。 ](https://github.com/space-ros/docker/pull/205)。

## RACS2 extended-DDS
RACS2 bridgeの他にRACS2 extended-DDSが準備されています。こちらもGithubに公開済です。

https://github.com/jaxa/racs2_extended-dds

[アーキテクチャは以下](https://drive.google.com/file/d/1VBsiUEW6Z8pG8LvbM7lEyZMRMz9w-sjX/view) の通りで直接ROS 2が使用しているDDS層でcFSも含めて通信を行うスキームです *1。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517365/5a5fad41-1ccf-e71f-7a9f-c844b5feb474.png)



*1 [H. Kato and T. Saito. “RACS2: the ROS2 and cFS System, launched” Flight Software Workshop 2023 in March 2023](https://drive.google.com/file/d/1VBsiUEW6Z8pG8LvbM7lEyZMRMz9w-sjX/view) 

*2 [池田 他, JAXAにおける宇宙機開発へのROS活用とSpace ROS開発, ROSConJP2024](https://roscon.jp/presentations/05.pdf)
[SwiftUI] View Identityの変化を視覚的にわかるようにするmodifier

# 背景

SwiftUIのViewはView Identityと呼ばれる識別子によって管理されています。このView Identityが変化すると完全に別のViewであると判断されるため、再描画コストがかかり、内部に持つ状態（`@State`）が初期化され、アニメーションなども期待通り動作しなくなります。

以上から、意図しないView Identityの変化はバグを生むため、避けなければいけません。

参考

https://zenn.dev/kntk/articles/1f1b40da6fe181

https://zenn.dev/kntk/articles/4e3538f402d171

# 本題

基本的にはコードからView Identityが変化する可能性に気付いて修正するのが理想ですが、既存のViewを調査する場合にコードを全て読み解いてバグの有無を判断するのはめんどくさい場合もあります。そんな場合に役立つmodifier。

```swift
private struct HighlightViewIdentityChanged: ViewModifier {
    @State private var loaded = false

    func body(content: Content) -> some View {
        content
            .overlay {
                if !loaded {
                    Color.yellow.opacity(0.5)
                }
            }
            .onAppear {
                withAnimation {
                    loaded = true
                }
            }
    }
}

public extension View {
    func _highlightViewIdentityChanged() -> some View {
        modifier(HighlightViewIdentityChanged())
    }
}
```

View Identityが変わるとStateが初期化される挙動を利用して、View Identityが変わった（生成された）瞬間Viewを黄色にハイライトする、というアプローチ。

## 使い方例

ViewIdentityが意図せず変わっている疑惑があるView（if, switchの内側のView）や、変わると困るView（描画コストが高いListとか、状態を内部に持ったView）に対して`._highlightViewIdentityChanged()`を付けてアプリをデバッグしてみる。

基本的にはmodifierの中で最も内側につけるのを推奨。

```swift
struct ContentView: View {
    @State var condition = false

    var body: some View {
        List {
            Text("Hello")

            Button("toggle") {
                condition.toggle()
            }
        }
        ._highlightViewIdentityChanged()
        .if(condition) {
            $0.foregroundStyle(.blue)
        }
    }
}

extension View {
    @ViewBuilder
    func `if`<Content: View>(
        _ condition: Bool,
        @ViewBuilder transform: (Self) -> Content
    ) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}
```

ListのView Identityが変わっていることが視覚的にわかる。

![Simulator Screen Recording - iPhone 16 Pro - 2024-12-18 at 02.31.13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388166/6e6eb5ba-aba0-30dd-27e4-8531c77fdae2.gif)


なお、このmodifierは付けた一点のView Identityの変化のみ検知する。つまり付けたViewの子ViewのView Identityだけが変化していても検知しない。

例えば`Text("Hello")`のView Identityのみ変わるケースも検知したい場合はまた別の`._highlightViewIdentityChanged()`をつける必要がある。

```swift
struct ContentView: View {
    @State var condition = false

    var body: some View {
        VStack {
            Text("Hello")
                ._highlightViewIdentityChanged()
                .if(condition) {
                    $0.foregroundStyle(.blue)
                }

            Button("toggle") {
                condition.toggle()
            }
        }
        // これはText("Hello")のView Identity変化を検知しない
        ._highlightViewIdentityChanged()
    }
}
大量データをDynamodbのBatchWriterで書き込んでも3時間程かかった

大量のデータをDynamoDBに書き込む際、PutItemでは日が暮れてしまう。
そんな時にBatchWriterを使用して書き込みたいところ。
ただ、先日BatchWriterで100万〜200万件のデータを書き込む必要があって、
業務端末上のスクリプトで実行したところ、ありえない時間がかかった。

## 弊スペック
- インターネット回線
  - 種別：CATV
  - 下り：120MB(理論値)
  - 下り：5MB(理論値)
- 業務端末
  - CPU：Apple M1 コア8
  - Memory：16GB
  - OS：macOS Monterey

## 結論
170万件のデータを20万件毎に分割し、20万件毎にBatchWriterで書き込んだところ、
3時間強かかった。
BatchWriterはPutItem、DeleteItemが対象であり、それ以外はBatchWriterで
扱う事ができない

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html

`BatchWriteItem cannot update items. If you perform a BatchWriteItem operation on an existing item, that item's values will be overwritten by the operation and it will appear like it was updated. To update items, we recommend you use the UpdateItem action.`
上記引用では、BatchWriteItemのAPIに触れているが、BatchWriterはBatchWriteItemをWrapして使用しているので、同じと考えて差し障りない。

## サンプルコード
ダミーCSV
```csv:data.csv
user_id,date,segment,total_buys
1,2024-12-18,high,80
2,2024-12-18,low,12
3,2024-12-18,middle,67
4,2024-12-18,middle,35
5,2024-12-18,middle,45
6,2024-12-18,low,10
7,2024-12-18,high,85
8,2024-12-18,middle,30
9,2024-12-18,low,5
10,2024-12-18,high,90
11,2024-12-18,middle,50
12,2024-12-18,low,15
13,2024-12-18,high,95
14,2024-12-18,middle,40
15,2024-12-18,low,18
16,2024-12-18,high,100
17,2024-12-18,middle,60
18,2024-12-18,low,8
19,2024-12-18,high,88
20,2024-12-18,middle,70
```
ダミーsample.py
※実際のコードはこのようになっておりません。
```python:sample.py
import boto3
import pandas as pd

dynamodb = boto3.resource('dynamodb')
data = pd.read_csv('data.csv')

user_table = dynamodb.Table('User')
user_buy_history_log_table = dynamodb.Table('UserBuyHistoryLog')

for index, row in data.iterrows():
    with user_buy_history_log_table.batch_writer(
        overwrite_by_pkeys=['user_id', 'date']
    ) as batch:
        # PutItem
        batch.put_item(Item={
            'user_id': int(row['user_id']),
            'date': row['date'],
            'total_buys': int(row['total_buys']),
        })

        # BatchWriterのスコープ内でUpdateItemをやってはいるが...
        user_table.update_item(
            Key={
                'id': int(row['user_id']),
            },
            UpdateExpression='SET #attr = :val',
            ExpressionAttributeNames={
                '#attr': 'segment',
            },
            ExpressionAttributeValues={
                ':val': row['segment'],
            },
        )

```

## スクリプト実行後、どうして時間かかった？
BatchWriterにより1操作で最大25項目の追加または削除操作を含むデータサイズにして、
16MBまで可能との事。
連続したPutItem時よりも低いWCU消費で済むことができ、かつ時間が短縮されると考えていたが、3時間かかるのはおかしい結果となった。

BatchWriterを使用したUserBuyHistoryLogテーブルでは
PutItem使用してバルク処理になってたが、UserテーブルのUpdateItemは1件ずつ処理していた事で
それに引っ張られて本来のBatchWriterの恩恵を受けられなかった。

## 速く終わらせるには、どうすべきか
1. 業務端末でやらない。AWSにEC2やECS/EKSのコンテナ上でバッチ処理実行
※ 設計次第ではLambdaを使用して並列に書き込むのもアリ。
2. BatchWriterからUser更新に使っていたUpdateItemをスコープから外す
3. スレットを導入し、並列に実行させる

## まとめ
BatchWriterはPutItem、DeleteItemが対応しているが、それ以外は対応していない
BatchWriterはBatchWriteItemをWrapしたもの
業務端末で重たい処理は走らせず、AWS上でバッチサーバを置いて処理させるべき
【Python】pandasのDataFrameでgroupbyで合計した結果から上位の件数を指定して値取得

## 概要
pandasのDataFrameで、ある項目でgroupbyした後にその合計値で上位のものを取得する実装をメモ書きします。

## 前提
* 使用したpandasのバージョンは`2.2.3`です。

## 対応方針
* groupbyで合計値を算出します。groupbyの使い方については[Pandas｜groupbyの使い方](https://pyhoo.jp/groupby)の記事が参考になります。
* groupbyで合計値を算出した後に、`nlargest`関数で上位のものを取得します。nlargestの使い方については[pandasでn個の最大値・最小値を取得（nlargest, nsmallest）](https://note.nkmk.me/python-pandas-nlargest-nsmallest/)が参考になります。

## 実装サンプル
以下のサンプルを実行すると、`group1:  B value:  150`、`group1:  A value:  100`が出力されます。

```python
import pandas as pd

# サンプルデータの作成
df = pd.DataFrame(
    {
        "group1": ["A", "A", "B", "B", "C", "A", "D", "B", "E"],
        "group2": ["X", "Y", "X", "Y", "X", "S", "C", "A", "K"],
        "value": [10, 20, 30, 40, 50, 70, 70, 80, 9],
    }
)

# group1でgroupbyして上位2件を取得
grouped = df.groupby("group1")["value"].sum().nlargest(2)

# 対象のgroupとvalueを出力
for i, v in grouped.items():
    print("group1: ", i, "value: ", v)

```
Linuxにおけるユーザ管理

## ユーザの種類
Linuxにおいて、ユーザは`system user`と`normal user`の2種類に分けることができます。

### system user
人間が直接ログインするためのユーザではなく、デーモンプロセスやサービスの実行のために使われるユーザです。
nginxのwoker processを実行する際に慣習的に使われる`www-data`や、mysqldを実行する際に使われる`mysql`などがこれに該当します。

### normal user
人間が対話的に使用する際に使うユーザです。

## カーネルから見たユーザ
ユーザは`www-data`, `mysql`などのユーザ名を持っていますが、カーネルはこのユーザランドで使われているユーザ名を認識していません。
カーネルが認識しているのは、ユーザID(`UID`)です。

この`UID`はユーザの種類によって割り当てられる範囲が決まっています。
割り当ての範囲は、ディストリビューションによって異なります。

例としてsystemdのドキュメントを参照すると、以下のようなUIDの範囲の割り当てになっています。

https://systemd.io/UIDS-GIDS/

- `0`
    - root user
- `1…999`
    - system user
- `1000…65533`, `65536…4294967294`
    - normal user
- `65534`
    - nobody user

カーネルはユーザ名を認識していないため、ユーザランドからカーネルとやりとりする際にはUIDを特定する必要があります。

## /etc/passwd
ユーザ名とUIDを対応づけているファイルが`/etc/passwd`です。
ユーザ名とUIDを1:1で対応づけているのではなく、その他のメタ情報も含まれます。

ファイルの中身は以下のようになっています。
```sh
$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# ...
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
# ...
tsuzuki-takaaki:x:1000:1000:tsuzuki takaaki:/home/tsuzuki-takaaki:/bin/bash
```

各レコードが1ユーザを表しており、1レコードに7つのフィールドが含まれています。
各フィールドは以下を意味します。
```
<username>:<password>:<UID>:<GID>:<real_name>:<home_dir>:<shell>
```
- `username`: ユーザ名
- `password`: パスワード
    - `x`が入っていますが、ここに平文でパスワードが保存されることはほとんどなく、`/etc/shadow`に暗号化されて保存されます。
- `UID`
- `GID`: グループID
- `real_name`: フルネームや連絡先
- `home_dir`: 対象ユーザのホームディレクトリ
- `shell`: シェル
    - loginを許可しない、システムユーザなどは`/usr/sbin/nologin`が指定されます。

## /etc/group
`/etc/passwd`でユーザが管理されている一方で、`/etc/group`では、グループが管理されています。

```sh
$ cat /etc/group
root:x:0:
daemon:x:1:
# ...
sudo:x:27:tsuzuki-takaaki
# ...
```
フィールドが4つ含まれており、フォーマットは以下です。
```
<groupname>:<password>:<GID>:<other_member>
```

新たなユーザを追加するごとに、そのユーザと同名のグループが自動的に追加されます。
仮に`hoge`という名前のユーザを追加すると、デフォルトで`hoge`という名前のグループが作成されて、そのグループに属することになります。

```sh
root@bc9413b0bcf2:/# adduser hoge
info: Adding user `hoge' ...
info: Selecting UID/GID from range 1000 to 59999 ...
info: Adding new group `hoge' (1001) ...
info: Adding new user `hoge' (1001) with group `hoge (1001)' ...
info: Creating home directory `/home/hoge' ...
info: Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for hoge
Enter the new value, or press ENTER for the default
        Full Name []: hoge
        Room Number []: 999
        Work Phone []: 999
        Home Phone []: 999
        Other []: 999
Is the information correct? [Y/n] y

root@bc9413b0bcf2:/# tail -n 1 /etc/passwd
hoge:x:1001:1001:hoge,999,999,999,999:/home/hoge:/bin/bash
root@bc9413b0bcf2:/# tail -n 1 /etc/group
hoge:x:1001:
```

## 参考

https://tatsu-zine.com/books/superuser-linux-system

https://www.oreilly.co.jp/books/9784814400218/

https://ubuntuforums.org/showthread.php?t=1146686
40過ぎたおじさんが、JAWS-UGに参加して

# はじめに
こちらは、https://qiita.com/advent-calendar/2024/jaws-ug 18日目の記事です。
技術的なお話はありません。

https://qiita.com/advent-calendar/2024/jaws-ug

# AWSとの出会い
　私のAWSとの出会いは2019年です。それまでオンプレOnlyだった私が、ふとしたきっかけから新たに立ち上げることになったサービスでAWSに触れ始めました。それまで何か試そうとしても、ハードウェアがないと仮想サーバの立ち上げすらできませんでした。それが、AWSアカウントさえあれば、何でもお試しができるようになり感動したことを今でも覚えています。
　ただ、社内ではAWSで開発をしているプロジェクトはほとんどなく、AWSについて相談できるエンジニアはほとんどいない状態でした。パートナー企業のエンジニアと開発しながら、ドキュメントやWebで記事を見て社内で、独学で勉強する日々でした。

# JAWS-UGを知る
　そんな私が大きな転換を迎えたのはre:Invent2022への参加です。事前Meetupや現地で社外の人とAWSについて話をする機会を得ました。その中で、AWSに関するスキルや知識量、イベントにかける熱量に自分と大きな差があることを痛感しました。自分が頑張ってきたこれまでの中の世界と、外の世界との大きな差を感じて、外の世界を知らなければならないと、危機感を感じたイベントでした。この参加経験がなかったら、今の私はないと断言できます。ですので、この時に予算を捻出してre:Inventへの参加枠を会社として初めて作ってくれた当時の上司には、ただただ感謝しかありません。
　そうして参加したre:Invent中にお話をした方にJAWS-UGのコミュニティ運営をされている方がいて、コミュニティの存在を知りました。なお、最初のre:Inventは消化不良でした。情報不足と準備不足。帰路の飛行機でイベントの熱量に圧倒され、楽しかったと感じる自分と、せっかくラスベガスまで行ったのにもっと色々経験できたと後悔する自分がいました。

# JAWS-UGへの参加
　帰国後、消化不良や後悔、外の世界とのギャップをどうにかしなければならないと思った私は、JAWS-UGを通して外の世界を知りながら、自身のレベルアップを図ろうと考えました。自分が変わることで周りの状況も変えていけるのではないかと考えたのです。そして、re:Cap等の案内をキャッチアップして、オンラインのイベントに色々と参加し始めました。オンラインでみなさんのLTを見ている中で、社外の人と同じ興味・分野のことについて議論していて、何だか楽しそうだな、輪に入りたいなと思うようになりました。そして、意を決してオフラインイベントに参加してみることにしました。
 
　そして40歳を過ぎたおじさんが、ドキドキしながらも、ぼっちでオフラインイベントに参加しました。どうしようかなと思っていると、他にも一人で参加されている方がいて、そんな方と話をしたりして参加の動機を話してみたりしました。みなさん似たような動機で参加されていると知って私は安心しました。楽しそうに話をしてる人たちの輪に「すみません、せっかくなので挨拶させてください！」と無理矢理割り込んでみたり(毎度、話を折ってすみません。。)何度か参加していると、あ、この人また来てる、みたいに気づいてくれる方がいて、またお会いしましたね、と話ができたりもしました。
 
　JAWS-UGには地方支部もあり、その地域に関係ないのに参加して話を聞いてみたり、登壇もさせていただきました。先日はJAWS-UG横浜のre:Capに参加しました(ちなみに私は横浜に縁もゆかりもありません)。そんな他所者でも暖かく迎え入れてくれる優しいコミュニティです。懇親会にも参加させてもらって話をして、参加者の方のお話が聞けたり、自分が苦労していることを話してみんな同じ状況だったり、うまい解決策を知っている方がいたりします。自分の経験、失敗をお話しすると更に得られるものが多くなるなと感じています。いつもの自分の立場、ロールを全く気にせず接してくれて、AWSについて話をしてノウハウを共有、成長できる、とても良い場だと思っています。

# 次の一歩
　2年ほど、色々なJAWS-UGのイベントに参加する中で、コミュニティの運営にも興味が出てきました。どうしようかなと考えていたところ、前述のJAWS-UG横浜のイベントの際にJAWS DAYSのボランティアの話を聞きました。自分自身に次の変化を起こすための一歩を踏み出そうと思い、今回、JAWS DAYS 2025のボランティアに応募してみました。

https://jawsdays2025.jaws-ug.jp/

　JAWS DAYSは昨年、初めてオフラインの参加をしました。イベント自体がとても楽しかったのはもちろんのこと、1,000人近くの参加者が集まる大規模イベントをコミュニティ主体で実現しているのかと、驚きました。楽しいJAWS-UGのイベントにいつもとは違う立場で参加できたら、きっと、もっと楽しい未来が拓けると考えています。

ボランティア100名の枠に入れたらいいな。

3/1、池袋でお会いしましょう。
curlで証明書エラーが出る場合の対処法

症状 - Symptom
================

```bash
# dnf check-update
AlmaLinux 8 - BaseOS                                      0.0  B/s |   0  B     00:01
Errors during downloading metadata for repository 'baseos':
  - Curl error (77): Problem with the SSL CA cert (path? access rights?) for https://mirrors.almalinux.org/mirrorlist/8/baseos [error setting certificate verify locations:
  CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none]
エラー: repo 'baseos' のメタデータのダウンロードに失敗しました : Cannot prepare internal mirrorlist: Curl error (77): Problem with the SSL CA cert (path? access rights?) for https://mirrors.almalinux.org/mirrorlist/8/baseos [error setting certificate verify locations:
  CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none]
```

- `dnf ~~`系(i.e. `dnf install`, `dnf update`)を実行するとSSL CA系(?)のエラーが表示され止まる。
- `curl`コマンドも同様
- `http://`はアクセスできそう。(`curl http://www.google.co.jp`はできた)
- `https://`がダメみたい(`curl https://www.google.co.jp`は↑のエラーが出た)

試したこと
-------------

1. `ls -l /etc/pki/tls/certs/ca-bundle.crt` とか `cat /etc/pki/tls/certs/ca-bundle.crt` したらファイルがなかった
   ```bash
   ls -l /etc/pki/tls/certs/
   合計 0
   ```
1. [Laravel関連の記事](https://qiita.com/wai_make_enginner/items/d8c65a685b0a2506d7a2)とか、[なんか面倒そうなやつ](https://qiita.com/aical/items/5b3ebee3840aae741283)の内容見た（見ただけ）
1. `date`で設定されているサーバの時間確認(大きく時間がズレているとダメみたいなので)

対処方法
=========

1. `/etc/yum.conf`の最下行(5-6行くらいしかないテキストファイル)に`sslverify=false`追記する
1. `sudo dnf -y reinstall ca-certificates`実施したらなおった
1. あとは`/etc/yum.conf`に追記した`sslverify=false`を消しとく

これが一番変更なくて済むのかな。( ๑╹⌓╹ )