OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】ドラッグ&ドロップでファイルアップロードをNext.jsで実装する

# はじめに
この記事は **react-dropzone** の使い方の備忘録です。

# インストール
```
npm install react-dropzone
```
## 最小セットでドラッグ&ドロップを実装する

```tsx:app/page.tsx
"use client"
import { useDropzone } from "react-dropzone";

export default function Home() {
  const onDrop = (files: File[]) => {
    console.log(files);
  }

  const { getRootProps, getInputProps } = useDropzone({ onDrop });

  return (
    <div {...getRootProps()} style={{ border: "1px solid #ff7f50", width: 200, height: 150 }}>
      <input {...getInputProps()} />
      <p>ここにファイルをドラッグ&ドロップしてください。</p>
    </div>
  );
}
```
**大事** なのは **getRootProps** と **getInputProps** と **onDrop** の **3点** です。

・**getRootProps** は 
**ドラッグ&ドロップ** で **ファイルアップロード** が作動してほしい範囲に渡します。
この場合 **divタグ** に **赤枠** を付けているので **赤枠の中** で **作動** します。

・**getInputProps** は 
**getRootProps** を渡した **タグの中** の **inputタグ** に使用します。

・**useDropzone** に渡された **onDrop** は
**ドラッグ&ドロップ** されたタイミングで発火する **callback関数** です。
**callback関数** の **第1引数** には **ドラッグ&ドロップ** された **ファイル群** が渡されます。

実際のアップロード処理は **onDrop関数** 内に記述することになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/1a20391c-34a9-a45b-8776-0aa2e0035b3c.png)

**描画内容** はこうなります。
**赤枠の中** を **クリック** か **ドラッグ&ドロップ** することで 
**ファイルアップロード** を行えます。

## 範囲内でドラッグされていることを判定して当てるCSSを変更する

```tsx:app/page.tsx
"use client"
import { useDropzone } from "react-dropzone";

export default function Home() {
  const onDrop = (files: File[]) => {
    console.log(files);
  }

  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });

  return (
    <div {...getRootProps()} 
    style={ isDragActive ? 
    { border: "1px solid #3eb370", width: 200, height: 150, marginTop: 25, marginLeft: 50} : 
    { border: "1px solid #ff7f50", width: 200, height: 150, marginTop: 25, marginLeft: 50}}>
      <input {...getInputProps()} />
      <p>ここにファイルをドラッグ&ドロップしてください。</p>
    </div>
  );
}
```
**大事** なのは 
**1**.**useDropzone** から **isDragActive** を取り出していること
**2**.**div** の **style** の **border** の色を **isDragActiveフラグ** によって変更していること
の **2点** です。

・**isDragActive** は 範囲内でドラッグされていることを判定する **フラグ** です。
**isDragActive** を使うことで **ドラッグされている時だけ** という条件を使えます。

## 範囲内のボタンクリックのみでエクスプローラーを開くようにする
大事なのは
**1.** `useDropzone`に`noClick: true`を渡して範囲内のクリックを無効化する
**2.** 戻り値から`open`を取り出して、`button`タグの`onClick`に渡す
の２点です。
```tsx:app/page.tsx
"use client"
import { useDropzone } from "react-dropzone";

export default function Home() {
  const onDrop = (files: File[]) => {
    console.log(files);
  }

  const { getRootProps, getInputProps, isDragActive, open } = useDropzone({ onDrop, noClick: true });

  return (
    <div {...getRootProps()} 
    style={ isDragActive ? 
    { border: "1px solid #3eb370", width: 200, height: 150, marginTop: 25, marginLeft: 50} : 
    { border: "1px solid #ff7f50", width: 200, height: 150, marginTop: 25, marginLeft: 50}}>
      <input {...getInputProps()} />
      <p>ここにファイルをドラッグ&ドロップしてください。</p>
      <button onClick={open}>ファイルを選択</button>
    </div>
  );
}
```
超便利なStandard Assetsを使ってみた！(Unity 2022.3.22f1)

***
Unity初心者です
今回は、UnityのStandard Assetsが非常に便利だということで、導入しようとしましたが、公式からのサポートがすでに終了し、***アセットストアから削除されてしまっていた***ため、他の方法で導入しました！！（手順のみサクッと記述していますのでご了承ください）

## Standard Assetsの入手
#### 入手方法については、３種類あります。
１．[Unityダウンロードアーカイブ](https://unity.com/releases/editor/archive)から、Unity 2018.1.9をダウンロードし、その中のStandard Assetsを持ってくる
２．Gitから持ってくる
３．過去に使用しているStandard Assetsのフォルダがあれば、それを持ってくる

## その後の手順
standard Assetsを使用したいUnityのプロジェクトをエクスプローラで開き、Assetsの中に入れてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738334/98034a41-cab9-b518-0918-548ea6a9e1e6.png)

この時、このまま動かそうとすると、エラーになります。
そこで、以下の操作を行います。
Standard Assets/Utility/の中にある
- SimpleActivatorMenu.cs
- SimpleActivatorMenu.cs.meta
- ForcedReset.cs
- ForcedReset.cs.meta

の４つを削除してください。そうすれば、エラーが解消されるはずです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738334/22ae5fa7-abad-9ab0-e197-8bde6c43b1f2.png)

少し使ってみましたが、あらかじめ設定されたパッケージが豊富にあって、これはとても便利ですね！！
Databricks (Spark) にてデータフレーム作成時の UnsupportedEncodingException cp932 への対応方法

## 概要
Databricks (Spark) でのデータフレーム作成時に発生する`UnsupportedEncodingException: cp932
`エラーに対する解決策を紹介します。

```text
FileReadException: Error while reading file file:/Workspace/Repos/share/share/cp932/sample.csv.
Caused by: UnsupportedEncodingException: cp932
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9c78f81f-281d-7e61-f915-71ebd7868d0b.png)

このエラーは、ファイルのエンコーディングとして`cp932`がサポートされていないために発生します。Python では`cp932`エンコーディングが使用されるため、誤ってこのエンコーディングを指定してしまうことがあります。この問題を解決するには、encoding パラメータに`cp932`の代わりに`ms932`を指定してください。これにより、エンコーディングの互換性が保たれ、エラーが解消されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5707fc86-2af8-e8bb-54c8-62e31bc3e6f5.png)


## エラーの発生方法と対応方法

### ファイルを準備

Databricks Repos 上で実行することを前提としています。

```python
import os
src_path = f"{os.getcwd()}/sample.csv"

src_data = """
col_1,col_2,col_3
a,b,c
あ,い,う
""".strip()

with open(src_path, "w", encoding='cp932') as file:
    file.write(src_data)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/53b0df3d-7d25-f7f2-a9bc-ac8551623faa.png)

### エラーの発生方法

```python
schema = """
col1 string,
col2 string,
col3 string,
_corrupt_record string
"""

df = (
    spark.read.format("csv")
    .schema(schema)
    .option("header", True)
    .option("encoding", "cp932")
    .load(f"file:{src_path}")
)

df.display()
print(df.collect())
```

```text
FileReadException: Error while reading file file:/Workspace/Repos/share/share/cp932/sample.csv.
Caused by: UnsupportedEncodingException: cp932
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/04a7cf4d-d320-d9e8-91de-7e660ab412d2.png)

### エラーの対応方法

```python
schema = """
col1 string,
col2 string,
col3 string,
_corrupt_record string
"""

df = (
    spark.read.format("csv")
    .schema(schema)
    .option("header", True)
    .option("encoding", "ms932")
    .load(f"file:{src_path}")
)

df.display()
print(df.collect())
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d1bc11cf-c069-d67a-81d6-f93d0a2e6447.png)
メールサーバ（Postfix）基本設定 その１

## はじめに
Linuxでメールサーバを構築する為の手順を備忘録として残します。
ディストリビューションはRHEL、SMTPサーバはPostfixを使用します。
稼働環境はローカルネットワーク、SMTP認証なし、暗号化なし、SMTPプロトコル設定はデフォルトとします。
IMAP、POPサーバ(dovecot)については今回記載しません。
記載内容に相違がある場合はコメントにてお知らせください。

## 構築環境
OS:REHL8.8
パッケージ:Postfix 3.5.8

## Firewalld通信許可
SMTP(25番)、SMTPS(465番)、smtp-submission(567番)の通信を許可します。本記事の構成では25番のみ使用しますが、暗号化通信を使用する場合の補足として465番、567番許可時のコマンドも記載します。
```php
firewall-cmd --permanent --zone=public --add-service=smtp
firewall-cmd --permanent --zone=public --add-service=smtps
firewall-cmd --permanent --zone=public --add-service=smtp-submission
systemctl restart firewalld
```
## Postfixインストール
SMTPサーバ機能を要するPostfixパッケージをインストールします
```php
dnf install postfix
```

## コンフィグ構成
* /etc/postfix/main.cf
SMTPサーバの基本設定はこちらを編集します。
* /etc/postfix/master.cf
SMTPサーバの詳細設定はこちらを編集します。
SMTPS(465番)、smtp-submission(567番)を使用する場合は編集が必要です。
当記事では編集しません。

## コンフィグ設定
基本的な設定箇所を記載します。
サーバ設定、稼働環境に沿った設定を指定してください。
|項目|値|
|:---|:---|
|myhostname|自サーバのホスト名を定義します。|
|mydomain|自サーバのドメイン名を定義します。|
|myorigin|自サーバから配送されるメールのドメイン部を指定します。|
|inet_interfaces|メール受信するインタフェースを指定します。|
|inet_protocols|メール送受信に使用するIPプロトコルをIPv4、IPv6から指定します。|
|mydestination|ローカル配送(受信)するドメインを指定します。|
|mynetworks|信頼できるネットワークを指定します。MUAが動作するクライアント等のネットワーク帯を指定してください。|
|relay_domains|リレーを許可するドメインを指定します。|
|relayhost|リレー先ホストを指定します。ブランクの場合、MXレコードを参照しインターネット側に中継します。ローカルネットワークで動作させたい場合は、メールサーバをもう1台構築し指定します。|
|home_mailbox|ローカル配送するメールの保存形式。Maildir/を指定すると、ユーザのホームディレクトリ配下にMaildirディレクトリが作成され、メールファイルが個別に保存されます。|

## ユーザ作成
メールサーバ内にユーザを作成します。
[ユーザ名@自サーバのドメイン]がメールアドレスとなります。
```php
adduser "ユーザ名"
passwd "ユーザ名"
```

## メール処理フロー
Postfixがメールを受け取った後の処理について記載します。
1. ローカル配送
mydestinationで指定したドメイン宛のメールを受信すると、自サーバへローカル配送します。

2. メール中継
許可された設定のみ、[relayhost]へメールを中継します。
　1. [mynetworks]で指定されたネットワークからのメールを許可します。
　2. [mynetworks]以外からメールが送信された場合は、[relay_domains]で指定された宛先ドメインへのメールのみ許可します。
　3. それ以外のメールは中継せず、接続を拒否します。

## 動作確認
Telnet接続し、CLI上からメールを送信します。
ローカル接続以外の場合は、Telnet接続できるようにFirewalld設定は変更してください。


```php
telnet SMTPサーバのIPアドレス 25

MAIL FROM: Envelope Fromを指定
RCPT TO: Envelope Toを指定
DATA
From: Fromメールアドレスを指定
To: Toメールアドレスを指定
Subject: 件名を指定
本文を記載
.

quit   "Telnet切断”
```
ユーザのメールディレクトリにメールが保存されたことを確認します。
```php
ls -l /home/ユーザ名/Maildir/new/    "新規メール保存ディレクトリ"
ls -l /home/ユーザ名/Maildir/new/    "参照済メール保存ディレクトリ"
```
Lambda内のCSVファイルをPythonで読み込む

```
import boto3
import datetime
import time
import csv
import logging

def lambda_handler(event, context):
    # 実行日取得
    to_time = datetime.datetime.now()
    # 1日前取得
    from_time = datetime.datetime.now() - datetime.timedelta(days=1)
    # エポック時刻取得(float型)
    epoc_from_time = from_time.timestamp()
    epoc_to_time = to_time.timestamp()
    # エポック時刻をミリ秒にしint型にキャスト
    m_epoc_from_time = int(epoc_from_time * 1000)
    m_epoc_to_time = int(epoc_to_time * 1000)

    file_path = 'xample8.csv'  # Lambdaのデフォルトの作業ディレクトリ
    try:
        with open(file_path, mode='r') as file:
            rows = csv.reader(file)
            client = boto3.client('logs')

            for row in rows:
                logging.basicConfig(level=logging.DEBUG)
                log_group_name = row[0]
                s3_bucket = row[1]

                client.create_export_task(
                    logGroupName=log_group_name,
                    fromTime=m_epoc_from_time,
                    to=m_epoc_to_time,
                    destination=s3_bucket,
                    destinationPrefix=log_group_name
                )

                export_tasks = client.describe_export_tasks(statusCode='RUNNING')
                while len(export_tasks['exportTasks']) >= 1:
                    export_tasks = client.describe_export_tasks(statusCode='RUNNING')
                    time.sleep(5)
    except FileNotFoundError:
        logging.error("CSVファイルが見つかりません: {}".format(file_path))
        # ここで処理を終了するか、適宜他の処理を加えてください
PythonでWordをHTMLに変換する

WordをHTMLに変換することで、ユーザーが特定のソフトウェアをインストールすることなく、ブラウザで直接文書を表示したり読んだりできるように、文書の内容をWebページで公開することができます。WordをWebページに変換すると、情報をオンラインで公開したり、オンライン・ドキュメント・ライブラリを作成したり、インタラクティブなWebアプリケーションを構築したりするのに便利です。
以下は、Pythonを使ってWordをHTMLに変換する方法の2つの例です。
* PythonでWord Doc/DocxをHTMLに変換する
* PythonでWordをHTMLに変換し、CSSスタイルや画像などを埋め込む

## Python Wordライブラリのインストール
Word Doc/DocxからHTMLへの変換を行う前に、[**Spire.Doc for Python**](https://www.e-iceblue.com/Introduce/doc-for-python.html)ライブラリをインストールする必要があります。これは専門的なPython Word開発コンポーネントであり、簡単にWordドキュメントを作成、読み取り、編集、変換することができます。
ライブラリは以下のpipコマンドでインストールできます：
```
pip install Spire.Doc
```

## PythonでWord Doc/DocxをHTMLに変換する
最初の例は特に簡単な変換方法です。.docまたは.docx文書を読み込み、**Document.SaveToFile (FileName string, FileFormat.Html)** メソッドを使用してWord文書をHtml形式で保存するだけです。

Pythonコードサンプル：
```python
from spire.doc import *
from spire.doc.common import *
     
# Documentオブジェクトの作成
document = Document()
 
# docまたはdocxドキュメントの読み込み 
document.LoadFromFile("Input.docx")
 
# HTMLファイルとして保存
document.SaveToFile("WordtoHtml.html", FileFormat.Html)
document.Close()
```

出力結果：
![Word2Html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/034bef9a-aa45-7f8d-0381-47a7d34d8ecc.png)


## PythonでWordをHTMLに変換し、CSSスタイルや画像などを埋め込む
内部スタイルや外部スタイルなど、変換時に特定のCSSスタイルを埋め込みたい場合や、画像を埋め込む必要がある場合は、Spire.Doc for Pythonが提供する**HtmlExportOptions**クラスを使用できます。

Pythonコードサンプル：
```python
from spire.doc import *
from spire.doc.common import *
 
# Documentオブジェクトの作成
document = Document()
 
# docまたはdocxドキュメントの読み込み
document.LoadFromFile("Input.docx")
 
# CSSスタイルの埋め込み
document.HtmlExportOptions.CssStyleSheetFileName = "sample.css"
document.HtmlExportOptions.CssStyleSheetType = CssStyleSheetType.External
 
# 画像を埋め込むかどうかの設定
document.HtmlExportOptions.ImageEmbedded = False
document.HtmlExportOptions.ImagesPath = "Images/"
 
# フォームフィールドをプレーンテキストとしてエクスポートするかどうかを設定するdocument.HtmlExportOptions.IsTextInputFormFieldAsText = True
 
#ドキュメントをhtmlファイルとして保存する
document.SaveToFile("ToHtml.html", FileFormat.Html)
document.Close()
```

* * *

> Spire.Doc for PythonのWordドキュメントの操作、編集、変換機能の詳細については、こちらをご覧ください：
https://www.e-iceblue.com/Tutorials/Python/Spire.Doc-for-Python/Program-Guide/Spire.Doc-for-Python-Program-Guide-Content.html
RDS MySQLをサクッとblue green deployでメジャーバージョンアップ

# Blue Green Deploy

サクッとやってみました。
以前、RDSのMySQLのメジャーバージョンアップをした際にもこのBlue Green deployをしたのですが、
今回、インスタンスのt2系廃止に伴い、t4gへとインスタンスタイプ変更が必要になり、
前回同様にBlue Green deployで実施しました。
メジャーバージョンアップする場合の手順もまとめつつ、今回の手順を説明します。

# 最初に注意点

RDSのBlue Green deployではトラフィックの振り分けをしたあと、
エラーが出た場合にもどす、ということができません。

後述する、以下の章で説明しています。
>トラフィックをGreenへと切り替える。

# まずはBlue Green deployの作成

作成しましょう。

ここでは2点ポイントがあります。

:::note info
**Point1**

ファイルシステムアップグレードも同時にやる場合greenの作成に1時間かかります。

:::

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_PIOPS.StorageTypes.html#USER_PIOPS.UpgradeFileSystem

これはblue green作成時のチェック項目として与えられます。
チェックを入れると、この作成時にファイルシステムアップグレードを実施できます。

これは推奨の項目なので、この機会にやってしまいましょう。
この１時間かかる、というのが、現行環境に影響なく対応できてしまうのも、
このBlue Greenデプロイの大きなメリットですね。


:::note info
**Point2**

MySQLのversionはここで指定します。

:::


メジャーバージョンアップするなどの要件がある場合は、ここで指定しましょう（作成後にバージョンアップするもできるがこの時点で新しいバージョンで作るのが簡便）。
また注意点として、デフォルトのままの選択だと、自動でMySQLのマイナーバージョンアップが選択されています。

# Greenのインスタンスタイプを変更

今回の要件であるインスタンスタイプ変更をここで実施します。

ここでの注意点は一つです。

:::note info
**Point**
変更の即時実行を選択しましょう。
:::

デフォルトではメンテナンスタイムにインスタンスタイプ変更する、という設定になっています。
およそ23時頃に設定変更となってしまいます。
特にこのBlue Greenデプロイでは、Green側の変更が現環境に影響されないため、即時変更一択だと思います。
無駄に作業を翌日まで持ち越さないようにするためにも、最終確認画面で、即時変更を選択しましょう。




# トラフィックをGreenへと切り替える。

ここまでで、必要な要件を満たした新しいRDS(Green)が作成されました。

もし、ここまででエラーが出て解決不可能であればBlue Green デプロイを削除しましょう。
現環境には何も影響がなく切り戻すことができます。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-deleting.html

問題無く進められていれば、切り替えましょう。

注意点は以下です。

:::note alert
トラフィックの切り替え後は戻すことは不可です。
:::

一般のBlue Green deployのイメージとは異なるかもしれません。
たとえば以下記事ではBGデプロイについて、トラフィックを戻せるという記述があります。

>ブルーグリーンデプロイメントの利点の1つは、システムのダウンタイムを短くできる点である。現状の本番環境を停止させて変更して戻す従来の運用方法とは違ってシステムをほとんど止める必要が無く、可用性を高められる。

>　新しい本番環境に切り替えて問題が生じた場合、すぐに現状の本番環境に切り戻せるのも利点の1つ。これもシステムの可用性向上につながる。

https://xtech.nikkei.com/atcl/nxt/keyword/18/00002/070800077/

これはRDSのBGデプロイではできないようです。

よって、切り替えたあとの動作確認でのエラー検証をステージングで行う、という要件には適しません。
そのような要件は実際のステージング環境で、Blue Green deployにより、デプロイ後検証、その後、production環境にBlue Green deployという形で達成しましょう。

切り替え時には、タイムアウト期間も設定できます。
4回やりましたが、全てで5分以内の切り替えは完了しました。


>切り替えのタイムアウト期間は、30 秒から 3,600 秒 (1 時間) まで指定できます。切り替えに指定された期間より長くかかる場合、変更はすべてロールバックされ、どちらの環境にも変更は加えられません。デフォルトのタイムアウト期間は 300 秒 (5 分) です。

そのほかにも切り替えのベストプラクティスとして、以下に詳しいです。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/blue-green-deployments-switching.html

# 完了後の旧環境の削除

作成したBlue Green deployと、古いブルーというタグがついているデプロイ前の環境を削除しましょう。

ここは別途切り替え後に作業が必要になります。

削除時に、削除前最新のスナップショットを保存するかを聞かれるので必要に応じて取得しましょう。


# 以上

Blue Green deployでエラーのリスクを低減し、短時間で正確に対応できるメリットを実感できました。

最後まで読んでいただきありがとうございました。
【Swift】クラスの参照渡しとは

# この投稿は...

Swiftのクラスで行われる **参照渡し** について、解説します。

> Swiftを基礎から学ぶには
自著、工学社より発売中の「[まるごと分かるSwiftプログラミング](https://amzn.asia/d/7YPWJwl)」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。
> また、Swiftプログラミングを基礎から動画で学びたい方には、Udemyコース「[今日からはじめるプログラミング](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwii1qTuj_2BAxV4hlYBHbj5BqEQFnoECBYQAQ&url=https%3A%2F%2Fwww.udemy.com%2Fcourse%2Fstart-programming-today%2F&usg=AOvVaw2vs4Sccq-bpfA4ZD2rCyNm&opi=89978449)」をお勧めします。

# クラスは参照型データである

Swfitでは、クラスは参照型データの分類されます。
構造体のような値型データとは異なり、参照型データは変数や定数あるいは関数に割り当てられたときに「インスタンスのコピー」が発生しません。
インスタンスのコピーではなく、**インスタンスへの参照** が渡されます（参照渡し）。

例として、ホームスピーカーのボリューム調節を考えます。
このホームスピーカーは家全体にひとつだけ設置されており、ボリュームは部屋のリモコンから操作できます。
つまり、すべてのリモコンは「共通のホームスピーカー1台」だけを操作します。

ホームスピーカーをモデル化する`HomeSpeaker`クラスは、次のように定義します。

```swift
class HomeSpeaker {
    var volume: Int = 0
}

let livingRoom = HomeSpeaker()
livingRoom.volume = 25
```

上のコードは、リビングルームからホームスピーカーを操作できるようにしたことを意味します。
そして、ボリュームを`25`に設定します。
このとき、`livingRoom`定数に設定されているのは「新たに作成された`HomeSpeaker`インスタンスへの参照」です。

次に、`livingRoom`定数を新しい`theaterRoom`定数に割り当てます。
そして、`theaterRoom`のボリュームを`30`に変更します。

```swift
let theaterRoom = livingRoom
theaterRoom.volume = 30
```

このとき、`theaterRoom`定数に設定されるのは「以前に作成した`HomeSpeaker`インスタンスへの参照」です。
つまり、`livingRoom`定数と`theaterRoom`定数は、両方とも「同一の`HomeSpeaker`インスタンス」を参照します。
要するに、「異なる2つの名前」で同一のインスタンスにアクセスしている状態です。

それを確認するために、`livingRoom`定数の`volume`プロパティにアクセスしてみましょう。

```swift
print("The volume of living room is now \(livingRoom.volume).")
// Prints "The volume of living room is now 30."
```

すると、シアタールームのボリュームに設定した`30`が、リビングルームにも影響していることがわかります。

この例は、参照型データの値について、いくつかの重要な点を示唆しています。
- ひとつは、値が予測しにくいことです。仮に、`livingRoom`定数と`theaterRoom`定数が離れてバラバラに存在していると、ボリュームを変更するすべてのコードを見つけるのは困難です。`livingRoom`定数を使用するときは常に、`theaterRoom`定数のことも考慮しなければいけません。これは、家中にリモコンがあると「誰がどこからホームスピーカーを操作するか」を予測できないことと似ています。

- もうひとつは、`livingRoom`と`theaterRoom`が定数として宣言されている点です。定数なのに、どちらも`velume`プロパティの値を変更できました。それは、これらの定数が保持しているのは「インスタンス自体」ではなく、「インスタンスへの参照」だからです。つまり、インスタンスの`volume`プロパティを変更しても、定数が「どのインスタンスを参照するか」は変わりません。実際に変更されるのは「インスタンスへの参照」ではなく、参照先にある`HomeSpeaker`インスタンスの`volume`プロパティです。
Databricks ( Spark )にて createDataFrame メソッド利用時の LENGTH_SHOULD_BE_THE_SAME エラーへの対応方法

## 概要

Databricks (Spark) で createDataFrame メソッドを使用する際に遭遇する`LENGTH_SHOULD_BE_THE_SAME`エラーについての解決策を紹介します。このエラーは、テスト時に変数からデータフレームを生成しようとした際に発生することがあります。

```text
PySparkValueError: [LENGTH_SHOULD_BE_THE_SAME] obj and fields should be of the same length, got 1 and 3.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a110aefc-4e4e-c935-6976-f1fb2178ffcc.png)

エラーの原因は、データを定義する変数のリスト内に別のリストが定義されていることにあります。コピー＆ペーストの操作ミスにより、このような構造が作成されることがあります。この問題を解決するには、リストをネストしないように注意してください。

```python
# 修正前
data_001 = [
    [
        {
            'str_col': 'abc',
            'int_col': 123,
            'date_col': datetime.date(2020, 1, 1),
        },
    ]
]

# 修正後
data_001 = [
    {
        'str_col': 'abc',
        'int_col': 123,
        'date_col': datetime.date(2020, 1, 1),
    },
]
```

## エラーの発生方法と対応方法

### エラーの発生方法

```python
import datetime

schema = '''
str_col string,
int_col integer,
date_col date
'''

data_001 = [
    [
        {
            'str_col': 'abc',
            'int_col': 123,
            'date_col': datetime.date(2020, 1, 1),
        },
    ]
]

df = spark.createDataFrame(
    data_001,
    schema,
)

df.display()
```

```text
PySparkValueError: [LENGTH_SHOULD_BE_THE_SAME] obj and fields should be of the same length, got 1 and 3.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ce128890-7302-9ff2-2f75-282773858676.png)

### エラーへの対応方法

```python
import datetime

schema = '''
str_col string,
int_col integer,
date_col date
'''

data_001 = [
        {
            'str_col': 'abc',
            'int_col': 123,
            'date_col': datetime.date(2020, 1, 1),
        },
]

df = spark.createDataFrame(
    data_001,
    schema,
)

df.display()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5bdf4cde-db6f-92a7-f90c-bf1c82e76e2e.png)
データがある範囲を外枠で囲んで中に格子を入れる方法

```vb
Sub ApplyThickBorderAndGridlinesAroundRange()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim rng As Range
    
    ' 使用するワークシートを設定
    Set ws = ThisWorkbook.Sheets("シート名") ' シート名をあなたの使用しているシートの名前に置き換えてください
    
    ' A列からF列でデータが存在する最終行を特定
    lastRow = ws.Cells(ws.Rows.Count, "F").End(xlUp).Row
    
    ' 範囲を設定 (この場合はA1からFまでの最終行)
    Set rng = ws.Range("A1:F" & lastRow)
    
    ' 太い外枠を範囲に適用
    With rng.Borders(xlEdgeTop)
        .LineStyle = xlContinuous
        .Weight = xlThick
    End With
    With rng.Borders(xlEdgeBottom)
        .LineStyle = xlContinuous
        .Weight = xlThick
    End With
    With rng.Borders(xlEdgeLeft)
        .LineStyle = xlContinuous
        .Weight = xlThick
    End With
    With rng.Borders(xlEdgeRight)
        .LineStyle = xlContinuous
        .Weight = xlThick
    End With
    
    ' 内側の格子線を適用
    With rng.Borders(xlInsideVertical)
        .LineStyle = xlContinuous
        .Weight = xlThin
    End With
    With rng.Borders(xlInsideHorizontal)
        .LineStyle = xlContinuous
        .Weight = xlThin
    End With
End Sub


```
ジェネリックについて少し理解できた気がする

## この記事でわかること
- ジェネリックをどのような場面で使用するか（型の安全性について）
- out(共変) について
- in(反変) について

## ジェネリックをどのような場面で使用するか（型の安全性について）
Kotlinにおいて、ジェネリックを利用することで、様々な型に対応可能な汎用的なクラスやメソッドを簡単に作成できます。ここでは、ジェネリックを使ったシンプルなBoxクラスを例に取り上げ、その基本的な使い方を説明します。
```kotlin
class Box<T>(t: T) {
    var value = t

    fun updateValue(v: T) {
        value = v
    }

    fun returnValue(): T {
        return value
    }
}

val box = Box("xxx")
box.updateValue("yyy")
box.returnValue // return "yyy"

val box = Box(111)
box.updateValue(222)
box.returnValue // return 222
```
BoxクラスはInt、String、カスタムクラスなど、どんな型のデータも格納できます。この柔軟性により、コードの再利用性と型安全を確保しつつ、様々なデータ操作を一つのクラスで行えます。

例えば、上記のコードでジェネリックの代わりにAnyを使用すると型の不一致が起きる可能性があります。


----
ここからは色々調べながら書いたので間違いがあればコメントで指摘お願いします。

## out(共変) について
outキーワードを使用することで、ジェネリック型の共変を安全に実現できます。これにより、サブタイプのインスタンスをスーパータイプの変数に代入することが可能になり、より柔軟なコードが書けるようになります。
```kotlin
// outを使用する場合
class Box<out T>(val value: T)

fun main() {
    val stringBox: Box<String> = Box("Hello")
    val anyBox: Box<Any> = stringBox // StringはAnyのサブタイプなので、これは許可されます。

    val intBox: Box<Int> = Box(123)
    val anyBox: Box<Any> = intBox
}
```
```kotlin
// outを使用しない場合
class Box<T>(val value: T)

fun main() {
    val stringBox: Box<String> = Box("Hello")
    
    val anyBox: Box<Any> = stringBox // コンパイルエラー
    val stringBox2️: Box<String> = stringBox // エラーは起きない
}
```
上記の例では、IntとStringはAnyのサブタイプであるため、Box< Any >にBox< Int >,Box< String >を代入することができます。
Any, StringではStringのスーパータイプにAnyがあるのと同じように、
Box< Any >とBox< String >ではBox< String >のスーパータイプがBox< Any >であり、
この方向が同じであるから共変と言います。

## in(反変) について
Kotlinのinキーワードは、ジェネリック型がメソッド引数としてのみ使用される場合に使います。これにより、ジェネリック型が反変になり、より具体的な型のインスタンスをより一般的な型のパラメータに代入できるようになります。
```kotlin
// inを使用する場合
class LoggerConsumer<in T> {
    fun log(item: T) {
        println("Logging: $item")
    }
}

fun main() {
    val anyLogger: LoggerConsumer<Any> = LoggerConsumer<Any>()
    anyLogger.log(123)
    anyLogger.log(true)

    // Any型のConsumerをString型のConsumerとして扱う
    val stringLogger: LoggerConsumer<String> = anyLogger
    stringLogger.log("This is a string")

    val intLogger: LoggerConsumer<Int> = anyLogger
    intLogger.log(111)
}
```
```kotlin
// inを使用しない場合
class LoggerConsumer<T> {
    fun log(item: T) {
        println("Logging: $item")
    }
}

fun main() {
    val stringLogger: LoggerConsumer<String> = LoggerConsumer<String>()
    stringLogger.log("This is a string")

    val intLogger: LoggerConsumer<Int> = LoggerConsumer<Int>()
    intLogger.log(111)
}
```
上記の例では、inを使用することで異なる型毎にインスタンスを作成する必要がなくなり、インスタンスを再利用できるようになります。
Any, Stringでは、StringのスーパータイプがAnyであり、
LoggerConsumer< Any >, LoggerConsumer< String >では、LoggerConsumer< Any >のスーパータイプがLoggerConsumer< String >であり、
この方向が反対であるため反変と言います。
window.matchMediaを使用したレスポンシブ対応

## matchMediaを使用する理由
Javascriptでレスポンシブ対応を行う場合、ウィンドウサイズを取得とresizeの監視により処理を行うという方法があります。しかし、それではウィンドウサイズを変更するたびに実行されるためパフォーマンスとして良くありません。

matchMediaを使用することでブレイクポイントの切り替わりに応じて処理を実行することができるため、resizeのように無駄な処理の実行を防ぐことができます。

## 使用方法
### ブレイクポイントを決める
```javascript
const mediaQuery = window.matchMedia('(min-width: 768px)');
```
まずはブレイクポイントを決めます。window.matchMediaを使用することで「MediaQueryListオブジェクト」が作られ、それを変数に格納します。こちらを基準として処理の切り替えを行います。

### 関数を定義
```javascript
function checkWindow(windowSize) {
    if (windowSize.matches) {
        console.log('PCの処理');
    } else {
        console.log('SPの処理');
    }
}
```
次に、ウィンドウサイズによりどのような処理を行うか関数を定義します。windowSize.matchesは真偽値となります。関数を実行する際に、引数には変数mediaQueryを入れることになるので、'(min-width: 768px)'がtrueの場合はPCの処理、それ以外はSPの処理という分岐になります。

### ブレイクポイントの切り替えに応じて関数を実行
```javascript
mediaQuery.addEventListener('change', checkWindow);
```
定義した関数を実行するため、mediaQueryにイベントリスナー'change'を設定します。これで、ウィンドウサイズがブレイクポイントに差し掛かったタイミングで関数checkWindowが実行されます。

## 全体のコード
ここまでの内容をまとめると以下のようなコードになります。
resizeイベントよりも使い勝手が良さそうなのでおすすめです。
```javascript
// ブレイクポイントを設定
const mediaQuery = window.matchMedia('(min-width: 768px)');

// 関数を定義
function checkWindow(windowSize) {
    // ウィンドウサイズが768px以上か
    if (windowSize.matches) {
        // 768px以上の時（PCの処理）
        console.log('PC');
    } else {
        // 上記以外の時（SPの処理）
        console.log('SP');
    }
}

// ロード時に判定
checkWindow(mediaQuery);

// ブレイクポイントが切り替わったら判定
mediaQuery.addEventListener('change', checkWindow);
```
指定バイトのランダムワードを出力するツールプログラム

1GBのランダムな単語が羅列させた改行なしのテストデータを作れやって突然言われたので、bashで作ってみたはいいけど処理が遅すぎて使いものにならない。

そんなわけでC言語にて、作りなおしたのがこちらです。

動作させるには、linuxだと
gcc -o create_data create.c
とかでコンパイルしてもらって

実行は、
./create_data 500000 hogehgoe.txt
みたいな感じです。

```c:create_data.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 単語のリストを定義
const char* word_list[] = {
    "apple", "banana", "cherry", "date", "elderberry",
    "fig", "grape", "honeydew", "kiwi", "lemon"
};

// 出力ファイルのパスを定義
const char* output_file = "output.txt";

int main(int argc, char* argv[]) {
    if (argc != 3) {
        printf("使用法: %s <limit_file_size_in_bytes> <output_file>\n", argv[0]);
        return 1;
    }

    long limit_file_size = atol(argv[1]);
    const char* output_file = argv[2]; // ここで再度 output_file を指定

    FILE* file = fopen(output_file, "a");
    if (file == NULL) {
        perror("ファイルを開く際のエラー");
        return 1;
    }

    // 現在のファイルサイズを初期化
    long current_file_size = 0;

    // 乱数ジェネレータを初期化
    srand(time(NULL));

    // 出力ファイルを追記モードで開く
    while (current_file_size < limit_file_size) {
        // リストからランダムに単語を選択
        int random_index = rand() % (sizeof(word_list) / sizeof(word_list[0]));
        const char* selected_word = word_list[random_index];

        // 改行なしで選択した単語をファイルに書き込む
        fprintf(file, "%s", selected_word);

        // 現在のファイルサイズを更新
        fseek(file, 0, SEEK_END);
        current_file_size = ftell(file);
    }

    // ファイルを閉じる
    fclose(file);

    // 成功メッセージを表示
    printf("単語が %s に正常に追加されました。現在のファイルサイズ: %ld バイト。\n", output_file, current_file_size);

    return 0;
}
```
1GBの出力で、だいたい2分ちょいです（環境によりけり）
ご利用は自己責任にてお願いします。

（了）
Zabbix6.4 を AlmaLinux 9 にインストール(MySQL) サーバ/エージェント

# Zabbixとは
「サーバー、ネットワーク、アプリケーションを集中監視するためのオープンソースの統合監視ソフトウェアです。監視、障害検知、通知機能を備えています」とあります。昔10年位前に監視設定するためインストールした記憶があり、個人的に懐かしいな～～って感じでいたら、最新7.0までになっていてびっくり。

あと某有名SIerさんの会社も参入していて２度びっくるｗ

# Zabbixサーバのインストール（前準備）
Zabbixのサイトで ”使用するバージョン/OS/OS バージョン・・・” を選択するだけでインストール方法を示してくれます。
好きなOS（Linux）を使用すればよいと思います。私は AlmaLinux 9 を使用します。

https://www.zabbix.com/download?utm_campaign=mainpage&utm_source=website&utm_medium=header

例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/ac8e2474-ef07-b848-907d-d12ef00307fb.png)

# Zabbixサーバのインストール（インストール前にやっておくべきインストール）
タイトルの日本語が正しくないかもしれませんが、Zabbixで使用するデータベース（ここでは MySQLで進めます）は、事前にインストールしておく必要があります。そうでないといきなりスキーマ設定から始まり詰む。

そんなこと回避するため事前に MySQLをインストールしておきましょう。

```bash
# dnf install mysql-server
# systemctl enable mysqld
# systemctl start mysqld
# mysql_secure_installation
```

https://rin-ka.net/mysql8-init/

# Zabbixサーバのインストール
データベースをインストール＆セットアップ済みであれば、あとはZabbixのサイトで ”使用するバージョン/OS/OS バージョン・・・” 選択した後に表示されている 「Install and configure Zabbix for your platform」以降を実行すればよい。

手順とおりに実施すれば、ログイン画面が表示されるので「ユーザー名にAdmin,パスワードにzabbix」と入力しログインできるはず。

# Zabbixを日本語化したい
日本語にしたい！！

```bash
# dnf -y install glibc-locale-source glibc-langpack-ja zabbix-web-japanese
```

ついでにタイムゾーンとロケールなども

```bash
# timedatectl set-timezone Asia/Tokyo
# localectl set-locale LANG=ja_JP.utf8
# localectl set-keymap jp106
# localectl
```

https://zenn.dev/payapayao/articles/setting-zabbix

https://changineer.info/server/monitoring/monitoring_zabbix_japanese.html

# Zabbixエージェントのインストール
Zabbixサーバと対になるバージョンのエージェントをインストールします。ここでも AlmaLinux 9 を使います。

```bash
# rpm -Uvh https://repo.zabbix.com/zabbix/6.4/rhel/9/x86_64/zabbix-release-6.4-1.el9.noarch.rpm
# dnf install zabbix-agent
```

インストールが終わったら `/etc/zabbix/zabbix_agentd.conf` を編集します。

https://www.naokilog.com/2023/11/03/zabbix-agent-installation/

# Zabbixサーバ側でのホスト追加
Zabbixサーバ側でホスト追加をする必要があります。ホスト追加手順は割愛しますが、しばらくするとエージェントの状態が ”緑色” になります。

”緑色” にならないサーバがあり、どうやっても原因が分からず・・・ｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44540/6c674e01-94ed-8ad0-c007-986dd1b5f852.png)

# Zabbixでログ監視
ずいぶん昔に触ったときに覚えたような気がするのですが、”アイテム/トリガー” をすっかり忘れていたようで２時間ぐらい勉強しました。そしてわかりやすいサイトがあったのでご紹介します。

https://n-laboratory.jp/articles/zabbix-notification

# Zabbix触ってみて
本音でいうと”使いにくい”です。操作の動線が分からずらい。
と思ってましたが、慣れるとそこそこ使えるようになりました。

結果個人的に思った点として
　・初期テンプレートを使用することで運用準備が軽減できる。
　・マップ機能を使うと非活監視が分かりやすい。
　・ダッシュボードカスタムすることでできる奴っぽく見えるｗ。
　・障害時のチケット管理がやりやすい。
ですかね。

# Zabbix + Proxmox
ちょっとかっこいいかもｗ って思いました。

https://zenn.dev/k1ch/articles/35f6dfbcee1a65

https://www.zabbix.com/integrations/proxmox

https://github.com/takala-jp/zabbix-proxmox
CodeCommitをローカルにクーロンする方法

# はじめに
今回業務でCodeCommitをローカルにクーロンするといった作業を行ったのでこちらに手順をまとめていこうと思います。

## 手順１～クレデンシャルパスワードの取得～
①AWSのマネジメントコンソールから一番右上のリージョンが書かれているタブの右のタブをクリックしてその中で『セキュリティ認証情報』をクリック。
②AWS CodeCommit認証情報を選んで『AWS CodeCommit の HTTPS Git 認証情報』をクリック
これでGitのクレデンシャルパスワードを取得できる。

## 手順２～Gitをローカル環境にダウンロード（Gitをダウンロードしていない人が対象）~
①下記のURLを使ってローカル環境にGitをダウンロードする。（自分の場合はWindows用の64bitのバージョンをインストールした)https://git-scm.com/downloads
## 手順３～CodeCommitからHttpsのクローンを取得する～
①AWSマネジメントコンソールの初期画面で『CodeCommit』と検索。
②『リポジトリ』の中からローカルにクーロンしたいものを選択する。
③右上の『URLのクローン』タブから『HTTPSのクローンを選択する』をクリックし、URLをコピーする
④先ほどコピーしたURLをメモ帳などに張り付けて、URLの前に『git clone』と入力する。
 →並べると  git clone https://~~~~のようになる。

## 手順４～コマンドプロンプトからデータを保存する～
①ローカルのコマンドプロンプトを開いて、cdコマンドを使ってリポジトリを保存したいディレクトリに移動する。
②手順③のメモ帳に記載してある『git clone https://~~~~』をコマンドとして張り付ける。
③クレデンシャルパスワードの入力を求められたら手順①で取得したパスワードを入力する。

# 最後に
Gitを初めて使ったのですが、とても便利な機能なので今後も使っていきたいと思います。
Databricks にて末尾に複数の改行文字がある CSV ファイルから Spark データフレーム作成の検証結果

## 概要
検証コードと実行結果を共有します
Databricks にて末尾に複数の改行文字がある CSV ファイルから Spark データフレーム作成の検証結果を後述します。

末尾に複数の改行がある CSV ファイルとは、下記のようなファイルです。

```text
a,b,c

e,f,g


h,i,j

k,l,m
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c4091d84-bd38-a1e5-8b9e-b212adc8c192.png)


下記のように末尾の複数の改行文字が

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/96884873-8f84-e45f-e784-250718abd7ed.png)

## 検証コードと実行結果

### ファイルの準備

Databricks Repos 上で実行することを想定しております。

```python
import os
src_dir = f"{os.getcwd()}/test_data"
src_path = f"{src_dir}/sample.csv"

src_data = """
a,b,c\r\n\r\ne,f,g\r\n\r\n\r\nh,i,j\r\n\r\nk,l,m
""".strip()

with open(src_path, "w") as file:
    file.write(src_data)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d8ed344-eeb0-1753-d482-6fbd9a84f1fd.png)

### Spark データフレームの検証

```python
schema = """
col1 string,
col2 string,
col3 string,
_corrupt_record string
"""

df = (
    spark.read.format("csv")
    .schema(schema)
    .load(f"file:{src_dir}")
)

df.display()
print(df.collect())
```

```text
[
    Row(col1="a", col2="b", col3="c", _corrupt_record=None),
    Row(col1="e", col2="f", col3="g", _corrupt_record=None),
    Row(col1="h", col2="i", col3="j", _corrupt_record=None),
    Row(col1="k", col2="l", col3="m", _corrupt_record=None),
]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/50f7cef7-ee59-1cf4-501c-5adf48db2e85.png)

### Spark データフレーム（`multiLine`オプションを`True`）の検証

```python
df = (
    spark.read.format("csv")
    .schema(schema)
    .option("multiLine", "true")
    .load(f"file:{src_dir}")
)

df.display()
print(df.collect())
```

```text
[
    Row(col1="a", col2="b", col3="c", _corrupt_record=None),
    Row(col1="e", col2="f", col3="g", _corrupt_record=None),
    Row(col1="h", col2="i", col3="j", _corrupt_record=None),
    Row(col1="k", col2="l", col3="m", _corrupt_record=None),
]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/50af268c-ecb0-3a08-1937-1af5d782cc54.png)
横に長いkey,valueを格納する

# 横に長いkey,valueを格納する
もうね、あるあるなんですよ。列でkey,valueになっちゃってるやつ。
しかも規則なくただ単に突っ込まれているようなもの。たとえばこんなの。
（今回はサンプルで3つだけど、これが300とかあると地獄）
|uuid  |key_1  |value_1  |key_2  |value_2  |key_3  |value_3  |
|---|---|---|---|---|---|---|
|鮭おにぎり  |素材  |鮭  |重さ  |200g  |製造者  |おれ  |
|梅おにぎり  |重さ  |300g  |素材  |梅  |素材製造者  |おふくろ  |

こんなもん、どこに何があるかわかるかい！ってなるわけですよ。
key_1にはこういう値をいれましょうねぇって誰も守らない。
で、そういうのをうまくkey,valueに出来ないもんかと。
そんなクエリ。

```sql:array_struct.sql
select
    uuid,
    [
    struct(key_1 as key_name,value_1 as col_value), --ここはスプレッドシートなりでうまく作っちゃう
    struct(key_2 as key_name,value_2 as col_value),
    struct(key_3 as key_name,value_3 as col_value)
    ] as key_value
from
    table_name
```
で、これがどうなるかというと、こうなる
|uuid  |key_value.key_name  |key_value.col_value  |
|---|---|---|
|鮭おにぎり  |素材  |鮭  |
| |重さ  |200g  |
| |製造者  |おれ  |
|梅おにぎり  |重さ  |300g  |
| |素材  |梅  |
| |素材製造者  |おふくろ  |

でも、ここで"重さ"だけを出したいとします。
先程のクエリをwith句に入れちゃうとこうなります。
（こういうのはテーブルにするほうが後々便利に使えることもあるので、テーブルにしちゃうのもアリだと思います）
```sql:unnest.sql
with info as (
    select
        uuid,
        [
        struct(key_1 as key_name,value_1 as col_value), --ここはスプレッドシートなりでうまく作っちゃう
        struct(key_2 as key_name,value_2 as col_value),
        struct(key_3 as key_name,value_3 as col_value)
        ] as key_value
    from
        table_name
)

select
    uuid,
    kv.key_name,
    kv.col_value
from
    info,unnest(key_value) as kv
where
    kv.key_name = "重さ"
```
で、結果はこうなります。
|uuid  |key_name  |kcol_value  |
|---|---|---|
|鮭おにぎり  |重さ  |200g  |
|梅おにぎり  |重さ  |300g  |

はい。出来ました。
こんなことあるかい！うちのマスタはきれいなもんだぜ！って言ってるそこのあなたにお届けします。おるんかどうかしらんけど。
git clone時にcurl 56 GnuTLS recv error (-110)で進まない

# 問題

いつも通り、いや結構久々WSL2上で`git clone`をしてみたところ、clone出来ない事象が発生する。
```
XXXXXX@XXXXXX:~/git$ git clone https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess.git
Cloning into '100knocks-preprocess'...
remote: Enumerating objects: 1798, done.
remote: Counting objects: 100% (593/593), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 1798 (delta 523), reused 513 (delta 494), pack-reused 1205
Receiving objects: 100% (1798/1798), 20.91 MiB | 5.44 MiB/s, done.
error: RPC failed; curl 56 GnuTLS recv error (-110): The TLS connection was non-properly terminated.
Resolving deltas: 100% (1004/1004), done.
```
ちょっと前に実施した際は上手くいっていたので、設定の問題ではないはず。
# 環境

- Windows10
- WSL2
- Ubuntu 20.04

# 調査結果
https://taktak.jp/2023/07/01/4492/
https://stackoverflow.com/questions/52529639/gnutls-recv-error-110-the-tls-connection-was-non-properly-terminated/52530617#52530617
うーん。zscalerね…。またか…。
しかもgitの再ビルドが必要なの…？

# 解決法
stackoverflowにはいくつかの解決法が書いてあるが、直近の方が望ましそうなので自分が上手くいった手順を記載する。

```
sudo apt remove git -y
sudo apt update && sudo apt upgrade

DEBIAN_FRONTEND=noninteractive

sudo apt install build-essential autoconf dh-autoreconf libcurl4-openssl-dev \
                 tcl-dev gettext asciidoc docbook2x install-info \
                 libexpat1-dev libz-dev -y

wget https://raw.githubusercontent.com/paul-nelson-baker/git-openssl-shellscript/master/compile-git-with-openssl.sh .

./compile-git-with-openssl.sh -skiptests
```
これをやってgit cloneを再度試してみる。
```
XXXXXX@XXXXXX:~/git$ git clone https://github.com/The-Japan-DataScientist-Society/100knocks-preprocess.git
Cloning into '100knocks-preprocess'...
remote: Enumerating objects: 1798, done.
remote: Counting objects: 100% (593/593), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 1798 (delta 523), reused 513 (delta 494), pack-reused 1205
Receiving objects: 100% (1798/1798), 20.91 MiB | 5.54 MiB/s, done.
Resolving deltas: 100% (1004/1004), done.
```
やったね！
プログラミング練習問題「銀行」

https://paiza.jp/works/mondai/query_primer/query_primer__bank


ひとまず前回と同じようにタプルで配列を組んでみたのですが
どうやって配列から参照するかで詰まってしまいました。
時間も長くかかってしまったので回答を見ました。

```py
N,K = map(int,input())
companies = [None] * N
for i in range(N):
    name,password,bill = input().split()
    companies[i] = (name,int(password),int(bill))
    
for _ in range(K):
    name,password,bill = input().split()
    if companies[name] 
    #ここで詰まる
```

回答を見ると、タプルと辞書を組み合わせた感じで、
私はまだやったことがない方法でした。。。
勉強させてもらうということで、ちょっと自分なりにやってみました。

```py
N,K = map(int,input().split())

companies = {}
#companies
for _ in range(N):
    company, password, balance = input().split()
    #辞書のキーをcompanyにして、パスと残高をタプルにする
    companies[company] = (password, int(balance))

#deal
for _ in range(K):
    company, password, deal = input().split()
    #タプルから変数で取得する
    pin, saving = companies[company]
    #パスワードが一致しなかったらスキップ
    if pin != password:
        continue
    #ふたたびタプルとして戻す
    companies[company] = (pin, saving - int(deal))

#現在の各会社名と残高を出力
for name, data in companies.items():
    print(name, data[1])

```
辞書とタプルの登録方法と、
タプルからは変数に代入させる方法でもどして
さらに計算をしてからタプルに戻すという感じに。

その後の出力は
辞書の出力は、キーは、`keys` 値は、`values` キー&値は `items`
でそれぞれ出力ができる。
さらに、上のように、それぞれ変数に格納して出力が可能なので覚えておきたい。
アシスタント機能のアップデート Cognos Analytics 12.0.1 + 12.0.2

# 概要
自然言語の入力でグラフの作成が行える「アシスタント」の機能に関して、こちらの記事で以前に紹介していました。
**Cognos Analytics 12.0 新機能 アシスタント**
https://qiita.com/shinyama/items/7eabb9e07926aa2d2354

今回はCognos Analytics 12.0.1と12.0.2での機能アップデートをご紹介します。

# 参考情報
**アシスタント 12.0.1**
https://www.ibm.com/docs/en/cognos-analytics/12.0.0?topic=2023-assistant
**アシスタント 12.0.2**
https://www.ibm.com/docs/en/cognos-analytics/12.0.0?topic=2024-assistant

# 12.0.1でのアップデート
データソースの選択時に、「choose source」「 set source」「 change source」「select source」というフレーズが使えるようになりました。
例えば、select sourceまで入れてみると、ソースの候補リストが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/914ff640-7611-fd5f-5034-29202e3b6184.png)

リストはされていませんが、「GS_Website」という名称のソースを指定してみると、Cognosフォルダ内を検索してマッチするソースを選択してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/607a2101-800a-aa6f-3b66-0ee61b044a28.png)

コマンドのガイドも親切です。Showまで打つと、候補のコマンドオプションが選択されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/c600adee-0d8e-ed2f-18db-3af02523eec2.png)

show columnを打つと、このソース内の列がわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/51b1f2d9-657b-42a9-1e6d-64a1280da87b.png)

Visualizationを得るためのコマンドも途中で候補が出ます。Regionを選択してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/6760dd5f-c2d4-64b0-b90d-6378db7cd5a7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/e168d572-9117-d315-3c31-71c1c3d18777.png)

Visualizationが表示されました。
この画面でもアップデートがあり、Shareで「Top Insights」の文言もメールやSlackで共有できるようになり、Add to でVisualizationを新規のダッシュボードだけでなく、現在編集中のダッシュボードにも貼り付け可能となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/c76c47b1-e032-3b4a-6300-a04b29365a9a.png)

「What is」「When is」「Where is」「Who is」などの質問に関して、アシスタントがシンプルな回答でOKと判断した場合、Visualizationではなく、イメージのようなテキストベースでレスポンス良く回答されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/839e3ed2-4c33-f361-e92c-8447ee266a67.png)

また、Visualization作成不能な質問に関してはLearn Panelのリンクが表示され
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/b0a42dd2-766a-6186-24e6-2691b38a17de.png)

リンクを開くと入力した質問が引き継がれて検索された結果が表示されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/a27e9857-e976-4645-a767-a25b5309d08c.png)

**12.0.2でのアップデート**
データソースの選択時に、「Select sample data source」が表示され、サンプルを利用してAssistantの機能を学習できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/a0eb28f4-c777-fc43-5093-971f2296f20e.png)

「コール・センター」「コーヒーの販売とマーケティング」「病院の入院データ」のサンプルソースが選べますが、サンプル選択すると、こんな質問してみてはどうかというSuggestionの質問を例として表示してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/8edbf4c3-6c09-813d-861f-91da49915e04.png)
display:flexの使い方

前回「displayの役割と要素の表示方式について」という記事を書いたのですが、今回は「flex」の役割について詳しく記載します。

## 「display:flex」とは
改めて「display:flex」についておさらいをします。

ChatGPTで調べたところ下記の回答がありました。

>ChatGPT：
>Flexboxは、従来のblock、inline、inline-blockでは難しかったレイアウト課題に対応するために開発されました。レスポンシブデザインの容易化、要素の垂直中央揃え、スペースの均等分配、アイテムの順序変更、複数行フレックスアイテムの管理など、柔軟なレイアウトを簡単に実現できます。コードの簡素化と保守性の向上も大きな利点です。これにより、ウェブ開発者はより複雑なレイアウトを簡易かつ効率的に構築できるようになりました。

要するに従来のblock、inline、inline-blockを使ってデザインするより、「要素のレイアウトが格段にやりやすくなりました。」ということです。

![スクリーンショット 2024-04-02 15.28.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/94bc6eec-17ee-4a23-b7a9-fb4837cc23e5.png)
そして「display:flex」はレイアウトを適用させたい子要素の「要素」と、それらをラップする親要素の「コンテナ」から構成されます。

参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")


## 「display:flex」でできること
では「display:flex」で行えることをまとめていきます。

### 並べる方向を指定（flex-direction）

```
使用例：
.container {
  display: flex;
  flex-direction: row-reverse;
}
```
![スクリーンショット 2024-04-02 15.33.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/5251dec4-f724-3267-d62c-eb0ea84a5988.png)
![スクリーンショット 2024-04-02 15.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/1cadb9f9-e1eb-7f39-94f8-0e4fa02dbae3.png)
参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")


### 折り返しを指定（flex-wrap）
```
使用例：
.container {
  display: flex;
  flex-wrap: wrap;
}
```
![スクリーンショット 2024-04-02 15.34.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/4f7416f3-8246-42ab-b134-018c21ba922c.png)
参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")

### 水平方向のレイアウトを指定（justify-content）
```
使用例：
.container {
  display: flex;
  justify-content: center;
}
```
![スクリーンショット 2024-04-02 15.40.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/19caac14-c355-807d-8f92-e9e6465ff5b2.png)
参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")

### 垂直方向のレイアウトを指定（align-items）
```
使用例：
.container {
　　display: flex;
　　align-items: center;
}
```
![スクリーンショット 2024-04-02 15.42.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/688f4718-80c3-39cb-f063-c12314243de8.png)
northeast-1.amazonaws.com/0/3670873/4f7416f3-8246-42ab-b134-018c21ba922c.png)
参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")

### 複数行の垂直方向レイアウトを指定（align-content）
```
使用例：
.container {
  display: flex;
  align-content: center;
}
```
![スクリーンショット 2024-04-02 15.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/df857bb1-2dfa-5cd4-bc15-5bbc5b4e77dd.png)
参照：[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")

## 参考文献
[【初心者向け】フレックスボックスとは？display:flexの使い方（基礎編）](https://www.asobou.co.jp/blog/web/flex-box#i "フレックスボックスについての記事")
[【CSS】flexboxの基本](https://zenn.dev/masakunn/scraps/98f14ac8396da4 "フレックスボックスについての記事")
[【CSS display:flex】フレックスボックスの使い方](https://webst8.com/blog/css-flex/ "フレックスボックスについての記事")
SoR／SoEとモード1／モード2の違い

よく違いを忘れるので備忘録として。個人的な解釈です。

## SoR／SoE
システムの特性・役割についての分類。「システム」を表現する言葉。

### SoR (System of Record)
・データが正確に保存することがテーマ。既存業務の高速化、コスト面の効率化に繋がる。
・会計などのいわゆる基幹システム全般が該当。
### SoE (System of Engagement)
・お客様との繋がりを促進することがテーマ。ビジネス拡大への貢献する。
・UXが重要で、差別化要素にも繋がる。

## モード1／モード2
開発アプローチ面での分類。「プロジェクト」や「開発チーム」を表現する言葉。
「モード2が新しくてモダンでこちらに寄せるべき」ではなく、プロジェクトに合わせて適切なモードが選択できる（＝バイモーダル）と幸せになれそう。

### モード1
予測可能な分野での開発。既存の業務フローをデジタル化するなど。
ウォーターフォールが主な開発アプローチ。

### モード2
予測が困難な分野での開発。新規事業や、業務要件が整理しきれないプロジェクト等。
アジャイル開発等で対応することが考えられる。

## 組合せの可能性
SoR×モード1、SoE×モード2が王道と思われる。それだけに、2つの言葉が同じ概念（SoR≒モード1、SoE≒モード2）として語られがち。

SoEがモード2を経て、ビジネスが拡大・安定したところでモード1にシフトする流れは正統派の進化。

SoR×モード2は、多くの場合バッドプラクティスになりそう...

## 参考
https://www.forbes.com/sites/joshbersin/2012/08/16/the-move-from-systems-of-record-to-systems-of-engagement

https://www.gartner.com/en/information-technology/glossary/bimodal
spring bootとDockerでWebAPIサーバ作成を試す

## APIコンテナを初作成してみる： springboot

表題の通りです。
ブラウザに「Hello」を表示させることをゴールにDockerでAPIコンテナ作成してみます。

springbootを使用するためにまず[spring initializr](https://start.spring.io/)へアクセス

※※今回springbootをメインで取り上げるわけではないので詳細な説明は省きます。ご了承ください。気になる方は以下の記事などおすすめです※※(https://note.com/on_bass/n/ne8c12b19f043)


![スクリーンショット 2024-04-02 14.41.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/d2923ad9-7f18-0b6a-80a1-395cfb3ce538.png)


1.向かって右上あたりにある「ADD DEPENDENCIES」をクリック
![スクリーンショット 2024-04-02 15.05.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/666066b7-ebcf-3a91-65bb-02e2ebe669bd.png)


2.追加する依存関係(＝ADD DEPENDENCIES)を検索してクリックすると追加してくれるので、雛形に「Spring Web」、「Spring Data JPA」「Postgle SQL Driver」、「H2 Database」の4つを追加します。
![スクリーンショット 2024-04-02 15.11.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/336e25f5-1e17-518e-75f5-98dc16f0abf4.png)

3.今回左側の設定は殆どデフォルトのままで生成しました。
※Project MetadataのNameとArtifactのみ「api_container_practice」に編集してます。
![スクリーンショット 2024-04-02 15.13.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/7de6d25c-1f54-5eaf-73b8-a659a6e65e65.png)

4.画面下部のGENERATEボタンを押下すると「api_container_practice.zip（変更した名前＝ファイル名）」というzipファイルが生成されます。

![スクリーンショット 2024-04-02 15.16.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/3f8fd44a-d0f6-8585-d2ec-3ab2058b9f94.png)

zipファイルを解凍すると中身はこんな感じ。※Javaなのにスネークケースで命名してしまっているのは何卒ご容赦ください…。
![スクリーンショット 2024-04-02 15.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/1763761a-f3f3-29c4-26cf-400d7cec9055.png)


## Javaファイルの編集：　controller作成
src/main/java/example/api_container_practiceの直下にHelloController.javaを作成します。
当該ファイル内は以下のように編集。

![スクリーンショット 2024-04-02 15.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/8ea99e20-6e15-2fdb-4ae0-83f064571f58.png)


## Dockerfileの作成
api_container_practice直下にDockerfileを作成。
中身は以下のようにします。

```dockerfile
#ベースイメージ
FROM gradle:7

#コンテナ実行時の作業ディレクトリ
WORKDIR /api_container_practice

#現在のディレクトリ＋コンテナ側のディレクトリ
COPY . .

#実行コマンド
CMD ["./gradlew","bootRun"]

```

ターミナルで以下コマンドを実行。（作業ディレクトリで行ってください。）

```
$ docker image build -t api-demo .

# Build後に実行
$ docker container run -p 8080:8080 --rm api-demo
```
以下のような画面が出ればAPIコンテナが起動してます。
![スクリーンショット 2024-04-02 14.32.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/f1bfc395-ec98-184b-091d-0cc2b539565c.png)


## ブラウザでリクエスト送って確認
![スクリーンショット 2024-04-02 14.40.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/3b20335c-9334-730c-88e9-df51254bfc13.png)


以上で終了です。
Dockerfileやコンテナはまだ理解が全然浅いので、精進します。

## 参考
[Spring Initializrでアプリケーションのひな型を作成する](https://qiita.com/rubytomato@github/items/b2c0686517e1c86ceb48)
Docker で Wordpress するときに自分が困ったこと

自分用メモです。

どうにか環境はできて、インストールの段階になったけど
データベース接続確立エラーになった。

localhost としていたところを、compose.yml で設定した services の名前 (db) にしたらいけた。

mod_rewrite が動いてなかった。

Dockerfile に一行追加

FROM php:7.2.34-apache
RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-install mysqli
RUN  a2enmod rewrite　←　これ

そういえば myspli も足りなかったっけ。

また困ったら追記していきます。
ZED SDK で複数の検出タスクをこなす

# 想定する読者
stereolabsのzed2, zed mini, zed x などのステレオカメラの利用者
いまどきのステレオカメラは何ができるのかを知りたい人

# 前提
ZED SDK 4.0
Ubuntu 20.04
ZED2i
Python 版のAPI

# ZED SDK にある例題
https://github.com/stereolabs/zed-sdk/tree/master/object%20detection/concurrent%20detections
C++版です。
次のようにして、ビルド、実行できます。

```
cd "zed-sdk/object detection/concurrent detections/cpp"
mkdir build
cd build/
cmake ../CMakeLists.txt
make
./ZED_concurrent_detections
```

## zed-concurrent-detections-python-proto
https://github.com/adujardin/zed-concurrent-detections-python-proto

- これはpythonによる実装です。
- 物体検出のタスクとbody_parts の検出のタスクを同時にこなします。


## 複数の検出タスクが失敗するときに注意したいこと
- 推論の実行の際に関係するinstance_module_id の値を複数のタスクで重ならないようにすること。
- zed.retrieve_bodies() , zed.retrieve_objects() の３つめの引数が必要になることに注意しよう。

```.py:
obj_param = sl.ObjectDetectionParameters()
body_param = sl.BodyTrackingParameters()

中略

obj_param.instance_module_id = 0
body_param.instance_module_id = 1
zed.retrieve_bodies(bodies, body_runtime_param, body_param.instance_module_id)
zed.retrieve_objects(objects, obj_runtime_param, obj_param.instance_module_id)
```

### 公式のドキュメントについて
https://www.stereolabs.com/docs/body-tracking/using-body-tracking

上記の公式のドキュメントでは、検出タスクが１つしか動作させていないため、３つめの引数を省略しても動作する。
そのため、３つめの引数についての記載がない。
`help(zed.retrieve_bodies)`
などとして、使い方にたどり着いてほしい。

### ヒントになったStereoLabs のフォーラム
[Concurrent custom Object Detection and Body Tracking](https://community.stereolabs.com/t/concurrent-custom-object-detection-and-body-tracking/2572)