OmniAICreator/Qiita-1.07M huggingface dataset:
MySQL の mysqlslap と PostgreSQL の pgbench の違い


MySQL には mysqlslap、PostgreSQL には pgbench という負荷を計測するツールがそれぞれ付属しています。同じような事をやるのに微妙に動きが違い戸惑ったので記録します。

## シナリオ

* 初期化スクリプト creeate.sql でテーブルを作成する。
* クエリ query.sql でクエリを発行する。
* 同時に 10 クライアントで接続する。
* 一クライアントあたり 100 回クエリを発行する。
* このテストを 3 回行う。

## mysqlslap の場合

mysqlslap はお行儀よく自分でテスト用のテーブルを mysqlslap という schema に作りテストが終了すると自分で削除します。

```
mysqlslap  -h 127.0.0.1 -u root \
    --number-of-queries=1000 \
    --concurrency=10 \
    --iterations=3 \
    --create=create.sql \
    --query=query.sql \
    --delimiter=";"
```

* --number-of-queries にはクエリ全部の数を指定します。この場合 10 x 100 なので 1000 回です。
    * ここには落とし穴があって、--concurrency が多いと --number-of-queries の回数を超えて実行されてしまいます。
* --concurrency にはクライアントの数を書きます。
* --iterations には試行回数を書きます。

結果

```
Benchmark
	Average number of seconds to run all queries: 0.735 seconds
	Minimum number of seconds to run all queries: 0.709 seconds
	Maximum number of seconds to run all queries: 0.765 seconds
	Number of clients running queries: 10
	Average number of queries per client: 100
```

結果は --number-of-queries で指定した回数分のクエリを発行するのにどれくらいの時間がかかったか出ます。
コマンド一つで --iterations で指定した回数試行できるので、平均、最速、最遅のそれぞれ計算してくれます。

この場合 1000 クエリの 平均 0.735 seconds なので、一秒あたりでは 1000 / 0.735 = 1360 クエリ/秒となります。

## pgbench の場合

pgbench には初期化スクリプトを実行する機能は無いので自分で実行します。

```
psql -h localhost -p 5432 -U postgres -d postgres -f create.sql
```

また、試行回数の指定も無いので、3 回試行したければ自分で3回試行しても良いですが、どうせ結果は一秒あたりで出るので

```
pgbench -h localhost -p 5432 -U postgres -d postgres \
    --no-vacuum \
    --client=10 \
    --transactions=300 \
    --file=query.sql
```

* --transactions にはクライアントあたりのクエリ回数を書きます。この場合 100 ですが、複数回試行する機能がないので3倍します。
* --clients にはクライアントの数を書きます。

結果

```
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 300
number of transactions actually processed: 3000/3000
latency average = 2.495 ms
initial connection time = 106.010 ms
tps = 4007.239746 (without initial connection time)
```

結果は、一秒間に何度クエリを発行出来るかという tps で出ます。この場合 4007 クエリ/秒 なので、1000 クエリでは 1000 / 4007 = 0.250 秒 となります。 

## 違い

* mysqlslap はテーブル作成と削除も行いますが pgbench は行いません(組み込みのシナリオだけ行うようです)。
* mysqlslap の --number-of-queries は全クライアントのクエリ数ですが、 pgbench の --transactions は一クライアントのクエリ数です。
* mysqlslap の結果は試行一度あたりの経過時間ですが、pgbench の結果は一秒あたりのクエリ数です。
* mysqlslap は --iterations で試行回数を設定出来ますが pgbench には試行回数はありません。結果が一秒あたりで出るのでクエリ数を増やせば良いという事だと思います。

## 参考

* [PostgreSQL: Documentation: 14: pgbench](https://www.postgresql.org/docs/current/pgbench.html)
* [MySQL :: MySQL 8.0 Reference Manual :: 4.5.8 mysqlslap — A Load Emulation Client](https://dev.mysql.com/doc/refman/8.0/en/mysqlslap.html)
6.8 (易) ベイズ推定2

## 方針

略解とはガンマ分布のパラメータbetaの定義が違うので注意．[ウィキペディア](https://ja.wikipedia.org/wiki/ガンマ分布)を参照．

## 答案

![6. 2周目-18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/048928d2-479f-53b3-f242-8e39ecfd48ab.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
shebang とは

## 勉強前イメージ

よく言われるおまじない的なやつ！

## 調査

### shebang とは

シェバンと読み、Linux等で実行されるシェルスクリプトにおいて先頭についている `#!` を指します。
このシェバン `#!` で、コンピュータ内でパスを指定すると実行時にそのプログラムが起動されて
それ移行のスクリプトが引き渡されて実行されます。
#(ハッシュ:hash/シャープ:sharp) と ！(バン:bang) を縮めて、shebangを言われるようになりました。

例えば、以下のようなプログラムだと 「/bin/bash」 で実行されるということを明示的に記載しています。

```:test.sh
#!/usr/bin/bash
echo "test"
```

```
./test.sh
```

シェバンに以下のようにpythonを指定するとpythonでシェルスクリプトのコードを実行することになるのでエラーになります。

```:test1.sh
#!/usr/bin/python
echo "test"
```

```
./test1.sh
```

`/usr/bin/python` で実行されるので、エラーになりました。

```
[root@localhost ~]# ./test1.sh
  File "./test1.sh", line 2
    echo "test"
         ^
SyntaxError: invalid syntax
```

## 勉強後イメージ

ずっと名前知らなかった、初めて知った。
例えば、 sh test.sh をやるとするとどういう順番で読み込まれるんだろう

## 参考

- [シバン 【shebang】 シェバン](https://e-words.jp/w/%E3%82%B7%E3%83%90%E3%83%B3.html)
- [シェルプログラムの先頭に付ける#!（シバン）の意味とメリット](https://penpen-dev.com/blog/shellprogramming-shebang/)
小企業でSalesforceを導入する時やった作業メモ(1) - ライセンスと最初の作業

## この文書を作成した理由

GoogleやYoutubeで検索してみると、大手企業や大規模企業への導入時の関連記事はありましたが、一人社長の会社や、社員30人以下の小規模企業への導入に関する記事はなかったので、誰かに参考になればと思い、自分が作業した内容をメモすることにしました。

小企業へのSalesforce導入を考えている方に少しでも参考になればと思います。

この文章は、ある程度Salesforceに基礎知識（標準オブジェクト名や基本操作が分かる）を持っている方を想定して記録しています。

## ライセンスに関して

今回導入したライセンスはそれぞれ違う形でした。

企業１：プロフェショナルライセンス　x ２　＋　プレミアムサポート

企業２：エンタープライズライセンス　x １

セールスフォース会社からはもちろんもっと多いライセンスをお薦められましたが、どちらも小さい会社なので、予算などを考え、最初のスタートは最小限に抑えるように調整をしました。

## 最初にやったこと

「取引先」標準オブジェクトの項目カスタマイズ、及びCSVからのデータインポート

> 詳細に関しては後ほど追記します

「社員」カスタムオブジェクトの作成

> 詳細に関しては後ほど追記します

とりあえず以上でした。
企業で使われている文字の一覧を作成してみた（文字列変換処理のサンプル）

エンジニアというのは時に色々な検証を求められる。
例えば企業名で使われている文字列全て網羅してるのか？という問いを受けた場合どうだろうか。
今日はそんな記事です。

まずは企業名の一覧をダウンロード！ここからもらってきました。
https://www.houjin-bangou.nta.go.jp/download/zenken/index.html#csv-unicode

後は以下のコマンドだ！！

```bash
// ファイル名長いのでオリジナルファイルってわかりやうしようにしておいた。
$ mv 00_zenkoku_all_20220531.csv original.csv

// 1.1Gの文字列とみて覚悟する。
$ ll -h original.csv
-rwxrwxrwx 1 root root 1.1G  5月 31 17:57 original.csv

// 企業名の列だけ切れてるかなぁとか調べる
$ head original.csv -n100 | cut -d ',' -f 7
"釧路検察審査会"
"伊達簡易裁判所".....
"株式会社＊＊＊"

// 株式とか有限とかよく出てくる文字はさすがに多すぎるので一旦除く（処理高速化のため）
$ head original.csv -n100 | cut -d ',' -f 7 | sed -E s/[あ-んア-ン株式会社有限]//g
"釧路検察審査会"
"伊達簡易裁判所".....
"＊＊＊"

// 一旦 temp.1.csvに吐き出す。
$ cut -d ',' -f 7 original.csv | sed -E s/[あ-んア-ン株式会社有限会社\"]//g > t
emp.1.csv

// 63MB!! 力技でいけそうな臭いがしてきた。 
$ ll -h temp.1.csv
-rwxrwxrwx 1 root root 63M  6月 16 17:43 temp.1.csv

// 文字を縦に並べてsortしてuniqして　ユニークな文字列を縦に並べる。(uniq.txtに保存)
// さすがに63MBあるのでsortが結構重い！！PCスペックにもよるけど7分ぐらいかかった気がする。
// 裁判とか市町村とかも削ればよかったって後悔してももう遅い！
$ cat temp.1.csv | fold -w 1 | sort | uniq > uniq.txt

// 一旦除外してた文字を列挙(ignore.txtに保存）
$ echo "株式会社有限あいうえおカキクケコ（除外した文字）" > ignore.txt

// ignore.txt uniq.txtを連結して改行削除して完成
$ cat uniq.txt ignore.txt | tr -d "\n" > all.txt

// 5323個しか文字ないんか！（あ～んア～ン株式会社有限を含めたら＋９８個？意外と少ないのね！）
$ wc -l uniq.txt
5323 uniq.txt

```

以上！
6.7 (易) ベイズ推定1

## 答案

![6. 2周目-17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/03273c96-bc36-df7e-a5bb-48c1f466b9c7.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
無料PDF変換ワード、無料、無料、無料


PDF変換ワードの紹介：


Word形式よりも、PDFがテキストを追加したり、フォントを調整したり、PDFファイルのレイアウトを変更したりするのが難しいことがわかります。場合によっては、便宜上、PDFをWordに変換する必要がある場合があります。しかし、PDFをWordに変換する方法が分からないかもしれません。ここで、無料の簡単な変換方法を見つけました。


Geekersoftの無料PDFでwordを転送する


アドレス：https://www.geekersoft.com/pdf-to-word-online.html



PDFをWordに変換する方法

この便利な無料PDF-Wordオンラインツールを使用すると、ページ数や頻度の製限なしにPDFをWordに変換できます。あなたがしなければならないのはファイルをアップロードして、変換が終わってwordファイルをダウンロードするのを待っています。


PDFファイルをWord形式に変換し、次の手順に従います。


ステップ1：ブラウザはページを開いてファイルをアップロードします。


パソコンや携帯電話でオンライン変換ページを開き、アップロードファイルをクリックしてPDFファイルを追加することを選択します。


強烈なアンリという無料PDFはwordを回転して、無料、無料、無料

ステップ2：PDFがWordに変換されるのを待って、ローカルにダウンロードします。


変換したPDFファイルをアップロードします。オンラインツールは、ファイルを自動的にアップロードして処理するのに役立ちます。少し待って、ファイルはWordに変換されます。ファイルのダウンロードボタンをクリックして、Wordファイルをデバイスにダウンロードします。
6.6 (標準) 最尤推定4，モーメント法

## 方針

パラメータの点推定の方法の一つに，モーメント法がある．モーメント法は，「母集団分布のモーメントと標本分布のモーメントが合うようにパラメータの推定量を決める」という方法である．最尤推定が難しい場合にモーメント法が役に立つ．以下で，ガンマ分布のパラメータalpha,betaを標本から推定する問題を考える．

![知ったこと-68.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/58d4325c-99b4-07f2-1f85-8c3b921abb72.jpeg)

## 答案

![6. 2周目-15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/c813621c-b54f-506a-7e9d-13a5ba0c5ba2.jpeg)
![6. 2周目-16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/54ed8855-d38c-ecfa-d06c-2b185a715eef.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
C# ファイルの移動方法

```C#:Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

private void button1_Click(object sender, EventArgs e)
{
     string path1 = @"C:\Users\○○\Documents\test1\test1.txt";
     string path2 = @"C:\Users\○○\Desktop\test2\test1.txt";

     File.Move(path1, path2);
}
```

参考サイト
https://itsakura.com/csharp-file-create
FileMaker Pro 19.5.1 へのアップグレードの際にライセンス認証を無限に求められる件を解消

# はじめに
## 2022/07/15 追記
* 19.5.2 では 19.5.1 で起きていた以下の問題が解消されたようです
  * [Claris FileMaker Pro 19.5.2 リリースノート](https://support.claris.com/s/answerview?anum=000035931&language=ja)

> Windows: 有効な保守契約でバージョン 19.5.1 にアップグレードすると保守期限切れの無効なメッセージが表示される。

## 対象読者
* [Claris FileMaker Pro](https://www.claris.com/ja/filemaker/pro/) ユーザ
* 既にインストールされている FileMaker Pro を ver. 19.5.1 へアップグレード
* Windows ユーザ

## 確認環境
* Windows 10 Pro
* FileMaker Pro 19.4.x → 19.5.1

# 問題
* アップグレードインストール完了後に、ライセンス認証が再度求められる
  * リモート接続環境のキャプチャなので画質が粗くて申し訳ない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/f624037a-855b-6dde-7cd8-3c543f5a35e6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/ee31565a-a063-76eb-e1d6-a9119949fcee.png)

* 上記画像で `ライセンス証明書` を指定すれば、その場限りでは通る
* しかし、一度 FileMaker Pro プロセスを終了して、再度起動しようとすると、またライセンス認証の入力が求められてしまう、という現象が発生

# 解消
* Windows だと管理者権限まわりがあやしいかとアタリをつけたところ、正解
* 解消に向けての手順としては以下の通り
  * FileMaker Pro を起動する際に `管理者として実行`
    * もしショートカットから実行している場合は、ショートカットのプロパティ内で以下画像のようなチェックボックスがあるので、チェックを入れておいてから実行
  * その状態でライセンス認証をおこなう
  * 以後は通常の権限で実行しても認証を問われなくなるはず
    * ショートカットで `管理者として実行` にチェックを入れていたら、はずしておく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/62616aac-cd76-b0bc-a965-dce262e7cb92.png)


# おわりに
## 感想
* いやー…… ver.up のたびに何かしらの罠を踏んでしまう……
* 我ながら直感に優れていてすぐに気づけて助かった。
* というか、期限も切れていないのに期限切れたとか言われるの、顧客体験としては最悪な心証ではある。
Windows標準アプリ（microsoft.windowscommunicationsapps）のショートカットを作成する方法

1. [Windows] + R で「shell:AppsFolder」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/c783fe65-35ae-f63c-8fbe-975216c7562a.png)
1. ショートカット作成したいアプリで右クリックし、「ショートカットの作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/598230d2-f178-35bb-9323-53930ca44adb.png)
1. デスクトップにショートカット作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/1a0349eb-e03d-2930-a1ec-fb0dfd1afc63.png)
1. デスクトップにショートカット作成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2220364/27bedbd5-aaa7-df95-1624-75c0a866c2cb.png)
フォルダ内の.msgファイルの宛先情報を一覧で取得する

VBAで以下を実行する
フォルダパスの部分は変更する

```vb
Sub a()

Dim OL  As Object
Dim msg As Object

Set OL = CreateObject("Outlook.Application")
Set fso = CreateObject("Scripting.FileSystemObject")

For Each file In fso.getFolder("C:\XXXXXXXXXXXXXXXXXX\YYYYYYYYY\ZZZZZZZ").Files
    strFileName = file
    Set msg = OL.CreateItemFromTemplate(strFileName)
    Debug.Print "To: " & msg.To
Next

End Sub
```
selenium よく使うコード

ログイン処理

```python
def login(driver: webdriver.Chrome, username: str, password: str) -> bool:
    """
    認証情報を元にログインを実行する。
    以下の情報を返す。
    - 成功: True
    - 失敗: False
    """
    wait = WebDriverWait(driver=driver, timeout=30)

    driver.get('URL')
    wait.until(EC.presence_of_all_elements_located)

    id_form = driver.find_element_by_name('user')
    id_form.send_keys(username)

    pw_form = driver.find_element_by_name('password')
    pw_form.send_keys(password)

    pw_form.send_keys(Keys.RETURN)

    wait.until(EC.presence_of_all_elements_located)

    success_url = 'URL'

    if driver.current_url == success_url:
        return True
    else:
        return False
```
AWS リージョンとAZ 試験メモ

# リージョンとAZ

## リージョン
AWSがサービスが提供している拠点を指す。
リージョンはそれぞれ地理的に独立している。
リージョンは複数のアベイラリティゾーン（以下AZ）が含まれており、
1つのAZは複数のデータセンターから構成される。

region- AZ
      - AZ -データセンター
           -データセンター

## AZ信頼性
AZはそれぞれ地理的、電源的に独立している。AZ間は数十キロ離れて配置される。
ある程度の距離はあるが高速なネットワークで接続されている。
AZ間レイテンシ（ネットワーク遅延）は2ミリ秒以下。
電源を分けて設計し1か所の停電ですべて落ちないようになっている。

## マルチAZ
高可用性を実現する仕組み
複数のAZを利用してシステムを構築する。
DNS Slave で Master から取得したファイルを書き込めずエラーになっていたのを解決した

# 問題の発覚

DNS Slave として動作していたが、syslog を見るとエラーが出ていた

```text
Jun 16 12:52:23 XXXX named[19280]: dumping master file: /etc/bind/slaves/tmp-4FQYi7Y1cp: open: permission denied
Jun 16 12:52:23 XXXX kernel: [610023.609770] audit: type=1400 audit(1655351543.314:837): apparmor="DENIED" operation="mknod" profile="/usr/sbin/named" name="/etc/bind/slaves/tmp-4FQYi7Y1cp" pid=19280 comm="isc-worker0000" requested_mask="c" denied_mask="c" fsuid=103 ouid=103
```

確かに必要なファイルが転送されていない

```text
$ ls -l /etc/bind/slaves
合計 40
-rw-r--r-- 1 bind bind 18190  6月 16 09:53 5.168.192.in-addr.arpa
（略）
```

※当方の環境ではほかに 1.168.192.in-addr.arpa と 10.168.192.in-addr.arpa が転送されていなければならない

# 環境

## OS

Ubuntu 18.04LTS Server（14.04LTS から 16.04LTS を経てアップグレードしている）

## named

```text
$ /usr/sbin/named -v
BIND 9.11.3-1ubuntu1.17-Ubuntu (Extended Support Version) <id:a375815>
```

# 解決

ググると AppArmor の設定で named がファイルを書き込むディレクトリの制限を緩和すると出てくる。

```text
$ cat /etc/apparmor.d/usr.sbin.named
（略）
/usr/sbin/named {
（略）
  /etc/bind/slaves/** rw,
（略）
}
```

すでに読み書きは許可されているように見える。

実はロックに対しても緩和する必要があった。すでにあるファイルに対しては読み書きはできていたようだが、新規にファイルを生成するときにエラーになっていた模様。

```diff
$ diff /etc/apparmor.d/usr.sbin.named{.bak,}
20c20
<   /etc/bind/slaves/** rw,
---
>   /etc/bind/slaves/** rwk,
```

AppArmor をリロードして書き換えた設定を有効にする

```text
$ sudo systemctl reload apparmor
```

しばらくして /etc/bind/slaves を確認すると、想定していたファイルが書き込まれていた🎉

```text
$ ls -l /etc/bind/slaves/
合計 104
-rw-r--r-- 1 bind bind 17849  6月 16 14:30 1.168.192.in-addr.arpa
-rw-r--r-- 1 bind bind 18394  6月 16 14:34 10.168.192.in-addr.arpa
-rw-r--r-- 1 bind bind 18190  6月 16 11:57 5.168.192.in-addr.arpa
（略）
```

syslog のエラーも消えた🎊
ubuntu環境にpgloaderを使ったMySQLからPostgreSQLへのテーブル移行時の落とし穴

# KABOOM!!!
この記事はHowToではなく、自分が遭遇したいくつかのエラーの備忘録です。
・うまく動いていないけどエラーログが出ない
・エラーの原因が摩訶不思議
・対処法がググりにくい
などなど、pgloaderを使うにはなかなか落とし穴が多かったので
はまった箇所を共有して解決の一助になれれば幸いです。


## pgloaderってなに？
MySQLのテーブルをPostgreSQLにドサっと入れられるすごいやつです。
合計2Gぐらいのテーブルを移行しました。
Windows mac linux 様々なOSで使えます。Qiitaにも紹介記事があります。
CUIで操作しますが、オプションに-dつけるとログがいっぱいでます。基本的にデバッグモードで実行してました
VPSだとかにあるMySQLに接続して移行 とかもできるらしいですが そんなにデータ総量が大きくなかったので、
Postgresの入っているマシンにMySQLを入れて VPSで作ったMySQLのdumpファイルをインポートして localhost MySQL から localhost PostgreSQLにデータを移動しました。

## 落とし穴たち
・パスワードに特殊記号が含まれてると、うまいことエスケープしないと エラーログなしにプログラムが終了する
・MySQLのバージョンによっては、Authentication ERRORが出る
・同じバージョンでも、apt installで入れたプログラムではエラーが出る

### パスワードに特殊記号が含まれるとうまくいかない
これ最悪なのがエラーコードでません。

```
pgloader version 3.6.3~devel
compiled with SBCL 2.0.1.debian
sb-impl::*default-external-format* :UTF-8
tmpdir: #P"/tmp/pgloader/"
2022-06-16T16:04:27.005000+09:00 NOTICE Starting pgloader, log system is ready.
2022-06-16T16:04:27.010000+09:00 INFO Starting monitor
2022-06-16T16:04:27.011000+09:00 LOG pgloader version "3.6.3~devel"
2022-06-16T16:04:27.011000+09:00 INFO Stopping monitor
```
こんなかんじで、Starting monitorしたあとすぐ Stopping monitorって出てプログラムが終了します。

MySQL側で起きるエラーなので、MySQLのユーザーのパスワードをいじります。
観測した限りだと、特にアットマーク@とドット.が入ってるとよろしくないようです。
パーセントエンコーディングかエスケープ処理すればよさそうですが、
エンコードする予約文字の種類が多分違ったのか、やり方が間違っているのか(RFC3986準拠なら違うかも)上記の2文字が入っていると
パーセントエンコーディングしても同様のエラーがでてしまったので
新しいユーザーを作成して、「記号もパスワードに含めよ！」に対応するため"！"を含む英語大文字・小文字・数字を使ったパスワードを作成して回避しました。



### MySQLのバージョンによってはAuthentication ERRORが出る
ログの一部にこんなかんじのエラーが出ます
```
QMYND:MYSQL-UNSUPPORTED-AUTHENTICATION
```

上段で作成したユーザーにテーブルへの権限をGRANTします。
MySQLに入って GRANT ALL ON 'table_name' TO 'user' で権限設定後 
ALTER USER 'user' IDENTIFIED WITH mysql_native_password BY 'password' でユーザーの認証プラグインを変更します。 
(GRANTの構文がMySQLのバージョンによって変更入っているのでお気をつけください)
使うpgloaderのバージョンによってはMySQLのmy.cnfの使用する認証プラグインを書き換える必要がありますが、
3.6.3-develではmy.cnfはそのままでも大丈夫でした。

### データベースに接続できるがプログラムが動かない
これについては成功したいまでもなんでやねんの気持ちが大きいですが、
開発者の方には常に最大級の感謝を忘れておりません。

タイトル通りubuntuでpgloaderを実行しましたが、
sudo apt-cache showpkg pgloaderで最新Ver確認後、
sudo apt-get install pgloader=3.6.3-1.pgdg20.04+1 でインストールをして実験してました。
0件結果で終わってしまって困ってたところ、
たまたま、Githubのフォーラムで「ソースからbuildしたらうまくいった」との情報を発見しました。
wgetでgithubのtar.zipファイルをダウンロードして、もろもろプラグインいれつつmake、
pgloader -V の結果が
pgloader version "3.6.3-devel"
compiled with SBCL 2.0.1.debian になったら
sudo pgloader -v mysql://'mysqlのユーザー名':'特殊記号を含まないパスワード'@localhost/'DB名' postgresql://'postgresのユーザー名':'パスワード'@localhost/'DB名'
を実行すると、無事プログラムが走って移行できました。
なおビルド方式でも3.6.1だと動きませんでした。


# あとがたり
そんなこんなで私は結果的にうまくいきましたが、恐らく他の人がはまってる今回紹介できてない落とし穴もいっぱいあると思います。
qiitadepgloaderタグの記事や、pgloaderのgithubのフォーラムをあさると 解決方法が載ってたり載ってなかったりするので、他の落とし穴にハマって抜け出せた人は情報共有してもらえると嬉しいです。
Microsoft Teams と Yammer の "ここが違う" 5 つのポイント

Microsoft 365 で利用できる Microsoft Teams と Yammer ですが、「違いはなに？どう使い分けるの？」と聞かれることも少なくありません。たしかに、どちらもグループを作ることができて、チャットが出来て、ファイルも共有できてと似ているところも多くある気がします…。

しかし、使ってみると全く違うツールだと実感できるんです。じゃあ、それって何かな？といった "ここが違う" と感じるポイントを 5 つにまとめて紹介したいと思います。

# 1. チームとコミュニティ
Microsoft Teams も Yammer のグループを作成しコミュニケーションを行うことができますが、それぞれで名称が異なります。Teams では「チーム」、Yammer では「コミュニティ」です。

それぞれの違いを実感するために、少し具体的に考えてみましょう。例えば「野球チーム」とした場合、普段の練習によって力を高め、他のチームと試合を行うといった活動をイメージします。一方で、「野球コミュニティ」とした場合はどうでしょうか。必ずしも試合を行うことが活動に含まれず、好きな選手やチームの話題、観戦した試合の感想を語りあったりすることも活動としてイメージができますよね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/7c465d71-4384-ff94-0ee7-52d942a8fbb3.png)

こうした違いが Teams と Yammer との役割の違いにも当てはまるのではないでしょうか。Teams は、「何かの目的を果たすためにメンバーが協力しあい物事を進めていくために利用するツール」、一方の Yammer は、「メンバーとして達成すべき明確な目的は持たないものの、同じものに興味を持ったメンバーが集まり、情報を共有し合うために利用するのツール」と考えられます。

# 2. パブリックの扱い
Teams のチームも Yammer のコミュニティも、どちらもパブリックなものを作成することができますが、その動作には大きな違いがあります。Teams のパブリックなチームでは、チームのメンバー以外のユーザーは、検索によりチームを見つけることができても、その中でどういった会話がされているのかはチームのメンバーにならないと分かりません。Yammer のパブリックなコミュニティは、そのメンバーにならなくても、コミュニティの中を覗くことができ、どういった会話がされているのかを見ることができますし、話題に参加することもできます。興味がありずっと関りを持ちたいと思えば、そのコミュニティに参加することもできます。

Teams のチームは、会議室のようなものです。何かしらそこで議論されていることは分かるものの、実際の内容は会議室に入らないと分かりません。Yammer のコミュニティは、立ち話のようなもので、近くに寄って行くと会話を聞くことができ、興味があればその輪に入っていくことも簡単にできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/3a02998a-9cd4-4cac-7037-8fdee1a964a4.png)

よりオープンで偶発的なつながりを生むコミュニケーションには、Yammer が適していると言えます。

# 3. ユーザーネットワーク
Yammer にしか存在しない機能として、他のユーザーを「フォロー」する機能があります。自分にとって仲の良い人や、興味のある会話を多く行っている人などをフォローしておくことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/360fe0cf-78b2-f7fb-a1b0-e7e2fb798d1d.png)

他のユーザーのプロフィールページを見てみると、そのユーザーがどういったユーザーからフォローされているのか、または、どういったユーザーをフォローしているのかを見ることができます。それによってさらに、自分の興味に合う人を見つけフォローしていくことで、他のユーザーとの繋がりをネットワークとして構築することができます。

この機能は Yammer にしか存在せず、Teams と Yammer を差別化する機能面の大きな違いだと思います。

※ Yammer にはトピック（タグ・ハッシュタグ）をフォローする機能もあります

# 4. コンテンツの見え方
このように Yammer では、いろいろなユーザーやトピックをフォローしておくことで、そのユーザーやトピックに関する会話が、自分のホームフィードに自動的に集まってくるようになります。これによって、特になんら意識せずとも、自分の興味のある社内の話題を把握できるようになるわけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/8841a9cf-cded-4a96-5664-ef80cace3211.png)

Teams のチームでは、それぞれのチームの会議室を渡り歩くように、部屋を出入りしないと話題を確認することができません。その代わりとして、部屋に入ってさえしまえば、そのチームの話題に集中することができます。

# 5. 会話の種類
Teams も Yammer も、スレッド形式で会話をすることができ機能的には似ています。近ごろ Yammer が力を入れているのが、「質問」形式の会話で、これを利用することで QA フォーラムのように活用することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/dd26fff2-2d01-8bc2-8582-bfce71a649a2.png)

質問に対して役に立った返信に「投票」したり、質問への答えを「ベストアンサー」としてマーク付けしておくこともできます。これによって、あとから同じ疑問を持ったメンバーが、その回答に辿り付きやすくなります。このようにして会話の内容をあとから再利用するようにできるところが、デジタル化されたコミュニケーションの良いところだと思います。

# さいごに
さて、Teams と Yammer をそれぞれ利用していて、違いに感じるポイントを 5 つ紹介してきました。それぞれの違いの紹介でも触れてきましたが、より社内でオープンなコミュニケーションを実現できるのは、Teams よりも Yammer だと思っています。リモートワークやハイブリッドワークによって、社員同士のコミュニケーション不足なども話題になりますが、そうした組織では Teams よりも Yammer 的なコミュニケーションが求められるのではないでしょうか。そして、Yammer をより効果的に利用するためには、「フォロー」や「質問」といった機能の上手な活用がポイントとなると思います。

Microsoft Teams も良いですが、Yammer もとても良いですので、ぜひ使ってみてほしいサービスです。
Git基本コマンドとGitの色々（個人メモ用）

最近の開発ではGit利用することが多く、多分これからも増やすと、
Git経験が少ないので、この場で整理しようかな思います。

## Git基本コマンド（随時追加・修正）
```
git config -l      #git設定一覧
git init           #リポジトリを新規に作成
git clone <url>    #リポジトリをローカルにクローン
git status         #作業ディレクトリでの現在の状態確認
git add 　　　　　  #ファイルをインデックスに追加する（コミットの対象にする）
git commit         #ローカルリポジトリにコミット、[-m]によりコミットメッセージを追加
git log            #コミット時のログを表示する
git push           #リモートリポジトリにアップロードする
git pull           #リモートリポジトリの内容を取得
git reset          #ファイルをインデックスから削除し、特定のコミットの状態まで戻す
git branch         #リポジトリ内のすべてのブランチを一覧表示、
                   #<branch>により新規ブランチを作成、[-d]<branch>により指定ブランチを削除
git checkout       #作業ツリーを異なるブランチ<branch>に切り替える
git merge          #他のブランチやコミットの内容を現在のブランチに取り込む
```

## Gitの色々（随時追加・修正）
* 目的：バージョン管理（Revision control）
* 似ているツール：SVN,CVS,VSS,TFS,Visual Studio Online
 その中、SVNとGitの違い：SVNは集中管理、Gitは分散管理
* Gitの原理
![Git-core.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2646301/ec98343d-e62f-aacb-4383-ec60b25189d9.png)
![Git2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2646301/13d8cdad-a61e-9426-c166-d6c73c3ab728.png)
* .gitignore
このファイルに書かれたファイルは上から順に処理されて、Gitのトラッキングの対象外になります。
斜めに飛び出すボタンを作ろう！〜かわいいCSS〜

# かわいいWebをやりたい！

コンピュータが可愛いことをしていると嬉しくなります。  
可愛いCSSを書いてボタンを可愛くしてみます。

## ソースコード

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

## 解説

実際に飛び出す部分を実装しているのは `button` 要素に対して適応されているスタイルの部分です。
(2つのクラスはそれぞれボタンのデザインと、見やすくするためのレイアウトに使われています)
`hover` すると、`box-shadow` が右下に現れつつ、`transform: translate` で `box-shadow` の幅の分だけ
ボタン自体を左上に移動させることで、ボタンが左上に飛び出しているように見えます。

可愛いですね。

# あとがき

しばらくWebのこと勉強してきたのに記事という形でアウトプットしたことがなかったので、簡単ですが書いてみました。
誰かのお役に立てれば幸いです。
diagrams.net で構成図を作成する時に使いたいアイコンが無かった時のメモ


# TL;DR
- 以下のサイトからダウンロードしてインポートするだけ

https://github.com/mondeja/simple-icons-drawio

# 前提
- draw.ioのアプリ版を利用したやり方です

# やり方

## 1. simple-icons-drawioのURLにアクセスする
https://github.com/mondeja/simple-icons-drawio

## 2. 以下のURLからsimple-icons.xmlをダウンロードする

![simpleicon.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/8cb60713-bbdd-5a30-b7a9-424bb975a0ae.png)

## 3. draw.ioのアプリケーションを起動する
ファイル > ライブラリを開く > デバイス... を選択する

![simpleicon01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/3a07b422-37ff-72af-6862-a67cca584476.png)

## 4. 先ほどダウンロードしたsimple-icons.xmlを選択して開く
こんな感じで追加されます

![simpleicon02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198480/526a2a39-5cfd-9a85-036b-d1ef7cf8afeb.png)

以上、

# 末筆
OSSのアイコンとかシステム構成図で使いたい時になかったのでsimple iconライブラリに追加するだけで結構様々なアイコンが利用できるようになるのでいいと思いました。
nested_attributesの中のattr_accessorが時々callbackを発火させない件

# TL;DR

```rb
class User < ApplicationRecord
  has_many :comments, dependent: :destroy
  accepts_nested_attributes_for :comments, allow_destroy: true

end


class Comment < ApplicationRecord
  attribute :foo, :string

  after_validation do
    p "foo: #{foo}"
  end
end
```

```rb
User.last.update(comments_attributes: { id: 1, foo: 'Foo' })
=> true
"foo: Foo"
# この時`comment`の`updated_at`も更新されること
```

# 発端
とあるプロジェクトがコメントの添付画像の削除機能が必要でしたが、普通に`attr_accessor :img_destroy`でフラグ置きました。
ただし実装したところ、「コメント変更して、添付画像の削除はできるが、コメントを変更せず、添付画像の削除ができない」との報告が来ました。

調べたところ、`nested_attributes` の `attr_accessor` のみ変更を行う際、`after_validation`などのcallbackは実行されない現象が発覚しました。

# 対処法
いろいろ調べた結果、 Rails 5.1+からの`attribute`機能を利用すればいいとわかりました。

もしRails 5.1以下の場合、`attr_accessor`が変更される際に`attribute_will_change!`を発火させればいいです。

```rb
class Comment < ApplicationRecord
  attr_accessor :foo

  def foo_attr=(value)
    attribute_will_change!(:foo)
    self.foo = value
  end

  ...
end
```


# 参考
- [Rails4: How to trigger the callback for attr_accessor while using accepts_nested_attributes_for](https://stackoverflow.com/questions/29073686/rails4-how-to-trigger-the-callback-for-attr-accessor-while-using-accepts-nested)
- [Rails nested attributes children callbacks aren't fired](https://stackoverflow.com/questions/9358520/rails-nested-attributes-children-callbacks-arent-fired)
【HTTPメソッド】データ送信における「GET」と「POST」の違い

<h1>そもそもHTTPメソッドってなに？

この内容については、[Web開発でよく使う4つのHTTPメソッド【REST API】](https://tsuyopon.xyz/2019/01/31/understand-4-http-methods/#:~:text=HTTP%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%81%AF%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88,%E3%81%8A%E9%A1%98%E3%81%84%E3%81%97%E3%81%BE%E3%81%99%E3%80%82...)で以下のように説明されています。

>HTTPメソッドとは、「__クライアントがサーバーにしてほしいことを依頼するための手段__」となります。
例えば、「Webブラウザ」で「今見ているこのサイト」を表示する際は、次のような処理がクライアントとサーバーの間で行われています。
①Webブラウザ(クライアント)が、
②このサイトのサーバーに対して、
③「ページ情報(=HTML形式のデータ)をください」と依頼して、データを受け取りページを表示する
このとき、クライアントがサーバーに依頼(=リクエスト)を投げる際に、リクエストの種類に応じてHTTPメソッドの種類を切り換えることができます。

つまりHTTPリクエストを用いてWebサーバーに「具体的な要求内容」を伝えているものです。
なのでクライアント側の要求によってHTTPメソッドはそれぞれ変わってきます。

<h1>HTTPメソッドにはどんな種類があるのか？

ここではWEB開発でよく使用される４つのHTTPメソッドを紹介します。

| HTTPメソッド名 | 説明 |
|:-:|:-|
|  GET |  HTMLファイルや画像といったデータを取得する場合に利用する。Webサイト閲覧時において使用頻度が高い |
| POST  |  フォームに入力したパスワードといったデータを転送する場合に利用する |
|  PUT |  データ（ファイル）をアップロードする場合に利用する。Webサーバー上のファイルを置き換えることができるため、利用できないように制限されている場合が多い |
|  DELETE |  指定したデータ（ファイル）を削除する場合に利用する。PUTメソッド同様に利用できないように制限されている場合が多い |

この表を見た通り、クライアント側でWebサイトを閲覧する際に主に利用されるHTTPメソッドは、「GET」メソッドと「POST」メソッドになります。
Webサーバーが保管されているコンテンツを書き換えたり削除できたりする「PUT」メソッドや「DELETE」メソッドは、Webサイトの改ざんができてしまうため、Webサーバー側で使用できなくしている場合が多いです。

<h1>「GET」と「POST」の違いを詳しく

ここでは本題のGETメソッドとPOSTメソッドの違いを詳しく説明していきます。

コンテンツを取得する際に利用するGETメソッドは、POSTメソッドと同じようにデータを送信する際にも利用できますが、GETメソッドとPOSTメソッドで**データの送信方法**が異なります。

GETメソッドを利用してデータを送信する場合は、**URLの後ろ**に送りたいデータを付与して送ります。
URLの末尾に「？」を付けて、「パラメーター名＝値」の形式で送信します。
```ruby:例
GETの場合   /sample.com?name=sample&password=1234

```

一方、POSTメソッドを利用してデータを送信する場合は、HTTPリクエスト内の**メッセージボディ内**にデータを含めて送ります。

GETメソッドを利用しデータを送る場合は、上記のようにURLにデータが組み込まれるため、送ったデータがWebブラウザの閲覧履歴に残ってしまい、漏洩の可能性があります。
一方、POSTメソッドを利用した場合はメッセージボディ内にデータが組み込まれるため、閲覧履歴には残りません。
そのため、ショッピングサイトや会員制のWebサイトにおいてログインする際に、ユーザーIDやパスワードといったデータをWebサーバーに対して送る場合は、機密性を考慮してPOSTメソッドが利用されます。

<h1>参考文献

>[イラスト図解式 この一冊で全部わかるWeb技術の基本](https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E5%9B%B3%E8%A7%A3%E5%BC%8F-%E3%81%93%E3%81%AE%E4%B8%80%E5%86%8A%E3%81%A7%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8BWeb%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E6%9C%AC-%E5%B0%8F%E6%9E%97-%E6%81%AD%E5%B9%B3/dp/4797388811/ref=sr_1_1?adgrpid=81750527692&gclid=Cj0KCQjwhqaVBhCxARIsAHK1tiP0_USyLb31HJr9BJ1fTMuI76D7i7jyGWaZxzWzLSFo8ZSs7cKTlZIaAht9EALw_wcB&hvadid=554668762059&hvdev=c&hvlocphy=1009547&hvnetw=g&hvqmt=e&hvrand=13063177094285219049&hvtargid=kwd-811307210612&hydadcr=2964_13504221&jp-ad-ap=0&keywords=web+%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E6%9C%AC&qid=1655360485&sr=8-1)

<h1>最後に

記事の感想や意見、ご指摘等いただけると助かります。
最後までご覧いただき、ありがとうございました。
6.5 (易) 最尤推定3

## 答案

![6. 2周目-14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/a7fd492c-4890-a5bd-eaa2-e8b83511cbf2.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
最近見たダメなフローチャートの書き方

最近フローチャートをよく見る業務がありまして、その中でもこれはまずいのでは?と思うようなものを書き出してみました。
ただ、特殊な場合(言語によるもの、システムの特性等)ではこの限りでないことがあります。

※図はかなり簡略化しております、ご了承ください。

# 1.終点が複数ある

![F01-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/93b841c9-9880-0ef0-a219-bae021caed24.png) 
###### 図.1-1


まあ、複雑なフローチャートの場合はありかもですが、基本終点１つにまとめてください。
![F01-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/864f00ae-8acd-786d-6945-213cc22322a8.png)
###### 図.1-2

ログを頼りに終点から操作をたどっていこうとした場合どのルートを通ってきているかがわかりにくいです。

# 2.双方向矢印
![F02-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/286a6a52-187e-ea39-e0b4-fd0254a4c260.png)
###### 図.2-1

言いたいことはわかりますし、基本設計書レベルであれば許されるかもしれません。
ただ、この書き方ですとどちらが先に送るかがわかりませんので、詳細設計書ではNGです。

この場合はA処理の途中でB処理を行いA処理に戻るとのことだったので、処理を見直しA処理をA'処理とA''処理と分割すれば順次処理にできます。
![F02-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/6d98625b-1dae-e5fa-0079-229e3bfd5718.png)
###### 図.2-2

# 3.いきなり分裂
![F03-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/c2978b0d-7140-b7e9-6c85-45361d0cf63c.png)
###### 図.3-1

詳細設計書でこれはどう意味なんだろうか…

以下のどちらかが考えられます。
・実はさらに条件があって書き忘れていただけ
→条件の追記お願いします…
![F03-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/f419b1be-4266-8f47-de05-0dbb2a2f71f0.png)
###### 図.3-2

・両方の処理を同時に行いたい
→同時、とはいえプログラム記載上はどちらかが前になるはずです。
![F03-3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567450/d86dc6f7-a20f-533d-c729-c2e5b5409dc0.png)
###### 図.3-3

---

今回はなかったですが…
上から下(および左から右)に記載していないとかもできれば避けた方がよい書き方ですね。
対象の文字列から指定した文字を取り出すscanメソッド

対象となる文字列や、文字列を代入した変数から指定した文字を取り出し、その数を出力する方法を記述していきます。

```
comment = "great good bad good good"
```
例として上記のような形でcomment変数に入ったgoodの数を知りたい時は次のようにscanメソッドが使用できます。
```
comment.scan("good").length

=>3
```

scanメソッドは文字列を配列の形で取り出します。
```
comment.scan("good")

=> ["good", "good", "good]
```
なのでlengthを用いて要素の数を取り出しています。
C# bool の配列

bool の配列を作り、それらがすべて true かどうかを１行で判定する方法

```C#:Form1.cs
int i = 100;
bool[] bools = new bool[3];
bools[0] = i > 50;
bools[1] = i < 200;
bools[2] = i * 2 == 300;
bool b = bools.All(result => result == true);

if(b == true) MessageBox.Show("OK");
else MessageBox.Show("NOT");
```

出力結果：NOT
MacのFinderで権限を変更する

## 手順

①Finderでアクセス権を変更したいフォルダを検索
②フォルダ内で右クリックをして「情報を見る」を押下
③共有とアクセス権から変更することができる。

権限のエラーってちょっと「うっ。。！」と思いますが、
簡単に変更できますね！！
(むやみやたらに変更してはダメですが。。。)
C# 入力された文字の判定

①フォームにテキストボックス（textBox1）を配置する
②文字を入力する
③半角カナ（伸ばし記号、カッコ、空白含む）だけ入力すればtrue、１つでも半角カナ以外が入っているとfalse

```csharp:Form1.cs
using System.Text.RegularExpressions;

//textBox1に入力された文字が数字か判定
bool b = Regex.IsMatch(textBox1.Text, @"^[0-9]+$");

//textBox1に入力された文字が半角カナか判定（伸ばし記号、カッコ、空白も含む）
bool b = Regex.IsMatch(textBox1.Text, @"^[ｧ-ﾝﾞﾟ\-\)\(\ ]+$"); //口座名義が半角カナで入力されているか判定

```
【新規事業】課題を見つけるのに苦労した話【開発秘話】

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556658/98b18b0d-ccab-1ea1-9c02-f5557c09aa70.png)
## はじめに
株式会社マイスター・ギルド新規事業部のヒツジーです。
弊社新規事業部では、新規サービスの立ち上げを目指して
日々、アイディアの検証やプロトタイプの作成などを行っています！

新規事業立ち上げ未経験の我々メンバーは、悪戦苦闘しながら今も新規サービスの立ち上げに向けて邁進しています。
その過程をお見せすることは、なかなか価値のあることなのではないかと考えています。
他社での新規事業立ち上げはどのようにしているかは知りたいところ。けれども、リアルな情報はあまり落ちていませんから。

新規事業の立ち上げに興味ある方はぜひお読みください！
（一部フィクションが入ってます。ご容赦ください。ぺこり）

## 課題を見つける旅のはじまり
それは、まだ肌寒い季節。
新規事業部では、新規サービスの根幹とも言える「解決すべき課題」の選定のために、何度も何度も打ち合わせを繰り返していました。

ウサギー「この課題に取り組むのはどう？」

りぃ「この課題も捨てがたい」

ヒツジー「こっちもおもしろくない？」

わいわい、がやがや

繰り返される打ち合わせ。

メンバーの心の中には沸々とある疑問が湧いてきました。。

「あれ、これ、どれに取り組めばいいんや？」

打ち合わせ内であがった数々のアイデアは面白いものが多く、熱心に取り組み時間をかければ、ある程度大きな事業になるんじゃないかと思えるものでした。

新規事業部のメンバー全員がこれでいこう！と意見が一致するには、**指針や基準が必要**というところまでは認識が合いましたが、何を基準に置いたらいいのかわかりません。

そこで、経営陣に相談しました=3
（弊社の経営陣は話しやすい人たちだからね！）

りぃ「かくかくしかじかで、何を基準に置いたらいいかわかりません。。。」
社長「ふむふむ、かくかくうまうまやね。なるほど。」
　　「熱意を持てる課題に取り組みたいね！でないと、途中でくじけて続かないからね！パッション！！」
メンバー「（...パッション！！）」
ヒツジー「パッション！！（やべ、声出た）」

こうして、パッ、熱意を持てる課題に取り組もうということになりました。

## 明かされる熱い想い
後日、各自が解決したいと思っていることを発表し合うプレゼン大会をしようとなりました。
プレゼン大会でおのおのの発表を聴き、みんながもっとも熱くなれた発表の内容に取り組もうとなったのです。
（いい展開だな？）

こうして、プレゼン大会の日までに各メンバーは心の奥底に眠らせていた熱い想いや悩みを呼び起こすのでした。

。
。
。

そこで、プレゼン大会当日。

おのおの発表していきます。
熱い発表ばかりです。
聴く側も熱い眼差しを向けます。
自分も発表しましたが、あまり人に喋ってこなかった想いなので、いざ発表するとなると正直恥ずかしかったです。
ただ、新規事業部メンバーは（口には出しませんが）心理的安全性を高めようとする人が集まってますので、否定されることは全くないと安心して発表できましたね。

全員が発表を終えました。
正直、全部ええやん、全部やりたいなと内心思ってましたが、リソースが足りないのでどれかを選択する必要があります。
でも、大丈夫。熱意が持てるものを選べばいいのだから。きりっ

## ペルソナに直接インタビュー！
プレゼン大会後、最終的に
**「遠く離れた人（友人）のもとにいける、どこでもドアがほしい！」**
という熱い想いにメンバー一同共感し、これからどうしていくかを話し合っていくことになりました。

解決すべき課題はこれだ！と初めからパシっと決まっていたわけではありませんでした。
幸いメンバー内にペルソナ[^1]がいるので、インタビューをくり返すことで課題を具体的に深ぼることにしました。

「なんでどこでもドアがほしいの？」
「その人の場所にいけたら、その悩みは解決するの？」
「どういうシチュエーションでその悩みを抱くことになったの？きっかけは？」
などなど...

たくさんの質疑応答の結果、どうやら直接行きたいわけではなく、ビデオ通話時に抱える

**「リアルに会ってる時とは異なる、なんだかモヤモヤした感じ」**

を一番解決したいということがわかってきたのです。
ZoomやLineなどを使った遠くはなれた友人たちとの会話は、リアルで会って談笑していたときとは大きくギャップがあったのです。
モヤモヤした感覚というのは、
- 目が合わないので話をちゃんと聞いてもらえてるかわかりにくい
- 会話のテンポがリアルで会ったときと違う
- 画面越しで友人たちだけで会話が進むことがある
といった事象から生じる**違和感**や**疎外感**だったのです。

ペルソナへのインタビューがひと段落し、話し合いの結果、
ビデオ通話時のモヤモヤした感覚である違和感と疎外感をなくすために**一体感を出す方法を考えよう**という話に一旦落ち着きました。
（よかった、よかった）

## さいごに
トップダウンの組織ではない、横並びのメンバーが同じ方向に進むというのは、なかなか難しいものがありました。
そのために、プレゼン大会も開催し、みんなが熱意をもてる課題に取り組めるように工夫してきました。
おかげで、ちょっとずつなんとか前に進んでいっています！

この後は、
**ビデオ通話時に離れた相手と一体感を出す方法を探るために、実験してみよう！**
という話になります。

続きは、また別記事でご紹介させていただきますね。
ここまで読んでいただきありがとうございました！
めぇ〜〜〜

[^1]: ペルソナ：ユーザー中心設計やマーケティングにおいて、サイト、ブランド、製品を使用する典型的なユーザーを表すために作成された仮想的な人物像のこと
【Android】manifestOutputDirectoryでエラーが出た時の対処法

# 概要
下記のようなエラーがでたのでその対処法。
```
Could not get unknown property 'manifestOutputDirectory'
```

# 対処法
下記コードを```manifestOutputDirectory```使用部分の直前に追加
```
def manifestOutputDirectory = multiApkManifestOutputDirectory.asFile.get()
```
(もしくは、```$manifestOutputDirectory```を```src/main```に置き換える)




[参考サイト](https://stackoverflow.com/questions/64389372/could-not-get-unknown-property-manifestoutputdirectory)
Go言語のフレームワークEchoを使ってみた

# はじめに
Go言語で代表的なフレームワークEchoをチュートリアルを試してみました
環境：MacOS Monterey 12.3.1
　　　go v1.18.3

# Echoについて
Echoとは
高性能、拡張可能、ミニマリストのGoWebフレームワーク
です

https://echo.labstack.com/

・最適化されたルーター
・拡張性がある
・自動TLS
・HTTP/2
・ミドルウェア
・Data Binding
・Data Rendering
・Templates
・拡張可能

# インストール
最初に環境変数の$GOPATHを設定します
```
export GOPATH=$HOME/.go
```
※参考
https://qiita.com/yuku_t/items/c7ab1b1519825cc2c06f

下記を実行します
```
mkdir myapp && cd myapp
go mod init myapp
go get github.com/labstack/echo/v4
```

# サーバ起動
server.goというファイルを作成して下記をコピペします

```go
package main

import (
	"net/http"
	
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}

```

サーバを起動させます

```
go run server.go
```

![スクリーンショット 2022-06-16 13.52.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/e2a0338a-4782-9dd5-4b31-92332996984a.png)
上記の出力があれば下記へアクセスします。
http://localhost:1323/

「Hello, World!」と表示されれば成功
【メモ】Dockerでseleniumスクレイピング始め方

```Dockerfile:/Dockerfile
FROM lambci/lambda:build-python3.8

COPY PROJECTNAME /var/task/PROJECTNAME
COPY tests /var/task/tests

WORKDIR /opt/python/

RUN yum install -y unzip && \
    curl -SL https://chromedriver.storage.googleapis.com/2.43/chromedriver_linux64.zip > chromedriver.zip && \
    curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-55/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip && \
    unzip chromedriver.zip && \
    unzip headless-chromium.zip

WORKDIR /var/task

RUN pip install boto3 chalice selenium==3.141.0
RUN pip install requests
```

```yaml:/docker-compose.yml
version: "3"
services:
  PROJECTNAME:
    build:
      context: .
      dockerfile: ./Dockerfile
    command: python ./PROGECTNAME/setup.py test
    environment:
      - PYTHONUNBUFFERED
    volumes:
      - ./PROGECTNAME:/var/task/PROGECTNAME
      - ./tests:/var/task/tests
```

```python:/PROJECTNAME/__init__.py
```

```python:/PROJECTNAME/setup.py
from setuptools import setup, find_packages

setup(
    name='PROJECTNAME',
    version='0.0.1',
    packages=find_packages(
        exclude=['*.tests', '*.tests.*', 'tests.*', 'tests']
    ),
    install_requires=[
        'requests==2.27.1',
    ],
    test_suite='tests'
)
```

```python:/PROJECTNAME/PROJECTNAME.py
from datetime import date, timedelta
import os
import time
from typing import Dict, List, Tuple

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36'

# Chromeドライバーオプションの設定
options = webdriver.ChromeOptions()
options.binary_location = '/opt/python/headless-chromium'
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--single-process')
options.add_argument('--lang=ja-JP')
options.add_argument(f'user-agent={USER_AGENT}')

```

```python:/tests/__init__.py
```

```python:tests/test_PROJECTNAME.py
from datetime import date
from selenium import webdriver
from PROJECTNAME import PROJECTNAME
from unittest import TestCase

# テスト例
# self.assertIsInstance(r, str)


class SeleniumProject(TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome(
            '/opt/python/chromedriver',
            options=PROJECTNAME.options
        )
        self.username = ''
        self.password = ''

    def test_login(self):
        r = PROJECTNAME.login(self.driver, self.username, self.password)
        self.assertTrue(r)

    def tearDown(self):
        self.driver.quit()
```
【随時更新】RSpec でハマったエラー

### はじめに
初心者ですので、言葉足らずなところや間違えがあるかもしれません。
お気づきになりましたら、ご指摘いただけると嬉しいです。


# ログインできない

##### エラーコード
```
Failure/Error: 
expect(current_path).to eq(root_path)
          
expected: "/"
got: "/users/sign_in"
          
(compared using ==)
```
"/"に遷移しようとしたけど、結果は"/users/sign_in"ですよ。
つまり、遷移できずにログインページのままになりエラー。
##### ソースコード(一部)
```ruby:system/users_spec.rb
     #省略

      # 正しいユーザー情報を入力する
      fill_in 'email', with: @user.email
      fill_in 'password', with: @user.password
      # ログインボタンを押す
      find('input[name="commit"]').click
      # トップページへ遷移することを確認する
      expect(current_path).to eq(root_path)
```


##### エラー発生状況
ログインテストコード実行時、
ログインボタンを押す処理
↓
トップページへ遷移したことを確認する←ここで発生

##### 原因

spec/factories/user.rbに記述していた

```
password                  { Faker::Lorem.characters(number: 6, min_alpha: 1, min_numeric: 1) }
#これ↓
encrypted_password        { password }
```
が不要なコードだった。

##### 理由
**encrypted_password**はパスワードを暗号化した値が入るので、factoryでは不要。
パラメータで送られたパスワードが暗号化されていたことから、値が相違しエラーになっていたことが原因だった。




# raise Errors::InvalidHash.new("invalid hash")

##### エラーコード
```
Failure/Error: raise Errors::InvalidHash.new("invalid hash")
          
          BCrypt::Errors::InvalidHash:
            invalid hash
```

##### ソースコード(一部)
```
 # 正しいユーザー情報を入力する
      fill_in 'email', with: @user.email
      fill_in 'password', with: @user.password
      # ログインボタンを押す
      find('input[name="commit"]').click
      # トップページへ遷移することを確認する
      expect(current_path).to eq(root_path)
      # トップページにログアウトボタンがあることを確認する
      expect(page).to have_content('ログアウト')
```

##### エラー発生状況
ログインテストコード実行時、
ログインボタンを押す処理
↓
トップページへ遷移したことを確認する←ここで発生

##### 原因
bcrypt のバージョンが上がり、ハッシュ化の形式が変わったためにこのエラーが出ることや、開発途中で、パスワードが入っていない状態の User が出来てしまっている場合も考えられるそうだが、上記の"ログインできない"エラーを解決すると同時に解消。
原因が分かり次第追記予定。
CentOS 8からRocky LinuxやAlmaLinuxに移行する際の注意点

# 概要

CentOS8のEOLに際して、Rocky LinuxやAlmaLinuxに移行した人や移行しようと考えている人がいると思います。
おそらくほとんどの場合においてCentOSライクに運用できると思いますが、そうではないケースがあることがわかったので注意喚起しておきます。

# /etc/os-releaseを参照するインストーラやツール

例えばdockerのインストール時やansibleの実行時などに、/etc/os-releaseのIDが参照される場合があります。
```
Rocky Linuxの場合:
ID="rocky"
ID_LIKE="rhel centos fedora"
```
ここでID_LIKEを見て適切な動作をしてくれれれば良いんですが、IDのみを見て"unsupported disturibution"として切り捨てられる場合があります。

以下の記事時点では、dockerをスクリプトを使ってインストールしようとしたときに問題が発生したケースが紹介されています。

https://pocketstudio.net/2022/01/17/centos-stream-8-rocky-linux-almalinux/

また、ansible-core(2.12.x)でも大抵の場合は問題ないんですが、IDがメジャーどころのOSでない場合にうまく動かない場合があります（2022-05-16時点で、localに対するfirewalldの設定でエラーになる）。

# 対処方法

一時的に/etc/os-releaseのIDを"centos"に書き換えれば、大抵の場合はうまくいくと思います。

# 恒久的に/etc/os-releaseのIDを変更するのはありか？

わかりません。

# CentOS Streamがいいかも

この問題は、あらゆるサードパーティー製のツールで発生する可能性があるので、今後不要な運用コストを払いたくない場合は、CentOS Streamに移行するのがいいかもしれません。

以上。
Ubuntuでcoreファイルを見つける

## 前提

```
ulimit -c unlimited
```

とかはやっておく。 

`/proc/sys/kernel/core_pattern` はapportに書き込むようになっているので、apport.serviceがstartしているか確認する。されてなければenable/start。

## パスの候補1

上記が正しく設定されていれば、通常は以下のパスに入るらしい。

```
/var/crash/
```

## パスの候補2

自分の場合はそうならないことが多く、 `/var/log/apport.log` を見ると "executable does not belong to a package, ignoring" とかになっていて、その場合以下のパスで見つかる。

```
/var/lib/apport/coredump/
```

## 参考
* https://stackoverflow.com/questions/69951510/can-not-find-core-dump-file-in-ubuntu-18-04-and-ubuntu-20-04
* https://askubuntu.com/questions/966407/where-do-i-find-the-core-dump-in-ubuntu-16-04lts
ミニマップのスライダーを見やすくする

VSCodeの端に表示されるコード全体を縮小表示したみたいなやつ(ミニマップと言うらしい)のエディタで表示されている範囲を示す矩形(スライダーと言うらしい)が見にくかったので、その設定を変えた時のメモです。

## スライダーの背景色を変える
配色テーマによっては周囲の色に馴染んでしまって見づらいため変えます。

```json:settings.json
"workbench.colorCustomizations": {
    "minimapSlider.activeBackground": "#06034dc0",
    "minimapSlider.background": "#06034dc0",
    "minimapSlider.hoverBackground": "#06034dc0"
}
```
## スライダーを常に表示
デフォルトではホバー時に表示されますが、スライダーを介してスクロールする場合はこちらのほう良いかと思います。

```json:settings.json
"editor.minimap.showSlider": "always"
```
Mackerel で特定ホストに最近投稿されているメトリックを全部出すワンライナー

Mackerel でこのホストに投稿されているメトリック何があるかな、というのをシュッと出したいときありますよね。特にプラグイン開発してたり、AWSインテグレーションを設定した直後だったり、常には発生しないメトリックの様子を見たいとき。

[GET/api/v0/tsdb/latest](https://mackerel.io/ja/api-docs/entry/host-metrics#get-latest) を使うと、メトリックの最新の値を全部引っ張ってくることができます。メトリック名は複数渡せるので、ホストに紐づいたメトリックを一気に渡しておきましょう。HOSTID と MACKEREL_APIKEY はいい感じに設定してください。

```zsh
hostid=$HOSTID
curl -H "X-Api-Key: $MACKEREL_APIKEY" -X GET "https://mackerel.io/api/v0/tsdb/latest?hostId=$hostid&name=$(curl -H "X-Api-Key: $MACKEREL_APIKEY" -X GET "https://mackerel.io/api/v0/hosts/$hostid/metric-names"  | jq -r '.names | join("&name=")' )"  | jq .
```

こんな感じでずらっと出ます

```json
{
  "tsdbLatest": {
    "HOSTID": {
      "filesystem.disk3s1s1.used": {
        "time": 1655352000,
        "value": 25109454848
      },
      "interface.en5.rxBytes.delta": {
        "time": 1655352000,
        "value": 0
      },
      "interface.gif0.rxBytes.delta": {
        "time": 1655352000,
        "value": 0
      },
      "interface.ap1.txBytes.delta": {
        "time": 1655352000,
        "value": 0
      },
      ...
      "memory.free": {
        "time": 1655352000,
        "value": 1406883157.3333333
      }
    }
  }
}
```

メトリックが多い場合はURL長の制限に引っかかるかもしれないので適宜分割してください。

## 注
筆者は GNU coreutils を使っているので、macOS の場合は微妙にオプションが違ったりするかもしれません。
Spring Bootで相関Validationを実装する（Aは入力かつBは未入力のチェック）


## はじめに

Spring Bootを使用して、フォームの値をバリデーションしたい。ただ、単一の項目ではなく、
複数の条件を指定した相関バリデーションを行いたい場合の実装を、自作アノテーションを
用いて対応したので、その備忘録を下記に残す。

## 今回やりたい例

あるフォーム画面にて、Aは入力していて、かつBは未入力の場合をバリデーションする。

## 環境

* Java11

## 実装例

### formクラスを作成する

``` testForm.java
@Setter
@Getter
@TestValidation(targetA= "targetAName", targetBName= "targetB")
public class ProfileForm {
  private String targetA;
  private String targetB;
```

* Lombokを使用しているため、`@Setter/@Getter`を付与
* @testValidation(targetA= "targetA", targetB= "targetB")`
    * @testValidation：後記するInterface名
    * (targetAName= "targetA", targetBName= "targetB")：左辺がformのname属性で右辺がフィールド名


### 独自アノテーション用のインタフェースを作成する

```TestValidation.Java
@Documented
@Constraint(validatedBy = {TestValidator.class})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface TestValidation{

  String message() default "エラーメッセージ";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};

  String targetA();

  String targetB();
}
```

* `@Constraint(validatedBy = {TestValidator.class})`
    * 後記するバリデーションの実装クラス名


### 作成したアノテーションの実装クラスを作成する

```TestValidator.java
public class TestValidator implements ConstraintValidator<TestValidation, Object> {

  private String targetA;
  private String targetB;
  private String message;

  @Override
  public void initialize(TestValidation constraintAnnotation) {
    this.targetA = constraintAnnotation.targetA();
    this.targetB = constraintAnnotation.targetB();
    this.message = constraintAnnotation.message();
  }

  @Override
  public boolean isValid(Object form, ConstraintValidatorContext constraintValidatorContext) {

    if (Objects.isNull(form)) {
      return true;
    }

    // formから対象項目を取得
    BeanWrapper beanWrapper = new BeanWrapperImpl(form);
    String testTargetA = (String) beanWrapper.getPropertyValue(this.targetA);
    String testTargetB = (String) beanWrapper.getPropertyValue(this.targetB);

    if (StringUtils.isNotEmpty(testTargetA) && StringUtils.isEmpty(testTargetB)) {
      constraintValidatorContext.disableDefaultConstraintViolation();
      constraintValidatorContext
        .buildConstraintViolationWithTemplate(this.message)
        .addPropertyNode(this.testTargetB).addConstraintViolation();

          return false;
    }

    return true;
  }
```

* `ConstraintValidator<TestValidation, Object>`
    * 第一引数には、先ほど作成したInterface名を記述
    * 第二引数には、formが渡されるのでObject型を指定
* `BeanWrapper beanWrapper = new BeanWrapperImpl(form);`
    * 上記記述で、formから欲しい値を取得
    


以上。
走り書きなので、追記するかもしれないです。


## 参考URL
https://arakan-pgm-ai.hatenablog.com/entry/2017/04/08/003859
Raspberry Pi の設定（config.txt）

Raspberry Pi には、BIOS がないため、起動時の設定は config.txt で行います。
# config.txt
ARM CPU が初期化される前に GPU が config.txt を読み込みます。そのため、config.txt は、SDカード上のブートパーティションに、 bootcode.bin と start.elf と一緒になければなりません。
Linux から普通に /boot/config.txtとしてアクセス可能で、 編集は root 権限が必要です。SDカードでは、FATパーティションとして BOOT が見えますので、Windows などからは、テキストファイルとして参照、編集できます。
変更はを再起動した後に有効になります。 Linuxのブートの後、次のコマンドで現在有効な設定を確認することができます。 

The config.txt file
https://www.raspberrypi.com/documentation/computers/config_txt.html
PDFの線を太くする(Python)

# 線の細いPDFがたまにある
たまにあります。
元がdxfやらdwgのCAD図面な奴です

# ちょっと困る事がある
画面で見る分にはAcrobatの設定変えるだけでいいんですが、印刷するとまあ普通に全然ダメです、特に、A3のPDFで来るので、普通のA4プリンタで縮小印刷すると、まずまともに印刷できません

# なので
線を太くするものを作ってみようと思いました。巷のPythonでPDFを弄る系は殆どがテキストやイメージを抽出するものばっかりだったので、なにかの一助になればと・・・

# Python用でPDF弄るものとしては
PyPDF2 , pdfminer.sixとか色々あるようですが、PyMuPDFが使いやすそうだったので、PyMuPDFを使ってみました。

```Python:PDFlinebold.py
import fitz

path = 'MyPDF.pdf'
opath = 'outPDF.pdf'

scale = 10.0
maxlimit = 2.0

doc = fitz.open(path)

page_count = doc.page_count

for p in range(page_count):
    page = doc.load_page(p)

    for draw in page.get_drawings():
        if draw['width'] != 0 or draw['width'] >= maxlimit:
            shape = page.new_shape()
            w = draw['width']*scale
            width =  w if w <= maxlimit else maxlimit
            color = draw['color']
            closepath = draw['closePath']
            fill = draw['fill']
            for path in draw['items']:
                if path[0] == 'l':
                    shape.draw_line(*path[1:])
                elif path[0] == 'c':
                    shape.draw_bezier(*path[1:])
                elif path[0] == 're':
                    shape.draw_rect(path[1])
                elif path[0] == 'qu':
                    shape.draw_quad(path[1])
                else:
                    print(path)
            shape.finish(color=color, width=width, fill=fill, closePath=closepath)
            shape.commit()

doc.save(opath)
```
path のファイル名に使用されている線を scale 倍に太くします
maxlimit より太い線にはならないように、 maxlimitより太い線には手を付けません。
opath のPDFファイルとして出力されます

PDFの線全てではなく、必要最小限(直線、ベジエ、四角形)のみ太くします。また、色は元の線と同じ色にしますが、点線、透明度、マスクなどの情報は無くなります

また、実際は元の線を消さずに、上から書き加えています。元の線をどうやって消すのかわかりませんでした。
ですので、線を細くすることはできません

直線、ベジエ、四角形以外の線があった場合、どういうデータか表示されるので、
https://pymupdf.readthedocs.io/en/latest/shape.html
などを見て追加すればよいと思われます
SpineとLive2D、どっちを始める？

前回の記事では、SpineとLive2Dの違いを、主に運用方法からご説明しました。
今回は、アニメーションを付ける側の観点から、ご案内しようかと思います。

■イラスト主導か、アニメーション主導か
　前回、ご説明したとおり、Live2Dは横を向いた顔、上を向いた顔、目を閉じた顔、右に傾いた姿勢、左に傾いた姿勢などを登録し、それぞれのパラメータを、調節してポーズを作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1781010/0507d771-3241-3ac4-bb67-d1d422cef443.png)

この際に、若干の絵心を必要とします。筆者はこれが壊滅的に下手でして、Live2Dのセットアップは諦めました……。Live2Dが上手い人は、絵も上手な人が多いと感じます。

　Spineは、ボーン制御です。3Dモデルと同じ手法ですね。弊社、株式会社Artnerも元々はMAYAを使って、3Dアニメーションを制作を主な業務としていました。Spineによるアニメーションも、基本は同じなため、3Dのアニメーターが、そのままSpineでのアニメーション制作を行っています。絵の苦手なスタッフも居ますが、絵心よりは物体の動きに対する理解度というか、自然な物体の動きを想像出来るイメージ力が必要とされている気がします。

　立体表現するには、画像を動かしながら、凹んで見えるところのウェイトを増し、膨らんで見えるところを削る、という作業を行います。こちらは、絵心よりは違和感を見抜く力……イメージ力が必要とされると思います。

■まとめ
極論をしてしまうと、Live2Dは、イラストを動かすため。Spineは、アニメーションを作るためのツールです。何をしたいのかを見極めて、ツール選びをしてほしいと思います。
※個人の意見です
UnityProjectのテンプレートを作りました

## 授業用のサンプルプロジェクトを作る手間
常に使うPackageを準備したり、GitHub管理するのにgit initや.gitignoreするのが非常に手間だったので、templateリポジトリを作りました。

GitHub/TemplateRepository
https://github.com/dsgarage/TemplateRepository

## 何が入っているか？
基本的にこのリポジトリで準備されているのが、
Probuilder
Cinemachine
PostprocessingStack
PlayerController(カスタムスクリプト)
になり、サッとTPS、FPS視点のサンプルプロジェクトが作れる状態のプロジェクトが準備されています。

## 授業での使い方
基本的にはGameDesignの授業のスクリーンショットなどで使用しますが、ちょっとした実装サンプル、AssetStoreで購入したもののテストなどを行なっていきます。
用途に応じて、素材を追加したり、サンプルシーンなども追加していきます。

## URPについて
これはURPを使用する前提で準備されていますが、理由としてTerreinのサンプル素材を使うためです。
TerreinのShaderはURP前提で準備されているので、それらに対応する前提として使用しています。
Shader Graphなどもバンドルされていますが、それらを使用する意図として準備されていません。