OmniAICreator/Qiita-1.07M huggingface dataset:
AIのROIを高めるために、プロセスを統合し簡素化させる

過去20年間でAIの価値創造に対する障壁は大きく変わりました。20年前は計算能力とストレージが障壁でしたが、クラウドコンピューティングがそれらを事実上無料にしました。次にクリーンでラベル付けされたデータが課題となり、私たちはデータウェアハウス、Hadoopデータレイク、ETL、ELT、データクリーニング、データ調和の開発に何年も費やしました。

次に、ボトルネックとなったのは人間の技術的スキルでした。誰もがAIや機械学習（ML）モデルを訓練し、統計的に有効な実験を行い、MLOpsを開発し、ビジネスの目標を理解できるデータサイエンスのユニコーンを雇おうとしました。しかし間もなく、ユニコーンは存在しないということを学び、代わりにユニコーンチームを構築しました。

今日、お客様との仕事をしていて私が見ている最大の障壁は人のスキルが多く挙げられますが、今回は、非技術的な障壁 — ビジョンと想像力の2点が挙げられます。

組織は目標を低く設定しすぎています。しばしば、AI開発チームは、価値が少なく[フロントラインのユーザーサポートが不十分](https://pages.dataiku.com/build-trustworthy-ai-systems)なポイントソリューションのユースケースを優先し、開発に1倍のコストがかかり、さらに導入と採用にも5倍のコストがかかり、0.5倍の価値しか生み出さないことで、驚異の-92%のROIをもたらします。（[医療](https://sloanreview.mit.edu/article/ai-on-the-front-lines/)と[保険](https://www.riskmarketnews.com/aigs-hancock-data-science-insurtech-casualty/)からの例を参照ください。）

## 技術価値創造の3つのレベル
過去300年間、破壊的な技術のユースケースは3つのレベルに分かれています。価値が高い順にすると以下の通りです。

1: ポイントソリューション: 例えば需要予測、顧客流出予測、予測保全など
2: プロセスを再設計するアプリケーション
3: 新しい一連のプロセスを導入するシステム

2番目のレベルで良い例としてJohn LeeによるNBCUniversalを取り上げます。
客観性に注意：私はファンボーイです。Johnは数年前、私がMerkleでクラウドとAutoMLへの移行を手伝った時の上司の上司でした。（私たちは一つの大きな共有SASサーバーから多数のAWSアカウントと弾性的なSparkクラスターへと移行しました。それはまるで、17世紀のヨークシャーの乳牛農家を今日のニューヨークシティのタイムズスクエアにドロップしたようなものでした。なんという旅でしょう！）

Johnにはビジョンがあります。彼はAIをたくさんの小さなポイントソリューションに適用するのではなく、むしろそれを使って主要なプロセスを再設計しています。それは一世代前には何階もの人々が実行していたプロセスです。ビデオメディアタイプ別の広告分析の分野のこのチャートを考えてみてください：
![Screenshot 2024-02-15 at 5.28.26 PM.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/ca97ae48-26c1-41a1-a740-7787cf220e4a.jpeg)

直接収集するデータで、例えば私がPeacockでYellowstoneを視聴していることをNBCUが知っていること、または私が緑のポロシャツを購入していることをNikeが知っているというものです。ビューアーのアイデンティティ管理は、NBCUやNikeへのアクセスに使用する全てのIDとデバイスを統合することです。メディアプランニングは、Nikeが広告を表示すべき場所、例えばYellowstoneのストリーミング上などを決定し、アクティベーションは広告を配信することです。["Mad Men"](https://www.youtube.com/watch?v=yj9rokSeack)の時代から使われてきたメディア指標には、広告を見る人の数（リーチ）と、それをどのくらいの頻度で見るか（頻度）が含まれます。リーチと頻度は手段に過ぎず、目的はNikeのビジネス目標です。それにはブランド認知度、ブランドに対する好印象、ウェブサイト訪問数、ウェブサイトの売上、ウェブサイトの収益、またはDick’s Sporting Goodsでの増分売上などがあります。

この表には18のセルがあります。二世代前、各列はそれぞれ独自の会社であり、一世代前は大きな代理店の独自のフロアでした。今日、それらは依然として大きく異なる、自身のデータ、ツール、および専門用語を持つ孤立したチームです。そのような専門化は、列の複雑さのために必要でした。JohnはビッグデータとAIを利用してその複雑さを大幅に削減し、18のサイロを1つの統合されたプロセスに収束させています。テレビ広告の[Henry Ford](https://www.youtube.com/watch?v=-QSe8RhWoK8)とでも言いましょうか。

このようなAIによるプロセスの収束はデジタルランドスケープ全体で起こっています。Epsilonも私たちのマーテック顧客の一つです。彼らはコネクテッドTV、ストリーミング、ウェブディスプレイ広告、オーディオ、SMS、メール、ウェブトラフィックなどをカバーする[リアルタイムのオムニチャネルハイパーパーソナライゼーションプラットフォーム](https://www.epsilon.com/us/products-and-services/epsilon-digital)を開発しました。Unilever（またDataikuのユーザーでもあります）はEpsilonのプラットフォームをウェブサイトのパーソナライゼーションに適用し、識別された顧客数を倍増させました。

## 何をすれば良いのか？

AIプロダクトのバックログを見てみてください。それらはすべてポイントソリューションですか？最も価値のあるものについて、プロセスを再設計するアプリはどのようなものでしょうか？アプリについては、新しいAI駆動のシステムはどのようなものになるでしょうか？私たちはデータソン、ハッカソン、ユースケース創発ワークショップ、ユースケーススコーピングワークショップを通じて、何百もの企業を支援してきました。さらに詳しく知りたい方は、ぜひ[お問い合わせ](https://www.dataiku.com/home/contact-us/)ください。
 
## ビジネス価値を高めるための7つの具体的な方法
ビジネスデータを一度きりではなく継続的なビジネス価値に変える準備はできていますか？[このEBOOK](https://pages.dataiku.com/more-value-from-analytics-ai
)は、分析とAIプロジェクトから繰り返しビジネス価値を確実に生み出すための7つの実用的な方法をカバーしています。
【Backlog記法チートシート】wiki作成にもPRにも役立つ…！？

# はじめに

こんにちは、エンジニア2年目の嶋田です。
まずは、この記事を開いていただきありがとうございます！

今回はBacklogチートシートを作成しました。

というのも、[markdown記法]("https://support-ja.backlog.com/hc/ja/articles/360036145833-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E6%95%B4%E5%BD%A2%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB-Markdown-%E8%A8%98%E6%B3%95-")とは違い、[backlog記法]("https://support-ja.backlog.com/hc/ja/articles/360035641594-%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E6%95%B4%E5%BD%A2%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB-Backlog%E8%A8%98%E6%B3%95-")となるものが存在するみたいでして。
wikiを書くとき、課題作成の内容を書くときに少し戸惑ってしまったので…
(markdownもプロジェクトによって選択可能です！)
備忘録としてまとめます！

## Backlog記法チートシート
| 機能           | 記法         |結果   |
|----------------|------------------|------------------------|
| 見出し        | `* 見出し1` <br>`** 見出し2`<br> `*** 見出し3`    |<img alt="見出し" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524119/00d50e1f-774a-d798-710a-b9c8ff9a71b6.png"> |
| 箇条書き      | `- 箇条書き1`<br> `- 箇条書き2`<br> `-- 箇条書き2-1`<br> `--- 箇条書き2-1-1`  |<img alt="箇条書き" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524119/6b56bd58-6e4e-6dc2-e7d6-8dc8a9545a25.png"> |
| 番号付きリスト | `+ 項目1`<br> `+ 項目2`  |<img alt="番号付きリスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524119/937cadf9-7ae4-af8a-b74d-ec0a7def0b75.png"> |

### 強調
- `'''太字テキスト'''`
- `''斜体テキスト''`
- `%%打ち消しテキスト%%`
- `&color(red) { 赤文字テキスト }`
- `&color(#ffffff, #8abe00) { 背景色付きテキスト }`

### リンク
- `[[リンクテキスト>URL]]`

### コードブロック
- `{code:言語}コード{code}`
- `{code}コード{code}` (言語指定なし)

### 表
- `|見出し1|見出し2|`
- `|:------|------:|`
- `| 左寄せ | 右寄せ |`

### チェックボックス
- `- [ ] 未チェック`
- `- [x] チェック済み`

### 引用
- `> 引用文`

### 水平線
- `---`

### 色付きテキスト
- `{color:red}赤いテキスト{color}`

### 注釈
- `((注釈テキスト))`




## Markdown記法とBacklog記法の主な違い

1. **見出し**:
   - Markdown: `#` (ハッシュ)記号を使います（例: `# 見出し1`, `## 見出し2`）。
   - Backlog: `*` (アスタリスク)記号を使います（例: `* 見出し1`, `** 見出し2`）。

2. **リスト**:
   - Markdown: 箇条書きに`-` や `*` を使い、番号付きリストに数字を使用します。
   - Backlog: 箇条書きに`-` を使い、番号付きリストには`+` を使用します。

3. **強調**:
   - Markdown: `**テキスト**` または `__テキスト__` で強調（太字）。
   - Backlog: `'''テキスト'''` で強調（太字）。

4. **リンク**:
   - Markdown: `[表示テキスト](URL)`。
   - Backlog: `[[表示テキスト>URL]]`。

5. **画像**:
   - Markdown: `![代替テキスト](画像URL)`。
   - Backlog: `[[画像(画像URL)]]`。

6. **コードブロック**:
   - Markdown: バッククォート（`）3つで囲みます。
   - Backlog: `{code}` タグを使用します。


# 最後に
少しでもお役に立てたら嬉しいです！


# 参考文献
https://backlog.com/ja/enterprise-help/userguide/userguide1686/

https://backlog.com/ja/wiki-guide/practice/02/
コンテナ上の VSCode にリモートからブラウザでアクセスする (または vscode.dev 的なものをセルフホストする話 )

# 要約
- リモートからブラウザで自分の VSCode にアクセスしたくなり VSCode Server (code serve-web) を用いて環境を構築した
  - (参考) [VSCode Serverがなくなって本体に統合されていた](https://qiita.com/ku_suke/items/07b67bd710b17a3a7cf3)
- ブラウザでアクセスする点では serve-web と vscode.dev は近しいが (おそらく) extension に制限がない、ローカルのファイルにはアクセスできない、など使い勝手は大分異なる
- [codercom/code-server](https://hub.docker.com/r/codercom/code-server) に近しいと思われるが純正の serve-web を選択した
- serve-web をリモートに公開する際の注意点としては、
  - 引数に `--host` を付加する
    - 付加しないとリモートからアクセスできない
  - 引数に `--without-connection-token` を付加する
    - 代わりの認証の仕組みが必要
  - HTTPS でアクセスする
    - HTTP でアクセスすると [Unauthorized client refused.](https://github.com/microsoft/vscode/issues/191276) が発生する
- 使用時の注意点としては、
  - `Ctrl+W` などブラウザに取られるショートカットを使用したい場合は他のキーを割り当てる必要がある
  - "User Settings" や "Keyboard Shortcuts (keybindings.json)" がファイルに残らない様子
    - ブラウザ間で設定を共有したい場合はプロファイルのエクスポート＆インポートが使える
  - [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) 使えた

# 手順
- [前の記事](https://qiita.com/ArK38/items/475269970717de1a0d43)に従い Docker や認証に使用する Nginx Proxy Manager の準備を行う
- [ココ](https://code.visualstudio.com/download)から Linux の CLI(x64) を取得する (code)
- ダウンロードした code と同じディレクトリ (vscode とする ) に以下のような Dockerfile を作成する

```dockerfile
FROM node:latest

ENV HOME=/home/vscode
WORKDIR ${HOME}

ADD code /usr/bin/code
RUN chmod 500 /usr/bin/code

# 必要なものを適宜追加
RUN npm install -g typescript

# --hostを指定しないと外部からアクセスできない、portはcommand(CMD)で外から渡す
ENTRYPOINT ["/usr/bin/code", "serve-web", "--accept-server-license-terms", "--without-connection-token", "--host", "0.0.0.0", "--port"]
```
- ビルドする
```shell
docker build --rm=true -t=vscode vscode
```
- 以下のような `docker-compose.yml` を作成して `docker compose up -d`
```yaml
version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
#      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
# ここから Quick Setup に無い定義
    depends_on:
      - vsnode
  vsnode:
    image: 'vsnode'
    restart: unless-stopped
    command: '8000'
    volumes:
      - ./vscode:/home/vscode
```
- [前の記事](https://qiita.com/ArK38/items/475269970717de1a0d43)に従い HTTPS や Basic 認証の設定を行う
- ブラウザでアクセスできることを確認する
  - ![vscode1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1060173/d321e5af-c273-670c-3773-75aa36e68a29.png)
- 適宜プロキシの設定を加えた後に、 Live Server も使えることを確認する
  - ![live1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1060173/c837b865-8d4c-d0fb-8286-b7b838bbf869.png)
- 以上です
Railsフォームで`fields_for`を使用せずにネストされた属性を扱う方法

# Railsフォームで`fields_for`を使用せずにネストされた属性を扱う方法

Railsの`fields_for`メソッドは、フォーム内でネストされた属性を簡単に扱うための便利なヘルパーです。しかし、特定の状況や要件により`fields_for`を使えない場合があります。この記事では、`fields_for`を使用せずにネストされた属性をフォームで扱う方法を紹介します。

## 前提条件
`hospitalsテーブル`、`business_daysテーブル`、`hospital_business_daysテーブル`、`hospital_business_hoursテーブル`がある。
`hospitalsテーブル`と`business_daysテーブル`は`hospital_business_daysテーブル`を中間テーブルとして多対多。`hospital_business_daysテーブル`と`hospital_business_hoursテーブル`は1対多の関係である。

## 基本的な考え方

`fields_for`を使用せずにネストされた属性を扱う主な方法は、フォームの`input`フィールドの`name`属性を手動で設定することです。これにより、コントローラに正しくネストされたパラメータを送信することができます。

例として、`hospital`オブジェクトに関連する`hospital_business_days`とその中の`hospital_business_hours`というネストされた属性を扱います。

## 具体的なコード例

以下は、`hospital`オブジェクトのアップデート用フォームで、`hospital_business_days_attributes`とその中の`hospital_business_hours_attributes`を送信するための入力フィールドの例です。

```html
<input type="hidden" name="hospital[hospital_business_days_attributes][<%= index %>][business_day_id]" value="<%= business_day.id %>">
<td>
  <input type="time" name="hospital[hospital_business_days_attributes][<%= index %>][hospital_business_hours_attributes][0][open_time]" value="<%= hospital_business_hour.open_time&.strftime('%H:%M') %>">
</td>
<td>
  <input type="time" name="hospital[hospital_business_days_attributes][<%= index %>][hospital_business_hours_attributes][0][close_time]" value="<%= hospital_business_hour.close_time&.strftime('%H:%M') %>">
</td>
```

このコードでは、`index`は各`hospital_business_days`オブジェクトのインデックスを示し、`business_day.id`はその`business_day`のIDです。`hospital_business_hour.open_time`と`hospital_business_hour.close_time`はそれぞれ開始時間と終了時間を示します。

## Strong Parametersの設定

フォームから送信されたネストされた属性をコントローラで正しく扱うためには、Strong Parametersを適切に設定する必要があります。以下は、`hospital`オブジェクトのパラメータを許可するための例です。

```ruby
params.require(:hospital).permit(hospital_business_days_attributes: [:business_day_id, hospital_business_hours_attributes: [:open_time, :close_time]])
```

## まとめ

`fields_for`を使用せずにネストされた属性を扱う方法は、フォームの`input`フィールドの`name`属性を適切に設定することで実現できます。この方法は、特定のシナリオやカスタムフォームの要件に応じて役立ちます。ただし、Strong Parametersの設定には注意が必要です。

---

この記事が、`fields_for`を使用せずにネストされた属性を含むフォームを作成する際の参考になれば幸いです。
windowsコマンドでフォルダ内の全ての.htmlを.phpに再帰的に変更する

記事タイトルのままです。備忘録。

## 手順
１．コマンドプロンプトで該当フォルダに移動

２．以下のコードを実行
~~~ 
for /r %x in (*.html) do ren "%x" *.php
~~~

## 結果
フォルダ内の全ての.htmlを.phpに再帰的に変更される。
（ChatGPTちゃんありがとう！）
DynamoDBのTTL機能を試しました

# やりたいこと
DynamoDBのTTLの動作確認をしたい

# やってみる！
まず、「2024-02-26 13:30:00」頃から作業スタート！

テストテーブルを作成し、expiration項目を作り、画像のようにデータを入れる

expiration項目は、ただの項目名であり、自由に命名できるから、expirationじゃなくても大丈夫～

テーブル作成時に、デフォルトTTLがオフになってますが、後で「オン」に変更したいと思う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/9146fd6c-10e6-07d0-3090-8cac758f44c4.png)


expiration項目には、「有効期限」をUnixtime形式で格納し、後でTTLを「expiration項目」に紐づける

今回は試しに、「2024-02-26 14:00:00」を有効期限にする

データを永遠に残し続けたい場合、expiration項目には0を格納する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/e2b71aa3-6610-780e-4fff-2274ca86411e.png)

そして、TTLの設定を～

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/cbb2102b-08c4-dd1a-965e-b6affcf90fd7.png)

TTL属性名に、先ほど作っておいたexpirationを記入

プレビューを押すと、「これから削除されるデータ」を洗い出してくれるね～

そして、以下の記載もあって、
「TTL の有効化がすべてのパーティションに適用されるまでに最大 1 時間かかることがあります。この更新が完了するまで、追加の TTL の変更を行うことはできません。」

要は、TTLは既存のデータの適用できるけど、適用するのに最大1hかかるよってこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/472c4800-8745-338f-e7e7-ac7dd71cfa9e.png)

「TTLをオンにする」を押すと、画面がこう遷移し、設定完了！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/ec800e11-8344-c0a9-be3b-5babefa8d2e7.png)

再び、テーブルのデータ内容をみると、表示が「expiration (数値) (TTL)」になった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/63c256ae-55b9-c490-391c-d6cad560ef90.png)

「適応に最大1hかかる」ということに気になって、「2024-02-26 13:30:00」の作業で「2024-02-26 14:00:00」の削除は間に合うか心配で、、、

14時になったら、さっそくデータを確認しようと

あれっ、まだいるね、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/0abac489-3d4f-7a47-72f2-e28939414f7f.png)

やはり、適用するのに間に合わないか、といろいろ調べたら、

AWSの公式ドキュメントに以下の記載があった！
「DynamoDB は、有効期限から数日以内に期限切れの項目を自動的に削除します。」

要は、リアルタイムの削除ではなくて、有効期限になって数日以内にどっかのいいタイミングで削除するということか！？

そのあと、1分間隔でチェックすると、「2024-02-26 14:09:00」頃データがなくなった！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/70f27f93-d79c-1f02-64e1-03a594a6dacf.png)

# 終わりに
以前テキストでTTLの仕組みを勉強したことあったが、今回動作確認することで、削除のタイミングやTTLの設定方法など、改めて理解を深めることができた。

今回はデータが1行しかなくて結構少ないので、適用に1hもかからなかったが、データが大量にあった場合、TTLを適用するのにもっと時間かかるかもしれませんね。

そして、時間になってすぐ削除ではないことも気をつけないといけないかなと思って、データ削除の即時反映が絶対要件の場合、TTLが不適切かもしれないと感じた


# 参考サイト

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/TTL.html

https://dev.classmethod.jp/articles/try-dynamodb-ttl/
Snowflake：記事：目次

### ■目次
### ■初期設定
説明：トライアルや新規契約アカウントを想定し、
　　　データベース作成までの初期設定関連をまとめています。
[①ACCOUNTADMIN編](https://qiita.com/taku_tachibana/items/b293ed07c8303999dcc6)
[②SECURITYTADMIN編 NETWORK POLICY](https://qiita.com/taku_tachibana/items/6de80c90bef72ce0a9fd)
[③USERADMIN編 ユーザー ロール作成](https://qiita.com/taku_tachibana/items/9c340cb3b40261095127)
[④SECURITYADMIN編 ロール階層作成](https://qiita.com/taku_tachibana/items/4d6895ffcac3edc473e7)
[⑤SECURITYADMIN編 ユーザーへのロール割当て](https://qiita.com/taku_tachibana/items/7fb7dc8e2b63c3e9fc72)
[⑥SYSADMIN編 仮想ウェアハウス作成](https://qiita.com/taku_tachibana/items/ff8e3f2776aab169b4d4)
[⑦SYSADMIN編 データベース作成](https://qiita.com/taku_tachibana/items/171df9a2be79ba4f805f)
[⑧SYSADMIN編 スキーマ作成](https://qiita.com/taku_tachibana/items/477041e4288f3b6cac91)

### ■Snowflake記述作法
説明：ワークシートやSnowSQL利用の際の記述作法になります。
[Snowflakeの記述作法について](https://qiita.com/taku_tachibana/items/1b394f015c4c365075bb)

### ■S3データロード
説明：AWS構成で、S3の外部ステージ利用でのデータロードの方法になります。
[①ストレージ統合](https://qiita.com/taku_tachibana/items/42f5e424c2325db5bfae)
[②ファイル形式](https://qiita.com/taku_tachibana/items/6ca0f9a49158260c1e39)
[③外部ステージ](https://qiita.com/taku_tachibana/items/030ed2720ee25039dc12)
[④COPY INTOによるデータロード](https://qiita.com/taku_tachibana/items/9c54f4a4dde5f1cf9853)
[ストレージ統合設計](https://qiita.com/taku_tachibana/items/ff335fd3b39e2eb9029e)

### ■Excelデータロード（非推奨）
説明：個人的には非推奨ですが、Excelデータをロードしてみました。
[Pythonによるロード（単一ファイル）](https://qiita.com/taku_tachibana/items/bda725cd2b6993f482e3)
[Pythonによるロード（特定フォルダ内の複数ファイル）](https://qiita.com/taku_tachibana/items/795ec176cc1d179b8426)

### ■Azure BLOB Storageデータロード
説明：Azure構成で、BLOB Storageの外部ステージ利用でのデータロードの方法になります。
[①ストレージ統合](https://qiita.com/taku_tachibana/items/e9ce026e2a41eab50341)
[②ストレージネットワーク構成](https://qiita.com/taku_tachibana/items/4252293bf53d498f971c)
[③外部ステージ～データロード](https://qiita.com/taku_tachibana/items/7aa800b012ba76a9bb45)

### ■資格関連情報
[Snowflake Advanced : Arichitect Certification Exam 合格備忘録](https://qiita.com/taku_tachibana/items/3e5055d8379e2cf1c365)
wingetで更新しようとしてカーソルが青くなるだけでインストールできない場合はwingetを更新する

## はじめに
会社のPCの調子が悪く、PCを交換してもらった後wingetでうまくインストールできなかったので同じ問題ではまった人向けのメモです。

## 状況
PCが壊れたので、wingetで必要なアプリをインストールしようとしたところ、winget install パッケージ名 でアプリをインストールしようとすると、カーソルが青くなるだけでインストールが始まりません。

## 原因
検索してみると、winget 自体のバージョンが低いと発生するようです。
`v1.2.10691` だとダメっぽいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/72b5d33c-67a7-5dd7-9209-a3c3b2b80013.png)

## 解決策

いくつかのページでマイクロソフトストアから更新できるとありますが、僕の環境ではストアから`アプリインストーラー`を検索しても引っ掛かりません。

winget-cliのgithubを確認すると、ストアページへのリンクがあったのでここから更新します。

https://github.com/microsoft/winget-cli

https://apps.microsoft.com/detail/9nblggh4nns1

ストアから更新したら `v1.6.3482` になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/2bf4ac1b-a18d-3051-879f-21c5bb4ebe93.png)

## おわりに

winget も apt などと同じように自信を簡単にアップデートできるようにしてほしいですね。
Spark の Dataframe を１レコードのみ Python の辞書型変数に変換する際の注意事項

## 概要

SparkのDataframeをPythonの辞書型変数に変換する際、最初の1レコードのみを対象とする場合があります。このとき、Dataframeが空である可能性を考慮することが重要です。以下に、collectメソッドの出力結果の最初のインデックスの値を取得し、asDictメソッドで変換するプログラムを示します。

```python
data = [
    ("Alice", 25),
]
df = spark.createDataFrame(data, ["Name", "Age"])

df_data = df.collect()
df_data[0].asDict()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/50d97771-6b11-1b21-5794-e1bc64c33871.png)


Dataframeが空の場合、以下のようなエラーが発生します。これは、collectメソッドの出力結果がリスト型変数であり、存在しないインデックスを指定したためです。

```python
# 空のDataframeを作成
empty_df = df.filter("1=0")
empty_df_data = empty_df.collect()

empty_df_data[0].asDict()
```

```text
IndexError: list index out of range
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/eb5f1f31-df17-60ca-b957-68172f4e7543.png)


通常、このようなコードを記述することは少ないですが、備忘録としてその対応方法を本記事にまとめておきます。

## コードと実行結果

### 事前準備

```python
data = [
    ("Alice", 25),
]
df = spark.createDataFrame(data, ["Name", "Age"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ca4b8a26-533a-cdbd-5410-d647fd9624f1.png)


### 基本的な動作確認

```python
df_data = df.collect()
df_data[0].asDict()
```

```text
{'Name': 'Alice', 'Age': 25}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e669eeb9-e049-1e77-1c76-4f5914097b25.png)

### エラーケースのコードを実行

以下のコードを実行すると、empty_df_data[0].asDict()の部分でエラーが発生します。これは、empty_df_dataが空のリストであり、empty_df_data[0]が存在しないためです。

```python
# 空のDataframeを作成
empty_df = df.filter("1=0")
empty_df_data = empty_df.collect()
```

```python
empty_df_data[0].asDict()
```

```text
IndexError: list index out of range
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/de255806-936b-39f8-414d-c1e2590d7e2b.png)

### データフレームが空であることを考慮した改善

以下のコードでは、`empty_df.limit(1).count() > 0`によりDataframeが空でないことを確認しています。Dataframeが空であれば、"empty_df_data is empty"と表示され、エラーは発生しません。

```python
empty_df = df.filter("1=0")
```

```python
if empty_df.limit(1).count() > 0:
    empty_df_data = empty_df.collect()
    empty_df_data[0].asDict()
else:
    print("empty_df_data is empty")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c5215f81-7e34-eb61-a7db-6fb083808414.png)
WSR-2533DHP2にOpenWRTを入れるメモ

準備
１　下記から「openwrt-mediatek-mt7622-buffalo_wsr-2533dhp2-initramfs-kernel.bin」をDL。
    https://taiha.net/jenkins/job/OpenWrt-master-BUFFALO-WSR-2533DHP2/
２　TFTP準備。下記等。
    https://pjo2.github.io/tftpd64/
３　TFTPに１のbinファイルを「linux.trx-recovery」にリネームして配置。
４　PC側でTFTP待ち受け開始。

TFTP起動でバックアップ取得
１　PCと有線接続。
２　PC側のNICを
    IP: 192.168.11.2
    mask: 255.255.255.0
    gateway: 192.168.11.1
    に固定。
３　AOSSボタン押しながら電源ON。TFTPでファイル送信がはじまるまで押しっぱなし。
４　送信完了したらPC側NICをDHCP有効化。
５　PC側NICに「192.168.1.?」が割り振られたら、ブラウザから「http://192.168.1.1 」にアクセス。
６　WebUIのSystem->Backup/Flash firmware
７　Save mtdblock contentsで全てのmtdblockをバックアップ
８　本体再起動

実際にOpenWRTを書き込む
１　ファームウェアをダウンロード。23.05.2は下記の「buffalo_wsr-2533dhp2-squashfs-factory.bin」
https://downloads.openwrt.org/releases/23.05.0/targets/mediatek/mt7622/
１　BuffaloオリジナルのWebUIを開く。
２　ローカルファイルからのアップデートで「buffalo_wsr-2533dhp2-squashfs-factory.bin」を書き込み。
３　しばらく待って本体が自動的に再起動し、PC側のNICに「192.168.1.?」が割り振られたら、ブラウザから「http://192.168.1.1 」にアクセス。

以上で完了。
Html構文を取得後、UTF８に変換する際の注意点

# Html構文を取得後、UTF８に変換する際の注意点

アップルのサイトにWebサイトをフェッチ（Fetch)する時のサンプルとして以下のコードを載せている。

しかし、このコード内には推奨されない関数が使われている。

```swift:Sample
func startLoad() {
    let url = URL(string: "https://www.example.com/")!
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            self.handleClientError(error)
            return
        }
        guard let httpResponse = response as? HTTPURLResponse,
            (200...299).contains(httpResponse.statusCode) else {
            self.handleServerError(response)
            return
        }
        if let mimeType = httpResponse.mimeType, mimeType == "text/html",
            let data = data,
            let string = String(data: data, encoding: .utf8) {
            DispatchQueue.main.async {
                self.webView.loadHTMLString(string, baseURL: url)
            }
        }
    }
    task.resume()
}


```

このサンプルコードはサンプルWebサイトのhtml文をData型で取得しUTF8にエンコードしてStringに変換している。
では使うべきでない関数は何かというと、utf8にエンコードするときのこの構文だ。

```swift
  let string = String(data: data, encoding: .utf8)

```

Dataからutf8に変換できない文字が１つでもあれば、Stringはnilを返す。しかし、本来なら変換できない文字を文字化けさせてでもStringで返すべき処理なのではないだろうか？　一般的にこの関数を使用していて変換できない文字に遭遇した場合、nilに対する処理をしていないので、そこでプログラムはクラッシュする。これを避けるために次の関数を代わりに使用する。

```swift
let string = String(decoding: data, as: UTF8.self)

```
MacでKeychron K8 Pro 日本語配列（K8P-J1-JIS）をBluetoothで接続した時、US配列として認識されてしまう現象の解決方法

私は某商社の社内SE・システム責任者として勤務しています。

社内では営業さんや事務員さんにサポートを行う際、リモートデスクトップで操作を行うことが多く、キーボードの配列はJISが使いやすいのです。

弊社ではWindowsの利用が基本ですが、私の所属しているシステム部門では（私のわがままで）Macを使わせていただいています。（Windows・Macの両刀です）

もちろん開発・プログラミングも頻繁に行いますが、JIS配列と共に歩んで来た人生。
US配列への強い憧れはあるものの、社内SEとしてJIS配列を使っていきたいという気持ちもあります。

そんな葛藤の中、MacのJIS配列キーボードでメカニカル、打鍵感の気持ちいいものとなると、もうKeychronさんまたはLogicoolさんしか無く、ヨドバシカメラにて実機を触り、今回Keychron　K8　Proに決定。

ヨドバシオンラインにて、K8P-J1-JISを購入させて頂きました。

https://www.yodobashi.com/product/100000001007517457/

US配列への憧れの強いJIS配列信者社内SEの願望はここまで。

## 環境
Macbook Air M2 8GB 8コアCPU10コアGPU　512GB

## 結論

Karabina-ElementsのDevices >　Keychron K8　Proの「Modify events」がOFFになっていた。
ONにすることで、Bluetooth接続時でもJIS配列として正常に認識されました。

確かに、キーボード系のソフトウェアとしてキーマップを上書きしているようなので、これは競合してもいた仕方ありませんね。

某サイトのレビューでは「Macで使えない」と記載してあるが、恐らくキーボード系のアプリを入れない環境が
メーカーの本来の検証環境であり、Karabina-Elementsのような必須級アプリはサードパーティ製のため、
考慮されていないのかもしれません。

ちなみに、この記事もKeychron K8 Pro　で書いています。
【Linux】時刻合わせ

# はじめに
システムクロックとハードウェアクロックを手動にて合わせる方法を備忘として残しておきます。

# システムクロック確認
```
date
```
# ハードウェアクロック確認
```
hwclock -r
```
# システムクロックを変更する方法
```
例：date -s "12/31 23:59 2099"
```
# ハードウェアクロックを変更する方法
```
例：hwclock --set --date "31 Dec 2099 23:59"
```
# ハードウェアクロックの時刻をシステムクロックに設定する方法
```
hwclock --hctosys
```
# システムクロックの時刻をハードウェアクロックに設定する方法
```
hwclock --systohc
又は
hwclock -w
```

# おわりに
あまり手動設定はせず、次のような使われ方が多いのかなと思います。
①NTPサーバを利用してシステムクロックを合わせ、cronで定期的に hwclock -w を実行して、システムクロックをハードウェアクロックに反映させる。
②Amazon Time Sync Serviceを使用する。(AWSを使用している場合)
java これだけは知っておきたいJava install.

### 最初に悪気は、無いと言っておこう。
javaをインストールしても、動かんとか、思った動きをしてくれな、と言う方におススメの記事としたい。
後からSDKを入れているはずなのに入ってなとか、SDK入れたら本体が消えたとか。
最初、俺も分からんかったのや、だから、恥じる事はない。
### 見つけたきっかけ
![スクリーンショット 2024-02-26 104300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625232/a830ed05-f891-60a1-ecad-9325c8e662c6.png)

トムキャットがエラーで動かんかったのや。これは、installされていなかった場合も、起きてた。つまり、有効ではない、問う事に思いあたった。
そこで、installされている、javaのプロパティを見てみると
C:\Program Filesにいるんだから当然、厳重な制限を受けてるよな。
### そこで、プロパティをいじる事に
![スクリーンショット 2024-02-26 113336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625232/091ed439-a295-6226-7d6d-07dfb058b991.png)

読み取り専用を外してから作業に当たろう。
変更が有効になるように、チェックを外す事から、始めます。
大元の「Java」を選択して「プロパティ」右クリックメニュー。
![スクリーンショット 2024-02-26 113154.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625232/75abdeb1-528c-caa5-4c01-8f5792f07597.png)

userのフルコントロール権限で、すべてを有効に出来る。
出来なかったら、ロックされてるところから外してく「フルコントロール」。
そして「編集」選択「チェック」「適用」「OK」と進み、最終的にチェックして終える。
その後、SDKのインストールをやって、本体が消えたら、再度設定して、再インストール。
なお、注意しなければならないのは、C:\Program Files (x86)にもJavaがあるという事。こちらも、忘れずに、やっておこう。
### 最後に
![スクリーンショット 2024-02-26 123810.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625232/ff52e7c9-7ce9-3f96-c532-5922d1549d2e.png)
上の写真の様になったら、二つ入っていて、他のアプリからも使えるだから「ok」と思う。
単純に「c:\Java」から、不用意に動かしたらいけませんよ。
それでは。
Snowflake Advanced : Arichitect Certification Exam 合格備忘録

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)

### ■受験の目的
Snowflakeの設計・運用の知識をつけるため
Snowflake Advanced Arichitectの認定を受けるため

### ■出題範囲
シラバスは以下を参照し、情報を収集します。
https://learn.snowflake.com/courses/course-v1:snowflake+SPSG-ARA+A/about

・ユーザー登録およびログインを行ってください。
・PDFでダウンロードしておくと、スマホからも使用できて便利です。
・シラバスは更新されますので、必ず最新版を確認して、ダウンロードしてください。
　※大体ですが、2～3カ月くらいで更新されている頻度だと思います。

### ■受験の前提
各種Advanced資格を受験するためには、
基礎資格である[SnowPro Core]の試験に合格している必要があります。

### ■受験のメリット
Snowflakeのデータ分析、検索、運用、セキュリティにおけるベストプラクティスの設計を習得できます。
詳しくは、上記のシラバスの内容になります。
特典として、Advanced試験に合格すると、Core資格の有効期限が、Advanced試験合格後2年間に延長されます。
※他のAdvanced資格を取得している場合は、そちらは延長されません。各再認定を受験する必要があります。

### ■教材
有料のTrainingもあるのですが、$3000とかなり高額なので、個人では手が出ませんでした。
そのため、シラバスを参照し、各出題セクションごとのURLからリファレンスを見て、学習しました。
リファレンス参照のポイントとして、不明点があれば、各所のリンクに寄り道してもいいので、一つずつ理解していくことをお勧めします。（地道に行きましょう）

### ■模擬試験
模擬試験はUdemyで購入
https://www.udemy.com/course/snowflake-ara-c01-certification-exam-sample-questions/
解説を"読む","覚える","再度テストする"を5周くらい繰り返しました。
正答率低いカテゴリは、リファレンスに戻って再学習します。

### ■学習期間
筆者の場合、実務である程度Snowflakeを取り扱っていたためと、
2カ月前に不合格だったAdvanced DataEngineerと共通出題の箇所もあったため
2カ月くらい（土日・連休込みの勉強）でパスできました。

### ■実際の本試験
日本語に対応した試験が発行されていましたので、そちらで受験しています。
全65問中の半分ほどは、模擬試験の内容に近い問題が出題されました。
時間は、2周目の見直しを行えるくらいの余裕があった感じです。
見直し精査で、"8/65問"ほど不安要素の問題がありましたが、
結果は8割以上のスコアで、満足のいく結果でした。

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
【資格試験を受ける方へ】不合格体験記のすゝめ

# 1. はじめに（結論）
__何かしらの試験を受ける予定があれば__
__不合格体験記を読みましょう。__

以上。

# 2. 補足
いきなり何のこっちゃと思われたかもしれません。失礼しました。
ＡＲアドバンストテクノロジ株式会社（ＡＲＩ）の鈴木タクヤです。

先日LPIC-1 101試験というものを受けまして無事合格できたのですが、その際に「不合格体験記」がものすごくためになったというお話です。

正直「Level 1の認定だし、余裕でしょ！」と侮っていたのですが、試験の前々日にある不合格体験記を目にして嫌な予感が。そして他の不合格体験記もいくつか読み漁るうちに私は青ざめました。 __そこに記載されていた不合格者の受験直前の状況が、自分のそれとほぼ同じだったからです。__

要約するに

:::note
・Level 1 だからと侮っている
・有名学習サイト「Ping-t」の正答率は80%程
・入力式の問題の対策不足
・他人の合格体験記を読んでいない
:::

また、

:::note warn
・本試験の出題内容は「スピードマスター問題集」（山本道子・大竹龍史 著、翔泳社）に近い
:::

という記載が複数の記事で共通していました。こちらは事前に購入しており、勉強方法を「スピードマスター問題集」に注力して解きつつ、入力問題で出題されそうなコマンドやフルパスを暗記する方向にシフトしました。

すると私が受けた試験では、選択肢まで含めてこの本の内容とほぼ同じ問題が複数出題され、自信をもって回答を進めることができました。もし試験の前々日に不合格体験記を読んでいなければ、間違いなく私は落ちていたと思います。

以上、合格体験記も参考になりますが、不合格体験記に救われたというお話でした。

加えて、もし試験に不合格となった場合には、不合格体験記を投稿することが、反省点の洗い出し& __人助け__ になるかもしれません。不合格体験記も非常に有意義だと感じました。

# 3. 参考
https://yassanabc.com/2021/11/02/1%E5%9B%9E%E8%90%BD%E3%81%A1%E3%81%A6%E5%88%86%E3%81%8B%E3%81%A3%E3%81%9F%E3%80%81lpic-level1-%E5%90%88%E6%A0%BC%E3%81%AE%E3%82%B3%E3%83%84/
Flutter image_pickerで端末から取得した画像のサイズ（メガバイト）を出す

# はじめに
Fluterで端末から画像を取得してアップロードするときなど、あらかじめ画像のサイズを知りたい場面がありました。

例えば、サーバーの容量を圧迫しないように、サイズが大き過ぎる画像はアップロードさせないなどなどの処理を入れたい場合などである。

画像を扱うパッケージはもちろんimage_picker

https://pub.dev/packages/image_picker

また、コードはriverpodで状態管理をしてあります。

https://riverpod.dev/ja/


# 画像を端末から取得する


```dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.dart';

  static final pickImageFromGallery = Provider.autoDispose(
    (ref) => () async {
      final image = await ImagePicker().pickImage(
      // 画像を取得する
        source: ImageSource.gallery,
      );
      if (image != null) {
        // バイト配列（Uint8List）へ変換
        final imageBytes = await image.readAsBytes();
        // 画像のバイト数（サイズ）を取得
        final bytesLength = imageBytes.length;
        // 1メガバイトは1000キロバイト（KB）なので、バイト数を1000で割り、その結果をさらに1000で割る
        final mbAmount = bytesLength / 1000 / 1000;
        print("画像のサイズ: $mbAmount MB");
        return imageBytes;
      } else {
        return null;
      }
    },
  );

```

1MB = 1000000バイトなのでこのような式になってます。

```
1000000 / 1000 / 1000 = 1 MB
```

# 注意点

シュミレーターで試したところ、アプリで表示されるサイズと実際にログで確認できるサイズが若干異なることが多くありました:sweat:

![Screenshot 2024-02-26 at 12.17.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/02590b50-d3f6-2100-f878-6bfa526d2dbd.png)
![Screenshot 2024-02-26 at 12.17.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/8b94c231-9ea1-3261-d1d8-354d031e92ee.png)

シュミレーターにデフォルトで入ってる画像を確認すると、大枠あってる画像もありましたが少し違ってる画像もありました。

またHEIF形式の画像も違った数値で出力されていました。。。

https://support.apple.com/ja-jp/116944

![Screenshot 2024-02-26 at 12.24.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/c982e9ab-71a5-31a6-150e-66352d364b6b.png)

うーん、画像を扱うのはほんと難しいですね〜:joy_cat:

もっと他にいい方法や性格に画像サイズを計れる方法があれば教えてください！
DMX USB コントローラについて、久々ちょっと調べたよ～

# 初めに
ムービングライト（DMX)を久々コントロールする事になり
DMXコントローラーについて調べたので
メモを書きます。
2024/02/26

##使用するコントローラー
安くあげるなら、自作　（次の所で説明）
作るの大変ならENTTECのDMX USB PROとか

https://www.enttec.com.au/product/dmx-usb-interfaces/dmx-usb-pro-professional-1u-usb-to-dmx512-converter/

ちなみに、ENTTECのDMX USB PROは、お高いだけあって
DMXの信号を中でバッファリングして送出していたりします。

今回は、自作、ENTTEC製の物どちらも使って
DMX送出用のソフトウェアで認識させたいと思います。


### 自作コントローラー　（先人の知恵）
当たり前と言うか、私より綺麗にコントローラーについて纏められている
方がいるので、ほぼ下記を参考にすれば問題なく使えると思います。

https://qiita.com/Ina3/items/f88a584d2011e99fc7ed

内臓EEPROMデータの書き換え
の部分でFTDI chipの書き込みソフトのurlが変わってました。
他は同じです。

https://ftdichip.com/utilities/

#### DMXコントローラーソフトウェア
ENTTECのDMX USB PROの場合
公式にソフトが公開されています。
以前はENTTEC PRO-Managerと言う
インターフェイスもわかりやすい物が公開されていたのだが
サイト探してもどこにもない。。。（どなたか、分かる方いましたら教えて）
公式ページを見ると
EMU – Sound to Light Controllerと言うイカしたソフトウェアを使えと書いてあります。

https://www.enttec.com.au/product/dmx-lighting-control-software/emu-sound-to-light-controller/

アプリも右上の歯車マークからUSBでデバイスつながっていると
認識できるのでさらにデバイスの歯車ーくを押すと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/673ad48f-ce62-0e21-0237-5c70eb974342.png)

ファームウェアのアップデートもここでできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/b894c1fb-9bea-b3a5-c54f-c6c8f72a0d36.png)

自作の場合は「自作コントローラー」の所で先人の方が使っている
QLC+　　(http://www.qlcplus.org/ )
など使ってみてください。
こちらは、ENTTECのDMX USB PROもちゃんと認識します。

こんな感じでどっちも認識します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/77bc929f-4999-0902-8c12-56000bad7790.png)


##### 最後に
久々触ったら、ドライバ？ソフト？何使えば良いの？
となったので自分用のメモ用に取ってます。
なので、コピペじゃね～か。。内容無いじゃね～かは
ごめんなさい。

次は、ソフトでDMXのデータ作るところかな

こんなのとかｗ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/a9c185c5-5d95-1300-6f7c-4470b525232d.png)

こんなの制御したいｗ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/d436a97a-4367-5d8c-70ce-b0ca161feb57.png)
[翻訳転載] Golang Tip #7: 三項演算子

# はじめに

https://qiita.com/a10a/items/5063899c9f4a3bf4a2f2

本記事は以下のツイートの翻訳転載です。

https://x.com/func25/status/1729588275940352156?s=20

# 三項演算子

Goは、a > b ? a : bのような組み込みの三項演算子をサポートしていません。

しかし、Go 1.18からはジェネリックスを使って同じような機能の関数を実装できます。

![image](https://pbs.twimg.com/media/GAC7VL8bwAAHuZA?format=jpg&name=medium)

# おわりに

Goを書いていて三項演算子が欲しい場面は多々あるが、

- 三項演算子を使いたいケースは全て`if`で代用可能
- 三項演算子がネストされる場合、可読性がかなり落ちる

ため、Goで採用されていないのも納得できる。

> The reason is a simple design choice. The operator although once understood, is an easy one is in fact a complicated construct for someone who is new to code. The Go programming language chose the simple approach of if-else. This is a longer version of the operator, but it is more readable.
> 
> - https://golangdocs.com/ternary-operator-in-golang

それも含めて、

```go
Ter(true, 1, 2)
```

だと何をしているのか`Ter`の実装を見るまで（個人的には）本当にわからないので、
三項演算子の代替実装を導入するにしても関数名については要検討かと思う。

（三項演算子イコール`Ternary Operator`だと言うことに慣れていれば違和感ないのか？ちょっとわからない）

Go1.21で`cmp`パッケージが導入され、以下のようにデフォルト値を使用するために三項演算子を使用したい場合、`cmp.Or`で代用することができるので、
それで足りるなら`cmp.Or`を使用するのがいいと思う。

```typescript
const foo = bar ? bar : "baz";
```

```go
foo := cmp.Or(bar, "baz")
```

https://pkg.go.dev/cmp@master#example-Or
Vimを覚える【vimtutor Lesson 4】


# はじめに

前回の記事はこちらです。

https://qiita.com/kohki_takatama/items/857bf1a3caeb52f0fab2

Lesson 7 までなので、折り返しですね！

# Lesson 4.1

<font color="LimeGreen">「`Ctrl + g` で現在位置がわかるよ！」</font>ですね。
「ファイル名」と「現在のライン・カラム番号」「全体の相対位置」がわかります。
`"/tmp/tutorR6xznw" line 499 of 972 --51%-- col 1` というのが今の位置でした！
ちょうど半分ですね。

また、<font color="LimeGreen">`:set ruler`で、右下に現在位置が表示されるようになります</font>（すでに表示されてる人もいるかも）。

他にもありますね。
<font color="LimeGreen">`G`でファイルの最後にジャンプ</font>
<font color="LimeGreen">`gg`でファイルの最初にジャンプ</font>
<font color="LimeGreen">`数字 + G`で該当の行番号に移動</font> です。
（`: + 数字`でも同じく、該当の行番号に移動が可能です）

# Lesson 4.2

<font color="LimeGreen">「`/`で検索ができるよ！」</font>ですね。ちなみにカーソルから下方向に検索をします。
`?`で上方向に検索です。

`n`で検索を繰り返します。「次の一致する文言にジャンプ」ですね。
`N`で逆方向に検索を繰り返します。

少しややこしいのが、`ctrl + o` / `ctrl + i`と`n` / `N` の違いです。
`ctrl + o`は「ジャンプリスト」をさかのぼります。
`ctrl + i`は「ジャンプリスト」を進みます。
`n`と`N`は「検索」を繰り返します。
「何をさかのぼるのか、繰り返すのか」が大事ですね。

# Lesson 4.3

<font color="LimeGreen">`%`を押すと該当する「カッコ」にジャンプ！</font>ですね。

"console.log<font color="LimeGreen">(</font>hoge<font color="Orange">(</font>fuga<font color="Orange">)</font><font color="LimeGreen">)</font>" を例にします。
'console.log<font color="LimeGreen">(</font>" までのどこかにカーソルがあるうちは、"<font color="LimeGreen">)</font>" にジャンプします。
"hoge<font color="Orange">(</font>" のどこかにカーソルがあるうちは、"<font color="Orange">)</font>" にジャンプします。

閉じカッコにカーソルがある時は、開きカッコにジャンプします。

# Lesson 4.4

<font color="LimeGreen">`:s/old/new/g`で、行内の置換！</font>ですね。
簡単に分解すると、

- `s`が置き換えを意味します。
- `old`と`new`はそれぞれ置き換える前と後の文字列です。
- 最後の`/g`は「該当する全てに適用」ですね（global の g です）。ここでは行全体を示します。

`/g`が無い場合は、「最初に該当した文字列」のみに適用します。

行を対象とせず、特定の範囲を指定するには以下のコマンドを使用します。
`:1,10s/old/new/g`：`1,10`の部分で 1~10 行目を指定しています。
`:%s/old/new/g`：`%`でファイル全体を対象にします。

また、`/gc`で確認メッセージ付きの置換を行います。
一つ一つの置換に対して、置換をしても良いか確認をしてくれます。

# Lesson 4 修了！

おつかれさまでした！

# おわりに

全体の置換、確認メッセージ付きの置換など、超実用的でしたね。

あと 3 レッスン頑張るぞ〜！

次回記事はこちら

https://qiita.com/kohki_takatama/items/441aa3744230feeaa059
【ChatGPT有＋DALL-E3】連続して似たものを出すなら（not 一貫性）。


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

　今回は、連続して似た画像を出すなら、という内容です。一貫性はありませんが、それでも似た状況の画像は出せます。

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

　まずは、ニュースから。

　OpenAI が
　　新しいプロジェクト
　　　「Feather」を発表しました。

　詳細は
　　まだ明らかにされていませんが、
　　　画像生成やテキスト生成など、
　　　　さまざまなタスクを
　　　　　こなせる汎用 AI になる
　　　　　　のではないか、という噂。

　サイト入り口は
　　用意されていますが、
　　　無料版・有料版の
　　　　アカウントでは
　　　　　弾かれました。

　しばらく様子見ですね。
***
　さて、
　　本題にいきましょう。

　“連続して似た画像を出すなら”と
　　書きましたが、一貫性のある
　　　画像にするのは、
　　　　DALL-E3の性質上、難しい。

　テキストから
　　イメージを作成する生成AI
　　　なのですから。

　特別な命令が
　　あれば、いいのですけどね🙃

　それでも
　　似た内容の画像を
　　　出すことは、可能です。

　私の経験からの
　　ものですが、
　　　ふたつあります。
***
　【その１】　“リトライ”。

　これは、
　　私の記事を
　　　読んでくださる方は
　　　　ご存知でしょう。

　結構、使ってますからね。

　気に入った画像が
　　出力されたら、
　　　再度、描画してもらうための
　　　　文言です。

　また、この“リトライ”は、
　　画像の修正にも使えます。

　例えば、
　　黒猫の画像を出力したが
　　　白猫にしたくなった、
　　　　というときに
　　　　“リトライ。黒猫を白猫にして”
　　　　　　とするわけです。

　ここで注意なのは、
　　削除系の文言は使わないことです。

　使うと、
　　ChatGPTは
　　　きちんとDALL-E3に伝えます。

　すると、DALL-E3は、
　　削除と捉えずに、
　　　使うんだ、と判断します。

　“消せ、消せ”と
　　何度、言っても、ムダなのです。

　そういうときは、
　　ChatGPTに
　　　指示しなければいけません。
　　　　“同じでしょ？”と
　　　　　思いますよね。

　違うんです。

　指示の仕方が違うんです。

　リトライを使っての削除は
　　さきほど書いたとおり、
　　　ムダなのです。

　では、どうすればいい？

　以前にも書きましたが、
　　“プロンプトから削除するように”
　　　と言わねばなりません。

　そう、
　　プロンプトに
　　　書かれてしまうと
　　　　DALL-E3に“描け”と
　　　　　言っていることに
　　　　　　なりますから、
　　　　　　　プロンプトから
　　　　　　　　削除するのです。

　これは
　　英文プロンプトを出力させて
　　　編集して、そのプロンプトで
　　　　画像出力をさせるのと
　　　　　同じことですが、
　　　　　　手間が減ります。

　ただし、
　　どちらも
　　　確実ではありません。

　例えば、
　　風呂敷包みなんかを
　　　頼むと、ラッピングして
　　　　帯締めされてしまい、
　　　　　どうにもなりませんでした。

　諦めて、
　　ふつうの
　　　ラッピングにしました。
***
　【その２】　同じプロンプトを入力

　こちらは、
　　さきほどの
　　　黒猫を例にとると
　　　　プロンプト全体をコピペして
　　　　　黒猫のところを
　　　　　　白猫にする
　　　　　　　パターンですね。

　これは
　　プロンプトの
　　　必要箇所を
　　　　直すだけですから
　　　　　わかりやすいかと
　　　　　　思います。

　描画される画像は
　　基本的に似た感じになりますが
　　　画風などが変わってしまう
　　　　こともありますので、
　　　　　プロンプトに記述して
　　　　　　おくことを
　　　　　　　オススメします。
***
　この記事が
　　みなさんの
　　　作品制作の糧に
　　　　なれば、幸いです。

　今回は、ここまで。
[C#] DataTableのCSV出力の短縮

C#のCSV出力が短縮できたのでメモ

今までは（https://dobon.net/vb/dotnet/file/writecsvfile.html）
に記載されている書き方で作成していた。

```C#
    //CSVファイルに書き込むときに使うEncoding
    System.Text.Encoding enc =System.Text.Encoding.GetEncoding("Shift_JIS");

    //書き込むファイルを開く
    System.IO.StreamWriter sr = new System.IO.StreamWriter(csvPath, false, enc);

    int colCount = dt.Columns.Count;
    int lastColIndex = colCount - 1;

    //レコードを書き込む
    foreach (DataRow row in dt.Rows)
    {
        for (int i = 0; i < colCount; i++)
        {
            //フィールドの取得
            string field = row[i].ToString();
            //"で囲む
            field = EncloseDoubleQuotesIfNeed(field);
            //フィールドを書き込む
            sr.Write(field);
            //カンマを書き込む
            if (lastColIndex > i)
            {
                sr.Write(',');
            }
        }
        //改行する
        sr.Write("\r\n");
    }

    //閉じる
    sr.Close();
```


以下のように短縮することができた
```C#

    //CSVファイルに書き込むときに使うEncoding
    Encoding enc = Encoding.GetEncoding("Shift_JIS");
    
    //書き込むファイルを開く
    using (StreamWriter sr = new StreamWriter(strOutputPath, true, enc))
    {
        //レコードを書き込む
        foreach (DataRow row in ds.dtOutput.Rows)
        {
            sr.WriteLine(string.Join(",", row.ItemArray));
        }
    }

```


・解説
```c# 
//sr.Write → sr.WriteLineで、改行も含むように
sr.WriteLine(...
```

```c# 
//１行単位のcsvを作成
string.Join(",", row.ItemArray)
```
[翻訳転載] Golang Tip #6: アンダースコア Import

# はじめに

https://qiita.com/a10a/items/5063899c9f4a3bf4a2f2

本記事は以下のツイートの翻訳転載です。

https://x.com/func25/status/1729113992902361111?s=20

# アンダースコア（`_`） Import

多くのライブラリで、時折、次のようにアンダースコア（`_`）と組み合わせたimport文を見かけるかもしれない。

![image](https://pbs.twimg.com/media/F_8K_X9bAAAr1sQ?format=jpg&name=medium)

これは、名前参照をせずに、そのパッケージの初期化コード（`init()`関数）を実行しています。

例としてunderscoreパッケージを作成しました。ここには`init()`関数を定義してあります。

![image](https://pbs.twimg.com/media/F_8LRetaQAEQu_K?format=jpg&name=medium)

And in main(), using underscore import, even if I don't do anything, it still prints:
そして`main()`関数にて、アンダースコアimportを使用すると、それ以外に何もしなくてもunderscoreパッケージの`init()`関数が実行されます。

![image](https://pbs.twimg.com/media/F_8LmrtacAAp9x-?format=jpg&name=medium)

# おわりに

MySQLに接続する際などに見かけるなと思っていた。

- https://github.com/go-sql-driver/mysql?tab=readme-ov-file#usage

> ``` go
> import (
> 	"database/sql"
> 	"time"
> 
> 	_ "github.com/go-sql-driver/mysql"
> )
> 
> // ...
> 
> db, err := sql.Open("mysql", "user:password@/dbname")
> if err != nil {
> 	panic(err)
> }
> // See "Important settings" section.
> db.SetConnMaxLifetime(time.Minute * 3)
> db.SetMaxOpenConns(10)
> db.SetMaxIdleConns(10)
> ```

アンダースコアimportは`init()`関数を実行する、と言うものなので、覚えやすいシンプルな機能かなと思う。

また、tools.goを導入する際も使うかもしれない。

https://chromium.googlesource.com/external/github.com/GoogleCloudPlatform/google-cloud-go-testing/+/d48483841e33340bed2c219a76b19e3eac8babc4/tools.go

https://qiita.com/k0kubun/items/39e89a98bf36ec476a92

気になったので実行順序を調べてみた。

``` go
package underscore

import "fmt"

func init() {
	fmt.Println("underscore.go: init")
}
```

``` go
package main

import (
	"fmt"
	_ "sample/underscore"
)

func init() {
	fmt.Println("main.go: init")
}

func main() {
	fmt.Println("main.go: main")
}
```

``` console
# go run .
underscore.go: init
main.go: init
main.go: main
```
StripeのPython SDKとJava SDKに`StripeClient`クラスが追加されました


Python SDKバージョン8.0.0とJava SDKバージョン23.0.0から、`StripeClient`クラスが追加されました。
これにより、複数のAPIキーや設定を利用するシステムの構築や、ユニットテスト時のモック化などが行いやすくなります。

## これまでの利用方法

これまでのPython・Java SDKでは、グローバルな`stripe`モジュールを利用する形でした。

**Python**
```python
import stripe

stripe.api_key = "sk_....";

cus = stripe.Customer.create(name="Jenny Rosen");
```

**Java**
```java
Stripe.apiKey = "sk_...";

AccountCreateParams params = ...;
Account account = Account.create(params);
```

この方式では、APIキーなどの設定がグローバルモジュールに設定されるため、複数のAPIキーを利用する大規模なアプリケーションなどで、設定の管理が難しくなることがありました。また、テスト時にモック化することも難しく、ユニットテストを書く際に問題となることがありました。

## `StripeClient`クラスを利用して Stripe APIを利用する

`StripeClient`クラスが導入されたことで、スレッドセーフで不変、かつモックなどもしやすい形で Stripe APIをPython / Javaから利用できるようになります。

**Python**

```python
from stripe import StripeClient

client = StripeClient("sk_...")

client.customers.create({"name": "Jenny Rosen"});
```

**Java**
```java
StripeClient client = new StripeClient("sk_...");
AccountCreateParams params = ...;
client.customers().update(...);
```

また、`StripeClient`クラスを利用することで、IDEから利用したいリソースのメソッドなどが見つけやすくなります。

![](https://storage.googleapis.com/zenn-user-upload/af17900402df-20240220.png)
![](https://storage.googleapis.com/zenn-user-upload/b41693e7f47f-20240220.png)


## 関連リソース

### Stripe Java SDK

https://github.com/stripe/stripe-java

https://github.com/stripe/stripe-java/releases/tag/v23.0.0

https://github.com/stripe/stripe-java/pull/1622

### Stripe Python SDK

https://github.com/stripe/stripe-python

https://github.com/stripe/stripe-python/releases/tag/v8.0.0

https://github.com/stripe/stripe-python/wiki/Migration-guide-for-v8-(StripeClient)
RECRUIT TECH CONFERENCE 2024 - 技術で挑み、技術でつなぐ。参加レポート

## はじめに
本記事は、2024 年 2 月 21 日に開催された 「RECRUIT TECH CONFERENCE 2024 - 技術で挑み、技術でつなぐ。」に参加した際のレポートです。

## 参加した経緯
SRE NEXT 2023 に参加して半年経ったので、改めて他社さんの SRE について知見を持とうと思ったから、また Platform Engineering についてのセッションがあったので気になったから

# ピックアップ：自己完結な開発組織を支えるプラットフォーム作り
### SRE チームの目標
**自己完結チームが、プロダクトを素早く安全に稼げるためのプラットフォームと文化を作る**

* 自己完結チーム？
自分たちに必要な問題解決をできるかぎり、自分たちで行うことができるチーム
(具体的には、自分たちで開発するのは、もちろんのことインフラ環境の構築や本番リリース後のトラブル解決等をすべて一貫して開発チームで行っていくチームのこと)
<br/>

* なぜ自己完結チームなのか
ユーザーへ、より素早く価値を提供できるから
<br/>

### 自己完結チームに求められる要素
* 自分たちでサービスが観測可能である
サービスがどのように動いており、今どのような状態であるかを開発チームで把握し、説明できること
( オブザーバビリティが高いということ )
<br/>

* 自分たちでサービスが制御可能である
開発チームが必要なタイミングでリリースができること
要求される仕様変更やトラフィックの増加等の内外原因の変化に対して、自分たちで対応が可能であること

### SRE チームの取り組み
#### **プラットフォームを作る**
開発者はサービスをできるかぎり、自分たちでコントロールできる状態にする
SRE はリリースの可否を判断する存在ではない

#### 手作業は極力避ける PRを作成、CI が通れば OK という状態にする
* Terraform Repository で管理
* tfaction による GitOps の実現
* PR を作成するれば plan 結果が表示され、マージすれば apply
* 安全ではない、望ましくない設定は CI が通らないように

#### 開発環境と本番環境の差分を小さくする
* 開発用DB 日時で本番からマスキングして同期
* オブジェクトストレージはマスキングして開発環境へコピー
→ これらによりパフォーマンス問題に早く気付ける

#### 可観測性
* SLO の合意、運用
* アラートをアクション可能なものに制限

#### 文化を作る
* 開発者にとって身近な存在に
* 積極的に不満などを聞きに行く
* プラットフォームのフィードバックを得る


## 感想
このセッションを聞いて、個人的に考えていた開発者のためのプラットフォームとは一体なんなのかについて、答えを得ることができた。近年、DevOps の推進によって運用やインフラ関連のタスクを開発者が行うことが多くなっている。それこそ、このセッションでも言われていた開発、インフラにおいて一貫することで自己完結していくチームが多くなるのは明確な事実で実際に起っている。しかし、これらによって開発者に多大な負荷がかかっていることも同時に起こっているのも一つの事実である
この負荷を解消するために PlatformEngineering はあるのではないかと本セッションを聞いて感想を抱いた。ただ、本セッションにおいても話題にあったかと思われるプラットフォームは開発者が必要としているものでなければ、使われず失敗に終わることがよくある
もしプラットフォームを作る機会があるなら、すぐ作るのではなく、なぜ必要なのか、何が必要なのかを正確に考える時間が必要だと思った
高レベルAPIと低レベルAPIとは

# 低レベルAPIと高レベルAPIとは

- 高レベルAPI（高水準API）： 提供する機能が大ざっぱで、簡単に使えるが、細かい需要に応じること（カスタマイズ）は不得意
- 低レベルAPI（低水準API）： 提供する機能が細かく、さまざなことが可能だが、いちいち指示せねばならず、使うのがやや面倒

# 「歩く」という機能の使い方（＝API）が高レベルと低レベルの2種類で提供される場合の例

- 高レベルAPIの例：「歩く（時速4km）」と、1つの大ざっぱな性質＋動作の機能で提供
- 低レベルAPIの例：「時速＝4km」「足を動かす（両足を、前後に）」「手を振る（両手を、前後に）」と、複数の細かい性質・動作の機能で提供

# それぞれのメリット・デメリット

### メリット（高レベルAPI）
- 短くシンプルなので、使うのが簡単
- よってコードが短くなる

### デメリット（高レベルAPI）
- 細かなカスタマイズができない

### メリット（低レベルAPI）
- 細かなカスタマイズが可能

### デメリット（低レベルAPI）
- 複雑で長いので、使うのが面倒
- よって書くコードもこちらが長くなる

# 使用用途

基本的な使い方をしたい場合は高レベルAPIを、特殊な独自の使い方をしたい場合は低レベルAPIを使う。

 # 参考文献
 https://atmarkit.itmedia.co.jp/ait/articles/1812/18/news143.html
AWS上のUbuntu 22.04でchronyの設定をする

# 注意
小規模・個人利用のシステムにおける設定を記載しています。
中大規模システムの設定を予定している場合は別サイトも参考にしてください。

# 設定

```bash
systemctl status chrony
# -> chronyがインストールされていること、activeであることを確認
systemctl is-enabled chrony
# -> enabledであることを確認

vi /etc/chrony/chrony.conf
# pool ～～の行をコメントアウトする
# コメントアウトしたpoolの下に「server 169.254.169.123 iburst minpoll 4 maxpoll 4」

systemctl restart chrony
systemctl status chrony
# -> activeであることを確認

chronyc sources | fgrep '^*'
# -> 169.254.169.123が表示されることを確認

chronyc tracking
#Reference ID    : 169.254.169.123 (169.254.169.123)
#            Stratum         : 4
#            Ref time (UTC)  : Wed Nov 29 07:41:57 2017
#            System time     : 0.000000011 seconds slow of NTP time
#            Last offset     : +0.000041659 seconds
#            RMS offset      : 0.000041659 seconds
#            Frequency       : 10.141 ppm slow
#            Residual freq   : +7.557 ppm
#            Skew            : 2.329 ppm
#            Root delay      : 0.000544 seconds
#            Root dispersion : 0.000631 seconds
#            Update interval : 2.0 seconds
#            Leap status     : Normal
```

# 🔎chrony 読み方
「クローニー」 と読むらしい

# 参考
「Linux インスタンスの時刻の設定」
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-time.html
Windows XAMPP htdocs 別の場所のフォルダを参照

XAMPPのhtdocs内に実際のフォルダを作成しないで、別の場所のフォルダを参照させる方法
例
c:\xamppに、XAMPPがインストールされている状態
c:\dev\linktestフォルダがある状態

コマンドプロンプトのアイコンを右クリックして、管理者権限で起動する
```
mklink /D c:\xampp\htdocs\linktest c:\dev\linktest
```
/Dオプションは、ディレクトリ参照リンクのD

c:\xampp\htdocs内に、c:\dev\linktestフォルダへのリンクが作成される
これをシンボリックリンクという

ブラウザで、http://localhost/linktest/を表示すると、
c:\dev\linktestフォルダ内の内容が表示される
docker compose ※yaml構築も 〜Elixir〜

# Brightの対象
Webアプリ開発 Elixir > クラス1 > Elixir環境構築 > ローカルPC >  docker compose ※yaml構築も

# 前提
・mix phx.new で作成済みであること

・config/dev.exsの
 　データベースhostnameを
 　hostname: "db"
　に変更済みであること

・config/dev.exsの
　httpの設定を
　http: [ip: {0, 0, 0, 0}, port: 4000],
　に変更済みであること

# Dockerfileとdocker-compose.ymlの作成
プロジェクト直下に作ります
```:Dockerfile
FROM elixir:1.15.4

RUN mix local.hex --force 

```

```:docker-compose.yml
version: '3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 4000:4000
    volumes:
      - .:/work
    working_dir: /work
    command: "mix phx.server"
    links:
      - db
  db:
    image: postgres
    environment:
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432
    volumes:
      - ymndb:/var/lib/postgresql/data

volumes:
  ymndb:

```

# DB構築
```
$ docker compose run --rm db -d
$ docker compose run --rm web mix ecto.create
$ docker compose down
```

# コンテナの操作
起動

```
$ docker compose up -d
```

停止
```
$ docker compose down
```

これで終わり
多重継承

# 多重継承
複数のクラスを親として子クラスを定義する事を多重継承と呼びます。
しかし、Javaではクラスの多重継承は出来ません。

原因としては、複数のスーパークラスがインスタンス化をする際に、同じフィールドがあると不都合が生じるようです。

ただし、フィールドを持たないインターフェイス(interface)を用いる事で多重継承を実装出来ます。


# 参考文献
https://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
TiDB関連イベント 3月分

TiDBに関するイベントの一覧です。PingCAP主催のもの、コミュニティイベントのものも混ざっています。

WebinarについてはJSTで6:00-24:00に開催されるイベントを記載しています。
（こんなのもあるよ！という方、記事にコメントください。追加します）

## 3月4日(月) 金融×スタートアップEXPO 2024

https://fin-startup-expo2024.peatix.com/

PingCAPも協賛しているFITA（金融IT協会）のイベントです。私もPingCAPブース&LTで登壇します。
金融・フィンテック系の方は是非お越しください。

## 3月6日（水） IDCF x PingCAP

https://www.idcf.jp/topics/20240213001.html

IDCFさんのメモリDB CacheDBと、メモリをあんまり使わないTiDBのセミナーです。異なるDBを同時に説明するセミナーは珍しいかもしれませんね。IDCFさんとPingCAPの共催セミナーです。


## 3月28日（木） TiProxyのウェビナー

https://pingcap.co.jp/webinar-introduction-to-tiproxy/

TiDB Cloudでは一部先行して使われているTiDB専用SQL ProxyのTiProxyについて。なぜProxySQLやHAProxyではなくTiProxyなのか？ その辺を解説してくれるでしょう（期待）。講師はPingCAP TSEの本田さん。

## 3月28日（木） みんなのPython勉強会 #102

https://startpython.connpass.com/event/312783/

最近はPythonでTiDBに接続している方も増えていますが、Stapyコミュニティからお声がけ頂きまして、みんなのPython勉強会で発表する機会を頂けました。TiDB Serverlessと、Pythonフレームワークとの連携についてお話しします。


## 3月29日(金) TiUG #1 

https://tiug.connpass.com/event/310114/

前回大盛り上がりのTiUG、3月29日に開催します。今回はKDDI Digital Gateさんでオンライン・オフラインのハイブリッド開催！ 私もTiDB最新情報ということで、Vector Searchの話題が出来るといいなと思っています。
ECCUBE4からSQL接続

# 基本環境

EC-CUBE4.1.2-p2
PHP 7.4.33
# 接続しているデータベース情報を取得
`env("DATABASE_URL")`
で、root/.env 内のデータベース接続情報を取得

```
 $dbInfo = env("DATABASE_URL");
 echo $dbInfo;

 mysql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]

```
# １）mysqldumpで使える形に変換
`mysql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]`
という取得データを、
`$command = mysqldump [データベース名] --host=[ホスト名] --user=[ユーザー名] --password=[パスワード] > [ファイルを仮置きするパス]`
という形に変換する

```
// データベース情報取得　→　変換
$dbaaa = env("DATABASE_URL");
$dbbbb = str_replace('mysql://', ' --user=', $dbaaa);
$dbccc = str_replace(':', ' --password=', $dbbbb);
$dbddd = str_replace('@', ' --host=', $dbccc);
$dbURL = str_replace('/', ' ', $dbddd);
```

`$dbURL`
に
`[データベース名] --host=[ホスト名] --user=[ユーザー名] --password=[パスワード]`
が入る

```
// データベース名取得
$dbeee = strstr($dbbbb, '/');
$sqlName = str_replace('/', '', $dbeee).".sql";

// ファイルを仮置きするディレクトリ
$dir = /root/;
// ファイルパス
$zipPath = $dir. '' .$sqlName;
```
`$zipPath`
に
`/root/[データベース名].sql`
が入る

# ２）PDOで使える形に変換
`mysql://[ユーザー名]:[パスワード]@[ホスト名]/[データベース名]`
という取得データを、
`new PDO(mysql:dbname=[データベース名];host=[ホスト名], [ユーザー名], [パスワード])`
という形に変換する
```
// データベース情報取得→変換
$dbsss = env("DATABASE_URL");
$dbttt = mb_substr($dbsss, 0, mb_strpos($dbsss, "@"));
$dbuuu = str_replace('mysql://', '', $dbttt);
$dbzzz = strstr($dbuuu, ':');
$dbvvv = strstr($dbsss, '@');
$dbxxx = strstr($dbvvv, '/');
$dbyyy = strstr($dbvvv, '/', true);
$dbHost = str_replace('@', '', $dbyyy);
$dbUser = strstr($dbuuu, ':', true);
$dbPwd = str_replace(':', '', $dbzzz);
$dbName = str_replace('/', '', $dbxxx);
$dsn = ("mysql:dbname=".$dbName.";host=".$dbHost);
```
`$dsn`に`mysql:dbname=[データベース名];host=[ホスト名]`
`$dbUser`に`[ユーザー名]`
`$dbPwd`に`[パスワード]`
が入る
```
// データベースに接続
try {
    $dbh = new PDO($dsn, $dbUser, $dbPwd);
    echo "接続成功\n";
} catch (PDOException $e) {
    echo "接続失敗: " . $e->getMessage() . "\n";
    exit();
}

// 実行するSQL文
$sql = "DROP TABLE [テーブル名]";
```
# 
#