OmniAICreator/Qiita-1.07M huggingface dataset:
DatabricksのMosaic AI Vector Searchのハイブリッド検索を試す

すでに試されている方もいらっしゃいます。

https://qiita.com/isanakamishiro2/items/d095900e7a816a29011c

ちなみに、現時点での正式名称は**Mosaic AI Vector Search**となっています。LLM/RAG関連の機能はすべてMosaic AIの枠組みの中に位置付けられるようになっています。

こちらで構築したVector Indexに対して試してみます。

https://qiita.com/taka_yayoi/items/f174599e4721e51e9e1d

ライブラリ`databricks-vectorsearch`をアップグレードします。そうしないと、ハイブリッド検索の引数を受け付けてくれません。`0.38`になっていることを確認します。

```py
%pip install --upgrade databricks-vectorsearch
dbutils.library.restartPython()
```
![Screenshot 2024-06-10 at 16.40.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/11726103-9d06-2967-6a1a-73d286e37df7.png)

Vector Search Indexを取得します。

```py
from databricks.vector_search.client import VectorSearchClient
import os

VECTOR_SEARCH_ENDPOINT_NAME="one-env-shared-endpoint-8"
catalog = "takaakiyayoi_catalog"
dbName = db = "rag_chatbot"

index_name=f"{catalog}.{db}.databricks_documentation_vs_index"
host = "https://" + spark.conf.get("spark.databricks.workspaceUrl")
os.environ['DATABRICKS_TOKEN'] = dbutils.secrets.get("demo-token-takaaki.yayoi", "rag_sp_token")
os.environ["DATABRICKS_HOST"] = host

# vector search indexの取得
vsc = VectorSearchClient(workspace_url=host, personal_access_token=os.environ["DATABRICKS_TOKEN"])
vs_index = vsc.get_index(
    endpoint_name=VECTOR_SEARCH_ENDPOINT_NAME,
    index_name=index_name
)
```

デフォルトの挙動で確認します。[こちら](https://docs.databricks.com/ja/generative-ai/create-query-vector-search.html#query-a-vector-search-endpoint)にあるように、デフォルトは`"ann"`(近似最近傍:approximate nearest neighbor)となっています。

```py
question = "Deltaログの保持期間は？"

results = vsc.get_index(VECTOR_SEARCH_ENDPOINT_NAME, index_name).similarity_search(
  query_text=question,
  columns=["url", "content"],
  num_results=5,
  query_type="ann")
docs = results.get('result', {}).get('data_array', [])
display(docs)
```

ふーんという感じです。
![Screenshot 2024-06-10 at 16.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8205bdd8-87b9-5ab5-ef3a-8df3328f9f91.png)

ハイブリッド検索をオンにします。

```py
results = vsc.get_index(VECTOR_SEARCH_ENDPOINT_NAME, index_name).similarity_search(
  query_text=question,
  columns=["url", "content"],
  num_results=5,
  query_type="hybrid")
docs = results.get('result', {}).get('data_array', [])
display(docs)
```

やはり、感触的には精度あがっていますね。
![Screenshot 2024-06-10 at 16.44.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/2c29e175-e1ec-8f27-566d-588abea4fb07.png)

今度は[リトリーバの精度検証](https://qiita.com/taka_yayoi/items/6378214c39d8ddf668d8)もやってみたいところです。


### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
BigQuery の特定データセットの table をすべて消すワンライナー

# 前提

- projectId
    - foo-project
- datasetId
    - bar-dataset


```bash
bq ls --format prettyjson -n 10000 --project_id foo-project bar-dataset  \
|  jq -r '.[].tableReference.tableId' \
| xargs -t -I {} bq rm -f --project_id foo-project --dataset_id bar-dataset "{}"
```

条件指定などはご自由に
(QA) RDiでコンパイルコマンドのパラメーターを変更したい

## Q. Rdi でコンパイル時のパラメーターを変更したい

## A1. コンパイルコマンドをプロンプト表示して、変更する。

例えば、CRTDSPFコマンドを実行する際、RDiでソースを右クリック-> プロンプト -> CRTDSPF を指定すると、ファイルの置き換え REPLACEパラメーターを指定可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/750d1078-03d0-e2ea-140f-8c2727be1035.png)

## A2. パラーメーター変更した、ユーザー独自のコマンドを定義する。

RDiでソースを右クリック-> プロンプト ->コンパイルコマンドの処理 を表示して任意のコマンド名（以下の例ではCRTDSPF1）とし、パラメーターを必要に応じて変更できます。
下記例では REPLACE(*YES)としています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/4026d3bc-d933-5440-2a27-0e2f1197056b.png)

実行時は作成したコマンド名（例ではCRTDSPF1)を指定します。
作成したユーザーコマンドはプロンプト表示する・しない、どちらでも実行できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/8dd48c7d-8c32-2c21-aed1-2ae306fd3351.png)
AWS Certified DevOps Engineer - Professional合格の雑談

**:congratulations:2024年5月27日に一発でAWS認定DevOpsエンジニア – プロフェッショナル（DOP）がギリギリの点数で合格しました:congratulations:**

<font color="Gray">→[SAPの時](https://qiita.com/nakamurahiro/items/948a833717e836527046)と同様またギリギリ🙈</font>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236892/e91f7f43-5b72-dc5c-5168-86b8571071e3.png)

今回もあんまり長い記事を書きたくないので、雑談にしましょう:relaxed:

# 試験内容について:bow:
SAPと同様に連続３時間で集中して、相変わらず疲れました😿。SAPの時は日本語受験でつらかったので、今回は大人しく母語で受験しました。
問題文と選択肢は若干SAPより短かったです、また母語なので読みスピードは速くて、残り30分の時にも全部答え完了でした。後で見直しマークは12個くらいつけたので、残った時間でもう一度考えて答えました。
ちなみに、英語母語ではない人は試験の30分延長の申請ができるから、申請してみてください。筆者は残念ながら、知っていた時もう申し込みしたので今回は利用できませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236892/3c314ce7-07cc-7e82-11f9-98d0928257ba.png)


# 採点について:white_flower:
満点は1000点:100:、合格は750点:u5408:です。筆者は788点をとりました:joy:　ぎりぎりですが、前回よりちょっと高いです。（SAPの時は764）

#### 模擬試験
Udemyでの2回模擬試験は全部失敗しました🫥
* 第一回目45問
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236892/b0b0986b-75af-2ba0-da85-154df9ef2c31.png)
* 第二回目75問
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236892/949a3743-c87a-a6e5-a78a-a4b1de954d4f.png)
でもなんとなく間違えた問題を全部理解した後、本試験は多分大丈夫かなと根拠のない自信がありました。結局本当に大丈夫でした、ラッキー🥜

# 勉強法＆参考資料📓
今回のDOPは、本の代わりにUdemy二つ資料をちゃんと見ていました、全部Stephaneのコースです。他の資料はほとんど参照していませんでした。
コースであやふやなところはClaude AIと話して全部のロジックが通じるようにしました。今のAI時代では、これが一番魅力的なことですね、誰の側にも素晴らしい「専門家」がいて、いつでも聞かれます👾
でも注意点としては、Claude AIは賢くて99％の時は正しいですが、偶に正しくない答えが出てくるので、自分のロジックとコンフリクト感がある時ちゃんとGoogleどうかで調べてください。

* コース

https://www.udemy.com/share/101WpU3@Id8S7o91FNmpF76B86srxTvxg5RGrdDiME4Mz-WlqOrx6VEkfPRdJwyHIt6N-vQTBw==/

* 問題集

https://www.udemy.com/share/1021dU3@kKmewuNcYWAgVXEEG4Qynb7CKGrfR3aAQ3P744o78BUtiun1rHP4IoztOUpLqWfYcA==/

# 終わり:tokyo_tower:

DOPはSAPと同じレベルの試験だと思います、単純な知識点を聞く問題はなく、設計・開発上の解決案や改善案を聞くわけです。
筆者は三年前のSAP：764点、今回のDOP：788点です。幸い今回も合格でした。

**最後に皆さんは合格できるように、Good Luck！🍀**
Hangman

### この記事において、Hangmanという相手の考えた単語を当てる2人用のゲームをPythonコードで書く方法を皆さんに教示したい。

#### 初期設定としては、このコードを書いたらいい。
![Screenshot 2024-06-10 at 15.59.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/75e2b514-e082-7d58-76da-b74c405b578d.png)

#### 単語の選択と変数の初期化が必要になってくる。
![Screenshot 2024-06-10 at 16.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/5f385f9b-82c7-0714-2466-621c9de60ccb.png)

hangman_words.word_listからランダムに単語を選びます。
選ばれた単語の長さをword_lengthに格納します。
end_of_gameはゲームが終了したかどうかを示すフラグです。
livesは6に初期化され、これは許されるミスの回数を表します。
displayは、推測された単語の現在の状態を保持するリストで、最初はアンダースコア（_）で埋められます。

#### ゲームループ
![Screenshot 2024-06-10 at 16.01.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/0988ae26-a54c-421d-7e93-9649930eba1e.png)

end_of_gameがFalseの間、ゲームは続きます。
プレイヤーは文字を推測するように促され、その文字は小文字に変換されます。
画面をクリアして表示をきれいに保ちます。
もし推測された文字がすでにdisplayに含まれている場合、プレイヤーにそのことを知らせるメッセージを表示します。

#### 推測の確認
![Screenshot 2024-06-10 at 16.03.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/24047952-bba4-e72f-a720-09968410295f.png)

このループは、選ばれた単語の各文字を繰り返します。
各位置で、推測された文字が選ばれた単語の文字と一致するか確認します。
もし一致した場合、"display"の対応する位置をその文字で更新します。

#### 間違った推測の処理
![Screenshot 2024-06-10 at 16.05.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/3978c09b-6e55-f047-4768-c1fdace217c6.png)

もし推測された文字が選ばれた単語に含まれていない場合、メッセージを表示し、プレイヤーはライフを失います。ライフが0になると、end_of_gameがTrueに設定され、プレイヤーに、負けたことを知らせます。

#### 勝利条件の確認
![Screenshot 2024-06-10 at 16.06.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/04b0fd5a-17f7-89f6-7ba0-481ad704192a.png)

単語の現在の状態を表示します。もし、"display" にアンダースコアが含まれていない場合、プレイヤーがすべての文字を正しく推測したことを意味し、ゲームは勝利メッセージとともに終了します。

#### ハングマンの段階を表示
![Screenshot 2024-06-10 at 16.07.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/8f54ee69-8419-b3a2-4938-0147e10c7497.png)
残りのライフ数に基づいて、適切なハングマンの段階のグラフィックを表示します。

これだけでは、わからないと思うので、このコードを利用して、実際にHangmanをしている画像を添付しておく。

![Screenshot 2024-06-10 at 16.09.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/e382c777-7785-a425-f308-1de10d6045ab.png)

今回私は、dをいう文字を予想した。Current Letterが正解のアルファベットで、Guessed Letterが、ユーザが予想した文字だ。この場合は、Fuchsiaというのが正解だ。

![Screenshot 2024-06-10 at 16.10.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/0e132737-b8b0-d473-fe3f-2f4c60f7191c.png)

そこで、再度試してみた。私は、lという文字を予想した。Current Letterは、Youthfulと出力されたので、一つの文字が的中したことになる。
![Screenshot 2024-06-10 at 16.15.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518583/7c5c2bfa-6ff7-85e1-0901-00e75ca31c12.png)

#### まとめ
ゲームはランダムな単語を選び、表示とライフを設定します。
プレイヤーは文字を推測し続け、正解なら表示を更新し、不正解ならライフが減ります。
プレイヤーが単語をすべて当てるかライフがなくなるまでゲームは続きます。
各推測後にハングマンのグラフィックが表示され、プレイヤーの進捗が示されます。

皆さんもこのプログラムコードを使い、Hangmanを一度試してみたらいかがでしょうか。

注）このプログラムコードを書くにあたって、このリンクを参考にしました。
https://github.com/Vickyabiodun/Hangman-Game
【開発者向けQA用語解説】シフトライト【Vol.2】

## はじめに
現在のソフトウェア開発において、開発とQAは密接な関係にあります。
それこそ、手を取り合ってプロジェクトを進めていくのが基本となりつつあります。
しかし、開発の専門性が高いようにQAも専門性が高く、用語や意図がわからない場面は多々あるでしょう。
そんな方のため、用語の解説を行っていくシリーズです。
また、本記事は私の独断と解釈によるまとめですので、一部事実と違う点があるかもしれませんが、その際はご指摘ください。

## 「シフトライト」のざっくりとした解説
### 「シフトライト」の概要
本来、開発物を確認する工程は「テスト」のみでした。
その「テスト」より後ろの段階で「確認する」という作業を実施することを指します。
また、何かの仕様についての正と定めるものを、要件定義や設計ではなく、
リリース後の「顧客の声」を正として開発すること、とも言えます。

### 「シフトライト」の主なメリット
「実際の顧客の要望を正確に反映できること」がシフトライトの主なメリットです。

### 「シフトライト」のお試し方法
製品のリリース後、顧客の声を元に開発を行っているのであれば、
そこの拾い上げ方を工夫したり、強化することがシフトライトに繋がります。
ただ、その一部の手法は非常にデリケートであり、お試し感覚で実施できません。

## 「シフトライト」の詳細な解説
### 品質関連書籍からの引用
まずは私自身の言葉で説明するよりも正確性を大事に、世に出ている公的な書籍から引用しようと思いました。
が、手元にある何冊かQAの参考書に、シフトライトの記載はありませんでした。

### 何に対して「右」なのか
「右に行く」ことはわかると思いますが、何を指して右方向なのかが不明瞭かと思うので、そこから解説します。
[Vol.1で「シフトレフト」を解説している](https://qiita.com/Syahu_Writer/items/ebd1220afc31dcbd589d "【開発者向けQA用語解説】シフトレフト【Vol.1】")ので、一旦そちらを参照いただくと前段の理解も深まるかと思います。

前段を端折って説明すると、
古くはウォーターフォールという開発手法が世の代表だった時に「シフトレフト」が生まれました。
ウォーターフォール開発はその名の通り、一方通行で行ったっきりの開発フローです。
![ウォーターフォール開発横.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565882/d2d6a8e7-abef-bc1a-6785-3f329ea3debd.png)
この図で、元の「テスト」のフェーズよりも左側でもテストを実施する、ということで「シフトレフト」と呼ばれています。

そして、近年の、特にソフトウェア開発では、ほぼウォーターフォール開発は使われていないでしょう。
リリースして終わり、ということはなく、機能追加、要望、不具合修正等々、継続的な開発が行われます。
終わりなきシステム開発ライフサイクルです。
先ほどの図に書き足すと、以下のような感じでしょうか。
![スクリーンショット 2024-06-05 163108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565882/0a5eec77-d9ce-856e-caca-a73dce9275d6.png)
「シフトレフト」は「テスト」より左側でテストをすることですので、
「シフトライト」は「テスト」より右側、つまり「運用」をテストの場にすることです。

### 「シフトライト」の詳細なメリット
最も大きなメリットは、
「要件定義や開発者の想定したものでなく、実際の顧客の要望を反映できる」という点です。
「リリースした後も修正が無限に続く」というのが実務上の感想でしょうが、
「リリースした後に修正することができる」と利点に捉えています。

関連して、要件定義や設計段階で顧客のニーズやシナリオを想定して仕様を決定したりしますが、
それが一発で、すんなりと決まったことはありますでしょうか。
特にフロント側、WEB系だと、デザインも相まって紛糾するでしょう。
「実際に運用してみて、顧客の反応を見ましょう」と、そこで議論を収めることができます。
つまり、運用のタイミングで何が良いかテストを実施しています。
多少レビューの時間を抑えつつ、本当の正解を探ることができます。

デザイン周りであれば、改修する場合に表示崩れなどあるかもしれません。
多彩なデバイスでの表示確認など、修正工数と比較して確認やテストの工数が多くかかったりします。
「メジャーケースは押さえておいて、マイナーケースは実際に運用してみて、指摘されたら修正しましょう」と、
ある程度の工数で切り上げる判断ができます。
つまり、運用のタイミングで不具合がないかテストを実施しています。
工数を抑えつつ、効率よく不具合を検出することができるということです。

「ABテスト」や「カナリアリリース」と言えば、聞き覚えがあるでしょう。
これらが「シフトライト」に当たります。

### 「シフトライト」の導入方法
シフトレフトとセットで詳細を記載しようと思っています。
シフトレフトでも記載していますが、これ自体は**導入しようと思って導入するものではありません**。
品質向上のため、不具合をより発見しやすくするため、各種コストを下げるため、
そういった問題を解決するための**手段の一つ**だからです。
特に「シフトライト」とはその性質上、不具合をリリースする前提でもあり、容易に行うことができません。
本記事ではそのあたりまでご理解いただければ幸いです。
pillowを使って見切れないように画像に文字を入れる。

# 前書き
こんにちはatomです。
仕事の一環でちょっと Pillowを使って画像をいじる場面がありました。
ちょこちょこと調べながらやったので、同じようなことでつまづくかたが減るようにメモを残します。

# Pillowって何？
リサイズや切り出し、この記事のテーマの文字を入れる、などの画像処理をすることができるライブラリです。

簡単な処理をしたいだけなら結構便利。

# 筆者のやりたかったこと
- たくさんある画像に文字を入れたい
- 文字は複数行に渡っていて右下端が切れると嫌なので座標を適宜指定したい
- ついでに文字の画像全体に占める割合を気にしておきたい

# いざ
先にPillowで画像に文字を入れるときの大まかな使い方を書きます。
```python
from PIL import Image, ImageDraw, ImageFont

img = Image.open('ファイル名')
draw = ImageDraw.Draw(img)

text = '書き込みたい文字'
font = ImageFont.truetype('フォントファイルの指定', 文字サイズ)
# textメソッドを使って、指定したtextが第一引数の座標に書き込まれる。
draw.text((x座標, y座標), text, font=font)

img.open(’新しいファイル名’)
```

x,y座標と文字サイズはintです。

## つまづいたところ
### 1\.使えるフォントの一覧がわからない
ft-listコマンド(macじゃない方は適宜調べてみてください...)で一覧を取得可能。
今回はヒラギノ角ゴシックを使いたかったので

```python
fc-list | grep ヒラギノ角ゴシック
```

という感じで絞って適当に見繕った。

### 2\.文字の右端の座標を知りたい
multiline_textbboxメソッドを使って取得します。
このメソッドの返り値が文字の占める領域(バウンディングボックス)のleft, top, right, bottomとなるので、とりあえず下の例のように画像左上に文字を書いたとして、ボックスの大きさを確認します。
```python
bbox = draw.multiline_textbbox((0, 0), text, font=font)
```

座標がわかるので、上に書いてあったバウンディングボックスの画像全体に対する割合も計算が簡単です。
計算は特にPillowに関わりないので割愛。

# 参考文献

[ImageDraw Module](https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html#PIL.ImageDraw.ImageDraw.multiline_textbbox)
Visual Studio 2013 タブオーダーが途中で1になる

# 今回の内容
とあるプログラミングのアルバイトで、Visual Studio 2013でタブオーダーを変更する案件があったのだが、それの変更にかなり苦労したので、備忘録として残しておく。

# 途中で1になる原因
タブオーダーは途中で1になるとすべてやり直しである。そのため、予期せぬところで1になるという現象が発生し、かなりイライラした。その原因は、タブオーダー変更中に画面横のスライドバーを操作することが原因だった。
自分の環境では、ウィンドウ全体を表示していなかったため、タブオーダー変更中に、写っていない領域を表示するために、スライドバーを操作して、別の領域を表示していた。その操作をすることで、タブオーダーが1に初期化される。
ウィンドウ全体を表示してタブオーダーを押すようにしたら、1になることはなくなった。ただ、コントロール押し忘れると1からやり直しになるのはどうにかならんものかなぁ...
【JavaScript】配列メソッド「reduce」

## reduce とは

`reduce`メソッドとは、「**配列内の要素を順番に処理して、1つの結果を算出するヤツ**」です。

以下では、配列`numbers`の数値の合計値を算出しています。

```javascript
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 15
```

個人的に`reduce`メソッドは、引数の多さや、複雑な見た目からJavaScriptの配列メソッドの中でも最難関だと思っています。

## 破壊的 or 非破壊的

`reduce`メソッドは、**非破壊的メソッド**です。使用しても、操作元の配列に影響は及びません。

> JavaScriptの配列メソッドには、実行した際に元の配列やオブジェクトそのものを変更する「破壊的メソッド」と、元の配列やオブジェクトを変更せずに新しい配列やオブジェクトを作成して返す「非破壊的メソッド」の2種類があります。
> 
> 使用したい配列メソッドが「破壊的」なのか「非破壊的」なのかが考慮できていない為にバグが発生することはよくあるので、使用する際には確認しておきましょう。
>
> [こちらのサイト](https://jsprimer.net/basic/array/#mutable-immutable)で詳しく説明されていますので、併せてご確認ください。

## 使い方（基本）

まずは`reduce`メソッドを複雑にしている引数について、1つずつ整理して説明します。

`reduce`メソッドには、引数は**2つ**渡します。（★：重要度高 ◼︎：重要度低）

1. ★「**コールバック関数**」：配列の各要素に対して実行される関数。ここで`return`された値が次の回の「accumulator」になる
1. ★「**『accumulator』の初期値**」：後述する「accumulator」の初期値

👆の1つ目で渡している「コールバック関数」には、引数を最大**4つ**渡します（🥵）。（★：重要度高 ◼︎：重要度低）

1. ★「**accumulator**」：前回の呼び出しの戻り値
1. ★「**currentValue**」：現在の配列要素
1. ◼︎「**currentIndex**」：現在の配列要素のインデックス
1. ◼︎「**array**」：実行対象の配列そのもの

****

```javascript
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 15
```
例で提示した上記のプログラムに合わせて説明すると、

1. `accumulator`に、「『accumulator』の初期値」として指定された「0」が代入される
1. `currentValue`は配列`numbers`の1個目の要素「1」なので、`accumulator`（初期値「0」）に`currentValue`「1」を足した値、「1」を`return`する（`accumulator`に代入する）
1. `currentValue`は配列`numbers`の2個目の要素「2」なので、`accumulator`「1」に`currentValue`「2」を足した値、「3」を`return`する（`accumulator`に代入する）
1. `currentValue`は配列`numbers`の3個目の要素「3」なので、`accumulator`「3」に`currentValue`「3」を足した値、「6」を`return`する（`accumulator`に代入する）
1. `currentValue`は配列`numbers`の4個目の要素「4」なので、`accumulator`「6」に`currentValue`「4」を足した値、「10」を`return`する（`accumulator`に代入する）
1. `currentValue`は配列`numbers`の5個目の要素「5」なので、`accumulator`「10」に`currentValue`「5」を足した値、「15」を`return`する（`accumulator`に代入する）
1. 最終的な`accumulator`の値「15」が`reduce`メソッドの結果として返されて、変数`sum`に「15」が 代入される

****

このように、配列の要素を使用して何か1つの結果を算出したい場合に、`reduce`メソッドを使用します。

`reduce`メソッドを見つけた際には、

- 第二引数に注目して「accumulator」の初期値は何か確認する
- コールバック関数内で何を`return`しているかに注目して、「accumulator」に対してどんな操作を行なっているかを確認する

という点に注目してみると、頭が整理されて見やすくなるかと思います。

## 使い方（応用）


### オブジェクト配列を扱う

```javascript
const items = [
  { name: 'apple', price: 50 },
  { name: 'banana', price: 30 },
  { name: 'orange', price: 20 }
];

const totalPrice = items.reduce((accumulator, currentValue) => {
  return accumulator + currentValue.price;
}, 0);

console.log(totalPrice); // 100
```

### オブジェクトを生成する
算出結果「accumulator」はシンプルな数値である必要はありません。以下のように、オブジェクトを生成することも可能です。

以下のプログラムでは、配列`fruits`の各要素を数えて、それぞれのフルーツの出現回数を持つオブジェクト`fruitCount`を作成しています。
```javascript
const fruits = ['apple', 'banana', 'orange', 'apple', 'orange', 'banana', 'banana'];

const fruitCount = fruits.reduce((accumulator, currentValue) => {
  if (accumulator[currentValue]) {
    accumulator[currentValue]++;
  } else {
    accumulator[currentValue] = 1;
  }
  return accumulator;
}, {});

console.log(fruitCount); // { apple: 2, banana: 3, orange: 2 }
```
学校の大型モニターを常時フル活用しよう！

こんにちは。今日はモニターを常時フル活用するツールを作った話をしようと思います。

:::note alert
記事の投稿を6か月くらい忘れてました
:::

:::note warn
この記事は「[学校に自作のポータルサイト的なものを導入したかった話]()」を見てからだとより楽しめるのでぜひ見てくださいね！
:::

# 教室のモニターのスペック
各教室に一台おいてあってテレビにAirPlay投影用のApple TVとかが繋いであります。

# 現状の課題
- 動画を映すときやなんかするとき以外は基本的に利用していない
- せっかくの大画面がもったいない
- 有効活用するアプリ作ろう！

# アプリの構成
- HTML
- Bulma(CSS Framework)
- Vanila JS

# デモ
完成したものがこちら！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518724/72a4dfc8-5e8f-9c2f-78c5-47dc9e96f020.png)

時計、日付、時間割、宿題、ニュース等様々な情報が確認できます。
お知らせや時間割は画像にもある通りmicroCMSから書き換えることができます。
microCMS取得分は5分またはmicroCMSのみのリロードまたは普通のリロードごと、ニュース天気は手動リロード(`Ctrl+R`の普通のやつ)または30分のオートリロード(`addEventListner`で30分ごとに`location.reload()`を実行)時に更新されます。

## まとめ

需要があればOSSで公開します
Azure Data factory メタデータ駆動のコピータスクにてパラメータ化したリンクサービスを利用した際のデータセットに対する修正の必要性について


## 概要

Azure Data factory メタデータ駆動のコピータスクにてパラメータ化したリンクサービスを利用した際に、2024年6月10日時点では、データセットに対する修正が必要となるようです。

パラメータ化したリンクサービスを用いてメタデータ駆動のコピータスクを作成すると接続制御テーブルに基づき、接続情報をを渡せるようになりますた。

> パラメーター化されリンクされたサービスを使用した場合、接続制御テーブルはデータ ストアの接続値を格納します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/83491754-c66d-5b88-5572-bb6bb1a011c4.png)


引用元：[データのコピー ツールでメタデータ駆動型の方法を使用して大規模なデータ コピー パイプラインを作成する - Azure Data Factory | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/data-factory/copy-data-tool-metadata-driven#create-metadata-driven-copy-jobs-from-copy-data-tool)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0c915668-c7d9-6f5c-5639-a626c3b6842d.png)

引用元：[データのコピー ツールでメタデータ駆動型の方法を使用して大規模なデータ コピー パイプラインを作成する - Azure Data Factory | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/data-factory/copy-data-tool-metadata-driven#create-metadata-driven-copy-jobs-from-copy-data-tool)

ただし、データセットにおいてリンクドサービスのプロパティにて、データセットのパラメータがセットされておらず、作成した時に入力した項目値として設定されていました。そのため、データセットのパラメータを渡すように修正する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/81ad3474-3228-3460-0b83-a3fd864bb6a2.png)


## 修正手順

### 1. `リンクサービスプロパティ`における値を`cw_ls`ではじまるパラメータに変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ee8541b0-10eb-ef9c-d609-c0fc31d1c1e7.png)

### 2. デバック実行後に正常終了することを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9d05c966-e73a-3196-0863-a42ebf036a0d.png)
Windows PC で Apple から CSV に連絡先をスムーズに移動/シフトする

<p>PC で Apple の連絡先を CSV にエクスポートする方法を知りたいですか? 答えが「はい」の場合、このページは正しいページです。この質問に対する最適な答えを見つけるお手伝いをします。</p>
<h2><strong>vCard: それは何ですか? なぜプロの vCard から CSV 形式へのエクスポート方法を使用する必要があるのですか?</strong></h2>
<p>vCard ファイルには、私たちが知る限り、名前、住所、電話番号、電子メール アドレスなどの連絡先情報が含まれています。したがって、信頼性が高く安全な方法で形式を変換することが重要です。そうしないと、連絡先情報が損傷したり悪用されたりする可能性があります。私が提案する方法を使用する場合は、個人情報をオンラインに投稿する必要はありません。さらに、vCard ファイルを手動でインポートすることは、データ損失に関連する多くの危険があり、技術に詳しくないユーザーにとっては理解が難しい可能性があるため、ユーザーに警告します。</p>
<h2><strong>ユーザーの質問:</strong></h2>
<p>私は Juanita Lopez です。こんにちは。Windows コンピューターで Apple の連絡先を CSV ファイルにエクスポートすることは可能ですか? この課題を今すぐに実行する必要があるので、洞察力のある提案を私と共有してください。よろしくお願いします。</p>
<h3><strong>vCard 形式を CSV 形式に変換する便利なアプリは、vCard から CSV へのコンバーター です。</strong></h3>
<p><strong>Softaken </strong><a target="_blank" rel="noopener noreferrer" href="https://www.softaken.com/jp/vcf-csv"><strong>vCard から CSV へのコンバーター</strong></a> を使用すると、vCard ファイルを CSV 形式に変換するのが簡単になります。このプログラムを使用すると、PC、携帯電話、電子メール クライアント、クラウド メール アプリケーション、メール サーバーなど、さまざまなデバイスから vCard ファイルをエクスポートできます。変換プロセス中、名前、連絡先情報、住所、電子メール アドレスなど、連絡先ファイルのすべてのフィールドは同じままです。さらに、ユーザーは 3.0 および 2.1 バージョンの vCard ファイルをエクスポートできる場合があります。</p>
<p>VCF ファイルを追加するには、「ファイルの追加」と「フォルダーの追加」の 2 つのオプションがあります。前のオプションでは一度に複数のファイルを選択でき、後のオプションではフォルダー全体を選択できます。バッチ モードでは、この方法で vCard ファイルを CSV 形式にインポートします。ユーザーは、生成されたファイルを保存する場所を自由に選択できます。さらに、ユーザーはプロセスが完了したらすぐに変換ステータスを表示できます。では、このプログラムの動作の詳細について説明します。</p>
<p>Apple から PC の CSV ファイルに連絡先をエクスポートするにはどうすればよいでしょうか? 次の手順についてお話ししましょう</p>
<h3><strong>まず、vCard から CSV へのコンバーター をインストールします。</strong></h3>
<ul>
    <li>次に、必要に応じてさまざまなファイルまたはディレクトリを追加します。</li>
    <li>これで、ユーザーは「削除」および「すべて削除」オプションを使用して、不要なファイルの選択を解除できます。次に、「次へ」をクリックして続行します。<br>次に、優先ファイル形式として「CSV」を選択します。</li>
    <li>出力先ディレクトリを追加したら、「エクスポート」をクリックできます。次に、「OK」をクリックして移行手順を効果的に完了します。</li>
</ul>
<h3><strong>結論</strong></h3>
<p>前述の方法により、ユーザーは PC で Apple の連絡先を CSV にエクスポートする作業を非常に簡単に処理できるようになりました。この簡単な手順により、技術的な知識がなくても、誰でも VCF から CSV へのフォーマット変換を行うことができます。デモ目的で、ユーザーは 5 つの vCard ファイルを CSV 形式で無料でエクスポートできます。</p>
proxmoxの初期設定

# はじめに
ここ最近、proxmox(プロックスモックスで読み方はあってるのだろうか？)というものを知って、自宅PCに入れて遊んでいます。
この記事では、その時に必ずやる初期設定を備忘録として記載します。

# proxmoxとは
自分は、仮想環境を建てるのに特化したOSという認識です。
似た商品としては、VMware社の無償版ESXiだと思いますが、無料提供が終わったことでproxmoxに注目が集まってるのだと思っています。

# なぜproxmoxなのか？
遊び用PCにubuntuを入れてやる方法もありますが、新しいものを使ってみたいという気持ち半分、使って分かった「立てやすく壊しやすい」という特徴から個人的に気に入っています。
virtualboxのような仮想環境もできますし、LXC(Linux Container)での仮想環境もデフォルトでできます。
あと、その構築をブラウザ画面から操作できるのがとても便利です。
ちょっと環境の勉強をしてみようと考えてる人には向いてると思います。

# 前提条件
この記事では、以下のバージョンを利用しています
- proxmox:8.2.2

また、自宅からのみのアクセスを前提にしていますので、セキュリティ関係は抜きで記載しています。

# 構築
構築に関しては、自分はこちらを参考にしました（ありがとうございました）
https://internet.watch.impress.co.jp/docs/column/shimizu/1551702.html

![008_o.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/a3797188-6163-49d0-802d-be99f8671147.png)
この画面の時、hostnameはmdns設定を利用前提で、「〇〇.local」を設定。
後で変更することもできますが、自分は変更したことでweb画面が立ち上がらなくなったりしましたので、mdns前提での運用を行っています。(知識不足のため、ご容赦ください)

立て終わった後は、「[https://＜IPアドレス＞:8006](https://＜IPアドレス＞:8006)」でweb画面にアクセスができるようになります。

# 初期設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/4dc2168b-d385-177e-a597-9820996d83a9.png)
ここから、ホストOSにアクセスが可能です。

## SSHできるように
```
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh
```

こちらを参考にさせていただきました。(ありがとうございます)

https://qiita.com/ohtsuka-shota/items/d9338e2a31c42426620b) 

これでSSHでつながるようにはなります。

:::note warn
rootでのパスワード認証ですので、案件等で利用される方は鍵を設定した後は閉じることをお勧めします。
:::

## mdns（multicast DNS）
以下をインストール
```
apt-get install -y avahi-daemon avahi-dnsconfd avahi-discover avahi-utils
```

ホスト名を調べる
```
# hostname
proxmox
```

問題なく適応されてるなら「[https://proxmox.local:8006](https://proxmox.local:8006)」でweb画面にアクセスができるようになります。

## LXC用のCTテンプレートのダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/0e689650-d06b-bc01-08cb-2093b80cb48b.png)
テンプレートからお好みのOSをダウンロートしてください。
自分はubuntuの最新をチョイスしています。

# さいごに
この記事では、以上となります。
本当はセキュリティも考慮して色々やった方がいいとは思いますが、立てて壊して遊ぶをモットーに利用していますので、必要最低限です。
環境を建てたいことがあったら、proxmoxをお勧めします。
今の激安PCでも動くでしょうし、raspberry pi 5でも動く記事も目にしました。
(raspberry pi 5では、スペック上あまり環境を建てれないので個人的には微妙に感じます。)
皆様も環境を建てる機会があったら利用してみてください。
タグ選択機能のリファクタリング

# はじめに
rails案件でタグが力業で実装されていたので、そこを改修した際の備忘録となります。
親子孫関係を一括で登録する似たような記事はたくさんあるので、説明は割愛気味で記載しています。

# 実装状況
ruby:3.3.0
ruby on rials:7.1.3
css , js: jsbundling-rails + cssbundling-rails 構成
view：haml

# モデルの構成
以下のような構成
master_tag -> test_tag <- test 

# モデルの変更
```ruby
class MasterTag < ApplicationRecord
  has_many :test_tag
end
```
```ruby
class TestTag < ApplicationRecord
  belongs_to :master_tag
  belongs_to :test
end
```
```ruby
class Test < ApplicationRecord
  has_many :test_tag, dependent: :destroy
  has_many :tags, through: :test_tag, source: :master_tag
  accepts_nested_attributes_for :tags, allow_destroy: true
end
```

# コントローラー
ストロングパラメータ部分を修正
```ruby
    def test_params
      params.require(:test).permit(:title, tag_ids: [])
    end
```

# ビュー
```haml
    タグ
    = content_tag(:dev, class: 'flex items-center') do
      = f.collection_check_boxes :tag_ids, MasterTag.all, :id, :name do |tag|
        = tag.label do
          = content_tag(:dev, class: 'flex items-center m-1') do
            = tag.check_box(class: 'checkbox rounded')
            = content_tag(:dev, tag.text, class: 'badge badge-lg', style: "background-color: #{tag.object.color_code}")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/01755420-5d48-69c2-10dd-f67cf7df383e.png)


# 最後に
よくある記事なので目新しいものはありませんでしたが、チェックボックスを加工するのは久々だったのもあり検索などして対応しました。
今回は暫定対応だったので、ここまでとします。
【Flutter】経過時間を測る

こんにちは。
今回は、経過時間を測る方法を紹介します。

# 方法
![スクリーンショット 2023-08-13 20.18.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/ce57fee2-1687-ea40-8538-b4c8b9db94e0.png)

経過時間を測るには、Stopwatchクラスを使います。
まず、Stopwatchのインスタンスを用意します。

次に、Stopwatchの次のメソッドを使い、経過時間を測ります。

:::note info
* start() : 時間を測り始める
* stop() : 時間を測るのをやめる
* reset() : 時間をリセットする
:::

最後に、次のプロパティを使って時間を確認します。

:::note info
* elapsed : 経過時間
* elapsedMicroSeconds : 経過時間（マイクロ秒）
* elapsedMilliSeconds : 経過時間（ミリ秒）
:::



# 使用例
```dart

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Stopwatch _timer = Stopwatch();  //Stopwatchのインスタンス
  String duration = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text("Time; ${_timer.elapsed}"), //経過時間
            ElevatedButton(
              onPressed: () {
                setState(() {
                  if (_timer.isRunning) {
                    duration = _timer.elapsedTicks.toString();　//
                    _timer.stop();
                  } else {
                    _timer.start();
                  }
                });
              },
              child: Text(_timer.isRunning ? 'Sto![ストップウォッチ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/86e6cad3-0ff8-fbcb-e6a7-759eb253b1cf.gif)
p' : 'Start'),
            )
          ],
        ),
      ),
    );
  }
}

```

# 実行例
![ストップウォッチ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524120/d6c836fd-52e8-beb1-5f2a-78e7e73fea98.gif)


# 最後に
ここまで読んでいただき、ありがとうございました！
いいねしてくれたら、スキップして喜びます:heartpulse:
フリーランスエンジニアの業務委託の商談で聞かれることリスト

# はじめに
フリーランスエンジニアなって、業務委託の商談時に実際に聞かれたことをまとめます
転職と違って、志望動機や強み弱みみたいな部分よりは、スキルがマッチしているかという部分と案件をこなせるか即戦力としての適正の部分を主にみられます。


# 経歴や今後の方向性
◆スキルシート○○番で担当していたポジションや業務は何ですか
◆リモート作業で課題に感じたことや工夫をしていることはございますか？
◆今までで1番大変だった案件や苦労した経験はございますか？
◆経験やスキルを今回の案件でどう活かしますか？
◆今のあなたの課題は何ですか？
◆身に付けたいスキルは何かありますか？
◆今後のキャリアプランをお聞かせください
◆未経験技術はどのようにキャッチアップしていますか？
◆フリーランスになったきっかけはなんですか？

# リーダー/チーム開発
◆リーダー経験はございますか？
◆リーダとして辛かったこと解決した課題はありますか？
◆チームメンバーと意見がぶつかった際は、どのように対応しますか？
◆技術選定の経験はございますか？
◆実装やコードレビューをするときにどういうことを意識していますか？
◆対外折衝や企画の要望を具体的なタスクに落とし込んだ経験はありますか？
◆どういう環境やチームだとストレスを感じますか？
◆上流と手を動かすのどちらが好きですか？

# 技術(言語/フレームワーク/アーキテクト/環境/開発手法)
◆言語のバージョンは何ですか？
◆phpで気を付けてる点はなんですか？
◆言語やmyadminのバージョンや違いについて
◆よいプログラムとは？
◆フレームワーク、デザインパターンは何を使っていましたか？
◆MVCモデル以外にデザインパターンは何か使っていましたか？
◆jsのライブラリーやフレームワークは何を使っていましたか？
◆aws、gcp、azureの経験はありますか？
◆オブジェクト指向について(使ったことあるか、ぞれぞれの使用用途など)
継承、抽象化、カプセル化、インターフェース、ポリモーフィズム
◆DOM操作はしたことがありますか？
◆クリーンアーキテクチャの知見はありますか？
◆得意としている担当工程や開発手法はございますか？
◆DDDの経験はありますか？
◆テスト駆動開発(TDD)の経験はありますか？

# DB設計/負荷分散
◆DB負荷分散、チューニングはどういうことをやっていましたか？
◆キャッシュは何を使っていましたか？
◆KVS(memcached、apc)は使っていましたか？
◆redis(レディース)は使っていましたか？
◆担当していたサービスで負荷の高いものだと、どのくらいの規模になりますか？
◆MySQLのEXPLAIN(エクスプレイン)を使ったことがありますか？
◆チューニングで苦労したことはありすか？
◆正規化はどこまでやっていましたか？


# ゲーム/Unity系
◆なぜゲーム業界にはいったのですか？
◆インゲームとアウトゲームどちらが得意ですか？
◆マルチ対応はしたことがありますか？
◆非同期処理は何を使っていましたか？

# その他技術
◆CIツール(Jenkins、Circle CI、github actionsなど)を使っていましたか？
【 React 】CSS変数を使った効率的な色管理方法: サブカテゴリの使用 と その他色管理方法

## はじめに
CSS変数（カスタムプロパティ）は、色を含むデザイン要素の管理を簡素化し、コードのメンテナンス性を向上させる強力なツールです。

この記事では、特に色が多くのデザインパターンにわたる場合に、サブカテゴリを使用して色を効率的に管理する方法について解説します。

## 基本的なCSS変数の設定
まず、基本的な色の設定方法をおさらいします。
**CSS変数**を使うことで、再利用性が高まり、**一貫性のあるデザインを保つ**ことができます。

```css:styles.css
:root {
  --primary-color: #3498db;
  --secondary-color: #2ecc71;
  --background-color: #ffffff;
  --text-color: #333333;
}
```

これらの変数は、以下のように使用します。

```css:top.css
body {
  background-color: var(--background-color);
  color: var(--text-color);
}

button {
  background-color: var(--primary-color);
}
```

## サブカテゴリの使用
**多くのデザインパターンに色が関わる**場合、**サブカテゴリ**を使用して色を整理することが非常に有効です。

例えば、ボタン、カード、ヘッダーなどのコンポーネントごとに **色変数を分けて管理** します。

```css:styles.css
:root {
  /* 基本色 */
  --color-primary: #3498db;
  --color-secondary: #2ecc71;
  
  /* ボタン色 */
  --button-primary-bg: var(--color-primary);
  --button-primary-hover-bg: #2980b9;
  --button-primary-active-bg: #1f639a;

  --button-secondary-bg: var(--color-secondary);
  --button-secondary-hover-bg: #27ae60;
  --button-secondary-active-bg: #1e8449;
  
  /* テキスト色 */
  --text-primary: #333333;
  --text-secondary: #666666;
}
```

## その他の管理方法
### (1)色の変形 (色合い、明度、彩度)
CSS変数を使って**色の変形**（明るくする、暗くする、彩度を変える）を行います。
**SassやLess**のようなプリプロセッサを使うと、さらに柔軟に変形できます。

```css:styles.css
:root {
  --primary-color: #3498db;
  --primary-color-light: #5dade2; /* 明るいバージョン */
  --primary-color-dark: #2e86c1; /* 暗いバージョン */
}
```

## (2)関連するデザインパターンごとの命名
**デザインパターンごと**に色変数を定義し、それぞれの**パターンに応じた名前**を付けます。
```css:styles.css
:root {
  /* カード */
  --card-bg: #ffffff;
  --card-border: #e0e0e0;
  --card-shadow: rgba(0, 0, 0, 0.1);

  /* ヘッダー */
  --header-bg: #f8f9fa;
  --header-text: #333333;

  /* フッター */
  --footer-bg: #2c3e50;
  --footer-text: #ecf0f1;
}
```

## (3)モジュール化
プロジェクトを**モジュールに分割**し、それぞれの**モジュールで特定の色変数を定義・使用**します。

```css:_buttons.css
:root {
  --button-primary-bg: #3498db;
  --button-primary-hover-bg: #2980b9;
  --button-primary-active-bg: #1f639a;
  --button-secondary-bg: #2ecc71;
  --button-secondary-hover-bg: #27ae60;
  --button-secondary-active-bg: #1e8449;
}
```

```css:_cards.css
:root {
  --card-bg: #ffffff;
  --card-border: #e0e0e0;
  --card-shadow: rgba(0, 0, 0, 0.1);
}
```

## (4)カスタムプロパティによる動的変更
JavaScriptを使用して**カスタムプロパティを動的に変更する**ことで、多様なデザインパターンに対応できます。
```javascript:script.js
document.documentElement.style.setProperty('--primary-color', '#3498db');
```

## さいごに
CSS変数を使って色を管理する際に、**サブカテゴリ**を活用することで、コードの可読性とメンテナンス性が大幅に向上します。

コンポーネントごとに色変数を整理し、必要に応じて色を変形させることで、柔軟かつ効率的な色管理が可能になりました。
Ginを使ったWeb APIをreleaseモードで起動する方法と、環境変数の使い分け

# はじめに

Ginを使ったWeb API起動時には、基本的に以下の文が表示されます。

```
[WARNING] Running in "debug" mode. Switch to "release" mode in production.
```

これは開発環境なら問題ありませんが、デプロイの際にはreleaseモードとして起動する必要があるということです。

そこで、releaseモードでの起動方法と、ついでに環境変数の使い分けについて紹介しようと思います。
<br>

***バージョン一覧***
| 使用技術 | バージョン |
|:-:|:-:|
|  go |  1.22.0 |
|  gin |  1.9.1 |
|  godotenv |  1.5.1 |


# releaseモードでの起動

これは簡単で、起動時のコマンドを以下のようにするだけです。

```
GIN_MODE=release go run cmd/main.go
```

このコマンドによって起動すると、起動時に
```
[GIN-debug] GET ~
[GIN-debug] GET ~
[GIN-debug] POST ~
```

のように表示されていた、debug特有の表示がなくなります。

ターミナルには何も表示されていませんが、実際にAPIにアクセスするとレスポンスが返ってくることが確認できます。

# 環境変数の使い分け

先程release時には、以下を実行する必要があると紹介しました。

```
GIN_MODE=release go run cmd/main.go
```

この***GIN_MODE***の値をmain.goで読み取ることによって、envファイルの使い分けが可能になります。

具体的には、以下のコードになります

```go
    // GIN_MODEを読み取る
    env := os.Getenv("GIN_MODE")
    
    // GIN_MODEが設定されてなければdevelopmentを代入
	if env == "" {
		env = "development"
	}

	// .envファイルの読み込み
	err := godotenv.Load(fmt.Sprintf(".env.%s", env))
	if err != nil {
		log.Fatal("Error loading .env file")
	}
```

これによって、***.env.release*** や ***.env.production***といったファイルを準備することで、環境変数を使い分けることが出来ます。

makefileに以下のようなコマンドを準備しておけば、簡単に使い分けることが可能になります。
```makefile
# 開発段階でのサーバ起動
run-dev:
	go run cmd/main.go

# 製品段階でのサーバ起動
run-release:
	GIN_MODE=release go run cmd/main.go
```

# おわりに

どちらも、デプロイしよう！と意気込んだ時に軽く手こずったので誰かの参考になれば幸いです。

読んでいただき、ありがとうございました！
Difyを用いた日本の郵便番号APIの実行

# はじめに
今回は、Difyを用いて日本の郵便番号APIを実行した。
・日本の郵便番号API

https://zenn.dev/ttskch/articles/309423d26a1aaa

郵便番号を入力すると、その番号に合った市区町村名が出力される仕組みである。
Difyの詳細については、以下の通りである。

https://dify.ai/jp

以下に、導入を示す。

# 導入
今回は「ワークフロー」のタイプで作成した。
アプリケーションの全体像は下記のようになっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/8df0a7a5-6308-4530-deba-590168a5417c.png)


開始の部分では、変数名を postal_code とし、ラベル名を 郵便番号 とした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/a8f9388b-a693-5e68-9eda-a846ab428dbb.png)

HTTPリクエストの部分では、まずAPIをGETに設定した。
URLには、
~~~
"https://jp-postal-code-api.ttskch.com/api/v1/{x}postal_code.json
~~~
を入力する。
また、ボディは none を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/f0fcbe47-61b3-6d49-7812-ca953a24b8e5.png)

続いて、LLMを追加し、リクエストの結果から住所を変換する。
言語モデルに対し、質問を行ったり指示を出すことができる、USERプロンプトに、
｛x｝bodyから住所に変換してください。と入力。
ここで変換例を記入することで、シンプルな出力結果を得ることができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/87105da2-5345-32e9-4e70-79a390b6eeb6.png)


変換例なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/76913f54-5a12-6249-8ebc-035e33078096.png)

変換例あり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/9045ce79-a48e-ff44-a63c-2d0fd531987d.png)

終了部分では、出力変数に、LLMの変数{x}textを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/dd409708-2d91-256d-0cd4-a827d828dc62.png)


# 実行結果
郵便番号を入力すると、入力された郵便番号と、それに合った市区町村名が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/a486049e-42d9-df49-f0eb-6ec930e512d7.png)


# まとめ
今回は、Difyを用いて日本の郵便番号APIを実行した。
今後もDifyを使った様々なアプリケーションを作成していきたいと考えている。
The Benefits of Outsourcing Mobile App Development

In today's digital age, having a mobile app has become crucial for businesses to stay competitive. However, building a mobile app requires specialized skills and expertise only some developers possess. Therefore, it's essential to carefully evaluate a developer's qualifications and experience before hiring them to create your mobile app. Here are some factors to consider when looking for a mobile app developer:
[Hire Mobile App Developer.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3106968/61793847-5d29-3953-56eb-805e99543f0a.jpeg)

1.	Technical skills: A mobile app developer!
 Should!
 Have strong technical skills in app development, including knowledge of programming languages such as Swift, Java, Kotlin, and React Native. They should also be familiar with mobile app development frameworks, APIs, and databases. Ensure that the developer you hire has the skills to create the app you need.

2.	Portfolio: It is important to evaluate a developer's portfolio before hiring them. Look at their previous work and assess the quality of their apps. Evaluate the user interface, functionality, and user experience of the apps they have developed in the past. Check if the developer has worked on apps similar to yours.

3.	Communication skills: A mobile app developer should have excellent communication skills, as they need to collaborate with you to understand your vision and requirements for the app. They should be able to communicate technical concepts in simple language and be responsive to your feedback and queries.

4.	Professionalism: Look for a professional and reliable mobile app developer. They should clearly understand timelines, budgets, and project requirements. Ensure they have a professional work ethic and are committed to quality work.

5.	Relevant experience: Look for a mobile app developer with relevant experience in the type of app you want to build. For example, if you're building an e-commerce app, look for a developer with experience building e-commerce apps. This way, they will understand your app's specific requirements and be able to deliver quality work.

6.	References: Ask for references from the developer's previous clients. Speak to their past clients and ask about their experience working with the developer. Did the developer deliver the project on time and within budget? Were there any issues during the development process? How did the developer handle those issues?

7.	Pricing: Finally, consider the developer's pricing structure. While finding a developer who fits your budget is important, you shouldn't compromise on the quality of work. When negotiating the price, consider the developer's experience and the project's complexity.

 In conclusion, hiring a mobile app developer requires careful evaluation of their technical skills, portfolio, communication skills, professionalism, experience, references, and pricing. Considering these factors, you can find a developer who can create a high-quality mobile app that meets your requirements and helps your business stay competitive in the digital age.
CSSで変数を扱う

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

# CSSで変数を扱う

いまでは当然といえば当然なんですが、
かつてはCSSで変数を扱うとなるとSCSSやSass等のメタ言語を使う必要がありました。
しかしCSSがアップデートされ、いまは素のCSSで変数に相当する「カスタムプロパティ」が
扱えるようになりました。
これがあるとCSSの設計やコーディングが非常に楽になるので、自己学習も兼ねてメモ記事にしてみます。

## まずは実例

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="NWVvozB" data-pen-title="css_custom_property" data-user="pluscolor" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/pluscolor/pen/NWVvozB">
  css_custom_property</a> by pluscolor (<a href="https://codepen.io/pluscolor">@pluscolor</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 書き方

### プロパティの宣言

プロパティの宣言自体は単純です。
適応させたいスコープの中で、--のあとにプロパティ名と値を記入するだけ。
以下の書き方だと　sample 内でのみ有効になります。

```css
.sample {
  --font-large: 48px;
  font-size: var(--font-large);
  }

/*スコープ外なので適応されない
.outofscope {
  font-size: var(--font-large);
  }
```

全体に適応する場合は擬似クラスを使って以下のように書きます。

```css
:root {
  --color-orange: orange;
  }
```

#### 注意点

大文字・小文字を区別します。
--color-orange と　--Color-orange は別のプロパティとして扱われます。

### 使い方

使い方は適応させたい箇所をvar()で囲って宣言するだけ。

```css
.fruit {
  background-color: var(--color-orange);
  }
```

#### 注意点

先ほども書きましたが、スコープに注意です。
クラス内で宣言したものはクラス内でしか使えません。


## まとめ

CSSを書いていくと同じ値を何度も使い回すシーンがあると思います。
そういうときに、プログラミング的に共通で利用するカスタムプロパティを用意しておけば
視認性も保守性も高くなって便利だと思います。

ベテランほど知らなかったりするので、ちょくちょくと広めて行きたいな。
DX-Suiteの操作指導を受けました！

### こんにちは！
### 生き物好きのエンジニア【<font color="red">JPW</font>】です！！
##### 今回は在職中の会社でも取り扱いのある「DX-Suite」の操作指導を受けた感想をお伝えします！

## そもそもDX-Suiteってなに？
DX-Suiteという名前を聞いたことのない方は、まずこの疑問が出てきたと思います。
そこでまずは、DX-Suiteで使用されている【<font color="red">AI-OCR</font>】という物についてざっと説明いたします。

### OCRってなあに？
“ OCRとは？ ”

Optical Character Recognition（光学式文字読取）の略で、活字や手書き文字などを画像データとして取り込み、編集可能なテキストデータ（文字コード）に変換する技術のことです。

>[OCRについての参考サイト](https://www.panasonic.com/jp/business/its/ocr/column/column-ai-ocr.html)

AI-OCRはAIの深層学習によってOCRの読み込み精度をさらに上げたものになります。



### じゃあどういうときに使えるの？
例を挙げると、「FAXで送られてきた注文書の内容がCSVデータで欲しい！」という際に活用できます。

①FAXで送られてきた紙の注文書をプリンターでスキャンしてPDF化
②PDF化されたデータをDX-Suiteで読み込んで項目ごとにテキスト化
③テキスト化されたデータをCSVで出力

従来のOCR技術ですと、FAX送信時に黒く霞んでしまっている文字などを認識することが難しいです。
しかし、AIの深層学習をOCRに＋することでFAXの文字も高確率で読み取ることが出来ます！

> こちらにAI-OCRの効率的な使い方が記述されています
(https://kyosopras.biz/blog/1056/)

## 実際に操作してみてどうだったか
そして実際に操作指導を受けてまず感じたことは「UIがわかりやすい」と思いました。
今回は定型的な帳票を4枚読み込んで、結果をcsvに出力するという物でした。
最初にワークフローを作成する必要があります。
対象の書類を一つ読込んで、「この位置にあるのは会社名」「この位置にあるのは合計金額」と設定します。
その設定もドラッグで囲んで名称を付けるだけなど簡単に設定することが出来ます。
初めて触る私でも直感的に操作することが出来たので、その点がすごくよかったと感じました。

## RPAツールとの相性について
RPAツールによりますが、相性はいいと思います。
AI-OCRにRPAを組み合わせることで、さらに工数を削減することが出来ます！
しかし、既にRPAを扱っている企業、既にAI-OCRを使用されてる企業は検討がしやすいですが、最初から2つを利用するとかなりの費用が掛かってしまいます。
ですので、費用対効果などもしっかり視野に入れつつ検討しなくては、「使用してみたけどあまり効果を実感できなかった」や「費用に比べて利益が対して伸びない」という「RPA損」を事前に確認することが大切です。

## 最後に
##### 以上がAI-OCRを触ってみた感想と最後にRPAとの相性も考えてみた結果になります！
##### 参考になれば幸いです！
AI-900の受験日記

# 1. はじめに
AzureのAI-900を受験しましたので、日記ついでに情報共有させて頂きます。
AI-900はこちらの記事でも紹介している、AzureのAI分野の入門資格です。

https://qiita.com/JinichiroYoshida/items/d582ee659de586dfb61a


# 2. 出題範囲
- 機械学習の基礎
    - 特徴とは？ラベルとは？
        - 築年数と床面積から土地の価格を予測させたい場合、特徴とラベルは何が適切かなど
    - 回帰／分類／クラスタリングなどの分析モデルの違いついて
        - 大学試験に合格するかを予測する学習モデルを構築したい、どの分析モデルが適切かなど
- 責任あるAI
    - 公平性・包括性・透明性・アカウンタビリティ・安全性・信頼性・セキュリティ・プライバシーの知識
        - こういうケースだと責任あるAIのうち、何を考慮する必要があるか？
        - こういう考慮を行うことは、責任あるAIの何に該当するのか？
- AzureのAIサービスについて
    - 自然言語・画像生成・顔認識・OCR・音声・翻訳・機械学習などの各サービスについての知識
        - こういうケースではどのAzureサービスを利用すればよいか？
        - このAzureサービスで利用できる機能は何か？

:::note warn
**注意**
上記はざっくりとした出題範囲です。
詳細は以下の公式ページを参照してください。
:::

https://learn.microsoft.com/ja-jp/credentials/certifications/azure-ai-fundamentals/?practice-assessment-type=certification


# 3. 学習方法と時間について
私はAI初心者だったので、初めに参考書を購入しようと考えましたが、**AI-900の日本語の参考書は見つけられませんでした。。**

参考書なしでMicrosoftLeanとUdemyの問題集をメインで学習しましたが、実際に出題範囲自体はそれほど広くないので、それだけで十分学習できました。

https://www.udemy.com/share/108TQa3@Y9PuN2ZUPp87eSVy_5kuROcT_qyY0JUyY3yt4PEJesJZ5Y_1iGMHUlVZAnF4LSSYDw==/

学習自体は２日ぐらいでザラっと終わらせて、その後２日程度で模擬テストをやれば大丈夫だと思います。
機械学習の評価モデルに関する出題は、回帰や分類のより詳細な種類（ロジスティックス回帰どうなど）なども出題されますが、出題数自体はかなり少ないので、試験に合格するだけなら数学チックな部分はスルーしても良いかもしれません。（正しい知識を身に着けるという観点では、当然適切に学習すべきだと思いますが。。）


# 4. 最後に
私はAIの知識が全くない状態で学習を開始したので、「AIの基礎を知る」という意味でも大変勉強になりました。
AIよく知らないけど勉強したいという人にはとてもおススメな資格です！
「大学入試の複素数平面の問題は、何のためにありますか?」(回答抜粋)をAI先生に聞きました。

(2025-04-04)旧タイトル
ChatGPT-3.5先生へ「大学入試の**複素数**の問題は、何のためにありますか?」

User
大学入試の**複素数平面**の問題は、何のためにありますか?
受験生の負担が増えるだけだと思います。
業界の人の飯の種ですか。
必要な人は、大学で勉強したらいいと思います。

# Gemini先生へ
(2025-04-04)
(回答抜粋)
>大学入試の複素数平面の問題は、受験生の負担を増やすだけの無意味なものではなく、いくつかの重要な目的と意義があります。
複素数平面が大学入試に導入される主な理由
1.数学的な思考力・表現力の育成:
・図形的な視点の導入:...
・抽象的な概念の理解:... 
・論理的な記述力:...
2.理工系分野との接続:...
　電気・電子工学: ...
　物理学:...
　情報工学:...
　数学:...
3.選抜の多様性:...
「受験生の負担が増えるだけ」という意見について...
「業界の人の飯の種」という意見について...
「必要な人は、大学で勉強したらいい」という意見について...
まとめ...

# ChatGPT-3.5先生へ
**古いです** (2024-06-10)
User
大学入試の**複素数の問題**は、何のためにありますか?

User
受験生の負担になりませんか

User
大学入試の複素数の問題は、平面図形の問題に、書き換える事はできますか?

ChatGPT
例1：

例2：

つづく

# copilot先生へ


# いつもと違うおすすめです。
・分野が違いますけど,参考にしました。
　ふるさと@レアテック 様へ。ありがとうございました。
>必要性・差分・反例を考える。
オブジェクト指向の仕組みや、便利さを知るよりも先に、「必要性」を知る方が、理解度を深めてくれることが多いです。逆に言えば、**その必要性を知らなければ、何が便利になったのかもわからないのです。**

https://qiita.com/t-furusato/items/c7c434d02fc538f1e793#%E5%BF%85%E8%A6%81%E6%80%A7%E5%B7%AE%E5%88%86%E5%8F%8D%E4%BE%8B%E3%82%92%E8%80%83%E3%81%88%E3%82%8B
特定のSRA (Sequence Read Archive) IDを使用してFASTQ形式のHi-Cデータをダウンロードするスクリプト (失敗した場合に1分後にリトライ成功するまでループ)

この記事では、特定のSRA IDを使用してFASTQ形式のHi-Cデータをダウンロードするスクリプトの作成と実行方法について説明します。スクリプトは、失敗した場合1分後にリトライする機能を備えています。

## conda仮想環境構築
まず、必要なパッケージをインストールするためのconda仮想環境を作成します。

```bash
conda create -n sra_env_x86_64 python=3.8
conda activate sra_env_x86_64
```

## SRAtoolsのインストール
次に、SRAtoolkitを仮想環境にインストールします。

```bash
conda install -c bioconda sra-tools
```

## インストールの確認
インストールが正しく行われたか確認するために、以下のコマンドを実行します。

```bash
fastq-dump --version
```

## スクリプトの作成
以下のスクリプトを任意のエディタで作成し、`download_fastq.sh`という名前で保存します。

```bash
#!/bin/bash

SRA_ID=$1
OUTPUT_DIR="/path/to/your/output_directory"
LOG_FILE="${OUTPUT_DIR}/${SRA_ID}.log"

# conda環境のアクティベート
source $(conda info --base)/etc/profile.d/conda.sh
conda activate sra_env_x86_64

while true; do
    nohup fastq-dump --split-files --outdir ${OUTPUT_DIR} ${SRA_ID} > ${LOG_FILE} 2>&1
    if [ $? -eq 0 ]; then
        echo "Download completed successfully."
        break
    else
        echo "Download failed, retrying in 1 minute..."
        sleep 60
    fi
done
```

## 実行方法
スクリプトを実行するには、ターミナルを開き、スクリプトが保存されているディレクトリに移動して以下のコマンドを実行します。

```bash
bash download_fastq.sh <SRA_ID>
```

`<SRA_ID>`の部分は、ダウンロードしたいSRAのIDに置き換えてください。

## 実行中の動作
スクリプトを実行すると、以下のようなメッセージがターミナルに表示されます。

- ダウンロードが成功した場合:
    ```
    Download completed successfully.
    ```
- ダウンロードが失敗し、リトライする場合:
    ```
    Download failed, retrying in 1 minute...
    ```

これにより、Hi-Cデータのダウンロードプロセスが自動化され、失敗した場合も再試行することで、データを確実に取得することができます。

## ログファイルについて
スクリプトは、ダウンロードプロセスの詳細なログを指定されたログファイルに保存します。ログファイルのパスは、`LOG_FILE`変数で指定されており、各SRA IDに対応したファイル名が生成されます。これにより、ダウンロードプロセス中に発生したエラーや進行状況を確認することができます。

例えば、SRA IDが`SRR123456`の場合、ログファイルは`/path/to/your/output_directory/SRR123456.log`という名前で保存されます。ログファイルには、`fastq-dump`コマンドの出力が全て記録されます。
Javaの値をJavaScriptで使用する方法

# やりたいこと
JavaScriptでJavaの値を使用する。
フレームワークはSpringBootで、thymeleafを使用する。

# 使用例
バックエンドであるJavaでデータベースの値を得て、JavaScriptがその値を参照したいとき。

# 実践例
```HomeController.java
@GetMapping("/home")
public String view(Model model) {
    model.addAttribute("キー名", 値);
    return "home";
}
```
キー名を指定してJavaScriptで使用したい値をmodelに格納する。キー名は任意。
```home.html
<html xmlns:th="https://www.thymeleaf.org" lang="ja">
<script th:inline="javascript">
const a = /*[[${key名}]]*/"key名";
<script>
</html>
```
JavaScript内でこのように記述したらaにJavaの値が入る。

# これを使った例
Google Maps APIを使用した際にこのやり方を使った。
Google Maps APIはJavaScriptで操作するため、Javaでのデータベースの値を使いたい時に使った。

# 参考にした記事
https://qiita.com/curry__30/items/5e19294d457f3322f647
ECS Scheduled Tasks利用時の問題点とその対策

## 問題点

- ECS Scheduled Tasks の実態である EventBridge では、スケジュールされた期間に対して同じルールを複数回トリガーする可能性がある

  - [参考 ①](https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-troubleshooting.html?fbclid=IwAR2rYOjBfgh0N6n_zt_7mnyjdWt5gqj7Ez2xSkEABV23vRdNAAcUYWAI4Ug#eb-rule-triggered-more-than-once)
  - [参考 ②](https://qiita.com/nishimura-toru/items/a706b941a9046c71b9ea)
- 弊社ではユーザーへのメール送信など複数回実行されては困るケースがあるので、これをなんとかしたい

- 対策として DynamoDB を使って実行中タスクのロックを実装するという手段があるが、EventBridge ではタスク実行中だけでなく終了後にも起動されるパターンがあるので、そのケースに対応できない

  - [参考](https://qiita.com/omukaik/items/82b6619c6b505e180e40)

- そもそもこの手法は運用フレンドリーなのか？という疑問

## 対応策

- 2023/11/13 から CLIのECS RunTaskでタスク起動の冪等性がサポート可能となったのでこれを使う
  - [参考 ①](https://aws.amazon.com/jp/about-aws/whats-new/2023/11/amazon-elastic-container-service-idempotency-launches/)
  - [参考 ②](https://dev.classmethod.jp/articles/idempotent-ecs-task-run/)

- 具体的には、以下のようにECS RunTask 実行時のclient-tokenパラメータでトークンを仕込むことにより、タスクロックの仕組みを自前で用意しなくても、同じtokenが指定されている場合は冪等性を担保した状態でタスクが処理される

    ```
    aws ecs run-task \
      --cluster MyCluster \
      --task-definition MyTaskDefinition:2 \
      --client-token 550e8400-e29b-41d4-a716-446655440000
    ```
- 正常に完了した後で、同じクライアントトークンと同じリクエストパラメータを使用して API リクエストを再試行すると、元のリクエストの結果が返される
   - [参考 ①](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/ECS_Idempotency.html)
   - [参考 ②](https://dev.classmethod.jp/articles/idempotent-ecs-task-run/)

- クライアント・トークンの TTL は以下の小さい方なので、タスク終了後に再実行されるケースにも対応できる

  1. 24 時間
  1. タスクが STOPPED になってから+1 時間

- ただし、CloudFormation のプロパティで直接的にこれを定義する方法はないので、ワークフローの中で aws ecs run-task コマンドを実行する形である必要がある

- また、1時間以内の間隔でタスクを実行したい場合でも、tokenのTTLによって実行が阻害されてしまいます。なのでその場合だけtokenの指定を外して重複実行の可能性を許容する、もしくは違うジョブスケジューリングツール（Jenkinsやdigdagなど）をEC2にホスティングして動かすことになると思います

## ワークフローの選択肢

1. EventBridge Scheduler で lambda 関数を実行し、その中で ECS RunTask を実行する。

   - シンプルに実装可能だが、15分の実行時間上限がある
   - lambda内でECS RunTaskを実行した場合、タスクの起動を完了とみなす（起動したタスクの完了まで待つわけではない）ので、ECS RunTaskだけ実行したい場合はこちらの方法でこと足りる

2. EventBridge Scheduler で AWS Batch を起動し、ECS RunTask を実行する。

   - 15分の実行時間上限を取り払いたい場合はこちら

3. EventBridge Scheduler で StepFunctions を起動し、ECS RunTask を起動する。

   - より複雑なワークフローを定義可能

4. docker コンテナで cron を動かす
   - ある意味わかりやすい
   - 理論的には可能だが、1 コンテナ 1 プロセスという docker のベストプラクティスと乖離するため極力避けたい

弊社の場合は複雑なワークフローは不要かつ、ジョブの実行時間は15分を超えることはないので①の選択肢としました
また、定期実行の選択肢としてEventBridge RuleとEventBridge Schedulerがありますが、EventBridge Schedulerの方がタイムゾーンの指定やタイム ウィンドウ スケジュールなど、よりスケジューリングに最適化されているのでこちらを使った方が便利です
[参考](https://dev.classmethod.jp/articles/eventbridge-scheduler-and-event-bridge-rule-difference/)

## 最終的な構成

①CircleCIから`aws cloudformation deploy`を実行する
②CloudFormationがEventBridge Schedulerの定義を最新化する
③EventBridge Schedulerで定義されているスケジュールでLambda Functionが実行される
④Lambda FunctionでECS RunTaskを実行し、ECSタスクが実行される

![無題のプレゼンテーション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139602/8bd5f8e6-295b-f812-e1f2-85990c01ab7f.jpeg)

## 一難去ってまた一難
上記の方法で1時間以上の間隔のジョブについては対応できるようになった。
しかし、1時間以内の間隔の場合、トークンによって重複実行と見なされてしまうため、トークンを指定せず重複実行を許容しなくてはならない点に注意。
これが気になるなら、もはやEventBridgeからdigdagのようなワークフローエンジンに移行を検討した方が良さそう。（筆者は1時間以内のジョブに関してはジョブサーバーで運用する方針としました）
SpringBootにおける3層アーキテクチャとMVC

# はじめに
Spring Bootを学習する中で「3層アーキテクチャ」と「MVC」の違いについて躓いたので，整理がてら簡単にまとめました．
初学者で理解が浅いところが多いので，間違い等あればご指摘お願いします．


# 3層アーキテクチャとは
Webアプリケーション開発の設計思想（アーキテクチャ）の一つで，以下の3層に分類される．

- プレゼンテーション層
- ビジネスロジック層
- データアクセス層（インフラ層）

Spring Bootの場合は，ビジネスロジック層を「アプリケーション層」と「ドメイン層」の2つに分けて，4層から構成されている．
（ドメインモデル云々などドメイン駆動設計に関する知識が無いため省略します）

## 各層について
### 1. プレゼンテーション層
ユーザ側とのやり取りを行うインタフェースとして機能する層．ユーザからの入力を受け付けたり，アプリケーション層からの結果を表示するなど．

### 2. アプリケーション層
ドメイン層で実装されたロジックの呼び出しを実施する層．

### 3. ドメイン層
Webアプリケーションのコアな業務処理や仕様を実装する層．

### 4. データアクセス層（インフラ層）
外部のDBやファイルとの入出力などのやり取りを行うインタフェースとして機能する層．


# Model View Controller(MVC)とは
3層アーキテクチャと同様，Webアプリケーション開発の設計思想の一つ．
主な違いは，MVCはプレゼンテーション層とアプリケーション層（ドメイン層）における設計思想になる．
（3層アーキテクチャはシステム<font color=yellow>**全体**</font>の設計思想）

### 1. Model
外部のDBやファイルとのやり取りを行うインタフェースとして機能する層

### 2. View
ユーザとのやり取りを行うフロントエンド的なインタフェースとして機能する層

### 3. Controller
ModelとViewの制御を行う層

図解すると恐らくこんな感じ．
![3-LayerArchitecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799758/3f487e26-baec-bebf-7434-736ba6b6628f.png)



# 参考
- [MVC、3 層アーキテクチャから設計を学び始めるための基礎知識](https://qiita.com/os1ma/items/7a229585ebdd8b7d86c2#%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AF-4-%E5%B1%A4%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%93%E3%81%A8%E3%82%82)
- [第2回 プログラム構成編【誰もが一度はつまずくSpring Bootを解説♪】【若手Javaエンジニア向け】](https://stechup.co.jp/springboot_pgstructure/)
- [Model View Controller](https://ja.wikipedia.org/wiki/Model_View_Controller)