OmniAICreator/Qiita-1.07M huggingface dataset:
MetabaseをDb2で使いたい

# はじめに
Metabaseはオープンソースのデータ可視化ツールです。SQLの実行結果をきれいなグラフにしてくれます。私はデータベースのパフォーマンス評価に使っています。ただし、**標準ではDb2をサポートしていないので工夫をする必要**があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/0b138204-b738-a061-e080-962a1532921c.png)
データベースのパフォーマンス情報を取得するSQLは以下の記事に記載しています。
[Db2:性能評価にSQL平均応答時間を用いる](https://qiita.com/tsunenorikan/items/6cf055daef790838c305 "Qiita")

# 内容
##### 話すこと

- MetabaseをDb2で使えるようにすること

##### 話さないこと

- Metabaseの概要
- Metabaseのhello,world的な使い方
- Docker Desktopの使い方

# 環境
ローカルPCのDocker上でMetabaseをインストールし、リモートにあるDb2サーバーに接続します。

- Windows 10
- Docker Desktop 4.2
- IBM Db2 V11.5 Linux

# インストール
### Docker Desktop

WSL2環境でDocker Desktopを動かします。公式からダウンロードしてセットアップしてください。

### Docker Compose

##### 設定ファイル
dockerのデフォルトフォルダーにdocker-compose.ymlを配置、以下のように編集します。

```yml:docker-compose.yml
version: "3"
services:

  metabase:
    image: metabase/metabase:latest
    container_name: metabase
    restart: unless-stopped
    environment:
      - JAVA_TOOL_OPTIONS=-Xmx2g
      - JAVA_TIMEZONE=Asia/Tokyo
    ports:
      - "3000:3000"
    volumes:
      - ./metabase/metabase.db:/metabase.db:cached
      - ./metabase/plugins/db2.metabase-driver.jar:/plugins/db2.metabase-driver.jar
```

##### Db2ドライバー

1. **db2.metabase-driver.jar**をダウンロード(https://github.com/alisonrafael/metabase-db2-driver)
1. dockerデフォルトフォルダーに**metabase/plugins**という名前でフォルダーを作成
1. jarファイルを作成したフォルダーに配置

##### コンテナ起動

デフォルトフォルダーから以下のコマンドで起動します。

```powershell:起動コマンド
docker-compose up -d
```

起動が完了したかは、tailコマンドで確認します。

```powershell:tailコマンド
docker-compose logs -f --tail=30 metabase
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/b330a790-9e93-8416-ac12-ef74627ebdfd.png)

# Metabaseの設定

### データソースの追加

1. http://localhost:3000/ にアクセスして、Metabaseにログオン
1. 設定→管理者→データベースからデータベースを追加
1. データベースのタイプをDb2にして、接続情報を登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/82e6bce4-f3df-00fd-aab4-ced3ce6fa1b2.png)

### コレクションの作成

右上の**SQLを書く**をクリック、Db2のデータベースを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/d5bcecb8-c5e0-1a16-5349-42690d5066ea.png)

SQLを記述して、実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/6e685e68-ec18-bd1e-6206-c37123689e61.png)

実行結果が表示されたら、ビジュアライゼーションでグラフ化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/5eb6f2f6-fccf-b1e2-bf97-e69c10029aaa.png)

実行結果のグラフ化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/5729c521-180d-37ae-7473-2214c6a01c24.png)

# おわりに
コレクションを保管しておくと、選ぶだけでSQLを実行、グラフにしてくれます。無料でここまでできるのはうれしい限りです。
Bot作成画面の起動方法【Automation Anywhere】　- はじめてのAA

#はじめに

Automation Anywhere の動作環境が整ったら、さっそくBotを作ってみましょう。

この記事では、Botの作成画面の起動方法を紹介します。

まだ動作環境が整っていない人は、以下の手順を参考にCommunity Editionを申し込んでみましょう。
- [Community Editionを申し込む（無料）](https://qiita.com/IQ_Bocchi/items/00f07f020d7adcd17098)

#Bot作成画面の起動方法

Automation 360 の Control Room にログインし、「オートメーション」のタブから「Botを作成」のアイコンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/8352b46a-13db-1545-a999-ae8ec9ae0619.png)

任意の名前をつけて「作成と編集」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/80e9497e-1715-e358-925a-7eaeaf27411b.png)

Bot作成画面が起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/c8707cfc-7ed0-f2aa-cb0d-23052490941f.png)

なお、開発画面の言語が英語表示になっていて、日本語に直したい場合は、以下の手順を参考にしてください。

https://qiita.com/IQ_Bocchi/items/192cea506bc98f4088e1

#次のステップ

具体的な開発画面の使い方は、[はじめてのAAシリーズ](https://qiita.com/IQ_Bocchi/items/8d28f12256037b5f9058)の今後の記事で、実際にBotを作りながら解説していきます。


#最後に

この記事は、「はじめてのAA」シリーズの一部となっています。

https://qiita.com/IQ_Bocchi/items/8d28f12256037b5f9058

Automation Anywhere を使い始めたばかりの方はもちろん、これから使ってみようと思っている方や、ずっと使っているけど改めて基本を学びたい方も、ぜひ上記のリンクを開き、シリーズ全体をチェックしてみてください。
【iOS】App内課金のレシート検証で responseBody.Latest_receipt_info が undefined だった時の対処法

``NG:`` responseBody. **L** atest_receipt_info
``OK:`` responseBody. **l** atest_receipt_info

先頭を小文字にすればOKでした。

公式DOC（[responseBody.Latest_receipt_info _ Apple Developer Documentation](https://developer.apple.com/documentation/appstorereceipts/responsebody/latest_receipt_info)）は大文字始まりで書いてあるので注意です。
ESlintとPrettierの設定

#1 背景
Webアプリ開発をするにあたり、個人開発ではフォーマットを特に気にする必要がなかったが、今後チーム開発をしていく上で、メンバーでコードのフォーマットを統一する必要がある。
ESlint＆prettierというツールを用いることでコードのフォーマットを自動で整えられるらしい？ので後学のために初めて自分でESlintとprettierの設定をするまでの道筋を備忘録として残しておきます。

#2 ESlint,Prettierとは？
- ESlint：https://eslint.org/  
コードを静的に分析して、構文チェック、コード整形を行ってくれる
- Prettier：https://prettier.io/  
コードを整形してくれる

簡単に言えば上のような機能を持った便利ツールなのですが、ESlintもコード整形を行なってくれるならPrettierは必要ないように思えます。
しかし、二つを併用することでよりコード整形を正確に行うことができます。
具体的な違いについては本記事では割愛しますが、詳しく知りたい方は以下の記事を参考にしてください。
https://qiita.com/soarflat/items/06377f3b96964964a65d

#3 ESlintとPrettierの導入
ここではpackage.jsonが作成されていることを前提として話を進めていきます。 

まずは必要なパッケージをインストールします。 

```shell
npm install prettier eslint eslint-config-prettier --save-dev
```
次にローカルインストールしたPrettierを実行するためにパスを通します。

```shell
export PATH=$PATH:./node_modules/.bin
```
そして以下のようなディレクトリ構成になるようファイルを作成します。 

```
sampleApp
├── .eslintrc
├── .prettierrc
├── package.json
└── index.js
```

**.eslintrcの内容** 

```:.eslintrc
{
  "root": true,
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": ["eslint:recommended", "prettier"]
}
```
```
  "extends": ["eslint:recommended", "prettier"]
```
でESlintのフォーマットルールが無視される。

**.package.jsonのscripts** 

```.json:package.json
{
  "scripts": {
    "format": "prettier --write index.js",
    "lint": "eslint --fix index.js",
    "fix": "npm run format && npm run lint"
  }
}
```
上のように記述することで

```shell
npm run fix
```
を実行するとprettierによるコード整形とeslintによる構文チェックを同時に行えるようになります。

**.prettierの内容**
デフォルトでもprettierはコード整形を行なってくれるが、私が今回設定した内容を少し見てみよう。

```:prettierrc
{
  "printWidth": 120,
  "useTabs": false,
  "semi": true,
  "singleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}
```
具体的にどんなルールを適用しているかは割愛しますが、自分なりにフォーマットルールをカスタマイズできるので調べてみると面白いかもしれませんね。

#4 最後に
これでコード整形をカスタマイズルールで行えるようになりましたが、さらにcommit時にもチェックを行えるようにすることもできます。こちらも調べてみると良いでしょう。
私も使い始めたばかりなのでこれからもまだまだ調査が必要ですね。笑
もし「ESlint,Prettierを使ってみたいけど設定がいまいち分からない」といった方の参考になれば幸いです。
Python3: 診療・検査医療機関の PDF を JSON に変換

次で公表されている PDF を JSON に変換します。
[診療・検査医療機関の公表について](https://www.pref.tochigi.lg.jp/e04/sinnryoukensa2.html)

小山地区のデータを取得します。

```bash
wget https://www.pref.tochigi.lg.jp/e04/documents/20220112225313.pdf
```

PDF の表示

```bash
evince 20220112225313.pdf
```

![medical_jan24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/4d70c5b8-6634-ca92-27d8-870c37520454.png)

変換

```bash
pdftotext -layout 20220112225313.pdf
#
./medical_to_json.py 20220112225313.txt oyama_medical.json > tmp01
#
```

```py:medical_to_json.py
#! /usr/bin/python
#
#	medical_to_json.py
#
#						Jan/24/2022
# ------------------------------------------------------------------
import sys
import json
# ------------------------------------------------------------------
def true_false_convert(ss_in):
	rvalue = False
	if ss_in == '○':
		rvalue = True
#
	return rvalue
# ------------------------------------------------------------------
def convert_to_dict(ss):
	unit_aa = {}
	unit_aa["name"] = ss[0]
	if 1 < len(ss):
		unit_aa["postal"] = ss[1]
		unit_aa["address"] = ss[2]
		unit_aa["phone"] = ss[3]
		unit_aa["consult"] = true_false_convert(ss[4])
		unit_aa["inspect"] = true_false_convert(ss[5])
		unit_aa["only"] = true_false_convert(ss[6])
		if 7 < len(ss):
			unit_aa["others"] = true_false_convert(ss[7])
		if 8 < len(ss):
			unit_aa["comment"] = ss[8]
#
	return unit_aa
#
# ------------------------------------------------------------------
def omit_check_proc(line):
	rvalue = True
	array_omit = ["診療・検査医療機関","実施内容","電話番号","医療機関名",
			"（代表）","のみ可","検査","ページ",":"]
	for word in array_omit:
		if word in line:
			rvalue = False
#
	return rvalue
# ------------------------------------------------------------------
def line_proc(line,list_aa):
	chx = line[0]
#	if chx != " " and chx != "【" and chx != "0":
	if chx != "【" and chx != "0":
		if (omit_check_proc(line)):
			ss = line.split()
			print(ss)
			unit_aa = convert_to_dict(ss)
			list_aa.append(unit_aa)
#			print(line)
#
# ------------------------------------------------------------------
sys.stderr.write ("*** 開始 ***\n")
file_in = sys.argv[1]
file_json = sys.argv[2]
sys.stderr.write(file_in + "\n")
sys.stderr.write(file_json + "\n")
#
fp_in = open(file_in,encoding='utf-8')
lines = fp_in.readlines()
fp_in.close()
#
list_aa = [] 
for it in range(len(lines)):
	line = lines[it]
	if 10 < len(line):
		line_proc(line,list_aa)
#
json_str = json.dumps(list_aa)
#
fp_out = open(file_json,mode='w',encoding='utf-8')
fp_out.write(json_str)
fp_out.close()
sys.stderr.write ("*** 終了 ***\n")
# ------------------------------------------------------------------
```
RPAで自動化してはいけない作業を自動化してみた

#1.重要じゃないのに煩わしい仕事ってあるよねって話

皆さんの会社には災害時に従業員の安否を確認する仕組みはありますか？
もしくは、最近だと毎朝健康状態チェックのようなことをしている会社もあるかもしれません。
弊社ではこの災害時安否確認が訓練として不定期で飛んできます。

この手の作業、著者は嫌いです。
・作業自体が利益を一切生み出さない
・無事・OKでもわざわざレスを返さなければならない煩わしさ
・回答を忘れると集計結果メールにて全社員に晒上げられるというおまけ付きetc…。

この作業より優先すべきことが多すぎてついつい忘れてしまうんですよね。
その結果、晒し者にされるって酷くないですか…？

#2.なくならないなら、自動化しようその作業
作業自体がなくせならのであれば、こちらも確実に対応する手段を考えてみましょう。
と、いうわけで、今回はRPAを使って安否確認登録作業を自動で応答してみようと思います。

やりたいことをざっくりと業務フローにまとめると以下のような感じになります。
![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471853/9039d0e4-dd0a-f608-4f1e-a1479219fd27.png)
##2-1.使ったもの
・Power Automate Desktop（Microsoft製RPAツール）
・Gmail（メール受信用）

##2-2.できあがったもの
前回の開発で使ったPowerAutomateDesktopのメールボックスの定期監視処理を流用し、特定のメール受信があった際に、操作の自動化を使ってWebシステムへの登録を自動化する仕組みを作ってみました。

↓前回の開発↓

https://qiita.com/af-noguchi/items/d1efab8559beb7c4e0e5

完成した Power Automate Desktop のフローは以下の通りになります。
![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471853/5a9f31f2-fe6c-616f-3ece-3732f8062445.png)
##2-3.開発におけるポイント
メール取得における注意点は前回の通りです。
###・Web画面の表示ずれ問題
画面操作記録時の注意点として、 Web 画面の表示ずれを抑えるため、Webサイトを最大化で開く必要があります。
後、実行環境が変わると高確率でずれるので注意です。
###・結果の取得も検討する
処理が失敗するケースもまれにあるようなので、処理結果を受け取る仕組みを検討する必要があります。
今回は Web システムへの登録後、結果が自動でメールが送信される仕組みがありましたので、システムへの実装はしていませんが、レスポンスがWeb画面などで完結する場合は、検討する必要がありそうです。
###・画面記録の再取得が面倒問題
今回利用した Power Automate Desktop は1動作ずつアクションとして記録されるので、必要な部分だけ再記録して繋ぎ直せばOKです。処理全体の再記録はいりません。

#3.自動化してみたけど、これ自動化しちゃダメなやつだった
##3-1.そもそも業務の目的を満たしていない
私がやりたいことは実現できたのですが、これ、私自身の状態にかかわらず、「無事です」と登録してしまいます。
本当に災害時にあったら、状況把握が遅れてしまうという結果につながりかねない…。
##3-2.部門側の業務要件を満たすため改修案
部門としては、正しい安否状態を取得することが目的になりますので、今後は本人が本当に被災した場合の処理を組み込む必要があります。
今回はメール受信 → 自動化処理としたため、自動的に Yes を回答する仕組みとしたのですが、今後の発展として、LINE Messaging API を使ってメール受信後に通知を送付し、応答内容によって自動処理するか自身で手動登録するかを変更できる仕組みにしたいですね。
メール受信通知ツール「通知さん」を作ってみたら、休日のメールチェックから解放された件

#1．休みの日は仕事のメールを見たくない

普通は見ちゃいけないんですけどね。
ですが、情報システム担当をしていると、そうも言ってられないわけです。
例えば、システム障害の通知メールとなどは、いつ来るかもわからない上に、対処が遅れると致命的になります。
なので年末年始の長期休暇も最低半日に1回のメールチェックが日課になってしまっています。
会社のメールを全部個人メールに転送すれば早いのですが、禁止されているんですよね。
システム障害のメールが来た時に個人スマホとかに通知が来るようなシステム導入してくれればいいのに…。

#2．メール受信時に通知がくる仕組みを作ってみよう
と、いうわけで今回の開発は、休暇中に会社のメールに確認が必要なメールが届いたときに、
自分に身近なツール（個人メールやLINE等）に通知する機能を目標に開発を進めました。

##2-1.使ったもの
LINE Notify （LINEに外部サイトからの通知を送るツール）
Power Automate Desktop（Microsoft製RPAツール）
Gメール（メール受信用）

##2-2.できあがったもの

今回はPowerAutomateDesktopでメールボックスの定期監視処理を走らせ、
特定のメール受信があった際に、LineNotify経由で個人用LINEに通知が届く仕組みを作りました。

以下、PowerAutomate のフロー
![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471853/8ff43cbd-e6e7-ad44-b22e-e14ef1a21d61.png)


##2-3.開発におけるポイント

###・開始トリガをどうするのか問題
今回、PowerAutomate Desktop というツールを作ったのですが、
そもそもRPAツールなので常時稼働を想定されていません。
なので、実行トリガーをどうすべきかを初めに悩みました。
結果としては、常時起動させて5分おきにメインプログラム走らせる仕様で落ち着いたのですが、
この部分は利用するツールによっていろいろとやりようありそうなので、検討の余地がありますね。
###・取得メッセージの再処理を抑止する
5分おきにGメールのチェックを再走査する仕組みになりますので、
フィルター条件しくじると、何度も同じ通知が来ます。
今回は未読メールをフィルタ条件にし、処理時にメールを既読にすることで回避しています。
![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471853/5f1028e7-294b-9187-f9a7-f3f39ee9d84d.png)
###・LINEへの通知設定
基本添付画像の通りでOKです。
ポイントとして、規定で「エンコードするのチェックが入っているので、ここをオフにしておかないとうまく動かないです。」
![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471853/301c313c-c5de-b049-9d20-ed2a7e430135.png)
#3．便利だけどもやもやする
##・メールチェックから解放された
このツールのお陰で休日に会社のメールを気にしなくてもいい日々を送れています。
LINEに通知が届くので、これまでより気付く速度も格段に速いです。
通知さん、なんて便利な奴なんだ！
※現在は、休日前にフローを起動し自分宛に届いたメールを全通知しています。
##・パトランプを思い出す
システム運用現場にはパトランプという、システム障害が起きたら警報を鳴らすアイテムがあります。
通知さんはそれに近いです。日時・場所を選ばず個人LINEにアラートを届けてくれます。
定期的にメールを見ていた時はある程度意識を切り替えて対応できていたのですが、「通知さんは」プライベートに割り込んでくるのでもやっとしますね。
DXってプライベートとビジネスの垣根もなくしていくんじゃなかろうか。
##・更なる効率化を目指す
今回は PowerAutomate Desktop に触れる機会があったので、無理やりこのツールを使って実装してみたのですが、
良く考えてみると、Node-RED と Gmail の API を使ってメールの受信をトリガにフロー走らせた方が効率的ですね。
メールをトリガにして何らかの処理を走らせる方法は、いろいろと調べてみようと思いました。
React状態管理ライブラリ Jotai と Jotai Friends

## はじめに
React状態管理ライブラリの１つであるJōtaiをご存知でしょうか。数々の状態管理ライブラリを開発してきた[Daishi](https://qiita.com/daishi)さんの代表作であるJōtaiは世界的に注目されているライブラリの一つです。([2021 JavaScript Rising Stars - State Management](https://risingstars.js.org/2021/en#section-statemanagement))

この記事は、JotaiとJotaiファンになった私が立ち上げたJotai Friendsの紹介記事となります。

## Jotaiとは
Jotaiは以下のような特徴があります。

```
- ボトムアップアプローチ型の状態管理ライブラリ（単一のStateではなく複数のStateを自由にグローバル定義・利用する。1つのStateをAtomと呼称する）
- ミニマルなAPI
- AtomにユニークなKeyを設定する必要は無し（Recoilは必要）
- Providerレスモードで利用可能
- TypeScriptで開発されている
```

以下の様に使います。

```jsx
import { atom, useAtom } from 'jotai'

export const countAtom = atom(0) // グローバルステート

function Counter() {
  const [count, setCount] = useAtom(countAtom) // useState()と同様の使い方
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => setCount(c => c + 1)}>one up</button>
    </div>
  )
}
```

https://jotai.org/

## Jotai Friendsとは
いちJotaiファンとして、エンジニアの皆さんにもっとJotaiを知ってもらい、使ってもらいたい、そんな思いから立ち上げたのがJotai Friendsです。

https://jotaifriends.dev/


## 特集記事を書きました
zenn.devにて、Jotaiを知ってもらうべく特集記事を書きました。

記事一覧はこちら

https://zenn.dev/tell_y/articles/8d13419646b632

特集の中でも多くの方に読んで頂けたのはこちらの記事です。

https://zenn.dev/tell_y/articles/7a5bd147d34ec2

## おわりに
これまで、Redux等に始まり、状態管理ライブラリはいくつか登場してきました。Reactをはじめ、フレームワークなどの発展とともにライブラリも追従し進化する必要があります。アプリケーションに必要となるライブラリも、少なからずその影響を受けます。
Jotaiは単に魅力があるというだけではなく、Reactに関する知見が豊富なDaishiさん([React Conf](https://conf.reactjs.org/speakers/daishi)の登壇も記憶に新しいですね)がしっかりとフォローしてくださっています。

一つのOSSライブラリをテーマに"推し"広めることは稀かもしれませんが、Jotai Friendsでは開発者の皆さんにJotaiをより知ってもらい、使ってもらえるよう知見を提供していきます。

https://jotaifriends.dev/

今後とも宜しくお願いします！
読書メモ: 入門情報幾何

8ページ、式(1.22)の

```math
\frac{1}{\sqrt{n}}\left(1-\sum_{i=1}^{n} a_{i}\right)
```
は、幾何的な意味でいうと、n次元超平面と点の距離。
7ページ図1.2の2次元の例でいうと、
点(1, 0)点(1, 0)を結ぶ線分と任意の点の距離のこと。
図1.3の3次元の例で言うと、
点(1,0,0), 点(0, 1, 0), 点(0, 0, 1) を通る平面と任意の点の距離のこと。
つまり式(1.22)は、点aとn+1個の境界面との距離のminをεとするということであり、
開球B(a,ε)の球面は、点aから一番近い境界面に接することになる。
（開球の球面っていう言い方は変かもしれない。開球は球面を含まないので。）
というわけで、幾何的にはそりゃそうですよねという感じ。

35ページ、式(2.10)には正誤表あり。
誤のほうだと、点pから点qまで最短距離で行くために、
一定の速さで向かわなきゃいけないことになるが、
もちろんそんなことはなく、pからqの方向へまっすぐ向かってさえいれば、
速さが変化するのは問題ない。
そういう意味の正誤表。

2022/01/23 40ページまで。

ちょっと戻って36ページ、リーマン計量が導入されているところ。
リーマン計量は標準内積とは限らない内積として導入されているので、
2ページ定理1.1の対称性・線形性・正値性を、リーマン計量も満たすと思って読んでいく。
そうやって読んでいくと、40ページで線形性・対称性・正値性を使って、
39ページ式(2.28)が導ける。

2022/02/06 47ページまで。
【jQuery】fileupload注意点

先日、jQueryのfileuploadを使おうとしていたところ、以下のエラーが出てハマったことを残しておきたい。

<h2>jQuery fileuploadについて</h2>
・Github
https://github.com/blueimp/jQuery-File-Upload

・公式のjQuery File Uploadのデモ
https://blueimp.github.io/jQuery-File-Upload/

<h4>エラー</h4>
`caught TypeError: Cannot read properties of null( innerHTML )`


<h2>対処方法について</h2>
原因は至ってシンプル。
jQueryのFile-Uploadはtext/x-tmplというmime-typeを使うJavaScriptエンジンに依存関係にあるらしい。
すべてのエラーに当てはまるわけではないので、今後もし詰まってしまったときには試してみたい。

※参考サイト
https://stackoverflow.com/questions/10025856/what-is-x-tmpl
Vivliostyle CLIで複数のMarkdownファイルを個別にPDF化する


# 概要

シェルの繰り返し構文を使って 環境変数に番号をセットしておき、vivliostyle.config.jsでは環境変数を読み込んでタイトルやMarkdownファイルのファイル名の設定に利用することで複数のMarkdownファイルを個別にPDF化します。

将来的にはVivliostyle CLI本体だけで可能になるかもしれません。

https://github.com/vivliostyle/vivliostyle-cli/issues/229

# 環境

OS: macOS BigSur
Vivliostyle CLI: 4.4.1
shell: zsh(shやbashなどでも動作するはず)

# vivliostyle CLIを繰り返し呼び出すシェルスクリプト

```sh:build.sh
#!/bin/sh

# nが1から24までの間繰り返す bash(4.0以降),zshでパディングするなら{01..24}
for n in {1..24}
do
 # NOという環境変数にnを設定してVivliostyle CLIのビルドを行なう
 NO=$n vs build
done
```

# 環境変数を利用するvivliostyle.config.js

```javascript:vivliostyle.config.js
const no = process.env.NO; // 環境変数から値を取り出す

module.exports = {
  title: '評価シート_'+no,  // タイトル、出力ファイル名に変数を埋め込む 評価シート_1.pdf 〜 評価シート_24.pdf
  author: 'Ayumu Takai',
  size: 'A4',
  theme: 'style.css',
  image: 'ghcr.io/vivliostyle/cli:4.3.1',
  entry: [ no+'.md'],     // 原稿Markdownファイル名に変数を埋め込む 1.md 〜 24.md
  workspaceDir: '.vivliostyle',
};
```
Power Appsをバージョン管理（Azure DevOpsのgitで）

## はじめに

Power Apps で、GitHubやAzure DevOpsのgitリポジトリと連携することで、アプリのバージョン管理を行える機能がプレビュー機能として登場しました。
今日は、Azure DevOpsでバージョン管理を試してみたいとおもいます。

## 材料

* Azure DevOpsのRepoのgitリポジトリ
* Power Appsの開発環境

## 準備

* 設定の近日公開予定の「バージョンコントロールの設定を表示する」をオンにします。
![001_バージョンコントロールの設定を表示するをオン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/6bbecbb9-7f4e-a387-d4f6-b652a7684dea.png)


## gitリポジトリとの接続設定

* 設定の「Git バージョン管理」を押し、接続ボタンを押します。
![002_Git接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/9e6b7768-e7bc-33da-039c-08677784fa8c.png)


* git接続のための設定を行います
    * Git リポジトリのURL
        * https://＊＊＊＊.git を指定します
    * 分岐
        * ブランチ名を指定します
    * ディレクトリ名
        * ソース内のフォルダ名を指定します

![003_git接続のための設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/592cf143-86c8-3754-b6d4-af6662e3ba3e.png)


* ID, password 入力します
![004_IDpass入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/38f61331-a520-ad94-3e40-98c2ef1338f9.png)


* gitリポジトリ接続設定が完了すると以下のような画面になります
![005_git接続完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/56e3e8eb-3af8-4c3e-9796-e13b695cd79d.png)


* Azure DevOpsにもファイルが連携されています
![006_AzureDevopsのファイル連携.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/09be759f-e20a-1027-6f6d-28610a6913d9.png)


## バージョン管理を試す

* なにかアプリ内にボタンを配置して、アプリを保存します。
![007_ボタンを置く.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/cb882ee1-f826-07db-800e-9197340a5212.png)


* すると、保存のタイミングで自動的にgit commitされます。
    * いままではだれが修正したかわからなかったので、修正者が出てくるのは助かります。
![008_コミット後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/1e5a30f0-ba2e-2f8b-9d27-cac090cc9342.png)



## 次回

* 同時編集を試す予定です。
* git用のボタンが増えているので、このボタンを押したらどうなるか試してみる予定です。

![009_git関連ボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52550/39eca232-a28a-1180-4990-d5ff7b0f631e.png)
ModelerFlowでICOSのCSVを読んでICOSに書き込む

CP4DのModelerFlowでICOSのCSVを読んでICOSに書き込んでみます。

テスト環境
CP4D 4.0.4

#1 ICOSデータ読込
データ資産ノードを選び開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/60abaf5f-4c66-747b-6953-05aae2012bc9.png)

データ資産の中からICOSのcsvファイルを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1e996139-3349-6b45-24ce-feb9e60c7f8f.png)

保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6060aed1-fedc-9855-2323-0262a014d854.png)

#2 ICOSへの書き込み
データ資産エクスポートを選び開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/91865073-5682-3e4c-9e3b-e0099d81b5bc.png)

エクスポート先に「接続に保存」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/bf04255b-0df7-2eb5-3e56-c74fd5a100af.png)

接続にICOSの接続（例：200322icosbucket）を選びフォルダ（例：output）を選んだあとに新規のファイル名（例：mf_Cond4_e104.csv）を入力し選択ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/26f9e1e5-c557-62ed-bae5-f0869670927d.png)


保存ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6b04869c-3731-733a-87bc-027ef98a6f78.png)


データ資産エクスポートを右クリックし実行を行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6c39c77e-bd2c-8c24-83b4-d8f3e6566894.png)


成功しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d6161d49-027a-509b-2118-9f88563f321f.png)


#3 確認
データ資産ノードをもう一つ選び、開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/91c2e975-4745-f76c-18ad-1ab975a657f1.png)


接続（データ資産ではない）から作成したcsvを選択し、選択ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/499cea7f-66ea-c12f-7dda-dce5843e604a.png)




保存ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6c1b1cc5-ef20-b1ff-e69a-30afd0f86d73.png)


プレビューします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0e7680fe-0d73-e960-a688-788dea125371.png)


データが書き込まれていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b5c3bffd-dfa0-eb20-0f69-4cde7e9b31cd.png)
Delta Lake on DatabricksのOptimizeコマンド

[Optimize \(Delta Lake on Databricks\) \| Databricks on AWS](https://docs.databricks.com/spark/2.x/spark-sql/language-manual/optimize.html) [2021/4/5時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

Delta Lakeデータのレイアウトを最適化します。オプションとして、カラムを指定することでデータのサブセットを最適化したり、データを近い場所に配置することができます。カラムを指定しない場合にはbin-packingの最適化が実行されます。

> **注意**

> - Bin-packingの最適化は冪等性が保証されるので、同じデータセットに対して2回実行したとしても、2回目の実行の効果はありません。ディスク上のデータファイルのサイズに基づいて、均等にバランスされたデータファイルを生成しようとしますが、ファイルごとのタプルの数が必ずしも均等になるわけではありません。しかし、これら二つの指標は多くの場合相関します。
- Z-Orderingは冪等性が保証されませんが、インクリメンタルな処理を行おうとします。複数回のZ-Orderingで処理に要する時間が削減されることは保証されません。しかし、Z-Orderingが実行された直後のパーティションに新規データが追加されない場合、当該パーティションに対するさらなるZ-Orderingには効果がありません。タプルの数に基づいて均等なデータファイルを作成しようとしますが、ディスク上のデータファイルサイズが必ずしも均等になるわけではありません。これらの二つの指標は多くの場合相関しますが、そうでない場合もありえますし、最適化タスクの時間に偏りが発生することもあります。
- アウトプットのファイルサイズを制御するためには、[Spark設定](https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#spark%E3%81%AE%E8%A8%AD%E5%AE%9A)の`spark.databricks.delta.optimize.maxFileSize`を指定します。デフォルトは`1073741824`であり、1GBとなります。値を`104857600`とすることで、100MBのファイルサイズに指定することができます。

**`WHERE`**
指定されたパーティション述語にマッチする行のサブセットを最適化します。パーティションキー属性を含むフィルター条件のみがサポートされています。

**`ZORDER BY`**
カラム情報を同じファイルセットにコロケートします。読み込みに必要なデータの量を劇的に削減するために、Delta Lakeのデータスキッピングアルゴリズムによってこの局所性が活用されます。カンマ区切りのリストとして複数のカラムを`ZORDER BY`に指定することができます。しかし、カラムを追加するごとに局所性は損なわれます。

# 例

```sql:SQL
OPTIMIZE events

OPTIMIZE events WHERE date >= '2017-01-01'

OPTIMIZE events
WHERE date >= current_timestamp() - INTERVAL 1 day
ZORDER BY (eventType)
```


### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
DNSサーバの各実装まとめ(ざっくり)

主要なDNSサーバの実装をまとめた。

# BIND

- リファレンス実装
- Berkeley Internet Name DomainでBIND
- DARPA(旧ARPA)からの資金援助により開発が開始され、その後DECの社員に引き継がれ、現在はISC(Internet Systems Consortium)によってメンテナンスされている
- ※ ちなみにISCはDNSのルートサーバ(Fサーバ)の管理も行っている
- BIND 9はDNSSECへの対応に伴い、BIND 4/8のコードを捨てて新たに書き起こされた
- C実装
- リンク
  - 公式サイト: https://www.isc.org/bind/
  - ソース: https://github.com/isc-projects/bind9

# djbdns

- ダニエル・バーンスタインが開発
- DNSキャッシュサーバのdnscacheとDNS権威サーバのtinydnsの２つから構成される
- シンプルかつ堅牢な構造
- djbdnsはその管理にdaemontools、内部で使用するDBにcdb(constant database)が用いられているが、これらは両方ともダニエル・バーンスタインによって開発されたものである
- C実装
- リンク
  - 公式サイト: http://cr.yp.to/djbdns.html
  - ソース(ミラー): https://github.com/abh/djbdns

# Dnsmasq

- 小規模ネットワーク(LAN内)向け
- DHCP/TFTP/PXEも含まれている
- hostsやAvahiの代替として使われることが多いっぽい(?)
- C実装
- リンク
  - 公式サイト: https://thekelleys.org.uk/dnsmasq/doc.html
  - ソース(ミラー): https://github.com/imp/dnsmasq

# NSD

- DNS権威サーバのみを提供する
- Name Server DaemonでNSD
- NLnet LabsがPIPE NCC協力のもと開発
- C実装
- リンク
  - 公式サイト: https://www.nlnetlabs.nl/projects/nsd/about/
  - ソース: https://github.com/NLnetLabs/nsd

# Unbound

- DNSキャッシュサーバのみを提供する
- Kirei社/Nominet社/VeriSign社/EP.net社がJavaベースで開発していたものをNLnet LabsがCで実装し直した
- リンク
  - 公式サイト: https://www.nlnetlabs.nl/projects/unbound/about/ 
  - ソース: https://github.com/NLnetLabs/unbound

# PowerDNS Authoritative Server

- 元々はプロプライエタリだったDNS権威サーバ
- C++実装
- リンク
  - 公式サイト: https://www.powerdns.com/auth.html
  - ソース: https://github.com/PowerDNS/pdns

# PowerDNS Recursor

- DNSキャッシュサーバ
- 公式サイト: https://www.powerdns.com/recursor.html
- ソース: https://github.com/PowerDNS/pdns

# PowerDNS dnsdist

- DNS用のロードバランサ
- 公式サイト: https://www.powerdns.com/dnsdist.html
- ソース: https://github.com/PowerDNS/pdns

# Knot DNS

- チェコのNIR(国別インターネットレジストリ)であるCZ.NICが開発したDNS権威サーバ
- リンク
  - 公式サイト: https://www.knot-dns.cz/
  - ソース: https://github.com/CZ-NIC/knot

# Pi-hole

- アドブロックを内包しているDNSサーバ
- 小規模ネットワーク(LAN内)向けっぽい
- リンク
  - 公式サイト: https://pi-hole.net/
  - ソース: https://github.com/pi-hole/pi-hole

# CoreDNS

- CNCFのプロジェクトの１つ
- 充分成熟したプロジェクトとされ、Graduatedに指定されている
- Go実装
- リンク
    - 公式サイト: https://coredns.io/
    - ソース: https://github.com/coredns

# Trust-DNS
  
- Rust実装
- ソース: https://github.com/bluejekyll/trust-dns
元サッカー日本代表監督が語る「運」とはっ！

##前書き
『「運」という不確実なものについて、世の先人たちが語る「運」には、ある種の共通項があるのではないか？』
毎日続けている読書感想文「１日１話」の記事の読書の中で、何度か「運」について語る先人たちの記事を読んできた私は、「運」について語る記事について「運シリーズ」というタグを振る感想文をQiitaの中でも書くことを始めた。
先人たちが語る「共通項」について考察し、エンジニアとして、人間として生きるためのヒントを掴もうというためである。

今日読んだ記事、致知出版社[『1日1話、読めば心が熱くなる365人の仕事の教科書』][1]の【10月1日】目。元サッカー日本代表監督の岡田武史さんの記事。
現在は、JFAの理事の他、自らJリーグ入りを目指すサッカーチームFC今治のオーナーとしても活躍する「岡ちゃん」の語る「運」を紹介させていただきます。

[1]:https://www.amazon.co.jp/1%E6%97%A51%E8%A9%B1%E3%80%81%E8%AA%AD%E3%82%81%E3%81%B0%E5%BF%83%E3%81%8C%E7%86%B1%E3%81%8F%E3%81%AA%E3%82%8B365%E4%BA%BA%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E8%97%A4%E5%B0%BE%E7%A7%80%E6%98%AD/dp/4800912474




##本題【10月1日】 勝負の神様は細部に宿る 岡田武史 日本サッカー協会理事・サッカー日本代表前監督

岡田武史。サッカー指導者。1998年の仏Ｗ杯では日本代表監督として初めてＷ杯出場を果たす。
あのジョホールバルの歓喜は、名将加茂周監督の更迭によりコーチから監督に昇格した無名の岡ちゃんの人生の転機だっただろう。
1956年生まれ。御年65歳。

この記事は2011年1月号の雑誌「致知」の対談記事。南アフリカＷ杯で再び監督の指揮を執った岡田が振り返る。岡田が語るのは「運」を掴むためにやるべきこと。
おお、「運」シリーズだ。岡田は『いつも選手に言うこと』、『ずっと言ってきたこと』として、２つの持論を語っている。

>これはいつも選手に言うことですが、「運」というものは誰にでも、どこにでも流れていて、それを掴むかつかみ損ねるかだと。僕は掴み損ねたくないから、そのために本当にベストを尽くしてきた。
　だから今回も睡眠時間は平均四時間くらいで、深夜二時、三時まで必死に試合のビデオを見て、また翌日の練習に臨むという生活を続けました。そうして必死になってやっていると、最後は神様がご褒美をくれるんです。
　要するに、自分にできる限りの準備は全部する。その後の勝負の結果についてはもう分からない部分ですから。
　それともう一つ、ずっと言ってきたことですが、「勝負の神様は細部に宿る」と。勝ち負けが決まると、マスコミの人はいろんな戦術論を並べ立てるんですが、僕は感覚的に八割ぐらいは「小さなこと」が勝負を分けているように思うんです。
　だから僕は、細かいことにものすごくうるさいんですよ。
　おまえがあそこでたった一回、「まぁ、いいか」とか「これぐらいで大丈夫だろう」と気を抜いたために、運を掴み損ね、Ｗ杯へ行けなくなってしまった。そんなふうに運を掴み損ねたくなかったら、どんな小さなこともすべてきちっとやれ、と。
　で、今回、選手たちはそれをちゃんとやってくれたんですよ。そうやって運を掴み損ねなかったから、あそこまで行けたんだと思うんですよね。


　ふむ。岡ちゃんの自らの実体験を物語るような持論である。
Wikiによると、岡ちゃんは当初加茂ジャパンのコーチを固辞したらしい。
　まだ無名のコーチで加茂さんとも面識はなかったという。
当時ジェフのコーチをしていたが、ジェフ監督の清雲さんが加茂監督や岡田自身にも熱心に勧めたという。
　サッカー指導者として最初の「運」を掴み取った瞬間かもしれない。
　その後、加茂監督の更迭による代表監督へのスライド就任。当時は臨時としての監督だったが、チームは勝ち続け、とうとうジョホールバルで初のＷ杯出場を決めた。

　**『「運」というものは誰にでも、どこにでも流れていて、それを掴むかつかみ損ねるかだ』** という岡ちゃんの言葉に説得力が増す。
　さらに『僕は掴み損ねたくないから、そのために本当にベストを尽くしてきた。』という岡ちゃんを、周りの人もちゃんと見ていたのだろう。
　そして、岡ちゃんはいつでも準備ＯＫなのだから、特別なウォーミングアップは不要なのである。既に掴んだ「運」に対する準備は出来ている訳だ。

　また岡ちゃんはこのように語っている。『**「勝負の神様は細部に宿る」』** と。**勝負の結果については神様にしか分からないけれども、神様はひとつひとつの「小さなこと」を見ているんだよ、** と。
だから、ほんの小さいこと、細かい事にも妥協せずに気を抜くなと言っている。運を掴み損ねるぞ、と。
　これはサッカー愛好家であれば、サッカーの試合を見ていると分かるかも知れない。一つのミス、一つのパス、一つの選択が試合を決定づける得点につながることがサッカーには往々にしてある
　選手も人間だから油断するし、楽もしたい。だが、しかし。それは相手チームも同じなのである。そして、レギュラー争いをする選手たちだけではなく、ともに戦うコーチや監督も同じなのである。
　岡田はプロの指導者として、サッカーの技術、戦術だけではなく、そういう人間の性質、気持ち、メンタルも指導していた。

　岡田が語る「運」とは、 **自分自身が望むことに対して常にベストを尽くしたとしても100%掴み取れるとは言えないもののこと。**」
　サッカーでいうと、試合での勝利であったり、日本代表に選出されるだったり、その中でレギュラー選手となることだったり、か。
　**そして、その「運」はいつでもどこでも流れていて、それを逃さずに掴み取るためには、常にベストを尽くして油断するな、ということであった。**
　かなり手厳しいな。これが勝負師岡ちゃんの語る「運」である。

（参考）
岡田武史　-Wiki

https://ja.wikipedia.org/wiki/%E5%B2%A1%E7%94%B0%E6%AD%A6%E5%8F%B2

##後書き


以上、「運シリーズ」第7弾、**元サッカー日本代表監督が語る「運」とはっ！** でした。
最後までお読みいただきありがとうございました。

よろしければ、過去の「運シリーズ」も読んでいただければ幸いです。

https://qiita.com/takeC74/items/30bcef3dbcfb595864d6

https://qiita.com/takeC74/items/fcc22c9a0e27bc8b0f46

https://qiita.com/takeC74/items/c496778447ea86ce8769

https://qiita.com/takeC74/items/5801a8e53e63153f86a6

https://qiita.com/takeC74/items/386a20e56d2cffa3bd94

https://qiita.com/takeC74/items/e2f51d395a6efc94d8c5
css のレイアウト系のメモ (随時更新)

# 概要

FlexBox や Grid layout など、実装する際に毎回迷うのでテンプレとして元になるコードを列挙しておく。


# 中央寄せ

```html
<div style="height: 200px; display: flex; align-items: center; justify-content: center;">
  <div style="width: 100px; height: 100px">中央寄せ</div>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29899/2092e2e5-5a49-1700-188a-20b68cfc0410.png)


# 画面いっぱい

```html
<style>
.layout-max-screen {
  box-sizing: border-box;  /* これがないと padding 分はみ出てしまう */
  border: none;  /* border 分ははみ出るので注意 */
  height: 100vh;
  padding: 10px;  /* padding 要らないなら不要 */
  display: grid;  /* これにより子の div も画面いっぱいに広がる */
}
</style>

<div class="layout-max-screen">
  <div>画面いっぱい</div>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29899/c516067b-899a-0153-7ab6-682684be6b96.png)


# 画面のレイアウトの一部が可変

レイアウトが完全固定なら Grid 使えばよいが、可変でアニメもする場合は FlexBox で実装する必要あり。

```html
<div>
  <div style="display: flex; flex-wrap: nowrap; gap: 10px; justify-content: flex-start; align-items: stretch;">
    <div style="width: 80px;">a</div>
    <div style="width: 80px;">b</div>
    <div style="flex: 1;">c</div>
  </div>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29899/18aa818f-d711-573c-222c-54b91e074849.png)


# 前述と組み合わせれば、高さ方向で画面MAXになる。

```html
<div class="layout-max-screen">
  <div style="display: flex; flex-wrap: nowrap; gap: 10px; justify-content: flex-start; align-items: stretch;">
    <div style="width: 80px;">a</div>
    <div style="width: 80px;">b</div>
    <div style="flex: 1;">c</div>
  </div>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29899/cbd79810-ec88-794e-410c-d007dc7f253f.png)


# Grid Layout

```html
<div class="layout-max-screen">
  <div style="
    display: grid;
    grid-gap: 10px;
    grid-template-columns: 80px 80px 1fr;
    grid-template-rows: 40px 1fr;
    grid-template-areas: 'left  center  header'  'left  center  main';
  ">
    <div style="grid-area: left;">left</div>
    <div style="grid-area: center;">center</div>
    <div style="grid-area: header;">header</div>
    <div style="grid-area: main;">main</div>
  </div>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29899/c4e36b4f-5bd9-8ded-65e7-2c0c77fa1b8d.png)

- `grid-template-areas: 'left  center  header'  'left  center  main';` は改行すると認識しなくなるので注意。(Vue3 にて確認。) Vue3 なら、下記のようにするのがよい。

  ```
  :style="{
    gridTemplateAreas: `
      'left  center  header'
      'left  center  main'
    `
  }"
  ```
Railsのminitestで、ngram検索のテスト実装時に苦戦した話

検索機能の実装時に全文検索を実装する為、Like検索ではなくMySQLのN-gramを用いて実装を行いました。
実装はスムーズにできたのですが、minitest実行時にハマったのでよければ参考にしてください。
N-gram自体が何なのかについては、下記の記事が非常に分かりやすく記載して下さっていたので、参考にしてみてください。
[MySQLでの全文検索(N-gram編)](https://qiita.com/wf-yamaday/items/a123e7b0f79fa799454b#:~:text=N%2Dgram%E3%81%A8%E3%81%AF%E4%BB%BB%E6%84%8F,%E5%BD%A2%E3%81%A7%E8%A1%A8%E3%81%99%E6%96%B9%E6%B3%95%E3%81%A7%E3%81%99%EF%BC%8E&text=%E3%81%A8%E3%81%84%E3%81%86%E5%BD%A2%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99,bigram%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%BE%E3%81%99%EF%BC%8E/　"キータ")

##実装方法

### MySQLで全文検索機能ができるように設定
N-gram自体の実装については、検索時に取得したいカラム名に対して、
FULLTEXT INDEXを貼り、パーサーにN-gramを指定するといった具合です。
※パーサーとはデータベースが持つ機能の1つで、SQL文の解析に用いられる際に使用されるそうです。

```sql
ALTER TABLE content ADD FULLTEXT INDEX ngram_idx (content_name) WITH PARSER ngram;
```

### Rails側での全文検索の記述
INDEXを貼り終えたら、Railsのコントローラー側で実装していきます。
下記のように、<font color="Red">Railsで記法が用意されていないので、生SQLで書く必要があります。</font>
MATCH()には検索したいカラム名・AGAINST(?)には引数として後ろに記載されているword(検索フォームで入力した値)が入ります。

```ruby
Content.where('MATCH(content_name) AGAINST(❔)',word)
```

##問題点
上記のように実装自体は簡単にできるのですが、Railsのminitestを実行した際に問題が発生しました。
いくらテストを流しても想定している値が取得できないのです...
用意しているymlファイルにデータ上おかしな点はないか・このSQLの構文自体がそもそも間違っていないか等色々検証を重ねましたが解決には至らず。

自力では解決できなかったので、周りの先輩社員に相談してみたところ
インデックスは<font color="Red">commitのタイミング</font>で生成される為、現行の書き方ではインデックスにヒットしないのではないかと。
現行の書き方ではsetup doの中に使用するymlファイルとモデルを記載していました。

```ruby
setup do
  ActiveRecord::FixtureSet.reset_cache
  ActiveRecord::FixtureSet.create_fixtures('test/fixtures/hoge', [:content],
  {:content => Content}, ContentDbInfo)
end
```

このsetupはrunという関数から呼び出され、テストを回したと同時に用意したデータをテーブルの中にInsertします。
この際トランザクションが貼られますが、commitはされずテストを回し終えると自動でロールバックされる仕組みになっています。
その為インデックスが生成されていない状態で検索を掛けにいってしまっている状態にある訳です。

##解決策
この仕組みを回避する為、呼び出し元であるrunをオーバーライドして先にデータを入れておくように実装してみます。

```ruby
def run
  ActiveRecord::FixtureSet.reset_cache
  ActiveRecord::FixtureSet.create_fixtures('test/fixtures/hoge', [:content],
  {:content => Content}, ContentDbInfo)
  super
end
```

このように実装してやることで、トランザクションが貼られるより前にテーブルに値を入れておくことができます。
言い換えれば既に<font color="Red">コミットされている状態</font>にあるので、きちんとインデックスが生成されている状態にできる訳です。
結果として無事に想定していた値を取得することができました。
※上記の方法で実装した場合、テストデータはDBに残ることになりますのでその点は注意する必要があります。

##終わりに
そもそも現行の作りではIndexは生成されていない状態で、テストが実行されている点に驚きましたね...
あくまでテストデータを入れているだけなので、基本的にデータが大量には必要ないですし、
インデックス自体不要というのも言われてみれば納得かなと。
ハマりはしましたが、データベース側の知識も含めて色々と勉強になりました。
【6】「いかのおすし」を縦表記しよう 

ファイルの名前は，「20211220_[自分の名前].py」でお願いします．

以下ターミナル実行時の出力例です．

```
い
か
の
お
す
し
```
https://gyazo.com/d275362db67f52ccd975376177047ee4 
↑にも授業資料の演習提示時のgifがあります．
Setting up NTFS3 as default NTFS driver

5.15 LTS has been shipped to Debian bullseye-backports, but somehow CONFIG_NTFS3_FS is disabled...

## Build ntfs3.ko (for testing)

```sh
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.5.tar.xz
tar xf linux-5.15.5.tar.xz
cd linux-5.15.5

make CONFIG_NTFS3_FS=m CONFIG_NTFS3_64BIT_CLUSTER=y CONFIG_NTFS3_FS_POSIX_ACL=y CONFIG_NTFS3_LZX_XPRESS=y -C /lib/modules/`uname -r`/build M=$PWD/fs/ntfs3 modules
sudo insmod fs/ntfs3/ntfs3.ko
```

## Setup Userland

- install 99-ntfs3.rules
    - acknowledgement: https://askubuntu.com/questions/1374541/how-can-gnome-filesnautilus-use-the-default-settings-for-mounting-ntfs-disks-w/1375955#1375955

```sh
sudo dd status=none of=/etc/udev/rules.d/99-ntfs3.rules <<EOF
# UDISKS_FILESYSTEM_SHARED
# ==1: mount filesystem to a shared directory (/media/VolumeName)
# ==0: mount filesystem to a private directory (/run/media/USER/VolumeName)
# See udisks(8)
SUBSYSTEM=="block", ENV{ID_FS_TYPE}=="ntfs", ENV{ID_FS_TYPE}="ntfs3", ENV{UDISKS_FILESYSTEM_SHARED}="0"
EOF

sudo udevadm control -R
```

- edit /etc/udisks2/mount_options.conf
    - acknowledgement: https://github.com/storaged-project/udisks/issues/932#issuecomment-958117328

```
[defaults]
ntfs3_defaults=uid=$UID,gid=$GID
ntfs3_allow=uid=$UID,gid=$GID,umask,dmask,fmask,locale,norecover,ignore_case,compression,nocompression,big_writes,nls,nohidden,sys_immutable,sparse,showmeta,prealloc
```

(seems restart is not required)

## DKMS

- after initial testing is done, you can install https://github.com/rmnscnce/ntfs3 `sudo make dkms` to make sure to have the module for further kernels.

## 220316

It seems that rmnscnce/ntfs3 cannot be built on Kernel 5.16, so run this script after rebooting...

```sh
KernelVersion=$(uname -v|grep -Po '\d+\.\d+\.\d+') # note this line is checked only on Debian
KernelMajorVersion=$(echo $KernelVersion|perl -pe 's/\.\d+\.\d+$//')
wget https://cdn.kernel.org/pub/linux/kernel/v${KernelMajorVersion}.x/linux-${KernelVersion}.tar.xz
tar xf linux-${KernelVersion}.tar.xz
pushd linux-${KernelVersion}

make CONFIG_NTFS3_FS=m CONFIG_NTFS3_64BIT_CLUSTER=y CONFIG_NTFS3_FS_POSIX_ACL=y CONFIG_NTFS3_LZX_XPRESS=y -C /lib/modules/`uname -r`/build M=$PWD/fs/ntfs3 modules
sudo cp fs/ntfs3/ntfs3.ko /lib/modules/`uname -r`/updates/dkms/ # omg note that this is not dkms.
sudo depmod -a
# now ntfs3.ko will be loaded when you insert NTFS drive.

popd
rm -rf linux-${KernelVersion}
rm linux-${KernelVersion}.tar.xz
```
DatabricksにおけるOpenCVの活用

Databricks上でも[OpenCV](https://opencv.org/)を活用して画像処理を行うことができます。ただ、ノートブック上に画像を表示する際には注意が必要です。

# 準備
`opencv-python`をクラスターライブラリとしてインストールしてください。

![](https://sajpstorage.blob.core.windows.net/qiita-images/opencv_cluster_library.png)

# ノートブック上での画像処理

cv2ライブラリを読み込んで処理を行うことができます。ただ、[こちら](https://qiita.com/narumi-github/items/63715853394bd4d110d6)で説明されているようにノートブック上で処理された画像を表示する際には注意が必要です。

```py:Python
import matplotlib.pyplot as plt
import cv2
import numpy as np
```

画像の表示にはmatplotlibを使用しますが、その際にGBR→RGBに並び替えが必要となります。

```py:Python
target = cv2.imread('/dbfs/databricks-datasets/cctvVideos/train_images/label=0/LeftBagframe0004.jpg', cv2.IMREAD_UNCHANGED)

# 画像の表示
plt.imshow(cv2.cvtColor(target, cv2.COLOR_BGR2RGB)) # OpenCV は色がGBR順なのでRGB順に並べ替える
plt.show()
```

![Screen Shot 2022-01-24 at 11.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ffb973f6-c393-0944-c991-185d87cf43f0.png)

## グレースケール変換

グレースケールへの変換も可能です。

```py:Python
# imreadの第二引数でグレースケールを指定
gry = cv2.imread('/dbfs/databricks-datasets/cctvVideos/train_images/label=0/LeftBagframe0004.jpg', cv2.IMREAD_GRAYSCALE)
#imshow(gry)
cv2.imwrite('/tmp/gray.jpg', gry)

# 画像の表示
plt.imshow(cv2.cvtColor(gry, cv2.COLOR_BGR2RGB)) # OpenCV は色がGBR順なのでRGB順に並べ替える
plt.show()
```

![Screen Shot 2022-01-24 at 11.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cdd245d5-3348-742c-a50a-7728325c28d4.png)

## エッジ検出

```py:Python
# エッジ検出
canny_img = cv2.Canny(target, 50, 110)

# 画像の表示
plt.imshow(cv2.cvtColor(canny_img, cv2.COLOR_BGR2RGB)) # OpenCV は色がGBR順なのでRGB順に並べ替える
plt.show()
```

![Screen Shot 2022-01-24 at 11.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f74a75ff-7dd6-be13-acd5-eca139324e74.png)


## サイズ変更

```py:Python
# 画像の高さ幅を指定
width,height = 60, 60
# 画像をリサイズ
resized_img = cv2.resize(target, (width, height))

# 画像の表示
plt.imshow(cv2.cvtColor(resized_img, cv2.COLOR_BGR2RGB)) # OpenCV は色がGBR順なのでRGB順に並べ替える
plt.show()
```

![Screen Shot 2022-01-24 at 11.57.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/3df6b016-700f-abdf-d667-20cb4249d678.png)

# サンプルノートブック

https://github.com/taka-yayoi/public_repo/tree/main/opencv

# 参考資料
- [Python Image Processing on Azure Databricks \- Part 1, OpenCV Image Compare – Stochastic Coder](https://stochasticcoder.com/2018/06/06/python-image-processing-on-azure-databricks-part-1-opencv-image-compare/)
- [Pythonを用いた画像処理\(openCV,skimage\) \- Qiita](https://qiita.com/taka_baya/items/453e429b466ffaa702c9)
- [OpenCVを用いて、Jupyter Notebook上で画像を表示させたい（mac） \- Qiita](https://qiita.com/narumi-github/items/63715853394bd4d110d6)


### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
django REST Framework で operationId が被らないようにする

同じ Serializer や Model を使って View を作る時、OpenaAPI のスキーマを出力させると、operationId が被る旨の警告が出る。

```
$ python manage.py generateschema > openapi.yaml

UserWarning: You have a duplicated operationId in your OpenAPI schema: retrieveWorker
```

このスキーマを他のところで読ませると、エラーになったりするので、かぶらないようにする必要があった。

この operationId の生成は、AutoSchema というデフォルトのスキーマ生成クラスが使われ、ViewのModel、Serializerから名前をとってoperationId を生成している。

https://github.com/encode/django-rest-framework/blob/master/rest_framework/schemas/openapi.py

AutoSchema のコンストラクタ引数には operation_id_base という直接名前を与えることができる。
これをAPIViewに設定する。

```python
from rest_framework.schemas.openapi import AutoSchema

class UpdateWorkerAPIView(generics.RetrieveUpdateAPIView):

    serializer_class = WorkerSerializer
    schema = AutoSchema(operation_id_base="SingleWoker")
```

AutoSchema は、`rest_framework.schemas.openapi` パッケージのを使う。 `rest_framework.schemas`パッケージにも AutoSchema はあるので注意して使わないようにする。
Javascriptの連想配列をpushするときに詰まった話

# ポイント
1. `Array.push(original)`は参照になる。
1. `Array.push(Object.assign({}, original))`を使おう。

# はじめに

次のようなプログラムを作成したときに、正しいnoが得られないトラブルが発生した。

```javascript
result = [{a: 'a'}, {a: 'b'}, ...];
  for (let i = 0; i < result.length; i++) {
  a.push(result);
  if (適当な条件) {
    b.push(result);
  } else {
    c.push(result);
  }
}

// Aに対する処理
for (let i = 0; i < a.length; i++) {
  // ...
  a[i].no = i;
}

// Bに対する処理
for (let i = 0; i < b.length; i++) {
  // ...
  b[i].no = i;
}

// Cに対する処理
for (let i = 0; i < c.length; i++) {
  // ...
  c[i].no = i;
}
```

# 原因

`Array.push`は参照になるために、すべてのArrayが同じ連想配列に書き込んだために正しい数値が得られなかった。

# 対策

誤

```javascript
Array.push(result);
```

正

```javascript
Array.push(Object.assign({}, result));
```

PUSH対象の連想配列を`Object.assign`を使用してコピーしてからpushすることで、元のデータを参照することを避けられる。
好みのアニメフィルターをつくりたいーー機械学習モデルAnimeGANv2をトレーニングする

#写真をアニメに変えるAnimeGANv2を、自分で用意したアニメデータで学習する方法です

<img src=https://user-images.githubusercontent.com/23278992/150713827-589c3d10-8bc6-41d1-b2a3-bfd08ab6f3cf.png> ![2a8196f7-a8db-45fb-96aa-29c6979f6d25.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/5c79b6a1-2c25-dcf2-36b0-072d1d8baf82.jpeg)

#アニメの好みは人それぞれ、自分の好みのアニメ風写真を生成したい

#自分でモデルを学習させよう

AnimeGANv2を自分で用意したアニメデータでトレーニングすれば、自分なりのモデルが出来上がります。

#手順

１、AnimeGANv2のリポジトリをクローンします。

２、アニメとリアルの写真をできるだけたくさん用意します。

datasetフォルダーに以下のように集めた写真を配置します。

```
dataset
 |
 |__ DatasetName
 |    |
 |    |__style
 |        |
 |        |__anime0.jpg
 |        |__anime1.jpg
 |        |__....
 | 
 |__train_photo 
 |   |__real0.jpg
 |   |__real1.jpg
 |   |__.... 
 |
 |__val
     |
     |__test_real0.jpg
     |__test_real1.jpg
```

valは、トレーニング中に変換サンプルを生成するのに使われます。


３、アニメの線をぼかします。

```python
python edge_smooth.py --dataset {DatasetName} --img_size 256
```

4、トレーニングを開始します。

```python
python train.py --dataset Own --epoch 101 --init_epoch 10　--save_freq　10
```

--epochの回数トレーニングが行われます。
1epochごとにvalの写真をモデルで変換したサンプルがsampleフォルダに保存されます。
--save_freqごとに、checkpointフォルダにモデルの状態が保存され、
トレーニングを中断した後も、checkpointの状態で続きのトレーニングができます。

**[epoch20]**
<img src=https://user-images.githubusercontent.com/23278992/150713827-589c3d10-8bc6-41d1-b2a3-bfd08ab6f3cf.png> <img src=https://user-images.githubusercontent.com/23278992/150713834-1244aaf9-62e9-4479-b382-32d077b4803f.jpeg>
まだ途中ですが、イラストっぽくなってます。

#いろいろなスタイルでためしてみよう

いろいろなアニメフィルターが作れたらおもしろいですよね。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Datastage as a Service にローカルのcsvファイルをアップロードする。

#Datastage as a Service にローカルのcsvファイルをアップロードする。

- 本記事は、IBMCloud のETLサービスであるDatastage as a Service を使用する場合に、手元のcsvファイルをアップロードする手順を記載しています。

- この記事は、[IBM Cloud Pak for Data as a Service ハンズオン資料（4.ETL編）2021年8月作成](https://qiita.com/Shumpei_Kubo/items/aad5aa18731224d3dfcb) の追加記事として記載しています。

# 1.ローカルのcsvファイルを、Datastage と同じプロジェクトにアップロードする。

- 今回Uploadするファイルの中身（ダミー個人情報）はこのような感じになっています。
![スクリーンショット 2022-01-24 11.46.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/2476ee4d-0033-944f-fd53-e1a7f88602dd.png)

- このファイル自体は、こちらのサイト(https://hogehoge.tk/) で作成したものです。

- プロジェクト画面の右側に対して、ローカルのcsvファイルをドラッグ＆ドロップします。
![スクリーンショット 2022-01-24 10.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/5027db69-a5d5-5b6a-d85b-d1539a470b14.png)

- Upload完了後、ファイルが「データ資産」の欄に表示されている事を確認します。
![スクリーンショット 2022-01-24 10.58.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/2bb2f4c4-1bb9-b756-013d-b407882fbb86.png)

# 2.Datastage 画面 でファイルをインポートする。

- Datastageデザイナーフロー画面似て、左上の「コネクター」をクリックして、「Asset browser」をダブルクリックします。

![スクリーンショット 2022-01-24 10.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/959ef384-3335-b42b-e37a-c05321ce40d6.png)

- Asset browser画面が表示されますので、今回選択したいcsvの分類である「データ資産」の右横の「＞」マークをクリックします。
![スクリーンショット 2022-01-24 11.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/8f0eee79-e1d8-b3fe-ab62-efdb8ddbe55e.png)

- 「データ資産」配下に今回Uploadしたいファイルが表示されますので、そのチェックボックスをクリックします。
![スクリーンショット 2022-01-24 11.18.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/dbae4f74-24b3-91e3-ee99-0cb6fc33e2a8.png)

- 画面右下の「追加」ボタンをクリックして資産をフロー画面に追加します。
![スクリーンショット 2022-01-24 11.21.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/20dacd47-3843-1c85-7622-62da3db256bc.png)

- Datastage 画面で、先程Uploadしたファイルが表示されていることを確認する。
![スクリーンショット 2022-01-24 11.24.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/74f7af28-80bb-ec37-5c9b-9129ac5e900f.png)

# 3.データファイルの中身の確認
- Uploadしたファイルのアイコンをダブルクリックして、画面右側に設定画面が開かれる事を確認します。
- プロパティ の箇所をクリックします。
![スクリーンショット 2022-01-24 11.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/3e1e529e-eefc-5893-6397-7a7ee30d5962.png)

- スクロールして下に行くと、「データのプレビュー」というボタンがあるので、これをクリックします。
![スクリーンショット 2022-01-24 11.42.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/9c87d7fb-3901-442f-4ee1-d2a53b210031.png)

- データのプレビューを確認します。
![スクリーンショット 2022-01-24 11.44.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/79bb0bb9-8280-8e8a-3087-1e395ad4fed1.png)
Androidアプリ開発におけるローカルデータベース〜Room覚書

## はじめに

１年以上前（2021年1月）に下記の記事を書きました。

https://qiita.com/yoshiyuki_kono/items/05496b26e1dc4eb99ddb

Realm、Couchbase Liteからはじめ、色々とマイナーなものを取り上げたものの、影響力に鑑みて、Android Roomを無視するわけには〜OSレベルの汎用性は別として〜いかないと考え、調査を始めた記録を覚書として残します。

上記記事を執筆したモチベーションは、業界の技術動向を理解した上で、Couchbase Lite/Mobileを、その中に位置付けることでした。Couchbase Mobileについては、以下参照ください。

https://qiita.com/yoshiyuki_kono/items/6a5bbad1b02196a25417

https://techbookfest.org/product/5074954942939136?productVariantID=5042865933647872

Couchbase Mobileは、NoSQL組み込みデータベースCouchbase Lite、およびCouchbase ServerとCouchbase Liteとのデータ同期を担うSync Gatewayからなります。
Couchbase Serverについては、次の拙著を紹介させていただきます。

https://www.amazon.co.jp/-/en/%E6%B2%B3%E9%87%8E-%E6%B3%B0%E5%B9%B8-ebook/dp/B09KTRXG7X/ref=sr_1_2?crid=1M9TBPNHHS12Z&keywords=Couchbase&qid=1642992094&s=books&sprefix=couchbase%2Cstripbooks%2C285&sr=1-2

## RoomとRealmの比較

https://qiita.com/messi_/items/357cbd3b97a6573b034c

>Realm
>メリット
>・速い
>動作はSQLiteよりも早く、
>・iosとAndroidともに対応

>デメリット
>apkファイルを2.5MB増加させる

>Room
>メリット
>・SQLiteデータベースにアクセスする処理がとても簡単に記述できます。
>・SQLの中に現れるカラム名のミスなどがコンパイル時にエラーとして検出できることが強みです。
>・LiveDataと一緒に使えばデータ変更を検知してUIを更新するような処理がとても簡単に記述できます。

>デメリット
>Swiftにはない

## Android Room

https://developer.android.com/training/data-storage/room?hl=ja


>Room は、SQLite 全体を対象とする抽象化レイヤを提供し、SQLite を最大限に活用しつつ、スムーズなデータベース アクセスを可能にします。

>比較的大量の構造化データを処理するアプリは、そのデータをローカルに永続化することで大きなメリットを得ることができます。最も一般的なユースケースは、関連データのキャッシュを保存することです。これにより、デバイスがネットワークにアクセスできない場合でも、ユーザーはオフラインでコンテンツを閲覧することができます。ユーザーがコンテンツに変更を加えた場合は、デバイスがオンラインに戻った後にサーバーに同期されます。

>Room を使用すれば、このような処理が自動的に実行されるため、SQLite の代わりに Room を使用することを強くおすすめします。SQLite API を直接使用したい場合は、SQLite を使用してデータを保存するをご覧ください。


https://developer.android.com/training/data-storage/sqlite?hl=ja

>注: 上記の API は強力ですが、極めてローレベルであるため、活用するにはかなりの時間と労力が必要となります。

>RAW SQL クエリはコンパイル時に検証されません。データグラフに変更があった場合、影響を受ける SQL クエリを手動でアップデートする必要があります。これは、時間がかかり、エラーも発生しやすいプロセスです。
SQL クエリとデータ オブジェクトを変換するには、大量のボイラープレート コードを記述する必要があります。

## Android Room

### Room アーキテクチャー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/484fa0d4-a5fe-19d2-1537-60c7a8331616.png)

(画像は上述の公式ドキュメント[Room を使用してローカル データベースにデータを保存する](https://developer.android.com/training/data-storage/room?hl=ja)より引用)

### オブジェクト間のリレーション

>SQLite はリレーショナル データベースであるため、エンティティ間のリレーションを指定できます。ほとんどのオブジェクト リレーショナル マッピング ライブラリにおいて、エンティティ オブジェクト間の相互参照が可能ですが、Room では明示的に禁止されています。

- 埋め込みオブジェクト
- 1 対 1 のリレーション
- 1 対多のリレーション
- 多対多のリレーション
- ネストされたリレーション

https://medium.com/androiddevelopers/database-relations-with-room-544ab95e4542

## 最後に

下記の記事には、Realmを利用した簡単なアプリのサンプルがあるので、実際に動作確認の上、Room利用版を作ってみても面白そうだと考えています。

https://qiita.com/messi_/items/357cbd3b97a6573b034c


## 関連情報

https://note.com/aihana_8/n/ndf9c067b93f2

https://qiita.com/iTakahiro/items/7e0d63140ae4dac10d18

https://qiita.com/kaleidot725/items/34f29efaeb6d836e010e
[py2rb] partition, rpartition

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# partition, rpartition (Python)
```python
s = 'a,b,c'

print(s.partition(','))
print(s.rpartition(','))
print(s.partition('/'))
print(s.rpartition('/'))
print(s.partition(''))
print(s.rpartition(''))

('a', ',', 'b,c')
('a,b', ',', 'c')
('a,b,c', '', '')
('', '', 'a,b,c')
ValueError: empty separator
```
https://docs.python.org/ja/3.7/library/stdtypes.html#str.partition

文字列を区切りますが、空文字の場合エラーとなります。
# partition, rpartition (Ruby)
```ruby
s = 'a,b,c'

p s.partition(',')
p s.rpartition(',')
p s.partition('/')
p s.rpartition('/')
p s.partition('')
p s.rpartition('')

["a", ",", "b,c"]
["a,b", ",", "c"]
["a,b,c", "", ""]
["", "", "a,b,c"]
["", "", "a,b,c"]
["a,b,c", "", ""]
```
https://docs.ruby-lang.org/ja/latest/method/String/i/partition.html

ruby でも同様のメソッドがありますが、空文字の場合の動作が異なります。
# メモ
+ Python の partition, rpartition を学習した
+ 百里を行く者は九十里を半ばとす