OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby OpenSSL::PKCS5.pbkdf2_hmac_sha1 をPHPで置き換えたときのメモ

```ruby
def self.encrypt(data, pass, salt)
    cipher = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
    key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, 1000, cipher.key_len+cipher.iv_len)
    key = key_iv[0, cipher.key_len]
    iv  = key_iv[cipher.key_len, cipher.iv_len]
    cipher.encrypt
    cipher.key = key
    cipher.iv = iv
    encryptvalue = cipher.update(data) + cipher.final
    return Base64.b64encode(encryptvalue)
end
  
def self.decrypt(data, pass, salt)
    enctyptvalue = Base64.decode64(data)
    cipher = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
    key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, 1000, cipher.key_len+cipher.iv_len)
    key = key_iv[0, cipher.key_len]
    iv  = key_iv[cipher.key_len, cipher.iv_len]
    cipher.decrypt
    cipher.key = key
    cipher.iv = iv
    cipher.update(enctyptvalue) + cipher.final
end
```

```php
function encrypt($data, $pass, $salt) {
	$key_iv = openssl_pbkdf2($pass, $salt, 32+16, 1000);
	$key = substr($key_iv, 0, 32);
	$iv  = substr($key_iv, 32, 16);
	$decrypted_text = openssl_encrypt($data, 'AES-256-CBC', $key, 0, $iv);
	return $decrypted_text;
}
function decrypt($data, $pass, $salt) {
	$key_iv = openssl_pbkdf2($pass, $salt, 32+16, 1000);
	$key = substr($key_iv, 0, 32);
	$iv  = substr($key_iv, 32, 16);
	$decrypted_text = openssl_decrypt($data, 'AES-256-CBC', $key, 0, $iv);
	return $decrypted_text;
}
```
二項分布の正規分布による近似を Python で確かめる

# 本記事の目的
二項分布は $n$ が大きい場合に正規分布によって近似できます．
これを Python で確かめるのが本記事の目的です．

二項分布の正規近似について少し具体的に述べます．
まず，二項分布 $\mathrm{Bin}(n,p)$ に従う確率変数 $X$ を考えます．
$n$ を大きくすると，近似的に $X$ は正規分布 $\mathrm{N}(np, np(1-p))$ に従うというものです．
※ $\mathrm{Bin}(n,p)$ に従う確率変数の平均は $np$, 分散は $np(1-p)$．
これは中心極限定理の特殊な場合とみなせます（詳しくは https://hsugaku.com/18-20 がわかりやすかったです）．

# 本当に二項分布が正規分布に近づくか確かめる

二項分布で $n$ を変えて分布のヒストグラムを描き，正規分布に近づくか確かめます．
$n$ は変えますが，$p$ は0.5で固定しています．

`stats.binom` の `rvs()` という関数を使うことで，二項分布からのサンプリングを行います．
その結果を用いて，二項分布のヒストグラムを描画します．
このヒストグラムを，正規分布 $\mathrm{N}(np, np(1-p))$ の確率密度関数と重ねて描画し，見比べます．

以下にコードを示します（Jupyter Lab 上で動かしました）．
まず必要なライブラリをインポートします．

```Python:ライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set()
from scipy import stats
```

次にプロット用のコードです．
二項分布 $\mathrm{Bin}(n,p)$ から 100000 回サンプリングを行い，その結果をヒストグラムで描画します．
また，正規分布 $\mathrm{N}(np, np(1-p))$ の確率密度関数を描画して，比較します．
これを各 $n$ について繰り返し，最後にまとめてプロットします．

コードに関する説明
- 二項分布のヒストグラムは `plt.hist()` を使って描画します．このとき `density=True` を渡すことで度数の合計が1になるように正規化します．これにより，正規分布の確率密度関数と見比べることができます．
- 正規分布の確率密度関数を描画するためには横軸の値（正規分布に従う確率変数の実現値）を与える必要があります．これらの値として，$x \in [np-2.58np(1-p),~~np+2.58np(1-p)]$ を満たす $x$ を 0.001 の間隔で生成しました（`np.arange()` を使用）．2.58という数字は正規分布の両側99%点からきています．

```Python
fig = plt.figure(figsize=(20, 12), dpi=200)
n_list = [1, 5, 10, 50, 100, 1000, 5000, 10000]
p = 0.5

for i, n in enumerate(n_list):
    ax = fig.add_subplot(2, 4, i+1)
    plt.title(f'$n={n}$, $p={p}$')
    # 二項分布からサンプリング
    binom_vals = stats.binom.rvs(n=n, p=p, size=100000)
    # 二項分布の平均と分散
    mu = n*p
    var = n*p*(1-p)
    # 二項分布のヒストグラムを描画
    plt.hist(binom_vals, bins=30, label='binom', alpha=0.4, density=True)
    # 正規分布のpdfを描画
    x = np.arange(mu-2.58*var**0.5, mu+2.58*var**0.5, 0.001) # 99%点まで描画する
    norm_vals = stats.norm.pdf(x, loc=mu, scale=var**0.5) # pdfの値
    plt.plot(x, norm_vals, label='norm')
    plt.legend()
# 余白を調整して保存
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.95)
plt.savefig('binom_norm.png')
```

上のコードで保存される `binom_norm.png` は以下のような画像になりました．
青色が二項分布，オレンジ色が正規分布です．

![binom_norm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462721/622e221b-099c-f002-5019-b5bdf9ab4b16.png)


$n=1, 5, 10$ あたりでは正規分布になっている感じはありませんが，$n=50$ あたりからだいぶ正規分布に近づいているのがわかります．
$n$が 1000 以上になると二項分布と正規分布のヒストグラムはほぼ一致しているのがわかります．
Data Integration Specialist

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)


# 資料

+ [Data Integration Specialist](https://trailhead.salesforce.com/ja/content/learn/superbadges/superbadge_integration)
+ [Data Integration Specialist 日本語訳](https://fukadadenki.quip.com/RGRzAonvoKpr/Data-Integration-Specialist-)

# Challenge 6

The 'ProjectRESTService' Apex REST service does not appear to be working properly.
Calling the service either didn't update the opportunity correctly, return the string 'OK', create an associated project correctly or function correctly in general.

[How Salesforce expect to call the Rest API in Data Integration Specialist Superbadge](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FT0Xy)
【Excelアドイン】再計算用のボタンを追加してみる

ボタンを追加し、Sharperlight数式とバインディングすることで、フィルター値変更に伴う自動再計算機能を停止します。
ボタンをクリックして再計算を行えるようにします。
## ボタンの追加
セル$\color{Blue}{\rm E2}$を選択し、Sharperlightリボンから”ボタン”->"既定のボタン"を選択します。
![Qiita 2022-02-26 Figure 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3bb5f618-ee19-dc08-2eef-0dbdb9a5aa4e.png)
ボタンがセル$\color{Blue}{\rm E2}$を起点に追加されます。キャプションを”更新”に変更し、ボタンのサイズも変更します。
ボタンの名前を$\color{Red}{\rm TableRefresh}$とします。
![Qiita 2022-02-26 Figure 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/5d1c065a-3589-911f-650f-d8aca39c0edd.png)
## Sharperlight数式とボタンのバインディング
適当なセル上で右クリックメニューを表示し、”Sharperlight XL”->”ボタン/テーブルバインドを編集”を選択します。
![Qiita 2022-02-26 Figure 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cca3035d-dcda-e4b5-a958-5870776e003e.png)
”Button Table Binding”ダイアログが表示されます。（日本語化がまだですね。:bow_tone1:）

+ ボタンの名前 $\color{Red}{\rm TableRefresh}$
+ クエリの名前 $\color{Red}{\rm Sales}$
+ アンカーセル $\color{Red}{\rm $C$5}$
+ テーブルの名前 $\color{Red}{\rm Sales}$　
+ パラメータ01 $\color{Red}{\rm =$C$2}$
+ パラメータ02 $\color{Red}{\rm =$D$2}$

このように入力しOKをクリックします。これで完了です。
![Qiita 2022-02-26 Figure 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a49bfeb3-5575-dc18-b313-aaffd77bdcd4.png)
ボタンが機能するか確認してみましょう。テーブルの真ん中あたりの値を削除します。
![Qiita 2022-02-26 Figure 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/577ce83d-3228-f20e-3d70-993b816ddf93.png)
ボタンを押します。テーブルが再計算されて値が再表示されます。
これでボタンと数式のバインディングが完了し、正常に動作することを確認できました。
![Qiita 2022-02-26 Figure 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d06ce571-f72a-6566-4ac2-160849296e07.png)
バインディングが完了するとアンカーセルに存在する数式は不要になるので、アンカーセルの数式を削除します。
![Qiita 2022-02-26 Figure 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a8b4b437-e1d7-9b2b-73f9-572a85d5a785.png)
削除後。
![Qiita 2022-02-26 Figure 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3f996ad3-bf64-b603-337e-cc3e167dbc5d.png)
数式は、セルから削除されてもワークブックに保存されているので大丈夫です。
Sharperlightリボンの”クエリ”グループの”マネージャー”からいつでも閲覧および編集を行うことができます。
![Qiita 2022-02-26 Figure 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/140d2016-7fd0-84ba-ee26-14a4eb618dbd.png)


:postbox:[お問い合わせ](https://sharperlight.jp/about-us/contact-us/)
Pythonでfirestoreライブラリがインポートできない...(VSCode)

# 原因
VSCodeのインタプリタ設定が誤っていました。
# 事象
launch.jsonおよびsettings.jsonの設定でパスは通っているはずなのに、「from firebase_admin import firestore」で下記エラーが発生・・・なぜ？
```
例外が発生しました: ImportError
Failed to import the Cloud Firestore library for Python. Make sure to install the "google-cloud-firestore" module.
```
※コマンドラインからは実行可能だけど、VSCodeでデバッグ実行しようとするとエラー。VSCodeの設定がどこかおかしい！

# 対応
①コマンドパレットを開いて「インタープリターを選択」
windowsの場合、Ctrl+Shift+P で開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364867/e457ebec-5553-bbe5-95c8-b56e8218adee.png)
バージョンが違っていました↓（インストールしたPythonは3.10だった）。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364867/554c86fa-fbc6-8347-7cc5-ee71f1338890.png)
ので、3.10を選択して解決。

# 反省
VSCodeインストール時に確認すればよかった。。
https://python.softmoco.com/devenv/how-to-setup-vs-code-for-python.php#2
OSSがDocsに使ってるツール一覧

# OSSがDocsに使ってるツール一覧
とりあえず、よく見るところだけ書いた(適宜更新予定)

## [Hugo](https://gohugo.io/)

- https://kubernetes.io/
- https://istio.io/
- https://etcd.io/
- https://prometheus-operator.dev/
- https://www.kubeflow.org/
- https://skaffold.dev/
- https://github.com/kiali/kiali.io
- https://thanos.io/
- https://keda.sh/
- https://vitess.io/
- https://tekton.dev/


## [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)

- https://kserve.github.io/
- https://knative.dev/docs/
- https://argo-cd.readthedocs.io/
- https://riverml.xyz/latest/
- https://doc.traefik.io/traefik/
- https://external-secrets.io/
- https://www.conftest.dev/

## [Gitbook](https://www.gitbook.com/)

- https://quii.gitbook.io/learn-go-with-tests/
- https://docs.feast.dev/

## [mdbook](https://rust-lang.github.io/mdBook/)

- https://book.kubebuilder.io/
- https://metacontroller.github.io/metacontroller/

# 言葉

- Static Site Generator (SSG)
    - データやテンプレートから静的HTMLウェブサイトを生成するツール。
    - 毎回同じものを返すものに使われ、prebuildしたものを使うことで、ロードが早い。
- [JAMstack](https://jamstack.org/)
    - JAMstack (JAM: "JavaScript, APIs, Markup")は、効率的に軽くて、早いウェブアプリケーションを作成する方法。SSGもこれに入る。
-  [Content Management Systems (CMS)](https://en.wikipedia.org/wiki/Content_management_system)
    - SSGに対応するCMSは、サーバー側で、リクエストに対応するデータとテンプレートからHTMLを生成するタイプ。毎回のリクエストによって表示する内容を変える必要があるウェブサービスはこちらを用いる。毎回サーバー側での処理（例. データベースにアクセス）が必要なので、毎回生成してフロントへ返して上げる必要あり。

# 比較&感想
1. シンプルにやるならmkdocsが楽そう
1. mdBookの[Preprocessor](https://rust-lang.github.io/mdBook/for_developers/preprocessors.html)は便利そう (例. [suite_test.go](https://github.com/kubernetes-sigs/kubebuilder/blob/da74a5113c983cca962f9672dc8b953ed1574be8/docs/book/src/cronjob-tutorial/testdata/project/controllers/suite_test.go) -> [Writing controller tests](https://book.kubebuilder.io/cronjob-tutorial/writing-tests.html))

# 参考
- https://www.cloudflare.com/learning/performance/static-site-generator/
- https://jamstack.org/
- https://gohugo.io/
- https://rust-lang.github.io/mdBook/
- https://www.mkdocs.org/
- https://squidfunk.github.io/mkdocs-material/
- https://www.gitbook.com/
export * fromとは何なのか

## はじめに

ある時こんなファイルを見て「？？？」となったので調べてみた。

```js:index.ts
export * from '...略'
export * from '...略'
```

## 結論

様々なモジュールから様々なエクスポートを集約した１つのモジュールを作成しているということらしい。
つまり集約元として動作するのみのモジュールということ。

例えば以下のようなコンポーネントがあるとする

```jsx:src/components/Layout/Header.tsx
export const Header = () => {
 return <header>ヘッダー</header>
}
```

```jsx:src/components/Layout/Footer.tsx
export const Footer = () => {
 return <footer>フッター</footer>
}
```

上記のコンポーネントを集約したモジュールを作成する

```js:src/components/Layout/index.ts
export * from './Header'
export * from './Footer'
```

コンポーネントを読み込むときは集約したモジュールから読み込むだけ
importの記述がスッキリする！

```jsx:src/pages/index.tsx
// スッキリ爽快
import { Header, Footer } from '@/components/Layout'

export const Top = () => {
  return (
    <>
      <Header />
      <h1>TOP</h1>
      <Footer />
    </>
  )
}
```

以上！！

## 何がうれしいのか

モジュールを集約しなかった時の場合importの記述が煩雑になる
コンポーネントが増えてくるとより恩恵を受けられそう。

```jsx:src/pages/index.tsx
// モジュールを集約しなかったときの場合
import { Header } from '@/components/Layout/Header'
import { Footer } from '@/components/Layout/Footer'

export const Top = () => {
  return (
    <>
      <Header />
      <h1>TOP</h1>
      <Footer />
    </>
  )
}
```

## 注意点

`export * from ...`は名前付きエクスポートのみ有効になる

以下はバッドパターン

```jsx:src/components/Layout/Header.tsx
const Header = () => {
 return <header>ヘッダー</header>
}

export default Header
```

```js:index.ts
export * from './Header' // エラー。再エクスポートできない。
```

## Tree Shaking 的にどうなん？

`Tree Shaking`と`re-export`に関してこちらの記事を拝見しました。

https://zenn.dev/uttk/articles/re-export-tree-shaking

結論、Reactを書く上ではあまり気にしなくてもいいかなぁといった印象を持ちました。

このあたりまだフワッっとしているのでアンチパターンなどあったら教えて頂きたいです。

```jsx
import React from 'react'

import { Header } from '@/components/common'

import { Top } from './Top'

export const TopPage = () => {
  return (
    <>
      <Header />
      {toggle && <Top />}
      {/* <Footer /> */}
    </>
  )
}
```
 
↑FooterをコメントアウトしてみたけどbuildしたJSには含まれてなかった👍

```jsx
import React from 'react'

console.log('フッター') // <-buildに含まれる

export const Footer = () => {
  return <footer>Footer</footer>
}
```

ただし、↑のようにグローバルに定義したものはbuildに含まれてしまうので注意。
グローバルに書かなければ問題なさそう。 

### 2022/3/19 追記

```jsx
import XXX from '何かしらのライブラリ'

export const Footer = () => {
 return <footer>フッター</footer>
}
```

上記のような場合でこのFooterコンポーネントがどこでも使われておらず、集約モジュールに入っている場合は、このimportしたモジュールも読み込まれてファイルサイズが大きくなるでのは？とご指摘いただいた。

確かに！
試してみないと何とも言えないところですが、使われていない変数や関数はbuild時に削ぎ落とされるので、そこまで気にする必要はないのかなと思いました。

モジュールをimportするだけで関数が勝手に実行されるライブラリだと怖いですけどね（そんなのある？）


## 参考資料
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export

https://jsprimer.net/basic/module/#re-export
マイクロ秒(μs)を変数名としてどう表すか

マイクロ秒を変数名のsuffixにつけるときに命名に迷ったのでメモ。
結論としては、_usでいいかなと。

microsecondsなので略すとmsでミリ秒と被ってしまう。
μsはギリシャ文字なのでASCII文字で表したいため使えない。

候補
_ms
_micros
_micro_seconds
_mus
_us

- _ms
ミリ秒と被るのでなし
- _micros
- _micro_seconds
状況に置いては採用もあり。ただsuffixにこんなに文字数は使いたくないので基本なし。
- _mus
μを"mew" (/mju/)と発音するため。普通にあり。
- _us
μとuは別ものなので怒られそうな気もするけど、システムコールでもusleepとか使ってるしこれでいいかも。


reference
なんか議論してるやつ、参考にはしてない
https://forum.wordreference.com/threads/ms-milliseconds-and-microseconds.289143/
GutHubにプログラムをあげてみました。

GutHub　URL

https://github.com/murase124?tab=repositories


GutHubにプログラムをあげてみました。

GitHub Extension for Visual Studioを使いました。

GutHubに投稿される範囲はVisual Studioの新しいプロジェクトの作成で作成されるファイル内のすべてが対象です。

表示メニューの横に　Gitメニューが増えている。
Gitメニュー内のGitリポジトリ作成で新しくGitHubに投稿できる。

更新はGitメニューのコミットまたは一時退避を開き、
コミットした後プルをすることにより、更新されます。

---
C#
TODOlist　作成途中　記事更新2022/02/28
ToDoリスト
納品日と200文字のテキストを入力できる。
oracleデータベースを使用。

---
C+言語
Phone_book 一時作成完了　記事更新2022/02/28
電話帳
名前と電話番号を登録できる。

---
C+言語
edit_a_picture 作成途中　記事更新2022/02/28
画像編集ソフト
サイズ変更
文字、線、多角形を描画可能

---
FlutterのビルドErrorでまず疑うのは、各パッケージの更新

Flutter開発を行っていく上で、パッケージが常にversionが新しいものに変わって行くため、思いもよらぬエラーに見舞われることがあります。そんな時はまず、アップデートが必要なものがないか旧式のパッケージを確認します。
```terminal
dart pub outdated
```
これを実行することで、アップデートが必要なパッケージがコンソールにずらりと流れてきます。全ての`pubspec.yaml`ファイルを編集して、`dart pub upgrade`を実行するのは手間なので、
```tarminal
dart pub upgrade --major-versions
```
で、ある程度更新されると思います。`pub outdated`で
```
Current：    現在使っているversion
Upgradable： アップグレード可能な安定version
Resolvable： 現在使用中の他のパッケージとの相性を考慮しアップグレード可能なversion
Latest：     最新版
```
`Resolvable`に記載されている値に手動で変更し直して、
```
flutter pub get
```
するとおおかた最新版に更新されます。それでも更新されない場合は、そのパッケージは整合的に互換性があるものと判断されます。
pythonでプロットしてみる#2

前回pythonでptsファイルの中身をプロットしてみた
ちゃんと指定した点の形でプロットできたことを確認したが、、ここで問題発生！
実際に取得している点群とプロットした形が違うことが分かった
以下のコードで画像の保存が可能
```main.py
import math
import matplotlib.pyplot as plt
fig = plt.figure()
for i in range(len(list_float_sorted)):
    for ii in range(1):
        plt.plot(float(list_float_sorted[i][ii]),float(list_float_sorted[i][ii+1]),marker='*')
plt.xlim(0,math.ceil(float(max(x_list))))
plt.ylim(0,math.ceil(float(max(y_list))))
plt.title('Title',fontsize=15)
plt.xlabel('X',fontsize=10)
plt.ylabel('Y',fontsize=10)
fig.savefig('plot.jpg')
```
# 保存したプロット画像
![plot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1496349/3df674ed-c873-056c-baac-1f6382b6cb23.jpeg)
# 取得した点群情報
![messageImage_1646011436918.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1496349/2b08be53-bfdf-336f-cd2f-e5e1860fb382.jpeg)
使用したアプリケーションはframe_grabberというもの
プロットしたものが点群の一部にないことが分かる
# 課題
点群情報を保存したptsファイルが何を意味しているのかを調べる必要がある
スケジュール実行の時は必ずタイムゾーンを設定し、開始時刻の末尾を注意すること

Power Automate のスケジュールフローについて、「タイムゾーン」や「開始時刻」の末尾の設定を正確に指定しないと意図していないタイミングでフローが実行される可能性があります。
今回実際に検証を行ったので3つのフローを比較した結果を記録します。

# 【比較検証】3つのフローとも毎日15:00に通知がくるように「開始時刻」を設定
- 設定の違いは「タイムゾーン」の指定、**「開始時刻」の末尾に"Z"がついているか否か**です。
- 実行結果は15：00に開始されたフローは１つのみでした。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/f5582f63-892c-97cb-85da-d694b2db9f7e.png)

下記のフローは正しい実行結果のフローとその実行履歴です。

👇「タイムゾーン」は日本、開始時刻末尾に**Zがついてない**フロー👇
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/ce1f41ec-0645-97a5-a48a-5efe653c3e12.png)
![タイムゾーンは日本、開始時刻はZついてない履歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/9fa26462-a8d1-3c39-bcfe-c9c439224810.png)

## 😢意図していない実行結果
一方、下記2つのフローは意図していないタイミングで実行されたフローとその履歴です。
    
👇「タイムゾーン」の指定はなし、開始時刻末尾に**Zがついている**フロー👇
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/3422dbf2-7e32-67d1-7f9d-9930ce466a06.png)
![タイムゾーンなし、開始時刻はZついてる履歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/932d9f8d-e960-8d23-90d0-a89a236c2c57.png)

👇「タイムゾーン」は日本、開始時刻末尾に**Zがついている**フロー👇
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/760a7955-dcb0-1a75-a702-9907360aaa2d.png)
![タイムゾーンは日本、開始時刻はZついている履歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2218676/49ae0aed-edd2-63a0-ab30-339c2235704e.png)

## 開始時刻末尾の"Z"は消す！
意図していない実行結果となった原因は、**開始時刻末尾に"Z"がついているため**。

::: note info
 "Z"がついたことで日本時間の15：00ではなく世界標準時間の15：00(日本時間と +9H の差)に実行されてしまいました。
:::

https://support.microsoft.com/ja-jp/topic/microsoft-power-%E3%82%AA%E3%83%BC%E3%83%88%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%E3%81%AE%E5%A4%89%E6%8F%9B-8bce2441-1859-4d76-2f51-985d9c96534d
>Datetime は、さまざまな形式になっている場合があります。
**Datetime の末尾に "Z" がある場合は、UTC 時刻であることを意味します。**
 次に例を示します。 2020-04-10T01:28:14.0406387Z

>Datetime 形式の詳細については、[「標準の日付と時刻の書式設定文字列」](https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-date-and-time-format-strings)を参照してください。
【Rails】enumとransackを使って複数条件での検索を実装する

# 環境
Ruby 3.0.0
Rails 6.1.4.4
ransack 2.5.0
enum_help 


# 何ができるようになるか

![スクリーンショット 2022-02-28 9.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110285/c574573d-edb0-1d28-d8cd-5854327116ea.png)

上記の画像のようにタスクをタスク名とステータスからAND検索できるようになる。
また、ステータスはenumを使って表現できるようになる。

# 手順
## ①enumを導入する
ここでは、name(タスク名)を持つTaskモデルにstatus(タスクのステータス)カラムを追加します。
今回は、Taskモデルに`未着手`、`着手中`、`完了`の3つのステータスを持たせることにします。
その場合、statusにそのまま文字列で保存するやり方もあるのですが、それだと効率が悪いためActiveRecordの機能である`enum`を使用して、それぞれのstatusに数値を与えることとします。

```ruby
not_started_yet: 0,
under_start: 1,
completion: 2
```

まずはmigrarionファイルの作成です。

```
% rails g migration AddStatusToTasks status:integer
```

statusは数値を保存するため、`integer`型とします。

カラムを追加したら、enumクラスメソッドにカラム名、対応する値を定義します。

```ruby:app/models/task.rb
class Task < ApplicationRecord
(略)
  enum status: {
    not_started_yet: 0,
    under_start: 1,
    completion: 2
  }
end
```

これで、enumの設定は完了です。

## ②enumの日本語化
次に先ほど定義したシンボルを日本語化します。
日本語化には、`enum_help`というgemが便利です。

```
gem 'enum_help' をGemfileに追加
% bundle install
```

gemをインストールしたら、locales/ja.ymlに日本語訳を記述していきます。

```yaml:locales/ja.yml
ja:
  enums:
    task:
      status:
        not_started_yet: "未着手"
        under_start: "着手中"
        completion: "完了"
```

参考: https://github.com/zmbacker/enum_help

## ③ransackを使って検索機能の実装
ransackを使うことで検索機能を簡単に実装することができます。

```
gem 'ransack' をGemfileに追記
% bundle install
```

先にコントローラの完成形を記します。

```ruby:app/controllers/tasks_controller.rb
class TasksController < ApplicationController
  before_action :set_q, only: [:index, :search]

  def index
    @statuses = Task.statuses_i18n
  end

  def search
    @tasks = @q.result(distinct: true)
  end

  private

  def set_q
    @q = Task.ransack(params[:q])
  end
end
```

ここでは、`set_q`アクションで送られてきたパラメータを元にransackがデータの検索を行います。
そのデータが`search`アクションにてActiveRecord形式に変換され、`@tasks`に格納されます。

次にviewを記します。

```ruby:app/views/tasks/index.html.erb
<%= search_form_for @q, url: search_tasks_path do |f| %>

<%= f.label :name_cont %>
<%= f.search_field :name_cont %>

<% @statuses.each do |status| %>
<%= f.check_box :status_eq_any, { multiple: true, include_hidden: false }, status[0] %>
<%= f.label status[1] %>
<% end %>

<%= f.submit %>
<% end %>
```

ここでのポイントは検索条件の指定方法です。
何やら`name_cont`や`status_eq_any`のようにカラム名に続く文字が存在しています。
これは検索条件を表しており、
contだと`〜の文字列を含む`
eq_anyだと`完全一致した一つ以上のパラメータ`
という意味を持ちます。

参考: https://github.com/activerecord-hackery/ransack#search-matchers

# まとめ
gemを使うことで、簡単に検索機能を実装することができました。
オブジェクトとは

# 概要
よくオブジェクトやオブジェクト指向型などよく聞きますが、自分の中で理解できていなかったので、基本的な事をまとめていきます。


# オブジェクトとは
オブジェクトはクラスとかインスタンスのことを指します。


- クラスとは
属性（固有のデータ）と操作（メソッド）を定義したもので、設計図のようなものです。例えば、家を作るときの設計図と考えると分かりやすいと思います。


- インスタンスとは
クラス（設計図）から実際に作り出したものをインスタンスと言います。


例えば腕時計を作りたいとします。まずどんなものを作るか頭の中で決め、設計図を作ります。その設計図を元に腕時計を作ります。この話における設計図がクラスで、実際に出来上がった腕時計がインスタンスです。そして、設計図と腕時計がオブジェクトです。


ここで混乱しやすいのですが、クラスだけでもオブジェクトと呼ぶことがありますし、インスタンスだけでもオブジェクトと呼びます。またクラスとインスタンスを合わせてオブジェクトと呼ぶこともあります。オブジェクトは結構ざっくりしているので、そのときの文脈によって変わります。

# 最後に
結構ざっくりしていますが何となく理解するにはちょうどいいかなと思います。


[参照サイト：「分かりそう」で「わからない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word1898.html)

[参照サイト：IT用語辞典　e-Words](https://e-words.jp/w/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88.html)
Storybookのキャッシュ削除

# 解決したいこと
* storybookのキャッシュを削除したい


# 背景
* storybookのビルドで以下の警告が出ため対処したが、確認でstorybookのキャッシュにより再現されなかった

```
node_modules/xxxxx Though the "loose" option was set to "false" in your @babel/preset-env config, it will not be used for @babel/plugin-proposal-private-property-in-object since the "loose" mode option was set to "true" for @babel/plugin-proposal-private-methods.
The "loose" option must be the same for @babel/plugin-proposal-class-properties, @babel/plugin-proposal-private-methods and @babel/plugin-proposal-private-property-in-object (when they are enabled): you can silence this warning by explicitly adding
 ["@babel/plugin-proposal-private-property-in-object", { "loose": true }]

```

# 方法
```sh
rm -rf node_modules/.cache/storybook
```

# 参考
https://github.com/storybookjs/storybook/issues/13200#issuecomment-759180590


# その他
* 検索してもすぐに回答にたどりつけなかったので投稿することにしました。


いつもQiitaにはお世話になってます。
FreeBSDでUVCカメラ


AcerのノートについているUVCなWEBCAMを試してみました。

こちらのSAITOU Toshihideさんのコードを使わせてもらいます。

https://lists.freebsd.org/pipermail/freebsd-users-jp/2014-September/000276.html

uvc_device_listに以下を追加します。

```
        /* XPA9S1JG8 1.3M WebCam */
        { 0x0402, 0x9665, 0, 1, 1,  0, 0x81, 1, 0x0400, 0x0100 },
```

コンパイルして実行してみます。640x480(1)では動かなくて、320x240(2)では動きました。

```
% sudo ./ex41 2 test
1: 640x480
2: 320x240
XferType: 1
dwMaxPayloadTransferSize: 00000400
153600
1
153600
2
153600
3
153600
4
153600
5
153600
6
153600
7
153600
8
153600
9
153600
10
153600
11
^Ctime lapse: 989651
fps: 11
% sudo cat test | ffmpeg -f rawvideo -pix_fmt yuyv422 -s 320x240 -i - tmp.avi
```

このWEBCAMにはbFrameIndexは1から4まであるのですが2だけが使えるようです。

Windowsにtmp.aviをコピーして再生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/c743a8cd-4ed5-bb72-f0af-310c77a87339.png)

640x480が処理できないのはdwMaxPayloadTransferSizeが関係しているようです。SAITOUさんのコードはMINの0x400(1Kbyte)で処理しているのですが、これだと320x240しか送れないみたいです。大きくすると640x480のEOFが拾えるようになるのですが、データがかけてしまいます。他のパラメータの調整も必要なのだと思われます。

640x480といってもyuyv422が1ピクセル16bitで5Mbit/frameくらいで、秒間30フレームだと150Mbit/secになり結構な量です。

dwMaxPayloadTransferSize(22-25)とFrame interval(4-7)をMINの二倍にしたら640x480でもキャプチャできました。Frame intervalは三倍にすると効かなくなるようなので、設定できる値に制限があるようです。

libuvcも試してみたのですが、まったくコールバックが呼ばれず、調べてみたら[転送のsubmit](https://github.com/libuvc/libuvc/blob/master/src/stream.c#L1240)のところでエラーになっていて動いていませんでした。デフォルトではエラーログも出さないし、クリーニングしてSUCCESSで返すし、DEBUGでビルドするとcore dumpするし、あまり品質のよくないプロジェクトみたいです。

ただ、どうもUVCなカメラはいろいろなようで、共通コードを作るのは結構大変で、いろいろ取り揃えて時間かけてやらないとダメそうな感じです。
[OutSystems]二次元配列相当の機能を実現する方法

質問箱にもらった質問から。
質問箱だと、テキストしか書けないので、実装方法をQiitaで。

# 質問
OutSystemsで二次元配列を実装する方法。
できれば可変長にしたい。

こういう形のデータを作りたいということ。
変数名[1][3]でアクセスすれば、15が得られる。

|  |  |  |  |
|:-:|:-:|:-:|:-:|
| 3  | 2  | 4  |   |
| 13  | 12  | 14  | 15  |
| 113  | 112  | 114  |   |

# 回答
ベストプラクティスとして確立はしていないと思うが、

1. ListをAttributeに持つStructureを定義する
2. 二次元配列相当のことを実現したい場所で、List of Structure (1で定義したもの）を作成する

とすれば、可変長で二次元のリスト構造を実現できる。
各要素へのアクセスは

```
変数名[i].要素名[j]
```

で可能。

## 実装例
### Structure定義
まずは、1のステップのStructureを作る。
Dataタブ > Structureを右クリック > Add Structure
で入れ物を作成。できたStructureを右クリック > Add Structure AttributeでStructureの属性を1つ作る。

この属性のData TypeでListを選択 > List各要素の型として希望の型を選択（以下の例ではText型を選択している）。
これで、リスト構造を持つStructureが定義できた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d80b579a-02d6-31b9-e579-e94d64554d81.png)

### List of Structure変数を定義
二次元配列を持たせたい場所（以下の例では、Reactive Web Appの画面）にLocal Variableを作成。
その型を↑で作ったStructureのListにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c9860626-df95-7747-c7e3-b2b54178c823.png)

これでこの変数には、2次元のデータを含めることができる。

### 1行追加するロジック
2次元配列の各次元をそれぞれ、行・列と呼ぶとして。
以下の例では、On Initializeで全データを登録しておく場合を示す。
行を追加するには、

1. ↑で作成したStructure型の変数（1つ前のスクリーンショットでは、TempArraySample）を用意する。
1. 必要に応じてTempArraySampleをクリアする（ListClear Action利用。行はいくつも追加するので2行目移行はこのステップが必要）
1. ListAppend　または　ListAppendAllでTempArraySampleの属性（例：TempArraySample.Texts）に任意の個数のデータを追加する
1. ListAppendで、List of StructureにTempArraySampleを追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9fc2847c-4ce9-1b08-a64c-008eae372891.png)

2行目でTempArraySampleに追加する部分（ListAppendAll2）のプロパティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c89f26f2-9050-8271-4696-e1fef5beaebd.png)

2行目でTempArraySampleを二次元配列相当の変数に追加する部分（ListAppend2）のプロパティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/dcb36c78-1f93-4a26-a56c-b85b8ffdafe3.png)

### 要素の値を取得する
2行目の4番目の要素にアクセスする場合は以下のように。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c3977790-95e8-2e25-b53d-2d9bf0e71f4b.png)

# 注意点
[1回のみ繰り返し、クエリに対するインデクサ（[ ]）の使用を避ける](https://success.outsystems.com/ja-jp/Documentation/Best_Practices/Performance_and_Monitoring/Performance_Best_Practices_-_Queries#1.E5.9B.9E.E3.81.AE.E3.81.BF.E7.B9.B0.E3.82.8A.E8.BF.94.E3.81.97.E3.80.81.E3.82.AF.E3.82.A8.E3.83.AA.E3.81.AB.E5.AF.BE.E3.81.99.E3.82.8B.E3.82.A4.E3.83.B3.E3.83.87.E3.82.AF.E3.82.B5.EF.BC.88.5B_.5D.EF.BC.89.E3.81.AE.E4.BD.BF.E7.94.A8.E3.82.92.E9.81.BF.E3.81.91.E3.82.8B)
というベストプラクティスがあるため、クエリの結果のListに対してはインデクサ（変数名[1]のようなアクセス）は注意を要する。
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost'で詰まったときの解消法

# 環境
MacBook Air (M1, 2020)
Laravel Installer 4.2.9

# エラー内容

```
SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' 
(using password: YES) (SQL: select * from information_schema.tables where table_schema = laravel_umarche and table_name = migrations and table_type = 'BASE TABLE')
```

SQLSTATE[HY000] [1045] とは
「.envファイルに記載されているデータベース名やユーザー名、パスワードが間違っている。」ということ。

# .envを修正

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=root
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
```

これが間違っていると違うエラーが出ます。
phpMyAdminでユーザを追加した際は、適当なDB_USERNAME・DB_PASSWORDを設定してください。

# これでもうまくいかない場合
.envもMAMPもphpMyAdminを見ても合っている・絶対間違ってないと思ったらこちらをターミナルで打ってください。

```
php artisan config:cache
```

投稿主もこのコマンドを打って、.env見直してを3時間やり続けたらできました。

# 終わりに
こんなエラーで数時間も悩まされるとは思いませんでしたが、無事解決できました。
もし同じエラーにあった人がいたら、ぜひ参考にしてください
【ためもく】アウトプットをしたいからオンラインもくもく会を開催してみた

先月息子が爆誕して絶賛親バカ中のだいちです。

今回は先日自分が主催したオンラインもくもく会
「ためもく」について
なぜ開催したのか、開催してどうだったのかなどのことについて
纏めていきます。

また、「ためもく」は第2回の開催も決定しております。
一人では勉強が続かない、勉強したのに身にならないなどある方は
是非ともご参加ください！
[ためもく！（第2回）](https://tamemoku.connpass.com/event/240954/)

## なぜ「ためもく」を開催したのか
結果を先に纏めると
### 強制的な勉強の場とアウトプットの場を自分が欲していた
要するに個人的な欲求を満たすために開催しました。
#### 強制的な勉強の場
一人でも勉強はできます。
だけど所詮は欲求の塊の自分なので
気がつけばアニメを見たり漫画を見たりなんてことはざらにあります。
それを少しでも矯正するためにもくもく会を開催して
勉強する時間を確保して自己成長に繋げようと考えました。
#### アウトプットの場
勉強はインプットしただけでは身につかないです。
これは樺沢紫苑さんの著書[「アウトプット大全」](https://amzn.to/3MhzuyC)に詳しく書かれてます。気になる方はぜひ読んでみてください。（ちなみに [オーディブル会員](https://amzn.to/3K0HYrP)は無料で聞くことができます。）
アウトプット大全の内容からどうにかアウトプットをしたいと思いもくもく会の最後に勉強したことを参加者全員に発表するという場を設けました。
こちらはまだ1回しか開催していないので身になっているかはまだ分かりませんが
他人に分かりやすく勉強したことを伝えるというのは
インプットしたことを整理してアウトプットすることでより理解が深まるので
ただただ勉強するだけよりは有益になると考えてます。

## 「ためもく」を開催してどうだったか
僕個人としては自分のやりたいことに集中できたのがよかったです。
また他の参加者が勉強したことを発表してもらい新たな知識を得る機会ができたのも
ためになって開催してよかった感じています。
他の参加者の方の感想ツイートです。

https://twitter.com/umino_mizu_/status/1494880879323217920

https://twitter.com/i_you0104/status/1494876058432143360

https://twitter.com/notosan_as/status/1494887491429548032

## まとめ
一人でも勉強はできます。
だけど一概にその勉強が身に付いているかはプログラミングであれば
実務で試されるのではないでしょうか？
ただ実務では勉強したことがそのまま使えるわけではないです。
使いたいと求めているユーザーに合わせて作られるコードは
勉強したことを応用して活かさないといけない。
そんな機会が生まれるのがためもくであって欲しいと思ってます。
ひとまずの目標は10回開催を目指します。
勉強したい方、アウトプットしたい方
是非ともご参加ください！
[ためもく！（第2回）](https://tamemoku.connpass.com/event/240954/)
Apple Silicon MacへParallelsの仮想マシンを移行する

## はじめに

MacBook Pro 2020（13-inch, Intel)から、MacBook Pro 2021（14-inch, M1 pro）に移行しました。Parallelsの仮想マシン(pvmファイル, windows 10）もうまく移行できました。

主な結論：

- VM（.pvm）はそのままは使えません
- VMを新たに作成し、プロダクトキーを入力し、デバイスの変更を申請することで、Windowsのライセンスも移行できました


## Intel MacでつかっていたVM（.pvm）はそのまま使えません

`.pvm`ファイルをコピーして起動すると、`起動できません`と言われます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/b6574ed3-3e91-c34d-ffd0-c0e03d69f3f3.png" width=50%>

cf. [Intel MacのParallels Desktopにある仮想マシンをApple silicon Macに移す](https://www.hiroakit.com/archives/2101?utm_source=rss&utm_medium=rss&utm_campaign=parallels-desktop%25e3%2581%25ae%25e4%25bb%25ae%25e6%2583%25b3%25e3%2583%259e%25e3%2582%25b7%25e3%2583%25b3%25e3%2582%2592%25e7%25a7%25bb%25e3%2581%2599)

`新規作成...`ボタンを押下し、仮想マシンを作ります。ユーザ体験はとてもスムーズで、10分ちょっと待っているだけで終わりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/56d4693b-41b5-ccc0-b13e-624ecdcfb5bc.png" width=50%>

## Windows 11のライセンス認証

まずはプロダクトキーを探します。[Windows 10のプロダクトキーを確認する方法](https://news.mynavi.jp/article/20210726-1930922/)を参考にしました。

```powershell
wmic path softwarelicensingservice get OA3xOriginalProductKey
```
は通らなかったので、`Windows Product Key View`をつかいました。

しかし、ライセンスキーを入力しても、認証が通りません。

<img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masatora_bd5/20220227/20220227095151.png" width=50%>

Microsoftの[Windows のライセンス認証エラーに関するヘルプ](https://support.microsoft.com/ja-jp/windows/windows-%E3%81%AE%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E8%AA%8D%E8%A8%BC%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E3%83%98%E3%83%AB%E3%83%97-09d8fb64-6768-4815-0c30-159fa7d89d85)を読んで、トラブルシューティングツールを利用し、`デバイスの変更`を申請します。

MicrosoftアカウントとWindowsのライセンスが紐づいているので、あたらしい仮想マシンにMicrosoftアカウントでログインし、ライセンスを紐づけることになります。まずここでは「現時点のWindowsへのログインパスワード」を求められます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/c0d5f7f1-833d-7ba7-09d0-56b4d254fe3e.png" width=50%>

:::note warn
注意
何も入力せず`次へ`を押します
Parallelsで新規作成し、パスワード設定していないためです
:::

認証するライセンスを選択します。

<img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masatora_bd5/20220227/20220227100239.png" width=50%>

<img src="https://cdn-ak.f.st-hatena.com/images/fotolife/m/masatora_bd5/20220227/20220227100523.png" width=50%>

次に起動した時、ログイン時にMicrosoftアカウントのパスワードを求められ、その後PINコードを設定するよう案内されます。ここのユーザ体験もスムーズでした。


## おわりに

Apple Silicon Macへの移行にあたっての一番の心配ごとはParallelsの仮想マシン移行でした。結果的には、「Windows側から見るとデバイスの構成変更」ということでスッキリしました。

ユーザ体験も全般的にスムーズで、「パスワードを入力せずに`次へ`を押す」ステップがいちばん緊張しました。

ついでながらWindowsも10から11になり、64bit化したのは棚からぼたもちでありがたい（11は64bitのみ）。これで[WLS](https://docs.microsoft.com/ja-jp/windows/wsl/)が使えるようになるので、ワクワクします。

### 環境

ここで書いていることは、下記のバージョンで実施しました。

- Windows 11 Home 21H2
- Parallels 17.1.1
- macOS Monterey 12.2.1
- MacBook Pro (14-inch, 2021)
- MacBook Pro (13-inch, 2020, Four Thunderbolt 3 Ports)

##
AIが文章の表現や文体をチェックしてくれるアプリを作った🤖

# はじめに
文章を分析してアドバイスをしてくれるAIアプリをリリースしました。今回はその機能と使用した技術についての記事になります。ダウンロードは画像もしくは[こちらのリンク](https://textcheckai.page.link/first)からどうぞ。ちなみに画像のキャラクターがAIの「ホメロス」です。

[<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713689/64d008e8-cd04-4dd0-5085-4908431c0957.gif">](https://textcheckai.page.link/first)

# ホメロスができること
![AI編集者が 文章チェック！のコピー-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713689/12432fe4-f6a5-7f9a-28d2-2d09bff59378.png)

## 文体分析
ユーザーが入力した文章を分析し、その文体を**5段階**で評価します。数字が大きいほど丁寧な文章であるということになり、例えばWikipediaの記事やニュースはレベル5と診断されます。

逆にレベルが低いものはくだけた表現ということになります。ブログ記事など、親しみが必要な文章は低いレベルで書くのがオススメです。広報のための公式アカウントなど、親しみやすさと丁寧さの両方が求められる場合にレベルを調節するという使い方もできます。

## 炎上対策
文体だけでなく、文中の表現も分析しています。いわゆる「炎上」につながるような過激なものが見つかった場合は注意を促すようにしています。SNSなど、投稿を行う前にチェックをしておくと思わぬトラブルを防ぐことが可能です。

また政治的な内容など、物議を醸すような文章に関してはより高いレベル、つまり丁寧な文章で書くように推奨します。正式な文体を使えば誤解されにくいためです。

## 表現の抽出
具体的にどんな言葉遣いや表現が検出されたか、という詳細を確認することができます。これで目的に応じた文体のレベルに書き換えることができます。論文や正式な書類を書くときに間違った言葉遣いをしていても修正できます、


# 技術的ポイント

## 言語モデルの課題
モバイルアプリへの言語モデルの導入として問題になるのは、**容量と処理**という２つの負担が大きいことです。特に後者は同じiPhoneでもどの機種でも機能するか、といったことにも気を配らなくてはなりません。

既存のWebにおけるAIサービスのように外部で処理を行えば以上の課題は解決されます。ただしこの場合、自分の文章がどこかに送信されてしまうことになります。機密性の高い文書はもちろんですが、プライベートな文章などはできるだけ安全性を確保したいものです。

結論として、ホメロスは処理を完全に内部だけで行うように設計しました。オフラインでも問題なく機能しますが一方でアプリ本体のサイズは記事執筆時点で**10MB以下**しかありません。これにはちょっとした工夫があります。

## NLPフレームワーク

iOSにおけるSwiftのフレームワークのひとつとして`NaturalLanguage`というものが存在します。これはその名の通り自然言語処理を行なってくれるものです。iOSに最初から組み込まれている機能を利用するため、これは容量と処理にほとんど負担を与えません。またiOS自体に依存しているため、機種の違いによる問題も起こりません。

その代わり、全ての機能が日本語に対応しているわけではなく万能ではありません。今回利用した文章のトークン化は日本語でも問題なく行うことができます。

```swift:TextCheck.swift
import NaturalLanguage

let text = "ホメロスは人工知能で文章を分析するアプリです"

func tokenize(text: String) {
    let tokenizer = NLTokenizer(unit: .word)
    tokenizer.string = text
    let tokens = tokenizer.tokens(for: text.startIndex ..< text.endIndex)
    var textTokens: [String] = []
    for token in tokens {
        let tokenStart = token.lowerBound
        let tokenEnd = token.upperBound
        let text = text[tokenStart ..< tokenEnd]
        textTokens.append(String(text))
    }
    print(textTokens)
}

tokenize(text: text)
```

実行結果は以下のようになります。精度としては十分なものかと思います。
```
["ホメロス", "は", "人工", "知能", "で", "文章", "を", "分析", "する", "アプリ", "です"]
```
これらの処理は内部で完結するので、外部のサーバーとやりとりする必要がないという利点もあります。このようにiOS内の言語モデルを活用することで課題を解決できるようになりました。

## SwiftUI
本アプリはそのほとんどをSwiftUIで構築しています。iOS15への変化もあり、UIKitに頼らなくてもできることがかなり増えてきました。またMac版の開発を視野に入れた上での導入でもあります。


# さいごに
[<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713689/8df9f287-25c9-eaa8-db91-7e9b4441825b.png">](https://textcheckai.page.link/first)
簡潔な説明だけにとどめたので開発のきっかけや経緯などは省略しています。もし興味を持ってくださるならばそういった内容は[note](https://note.com/izumo092)に投稿しているので、読んでいただけると嬉しいです。

このAIは記事執筆はもちろん、SNSの投稿の際にも役立ってくれます。いいなと思った方はシェア等していただけると幸いです。開発者としてさらによりよいものにしていくので、「ホメロス」をよろしくお願いします。
プロジェクトマネジメントに用いるプロジェクト憲章、Markdownテンプレート

プロジェクト憲章とは...
> プロジェクトを立ち上げる際に策定される、プロジェクトの目的や条件、内容などを明確に定義した文書。

https://e-words.jp/w/%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%86%B2%E7%AB%A0.html

ということでそれをMarkdownで書きたいときのためにテンプレートにしたものです。

## テンプレート

```md:テンプレート

## [プロジェクト名] タイトル
- プロジェクトリーダー
- プロジェクト名
- 作成日
- 作成者
- 承認者

## 背景と状況
（なぜこれをやることになったか？どんな問題が、誰にどのように影響しているのか？）

## プロジェクト内容
（何をするのか？どのプロセスが対象か？会社の方針との関係は？）

## プロジェクト範囲
（どのプロセス、どの地域が対象で、どれが対象外か？このプロセスの開始と終了地点は？制約条件は？）
### 範囲内
### 範囲外

## プロジェクト目標
（目的目標は何か？誰が最大の顧客か？誰がこのプロジェクトの成否を決めるのか？）

## 数値目標
（上記のプロジェクト目標の達成度を計る数値項目は何で、成功数値はいくらか？予算目標は？いつまでに？）

## プロジェクトチームメンバー

| 役割 | 名前 | 職位・所属等 |
|:--|:--|:--|
|   |   |   |
|   |   |   |
|   |   |   |


```

もう少しシンプルには以下。

```md:シンプルなテンプレート
## プロジェクトの目的
（このプロジェクトに取り組んでいる理由）

## プロジェクト目標
（プロジェクト終了までに、どのような成果物や資産を実現する予定か）

## プロジェクトスコープ
（プロジェクト成果物の対象範囲、プロジェクトに含まれていないイニシアチブ）

## プロジェクトチームおよびリソース
（誰がこのプロジェクトに取り組んでいるか。どのようなリソースが利用できるか）

## 関係者および承認者
（プロジェクトの関係者、承認者）
```



## 記載例 「夏休みの宿題」

### [プロジェクト名] タイトル

```md:テンプレート
### [プロジェクト名] 夏休みの宿題 集中突破

- プロジェクトリーダー: 磯野カツオ
- プロジェクト名: 夏休みの宿題 集中突破
- 作成日: 2022/08/20 
- 作成者: 磯野ワカメ
- 承認者: フグ田サザエ
```

### 背景と状況
（なぜこれをやることになったか？どんな問題が、誰にどのように影響しているのか？）

```md:テンプレート
### 背景と状況

- お盆まで存分に夏休みを満喫した。
- お盆が明けて波平に夏休みの宿題が未完であることを指摘された。
- 夏休み終了までまだ猶予のある現在のうちに、家族の助けを借りながら全力で宿題を集中突破するのが最も効率的である。

```

### プロジェクト内容
（何をするのか？どのプロセスが対象か？会社の方針との関係は？）

```md:テンプレート
- 課題は以下
    - 日記
    - アサガオの観察
    - 自由研究 
- 「家の手伝い」も提案されている。
```

### プロジェクト範囲
（どのプロセス、どの地域が対象で、どれが対象外か？このプロセスの開始と終了地点は？制約条件は？）

```md:テンプレート
### プロジェクト範囲
- 今回は学校から必達が言い渡されている以下に絞る。
    - 日記
    - アサガオの観察
    - 自由研究 

#### 範囲内

- 日記は絵日記という課題なので、絵も必要。
- アサガオの観察は、ワカメの日記を参考にできそう。
- 自由研究に最も時間がかかりそうである。

#### 範囲外
- 必達要件達成のため「手伝い」は今回は対象外

```

### プロジェクト目標
（目的目標は何か？誰が最大の顧客か？誰がこのプロジェクトの成否を決めるのか？）

```md:テンプレート
### プロジェクト目標

- 夏休み明け胸を張って宿題を持っていくこと
- 先生にできれば褒められること

```

### 数値目標
（上記のプロジェクト目標の達成度を計る数値項目は何で、成功数値はいくらか？予算目標は？いつまでに？）

```md:テンプレート
### 数値目標

- 日記、アサガオ に関しては、ページを埋める。
- 自由研究については、「家の手伝い」を実践し記録、新聞形式で公開することで一石二鳥に「おこづかい100円」を得られるのではという仮説が考えられる。

```


### プロジェクトチームメンバー

```md:テンプレート
| 役割 | 名前 | 職位・所属等 |
|:--|:--|:--|
| リーダー  | 磯野カツオ  | 本人  |
| 協力者  | 磯野ワカメ  | 妹  |
| 協力者 / 承認者  | フグ田サザエ  | 姉  |

```


## まとめ

https://dxcriteria.cto-a.org/236281cd94f54eb1b369f4d4123feeaf

> クライテリア
> インセプションデッキまたは **プロジェクト憲章** を作成し、チームの存在理由についてチーム全員が把握しているか。

というものがある。インセプションデッキに関しては以下など
[スクラムで使う「インセプションデッキ」のmarkdown形式版テンプレート - Qiita](https://qiita.com/bremen/items/ed491246ed83630bc84d)
[アジャイル初心者だけど、どうしてもインセプションデッキの素晴らしさを伝えたい話 - Qiita](https://qiita.com/bigchopstick-3412/items/47972d7ab8bce54b8fb5)
いずれも用途、場面に応じてつかいたいです。

### 参考

[プロジェクト憲章の書き方 (実例付) • Asana](https://asana.com/ja/resources/project-charter)
[プロジェクト憲章（チャーター）の書き方【エクセルテンプレート】　プロジェクトの企画書 | 業務改善＋ITコンサルティング、econoshift：マイク根上](https://econoshift.com/ja/project-charter-template/)

ということで以上サマリです。お役に立てばさいわいです。
macOS NAS SMB ファイル一覧が遅いのを解消


ほぼ個人的なメモ。
**macOS**で**NAS**が遅くて困っていたのを改善できた。 多分忘れるのでメモ。
# 症状
**SMB**で接続した**NAS**が劇的に遅い。 
Finderのみならず、lsコマンドなどでもファイル一覧の取得が劇的に遅い。
しかし、同じApple製品でも、iPhoneのファイルAppではストレスない速度でファイル一覧が得られる。
# 環境
MacBook Pro 2019
macOS Monterey 12.2.1
TP-link Archer AX50 の簡易NAS
# やったこと
ターミナルで下記コマンドを実行。その後、ログインし直す。
```ターミナルで実行
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE
```
# 解説
**.DS_Store**の読み込まなくなり、ファイル一覧の取得が早くなる。
動画ファイルも最初の読み込みが多少早くなった気がする。(感覚)
ただし、動画がカクカクするのは改善しない。それは無線LANが弱いからか...

詳しく本家のサポートページで。
https://support.apple.com/ja-jp/HT208209
2022/2/28主にITとかセキュリティの記事

3フェーズでクラウドコスト最適化をはじめる　FinOpsの具体的なアプローチを解説(2/25)
https://enterprisezine.jp/article/detail/15548

自宅の「ルーター」大丈夫？サイバー攻撃のリスク高く注意を(2/26)
https://www3.nhk.or.jp/news/html/20220226/k10013503071000.html

AP通信の「難民のビデオのNFT」に抗議殺到、販売中止に(2/25)
https://forbesjapan.com/articles/detail/46059

SWIFT排除でEU分断 対ロシア制裁、エネルギー懸念が影(2/26)
https://news.yahoo.co.jp/articles/e77efd79d476b266f592cc22035950a30143902f

ロシア、ＦＢ利用を制限　国営メディア「検閲」に対抗(2/26)
https://www.jiji.com/sp/article?k=2022022600431&g=int

App Storeで契約したサブスクリプションを解約する方法(2/24)
https://www.itmedia.co.jp/mobile/spv/2202/24/news056.html

欧州中銀「必要なあらゆる行動」用意　ロシア侵攻で(2/26)
https://www.nikkei.com/article/DGXZQOGR25EE80V20C22A2000000/

ロシアのウクライナ侵攻で暗号資産が暴落、OpenSeaでフィッシング詐欺──2/19～2/25のトップニュース(2/26)
https://m.finance.yahoo.co.jp/news/detail/20220226-00161416-coindesk-bus_all

ビットコインのライトニング・ネットワークとは何か？【基礎知識】(2/26)
https://m.finance.yahoo.co.jp/news/detail/20220226-00160715-coindesk-bus_all

PayPay、同社をかたるフィッシング詐欺に注意呼びかけ(2/26)
https://k-tai.watch.impress.co.jp/docs/news/1391162.html

ロシアのウクライナ侵攻に関する現地からのツイートを地図上に表示する「Russia-Ukraine Monitor Map」(2/25)
https://gigazine.net/news/20220225-russia-ukraine-monitor-map/

米半導体大手に不正侵入か　ロシアのサイバー攻撃警戒―英報道(2/26)
https://www.jiji.com/sp/article?k=2022022600306&g=int

ウクライナ軍、ベラルーシのハッカーの標的に＝当局(2/26)
https://jp.reuters.com/article/ukraine-crisis-cyber-idJPL4N2V0429

ロシア連邦政府、国内でのFacebook利用に制限　「国営メディアの投稿を制限したため」(2/26)
https://www.itmedia.co.jp/news/spv/2202/26/news043.html

3億円相当のビットコイン、1つのアドレスからウクライナ軍支援のNGOに寄付(2/26)
https://coinpost.jp/?p=324633

NVIDIAがサイバーセキュリティのインシデントを調査中、2日間デベロッパーツールとeメールがダウン(2/26)
https://jp.techcrunch.com/2022/02/26/2022-02-25-nvidia-cyber-incident/

サイバーセキュリティ月間スタート 対策強化と被害防止へ 官民連携で普及啓発を(2/27)
https://ab.jcci.or.jp/article/61815/

インターネットバンキングログオン時にサーバー接続できない事象について(2/25)
https://www.ryugin.co.jp/corporate/news/51838/

エヌビディアへのサイバー攻撃、ウクライナ情勢に無関係－関係者(2/26)
https://m.finance.yahoo.co.jp/news/detail/20220226-26564740-bloom_st-bus_all

Bitfuryがカナダにビットコインマイニング施設を設立(2/25)
https://nextmoney.jp/?p=48431
ArrayListをC言語で作ったよ


# はじめに
実は私はArrayListが何のことを指しているのかは知りません.
即興で作ってみただけ.

# vector

<details><summary>vector.h</summary><div>

```c
#ifndef VECTOR_H_
#define VECTOR_H_
#include <stdint.h>
#include <stdlib.h>

#define VECTOR_EXPAND (64U)
typedef struct vector_t
{
    void* context_;
} vector;

typedef struct vector_item_data_t
{
    size_t size_;
    void* data_;
} vector_item_data;

int create_vector(vector* x);
void destroy_vector(vector x);
int push_vector(vector x, size_t size, char* data);
void pop_vector(vector x);
vector_item_data get_vector(vector x, size_t index);

#endif //VECTOR_H_
```
</div></details>

<details><summary>vector.c</summary><div>

```c
#include "vector.h"
#include <assert.h>
#include <string.h>

typedef struct item_t
{
    void* data_;
    size_t size_;
} item;

typedef struct context_t
{
    size_t size_;
    size_t capacity_;
    item* items_;
} context;

static int expand_context(context* c)
{
    assert(NULL != c);
    size_t capacity = c->capacity_ + VECTOR_EXPAND;
    item* items = (item*)(malloc(sizeof(item)*capacity));
    if(NULL == items){
        return -1;
    }
    memcpy(items, c->items_, c->capacity_*sizeof(item));
    free(c->items_);
    c->capacity_ = capacity;
    c->items_ = items;
    return 0;
}

static void destroy_item(item x)
{
    free(x.data_);
}

int create_vector(vector* x)
{
    assert(NULL != x);
    x->context_ = malloc(sizeof(context));
    if(NULL == x->context_){
        return -1;
    }
    context* c = (context*)x->context_;
    c->size_ = 0;
    c->capacity_ = 0;
    c->items_ = NULL;
    return 0;
}

void destroy_vector(vector x)
{
    context* c = (context*)x.context_;
    for(size_t i=0; i<c->size_; ++i){
        destroy_item(c->items_[i]);
    }
    free(c->items_);
    free(c);
}

int push_vector(vector x, size_t size, char* data)
{
    context* c = (context*)x.context_;
    if(c->capacity_<=c->size_){
        if(0 != expand_context(c)){
            return -1;
        }
    }
    item* i = (item*)(&(c->items_[c->size_]));
    i->size_ = size;
    if(0<size){
        i->data_ = malloc(size);
        if(NULL == i->data_){
            return -1;
        }
        memcpy(i->data_, data, size);
    }else{
        i->data_ = NULL;
    }
    c->size_ += 1;
    return 0;
}

void pop_vector(vector x)
{
    context* c = (context*)x.context_;
    if(c->size_<=0){
        return;
    }
    item i = c->items_[c->size_-1];
    free(i.data_);
    c->size_ -= 1;
}

vector_item_data get_vector(vector x, size_t index)
{
    context* c = (context*)x.context_;
    assert(index<c->size_);
    vector_item_data data;
    data.size_ = c->items_[index].size_;
    data.data_ = c->items_[index].data_;
    return data;
}
```
</div></details>

# まとめ
べつになんとも
実行中のPodをデバッグするためにkubectl debugを調べてみた

# はじめに
kubernetesクラスター上で動作しているPodのデバッグ方法として`kubectl exec`を用いる方法があります。
ですがこのコマンドはデバッグ対象のPodのコンテナ上で実行するため、**`kubectl exec`ではコンテナにデバッグを行うための環境がなかった場合、デバッグが難しくなる問題** があります。
kubernetesではこのような問題を回避するために`kubectl debug pod`というコマンドがありますので紹介をしてみたいと思います。

# kubectl execとの違い
まず`kubetl exec`と`kubectl debug pod`との違いを簡単に説明したいと思います。

## kubectl execの仕組み
簡潔にまとめると、**Pod内のコンテナでコマンドを実行する動作** になります。
コンテナ内で使えるコマンドのみ使用することができます。

例としてimageに`nginx:latest`のコンテナが動作しているPodがあるとします。
このコンテナではnginxに関連するコマンド(例:`nginx -V`など)を使用することができますが、`ps`等のコマンドはインストールしなければ使用することができません。
なのでデバッグの際に`ps`を`kubectl exec`コマンドで見ようとしても見れないのです。
```
$ kubectl exec -n test-nginx -it test-nginx-b-78fbdc67f4-74c8v -- ps -aux
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ps": executable file not found in $PATH: unknown
command terminated with exit code 126
```

コンテナ内で使用できるコマンドであれば確認は可能です。
```
$ kubectl exec -n test-nginx -it test-nginx-b-78fbdc67f4-74c8v -- date   
Sun Feb 27 17:30:17 UTC 2022
```

## kubectl debug podの仕組み
では`kubectl debug pod`は何をするのかというと、**エフェメラルコンテナ**という**一時的に使用するコンテナを追加してシェルに入るコマンド** になります。

まず稼働中として、コンテナが一つ動いているPodがあるとします。
![pod](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/21ed67f3-6b43-7b9a-3dc5-0eefef4da9f6.png)

このコンテナの目的はアプリケーションを動かすことなので、アプリケーションの動作に関係ないコマンドはインストールされていません。

そのため`top`を使用したい！となった時にはコンテナ内のシェルに入り、`apt`等でtopコマンドをインストールする必要がありますが、
もしセキュリティの観点でPodが設定した外部と通信できない仕組みにしていたりなど、外部からコマンドをインストールすることができない場合があります。

このような問題の解決のために`kubectl debug pod`でエフェメラルコンテナを作成します。
![pod-ephemeral-container](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/271c2665-e256-64f0-fc56-1d7d7599fbef.png)

エフェメラルコンテナはこのように、特定のPod内にコンテナを追加します。
このようにすることで以下のような嬉しい点があります。
- アプリケーションのコンテナを汚さない
- busyboxなど、任意のimageを使用できる

特にbusyboxが使えるようになるのは嬉しいですね。

# kubectl debug podの使い方
まだ正式な機能ではないため、実際にクラスター上で使用するときには別途作業が必要になるので忘れないようにしましょう。
kubernetesの公式ドキュメントから引用ですが、このように使用します。
```
$ kubectl debug -it ephemeral-demo --image=busybox --target=ephemeral-demo
If you don't see a command prompt, try pressing enter.
/ #
```
このようにすることで、`ephemeral-demo`というpod内に`busybox`のコンテナを起動し、shellを呼び出すことができます。
`--container [コンテナ名]`を指定することでエフェメラルコンテナの名前を指定することができ、
`--target [コンテナ名]`を指定することで、プロセス名前空間を共有するコンテナを指定できます。
ここで気づくと思いますが、`kubectl debug pod`はエフェメラルコンテナの作成とシェルの実行なので、動作の一部に`kubectl exec`と同じことをおこなっていますね。

# まとめ
`kubectl debug pod`について調べてみました。
このコマンドはエフェメラルコンテナと呼ばれる一時的なコンテナを作成するものであり、
`kubectl debug pod`と`kubectl exec`との違いは、コマンドを呼び出す場所の違いでした。
`kubectl exec`は任意のPodのコンテナでコマンドを実行するようになっており↓
![pod-exec](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/92da69be-9e13-09cd-49c9-3367b3b4e650.png)

`kubectl debug pod`はエフェメラルコンテナの作成と、作成したコンテナでコマンドを実行するようになっていました。
![pod-exec-ephemeral-container](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212406/0cb1f915-f1d9-cb22-4fa6-43dfbeccb3b1.png)


最近ではコンテナのセキュリティ対策としてshellが実行できないようにする、といったようなこれまでのデバッグができなくなってしまう対策もありますが、
このようなデバッグの方法を覚えておくことで安心して対応して対応できますね。
[C#]フォルダが削除できないときの雑な対策

## 発生条件

一瞬の間にフォルダ作成とフォルダ削除を行おうとすると下記例外が発生した。

```
System.IO.IOException : The process cannot access the file
'ccc0.txt' because it is being used by another process.
```

## 解決方法

非同期でかつ遅延させて実行するとうまく行った。

```cs
Task.Run(async () =>
{
    await Task.Delay(500); // 500ms遅延
    Directory.Delete("aaa", true); // フォルダ削除
});
```

※遅延の秒数は適当。短いと失敗しやすい傾向にあったので、500[ms]に落ち着いた。コメント頂いてるように、真剣にやるときは遅延とリトライを繰り返す機構があるといい。

## 背景

xUnitでファイルをいじるロジックのテストを書く場面があり、テスト用ファイルの生成/削除をコンストラクタと`Dispose()`で行おうと思い立った。
とりあえずその部分の動作だけ確かめようとしたところ、冒頭の例外発生。

他のプロセスに使われているというメッセージだがそんなわけがない。多分、ファイル生成してすぐだから自分のプロセスのことなんだろう。

テストケース内にいくらか時間がかかる処理が書かれれば起きなくなるトラブルなんだろうけど、エラーメッセージと直接原因が噛み合わないケースなので情報共有。
Pythonでサーバーを立てて画像を表示する

# はじめに
家のハムスターの様子を外でも見たいので、まずはサーバーを作って画像を表示できるようにしようと思います。

# 環境
windows10
python3.9.4
google chrome


# サーバーの起動
適当なフォルダにindex.htmlとserver.py、表示したい画像を用意します。
```python:server.py
import http.server
import socketserver

PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

```

```html:index.html
<html>
<meta charset="utf-8">
<body>
<h1>ハムスター</h1>
<img src="あなたのハムスターの画像のパス.jpg"title="kinkuma" width="400" height="auto">
</body>
</html>


```
コマンドプロンプトを開いて作ったフォルダのあるディレクトリまで移動し、以下を入力します。
```
$ python server.py
```

成功していれば`serving at port 8000`と表示されます。
# 開いてみる
[http://localhost:8000/](http://localhost:8000/)にアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2424954/20c367c5-d14d-c2fe-0bb6-aebeb78f5989.png)
こんな感じで画像が表示されていると思います。

# 参考記事
[pythonでローカルwebサーバを立ち上げる](https://qiita.com/okhrn/items/4d3c74563154f191ba16)
COALESCEの引数に異なるデータ型を指定した場合の挙動

COALESCEが予想外の動きをしていたことで、とある調査に4時間程度かかったので
将来同じようなSQLに遭遇したときに3秒で解決するために＆いつかの誰かのために記録しておきます。

## 読み方（いつもわからなくなるので）
コウアレス。

## 使い方
`COALESCE（引数1,引数2,…）`
引数の数は任意で、引数の最初の非NULL値を返します。
以下では例として単純に2つの引数を指定した場合について書いています。
すなわち、引数1がNULLだったら引数2を返す、引数1がNULL以外だったら引数1を返す。

例1：引数1がNULLではない
```sql
SELECT COALESCE('0123', 'BBB') FROM DUAL

- - - - -
'0123'
```

例2：引数1がNULL
```sql
SELECT COALESCE(null, 'BBB') FROM DUAL

- - - - -
'BBB'
```

通常はリテラルだけを引数にする使い方はしません。
抽出対象のカラムを指定して、OracleでいうNVL、SQLServerでいうISNULLのような使い方をするのがほとんどかと思います。

## 気を付けるべき点
引数1と引数2は同じデータ型とするのが原則。
異なるデータ型を指定した場合、DBエンジンやバージョンによって挙動が異なる。

Teradataやsqliteの場合
```sql
SELECT COALESCE('0123', -1) 

- - - - -
'0123'
```

Db2 Warehouse on Cloudの場合
(バージョンを忘れてしまった…。Db2では再現しなかった)
```sql
SELECT COALESCE('AAA', -1) FROM SYSIBM.DUAL

→エラーになり参照できない
```

しかしSELECTではエラーになるがSELECT結果をINSERTするSQLでは失敗せず、
引数1がNULL以外の場合、引数2で指定したデータ型で引数1が返される。

```sql
INSERT INTO TABLE_1 (COL_1)
SELECT COALESCE('0123', -1) FROM SYSIBM.DUAL

SELECT * FROM TABLE_1

COL_1
- - - - -
123
```

引数2が数値のため'0123'が暗黙的に数値型にキャストされ、
その結果前ゼロが消失した数値123が返されていたということ。

引数1が文字列で引数2が数値という場合には上記のようなケースもありとくに注意が必要。

その他の製品や具体的なバージョンでの挙動の違いはわからないけど（ここでは整理しないけど）、
こういうことが起きるということを覚えているだけでも意味があると思うので、
忘れないようにしておこう。