OmniAICreator/Qiita-1.07M huggingface dataset:
Workato：Lists by Workatoコネクタの廃止と、廃止への対応

# はじめに

Workatoから、2024/6/13に Lists by Workatoコネクタの廃止に関するアナウンスが発表されました。背景として、Variables by Workatoがリストをサポートしていることや、Repeat Whileのリリースのような、Lists by Workatoよりも高い利便性を持った機能の提供が挙げられます。

# 本件による影響

## 新規レシピ

今後作成するレシピ(2024/8/6以降に作成されるレシピ)において、Lists by Workatoコネクタが利用（追加）できなくなります

## 既存レシピ

**当面の間は影響ありません。Lists by Workatoコネクタを現在利用しているレシピは、廃止後も引き続きLists by Workatoが提供する機能を利用可能です。ですので、これに対するレシピ改修等の対応は不要です。**

ただし、List by Workatoが提供するアクションを削除してしまった場合は、List by Workatoのアクションが追加できなくなる可能性がありますので、ご注意ください。

※レシピのバージョンを戻す、他のレシピからコピーすることで復旧可能かもしれませんが、今後廃止される機能でもありますので、特段の理由が無ければ復旧してレガシーを継続するのではなく、新たな方法に移行されることをお勧めします。

# 代替方法

Lists by Workatoの各アクションは、以下の方法で代替が可能です。これからレシピを作成する方や、既存レシピの改修（List by Workatoからの移行）を検討される方はご参考ください。

## Accumlate items to list

Variables by Workatoコネクタで代替可能です。
なお、Accumlate items to listでは単体で値を蓄積することが出来ましたが、Variables by WorkatoではCreate listアクションで予めリストを準備する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/bb31965e-a0c7-537b-a53c-11adc82229dd.png)

## Create repeat helper list

Repeat whileを利用し、whileの条件にループ回数を指定することで代替可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7b99baf3-3254-4a2c-dfa6-1979829d13dd.png)

`for (i = 0; i <= 9; i++){}` のようなループ処理を行いたい場合は、次のように実装します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/84d20089-7d17-e574-cd0a-b359c1cf6f51.png)
バージョン管理とログ管理を楽にするサンプルコード

研究をしているときに`git`でバージョン管理をすることは少なくないと思います。

- 複数人で開発を行っている場合
- 同じファイル構造をローカルPCとリモートサーバーなど2箇所に保存し、実行する場所(サーバー・GPUなど)とコードを書く場所(PC)を分けて開発する場合

などでお世話になる機会が多く、`git`に足を向けて寝られないエンジニアがほとんどなのではないでしょうか。

ある日、筆者はこのようなケースにぶち当たりました。

- かなり前の学習モデルの動作確認をしようとしたが、モデル構造が以前と今では変更されており、どのバージョンまで戻せばいいのか分からない
- `nohup`実行したときに`nohup.out`のどの部分にログが残っているのか分からない

このとき、`git reset`や`git reflog`,`git revert`を駆使して頑張ってバージョンを戻すことも可能ですが、間違えて今のファイルを全部消してしまうリスクもありますし、元のバージョンに戻すのが面倒くさいケースもあります。

極論言えば、タイムスタンプ付きのログ用フォルダを用意して、そこに移動すれば元のファイルを実行できる、というような環境を作りたいと考えました。

たとえば`dataset`と`models`を外部からインポートしている場合、こうすれば当時の実行環境を再現できると思います。

- フォルダ構造
```
-root
    -models
        -model_hogehoge.py
    -datasets
        -dataset_hogehoge.py
    -main.py
    -logs
```

- コマンドライン、`main.py`の実行例
```cmd
.../root$ python main.py #実行コマンド
```

- `main.py`の書き方の例、このような形式で実行すると後で実行ログを振り返るのが楽ちんに。
```main.py
from models import model_hogehoge
from datasets import dataset_hogehoge

import shutil
import os
import sys
from datetime import datetime, UTC, timedelta

if __name__ == "__main__":
    utc_time = datetime.now(UTC)
    #タイムスタンプ
    execution_time_str = (utc_time + timedelta(hours=9)).strftime('%Y%m%d_%H%M')
    log_folder = f"./logs/{execution_time_str}"
    #タイムスタンプを基にログフォルダを作成
    os.makedirs(log_folder, exist_ok=True)
    print(f"logs saved to {log_folder}") #この行だけ普通に標準出力

    # stdoutとstderrをログファイルに出力
    # このとき、実行ファイル名("main.py")はsys.argv[0]に格納されている
    out_f = open(f"{log_folder}/{sys.argv[0]}.log","w",encoding="utf-8")
    sys.stdout = out_f
    sys.stderr = out_f

    # 実行ファイルをログフォルダにコピー
    new_path = shutil.copy(f"{sys.argv[0]}",log_folder)
    parent_directory = '.'

    # 別ディレクトリからmain.pyを走らせていた場合
    # ただし兄弟ディレクトリとか(`../`)のケースは想定してないので注意
    if '/' in sys.argv[0]:
        parent_directory = '/'.join(sys.argv[0].split('/')[:-1])

    # importが必要なモジュールも入れておく
    datasets_path = shutil.copytree(f"{parent_directory}/datasets",f"{log_folder}/datasets")
    models_path = shutil.copytree(f"{parent_directory}/models",f"{log_folder}/models")

    #### ここに実行したいことを書く ####

    out_f.close()
```

できれば外部モジュールからimportしたものを自動でlog_folderにコピってくれるものも作りたいけど、やり方が分からず断念。

もしやり方が分かれば追記します

※このコードを応用してログを保存する場合、gitと併用するならばgitignoreするのを忘れずに（2024/6/21追記）
[動画生成] LumaのDream Machineが凄すぎた（プロンプト付き）

# はじめに
ついに来ましたね！ Dream Machine。

つい先日までSoraの動画生成が話題になってましたが、競合となるサービスが登場！
しかもFreeプランがあって、生成された動画の精度がめちゃめちゃ高い、、

これは本格的に、アイデア勝負の時代に入ったようです！

これまでの経験を活かして動画を生成してみたので、共有しますね😃

# Luma とは
LumaLabsというカルフォルニアの会社で、NVIDIAも出資。
動画から3Dモデルを生成するAIを開発しています。

# Dream Machine とは
テキストと画像から、驚くほどリアルな高画質動画を瞬時に作成できるAIモデル。
動画データで直接学習されており、物理的に正確で一貫性があるとのこと。

今回は、テキストのみで検証してます。

# 利用方法
[Lumaのサイト]()にアクセスし、「Try Now」をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/79fd2f81-d9a2-05de-17bb-f71fc53fa4c6.png" width="90%" />

Googleでサインインします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/0c4af275-c2d7-f8dd-208a-d3d9c89b6cdf.png" width="90%" />

サインイン直後の画面。
プロンプトを入力して、「↑」ボタンをクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/72138bf2-7256-423a-f2da-a6114ad0b572.png" width="90%" />

動画生成が始まりました！
2分くらいかかります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/6ee9466a-9f96-7297-0763-dd76d0962352.png" width="90%" />

約2分後、動画の生成が完了！

# 生成された動画
GIFに変換してます。（低画質にしたので小さめ）
これが2分で生成できてしまうとは、とんでもなく凄いですね:no_mouth:

![watermarked_video0c58c8675365b4644a22363c63340a54e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/2931fbd4-3675-0f4a-96cf-aecd9345dbbc.gif)

# プロンプト
プロンプトも公開します！
```text
A Harajuku girl, bursting with cuteness, is the center of attention. Her skin is pale as porcelain, her hair a riot of vibrant colors, and her clothing a symphony of fashion-forward trends. The world around her is a kaleidoscope of dazzling hues, a perfect backdrop for her playful, adorable dance. This is a live-action Hollywood film, with ultra-high-definition 4K visuals that capture every detail of her whimsical energy and the vibrant world she inhabits. Each frame is a celebration of color, style, and youthful exuberance.
```

# 同じプロンプトで何度も生成してみる
- 1回目
![watermarked_video0c58c8675365b4644a22363c63340a54e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/04a1c9bd-5401-7c1a-26e6-8b34b0408136.gif)

- 2回目
![watermarked_video0e3dce0cbe5d642eca4c71cc3dcc586f6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/53cf8a84-b194-73ad-308c-77a9f36307c9.gif)

- 3回目
![watermarked_video05e2927a5b14e4b22be8b60717094a66a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/a6eef3ae-9bf2-2e08-32f0-50367fd1d642.gif)


- 4回目
![watermarked_video0527b452b6c01421c95abe00b3800723d.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/a6af9055-1b38-e518-089a-9ffb24d7c9b4.gif)


- 5回目
![watermarked_video0bfce020d59ea48139f3e904d4d6c430e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/44345ab1-41ce-c02c-77a3-eae505e05138.gif)


同じプロンプトでも様々なパターンがありますね。
しかし、コンセプトは統一されているようなので、おおよそプロンプト通りの動画が生成されました。
これらが全て2分で生成されているのが凄いですね。（プロンプトを工夫したら、もう少し再現性が高くなるかも）

# まとめ
今回は、LumaのDream Machineで動画を生成しました。
若干の崩れがあったり、再現性に課題が残りますが、じきに解決すると思います。

将来的には、台本やキャラクターの詳細情報があれば、動画だけでなく、音楽や音声も同時に作ってくれるようになるかもしれません。

まだまだ可能性を秘めている動画生成AI市場、これからが楽しみですね😃
2024 プロジェクトマネジメントdayレポート2（～攻めのＰＭに求められる思考・行動様式～）

# はじめに
今年のプロジェクトマネジメントのセミナーに参加してきたのでレポーティングしたいと思います。

前回分：https://qiita.com/mnoguchi/items/f86cc67ac752faa6bd4e


# 新時代を生き抜くＰＭ ～攻めのＰＭに求められる思考・行動様式～

## 本日お伝えしたいこと
現代の技術基盤が急速に変化する中、プロジェクトマネジメント（ＰＭ）の仕事内容も大きく変わろうとしています。本セミナーでは、今後のＰＭに求められる役割、スキル、意識改革について考察します。

## 目次
1. 社会を構成している基盤技術の急激変化
   - 1.1 イノベーションの最前線
   - 1.2 日本の現在地は？
   - 1.3 日本のＤＸの進展状況
   - 1.4 業界なき時代の競争戦略
   - 1.5 最高峰の頭脳が安価に手に入る
   - 1.6 ソフト開発のあらゆるフェーズを生成ＡＩが支援
   - 1.7 Ｓｉｅｒの役割変化
   - 1.8 「正解を出す力」に、もはや価値はない
2. 守りのPM vs 攻めのPM
   - 「守りのPM」の定義
   - 「攻めのPM」の定義
3. 攻めのPMに求められるマインドセット
4. Key Success Factor
5. 攻めのＰＭに求められる能力
6. 「自分らしさ」を定義する

## レポート

### 1. 社会を構成している基盤技術の急激変化

#### 1.1 イノベーションの最前線
イノベーションの最前線では、技術の進化が加速しています。新しい技術が次々と登場し、それに伴いビジネスモデルや業務プロセスも変化しています。

#### 1.2 日本の現在地は？
日本は技術革新の波に乗り遅れないよう取り組んでいますが、他国と比較してまだ改善の余地があります。DX（デジタルトランスフォーメーション）の進展状況を見ても、さらなる努力が必要です。

#### 1.3 日本のＤＸの進展状況
日本のDXは進展していますが、まだ遅れを取っている部分もあります。特に企業文化や組織の壁が障害となることが多いです。

#### 1.4 業界なき時代の競争戦略
業界の垣根が崩れつつある現代では、競争戦略も変化しています。異業種間での競争が激化し、従来のビジネスモデルが通用しなくなっています。

#### 1.5 最高峰の頭脳が安価に手に入る
クラウドソーシングやAIの発展により、高度な知識やスキルを持つ人材が安価に利用できるようになっています。

#### 1.6 ソフト開発のあらゆるフェーズを生成ＡＩが支援
生成AIは、ソフトウェア開発の各フェーズを支援する役割を果たし、生産性を大幅に向上させます。

#### 1.7 Ｓｉｅｒの役割変化
システムインテグレーター（Ｓｉｅｒ）の役割も変化しています。従来のシステム開発から、DX推進やビジネス変革の支援へとシフトしています。

#### 1.8 「正解を出す力」に、もはや価値はない
従来の「正解を出す力」だけではなく、変化する環境に適応し、新たな価値を創出する力が求められています。

### 2. 守りのPM vs 攻めのPM

#### 「守りのPM」の定義
顧客から提示された要求事項に基づき、特定の成果の達成に向けて、コスト、納期、品質を確実に達成するPM。階層型、統制型の組織で有効なマネジメント。

#### 「攻めのPM」の定義
顧客の潜在ニーズを理解し、問題を探し出し、顧客が事業目的を達成するための活動を推進するPM。ビジネスパートナーと深く連携し、ビジョンを提示しリーダーシップを発揮できること。「デジタルのもたらす新しいビジネス価値創出」をマネジメントできること。

### 3. 攻めのPMに求められるマインドセット

1. **お客様の最前線に立ち、デジタルビジネスを前へ進める**
   - 顧客の課題を解決するために積極的に関与し、ビジネスの最前線で行動します。

2. **顧客の要望通りにシステムを作るから、顧客の課題を解決するへ**
   - 顧客の要求を単に満たすのではなく、その背後にある課題を解決することに焦点を当てます。

### 4. Key Success Factor

1. **見て見ぬふりはしない。圧倒的当事者意識を持って動く**
   - 問題を見過ごさず、当事者意識を持って積極的に行動します。

2. **軽快なフットワークで企業・部署を横断する**
   - 迅速かつ柔軟に対応し、企業や部署を横断して活動します。

### 5. 攻めのＰＭに求められる能力

1. **問の設定力**
   - AIを「同僚」として活用し、人間としての視点を持ち続けること。

2. **決める力**
   - 意思決定は理性と感性の融合が重要です。

3. **リーダーシップ**
   - 変革を推進し、組織のビジョンを実現する能力。チームを鼓舞し、方向性を示す役割を担います。

4. **自分らしさに生きる力**
   - 自己認識を高め、自分に合ったリーダーシップスタイルを見つけることが重要です。

### 6. 「自分らしさ」を定義する

- **自信を持って、自分らしいＰＭを見つける旅へ**
  - 具体的な目標を設定し、コーチや信頼できる同僚と共に自己成長を図ります。

- **試して学ぶ**
  - 新しいリーダーシップの実践を試し、小さなプロジェクトを通じて能力を試します。

## 結論
新時代を生き抜くためのＰＭには、顧客の課題を解決し、新たなビジネス価値を創出する「攻めのＰＭ」が求められます。
これには、柔軟な思考と行動様式、リーダーシップ、自分らしさの発揮が不可欠です。
今回のセミナーで学んだことを実践に活かし、変化に対応できるＰＭとして成長していけたら良いと感じました。
文系比率が61.8%！？文系エンジニア増加の理由とは？

かつては「ITエンジニア＝理系の仕事」というイメージが強かったかもしれません。しかし近年、IT技術の進歩と社会の変化に伴い、文系出身者でもITエンジニアとして活躍できる時代が到来しています。

本記事ではエンジニアの筆者が、文系エンジニアが急増している理由や文系からエンジニアになる方法を詳しく解説します。IT業界に興味を持っている文系の方、キャリアチェンジを考えている方にとって、必読の内容です。ぜひ最後までご覧ください。

## 文系出身のエンジニアが急増している？
![Surge-in-humanities-engineers.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784196/b577dda4-cd80-02d0-be7c-bd7c72b5e197.jpeg)

従来エンジニアの世界は、理系出身者が主流でした。しかし近年の傾向として、文系出身者がIT業界に進出する例が目立ってきました。<strong>実際に2023年の大学新卒就職者データを見ると、理系出身者が占める割合は38.2%にとどまり、61.8%が文系出身者となっています。</strong>2013年の大学学部の新卒就職者には、理系出身者が55.1％を占めていたことから比較すると、大幅に文系出身エンジニアが増加したことが確認できます。

[>> ITエンジニアへの新卒就職者の推移](https://codezine.jp/article/detail/19189)

なぜ、こうした変化が起きているのでしょうか？その背景には、IT人材の慢性的な不足があります。政府の試算では、**2030年にはおよそ79万人のIT人材が不足する見込み**です。こうした状況を受け、IT企業は人材確保に苦労しています。そこで注目されたのが、文系出身者の活用なのです。

[>> 経済産業省：「IT人材需給に関する調査」](https://www.meti.go.jp/policy/it_policy/jinzai/houkokusyo.pdf)

## 文系出身エンジニアが増加している理由

![Why-the-number-of-engineers-with-liberal-arts-backgrounds-is-increasing.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784196/73c19e49-a1fc-69ca-54ff-540bb2b7ea70.jpeg)


理系人材は技術力や論理的思考・問題解決力において、文系にはない強みがあります。一方で文系人材が増えている要因として、以下のようなことが追い風となっていることが考えられます。

- ユーザー視点での設計開発
- 生成AIの登場により技術的なハードルが低くなってきている
- 文系の高いコミュニケーション能力が求められている

[>> 増加している理由の詳細はココから確認！](https://taishi-official.com/2024/06/12/2463/#toc3)

## 文系出身者がITエンジニアになるための方法
最後に文系出身者がエンジニアになるためのプログラミング学習法について紹介します。プログラミングは、以下の3STEPで学習するのがおすすめです。

- 【STEP1】Progateでプログラミング適性をみる
- 【STEP2】Udemyでより実践的な学習をする
- 【STEP3】プログラミングスクールに通い、エンジニアになる

[>> 各ステップの詳しい解説はコチラから！](https://taishi-official.com/2024/06/12/2463/#toc7)

## まとめ
今回はプログラミング初心者に向けて、おすすめのプログラミング言語の学習順序や逆におすすめできない言語、学習方法についてご紹介をいたしました。この記事を参考にプログラミングができる方、エンジニアとなる方が増えると嬉しく感じます。

### おまけ

https://qiita.com/taishi_will_be/items/70a8ce8938944286b487

https://taishi-official.com/first-engineering-career-change/

<strong>＼Follow me／</strong>

- X（旧Twitter）：https://x.com/taishi_it_blog
- Instagram：https://www.instagram.com/taishi_will_be/
- YouTube：https://www.youtube.com/@Engineer_ILLBE
- TikTok：https://www.tiktok.com/@taishi_will_be
- note：https://note.com/taishi_wii_be/

<br>

最後にいいねお願いします:thumbsup:
TypeScript で useRouteError を使用した際に詰まったところ


## 背景

React Router の[チュートリアル](https://reactrouter.com/en/main/start/tutorial)を TypeScript で試していたときに、
useRouteErrorを使用する[Handling Not Found Errors](https://reactrouter.com/en/main/start/tutorial#handling-not-found-errors)のところで TypeScript のエラーが発生して少し詰まったので、その解決方法を記載します。

## 前提条件

以下の環境を前提とします。

- React 18.2.0
- TypeScript 5.2.2
- react-router-dom 6.23.1

## useRouteError とは

React Routerを設定したプロジェクト内で、何かしらのエラーが throw されたときにレンダリングされる[errorElement](https://reactrouter.com/en/main/route/error-element#errorelement)内で、useRouteError を使用します。  
useRouteError を使用すると、throw されたエラー内容を取得することができます。例えば存在しないページにアクセスしたときは、NotFound のエラー情報が入ります。

## TypeScript のエラー内容

チュートリアルと同じように、useRouteError 経由で取得した error オブジェクトから status や statusText を使用すると、「'error''は 'unknown' 型です。」というエラーが出ます。
これは useRouteError が unknown 型を返していることが原因です。  

前述したようにプロジェクト内で発生した何かしらのエラー情報が useRouteError から返ってくるので、unknown 型が定義されているのは納得です。

```jsx
import { useRouteError } from "react-router-dom";

export default function ErrorPage() {
  const error = useRouteError();
  console.error(error);

  return (
    <div id="error-page">
      <h1>Oops!</h1>
      <p>Sorry, an unexpected error has occurred.</p>
      <p>
        <!-- 'error''は 'unknown' 型です。 -->
        <i>{error.statusText || error.message}</i>
      </p>
    </div>
  );
}
```

## 解決方法

このエラーの解決方法として、[isRouteErrorResponse](https://reactrouter.com/en/main/utils/is-route-error-response) 関数を使用して型の絞り込みを行います。
isRouteErrorResponse の内部では、引数として受け取った error オブジェクトが以下のような ErrorResponse の型と一致するかを判定してくれます。

```typescript
export type ErrorResponse = {
  status: number;
  statusText: string;
  data: any;
};
```

これを利用して、以下のように型の絞り込みを行うと、TypeScript エラーを回避できます。

```jsx
import { useRouteError, isRouteErrorResponse } from "react-router-dom";

export default function ErrorPage() {
  const error = useRouteError();
  console.error(error);

  return (
    <div id="error-page">
      <h1>Oops!</h1>
      <p>Sorry, an unexpected error has occurred.</p>
      {isRouteErrorResponse(error) && (
        <p>
          <i>{error.statusText || error.message}</i>
        </p>
      )}
    </div>
  );
}
```

## 参考文献

- [What's the correct type for error in useRouteError() from react-router-dom?](https://stackoverflow.com/questions/75944820/whats-the-correct-type-for-error-in-userouteerror-from-react-router-dom)
- [useRouteError](https://reactrouter.com/en/main/hooks/use-route-error)
- [isRouteErrorResponse](https://reactrouter.com/en/main/utils/is-route-error-response)
Reactの開発環境をDockerで構築してみた

# はじめに
Reactを使う機会が今後増えそうなので、dockerで開発環境構築できるように調べてみました。

# Reactアプリケーションの作成

`Dockerfile`を記述します。

```Dockerfile
FROM node:latest

WORKDIR /app
```
`docker-compose.yml`を記述します。

```docker-compose.yml
services:
  app:
    build: .
    command: npm start
    volumes:
      - .:/app
    ports:
      - 3000:3000
```

yarnを使う場合は
```docker-compose.yml
services:
  app:
    build: .
    command: yarn start
    volumes:
      - .:/app
    ports:
      - 3000:3000
```

:::note
`command`を書かなくても動きそうと思うかもしれませんが、`docker compose run` だと書かれているポート番号が無視されてしまうので書いた方が楽だと思います
:::

この状態で`Dockerfile`と`docker-compose.yml`が置いてあるディレクトリで以下のコマンドを打って、イメージを作成します。
```
docker compose build
```

そして、reactのアプリケーションを作成します。

```
docker compose run --rm app sh -c "npx create-react-app yourproject"
```

yarnコマンドで行う場合は

```
docker compose run --rm app sh -c "yarn create react-app yourproject"
```
にしてください

>--rm:コマンド実行後にコンテナを削除します
sh -c:シェルを利用して、コマンドを実行させます。

ターミナルに
```
We suggest that you begin by typing:

  cd helloapp
  npm start

Happy hacking!
```
が出てきて、

lsコマンドで以下のようになったら大丈夫です。
```
ls
Dockerfile		docker-compose.yml	yourproject
```

# reactアプリの起動
`Dockerfile`を修正します。

```Dockerfile
FROM node:latest

WORKDIR /app/yourproject

COPY yourproject/package.json ./

RUN npm install

COPY ./yourproject .

```

yarnは
```Dockerfile
FROM node:latest

WORKDIR /app/yourproject

COPY ./yourproject/package.json ./

RUN yarn install

COPY ./yourproject .


```
Dockerfileの修正が終わったら、
```
docker compose up --build
```

でイメージの作成、コンテナの立ち上げを行います。


以下のアドレスに参照して
http://localhost:3000
以下の画像のようになれば、構築完了です。
![スクリーンショット 2024-06-14 17.15.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/9be44eae-8067-3288-6a53-cda311d76df5.png)

# おまけ
HelloReact!を表示させてみようと思います。

`HelloReact.jsx`を作成して記述します。

```HelloReact.jsx
const HelloWorld = () => {
    return(
        <h1>HelloReact!</h1>
    )
}

export default HelloWorld
```

`App.js`を以下のように修正します。
```App.js
import logo from './logo.svg';
import './App.css';
import HelloWorld from "./HelloWorld";

function App() {
  return (
    <div className="App">

      <body>
        <HelloWorld />
      </body>

    </div>
  );
}

export default App;

```
以下のURLで確認すると

http://localhost:3000


![スクリーンショット 2024-06-14 17.35.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/04fdcee3-24b7-e69d-f9ec-65fa4ca8b1aa.png)
2024 プロジェクトマネジメントdayレポート1（DX? AI? まず押さえておきたい原則とは何かを考える）

# はじめに
今年のプロジェクトマネジメントのセミナーに参加してきたのでレポーティングしたいと思います。


# テーマ
DX? AI? まず押さえておきたい原則とは何かを考える

## 目次
1. 上手くいかないDX vs 上手くいっているDX
2. 大きな変化を導入する時に不可欠なこと
3. PMIの提唱しているもの--変革に有効な枠組み
4. 展開に必要な人材とは?
5. で、どうする?
6. どうすれば、『良いチーム』が作れるか？

## 1. 上手くいかないDX vs 上手くいっているDX
DX（デジタルトランスフォーメーション）の成功と失敗の要因について議論が行われました。
上手くいかないDXの原因としては、以下の点が挙げられました：

- ポートフォリオマネジメントができる人材の不足
- プロセス改善のみでは売上が伸びないこと
- コストカットや合理化だけでは限界があること

一方、成功するDXには次の要素が重要です：

- 生産性を上げること
- 顧客中心のアプローチ
- 市場動向と競合分析
- 設備投資への積極的な投資

## 2. 大きな変化を導入する時に不可欠なこと
大きな変化を導入する際には、以下の要素が不可欠です：

- 適切な実績のあるマネジメントフレームワークの適用
- フレームワークを実践できる人材の育成
- 個人が小規模で実践することで経験を積み、その経験を基にビジネスへの適用を目指す

## 3. PMIの提唱しているもの--変革に有効な枠組み
PMI（プロジェクトマネジメント協会）の提唱するフレームワークは、変革を効果的に進めるためのツールとして有用です。
しかし、フレームワークを適用するだけでは成功は保証されません。
実践と経験の積み重ねが重要であり、失敗から学びつつ進めることが求められます。

## 4. 展開に必要な人材とは?
AI時代における優秀な人材の定義が変化しています。これまでのように知識量や高学歴だけで優秀さを証明することはできません。以下の要素が重要です：

- 知識を実際の成果に結びつける能力
- 実践を通じて結果を出せる能力
- 新しいことに挑戦できる積極性

## 5. で、どうする?
自らの役割と責任を認識し、実行に移すことが重要です。PMCDフレームワークに基づき、自己覚醒（自己認識と役割行動）が必要です。上流工程の重要性が増しており、小規模チームでの実践が求められます。戦略は状況に応じて変化しなければならず、その変化に対応することが鍵です。

## 6. どうすれば、『良いチーム』が作れるか？
良いチームを作るためには、以下の要素が重要です：

- 少人数でも多様なスキルを持つメンバーを集める
- 異なる価値観や経験を持ちつつ、同じ目標に向かって情熱を持つ人々を集める
- 互いへの敬意、公平性、責任感、誠実さを持つこと
- リーダーは自己認識を高め、自分なりのスタイルでチームを導くこと

リーダーシップは模倣ではなく、自分に合ったやり方で発揮することが求められます。自分の強みを理解し、それを無理なく発揮できることが成功の鍵です。

## 結論
このセミナーでは、DXやAIの導入における原則と具体的な手法について詳しく学ぶことができました。成功するためには適切なフレームワークの適用と実践、経験の積み重ねが不可欠であり、チーム全体の力を引き出すリーダーシップが重要です。
これらの教訓を活かし、プロジェクトマネジメントをより効果的に行うことが求められます。
after_saveでsidekiqを叩いてもデータが存在しない

# はじめに

E2Eがコケて原因が謎だったところについてまとめておきます

# 問題

ユーザーをDBに保存すると、Sidekiqのジョブを叩くような実装をしました

```rb:user.rb
  after_save TriggerIndexingCallbacks
```

しかしジョブでは作成したユーザーが存在しませんでした

# 解決方法

```rb:user.rb
  after_commit TriggerIndexingCallbacks
```

`after_commit`にすることでDBに保存してから実行されるようになりました
保存前に動いていたのが原因でした

# おわりに

初めてafter_commitというものを使いました
そもそも知らなかったです
Stripe カスタマーポータルの設定ページはここ

Stripe Customer portal の設定ページは[ここ](https://dashboard.stripe.com/settings/billing/portal)
いつも何処にあるのかわからなくなるのでメモ

:::note info
右上設定icon -> Setting -> Billing -> Customer Portal タブ
:::

サブスクのキャンセル設置
![スクリーンショット 2024-06-14 11.29.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47236/41b2dd51-5418-e82e-866e-b9642d109b28.png)

サブスクのプラン変更・複数プラン
![スクリーンショット 2024-06-14 11.34.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47236/7ffa8057-251e-521f-d2d2-b3bc200aa22f.png)
PowerShellのスクリプト実行ポリシーについて

## スクリプト実行ポリシーとは
<br>
皆さんはターミナルでこんな表示を見たことがあるだろうか

```
このシステムではスクリプトの実行が無効になっているため、
ファイル C:\Users\oooo\WindowsPowerShell\profile.ps1
を読み込むことができません。
```

私はこのエラーのせいで全然ファイルを実行することができず環境構築すらままならない状況だった。これはPowerShellがいろいろ制限していたことに起因する。したがってcondaなどを実行できなかった。

ではスクリプト実行ポリシーにはどんなものがあるのだろうか。
以下はgpt4oが教えてくれたポリシーの種類である
## スクリプト実行ポリシーの種類
__Restricted__:
概要: すべてのスクリプトの実行を禁止します。PowerShellのコマンドレットをインタラクティブに使用することはできますが、スクリプトファイル（.ps1ファイル）の実行はできません。
制限内容: スクリプトの実行が完全に禁止されます。
<br>
__AllSigned__:
概要: 実行されるすべてのスクリプトが信頼された発行元によって署名されている必要があります。これはローカルのスクリプトも含みます。
制限内容: 信頼されていないスクリプトや署名されていないスクリプトは実行できません。
<br>
__RemoteSigned__:
概要: インターネットからダウンロードされたすべてのスクリプトは署名されている必要があります。ローカルで作成したスクリプトは署名されていなくても実行できます。
制限内容: インターネットからダウンロードされた未署名のスクリプトは実行できません。
<br>
__Unrestricted__:
概要: すべてのスクリプトを実行できます。ただし、インターネットからダウンロードされたスクリプトを初めて実行する場合は警告が表示されます。
制限内容: インターネットからダウンロードされたスクリプトを実行する際に警告が表示されますが、実行は可能です。
<br>
__Bypass__:
概要: すべてのスクリプトを無制限に実行できます。警告も表示されません。
制限内容: なし（すべてのスクリプトを実行可能）。
<br>
__Undefined__:
概要: ポリシーが定義されていないことを意味します。通常、親スコープのポリシーが適用されます。
制限内容: 親スコープのポリシーに依存します。
***

<br>
結構いろいろある。
次に今の状態を知る必要がある。以下のコマンドで知る。

```
Get-ExecutionPolicy
```

これで私は　__Restricted__　と出力されたため、オールブロック状態である。
そこで任意のポリシーに変更できるコマンドを打つ。今回は用意したスクリプトを実行できればいいので　__RemoteSigned__　にした。
```
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

```

そしてターミナルを新しく作成すると、、、
警告消えたー！！！
IBM i Services Directory : SYSTOOLS.Defective_PTF_Currency ビュー　適用済みPTFの更新有無チェック

## 概要
■ビュー名：SYSTOOLS.Defective_PTF_Currency
■カテゴリ：PTFサービス
■サポート：IBM i 7.4以降
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-defective-ptf-currency-view

コマンドを実行するIBM i の適用済みPTFとインターネット上のIBM公式サイトの最新PTF情報を比較します。もし、適用済みPTFの置き換えPTFがあった場合、そのPTF番号を表示します。

DSPPTFコマンドとインターネット上のPTF情報を検索するプログラムを作成し、その結果を突き合わせることで同様な機能を実装できます。・・・がそんなことする必要はないですね笑。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/909e27bf-b9fc-cf18-653c-7de761d076f7.png)

### サンプルコード
```
SELECT * FROM SYSTOOLS.DEFECTIVE_PTF_CURRENCY; 
```
実行例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/66df748a-d5eb-9f98-3e03-57b2743df799.png)

上手の場合、システムに適用済みのSI84240について、置換されたPTF SJ00269が公開済みであることがわかります。
【OutSystems】Tableのソート実装

## この記事を書くきっかけ
OutSystemsのReactiveWebでは2通りの方法で簡単にテーブルを実装することができる。
ただし、片方の方法で実装したテーブルにはソートが実装されているように見えるが実際には動作しないという罠が存在する。
その方法でテーブルを実装してしまい、ソートができないことに気が付かなかったということがあった。

## この記事のゴール
ScreenにTableを配置してEntityを結びつけた場合、そのままではソートのUIがあるにもかかわらずソートが実装されていない状態になる。
そこからソートの処理を実装し、UIの期待通りに動作させる。

## 環境
OutSystems Service Studio 11
Reactive Web App

## 使用するEntity
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/10369ea8-3b40-a461-ddc6-3dad86e66478.png)

## 画面の実装
テーブルの作成方法には主に二つのパターンがある。

1. ScreenにEntityを配置してTableを作成
1. ScreanにTableを配置してEntityを紐づける

前者の方法で実装した場合、0件の場合のメッセージ表示やページネーション、ソートが実装される。
ところが後者で実装した場合、それらが実装されない。

ここでは当時を再現するため、後者で実装する。

### ソートのUIの確認
上記の方法でTableを作成するとヘッダのすべての項目に▲▼が表示される。また、クリックしてもソートされない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/8998631b-7243-9246-1013-cdb6147f4ff4.png)

ソートを実装するヘッダーセルにはSortAttributeが設定されていることを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/634f717a-c14f-8192-fc88-19a99edfc121.png)


### ソートを実装しない項目への対応
ここではDescriptionにソートを実装する必要がないので、DescriptionのヘッダーセルのSortAttributeの空にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/68c370cb-4c6e-7f33-2bcd-127e92705fd7.png)


概要から▲▼が消えたことを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/443d080b-8271-7eab-8e1c-5837cf8dd308.png)


### ソートの実装
TableウィジェットのPropertiesを確認する。EventsのOnSortに何も設定されていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/37143df0-7a2a-f383-9dbd-e4c73a2534e4.png)

ここに、「New On Sort Client Action」を設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/f80c1bdc-d93b-54d0-ed68-6cbfec6384d2.png)

すると、該当のLocalVariableに「TableSort」「StartIndex」「MaxRecords」が追加され、ScreenActionに「OnSort」が追加される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796185/61073089-f289-a467-07be-3c155da93f43.png)

これをPublishして動作を確認する。

## おわりに
簡単に実装できるが、残念ながらソートのたびにAggregateでデータ取得が発生してしまう。これはEntityをScreenに配置してTableを実装する場合も同じである。
データの再取得なしでソートする方法についても今後考えてみたい。

本記事のようなケースはめったに発生しないと思われるが、備忘のため記すこととした。
Optunaの使い方備忘録

# はじめに
ハイパラセッティング，沼ですよね．

Optunaとは，Pythonで機械学習をするときに使う自動ハイパラチューニングライブラリです．
ハイパラの探索空間を設定してあげると，いい感じに探索していい感じのハイパラを見つけてきてくれます．総当たりではないので，最適解ではないです．

この記事は，optunaの使い方の ~~(自分用)~~ 備忘録です．optuna解説記事はググれば多分出てきますが，いろんな解説があった方がいいでしょう．

昔は大学院生降下法(GSD: graduate student descent)，つまり大学院生に手作業でハイパラを探索させる手法が一般的だったようですが，時代はoptunaです．

# 全体的な構造

```
pip install optuna
```
- objective関数を作り，最小化・最大化したいscoreを返す
- objectiveをoptunaに渡して最適化を実行すると，ハイパラが最適化されて帰ってくる

簡単ですね！
学習は当然遅いので，探索結果のハイパラはjsonにでもdumpしましょう．

```python
# 適当コード
import optuna
def objective(trial):
    # 任意のモデルに使用するパラメータと，その探索空間
    lr = trial.suggest_loguniform('lr', 0.1, 0.001)
    n_hidden = trial.suggest_int('n_hidden', 128, 256)
    # 任意のモデル
    model = Sample_model(lr, n_hidden)
    # trainデータで学習し，validateデータで推論してスコアを返す．
    # 学習方法自体はこの記事では解説しない．
    score = train_step(model)
    return score

# スコアを最小化するか最大化するかは選べる
study = optuna.create_study(direction='minimize')
# n_trialsは探索回数，増やせばより最適なハイパラが出る
study.optimize(objective, n_trials=100)

print(f'Best value: {study.best_value}')
print(f'Best param: {study.best_params}')
```

学習するための関数を`train_step`としています．
ここで推論結果からスコアを計算して返しますが，精度以外にもAUCやF1，任意の評価指標を自由に設定できます．

## ハイパラ探索空間の指定

リファレンス
https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.Trial.html
色々指定できます．候補だけでなく範囲でも指定できるので，より最適なパラメータが見つかる……はず

`suggest_categorical(name, [option1, option2])`: 選択肢から選ぶ．数字だけでなく，評価指標やモデルの選択にも使える
`suggest_discrete_uniform(name, low, high, q)`: 離散値．偶数だけ探索，など
`suggest_float(name, low, high, *[, step, log])`: 小数．uniformの方が人気？
`suggest_int(name, low, high, *[, step, log])`: 整数．
`suggest_loguniform(name, low, high)`: 連続値．対数として探索するので，learning_rate等に良い
`suggest_uniform(name, low, high)`: 連続値．線形に探索
Openpyxl: Cell の結合 （汎用版）

こちらのプログラムを汎用的に使えるように改造しました。
[Openpyxl: Cell の結合](https://qiita.com/ekzemplaro/items/9996dc355cc957c1dd61)

## プログラム

```py:merge_cells.py
#! /usr/bin/python
# ---------------------------------------------------------------
#	merge_cells.py
#
#					Jun/14/2024
# ---------------------------------------------------------------
import sys
import openpyxl
from openpyxl.styles import Alignment

# ---------------------------------------------------------------
# [4-6]:
def column_analize(ws,column):
	print("ws.max_row = ",ws.max_row)
	print("column = ",column)
	istart = []
	iend = []
	nn = 0
	icount = 1
	for row in ws:
		if row[column].value != None:
#			print(row[column].value)
			istart.append(icount)
			if 0 < nn:
				iend.append(icount - 1)
			nn += 1
#		else:
#			print("None") 

		icount += 1
#
	iend.append(icount-1)
#
	print(istart)
	print(iend)
#
	return istart,iend
# ---------------------------------------------------------------
# [4]:
def column_proc(column_in):
	istart, iend = column_analize(ws,column_in - 1)
	for it in range(len(istart)):
		ws.merge_cells(start_row=istart[it],
		start_column=column_in, end_row=iend[it], end_column=column_in)
		ws.cell(istart[it], column_in).alignment \
			= Alignment(horizontal='center',vertical='center')
# ---------------------------------------------------------------
xlsx_in=sys.argv[1]
#
sys.stderr.write("xlsx_in = %s\n" % xlsx_in)
wb = openpyxl.load_workbook(filename=xlsx_in)
ws = wb.worksheets[0]
#
column_proc(1)
column_proc(2)
column_proc(3)
#
wb.save(xlsx_in)
# ---------------------------------------------------------------
```

## 実行方法

```bash
./merge_cells.py ex01.xlsx
```
[備忘録]　読んだネットの記事 (FA業界) ver.4

# 備忘録

"出荷前製品の数をAIが自動算出　物流現場の作業時間を約30％減らすソリューション"
https://monoist.itmedia.co.jp/mn/articles/2406/13/news085.html

[備忘録]
- 荷待ちや荷役、出荷確認などにかかる平均作業時間を約31％削減
- IotやAIなどを用いて入出荷業務全体の可視化，省人化を実現するシステム
- カメラで撮影した画像をもとにAIが駐車場の在車判定を行う
- 製品出荷時の製品のカウント作業をAIによって省力化する
    - スマホで出荷タグのラベルを読み取って荷物の画像を撮影すると，ラベル情報や製品の点数などが自動算出，入力される


"印刷配線とRFIDの技術を活用した液漏れ検知システムの販売を開始"
https://monoist.itmedia.co.jp/mn/articles/2406/10/news072.html

[備忘録]
- 印刷配線とRFIDの技術を活用して液漏れ検知システムを開発
    - 特殊インキで電気回路を印刷したテープ状の検知部とRFID技術で構成されている
    - RFIDリーダーの電波で通電
    - 検知部の電気回路に水や油などが付着すると通電状況が変化し，その変化をRFIDタグが感知する
    - RFIDタグはRFIDリーダーからの電波で起動する

"カメラベースの触覚センサー付きロボットがシューマイや卵焼きを巧みに盛り付け"
https://monoist.itmedia.co.jp/mn/articles/2406/13/news095.html

[備忘録]
- 触覚センサーを用いて食品を把持している
    - シリコン製のハンドの表面に黒点が埋め込まれている
    - 対象を把持した時の黒点の動きを内部のカメラで捉え，外力などを画像処理で解析して触覚に変換
    - フィードバック制御でロボットを動作
    - ロボットにカバーを取り付けて異物混入を防止
Pythonでファイルが見つからない

Pythonを初心者の頃、以下のようなコードでファイルが見つからず悩んだ。
```file_not_found.py
with open("test.txt") as file:
    print(file.read())
```
VScode上でPythonファイルをディレクトリで開かずに、再生ボタンを押して実行していたことがこの問題の原因である。この場合、作業ディレクトリがPythonファイルの存在するディレクトリではない。Pythonファイルからみた相対パスで指定すると`FileNotFoundError: [Errno 2] No such file or directory: 'test.txt'`と注意されてしまう。

再生ボタンを押すだけで実行可能という利便性を持たせつつ、ファイルのパスを正しく指定する解決法を2つ示す。
## pythonファイルのパスから絶対パスをつくる
Pythonでは`__file__`からそのPythonファイル自体のパスが得られる。文字列の操作でもパスをつくることができるが、`os`や`pathlib`を使うと簡単にパスが作れる。`os`では文字列のままパスを操作し、`pathlib`ではPathオブジェクトを作ってから操作をしている。この場合、ファイルのパス自体は絶対パスになっているので、作業ディレクトリがPythonファイルのディレクトリと異なることが問題にならない。
```os_ver.py
import os

# Pythonファイルのあるディレクトリ
directory_str = os.path.join(__file__, os.pardir)
# test.txtの絶対パス
test_file_str = os.path.join(directory_str, "test.txt")

with open(test_file_str) as file:
    print(file.read())
```
```pathlib_ver.py
import pathlib

# Pythonファイルのあるディレクトリ
directory_path = pathlib.Path(__file__).parent
# test.txtの絶対パス
test_file_path = directory_path.joinpath("test.txt")

with open(test_file_path) as file:
    print(file.read())
```
## プログラム上で作業ディレクトリを変更する
`os.chdir`を使って、作業ディレクトリを変更することができる。
```chdir_ver.py
import os

# Pythonファイルのあるディレクトリ
directory_str = os.path.join(__file__, os.pardir)

os.chdir(directory_str)

with open("test.txt") as file:
    print(file.read())
```
:::note info
`opencv`など日本語のパスを受け付けない場合にも、作業ディレクトリを変えることで問題なく開くことができる（無論ファイル名はアルファベットである必要がある）。
:::
Python文法まとめ【dict型】

# はじめに
この記事では、Pythonの辞書型について説明します。

# dict型
```Python:
変数 = {} # 空の辞書
```
```Python:
変数 = {a:n1, b:n2, c:n3}
```
の形で、複数の要素を扱うことができます。
`{}` (波括弧)を用いて`,`で要素を区切ります。
各要素は、すべて`key:value`の組み合わせで実行されます。
`key`・`value`ともに変数や文字列を利用できます。

```Python:サンプル
menu = {'パスタ':600, 'ピザ':550, 'グラタン':800}
print(menu)
```
```:実行結果
{'パスタ': 600, 'ピザ': 550, 'グラタン': 800}
```
`key`には変数も利用できますが、
key同士や、代入されている値が重複する場合、
下記のように値が上書きされます。
```Python:サンプル
a = 7
b = 8
c = 7
x = {a:3, a:5, b:3, c:11}
print(x)
```
```:実行結果
{7: 11, 8: 3}
```

# おわり
お役に立てたら幸いです。
1年かけて基本情報を取った話

個人的「質はともかく継続する」7日目です。

# 1年かけて基本情報を取った話

qiitaを眺めていると、
「新人エンジニアが半年でAWSの資格を全部取った」
「未経験素人が1ヶ月で応用情報に受かった話」
という話が溢れています。

凄すぎないか？？？

取得するための計画を練って実行できる能力や、
学習能力の高さ、努力できる能力、ぜんぶ凄すぎる。

そんなすごい話ばかりだけど、
私は全然すごくなくて素人から基本情報を1年かけて取りました。
2回ほど受験して、1回目は落ちて、2回目にリベンジ成功。
そのときにどんな勉強をしていたのかを思い出して見ようと思います。
ちなみに、2012,3年頃の話で、まだエンジニアが人気職ではなかった頃のお話です。

## 取得しようと思った動機

当時、私は開発とは関係ないカスタマーサポートをしていました。
が、特にスキルも身につかない、しんどい、給料は手取りで12万とかの状態で、
このままではジリ貧だし、開発エンジニアになりたいなぁと考えていました。
当時、スマホがようやく普及してきて、アイフォンのアプリを開発すれば
日本に居ながら世界と戦える！という思いもあり、エンジニアになるべく
まずは基本情報を取得することにしました。

## 勉強方法

まずは過去問を買って、さらさらと眺めてみる。
そうすると、知識問題の午前と、応用問題の午後に分かれていました。
まずは知識問題の午前の対策を始めることにしました。
その後、午後の対策をしていく作戦です。
過去問と、午前問題、午後問題、予想問題、参考書を買い、
それを使っていくことにしました。

### 午前問題対策

これはもう、片っ端から問題集をやりました。
過去問に、午前用の問題集に、ひたすら問題を解いていきました。
もちろんいきなりは解けないので、
解説がしっかりとしている問題集を買って、
問題を読み、ちょっと考え、すぐに答えを読む。
理解しきれなかった問題は参考書をよみ、ノートに書き写す。
書き写した内容は通勤時間とかに読み直す。
過去問が終わったら、問題集を解き、
その後また過去問をやって、また問題集を解く。
それを3回くらい繰り返して行きました。

### 午後問題対策

午前問題が一周したら、午後問題にも取り組み始めました。
方法は同じで、ひたすら問題を解いて、
メモして、振り返って、また問題を解いて...を繰り返す。

### 勉強時間の確保

会社勤めの社会人にとって最大の問題は時間の確保です。
いつ勉強するのか？
平日は通勤・帰宅と、昼休に20分くらい時間をとって、
休日は午前1時間、午後1時間ほど勉強をしていました。

## 1回目の受験

そして1回目の受験です。
午前も午後も2周くらいはこなしていて、
試しにやってみた模擬試験もギリギリ合格ラインだったので、
「本番に強いはず！」と思い込みながら受験したところ、
午後問題はすごく手応えが有りました。
が、見事に落ちました。
午前問で。
理解するのは得意だけど記憶するのがすごく苦手なんです。。

当時はまだオフラインで、半年に1回の受験だったので、
また半年改めて勉強して受け直すことになりました。

## 2回目の受験まで

方向性は間違ってなさそうだったので、
やり方は変えずに続けていきました。
ただ午前問題は流石に同じ問題集を解きすぎると
解答の番号を記憶してしまったりするので、
使っていた問題集をさらに2周して、わからない問題が２割を切ったので
別の問題集を購入し、再び同じやり方で勉強していきました。
午後問題も同様です。

## そして合格

半年後、迎えた２回目の試験です。
今度は午前も午後も手応えがあり、ワクワクしていました。
自分の力を試せるっていうのは、ワクワクしてしまいます。
そして見事合格！！
地道で時間はかかりましたが、どうにか合格にたどり着けました。

## 思うこと

SNSをみて人を羨むのと同じように、
Qiitaやzennを見ると凄い人たちのすごい話に溢れています。
でも、別にそこを目指す必要もないし、
比較しても仕方がないと思うのです。
私は半年でAzureの資格を総ナメ出来ないし、
２ヶ月で応用情報も取れません。

でも、地道に学習して１年かけて基本情報を取ることはできた。
これからも皆を「凄いなぁ」と思いつつ、自分は自分のペースで学習を
地道に続けて行こうと思います。
経営幹部向け生成AIを活用したデータ戦略成功のための3要素

### はじめに
Databricksのイベント「Databricks Data + AI Summit 2024」の講演内容を日本語訳した記事となります。

本記事では、Robin Sutaraさんによる「経営幹部向け生成AIを活用したデータ戦略成功のための3要素」について記載いたします。

### 概要
生成AIが、人、プロセス、プラットフォームを通じて組織をどのように強化するかに焦点を当てます。また、ガバナンスを念頭に置いて戦略を策定することで、データドリブンな意思決定を可能にし、イノベーション、競争力、生産性を向上させる方法について説明します。

### 講演内容
#### 生成AI導入の影響
昨年、生成AIの導入が顧客に大きな影響を与え、データとAI戦略に対する反応が見られました。生成AIはデータ戦略、特にガバナンスに新たな複雑さをもたらしました。

#### データ戦略の基盤
1. **ビジョンとミッションの明確化**: 新しい技術が登場すると、組織はその技術のビジョンやミッションにどのように寄与するかを明確にする必要があります。Microsoftの例で言えば、初期のミッションが「すべてのデスクトップにPCを」という具体的な目標から、「すべての組織がより多くを達成できるように支援する」という広範なビジョンに進化しました。生成AIも同様に、組織のビジョンやミッションを再評価する機会となります。
2. **指導原則の設定**: 一貫した意思決定を行うために、組織全体での指導原則を明確にします。例えば、「データのコピーを最小限に抑える」という原則を設定すれば、すべての決定がその原則に基づいて行われることになります。これにより、組織全体でのコミットメントと理解が深まり、戦略の実行がスムーズに進むようになります。
3. **測定可能なメトリクスの設定**: KPIを選定し、それに基づいて行動を促します。データ品質の向上を促すメトリクスを設定し、その達成を追跡します。

#### 人と組織の構造
- データエンジニア、データサイエンティスト、データアナリストなどの役割を適切に配置し、効率的にデータの取り込みと分析を行います。
- 多様性を確保し、バイアスの認識と是正を行います。

#### プロセスの影響
- 生成AIの導入に伴い、既存のプロセスや新しいプロセスの変更が必要です。新しいポリシーやトレーニングを導入し、適切な管理を行います。

#### プラットフォームの考慮事項
- 複数のクラウドを使用する場合、その複雑さを管理し、データの統合やアーカイブ、オープンエコシステムの採用を考慮します。データブリックスのようなプラットフォームを使用して、オープンエコシステムを構築します。

#### まとめ
生成AIを成功させるためには、技術だけでなく、変革の基盤、人材、プロセス、プラットフォームの考慮が不可欠です。データブリックスは、オープンエコシステムを通じて、データ戦略と生成AIの取り組みをサポートします。

### Databricks Champion からのコメント
生成AIによる組織の強化を最大化していくために、経営層の視点から、ビジョンやミッション、原則、KIP等の企業理念から再構築していくことが求められていると感じます。
Openpyxl: Cell の結合

    セルを結合するサンプルです。

結合前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/093db9a7-bfb5-8a61-9459-a77a9686545d.png)

結合後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/2354076b-ab4e-af97-3f92-121c64506fe3.png)

## プログラム

```py:merge_cells_basic.py
#! /usr/bin/python
# ---------------------------------------------------------------
#	merge_cells_basic.py
#
#					Jun/14/2024
# ---------------------------------------------------------------
import sys
import openpyxl
from openpyxl.styles import Alignment

# ---------------------------------------------------------------
def align_adjust_proc(row):
	ws.cell(row, 1).alignment = Alignment(horizontal='center',vertical='center')
	ws.cell(row, 2).alignment = Alignment(horizontal='center',vertical='center')
# ---------------------------------------------------------------
xlsx_in=sys.argv[1]
#
wb = openpyxl.load_workbook(filename=xlsx_in)
ws = wb.worksheets[0]
#
ws.merge_cells(start_row=1,start_column=1, end_row=4, end_column=1)
ws.merge_cells(start_row=1,start_column=2, end_row=4, end_column=2)
align_adjust_proc(1)
#
ws.merge_cells(start_row=5,start_column=1, end_row=8, end_column=1)
ws.merge_cells(start_row=5,start_column=2, end_row=8, end_column=2)
align_adjust_proc(5)
#
ws.merge_cells(start_row=9,start_column=1, end_row=12, end_column=1)
ws.merge_cells(start_row=9,start_column=2, end_row=12, end_column=2)
align_adjust_proc(9)
#
for it in range(6):
	jt = it * 2 + 1
	pos = 'C%d:C%d' % (jt,jt+1) 
	ws.merge_cells(pos)
	ws.cell(jt, 3).alignment = Alignment(horizontal='center',vertical='center')
#
wb.save(xlsx_in)
# ---------------------------------------------------------------
```

## 実行方法

```bash
./merge_cells_basic.py ex01.xlsx
```
Simple WordPress Membershipのメッセージ変更

# 概要
Simple WordPress Membershipを使って会員機能を実装する際に
ログインが必要なページに表示されるメッセージの翻訳が
イマイチだったので今回変更しました。

# 実際のコード
```functions.php
add_filter('swpm_not_logged_in_post_msg', 'custom_not_login');
function custom_not_login($text){
  // ログインページのURLを取得
  $login_url = SwpmSettings::get_instance()->get_value('login-page-url');
  // 新規登録ページのURLを取得
  $registration_url = SwpmSettings::get_instance()->get_value('registration-page-url');

  // カスタムメッセージを返す
  return '<p>本コンテンツは会員専用になります。<br>' . '既に会員の方は<a href ="' . $login_url . '" style="color:">ログイン</a>してください。<br>' . '会員登録がまだの方は' . '<a href="' . $registration_url . '">新規登録</a>してください。</p>';
}
```
swpm_not_logged_in_post_msg
というフックを使うことで変更することができます。
iCloud アカウントで CSV 連絡先ファイルを開くためのユーザー ガイド

<p>このブログ投稿では、CSV ファイルを使用して連絡先を iCloud にインポートするための自動および手動の両方の方法を紹介します。各手順を注意深く読んだ後、ためらうことなく移行タスクを進めてください。それでは始めましょう。</p>
<p>CSV (カンマ区切り値) と呼ばれるファイル形式を使用すると、Microsoft Excel で更新または作成できる表形式でデータを保存できます。CSV ファイルには、名前 (名、ミドルネーム、姓)、性別、誕生日、住所 (自宅と勤務先)、場所、部署、役職、FAX 番号 (自宅と勤務先)、電子メール アドレス、電話番号 (自宅と勤務先)、Web サイト、個人の Web サイト、携帯電話などのフィールドを持つ連絡先を含む、多数のデータ項目が保存されます。</p>
<h2><strong>CSV ファイルの自動クラウド インポート ツール</strong></h2>
<p>手動の方法を使用して <a target="_blank" rel="noopener noreferrer" href="https://www.datavare.com/jp/address.html"><strong>CSV 連絡先ファイルを iCloud アカウントにインポート/開く</strong></a> できない場合は、サードパーティの DataVare アドレス帳管理ソフトウェアを使用することを強くお勧めします。この専門的で信頼できるサードパーティ ユーティリティは、CSV 連絡先ファイルを iCloud アカウントに正確に変換し、データ損失を引き起こしません。初心者のユーザーでも、ユーザーフレンドリーでわかりやすいインターフェイスにより、CSV 連絡先ファイルを iCloud に簡単に変換できます。転送を完了するために技術的な知識は必要ありません。</p>
<h2><strong>特徴:</strong></h2>
<ul>
    <li>データを犠牲にすることなく、CSV ファイルから iCloud に連絡先を正確に転送します。</li>
    <li>iCloud に変換する前に、CSV ファイルのデータ プレビューを表示します。</li>
    <li>電子メール アドレス、電話番号、姓名など、CSV ファイルからすべての情報を取得します。</li>
    <li>CSV 連絡先をエクスポートする場合、ユーザーは重複する連絡先アドレスを削除できます。データの整合性の問題を防ぐために、ユーザーは空のアドレス フィールドを入力しないようにすることもできます。</li>
    <li>Windows 11、Windows 10、Windows 8.1、Windows 8、Windows 7、Windows Vista などの Windows OS プラットフォームと互換性があります。</li>
    <li>試用版として無料でダウンロードできます。</li>
    <li>完全なライセンス バージョンを購入すると、生涯にわたる無料のテクニカル サポートが提供されます。</li>
    <li>インストールとダウンロードは安全で、マルウェアやウイルスの心配はありません。</li>
</ul>
<h3><strong>連絡先の CSV ファイルを iCloud に変換する方法は?</strong></h3>
<ul>
    <li>アドレス帳管理ツールを起動します。</li>
    <li>変換するには、CSV ファイルを参照して選択します。</li>
    <li>プログラムによって、すべての CSV ファイルの内容のプレビューが表示されます。</li>
    <li>CSV ファイルの列をマッピングする必要があります。</li>
    <li>ターゲット形式と宛先パスを選択する必要があります。続行するには、[次へ] ボタンをクリックします。</li>
</ul>
<h3><strong>最終概要</strong></h3>
<p>CSV を iCloud に手動で変換するには、2 つの手順が必要です。まず、CSV データから vCard (VCF) ファイルを作成し、次に VCF ファイルから連絡先を iCloud アカウントにインポートします。したがって、CSV ファイルから iCloud に連絡先を手動で移行するのは困難で時間のかかるプロセスです。したがって、CSV ファイルをエラーなく、データを失うことなく iCloud に変換するには、専門のプログラムを使用することを強くお勧めします。</p>
<h3><strong>よくある質問</strong></h3>
<p><strong>1. DataVare アドレス帳マネージャー ツールを使用すると、データはサーバー上に保存されますか?</strong><br>はい。いいえ、ユーザー情報や資格情報は DataVare プログラムによってサーバー上に保存されません。これは、専門的なデータ移動および変換のための最も安全で信頼性の高いツールの 1 つと見なされています。</p>
<p><strong>2: 同じツールを使用して CSV ファイルを PST 形式に変換できますか?</strong><br>はい。はい、DataVare アドレス帳マネージャー プログラムを使用すると、PST、OST、MSG、NSF、vCard など、多くのファイル形式間でデータを転送できます。ファイルの種類に加えて、Gmail、Office 365、Live Exchange などのオンライン サーバーに CSV ファイルをアップロードできます。</p>
70歳の挑戦... STM32F103C8T6 から SPI接続TFTディスプレイ を使ってみた（ArduinoIDE環境）。面白い発見。

　「STM32F103C8T6(BluePill)」からSPI接続ディスプレイ（480x320、ILI9488）への表示を色々試してみました。やっと出来ましたので報告します。

:::note
１．ArduinoIDE 2.3.2
２．Generic STM32F1 series, BluePill F103CB(or C8 with 128k)
３．TFT_eSPIライブラリ
４．3.5" TFT SPI 480x320 V1.0 ILI9488
５．ST-LINK V2 (ミニ 互換プログラマ)
:::

![F103_9488.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/945a0fef-0a4c-9349-fc99-998b696086d2.jpeg)

![F103-SPI2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/689267b9-03e2-ddf6-975d-b281c0d9d7b6.jpeg)

スマホの不鮮明な写真でごめんなさい。

    ArduinoIDE -> File -> Examples -> TFT_eSPI -> 480x320 -> UTFT_Demo_480x320.ino
    と自作テトリス風ゲーム
    ArduinoIDE、TFT_eSPIライブラリ、 TENOROS.ino
の動作状況です。
　ここに至るまで様々試すものの全く白い画面しか出て来ず、「ArduinoIDE」と「STM32CubeIDE」の間を何度も行ったり来たりしてプログラミングしました。最後、既に「ESP32」と「TFT_eSPIライブラリ」で動いていた自作テトリス風ゲームを動かしてみました。やはりの白画面でしたが、眺めていると時々ゴミのようなものが表示されることに気が付きました。ひょっとしてこれはと、設定を見直しました。そしてSPIの周波数の問題ではないかと。TFT_eSPIライブラリの「User_Setup.h」の記述で周波数を下げてみたら動作画面が現れました。気付けば当然のことですが知らずにどれだけ頭を悩ませたことか。実はそれだけではありません。もっと重要な点がありました。「ST-LINK」の存在です。これが無ければ動かなかったのです。どういうことかと言いますと、PC(or電源)、STM32F103C8T6(BluePill)とST-LINKの接続が

    　　　　　　   .――――――――.
     PC(電源) -----|BluePill|----(SWD)----|ST-LINK|　（ST-LINKとPCの接続は必要なし）
    　　　　　　　 '――――――――'
のようでないと画面表示されないのです。つまり、動作中は不要なはず（PCに繋がれていないから）のST-LINKがBluePillにSWDで繋がったままであることが必要なのです。理由は不明ですが、ST-LINKを使ってなければ気付かなかったでしょう。以下に「User_Setup.h」の有効とした個所のみ示します。

```html:User_Setup.h
#define USER_SETUP_INFO "User_Setup"

#define STM32

#define ILI9488_DRIVER

#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
#define TFT_MOSI PA7
#define TFT_MISO PA6
#define TFT_SCLK PA5

#define TFT_DC   PA2 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
#define TFT_RST  PA3 // Reset pin to TFT RST (or RESET)
#define TFT_CS   PA4 // Chip select control pin to TFT CS

#define TOUCH_CS  PA1     // Chip select pin (T_CS) of touch screen
#define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts

#define SPI_FREQUENCY  27000000
#define SPI_READ_FREQUENCY  20000000
#define SPI_TOUCH_FREQUENCY  2000000
```
まだ課題はありまして、何とか表示は出来ましたがタッチ機能までは使えていません。
　最後までご覧いただき有難うございました。
Excelで数式とSPILLを利用して表の一部を表示する、一部を変更する

ここのところわりと頻繁にExcelを使った集計資料作成をしていたので、そこで知って便利だったテクニックをご紹介。

# Problem

表（配列）をフィルタして結果を別の表として示したい。
ただし元表のすべてではなく一部の列だけを示したい。
また特定の列については元表のデータを加工して示したい。

# Solution

SPILL（スピル）機能と表（配列）を操作する関数を利用します。

まず元表の例。国土地理院から頂いたデータです（国土地理院「[日本の主な山岳一覧](https://www.gsi.go.jp/kihonjohochousa/kihonjohochousa41140.html)」）。安易に「SANGAKU」というテーブル名にしました：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/4a1771da-d7a1-9131-86ad-2a369808c5b8.png)

この記事を執筆している2024年6月14日現在1059件のデータが含まれています。

## ①フィルタ結果を別の表として示す

SPILL機能で簡単に実現できます。
ここでは`FILTER`関数を使いフィルタしています（都道府県名でフィルタ）。あとは何もしなくてもSPILL機能で新表が表示されます：

```
=FILTER(SANGAKU, (SANGAKU[都道府県]="北海道"), #N/A)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/b9a8c374-777d-d3e3-0f2e-abcb95c82e73.png)

## ②元表のデータを加工しフィルタした結果を（以下略）

元表の値を使ってフィルタするだけでなく、元表の値を加工して得られた値でフィルタすることもできます（この例では標高を数値化してフィルタ）。加工には`LAMBDA`関数を使います：

```
=FILTER(
    SANGAKU, 
    (SANGAKU[都道府県]="北海道")*(MAP(
        SANGAKU[標高], 
        LAMBDA(
            x, 
            INT(LEFT(x, LEN(x)-1))
        )
    )>=1000), 
    #N/A
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/f212a13d-2680-2922-6a05-54dfccdc3581.png)

見ればわかる・・・かもですが、ここでは加工した値はフィルタで使用するのみで元表自体には手を加えていないので、SPILL機能で表示される新表では加工前の値が表示されます。

## ③一部の列だけ示す（単一の列）

フィルタした結果別の表に示すのが一部の列だけでよいことも多いはずです。1列のみでよければ`INDEX`関数を使えます：

```
=LET(
  san, 
  FILTER(...),
  INDEX(san, , 1)
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/ba592403-c92c-dc0e-8c9d-b5adc0f32c23.png)

`INDEX`関数の第1引数は配列、第2引数は抜き出す行の番号、第3引数は抜き出す列の番号です。ここでは行指定をせず列指定のみ行っています。
可読性のため、`LET`関数を利用してフィルタ結果の配列を変数に代入していますが、もちろん`INDEX`関数の引数の直接フィルタ結果を渡しても問題ありません。

## ④一部の列だけ示す（複数の列）

複数の列が必要な場合は`CHOOSECOLS`関数を使います：

```
=LET(
    san, 
    FILTER(...),
    CHOOSECOLS(san, 1, 5)
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/9276fe50-1094-3f9d-4c11-6b8a26e52252.png)

`CHOOSECOLS`関数の第1引数は配列、第2引数以降は抜き出す列の番号です。ここでは1番目の列と5番目の列を指定しています。

## ⑤特定の列は元表のデータを加工して示す

フィルタ結果のデータを新表として全部／一部表示するとき、特定の列についてはデータを加工してから表示したいということもあると思います。その場合は `BYROW`関数と`LAMBDA`関数による加工済データの配列の作成と `HSTACK`関数による加工前後の配列のマージ、そして `CHOOSECOLS`関数による列の取捨選択を行います：


```
=LET(
    san, 
    FILTER(...),
    CHOOSECOLS(
        HSTACK(
            san, 
            BYROW(
                san, 
                LAMBDA(
                    x, 
                    LET(
                        hyo, 
                        INDEX(x, 0, 5), 
                        LEFT(hyo, LEN(hyo)-1)
                    )
                )
            )
        ), 
        1, 
        10
    )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/a2cee1cd-17f5-13c3-9ba1-1d3077ea3d36.png)

`BYROW`は配列を行単位で処理するための関数。処理内容は第2引数の `LAMBDA`で指定します。この例では行の中でも5番目の要素を取り出して加工をしています。
`HSTACK`は2つ以上の配列（行列）を水平方向に連結する関数。この例では加工前のすべての列を含む配列と、加工後の1列のみからなる配列を連結しています。
うるう年の判別方法

### この記事では、Pythonを使い、どの年が、うるう年になるかを判別したい。

### うるう年とは
うるう年は、1年が366日ある年です。そうでない年は、平年だ。
ここでは、うるう年を"Leap year", 平年を"Standard year"として定義しておく。

### うるう年のルール
1. 西暦年が、4で割り切れる年は、（原則）として閏年
2. 西暦年が、100で割り切れて400で割り切れない年は、平年
example: 2100年は、100で割り切れるが、400で割り切れないので、平年になる。
要するに、4年に1回ある夏のオリンピックは、うるう年に開催されています。

### 西暦を受け取る
year = int(input("year"))
西暦をinput関数で受け取り、int型に変換

### うるう年かを判別

if year % 100 == 0 and year % 400 != 0:
   print ("standard year")

elif year % 4 == 0:
  print ("leap year")

else:
  print ("standard year")

![Screenshot 2024-06-14 at 15.08.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/d56d6e9d-067f-300f-4c6f-ed937e154861.png)


### 実際にこのコードを使い、うるう年になるか、判定してみます。
![Screenshot 2024-06-14 at 15.10.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/86731e0d-205e-8200-5c47-1416fc222e28.png)
1992年は、4で割り切れるので、うるう年になり、Leap Yearと出力されています。

![Screenshot 2024-06-14 at 15.10.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/3841f123-226b-c50a-27eb-0cb99cf69497.png)
2000年も、4で割り切れるので、うるう年になり、Leap Yearと出力されています。

![Screenshot 2024-06-14 at 15.11.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/8eff327c-7d49-b078-36f3-cb2ac9c46244.png)
対照的に、1900年は、4の倍数でもあり、100の倍数でもあるが、400の倍数ではない為、Standard Yearとして、出力されます。

![Screenshot 2024-06-14 at 15.18.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/636a87e4-1626-2597-7a35-a25605c0e8b4.png)
2100年も、1900年と一緒で4の倍数でもあり、100の倍数でもあるが、400の倍数ではないので、Standard Yearとして出力されます。

![Screenshot 2024-06-14 at 15.13.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/ee74fc36-8be4-1b13-ad70-93409cd3517e.png)
今年2024年も、4で割り切れるので、うるう年になり、Leap Yearと出力されます。

皆様もこのプログラムコードを参考にし、うるう年を判別してみたらいかがでしょうか。
【Next.js】環境変数の値を読み取れない

# 問題
クライアントサイドで、環境変数を読み取ろうとしたが取得できなかった...。
console.logで呼び出してもundifindになって取得できませんでした。


# 解決策

> Non-NEXT_PUBLIC_ environment variables are only available in the Node.js environment, meaning they aren't accessible to the browser (the client runs in a different environment).
In order to make the value of an environment variable accessible in the browser, Next.js can "inline" a value, at build time, into the js bundle that is delivered to the client, replacing all references to process.env.[variable] with a hard-coded value. To tell it to do this, you just have to prefix the variable with NEXT_PUBLIC_
> 

[公式のドキュメント](https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables)にはこのように書かれていました。
クライアントサイドから環境変数にアクセスするときは```NEXT_PUBLIC_```を変数名につける必要があるそうです。
例えば
```diff_abap
- DB_HOST=localhost
+ NEXT_PUBLIC_DB_HOST=localhost
 ```
shyaml で yaml を parse して shell script で楽したい

## tldr;

`shyaml` を使うと yaml を shell script で parse して value を使えて楽だよ

## requirements

1. `Python` && `pip` がインストールされている
2. [`shyaml`]() がインストールされている
    * なければ `pip install shyaml` 

## `shyaml` の使い方

```
cat /path/to/my.yml | shyaml get-value path.of.my.yaml.field
```

## example

例えば project root dir に以下の yaml があるとします。

```yaml:.elasticbeanstalk/config.yml
branch-defaults:
  develop:
    environment: my-eb-env-develop
  main:
    environment: my-eb-env-main
environment-defaults:
  my-eb-env-test:
    branch: null
    repository: null
  my-eb-env-prod:
    branch: null
    repository: null
global:
  application_name: my-eb-env
  default_ec2_keyname: my-eb-env
  default_platform: hogelang on 64bit Amazon Linux
  default_region: ap-northeast-1
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  sc: git
  workspace_type: Application
```

## yaml を parse する shell script を書いてみる

```shellscript:test.sh
#!/bin/bash

# 環境の名前を設定
EB_CONFIG=".elasticbeanstalk/config.yml"
GIT_BRANCH=$(git branch --show-current)
ENV_NAME=$(cat $EB_CONFIG | shyaml get-value branch-defaults.$GIT_BRANCH.environment)
APP_NAME=$(cat $EB_CONFIG | shyaml get-value global.application_name)
REGION=$(cat $EB_CONFIG | shyaml get-value global.default_region)

echo $EB_CONFIG
echo $GIT_BRANCH
echo $ENV_NAME
echo $APP_NAME
echo $REGION
```

## `test.sh` を実行してみる

validation は割愛しているけど欲しい項目の値が取得できる。

```shell
$ chmod +x test.sh

$ ./test.sh  
.elasticbeanstalk/config.yml
main
my-eb-env-main
my-eb-env
ap-northeast-1
```

## まとめ

`shyaml` を使うと yaml を parse して楽して便利になるんではないかと思いました。そんじゃまた。
PRを出すときにプレフィックスをつけると劇的に優先度がわかりやすくなる件

PRだすときは、見てもらうことが多いと思いますが
見る側の人もたくさんPRがあるとどれから見ればいいのかわからなくなります。

そのときにPRと一緒に１つプレフィックスをつけると優先度がわかりやすくなり
見る側がとても助かりました！みたいなことがあったのでメモしておきます。

# 【期限】＠メンション
この日までに絶対見てapproveしてほしいときにつけます。
リリースが近いものや、これを優先的に見てくれないと困るというときにつけましょう

# 【後続あり】＠メンション
このPRをマージしないと次の作業が進まないよってときにつけます。
開発しているとよくある光景だと思うので、つけてあげることでレビュワーは優先的に見てくれることでしょう

# @メンションのみ　お手隙の際にご確認お願いいたします
後続の作業に影響もないし、特に急ぎでもないとき、普段使いするならこれで十分だと思います。

## 最後に
大人数で開発をしているときは、それぞれがタスクを持っていると思います。
そんな中、小さな手間で、他の人の負担を減らせるこのテクニックは役に立つのではないでしょうか。