OmniAICreator/Qiita-1.07M huggingface dataset:
アジャイルソフトウェア開発においてドキュメント管理方法（考え方編）

## はじめに

アジャイルソフトウェア開発では、ウォーターフォールモデルとは異なり、ドキュメント作成の範囲や程度について明確な定義はありません。そのため、多くのプロジェクトマネージャーは、どこまでドキュメントを作成すべきか悩んでいるのではないでしょうか。筆者自身もアジャイルソフトウェア開発を行う中で、ドキュメンテーションについて試行錯誤を重ねてきました。

そこで今回は、アジャイル開発に取り組むプロジェクトマネージャーやエンジニアに向けて、私の経験を踏まえたドキュメント管理の考え方をまとめてみました。この記事が、アジャイルソフトウェア開発に携わる方々の一助となることを願っています。

## 対象読者

この記事は、以下のような方を対象としています。

- 初級のスクラムマスターやプロジェクトマネージャー
- ソフトウェア開発の経験が浅い、または知識がないプロジェクトオーナー

特に、アジャイル開発手法を導入したプロジェクトにおいて、ドキュメント管理の課題に直面している方に、有益な情報を提供できれば幸いです。

## 本記事の構成

この記事では、まずアジャイル開発におけるドキュメント管理の課題を整理します。次に、それらの課題に対する対応策について説明します。

## アジャイル開発におけるドキュメンテーションの課題

### ドキュメント作成の優先度の低下

- アジャイル開発では、ユーザーからのフィードバックを繰り返し取り入れ、ソフトウェアを漸進的に改善していくため、ドキュメント作成が後回しになりがちです。
  - この結果、ドキュメントの不足が属人化を引き起こし、プロジェクトメンバーを増員させたとしても、生産性低下を招く可能性があります。

### 意思決定や議論の経緯の追跡の難しさ

- 頻繁に仕様や要件が変更されるアジャイル開発では、仕様や設計に関する議論内容が無秩序に散在してしまうことがあります（SlackやIssue管理システムなどにおいて）。
  - その結果、なぜ特定の仕様に決まったのかを後から追跡することが難しくなり、プロジェクトの透明性が失われるリスクがあります。

## アジャイル開発におけるドキュメント管理方法

では上記の課題に対して、どのような考え方でドキュメント管理すべきか、以下のようにまとめてみました。

### ドキュメント作成は必要最低限に

アジャイル開発の基本原則の一つは、「動くソフトウェアを早く提供する」ことです。そのため、ドキュメント作成については、必要最低限に留めることが重要です。ただし、これはドキュメントが不要だという意味ではありません。プロジェクトの成功に不可欠なドキュメントは確実に作成するようにしましょう。

### ソースコードの可読性を上げる

ソースコードの可読性を高めることで、コードがドキュメントの役割を果たし、ドキュメント作成の負担を軽減できます。コメントや変数・関数の命名規則などに注意を払い、コードを読めば仕様が理解できるようにしましょう。

### トレーサビリティの確保

ドキュメント作成を最小限に抑えると、プロジェクトの経緯が分からなくなるリスクがあります。特に、新しいメンバーが途中から参加した場合、過去の意思決定の背景を理解するのが難しくなります。そのため、重要な仕様や決定事項については、その理由や経緯を追跡できるようにしておく必要があります。

具体的には、Issue管理システムやWikiを活用し、議論の内容や決定事項を記録しておくのが有効です。コードの変更とIssueを紐づけることで、コードの変更理由を追跡しやすくなります。また、重要な決定事項はWikiにまとめ、関連するIssueやドキュメントにリンクを張ることで、情報の散逸を防げます。

## まとめ

アジャイル開発におけるドキュメント管理では、必要最低限のドキュメント作成、ソースコードの可読性向上、トレーサビリティの確保が重要です。これらの実践により、ドキュメンテーションのオーバーヘッドを減らしつつ、プロジェクトの透明性と継続性を維持することができます。

ドキュメント管理の方法は、プロジェクトの特性や組織の文化によって異なる場合があります。大切なのは、チーム全体でドキュメンテーションの目的と価値を共有し、継続的に改善していくことです。

## 参考

[Clean Agile: Back to Basics（邦題：Clean Agile 基本に立ち戻れ）](https://www.amazon.co.jp/Clean-Agile-%E5%9F%BA%E6%9C%AC%E3%81%AB%E7%AB%8B%E3%81%A1%E6%88%BB%E3%82%8C-Robert-C-Martin/dp/4048930745)
失敗談：小規模企業へのSalesforce導入で失敗した経験談

##  前書き

今まで中小規模企業4社にSalesforceを導入を経験してきました。まだ成功事例はなく、頑張ってはいますが、その中で失敗したケースもあったので、その経験を共有したいと思います。

小企業でSalesforceの導入を考える方に少しでも参考になれたらと思います。

この文章を書いている自分は経験が浅く、見解も限られていて、主観的な観点になるかもしらないので、あくまでも参考程度にして頂けたらと思います。

## うまくいってない理由を並べて見る

### 一。継続使用に関して社長への動機付与が十分できてなかった。

知り合いの社長を説得して、まず1年使ってみるようにはしていましたのですが、次の一年間契約をする時期に十分社長を動かすものができず、契約の継続ができなかったのです。

自分の反省している部分ではございますが、Salesforceのレポートやダッシュボードなどの使用方法がよくわからなく、社長が見たい綺麗なレポート（グラフ）が作れなかったのが１番目の原因だと思います。

社員に頼んでデータ入力はしてもらっていたのですが、それなりの結果物ができなかったので時間が経つことにより失望して、継続することをやめたと思います。

### 二。プラン選びの失敗

小さい規模の会社なので、もともとSalesforceまで使う必要がなく、全てExcelにて社員一人が管理していた業務だったので、会社に取っては小さくはない金額でした。

プロフェショナルライセンス　x 2個　＋　サクセスプランで契約したところ、年間30万円程度が出たのですが、プロフェショナルライセンスではコーディングもできないし、API機能もなかったので、Salesforceの凄さを見せるのみ限界があったと思います。

今後やるとしたら、プロフェショナルライセンス2個よりは、エンタプライズライセンス1個（値段的には一緒）にした方がよかったのでは考えています。そしてサクセスプランは、大きい会社には役に立つかもしれませんが、小さい会社にはあんまりやくに立たない感じがするので、なしにして、まず金額を控えて社長に継続して使ってもらうようにした方が良かったかもしならいですね。

### 三。自分のコストは予算に入れなかったので、自分の投入時間にも限界が

人が動くには費用がかかりますが、今回はどうしても成功させたい気持ちで、自分のコストは考えていませんでした。それに伴い自分の時間投入も少なめになっていたので、自分への動機付与にも十分ではなかったと思います。

すこなくとも、自分が投入した時間分は報酬が出ていたら、自分も継続的に開発や勉強にもっと時間を入れたのではと思うようになりました。特に、自分も勉強しながらやっていたので、その分時間もかかったし、効率も低かったからでした。

## まとめ

なので、いままでの自分の浅い経験からまとめた内容にはなりますが、もしこれから小規模企業に導入をコンサルするのであれば、下記の三つぐらいは確保してから始めた方がいいかと思います。

- 自分の作業時間も考慮した十分な予算で始まること
- プランとしてはプロフェショナルよりエンタプライズが望ましい
- 小規模企業なので、コストをなるべく減らすためサクセスプランには加入しない
- 自分のSalesforce能力を高めてから導入する（レベルが低いと失敗率が高くなる）

以上です。

この文章を書く理由は、今回新しい小規模企業にSalesforceを導入しようとしてSaleforceに連絡したところ、Salesforce担当者から「2年前Qiitaに投稿した内容見たよ」との話があったので、それを探してみたら全然参考にならない文書だったので、恥ずかしく、しかもQiitaに書くと誰かは見てくれるとわかったので、これからはだれかの役に立つ、質のある記事を投稿しようと思ったからです。

今後実践で得た経験をどんどんQiitaに投稿しようと思います。
timmを利用したVision Transformerの学習

Vision Transformer(ViT)はCNNより高精度な画像認識が可能なことから注目されています．しかし，ViTは一から学習するためには膨大なデータが必要であるため個人の環境で学習するのは難しいです．そのため，Fine-tuningを用いることが一般的です．
そこで，本記事ではViTをFine-tuningする方法を書いていきます．
今回はtimmというライブラリを使用したViTのFine-tuningの方法と各引数の簡単に説明します．

ViTのモデル構造
![ViT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744226/c72ba88f-8856-88d6-87b7-efab30c798ed.png)

# timmの学習済みモデルを使用

ViTの学習済みモデルを使用するためにはtimmを使用すると簡単にできます．
timmは正式名称Py**t**orch **Im**age **M**odelsでSOTA(State of the Art)を達成した画像分類モデルを公開しているライブラリです．

下記はtimmでViTをFine-tuningするコードです．
下記コードでモデルを定義したら後はいつも通り学習するだけです．

```python
import timm # timmをインポート
from timm.models import create_model # timmで公開されているモデルを読み込む関数

# 学習済みのViTを読み込む
# num_classesはデータセットのクラスに合わせて変更
model = create_model("vit_tiny_patch16_224", pretrained=True, num_classes=10) 
model.to('cuda')
```

# 各引数について

ここでは各引数について説明します．

## モデル名

`vit_tiny_patch16_224`はモデル名を指します．
今回は`vit_tiny_patch16_224`を使用していますが使用できるモデルは他にも複数存在します．
実際に使用できるモデルは[ここ](https://github.com/huggingface/pytorch-image-models/blob/main/timm/models/vision_transformer.py)の1792行目以降に定義されています．

`tiny`はモデルサイズを指し，`tiny`，`small`，`base`，`large`などが存在し，モデルの深さ(Transformer Encoderの数)や埋め込み次元数などが異なります．
`patch16`はパッチサイズを指し，`patch14`，`patch16`，`patch32`などが存在します．
`224`は画像サイズを指し，`224`や`384`などが存在します．

## 学習済みの重み

`pretrained`は学習済みの重みを使用するかを選択します．
`pretrained=True`にすると学習済みのモデルが読み込まれます．

## クラス数

`num_classes`は分類器([上の図](https://camo.qiitausercontent.com/0670806dae9449178107f0681ad9e7763bfe3302/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333734343232362f63373262613838662d383835362d383864362d383762372d6566616233306337393865642e706e67)で言うMLP Head)の出力次元数を指します．使用するデータセットのクラスに合わせて変更します．10クラスであれば`num_classes＝10`になります．
`num_classes`は指定しなければImageNet-1kと同じ1000クラス分類用の分類器が読み込まれます．
`num_classes＝0`とすると分類器を使用せず特徴量を抽出することが可能になります．

# まとめ

今回はtimmというライブラリを使用したViTのFine-tuningの方法について説明しました．
timmを使用することで，簡単に学習済みのViTを使用することが可能です．
[ここ](https://github.com/SyunkiTakase/ViT_Classification_Sample/tree/main)で実際にtimmを使用してViTでCIFAR-10 / 100を分類するコードを公開しています．

# 参考文献
ViTの論文：An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
論文LINK：https://arxiv.org/abs/2010.11929
timmのリポジトリ：https://github.com/huggingface/pytorch-image-models/tree/main
Pythonで使えるOCRライブラリまとめ

# はじめに

皆さんこんにちは!ぽこちゃんです

他の記事も投稿してますし、Xではデータサイエンス系、エンジニアリングに関連した
情報を発信しているのでぜひみてってください!


https://twitter.com/tomato_boy77

今回はインターンにてPythonでOCRをする機会があって
調査したのでまとめてみました!

# ライブラリの選定基準
今回の選定基準は以下の通りです

- モデル
    - githubにレポジトリが公開されている
    - 商用利用可能
    - 英語、数字の検出ができる
    - 日本語の検出ができる
    - 文字検出（Scene Text Detection）と文字列分類(Scene Text Recognition)両方実施できる
    - 最大限精度が良い
        - 追加訓練可能
- API
    - 商用利用可能
    - セキュリティについて問題ない
    - 料金
    - 英語、数字の検出ができる
    - 日本語の検出ができる
    - 文字検出と文字列分類両方実施できる
    - 最大限精度が良い
        - 追加訓練可能

# OCRライブラリ一覧


| モデル名 | githubリンク | 商用利用可能か | 英語・数字の検出は可能か | 日本語の検出は可能か | 文字検出が可能か | 文字列分類は可能か |
| --- | --- | --- | --- | --- | --- | --- |
| PaddleOCR　 | https://github.com/PaddlePaddle/PaddleOCR | ○(Apache-2.0) | ○ | ○ | ○ | ○ |
| EasyOCR | https://github.com/JaidedAI/EasyOCR | ○(Apache-2.0) | ○ | ○ | ○ | ○ |
| Tesseract | https://github.com/tesseract-ocr/tesseract | ○(Apache-2.0) | ○ | ○ | ○ | ○ |
| manga-ocr | https://github.com/kha-white/manga-ocr | ○(Apache-2.0) | ○ | ○ | ○ | ○ |
| mmocr | https://github.com/open-mmlab/mmocr | ○(Apache-2.0) | ○ | ？（試していない） | ○ | ○ |


# モデル詳細
- モデルの詳細
    - Paddleocr
        - 検出、認識の学習済み日本語モデルがgithubにある
        - モデルの追加訓練可能
        - 多言語に対応（日本語も）
            
            https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7/doc/doc_ch/visualization.md
            
            ![Untitled](https://github.com/PaddlePaddle/PaddleOCR/raw/release/2.7/doc/imgs_results/PP-OCRv3/multi_lang/japan_2.jpg)

            
        - demo画像を見る限り、精度も良さそう？
            
            ![Untitled](https://github.com/PaddlePaddle/PaddleOCR/raw/release/2.7/doc/imgs_results/PP-OCRv3/en/en_2.png)
            
        - レイアウト分析＋テーブル識別、RE（関係性抽出）
            
            
    - Tesseract
        - Tesseract4は行認識に特化したLSTMベースのocrモデル
        - Tesseract3は文字パターンを認識することで動作するモデル
        - 100以上の言語をサポート
        - PNG、JPEG、TIFFを含む様々な画像フォーマットをサポート
        - Tesseractは様々な出力フォーマットもサポート： プレーンテキスト、hOCR（HTML）、PDF、不可視テキストのみのPDF、TSV、ALTO。
        - モデルの追加訓練可能
        - 精度面での記載なし
    - easy-ocr
        - 80以上の言語をサポート
        - モデルの追加訓練可能
        - 手書き文字のサポート
        - さまざまな用途に適用可能（カスタマイズが可能で、特定の用途やニーズに合わせて調整できる）
    - mmocr
        - テキスト検出やテキスト認識だけでなく、キー情報抽出のような下流のタスクもサポート
        - MMOCRのモジュラー設計により、ユーザーは独自のオプティマイザー、データ・プリプロセッサー、バックボーン、ネック、ヘッド、ロスなどのモデル・コンポーネントを定義可能
        
    - manga-ocr
        - マンガのテキストを上手く扱えるように学習されたモデル
        - 縦書きにも対応、ふりがなつきの文字、画像の上に表示されている文字、さまざまなフォント、低画質画像
        - 他の種類の印刷された文字にはきちんと対応できるが、手書きのテキストはおそらく扱えない
        - TransformerのVision Encoder Decoderフレームワークで構築されたカスタムエンドツーエンドモデルを使用
        - マンガOCRは、1回のフォワードパスで複数行のテキストを認識することをサポートしているため、マンガに見られるテキストバブルを行に分割することなく、一度に処理することができる
        - 学習済みモデルあり
        - モデルの追加訓練可能か 　不明

# 参考資料
https://tech-blog.rakus.co.jp/entry/20230925/ai

https://paperswithcode.com/task/optical-character-recognition

https://paperswithcode.com/task/scene-text-detection

https://paperswithcode.com/task/scene-text-recognition

https://www.jetir.org/papers/JETIR2104193.pdf

https://www.reddit.com/user/Due-Chair-3984

https://medium.com/@natsunoyuki/ocr-with-the-ctc-loss-efa62ebd8625
Pardot　UI関係の問題

[UI関係のトラブルに戻る](https://qiita.com/Keiji_otsubo/items/cc344223cfa02db6bed7)



+ [Account Engagement unable to load](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007AhaRz)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/51362379-01d2-56a3-0599-6d6da7ef10b7.png)

:::note

こちらの記事をご確認ください。

ユーザが Account Engagement Lightning アプリケーションにアクセスしようとすると、読み込みアイコンを通過できません
Please check this article.

User cannot get past loading icon when attempting to access Account Engagement Lightning App
https://help.salesforce.com/s/articleView?id=000383012&type=1
:::

+ [Hi ,I cannot access Account Engagement in SIT 2 screen keeps loading.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Yw0eo)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0fbc54b6-39da-72d3-0055-78954588bde2.png)

:::note
suggests it does not solve your issue, one thing you may check is if your profile can access the Connected App "b2bma_canvas".

問題が解決しないことを示唆している場合は、プロファイルが接続アプリ「b2bma_canvas」にアクセスできるかどうかを確認してください。
:::
Java: Refaster templateでソースコードを一括置換しよう(Gradle版)

# 概要

大規模なリファクタリングを安全に行うため、Google製のJava静的解析ツールである[Error Prone](https://errorprone.info/)にて、自作の[Refaster template](https://errorprone.info/docs/refaster)に対して[Patch作成機能](https://errorprone.info/docs/patching)を利用したソースコードの一括置換を試みました。

本記事では、その手順をまとめています。

# 実行手順

## 1. [Refaster Template](https://errorprone.info/docs/refaster)クラスを作成する

例: [Apache Commons DbUtils](https://commons.apache.org/proper/commons-dbutils/)の[DbUtils#closeQuietly](https://commons.apache.org/proper/commons-dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html#closeQuietly-java.sql.Connection-)の呼び出しの効率化を題材とします。

```java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.apache.commons.dbutils.DbUtils;

import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;

public class UseCloseQuietly {
	@BeforeTemplate
	public void calledCloseQueitly3Times(Connection conn, PreparedStatement ps, ResultSet rs) {
		DbUtils.closeQuietly(rs);
		DbUtils.closeQuietly(ps);
		DbUtils.closeQuietly(conn);
	}

	@AfterTemplate
	public void optimizedMethod(Connection conn, PreparedStatement ps, ResultSet rs) {
		DbUtils.closeQuietly(conn, ps, rs);
	}
}
```

ただし、(おそらく) `@BeforeTemplate` の構文木が複雑になる場合(if文やtry-catchが多く含まれている場合など)は、後述のrefasterファイルによるPatchを生成できませんでした。小分けにすると動作することもあったので、現状ではサポートしているケースが限られているのだと考えています。

## 2. refasterファイルを生成する

[error_prone_refaster](https://mvnrepository.com/artifact/com.google.errorprone/error_prone_refaster)や参照しているライブラリのjarファイルをクラスパスに含めた状態で、javacコマンドを実行します。(要: Java 11)

すると、 `myrule.refaster` ファイルが生成されます。

```shell
javac \
  -cp "error_prone_refaster-2.26.1.jar;commons-dbutils-1.8.1.jar" \
  "-Xplugin:RefasterRuleCompiler --out myrule.refaster" \
  UseCloseQuietly.java
```

## 3. Gradleプロジェクトに適用する

1. 生成されたmyrule.refasterを対象のGradleプロジェクトに配置する
1. [gradle-errorprone-plugin](https://github.com/tbroyer/gradle-errorprone-plugin)を利用するため、build.gradleに下記の内容を追記する
1. `gradle clean compileJava` を実行すると、 `error-prone.patch` が生成される
1. `patch -p0 -u -i error-prone.patch` を実行し、パッチを適用する

```gradle
plugins {
  id("net.ltgt.errorprone") version "3.1.0"
}
 
import net.ltgt.gradle.errorprone.CheckSeverity

compileJava {
  options.errorprone.checks = ['Refaster': CheckSeverity.ERROR]
  options.errorprone.errorproneArgs = ['-XepPatchChecks:refaster:' + buildscript.sourceFile.getParent() + '/myrule.refaster',
   '-XepPatchLocation:' + buildscript.sourceFile.getParent()]
  options.errorprone.checkOptions = ['Refaster': 'NamePattern=.*']
}

dependencies {
  errorprone("com.google.errorprone:error_prone_core:2.26.1")
}
```

なお、`-XepPatchLocation:IN_PLACE` と設定すれば、修正を直接適用できます。

参考: [Can Error Prone Auto-Apply Suggested Fixes?](https://stackoverflow.com/a/61710885)

# 結果

対象プロジェクトのソースコードに対して、下記のような変更が一括で適用されます。
変数名が異なっていても問題なく置換されますし、必要なimport文も自動で生成されます。
（余計な空行があるのはご愛嬌…別途、コードフォーマッターを適用しましょう）

```diff
		} finally {
-			DbUtils.closeQuietly(rs);
-			DbUtils.closeQuietly(ps);
-			DbUtils.closeQuietly(conn);
+			DbUtils.closeQuietly(conn, ps, rs);
+
+
		}
 ```
勝手に次のステップへ進むガイド

各ステップに以下を入れてステップ毎に動画の長さに応じてminとmax値を調整する。
プログレスバーが勝手にすすんで、次のステップへ移行する。

```html
    <progress id="p1" min="0" max="100" value="0" class="progress1" ></progress>

    <progress id="p2" min="0" max="100" value="0" class="progress2" ></progress>

    <progress id="p3" min="0" max="100" value="0" class="progress3" ></progress>
```

```javascript
function proc1(){
if (document.getElementById('p1').value < 100 ) {
		document.getElementById('p1').value++;
		setTimeout(proc1, 100);
	}
else{
    pendo.onGuideAdvanced()
  }
}
proc1()
```

![CleanShotXEPyzsUn.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227518/68258943-fe39-9c21-3529-8f1f59998162.gif)
【Publisher】Aiming for unified management of Excel reports

# Introduction #
Have you ever created a report using Microsoft Excel and want to publish it directly on your intranet or the Internet? Have you ever thought that you would like to centrally manage Excel reports?
It seems that this feature has been added to Sharperlight, so I would like to try it out right away.

# Creating a Report in Excel #
I have posted an article for creating a report with Sharperlight Excel Add-in before [[↗]](https://qiita.com/Miki_Yokohata/items/4e8b3cd5200281cef61e/) so please have a look it and prepare a Excel report for publishing. 



# Publish Excel Report #
Click on the "Publish Workbook" icon in the Sharperlight ribbon.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b3fde821-405d-4ddf-51f2-f5d9e9e6724e.png)
The Web Report Definition dialog will appear.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b69d46bb-8978-c7dc-6a11-20e88fe9ceb5.png)
Modify the **Code** and **Group** to your preferred values.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a80d1df6-153f-16d5-f3d8-41689cccf8a6.png)
First, click the **Apply** button to save the definition. Then, click the **View** button to preview the report in the browser.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d82d1028-9d84-82a7-928d-32cf41ba9e6c.png)
If the Sharperlight service is already running, a web report like this will be displayed. It's well-suited for immediate publication to various departments within the company, especially in an intranet setting. Of course, with appropriate configurations for Sharperlight service and user settings, it can also be made accessible to the public.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/33af3c3a-02cd-6da4-abe1-c9aa1cc28e64.png)
When you modify the parameters,...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6001e954-e6de-9ce9-a0f0-466a0235ef27.png)
...the result is immediately updated.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d3d5e678-079b-740d-3ae2-61f3c320d79e.png)

# Conclusion #
Isn't this a solution to the inconvenience of reusing valuable Excel reports stored individually on each computer and the challenges of file sharing when there is a need for centralized management of reports?
【パブリッシャー】 Excelレポートの一元管理を目指す

# はじめに #
マイクロソフトエクセルで作成したレポートをイントラネットあるいはインターネット上にそのまま公開したいなってことありませんか？、またExcelレポートの一元管理を目指したいなあなんて思ったことないですか？
Sharperlightにその機能が追加されたようなので早速試してみたいと思います。

# エクセルでレポートを作成する #
以前にSharperlight Excelアドインを使ったレポート作成記事を投稿しましたので[[↗]](https://qiita.com/Miki_Yokohata/items/c0bf5e9f4e8d86e1e3c3/)、ぜひそちらをご覧いただき、公開用のExcelレポートを準備してください。 。

# エクセルレポートの公開 #
Sharperlightリボンの`ワークブックのパブリッシュ`アイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cdcf7c13-b709-2634-ae15-fb35f17929f2.png)
Webレポートの定義ダイアログが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0033c848-bae5-2184-5d14-96bf57e74a85.png)
**コード**や**グループ**をお好みの値に書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/c76d8d6c-8780-07f3-0dfb-2bd0c3f6eec1.png)
先ず`適用`ボタンをクリックして定義を保存します。そして`ビュー`ボタンをクリックしブラウザでレポートを閲覧します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/edf4a1e3-eff5-eab4-5568-e2f11843b4a8.png)
Sharperlightサービスが起動済みであるとすると、このようなWebレポートが表示されます。
イントラネットであれば直ちに部署内に公開したりするのに適しているのではないでしょうか。もちろんSharperlightサービスやユーザー設定が一般公開用に設定されていれば、公衆への公開も行えますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/759363c1-17f1-1e3b-dcba-156fa7840f41.png)
パラメータを変更すると。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6001e954-e6de-9ce9-a0f0-466a0235ef27.png)
直ちに結果も更新されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/32947e20-6ed0-9be7-e769-089badb67dce.png)

# おわりに #
個々のパソコンにしまい込まれている有益なExcelレポートの再利用やファイルでの共有の不便さ、レポートの一元管理等のニーズに答えられる一品ではないでしょうか？
AWS ipv4でお金かかってるけど、どうすんだ（LB編）

# はじめに
Load Balancerをipv6対応するには下記
https://repost.aws/ja/knowledge-center/elb-configure-with-ipv6

1. VPC, SubnetにIPv6設定する
1. ALB本体でdualstackを設定する
1. route53のレコードにdualstackを付与してあげる

「1」は前の投稿を確認してください。
「3」は設定変更前に実施しても動作影響ないです。所属会社で訳も分からずdualstackがついてたり・ついてなかったり乱立してます。

なので順番的には
1 -> 3 -> 2
かなって

# 設定
## ALB本体でdualstackを設定する
ロードバランサのIPアドレスタイプをdualstackにするだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47012/72582888-1a7c-7848-0d72-d24a5707be9b.png)

terraform的には
aws_lbステートに下記1行を足すだけです。
optionalでdefaultがipv4です。
```
  ip_address_type = "dualstack"
```

通信断があったようには思えないですが、サポートに確認してみます。
→AWSに確認したところ
　公式の公表情報はなし
　サポートで動作確認してくれて、その上では断は発生しなかった

## route53のレコードにdualstackを付与してあげる
dualstackをつけただけだと基本ipv4っぽいです

Aレコード→AAAAレコードに変更すればipv6が強制されます。

ipv4のアクセスがある限りは課金されちゃうので強制した方が良いかもです。
でも接続元が対応してない可能性があるのでしばらくはipv4のままかなって
【メモ】Linuxのファイル・フォルダの表示色

## 青：ディレクトリ（フォルダ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/6f1421b7-ea32-06eb-3279-cae671ebce14.png)
## 緑：実行可能なファイル（或いは正しく認識されているファイル）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/b331620b-fd0f-333c-c31c-8bfdf1e7ab06.png)
    「実行可能である」とは、`source`コマンドで実行できる状態のこと。実行可能であるかどうかは、`ls -l`の結果で出てくるパーミッションコードにca「`x`」が含まれるかどうかで確認できる。
## 水色：有効なリンク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/dc477d68-a0bc-74b1-1938-3322a44820cf.png)
## 黒背景に赤文字：無効なリンク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/352513ce-b69a-c2a0-fa27-954c3cb13da8.png)
## 黒い背景に黄色い字：デバイスに対応するファイル・フォルダ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/8815da7c-b749-da95-0b79-60440f968f68.png)
## ピンク字：画像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/cbc6822c-114d-64b9-5c9a-af0952ff7678.png)
## 赤字：アーカイブファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629535/d4423f55-1583-bc7f-4ac5-bac54bbe0b2b.png)
[homebrew] M1 Macでnginxのサーバーにファイルをアップロードする

前提
- [nginxのCGIを動かす](https://qiita.com/jizots/items/3c18a9dcbb7469528db7)
までができていること。

上述したリンクの設定を引き継いだ前提で、ディレクトリ構成を行なっています。
nginxのconfigurationも前回の設定のままで変更不要です。（.pyのロケーションにPOSTを許可しなくても動作するのが不思議ですが、、）

# ステップ1： nginxとfcgiwrapの起動を確認
## fcgiwrapが起動していることを確認
コマンド
```
ps aux | grep fcgiwrap
```
``_www             30072   0.0  0.0 410629888   1344   ??  Ss   10:45AM   0:00.01 /opt/homebrew/Cellar/fcgiwrap/1.1.0/sbin/fcgiwrap``みたいなのが出ればOKです。

## nginxが起動していることを確認
コマンド
```
ps aux | grep nginx
```
``_www             30145   0.0  0.0 411434160   2272   ??  S    10:46AM   0:00.06 nginx: worker process``と``
root             30144   0.0  0.0 410740656    288   ??  Ss   10:46AM   0:00.00 nginx: master process nginx``みたいなのが出ればOKです。

どちらかがうまくいっていない場合は[nginxのCGIを動かす](https://qiita.com/jizots/items/3c18a9dcbb7469528db7)を参照して、起動させてください。

# ステップ2: ディレクトリとファイルの準備
## アップロード先ディレクトリの準備
### 作成
```
mkdir /opt/homebrew/Cellar/nginx/1.25.4/html/upload
```
### 権限変更
```
sudo chmod 777 /opt/homebrew/Cellar/nginx/1.25.4/html/upload
```

## htmlファイル（ユーザーのインターフェース）の準備
### upload.htmlの作成
以下のディレクトリにてupload.htmlを作成する。
```
cd /opt/homebrew/Cellar/nginx/1.25.4/html
```
upload.htmlの内容
```
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>ファイルアップロード</title>
</head>
<body>

<h2>ファイルアップロード</h2>
<form action="/upload.py" method="post" enctype="multipart/form-data">
  ファイルを選択:
  <input type="file" name="file">
  <input type="submit" value="アップロード">
</form>

</body>
</html>
```
upload.htmlファイル権限の変更はいらないと思いますが、permissionのエラーが出た場合は権限を変更してください。

### 


## .pyファイル（postメソッドを行う）の準備
### upload.pyの作成
以下のディレクトリにてupload.pyを作成する。
```
cd /opt/homebrew/Cellar/nginx/1.25.4/cgi-bin
```
upload.pyの内容
```
#!/opt/homebrew/bin/python

import cgi
import os
from http import cookies
import cgitb; cgitb.enable()  # CGIデバッグを有効化

form = cgi.FieldStorage()

# ファイルアップロードフィールドのチェック
fileitem = form['file']

if fileitem.filename:
    # ウェブサーバ上のディレクトリへのファイルパスを設定
    fn = os.path.basename(fileitem.filename)
    filepath = '/opt/homebrew/Cellar/nginx/1.25.4/html/upload/' + fn
    with open(filepath, 'wb') as f:
        f.write(fileitem.file.read())
    message = 'ファイル "{}" のアップロードに成功しました'.format(fn)
else:
    message = 'ファイルがアップロードされませんでした'

# HTMLコンテンツをUTF-8として出力
print("Content-Type: text/html; charset=utf-8\n")
print("""
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>アップロード結果</title>
</head>
<body>
   <p>{}</p>
</body>
</html>
""".format(message))

```
*　1行目の``#!/opt/homebrew/bin/python``はあなたのPCの環境設定に合わせてください

もし、cgi-binディレクトリの権限が_wwwで、ファイルの作成ができない場合は以下の対応を行なってください。
対応① upload.htmlをデスクトップに作成する。
対応② sudo + mvコマンドでファイルを移動する。例``sudo mv path_to/upload.html /opt/homebrew/Cellar/nginx/1.25.4/cgi-bin``

## 権限変更
.pyの実行権限を全てのユーザーにします
```
sudo chmod 777 cd /opt/homebrew/Cellar/nginx/1.25.4/cgi-bin/upload.py
```

# ステップ3：ブラウザからアップロード
ブラウザから``http://localhost:8100/upload.py``にアクセスして、ファイルをuploadすると、``/opt/homebrew/Cellar/nginx/1.25.4/html/upload``にファイルがあるはずです。

今回はここまで！
AWS ipv4でお金かかってるけど、どうすんだ（VPCとサブネット編）

# はじめに
公式の手順
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-migrate-ipv6.html

- ステップ 1: IPv6 CIDR ブロックを VPC およびサブネットと関連付ける
- ステップ 2: ルートテーブルを更新する
- ステップ 3: セキュリティグループルールを更新する
- ステップ 4: IPv6 アドレスを各リソースに割り当てる

ステップ3までは無影響でいけそうです。
ステップ4は別の記事で投稿します。

# ステップ 1: IPv6 CIDR ブロックを VPC およびサブネットと関連付ける
## VPC
### GUIでやる場合
VPCのCIDRの編集からやります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47012/b56ffe14-7e49-3200-df67-5d21a16b21d0.png)

解らなければAmazon提供のものを使うのが無難です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47012/60f3e336-c461-6403-b127-45dc8fc67070.png)

### terraform でやる場合
aws_vpc ステートに下記1行を加えるだけでGUIと同じ結果になりました。（素敵）

```
assign_generated_ipv6_cidr_block = "true"
```

## サブネット
### サブネット
参考
https://repost.aws/ja/questions/QUiMQuvvAzRMab8YDqWWTYeA/need-help-trying-to-connect-ipv6-address-to-vpc-subnets

aws_subnet ステートに下記2行を足します

```
  # ipv6
  ipv6_cidr_block = "${cidrsubnet(aws_vpc.ステート名.ipv6_cidr_block, 8, 0)}"
  assign_ipv6_address_on_creation = true # or false
```

cidrsubentの第三引数は、「第二引数のリストから、何番目のCIDR範囲を使用するか」らしいです。
ipv4の例 192.168.0.0/24, 192.168.1.0/24 この第3オクテッドに自分は合わせてみました。
`cidrsubnet(aws_vpc.ステート名.ipv6_cidr_block, 8, 0)`

### ルート
新規追加した方が影響少ないかなって思います。

```
resource "aws_route" "お名前" {
  route_table_id              = ルートテーブルのID
  destination_ipv6_cidr_block = "::/0"
  gateway_id                  = インターネットゲートウェイのID
}
```
【ROS2 パラメータTips】 int型配列パラメータをビルドできない場合の対処方法

# はじめに

ROS2のC++ノードでint配列(```std::vector<int>```)パラメータを使おうとしたら、コンパイルエラーとなったので、その対処方法を記載する。

# 環境
* ROS2 Foxy

# 方法

[リンク先](https://github.com/ros2/rclcpp/issues/1585#issuecomment-803695039)にあるように、```std::vector<int>```では、エラーとなるので、```std::vector<int64_t>```に変更する。

int(uint)型配列の対応状況は以下のようになっている。

* NG
    ```c++
    // int
    node->declare_parameter<vector<int>>("param", std::vector<int>{});
    node->declare_parameter<vector<int16_t>>("param", std::vector<int16_t>{});
    node->declare_parameter<vector<int32_t>>("param", std::vector<int32_t>{});
    // unsigned int
    node->declare_parameter<vector<uint16_t>>("param", std::vector<uint16_t>{});    
    node->declare_parameter<vector<uint32_t>>("param", std::vector<uint32_t>{});    
    ```

* OK
    ```c++
    // int
    node->declare_parameter<vector<int64_t>>("param", std::vector<int64_t>{});
    // unsigned int
    node->declare_parameter<vector<uint8_t>>("param", std::vector<uint8_t>{});    
    ```

# 補足情報

配列型パラメータでコンパイル可能な型は以下の通り。

```c++
node->declare_parameter<std::vector<double>>("param", std::vector<double>{});
node->declare_parameter<std::vector<uint8_t>>("param", std::vector<uint8_t>{});
node->declare_parameter<std::vector<bool>>("param", std::vector<bool>{});
node->declare_parameter<std::vector<int64_t>>("param", std::vector<int64_t>{});
node->declare_parameter<std::vector<double>>("param", std::vector<double>{});
node->declare_parameter<std::vector<std::string>>("param", std::vector<std::string>{});
```



# 参考

https://github.com/ros2/rclcpp/issues/1585#issuecomment-803695039
最速で作るDocker+Next.js+Laravelの開発環境構築用


## Next.JSとLaravelの開発環境をすぐに手に入れたい方へ（=結論）

成功した開発環境をそのまま手に入れる。

以下は私の環境で動作したソースコードです。

適宜、ファイルの中身は調整していただけると幸いです。

Windows検証だったので、MacやLinuxは検証していません。


```git
git clone https://github.com/naomina121/Laravel-Nextjs.git

or

git clone git@github.com:naomina121/Laravel-Nextjs.git

cd Laravel-Nextjs
.\init.bat
```

batファイルで開発環境を整えるため、Windowsではパワーシェルのセキュリティポリシー対策などが必要です。（ここでは割愛）

他にも使い方は、[README.md](https://github.com/naomina121/Laravel-Nextjs)に記載しています。


##　どうでもいい話

最初はQiitaで記事にして手順を説明しようかなと思ったんです。

でも自分で構築していて、面倒になりました←

実際のソースコード見た方が早いですよね。（＝手抜き）

## 参考にさせていただいた記事（感謝）

- [Next.jsとLaravelで2ちゃんねるっぽいアプリを作る](https://zenn.dev/ponta/books/95e0984aa9dcbd)
Enhancing Education with CRM: A Tool for Teachers and Students

In this digital era, Customer Relationship Management (CRM) systems are not solely reserved for businesses. They have become valuable tools in the educational sector, benefiting both teachers and students in numerous ways.

1. Personalized Learning Experience:
CRM software allows teachers to create personalized learning experiences for students. By storing and analyzing student data, such as learning preferences, academic performance, and interests, teachers can tailor their teaching methods to meet individual student needs. This personalized approach not only enhances student engagement but also ensures better academic outcomes.

2. Efficient Communication:
Effective communication is key in education. CRM systems provide a centralized platform for teachers to communicate with students, parents, and other educators. Whether it's sending out notifications, sharing updates on coursework, or arranging parent-teacher meetings, CRM streamlines communication processes, fostering stronger relationships within the educational community.

3. Data Management and Analysis:
CRM platforms enable teachers to efficiently manage student data, such as attendance records, grades, and behavioral information. With built-in analytics tools, educators can gain valuable insights from this data, identifying patterns, tracking student progress, and predicting performance trends. This data-driven approach empowers teachers to make informed decisions to support student learning effectively.

4. Task and Workflow Management:
Teachers juggle multiple responsibilities, from lesson planning to grading assignments. CRM systems offer task and workflow management features that help educators stay organized and productive. Teachers can set reminders, create schedules, and track progress on various tasks, ensuring nothing falls through the cracks and maximizing their teaching efficiency.

5. Parental Involvement:
CRM enhances parent-teacher collaboration by providing a platform for parents to stay informed about their child's academic progress, attendance, and overall well-being. Through CRM portals, parents can access real-time updates, communicate with teachers, and actively participate in their child's education journey. This transparency fosters a supportive learning environment that benefits student success.

In conclusion, CRM systems are transformative tools that revolutionize the education landscape, empowering teachers to deliver quality education and students to achieve their full potential. By leveraging CRM technology, educators can create engaging learning experiences, streamline administrative tasks, foster effective communication, and ultimately enhance the overall educational experience for all stakeholders involved.

Remember, learning never stops, and with CRM in education, the possibilities for growth and development are endless.
InDesignで選択したオブジェクトをキーオブジェクトの大きさに揃える


```javascript:選択したオブジェクトをキーオブジェクトの大きさに揃える.jsx
if (app.documents.length==0 || app.selection.length<2){exit();}
app.doScript("resizeobject()",ScriptLanguage.JAVASCRIPT,[],UndoModes.ENTIRE_SCRIPT);

function resizeobject(){
    var myDoc=app.activeDocument;
    var mySel=myDoc.selection;
    try{
        var myKeyObj=myDoc.selectionKeyObject;
        var myKeyTL=myKeyObj.resolve(AnchorPoint.TOP_LEFT_ANCHOR,CoordinateSpaces.INNER_COORDINATES,false)[0];
        var myKeyBR=myKeyObj.resolve(AnchorPoint.BOTTOM_RIGHT_ANCHOR,CoordinateSpaces.INNER_COORDINATES,false)[0];
        var myKeyW=myKeyBR[1]-myKeyTL[1];
            var myKeyH=myKeyBR[0]-myKeyTL[0];
        for (var i=0; i<mySel.length;i++){
            try{
            mySel[i].resize(CoordinateSpaces.INNER_COORDINATES,AnchorPoint.TOP_LEFT_ANCHOR,ResizeMethods.   REPLACING_CURRENT_DIMENSIONS_WITH,[myKeyH,myKeyW],undefined,false);
            }catch(e){alert(e.message+"\nその他のオブジェクトは処理します。")}
        }
    }catch(e){alert("キーオブジェクトを指定してください");}
}
```
魔法少女リリカルなのは形態素解析比較大会

# 「魔法少女リリカルなのは」を形態素解析しよう
まずこの話題を話すためには「魔法少女リリカルなのは」形態素解析問題について話さねばなるまい。「魔法少女リリカルなのは」形態素解析問題とは簡単に言うと「なのは」を人名としてユーザー辞書に登録すると「~なのは」という日本文の解析がUnidicやMecabでうまくいかなくなる問題である。しかし最近はBPEやSentence Pieceなどの台頭によりトークナイザー方法も進化してきた。そこで, 現代のトークナイザーはどのように「魔法少女リリカルなのは」をトークナイズしていくのかを見ていこうというのがこの記事の目的である。

# まずは人の手でトークナイズ
最近はトークナイズ方法も色々考案されてきているため意味が変わってきている気がするが, 元々の意味での形態素解析とは、文章を意味を持つ最小単位である「形態素」に区切り、それぞれを名詞や動詞などの品詞に分類することである。なので魔法少女リリカルなのはは固有名詞なので「魔法少女リリカルなのは」でも良いが, それだとコーパス内に「魔法少女リリカルなのは」トークンの存在確率は低いと考えられるので, より良いテキスト応答システムを作る観点から真面目に考えることにする。というわけで人手によるトークナイズ結果はこちらである。
```
['魔法', '少女', 'リリカル', 'なのは']
```
魔法, 少女が名詞であることは言うまでもないだろう。リリカルは「lyrical」という形容詞なのでこれが最も良い, なのはは人名である。これだけは譲れない。

# Tokenizer比較
## GPT2 BPE Tokenizer
* \ufffdとなるところはバイトリテラル表現にした
```
['魔', b'\xe6\xb3', b'\x95', b'\xe5\xb0', b'\x91', '女', 'リ', 'リ', 'カ', 'ル', 'な', 'の', 'は']
```

## Gemma (google/gemma-7b)
```
['魔法', '少女', 'リ', 'リ', 'カル', 'なのは']
```

## BERT base Japanese (tohoku-nlp/bert-base-japanese-whole-word-masking)
```
['魔法', '少女', 'リ', '##リカル', 'な', 'の', 'は']
```

## intfloat/multilingual-e5-large
```
['▁', '魔法', '少女', 'リ', 'リ', 'カル', 'な', 'のは']
```

## Mixtral (mistralai/Mixtral-8x7B-Instruct-v0.1)
```
['▁', '魔', '法', '少', '女', 'リ', 'リ', 'カ', 'ル', 'な', 'の', 'は']
```

## google/flan-t5-large
```
['▁', '魔法少女リリカルなのは']
```

## t5-base-japanese (sonoisa/t5-base-japanese) 
```
['▁', '魔法少女', 'リ', 'リ', 'カル', 'な', 'の', 'は']
```

# 感想
日本語コーパスを含んでいるであろうモデルは「魔法」, 「少女」もしくは「魔法少女」でトークン分割できていてよかった。「魔法少女リリカルなのは」, 「なのは」を1トークンで表現するやつはコーパス制作係にオタクのスパイでも紛れ込んでいたんだろうか
優勝はGemmaです。名誉オタクトークナイザー賞を差し上げます。
ActiveRecord::Reflection で Model 間の関連付け情報を取得する

株式会社学びと成長しくみデザイン研究所の藤澤です。

## はじめに

Rails の各 Model 間の関連付けの情報を実装上で取り扱うにあたり、ActiveRecord にはそれを取り出すためのメソッドとその情報を管理するクラスが用意されています。

今回は、以下のような Model を例に説明を進めていきます。
```rb
# 1つのAuthorに複数のBookが紐付き、1つのBookに複数のPageが紐づく。
# Author の主キーは code で、Book における外部キーは author_code。
class Author < ApplicationRecord
  self.primary_key = :code
  has_many :books, foreign_key: :author_code
end

class Book < ApplicationRecord
  belongs_to :author, foreign_key: :author_code
  has_many :pages
end

class Page < ApplicationRecord
  belongs_to :book
end

```

### 環境
Rails 7.0.8.1

## ActiveRecord::Reflection
`ActiveRecord` の関連付け情報を扱うクラス。

内部クラスとして、各関連を表現する `AssociationReflection` と、そのサブクラスである `HasManyReflection`（has_many 関連）や`BelongsToReflection`（belongs_to 関連）などを持つ。

### reflect_on_association(association)
レシーバーから見て引数 `association` のモデルに対する関連付け情報を取得する。

```ruby
Book.reflect_on_association(:pages)
# =>（一部省略）
# #<ActiveRecord::Reflection::HasManyReflection
#  @active_record=Book,
#  @name=:pages,
#  @options={}>
```

### reflect_on_all_associations
すべての関連付け情報を配列で取得する。

### ::reflections
すべての関連付け情報を、各関連名を `key`、関連情報を `value` とした `Hash` で取得する。

```ruby
Book.reflections
#=> （一部省略）
# {"author"=>
#   #<ActiveRecord::Reflection::BelongsToReflection
#    @active_record=Book,
#    @name=:author,
#    @options={:foreign_key=>:author_code}>,
#  "pages"=>
#   #<ActiveRecord::Reflection::HasManyReflection
#    @active_record=Book,
#    @name=:pages,
#    @options={}}
```

## ActiveRecord::Reflection::AssociationReflection

### foreign_key
関連先の外部キーを取得する。

```ruby
reflection = Author.reflect_on_association(:books)
#=> #<ActiveRecord::Reflection::HasManyReflection>
reflection.foreign_key
#=> "author_code"
```

### active_record_primary_key
関連元の主キーを取得する。

```ruby
reflection = Author.reflect_on_association(:books)
#=> #<ActiveRecord::Reflection::HasManyReflection>
reflection.active_record_primary_key
#=> "code"
```

### association_primary_key
関連先の主キーを取得する。
```ruby
reflection = Author.reflect_on_association(:books)
#=> #<ActiveRecord::Reflection::HasManyReflection>
reflection.association_primary_key
#=> "id"
```
Protocol Buffers v26.0 の破壊的変更

# protobuf v26.0 と protobuf-java v4.26.0

protobuf v26.0 が 2024/03/14 にリリースされましたが、Java, PHP, C++, Ruby, Python には破壊的変更が含まれています。

https://github.com/protocolbuffers/protobuf/releases/tag/v26.0

他の言語は詳しく分かりませんが、Java ではかなり大きな変更が入っており、[protobuf-java](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java) のメジャーバージョンが上がっていて v4.x となっています。(マイナーバージョンは、protobuf のバージョンと同期しています)

大きな問題点は、protoc v26 以降でコンパイルされたファイルは、protobuf-java v3.25 以下ではコンパイル・動作できず、v4.26 以降を利用する必要がある点です。

速報的に、Java でどう対処すれば良いかを書いておきます。

## コンパイル時のエラー

コンパイル時にこんなエラーが出たら、それは protoc に対して protobuf-java のバージョンが古いからです。

```
エラー: パッケージcom.google.protobuf.RuntimeVersionは存在しません
      com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
```
```
エラー: シンボルを見つけられません
    com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
                       ^
  シンボル:   クラス RuntimeVersion
  場所: パッケージ com.google.protobuf
```
```
エラー: シンボルを見つけられません
    if (!com.google.protobuf.GeneratedMessage.isStringEmpty(referenceId_)) {
                                             ^
  シンボル:   メソッド isStringEmpty(Object)
  場所: クラス GeneratedMessage

```
```
エラー: クラス com.google.protobuf.GeneratedMessage.Builder<BuilderType>のメソッド parseUnknownFieldは指定された型に適用できません。
              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                        ^
  期待値: CodedInputStream,com.google.protobuf.UnknownFieldSet.Builder,ExtensionRegistryLite,int
  検出値:    CodedInputStream,ExtensionRegistryLite,int
  理由: 実引数リストと仮引数リストの長さが異なります
  BuilderTypeが型変数の場合:
    クラス com.google.protobuf.GeneratedMessage.Builderで宣言されているBuilderType extends com.google.protobuf.GeneratedMessage.Builder<BuilderType>
```

## 対処方法

`.proto` をコンパイルする protoc と、protobuf-java のバージョンが違うことにより発生する問題なので、両方のバージョンを互換性のあるバージョンに合わせれば問題ありません。

ツールによっては、protoc を常に最新版で利用するようになっていたり、`brew upgrade` した途端にローカルの protoc が上がってしまったとか、のような状況で問題が発生することでしょう。

基本的には、以下のどちらかの方法を取ることになります。

### protoc のバージョンを固定する

当面の間は、ライブラリの依存関係等もあるので protoc を v25 系以下で動かしたいところです。

どのように protoc を利用しているかによりますが、protobuf-gradle-plugin では以下のようにバージョンが固定できます。

https://github.com/google/protobuf-gradle-plugin?tab=readme-ov-file#locate-external-executables

```groovy
protobuf {
  ...
  // Configure the protoc executable
  protoc {
    // Download from repositories
    artifact = 'com.google.protobuf:protoc:3.25.1'
  }
  ...
}
```

[buf](https://buf.build/) を使っている場合でも、`buf.gen.yaml` に以下のようにバージョンを指定することができます。

https://buf.build/docs/configuration/v1/buf-gen-yaml#plugins


```yaml
version: v1
plugins:
  - plugin: buf.build/protocolbuffers/java:v25.1
    out: java
  - plugin: buf.build/protocolbuffers/kotlin:v25.1
    out: kotlin
```

### protobuf-java バージョンを上げる

protobuf-java (`com.google.protobuf:protobuf-java`) を v4.26 以降に上げれば、protoc も v26.0 以降を使うことができます。

ただし、リリース直後の現在では protobuf に依存する他のライブラリも v4.26 以降に対応していない可能性があるので、注意。

将来的には、両方 v26 以降を利用できる環境を構築するべきでしょう。

## まとめ

gRPC とかで、コンパイル済みのクライアントライブラリを jar にして共有 or maven publish しているとかの場合、protobuf に今回のような破壊的変更が加わると大変そう。
UnrealEngineのVRTemplateでQuestLink切断、復帰後に継続してプレイできるようにする

UnrealEngineのVRTemplateにおいてQuestLinkを使ってMetaQuestのヘッドセットでプレイする場合に、QuestLinkが切断されると復帰した時点でアプリが終了してしまいます。
これをQuestLink復帰後にVRで再びプレイできるようにしてみたのでその内容を記録しておきます。

# 試した環境

Windows11
UnrealEngine5.3.2
QuestPro + QuestLink

# 対応した内容

## VRTemplateの作成

UnrealProjectBrowserでGAMESからVirtual Realityを選択してVRTemplateのプロジェクトを作成します。

## アプリが終了しないようにする

以下を実行してQuestLink復帰時にアプリが終了しないようにします。
ただ、この対応だけだと復帰後にHMDにはプレイ映像は映らず操作ができない状態になります。

Content/VRTemplate/Blueprints/VRPawnを編集してBeginPlay時にExecuteCommandで以下を実行しておくようにします
```
xr.OpenXRExitAppOnRuntimeDrivenSessionExit false
```

![2024-03-15_11h53_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16768/480fcf1a-9b98-da26-bbf2-958ee9c9d53e.png)

## VRに復帰できるようにする

以下の対応をしてHMDで映像が映って操作できる状態に復帰します。

Content/VRTemplate/Blueprints/VRPawnを編集してVRNotificationsコンポーネントを追加しHMDReconectedDelegateでEnableHMDノードをEnable引数にチェックを入れて実行するようにします

![2024-03-15_11h51_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16768/e5c9f2e3-0883-0e7e-5fb1-f57dc02d639e.png)

# 対応後の動作確認

以下の手順を実行します。

1. WindowsビルドしてパッケージングしたVRTemplateを実行する
1. MetaQuestProからUSBケーブルの線を抜く
1. USBケーブルを再びさしてメニューなどからQuestLinkを有効にする

本来だとこの後アプリが終了してしまうのですが、アプリが終了せずにMetaQuestProでVRTemplateをプレイできます。
AIチャットの機能とメカニズム

February 1, 2024 / [default](https://www.zonedelhippo.com/post_category/default)

AIチャットは、人工知能技術を基にしたコミュニケーションツールです。このツールは、自然言語処理（NLP）と機械学習（ML）の原理を利用して、人間のような対話を実現します。
## 基本原理
AIチャットは、大量のテキストデータを分析し、言語のパターンを学習します。この学習プロセスは、機械学習と呼ばれ、特定のアルゴリズムを用いて行われます。学習したデータを基に、AIは新しい質問や文に対して適切な回答を生成します。

## 機能と応用
•	自動応答: AIチャットは、ユーザーからの質問に対して即時に回答を提供します。
•	多言語対応: 多くのAIチャットツールは、複数の言語に対応しており、国際的なコミュニケーションに利用できます。
•	カスタマイズ性: ビジネスや個人のニーズに合わせて、対話スタイルや回答の内容をカスタマイズできます。

## 技術的側面
AIチャットは、主に次の技術で構成されています。
•	自然言語処理（NLP）: 言語の意味を解析し、理解する技術です。
•	機械学習（ML）: データから学習し、改善する技術です。

![crushon AI](https://i.ibb.co/Sv62dpj/ai1.jpg)

## 応用事例
AIチャットは、カスタマーサポート、教育、エンターテイメントなど、様々な分野で応用されています。

## パフォーマンスと効率
AIチャットのパフォーマンスは、使用するデータとアルゴリズムに大きく依存します。一般に、より多くのデータと高度なアルゴリズムを使用すると、応答の質と効率が向上します。しかし、これには高いコンピューティングパワーが必要で、結果としてコストが増加する可能性があります。

## コストと予算
AIチャットシステムの導入コストは、選択する技術と規模によって異なります。小規模なものでは比較的低コストで導入できますが、大規模で高度なシステムでは、サーバーや維持費などの追加コストが発生します。

## 将来の展望
[AIチャット](https://crushon.ai/)技術は今後も進化し続けるでしょう。特に、感情を認識し理解する能力の向上や、より自然で人間らしい対話の実現が期待されています。
インターフェースと継承の位置付けの違い

（Unity 上での C# で考えているので、ほかの言語・環境だと違うかも？）

> 電源プラグやUSBケーブルを見せるのが手っ取り早いかもしれません。
> 色々な形の端子があるとややこしいから、これに揃えるんだぞとか。
@radian-jp 2020-09-10 11:43（抜粋）
https://qiita.com/yutorisan/items/d28386f168f2f3ab166d#comment-d2d4657a033d99b6e65d

> 一般的に、インターフェースなどのオブジェクト指向をわかりにくくしている原因は包丁でくぎを打っているような内容が部分的に含まれているためではないかということに気づきました。
@J_Cotan(J COTAN) 2020-09-24 09:12（抜粋）
https://qiita.com/yutorisan/items/d28386f168f2f3ab166d#comment-233a43235d55ea91823b

> なにができるかで議論すると、間違った使い方をしてしまう危険があります。
@J_Cotan(J COTAN) 2020-09-26 07:58（抜粋）
https://qiita.com/yutorisan/items/d28386f168f2f3ab166d#comment-cd299d16e1d37bfd5a9a

> 抽象クラスという名前は極めて悪質であるように思う。ここまで読んでくれたなら、そして、継承に苦しめられた人ならわかってくれると思うのだが、抽象クラスは往々にして具象を含むのだ。
id:u_osusi  2022-06-29（抜粋）
https://nigiri.hatenablog.com/entry/2022/06/29/233247

以上を踏まえ、以下の理解をしている。

# abstract class：全国向けの自販機（の中身）

たぶん、日本語で「抽象」と捉えると実態とずれる。実際には、具体クラスとの対比的な概念として「ざっくりした」クラスというのが英語圏での認識だったりしないだろうか？それなら具体的な要素が入り込む理由も分かる。ほとんどの国・地域で使う機能・機構は、（法的な理由による「おま国」やインフラの問題で、たとえ余分なものがあったとしても）製造コストの観点から共通化したいところが出てくる。

# concrete class：ローカル仕様の自販機（の中身）

全国向けの自販機を改造したもの。元々付いている機構を取っ払って、内部を完全に別物にすることもあるし（`override` した関数内で、`base.Something()` を書かず別の処理だけを書く）、動作を追加することもある（`base.Something()` を書いて、その前後に追加の処理を書く）。投入されたコインを分類する機構をヨーロッパ仕様のものと入れ替えたり、新紙幣に対応させるなど。

# interface：自販機のボタン、硬貨・紙幣の投入口、取り出し口、硬貨返却口、等

自販機の利用者は国・地域が違っても同じように使いたいし、製造者はそのニーズに合わせるよう要求される。もちろん、勝手に商品や代金などを盗まれないようにもしたい。

# まとめ

- 信頼すると決めた相手（大元の製造者や委託先など）に、内部処理をいじってもらう前提なら、抽象クラスを継承して具体クラスを書いてもらう実装にする。
- 信頼すると決められない相手（自販機の利用者・補充アルバイトなど）に、ひたすら使うことに専念してもらうなら、インターフェースを実装して、それに合わせてもらう。

インジェクションができるとか、テスタブルだとか機能的なことは、構造次第で、たぶんどっちでもできる。コードの変更容易性も、IDE の静的解析とか一括リネームとかでどうにかなったりする。

それよりも、どの立場の人間がコードを書くのか、という人間側の事情に合わせることが大事。関係者の規模や分担の仕方、流儀・スキルによって、**快適な** 構造は異なる。

取り扱うデータの入出力は、基本的にはインターフェースからの経路を考える。インターフェースがない or 機能不足なら（必要性・妥当性のある範囲で）、クラスのプロパティやメソッドなどを触る。

# 追記

この記事を書いたきっかけ：
> シングルトンへの直接のアクセスは、あらかじめ定めておいたごく少数の箇所からのみ行うようにします。そして他のコードからは、インタフェースを通じてアクセスするのです。
https://プログラマが知るべき97のこと.com/エッセイ/シングルトンパターンの誘惑に負けない/

これがどういうことか理解したかった。
WSL2のディスクイメージサイズを最適化する

# 概要

日常的にWSL2を使用していますが、ボリュームサイズが増えてきて仮想ディスクファイルサイズ90Gを超えてきたので最適化（圧縮）しようと考えました。

下記の記事、他にもいくつか情報が見つかりましたが、 `Optimize-VHD` コマンドが必要だが自分の環境に無いからどうする、的なケースがあるようです。

https://qiita.com/siruku6/items/c91a40d460095013540d


実際私の環境も該当コマンドは存在しませんでした。

# 環境

環境に依存する部分が大きいと思いますので、手元環境を示しておきます。（2024年3月15日時点）


-  Windows11 Pro バージョン
-  バージョン 23H2 (OSビルド 22631.3296)


# インストールする

Windowsの設定関連インターフェイスは従来の「コントロールパネル」から「設定」へどんどん移行・変化している最中という印象です。
今回は「コントロールパネル」から操作しました。


##  コントロールパネルを起動

スタートメニュー→検索ボックスへ「コントロール」と入力するとコントロールパネルが見つかりますので、クリックして起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/78821901-c068-dcc7-d1eb-51e077927181.png)

※検索文字列は `control` でも良いですし、「ファイル名を指定して実行」へ `control` を指定しても起動可能です

## Windowsの機能の有効化または無効化を起動

「プログラム」をクリック、「Windowsの機能の有効化または無効化」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/945974b5-ad27-753a-d48b-3d8177c97c70.png)

## 機能をインストール

「Windowsの機能」ダイアログボックス内の `Hyper-V`以下の機能をチェックしてインストールします。
再起動が必要でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53115/57f4cc6f-9f67-4a95-7c12-98e8d5653676.png)



## 実行

管理者としてPowerShellを起動します。


### 現状のファイルサイズを確認

```
PS > dir
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2024/03/15    11:34    97638154240 ext4.vhdx
```

### 最適化実行

プログレスバーが表示されました。1分未満ぐらいで完了しました。

```
PS > Optimize-VHD .\ext4.vhdx -Mode Full
```

### 結果確認

```
PS > dir
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2024/03/15    11:45    82635128832 ext4.vhdx
```


事前に不要なファイルは削除してありまして、15,003,025,408バイト減りました。

```
>>> (97638154240-82635128832)/1024**3
13.97265625
```
およそ14GB圧縮されたという感じでしょうか。

WSLも通常通り起動できることを確認し、完了です。
CodeCommitのリポジトリをremoteに追加する

普段はBackLogにあるGitリポジトリを使っています。
CodePipelineを使いたいのですが、BackLogのGitと連携しようとするとちょっと大変そうだったので、
CodeCommitでリポジトリを作って、remoteにCodeCommitのリポジトリを追加する際の手順です。

## 環境

AWSアカウントが複数あり、CodeCommitを設置したAWSアカウントには、普段Switchロールしてアクセスしています。AWS CLIにはAssumeRoleするプロファイル(profile1)が設定してあるという状況です。

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up.html

> フェデレーティッドアクセス、ID プロバイダー、または一時的な認証情報を使用して CodeCommit や AWS に接続している場合、または IAM ユーザーや、IAM ユーザーの Git 認証情報を設定しない場合は、次の 2 つの方法のいずれかで CodeCommit リポジトリへの接続を設定できます。
> 
> git-remote-codecommit をインストールして使用します (推奨)。
> AWS CLI に含まれる認証情報ヘルパーをインストールして使用します。

上記の説明によると方法は2つあるようですが、今回は推奨されている `git-remote-codecommit`のほうで行いました。

1. git-remote-codecommitをインストールする
1. git remote add deploy codecommit://profile1@myrepo-name
1. git push deploy main

ポイントは `codecommit://profile1@myrepo-name` で\<profile>@\<repo-name>の形で指定します。

どこかでプロファイル指定するんだろうけど、どこよ?!という感じでしたが、これで無事pushできました。
CloudWatch Logs出力設定エラー　解消方法

## ■発生事象
新規にRedisのスローログをCloudWatch Logsへ出力する設定を行ったところ、設定時にエラーは発生しなかったものの、ログのステータスが「Error」と表示され、CloudWatch Logsへの出力が確認できませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570295/9ecdd64f-9f7e-cc1f-8667-422ede5c7d92.png)
エラーの原因と解消方法について、記事に残したいと思います。

## ■原因
AWSでCloudWatch Logs出力設定を行う際、通常はAWS側で自動的に生成されるリソースポリシーにロググループ名が追加されます。
しかし、今回のケースでは、自動で生成されるポリシーの文字数制限（**5120文字**）を超過していたため、リソースポリシーにロググループ名が追加されず、CloudWatch Logsにログが出力されない状況でした。

なお、すべてのサービスが自動生成の対象ではありません。
以下のページを参照し、CloudWatch Logsの列にて「**[V1 アクセス許可]**」もしくは「**[V2 アクセス許可]**」と記載されているサービスが対象となります。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html

## ■リソースポリシー確認方法
CloudWatch logのリソースポリシーはAWSコンソールのIAMポリシーには表示されません。AWS CloudShellなどでAWS CLIを使用することで、確認することができます。
```bash
$ aws logs describe-resource-policies
```

## ■対処方法
文字数上限が近づくと、自動的にAWS側でポリシー内に「**/aws/vendedlogs/\***」を追加します。
そのため、「/aws/vendedlogs/」配下にロググループ名を指定することで、CloudWatch Logsへの出力が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570295/65083134-05cd-7752-b271-c49b0a5e29fc.png)

また、ロググループやリソースを削除した場合でも、リソースポリシーの記述は自動的には削除されません。
リソースポリシー内の記述をまとめるのも、対処として有効です。

## ■まとめ
CloudWatch Logsへのログ出力設定を行う際には、ポリシーの文字数制限を意識する必要があります。また、設定時にエラーが発生した場合は、AWS CLIを使用してリソースポリシーを確認し、対処を講じる必要があります。

本記事が少しでもお役に立てれば幸いです。