OmniAICreator/Qiita-1.07M huggingface dataset:
VMware Fusion上でのMacOS仮想マシン構築時に40GBしか認識しない問題と対策

# 状況
Catalina以前のMacOSをVMware Fusion上で仮想マシンとして構築する時にVMware上でどれだけ大きくディスクを割り当てしてもMacOS上では40GBしか認識しない。
Big Surの場合は80GBが初期設定であるが、それ以上も割り当て可能のようである。

#原因
MacOSのインストーラで40GBだけ割り当てされ、残りは空き容量として割り当てられる。
仕様かどうかも含め詳細は現時点で不明。
現在のところ、空き容量部分を別ディスクとしても認識させる手順は確認出来ていない。

# 対策
- (事前準備)VMwareのハードディスク設定で今回は100GBを割り当てる。
![スクリーンショット 2021-01-01 0.23.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/b80bd5f6-aa77-b015-18b7-d2a4a062b67f.png)
- インストール時に**言語選択**の次の**macOSユーティリティ**画面にて、**macOSインストール**ではなく、**ディスクユーティリティ**を選択する。
![スクリーンショット 2021-01-01 0.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/c6abf821-2591-c203-b04e-e648119e983e.png)
- **Macintosh HD**で 42.61GBが割り当てられている事を確認
![スクリーンショット 2021-01-01 0.32.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/4d4c57a6-c286-6bbf-e133-673f5768b8dc.png)
- **パーティション作成**をクリックする。
![スクリーンショット 2021-01-01 0.33.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/6cfff940-2fa7-832d-c0a2-a36f01c149c9.png)
- **空き領域**の所を選択し下の[-]をクリックする。
![スクリーンショット 2021-01-01 0.35.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/1a8e2724-510c-a929-f4f9-b3dbdb4e31de.png)
- 全てが**Macintosh HD**に割り当てされるので**適用**をクリックする。
![スクリーンショット 2021-01-01 0.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/25482cc0-da51-df9a-9c91-814d99905ebe.png)
- 確認画面が出るので**パーティション作成**をクリックする。
![スクリーンショット 2021-01-01 0.39.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/5a5c7925-002e-1a5c-54e8-33ce0e978cab.png)
- VMwareで割り当てられた容量一杯に割り当てられる。
![スクリーンショット 2021-01-01 0.41.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/aa99f631-7c71-73fc-ee32-128c23e5ad0d.png)
![スクリーンショット 2021-01-01 0.42.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/d330131f-0bcd-0263-a785-9094e899f1cb.png)
- **ディスクユーティリティ**を終了。
![スクリーンショット 2021-01-01 0.45.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/d65a3826-4e88-9a48-116b-785ab6b22bd0.png)
- **macOSインストール**を選択。
![スクリーンショット 2021-01-01 0.45.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/4d1f037e-891f-ada2-6976-1b899605861e.png)
- MacOSインストーラ上でも正しく認識されている事を確認してインストールを継続する。(今回は100GB)
![スクリーンショット 2021-01-01 0.46.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/bf45f1ff-dd80-0314-e0b3-6890082afda8.png)

#注意点
ディスクユーティリティでパーティションを削除する時には**空き容量**のところを削除する。
MacOSが割り当てられているパーティションは[-]が無効になっており削除は出来なかった。
![スクリーンショット 2021-01-01 0.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/3971f28c-ed00-9399-756c-6f42a61adb3a.png)
初心者の自分がコードレビューを受けて指摘されたことまとめ

#はじめに
アプリのコードレビューを初めて受けて何点か指摘があったので次からは気を付けて行きたいといった意味を込めて指摘を受けた部分をまとめていく。
なお、指摘を受けた内容はフリマアプリの制作段階でのことである。


##REDMEでのコードレビュー
・deviseを使用したのだがencrypted_passwordというカラムを記述するのを忘れていた。

・メールアドレスは一意性という条件が設けられているにも関わらず一意性制約の記述がなかったこと。

・見本アプリではユーザーの登録時、姓、名、姓（フリガナ）、名（フリガナ）と入力欄が細かく分かれているのに姓名を一緒にしてしまっていたこと。

・誕生日カラムをdate型で年、月、日と一つにするのではなく、単に数字だからという考えでinteger型にしていたこと。

・imageの実装はactive storageを使うためREDMEに記述する必要がないにも関わらず記述していたこと。

・郵便番号はハイフンも含めるためinteger型にする必要があるのにstring型にしていたこと。

・active hashを使用時データはidで保存されるため、integer型にしなければならないのに、string型にしていたこと。

・電話番号は数字の文字列で保存するためstring型にしなければならないこと。

##新規登録・ログイン機能でのコードレビュー
・バリデーションをwith_optionsでまとめていなかったこと。可読性を上げるためにもまとめた方が良い。

・passwordでの文字数制限のバリデーションはdeviseでデフォルト設定になっているにも関わらずmaximumで設定しようとしていたこと。

・パスをprefixで記述していなかったこと。可読性を上げるためにもprefixで記述した方が良い。

・不要なコメントアウトの消し忘れ。可読性を上げるため。

##商品を出品する機能でのコードレビュー
・before_action :authenticate_user!で制限を設ける際、application_controller.rb内に記述してしまっていたこと。

・with_optionsをネストせずに分けて記述していたこと。

・300円以下は登録できないというテストコードを実装する際、境界値の299で実装した方が良いのに200で実装していたこと。

##商品の購入機能でのコードレビュー
・ @item = Item.find(params[:id])はdestroy,edit,update,showで共通なため、before_actionでまとめた方が可読性が上がるにも関わらずまとめていなかったこと。

・resources :items, only: [:index, :new, :create, :show, :edit, :update, :destroy]と全てのアクションが記述されているのに　resources :itemとまとめて記述していなかったこと。

・フォームオブジェクトの中に、:user_idと:item_idを記述していなかったこと。ユーザーのIDと商品のIDが無い場合、確実に購入できないようにするために必要。

・任意である、建物名の「建物名が空でも購入できること」のテストコードを実装していなかったこと。建物名は任意入力となっているため建物名を記入せずに購入するユーザーが居る可能性を想定したテストコードを実施する。

##最後に
改めてこのようにまとめてみると、初歩的なミスが多かったなと思った。同じミスせず効率よくコードを描けるように頑張って行きたい。
PlaygroundでSwift Packageを使う

この記事は無理やりSwiftKotlin愛好会アドベントカレンダー 2020の10日目の記事にしましたｗ

## 背景

「[Swift Algorithmsを軽く触ってみた](https://qiita.com/jollyjoester/items/4e5df18e4f5c0429ee9e)」を書く際にSwift AlgorithmsのSwift PackageをPlaygroundで動かしたかった。

Xcode12からPlaygroundでSwift Packageを使えるようになったらしいのだけどじゃっかんめんどくさかったのでやり方メモしておく

※Xcode12.3で実施。Xcodeの進化でそのうちこんなめんどい手順しなくてもイケるようになるはず。。。

# iOS Projectを作る

New -> Project...で適当にProjectを作ります。
今回はiOS->Appで作りました。
![Screen Shot 2020-12-31 at 23.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8868/7f4fe0c8-e710-4a3f-3a5b-d1fb42498a2b.png)

## PlaygroundをProjectに追加する

New -> Playground... -> iOS BlankでPlaygroundを作ります。

保存するときに先程作成したProjectに追加します。

![Screen_Shot_2020-12-31_at_23_59_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8868/4c7598e6-24d6-073c-5726-d7a17b36df5f.png)

## Swift Packageを追加する

File -> Swift Packages -> Add Package Dependency...で`https://github.com/apple/swift-algorithms`を追加する

![Screen Shot 2021-01-01 at 0.07.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8868/15dec1cd-b183-37f3-e0c4-f4ab7f920ebb.png)

## Playgroundで使う

Playgroundで下記を実装

※ここでなんでかXcodeを再起動しないとAlgorithmsを認識してくれなかった・・・

```swift
import Algorithms

let numbers = [10, 20, 30, 40]
for combo in numbers.combinations(ofCount: 2) {
    print(combo)
}
```

以上！

そのうち
1. workplaceを作る（projectじゃなくて）
2. Playgroundを追加する
3. Swift Packageを追加する
ですんなりイケるようになると嬉しいなという気持ち

## Refs

- WWDC2020 : [Explore Packages and Projects with Xcode Playgrounds](https://developer.apple.com/videos/play/wwdc2020/10096/)
「cowsay Happy New Year!」をやってみた

新年あけましておめでとうございます。
今年の干支は丑ですね。
丑といえばUNIXコマンドに`cowsay`があります。
これは牛に吹き出しで何か喋らせるアスキーアートを作るコマンドです。
例えばこんな感じの実行結果が出力されます。

```
 _____________
< Hello World! >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
```

というわけで今回はこのcowsayコマンドであれこれ遊んでみようと思います。

# インストール
UNIXコマンドなのでLinux、Macでそれぞれ使うことができます。

- Mac

```
brew install cowsay
```

- Linux

```
sudo apt-get install cowsay
```

# 使い方
先程のHello Worldを出力するときには以下のコマンドを実行します。

```
cowsay Hello World!
```

そして、コマンドの実行結果をcowsayで出力するときにはコマンドとコマンドの間に`|`を入れるとできます。

```
echo "Hello World!" | cowsay
```

# cowsay Happy New Year!
さて、本題である`cowsay Happy New Year!`をやってみます。

```
$ cowsay Happy New Year!
 _________________
< Happy New Year! >
 -----------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
```
まぁそうなりますよねｗ。
ここからさらに日付を付け加えて年賀状みたいにしてみます。
日付は`date`コマンドを使います。
そして日付を指定したフォーマットで出力させるには、以下のようにできます。

```
date "+%Y/%m/%d"
```

ダブルクオーテーションで囲んで頭に`+`をつけてあとは`%Y`のようにフォーマットを指定します。
指定するフォーマットは以下のサイトが参考になります。
https://hydrocul.github.io/wiki/commands/date.html

フォーマットさえ指定すれば、文字列の中に日付を挿入することも簡単にできます。
なので、`Happy New Year! 2021/01/01`のように出力したいときに以下のコマンドです。

```
date "+Happy New Year! %Y/%m/%d"
```

これで先程のcowsayコマンドを合わせると以下のコマンドになります。(Twitterの投稿用に時間フォーマットも指定してみました)

```
date "+Happy New Year! %Y/%m/%d %H:%M:%S" | cowsay
```

そして、2021年が始まった瞬間にツイートしたものができました。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">_____________________________________<br>&lt; Happy new year! 2021/01/01 00:00:00 &gt;<br> -------------------------------------<br> \ ^__^<br> \ (oo)\_______<br> (__)\ )\/\<br> ||----w |<br> || ||</p>&mdash; K.Miura (@k_miura_io) <a href="https://twitter.com/k_miura_io/status/1344659643071483906?ref_src=twsrc%5Etfw">December 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# まとめ
今回は丑年にちなんでcowsayコマンドを紹介しました。
UNIXコマンドにはこのようなユニークなコマンドもあるので、とても奥が深いです。
おそらくこの魅力に惹かれてUNIXコマンドにのめり込んだ方も少なくないのではないのでしょうか？
【NetAppあるある】ディスク空き容量があるのにファイル保存できない　～inode枯渇～

はじめに
-------------
NetAppを使用している方であれば、かなりの頻度で遭遇するのが、
ディスクの空き容量があるのに、ファイルの保存ができなくなるという事象。
特に、小さいサイズのファイルを多数保存している場合に発生しやすいですね。
ふと忘れてしまいがちなinodeの枯渇・・・
そのinodeの枯渇が発生した場合の対応について記載します。
※NetApp ONTAP 9.6で確認をしております。

実行コマンド
----

### inodeの利用状況確認
以下のコマンドを実行し、結果表示の「%iused」が「100%」となっている領域を確認します
※このボリュームがinode拡張対象となります。

```
df -i
```

### inodeの上限値変更
一度拡張を実施すると縮小はできないため、サイズ拡張の目安としては、既存値の２倍程度の値を設定すると良いでしょう。

```
volume modify -vserver <vserver名> -volume <volume名> -files Inode数
```

### inode拡張後の確認
上記コマンドで設定した値になっていることを確認します。
また、「df -i」で上限値拡張したボリュームの「%iused」が100%から下がっていることを確認する。


```
volume show -vserver <vserver名> -volume <volume名> -fields files
df -i
```
Happy quantum new year !

# qiskit芸

構想10分実装10分

```python

# 5-qubitの回路
n = 5
circuit = QuantumCircuit(n)
#circuit.initialize([1, 0],0) # set explicitly an inital state as |0> = [0,1] for 0th qubit
circuit.x(0)
circuit.x(2)
circuit.x(4)
circuit.measure_all()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/8582b119-7441-bae9-aed9-ed93cfd11259.png)

```python
import datetime
dt_now = datetime.datetime.now()
print('A job was queued at ' + dt_now.strftime('%Y年%m月%d日'))

job = execute(circuit, backend, shots=8192)
job_monitor(job, interval=2)
results = job.result()
counts = results.get_counts()
plot_histogram(counts)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878664/7c989b17-3c5c-3424-6533-2da3b47e7e52.png)


```python
print('Most frequent bit strig is ...?')
year = input()
```

Most frequent bit strig is ...?
`10101`

```python
dt_now = datetime.datetime.now()
print("Happy 20{} year ! \n".format(int(year,2)))
print('Now :  ' + dt_now.strftime('%Y年%m月%d日'))
```
`Happy 2021 year ! 
Now :  2021年1月1日`

*10101 = 21 (decimal)*

# 結論
ibmqで年を越した
複数のMacで互いに相手をTime Machineでのバックアップサーバにする



High Sierra 以降のMacOSではTime Machine サーバー機能が標準で提供されている。
これを使って他のMacのTime Machineによるバックアップ先として機能する事が出来る。
このバックアップの応用として、互いに相手をバックアップ先として運用出来たので手順を公開する。

# 背景
今回の事を思いついた背景は以下のとおり。

- バックアップを何らかの形で安価に分散化出来ないか。
- 今回はRAID等は以下の理由で行なわない。
  - コントローラ等のSPoFの問題が過去のトラウマ
  - バックアップを分散させる事でHDD関連の故障リスクを分散
  - 個々のディスクはシングル構成にする事で簡易化と高速化

# 手順

## 用意するもの
- High Sierra 以降が動作しているMac
- バックアップ先としてHDDをそれぞれのMacに1台以上

## ローカルでの準備
- ローカルのディスクを接続しそのディスクをウィルス対策ソフトでの対象から除外する。
→バックアップファイルをウィルス対策ソフトの対象にするとバックアップに時間がかかったりタイムアウトする場合がある為

-  各MacにてローカルディスクにTime Machineでバックアップ設定を行なう。
-  ローカルの初回バックアップを行なう。
-  対象ディスク内に **Backups.backupdb** というフォルダが出来ており、その中にホスト名のフォルダとその下に日付のフォルダが作成されている事を確認する。
-  対象ディスクに**Backups.backupdb**とは別のフォルダを新規に作成し、そのフォルダを**システム環境設定** → **共有** で共有する。
![スクリーンショット 2020-12-31 22.52.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/9464ea54-868d-7da8-c3c3-bd2294fabf7c.png)

   - ファイル共有
   - 共有フォルダ(+で選択画面が出るので該当のディスクを選択して**追加**)
   - ユーザは任意で設定する。
-  フォルダを左クリックして**詳細オプション**を選ぶ
![スクリーンショット 2020-12-31 22.54.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/cd13cd87-07c5-c08c-861a-d06302d6d865.png)


-  **Time Machineバックアップ先として共有**にチェックを入れる。
![スクリーンショット 2020-12-31 23.59.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/aedaed36-161d-2c17-8562-b52b46ef1284.png)

-  バックアップのサイズを制限したい場合は**バックアップのサイズを制限**にチェックを入れ、GB単位で指定する。
-  **OK**を押す

## リモートでの設定
-  **システム環境設定** → **Time Machine** を開く
-  **バックアップディスクを追加/削除** をクリックする。
-  **利用可能なディスク**に今回共有されたディスクが表示されているのを確認して選択する。
![スクリーンショット 2020-12-31 23.03.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99584/b987b851-5c16-b42b-a40c-830ee6ad4a40.png)


-  今迄1つだけのTime Machineを設定していた場合は「**バックアップ作成に〜を使用するのを停止して、代わりに〜〜を使用しますか?それとも両方にバックアップを作成しますか**」という表示が出るので**両方を使用**をクリックする。
-  リモートでのアクセスで使うユーザとパスワードを指定する。

この設定を行う事でそのとき利用可能なディスクにバックアップされる。1台に集中するのではなく、指定されたディスクに順次バックアップされていく。
また**バックアップを自動生成**のオプションを外し手動で行う運用でも可能。

これを相互で行う事で互いに自分のローカルディスクと相手のリモートディスクの両方にバックアップが保存され分散して管理する事が出来る。
これによりもし片側のMacのバックアップ先ディスクが破損しても相手のディスクで2台共Time Machineで復旧する事が出来る。
また他のMacからのバックアップ先として今回設定した両方のMacを指定する事も可能。

# 注意点
- 初回バックアップの時にはウイルス対策ソフトによる保護を無効にする。特にESETではバックアップに大抵失敗する。
- 初回バックアップでは転送量も多く時間がかかる事から有線LANの使用をお勧めする。
- 2回目以降はバックアップサーバ側も無線LANでの運用も可能。

# 懸念点
容量が一杯になったときの制御を考えるとローカルのバックアップとリモートのバックアップとでパーティションを分けてそれぞれでバックアップした方がいいか?
Re-entrancyの解析手法の紹介

# はじめに
先日開催された [The IEEE Blockchain-2020](http://www.blockchain-ieee.org/)にて、Ethereum Smart Contractの脆弱性であるRe-entrancy の解析手法についての論文が採択されたので、ざっくり概要を書いてみようと思います。

これは[RA(Re-entrancy Analyzer)というツールとして公開されています](https://github.com/wanidon/RA/)。
また[arXiv](https://arxiv.org/pdf/2007.01029.pdf)でも論文が公開されています。


# 超概要
解析手法を3行でまとめてしまうと
1. コードをシミュレートして
2. ただの関数呼び出しの実行経路とRe-entrancy攻撃による関数呼び出しの実行経路を抽出して
3. 両者を比較
です。
両者に差異がなければRe-entrancyなし、差異があればRe-entrancyありです。

# Re-entrancyとは
Ethereum Smart Contractの最も代表的な脆弱性で、不正な関数の再帰呼び出しを引き起こします。Ethereum史上最大の事件"The DAO"では、この脆弱性を突くことでコントラクトの送金処理が繰り返し実行され、莫大な被害が発生しました。
[Ethereum Smart Contract Best Practices](https://consensys.github.io/smart-contract-best-practices/known_attacks/#reentrancy-on-a-single-function)に掲載されているコード例が以下です。これは銀行の役割を持つコントラクトの通貨の引き出し処理を行う関数を想定しています。

```solidity
// INSECURE
mapping (address => uint) private userBalances;

function withdrawBalance() public {
    uint amountToWithdraw = userBalances[msg.sender];
    (bool success, ) = msg.sender.call.value(amountToWithdraw)(""); // At this point, the caller's code is executed, and can call withdrawBalance again
    require(success);
    userBalances[msg.sender] = 0;
}
```

攻撃のポイントをまとめるとこんな感じ。

- ユーザーの残高をリセットする(最終行)前に送金処理を行なっている(下から3行目)。
- Ethereumにおいて、コントラクトによる他のコントラクトへの送金と関数呼び出しはどちらもコントラクト呼び出しであり、同一である。
- 関数呼び出しの際に指定した関数が存在しない場合、fallback関数という名無しの関数が実行される。
- 普通の送金処理では呼び出す関数を指定しないため、fallback関数が実行される。
- 攻撃者は、自分が用意したコントラクトのfallback関数の中で被害者コントラクトの関数withdrawBalanceを呼び出す。

以上より、ユーザーの残高がリセットされる前に送金処理が再帰的に実行され、被害者コントラクトがもつ暗号通貨が吸い尽くされてしまいます。

# シンボリック実行(コードのシミュレート)
コードのシミュレートには、シンボリック実行(symbolic execution)という手法が用いられます。
これは、引数のようなコード上では不定な値を"シンボル変数"という任意の値を表す変数として表現することで擬似的な実行を行うものです。シンボリック実行によって、プログラムが取りうるあらゆる状態を網羅的に探索することができます。

RAでは、SolidityではなくEVM(Ethereum Virtual Machine)の命令をシンボル変数を処理できる形で実装することでコントラクトのシンボリック実行を可能にしています。

# 経路条件式(実行経路)
経路条件式(path condition)とは、プログラムがある状態に至るまでに満たされる必要のある条件式です。
例えば以下のようなpythonコードがあるとします。

```python

if 0 <= a:
    return 1
else:
    return 0
```

このコードの経路のイメージ図は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271851/76784259-0f72-5a89-d0b7-0b857c46e3ab.png)

プログラムの先頭は必ず実行されるので、初めの経路条件式は恒真です。
return 0 の行に到達するにはa < 0 である必要があるのでこれがこのブロックの経路条件式です。またreturn 1してるブロックに到達するには0 <= aである必要があり、これがこのブロックの経路条件式となります。

このように、条件分岐が増えるにつれ経路条件式が複雑になっていきます。

# 経路条件式の比較
Re-entrancyの検出には、通常の実行の際の経路条件式とRe-entrancy攻撃が発生した際の経路条件式を比較します。両者のイメージは以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271851/badac45a-bf85-ec53-d829-b8f63c0a8e54.png)

左が通常、右がRe-entrancy攻撃です。右の攻撃コントラクトでは単純な関数呼び出しのみを行います。そのためRe-entrancyを持たない関数の場合、左と右の結果は一致します。Re-entrancyを持つ場合、関数呼び出しが成功する際に満たされるべき条件が通常の関数呼び出しと異なるため、最終的な経路条件式が左右で異なります。厳密にはプログラムの終端状態は当然複数あり、それぞれが経路条件式を持つので、左と右で経路条件式が恒等式となるようマッチングできるかで一致判定を行います。

# 余談1
これは実は私の学生時代の研究です、えへへ
# 余談2
久々にコードをリファクタリングしてgithubにプッシュしたら完全に赤の他人のアカウントでコミットされてしまいました。こんなことあるんでしょうか。気持ち悪すぎます。過去のコミットを消しても消えません。助けてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271851/773bf0a2-002a-abc4-c739-ffefb474a281.png)
『OpenCVによる画像処理入門』1章-3章

[『OpenCVによる画像処理入門』](https://www.kspub.co.jp/book/detail/1538290.html)を読んでまとめる。

# 第1章：画像処理とOpenCV

・コンピュータの高性能化により、画像処理技術を使ったカメラシステムが普及しつつある。
　（例：Google翻訳、SNOW、車のバックカメラ、ドライブレコーダーなど）
・人は、視細胞が光を感じることによって脳に信号が送られ、3種類の電気信号の強度比率で色を認識している。
・画像処理(image processing)は、与えられた画像を処理して出力すること。
　一方、コンピュータビジョン（以下「CV」）は、画像を元に撮影対象を認識したり判別したりして、データ出力すること。
・OpenCVは画像処理やCVに関するアルゴリズムを含むオープンソースのライブラリ。C、C++Python、JAVAで利用できる。

# 第2章：OpenCVの導入
本および[この記事](https://qiita.com/koteko/items/60936f34f21d7decf0b5)にしたがっていけばインストールできるので省略。

__注意点（本との相違点）__
・OpenCVのバージョンが本では「3.2.0」だったが何となく「3.4.1」にした。問題は今のところなし。
・本ではVC14だったが、VC15を使用した。
　VisualStudioのバージョンが、2015→VC14、2017→VC15 を使う必要があるらしい。重要。
・p.17で追加の依存ファイルとして、本に書いてある「opencv_world320.lib」が存在しない。
　「opencv_world3413.lib」というファイルがあるので代わりにこれを設定する。


# 第3章：画像入力
## 入力装置
物体からの反射光をデジタルデータ（画像）として入力する装置は、デジタルカメラとイメージスキャナの2種類がある。

__デジタルカメラ__
動く被写体を極めて短い時間（数1000分の1秒）で切り取り、データ化する。
被写体のデータ化を連続的に行うと、動画を取得することができる。

__イメージスキャナ__
印刷された文字や絵を固定した状態で、イメージセンサが移動（走査）しながら時間をかけて取り込み、データ化する。
デジタルカメラのイメージセンサが2次元（平面）的に受光素子を配置いているのに対し、イメージスキャナのリニアセンサは1次元（線状）的に受光素子を配置している。センサ自体が移動することで2次元の画像として取得することが可能となる。

## 色空間 [^1]
[^1]: 色を数値の組み合わせによって表現するための方法を色空間と呼ぶ。JPEGなどの「画像形式」と、この「色空間」を区別しておく。
イメージセンサを用いてカラー画像を取得するためには、カラーフィルタによって色の三原色（赤、緑、青）に色分解を行い、それぞれの色成分の強度を取得しなければならない。色情報を表す代表的なフォーマットとして、__RGBフォーマット__と、__YUVフォーマット__がある。

__RGBフォーマット__
赤成分、緑成分、青成分を、それぞれのエリアイメージセンサで受け取り、画像データを生成する方法

__YUVフォーマット__
色情報と輝度信号(Y)、輝度信号と青色成分の差(UまたはGb)、輝度信号と赤色成分の差(VまたはCr)の組み合わせで表す方法。
人が敏感に感じる輝度信号と、そうではない色差信号に分けて色情報を再現している。
YUVのどこに情報量を多く持たせるかによって、YUVxyzという形式が決まる。
例えば、輝度に4ピクセル、色差に1ピクセルずつもたせるフォーマットは、YUV411と表現される。
Elmのモデル設計に失敗して学んだこと

年末なので、過去のPRを振り返って、自分なりに学びがあったElmのモデル設計を記事にしてみようと思います。
同じような仕様や、今後設計を考える上で参考になれば嬉しいです！
当時まだまだエンジニアになりたての時に書いていたコードなので、至らないところも多いと思いますがご容赦ください。

# 作った機能
チュートリアル機能

# 簡単な仕様
- 各項目がどれくらい完了しているかによってviewが異なる。(順不同)
- 全ての項目が完了しているかどうかによってviewが異なる。
- チュートリアルをそもそも表示しない対象が存在する。
- 各項目のステータスの状態によってviewが異なる。
    - 「完了・たった今完了・未完了」が存在。

# 初めに作成したModel
`{isDoneHoge : Bool, isDoneFuga : Bool, ...}` のように、各項目が終了しているのかどうかの状態をそれぞれ、フィールドとして持つのではなく、カスタムタイプをうまく活用したいという思いで設計を目指しました。

```elm
type alias Model =
    { tutorialStatus : TutorialStatus
    }


type TutorialStatus
    = NoTutorial
    | Tutorials Profile Post Edit Save


type Profile
    = ProfileCompleted
    | ProfileJustCompleted
    | ProfileNotCompleted


type Post
    = PostCompleted
    | PostJustCompleted
    | PostNotCompleted

type Save
    = SaveCompleted
    | SaveJustCompleted
    | SaveNotCompleted

```
(今改めて見るとほんとにいけてないですね。。。)
実装中に無理やりなパターンマッチが生じてしまう箇所もあり、違和感を感じていたものの、Modelを改善するというところまで自身で辿り着けなかったのは反省です。

## よくない設計だと思うポイント
***`「カスタムタイプを使う方が良い！」`***という思考が先行しすぎてて本質的には良い設計になってませんでした。
- チュートリアル項目の追加・削除といった変更に弱い。
    - modelに応じたviewを生成する際等にパターンマッチが必要になるが、変更コストが高い。
- 各項目ごとにカスタムタイプが記載されているため、共通の操作関数やview関数が作成しづらい。

# レビューを受けて改善したModel
チュートリアルの**「各項目名」**と**「(各項目の)状態」**を別のカスタムタイプで管理するように変更しました。またそうして、作成されたレコード(TutorialStatus)のリストにすることで各レコードの追加や削除への対応を簡単にし、また操作関数を適用しやすい設計にしました。

最終的にはこのサンプルのようなModelを採用しました。
やはり旧バージョンよりすっきりしていて、読みやすいし扱いやすいです。

```elm

type alias Model =
    { tutorialStatus : TutorialStatus
    }

type TutorialStatus
    = NoTutorial
    | ExistTutorials (List Tutorial)

type alias Tutorial =
    { name : TutorialName
    , status : TutorialStatus
    }

type TutorialName
    = Profile
    | Post
    | Save

type TutorialStatus
    = Completed
    | JustNowCompleted
    | NotCompleted

```

## 今思えば改善できそうなポイント
- `NoTutorial`と`ExistTutorials []`が同じ意味を表してしまう。
    -  tutorialsを`List Tutorial`に変更する。
    -  `[]`はチュートリアルが存在しない状態を表現する。

(※当時、これでは実現できない仕様があったかもしれないです)

```elm
type alias Model =
    { tutorials : List TutorialStatus
    }

type alias Tutorial =
    { name : TutorialName
    , status : TutorialStatus
    }

type TutorialName
    = Profile
    | Post
    | Save

type TutorialStatus
    = Completed
    | JustNowCompleted
    | NotCompleted

view : Model -> Html msg
view model = 
    case model.tutorials of
        [] -> 
            text "チュートリアルが存在しない。"
        missions ->
            Debug.todo "チュートリアルが存在している際のviewを記載"
```


# まとめ
- 手段の目的化を避ける。目的思考を大切に。
    - Elmのカスタムタイプは便利！ただし、何でもかんでも使えばいいというものではない。
- 一度設計したModelを崩して、再構築する決断をいとわない！
    - 違和感や、扱いにくさを感じた時点で一度Modelの設計を振り返る。
[OutSystems]Asynchronous Logging API

ログ関係のAPIとしては(System)にあるLogMessage Action (Server/Client両方のActionがあり、出力先はGeneralログ）があります。他にも、ログ出力用と思われるAPIがあるのですが、ドキュメントだけでは不明な点があったため、実際に動作させて確認してみました。

# 環境
Personal Environment(Version 11.10.0 (Build 22910))
Service Studio (Version 11.9.2)
Asynchronous Logging API (For version 11.10.0.)

# Asynchronous Logging API
OutSystemsが提供するAPIの1種で、AsynchronousLogging Extensionに含まれる、LogError/LogRecord/LogRequestEventの3つです。

ドキュメント：[Asynchronous Logging API](https://success.outsystems.com/ja-jp/Documentation/11/Reference/OutSystems_APIs/Asynchronous_Logging_API)
以下の記述で出てくる「Request_Key」については、以前[Request_GetKeyでログの関連付けを見られる](https://qiita.com/jyunji_watanabe/items/fd544ed1d62179454a08)で書きました。

このAPIは、非同期で実行（キューを利用）されます。

# LogError
ドキュメントによると、
> エラーをデータベースに非同期で挿入します。エラーはメッセージキューに保持され、しばらくしてからデータベースに一括挿入されます。

これだけだと、「エラー」とはどのようなエラーで、「データベース」とはどのデータベースのどのEntityのことか？　記述が曖昧ですね。

実際にプログラムを書いて試してみると、行き先は名前通りErrorログでした。つまり、「Service Center > Monitoring > Errorsで閲覧可能なあのエラーログを非同期に出力する機能」、でした。

実際に実行したActionのパラメーター（左）と実行したときにService Centerのエラーログの詳細画面に出力された内容（右）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/4d0e3305-b041-6dc5-dea1-947f3727b217.png)

# LogRecord
ドキュメントによると、
> レコードをデータベースに非同期で挿入します。レコードはメッセージキューで保持され、しばらくしてからデータベースに一括挿入されます。

とLogErrorと似たような記述ですが、こっちで記録するのはエラーではなく「レコード」。よって任意のEntityに出力できそうな気配を感じます。

簡単なEntityを定義して実験してみましょう。
まず、Entityを

- Entity名：LogRecordSample
- Attribute
    - Message (Text)
    - Instant (Date Time)
    - Severity (Integer)

と定義し、この型の変数をパラメータに渡してLogRecordを呼んでみます。
定義したEntity型の変数を用意し、適当に編集（画像の上）し、実行後にView Dataした（下）もの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/45bc9770-184d-ce94-4310-40de49e55362.png)

なお、LogRecordはパラメータの型がObjectであるため、ToObject(Entity型変数)のようにして呼びます。

Forumの投稿ではEntity型ではうまく行かないような記述が見られたのですが、私が試して時点では出力できました。

結果としては、この機能は「任意のEntityに対し非同期にレコードを追加できる機能」ですね。

## LogRecordの後に例外が発生したら？
となると、気になるのは、ログ出力がトランザクションと運命をともにするか（ロールバックしてもログは記録されるか）？　ですね。しないのであればエラー処理時にもログを記録する機能として望ましい（キューが死んだらだめなので100%ではない）。

以下のように、同じ処理の最後をEndでなく、Raise Exceptionに変えてみました（OutSystemsでは、Handleされない例外で終わった通信の最後で自動的にロールバックされます）。ちゃんとログ出力されていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/f4fb28c0-3596-7a74-43b3-81b6e547f622.png)

# LogRequestEvent
これはどうも、Production環境でないと使えない機能に関連していそうなので、私のPersonal Environmentでは確認できないです。
roman numerals

![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 

# 問題文

アラビア数字 (arabic numerals) を受け取って, ローマ数字 (roman numerals) を返す method を書け.
<https://qiita.com/daddygongon/items/2d0a73a51ddab2d9da1b>

# 解法(途中までしかできていない)

まず単純に1~5までを出力させてみる。

```ruby
def to_roman(arabic)
  if arabic == 1
    p "I"
  elsif arabic == 2
    p "II"
  elsif arabic == 3
    p "III"
  elsif arabic == 4
    p "IV"
  elsif arabic == 5
    p "V"
  else
    p "false"
  end
end

if $PROGRAM_NAME == __FILE__
  arabic = ARGV[0].to_i
  to_roman(arabic)
end
```

これは成功する。

次に、ループを使った形に変形する。

```ruby
def to_roman(arabic_numerals)
  arabic_and_roman = [[1,"I"], [2,"II"], [3,"III"], [4,"IV"], [5,"V"]]

  arabic_and_roman.each do |arabic, roman|
    if arabic_numerals == arabic
      return roman      
    end
  end
  puts(false)
end
```

これも成功した。1~5以外の数字や何も入力がない場合はfalseとなる。

手作業が多いが、arabic\_and\_roman変数に、表記が変わるポイントの数字を並べることにした。

この時点では表記されていない数字はfalseになってしまうので、ifで条件分岐していこうとしたが最後までは解けなかった。

```ruby
def to_roman(arabic_numerals)
  arabic_and_roman = [[1,"I"], [4,"IV"], [5,"V"], [9,"IV"], [10,"X"], [40,"XL"], [50,"L"], [90,"XC"], [100,"C"], [400,"CD"], [500,"D"], [900,"CM"], [1000,"M"]]

  arabic_and_roman.each do |arabic, roman|
    if arabic_numerals == arabic
      return roman      
    end
  end
  puts(false)
end

if $PROGRAM_NAME == __FILE__
  arabic_numerals = ARGV[0].to_i
  puts(to_roman(arabic_numerals))
end
```

------
 - **source** ~/grad_members_20f/members/o-michika/roman_numerals.org
MacOS BigSurの「Audio Midi設定」に表示される[！]マークについて調べた話

# BigSur 使ってますか？

Macファンのみなさま、MacOS BigSur 使ってますか？
BigSur を使っていて、「Audio Midi設定」画面（「オーディオ装置」画面）に表示される [！]マークに「なんだこれ？」って思ったかたはおられませんか？（下記の赤丸）
私は思いました。「なんかエラー出てる？」って思っちゃいました。^^;
![スクリーンショット 2020-12-31 22.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314375/c7062d5c-ca59-d82a-d9da-2f90c54175d4.png)

# わからないのでAppleサポートへ
それで、まぁまぁ頑張ってググったり Bingったりしてみたんですが 答えには辿り着けずで。
使用上ではなんの問題も出ていなかったんですが、やっぱり気になるなぁ・・ということで、めったに利用しない「Appleサポート」に聞いてみたところ、[!]マークはエラーの表示ではなく、**「この装置を通して通知音とサウンドエフェクトを再生」するという、設定フラグだった**・・ということが判明したのでした。
（サポートの方も、はじめは「なんです、それ？」っていう勢いだったんですけど、いろいろ確認してくださって無事に解決しました。ありがとうございました。）
「オーディオ装置」画面左下の歯車マークをクリックすると、下のようなメニューが表示されて、どの装置で通知音などを表示するかを選べるのだ・・ということでした。
![スクリーンショット 2020-12-31 22.29.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314375/9132b3b7-14e2-8436-29e0-dcb151b6fd3a.png)

# ちなみに
MacOS Catalinaではどんなだっけ？
・・と思って確かめてみたら、↓のような MacOSマークでした。
こっちのほうが平和そうでイイなぁ・・なんて思っちゃいましたネ。^^;
と同時に、MacOSマークがまたひとつ消えてしまったんだと思うと、ちょっとだけ寂しくも感じました。
![2020-12-31 22.35のイメージ-1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314375/bc406464-fd29-413b-2aba-a5d97cf83466.jpeg)

# 結び
わかってしまえばどうってことのない話なんですが、まぁ「わかってないとき」というのは往々にしてこんなモンですよね。聞くは一時の恥・・じゃないですが、サポートに聞いてみてよかったです。
たいしたネタでもないですが、同じ疑問を持ったどなたかの助けになれば幸いです。💻
【Ruby On Rails】include?を使ってparamsの中身を検索する方法

備忘録です。


# 検索方法

```ruby
params.require(:モデル名).permit(:カラム名).to_s.include?("検索ワード")
```

to_sと書くことで、"permit(:カラム名)" のカラムに含まれたデータを文字列として扱ってくれます。


# updateできる場合の例


例①

```controller.rb

  def update
    if params.require(:fridge).permit(:icecream).to_s.include?("ガリガリ君")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

  def fridge_params
    params.require(:fridge).permit(:vegetable, :meat, :icecream).merge(user_id: current_user.id)
  end

```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"茄子", "meat"=>"牛肉", "icecream"=>"ガリガリ君"}
```

例②

```controller.rb

  def update
    if params.require(:fridge).permit(:icecream).to_s.include?("雪見だいふく")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

  # fridge_paramsは以後省略
```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"ピーマン", "meat"=>"豚肉", "icecream"=>"雪見だいふく"}
```

例③

```controller.rb

  def update
    if params.require(:fridge).permit(:meat).to_s.include?("鶏肉")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"トマト", "meat"=>"豚肉と鶏肉", "icecream"=>"ジャンボ"}
```

# updateできない場合の例

例①

```controller.rb

  def update
    if params.require(:fridge).permit(:vegetable).to_s.include?("もやし")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"ニラ", "meat"=>"牛肉", "icecream"=>"爽"}
```

例②

```controller.rb

  def update
    if params.require(:fridge).permit(:vegetable).to_s.include?("ブロッッッコリー")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"ブロッコリー", "meat"=>"羊肉", "icecream"=>"爽"}
```

例③

```controller.rb

  def update
    if params.require(:fridge).permit(:icecream).to_s.include?("ジャイアントコーン")
      @fridge.update(fridge_params) 
      redirect_to root_path
    else
      render :edit
    end
  end

```

```terminal:params
Parameters: {"authenticity_token"=>"XXX==", "fridge"=>{"vegetable"=>"じゃがいも", "meat"=>"人肉", "icecream"=>"ジャイアンとコーン"}
```

# 注意点
コントローラーで保存したい文字列を制限しているだけで、DBでの保存を弾いてくれるわけではありません。使い方には注意が必要かもしれないです。


# 参考記事
https://stackoverflow.com/questions/57625775/how-to-check-if-parameters-string-contains-a-substring
https://stackoverflow.com/questions/5629402/how-to-test-if-parameters-exist-in-rails/5629506
Baseball Savantを弄ってみた

#はじめに
MLBのあらゆるデータが凝縮されているbaseball savantを弄ってみた
https://baseballsavant.mlb.com/

#サイト構成
* illustrator
* gamefeed
* scoreboard
* probable Pitchers
* Daily Matchups
* Search
* Visuals
* Statistics

から構成されている。

#illustrator
投手・打者の投球結果を色々と可視化できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/8e2c79f2-e043-43ff-9969-a327ff00cc6b.png)
細かい条件分岐のもと、コース別投球数や打率なども表示できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/a157085b-c853-dc9b-84d2-cda0ea64ce8a.png)
投球コースだけでなく、打球結果のマッピングなども実現可能

# visuals
illustratorより動的な情報を可視化することが出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/60290aa2-8a88-c2c1-59e2-c23ea1e0ed37.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/f88a6864-b5c7-e14c-a42d-176acf0aad13.png)
例えば、sliderの文字列のところにカーソルを合わせると、スライダーのみの結果が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/388fc5df-5b40-e009-5e43-25a68c29d152.png)
その他、ドラッグした場合、その部分の情報だけが表示されるようになる。

### Pitch Arsenal
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/b6720261-7d16-e552-e25c-c239b201f26f.png)
検索した投手の球種別の投球割合、球速、変化量を左から順に示している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/54a0fa32-a42a-3e30-2180-36106a6a49d8.png)
下にある3D Pitchなるボタンを押すと、捕手視点からの投球記録を見ることができる。投球をクリックすることで、だれに投げた球なのかなど、詳細を見ることができる。

# Statistics
ビジュアル的でなく、数値で選手を分析できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307295/c995fc21-5019-6aa2-25c7-15386eb7627e.png)

右から３列は左からそれぞれ、平均打球速度、平均打球角度、バレルのパーセンテージが記載されている。これらより左にある数値は、これらトラッキングデータから導出される成績予測となる。
ページ上部にある"custom column"を選択すると、一般的な指標（打席数、打率、本塁打数など）を表示することもできる。

CreateChartボタンを押すと、選んだ指標のヒストグラムを自動で作成する。
より詳細に分析したい場合はcsvファイルをダウンロードする。



そのほかの機能はまだいろいろ試しているところ
react-id-swiperのスタイルが反映されない問題

## バージョン

swiper 5.4.2
react-id-swiper 3.0.0

## 内容

以下のように、パッケージをインストールして、テキトーにコンポーネントを作成してみた。

`$ npm i -S swiper@5.4.2 react-id-swiper@3.0.0`


```jsx
import React from 'react';
import Swiper from 'react-id-swiper';

const ImageSwiper = () => (
  <Swiper>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
  </Swiper>
);
```

このコンポーネントを表示しようとしたが、スタイルが適応されていないらしく、正常に動いていなかった。

## 解決方法

CDNからcssをインポートする。

コンポーネントに直接インポートすることはできないので、以下のように、CDNから読み込むようのcssを作成する

```css:src/assets/style/swiper.css
 @import 'https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/css/swiper.css';
```

このcssファイルをコンポーネントで呼び出す。

```jsx
import React from 'react';
import Swiper from 'react-id-swiper';
import '../../assets/swiper.css'; // 追加

const ImageSwiper = () => (
  <Swiper>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
    <div>スライドです。</div>
  </Swiper>
);
```
[Rails] 複数の情報にまとめて同じ制限をかける

この記事はRailsドキュメントを参考させていただいております。
https://railsdoc.com/validation#validates_format_of

# with_options
with_options 〇〇 do ~ endと書くことで、複数の情報に対してまとめて同じオプションを付けることが可能です。

# formatオプション
モデルのクラスの中でvalidatesメソッドを使用する際に利用できるオプションです。
**format:　{with:　正規表現,　message:　正規表現にマッチしなかった場合のエラーメッセージ}**
とすることで、特定のカラムへ正規表現を用いた制限をすることができます。

正規表現については、基本的な「これがあればとりあえず大丈夫だろう」というもの
をこちらにまとめておりますので良ければご参照ください！
https://qiita.com/teipoi/items/8a28a56bc584780b8d8a

---
下記では３つのバリデーションに「値が存在 (presence) しなければならない」という制限を設けることができています。
また、formatオプションを利用して、名前や読み仮名などについて正規表現でのバリデーションを設定しています。



```apps/model/user.rb
with_options presence: true do
  validates :name, format: { with: /\A[ぁ-んァ-ン一-龥]/, message: "is invalid.
                             Input full-width characters." }
  validates :age, format: { with: /\A[0-9]+\z/, message: "is invalid. 
                            Input half-numbers." }
  validates :nickname, format: { with: /\A[a-z0-9]+\z/i, message: "is invalid.
                                 Input half-width characters." }
end
```

---
コンパイラ 字句解析 文字読み取り

「コンパイラ 作りながら学ぶ」
中田育男 著
の、p51コードを、参考にしました、メモ書きです。

```
#include <stdio.h>
#define MAXLINE 120
// コンパイラ 字句解析 文字読み取り

static FILE *fpi;
static FILE *fpo;
static char line[MAXLINE];
static int lineIndex = -1;

char nextChar()
{
    char ch;
    if (lineIndex == -1){
        if (fgets(line, MAXLINE, fpi) != NULL){
            fputs(line, fpo);
            lineIndex = 0;
        } else {
            printf("end of file\n");
            exit(1);
        }
    }
    if ((ch = line[lineIndex++]) == '\n'){
        lineIndex = -1;
        return ' ';
    }
    return ch;
}


int main(){

    char ch;

    //ファイルを読み込みモード、書き込みモードで開く

    fpi = fopen("test.pl0","r");
    fpo = fopen("test2.pl0","w");

    //次の文字を 3回出力

    ch = nextChar();
    printf("%c\n", ch);
    ch = nextChar();
    printf("%c\n", ch);
    ch = nextChar();
    printf("%c\n", ch);
        

    //ファイルオープンに失敗した場合

    if(fpi==NULL || fpo==NULL){

        //失敗と表示し終了

        printf("ファイルオープン失敗\n");

        return -1;

    }

    //ファイルを閉じる

    fclose(fpi);
    fclose(fpo);

    return 0;

}

```
参考サイト: http://www.isl.ne.jp/pcsp/beginC/C_Language_16.html
fastaファイルのヘッダーに含まれるスペースをアンダーバーに置換する

## 背景
fastaファイルのヘッダー部分は下記のようにスペースで区切られている場合がある。見る分には分かりやすいが、ツールよってはスペース前の単語のみが認識され、ヘッダー情報の一部が失われる場合がある（blastなど）。ヘッダー情報の損失を避けるため、このスペースをアンダーバーに置換する。

```sh
head -n 2 space.fasta
>LOCUS_00010 DNA binding response regulator
TGCTTACTCTGCGTTGATACCACTGCTTAGATCGGAAGAGCACACGTCTGAATGCTTACTCTGCGTTGATACCACTGCTTAGATCGGAAGAGCACACGTCTGAATGCT
```

## 環境
PC: MacBook Pro 2020
OS: macOS Catalina (10.15.5)
shell: zsh (5.7.1)

## 方法
sedコマンドで置換できる。gオプションをつけないと最初の置換対象しか置換されないので注意。上記の場合だと、gオプションを付けない場合「>LOCUS_00010」と「DNA」間のスペースは置換されるが、「DNA」と「binding」以降のスペースは置換されない。

```sh
sed 's/ /_/g' space.fasta > under.fasta
```

## 結果
全てのスペースがアンダーバーに置換された。

```sh
head -n 2 under.fasta
>LOCUS_00010_DNA_binding_response_regulator
TGCTTACTCTGCGTTGATACCACTGCTTAGATCGGAAGAGCACACGTCTGAATGCTTACTCTGCGTTGATACCACTGCTTAGATCGGAAGAGCACACGTCTGAATGCTTACTCTGCGTTGATACCACTGCTTAGATCGGAAGAGCACACGTCTGAA
```
Swiftでオブジェクトを比較する

何回も見直してあまり頭に入っていないと感じたので、備忘録として記事にします。

## Equatableを使う
`Swift`でオブジェクトを比較するためには`Equtable`を使えば可能です。

## 使用する目的
例えば2つの引数を構造体に与えて、片方だけの引数で比較してあげたいときに有効かと思います。

## サンプル
・青のリンゴと赤のリンゴを同一のリンゴとして判定したい
・与えれる情報は、名前と色

```swift
// Equatableはオブジェクトが比較できることを保証する
struct Fruit: Equatable {
    var name: String
    var color: String
    
    // name のみの判定で結果を得たい時
    static func == (lhs: Fruit, rhs: Fruit) -> Bool {
        return lhs.name == rhs.name
    }
}

let gApple = Fruit(name: "Apple", color: "green")
let rApple = Fruit(name: "Apple", color: "red")

var result = gApple == rApple

print(result) // output: true

```

## まとめ
かなりざっくりですが、具体的な用途があれば追記したいと思います。
PyCharmでコードの品質を保つために

#この記事について
<b>対象の人</b>
☆PyCharmでPythonを使っているけど、<b>自動フォーマットを使っていない</b>人
☆Pythonを使っているけど、<b>コードチェックツールを使っていない</b>人


自動フォーマットや、コードチェックツールを使うことで
コードの品質が向上するのでぜひ設定しましょう！

そして今回はPythonエンジニアなら誰もが一度は使ったことがあるであろう
IDEの<b>PyCharmでおすすめ設定</b>を共有したいと思います！


#File Watchersをインストールする
ファイル保存時にコードのフォーマットなどを行うために
`File Watchers`プラグインをインストールする。

`Preferences > Plugin`の順番で開く。
`Marketplace`から`File Watchers`で検索してインストール。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563930/3fdb2e7d-e95a-d8bc-242c-359b86875a50.png)

インストール後は再起動する必要あり。

#autopep8
Pythonのコードを自動的にPEP8に準拠したフォーマットにしてくれる。

```py:インストール
pip install autopep8
```

`Preferences > Tools > File Watchers`を選択。

＋ボタンを押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563930/3dd07a09-0ed7-2f19-ea43-0b5d80d7d6cc.png)


Name: 設定したい名前(autopep8)
File type: Python
Scope: Current File
Program: `/$PyInterpreterDirectory$/flake8`
Arguments: `--in-place --aggressive --aggressive $FilePath$`

OKからのAPPLYで適用完了！

#flake8

Pythonのコードチェックツール

```py:インストール
pip install flake8
```

`Preferences > Tools > File Watchers`を選択。

＋ボタンを押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563930/746c4b7c-ccc3-c5de-d745-bfe37efba0d8.png)



Name: 設定したい名前(flake8)
File type: Python
Scope: Current File
Program: `/$PyInterpreterDirectory$/flake8`
Arguments: `--max-line-length 99 $FilePath$`

OKからのAPPLYで適用完了！

#Black
PEP8より制限のきつめなフォーマットツール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563930/c34bd08e-fe6e-4b9d-2343-dac1fc095118.png)


Name: 設定したい名前(Black)
File type: Python
Scope: Current File
Program: `/$PyInterpreterDirectory$/black`
Arguments: `$FilePath$`

#flake8-isort
ファイルのインポート順をチェックしてくれるツール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563930/6d435d97-56b9-9a2d-ae81-b6d316efc436.png)

Name: 設定したい名前(isort)
File type: Python
Scope: Current File
Program: `/$PyInterpreterDirectory$/isort`
Arguments: `$FilePath$`


#.editorconfig
どんなエディターでも一貫したコードを保つことができるツール。

プロジェクト直下に`.editorconfig`を作成。

```py:.editorconfig
# http://editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{py,rst,ini}]
indent_style = space
indent_size = 4

[*.py]
line_length = 88
known_first_party = django,config
multi_line_output = 3
default_section = THIRDPARTY
recursive = true
skip = venv/
skip_glob = **/migrations/*.py
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true

[*.{html,css,scss,json,yml}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab

[nginx.conf]
indent_style = space
indent_size = 2
```
DockerでLaravelを入れているとPermissionDeniedエラーが出た

https://qiita.com/ucan-lab/items/56c9dc3cf2e6762672f4

こちらの記事を参考にDocker環境を構築していたのですが…
Laravelを

```
docker-compose exec app bash
composer create-project --prefer-dist "laravel/laravel=8.*" .
```
で入れた後

http://127.0.0.1:10080/
にアクセスしたところ……

```
The stream or file "/work/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission denied
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621241/393e518f-5674-a007-4a54-55e94d7c7d5d.png)

PermissionDeniedと言われてしまった…
Dockerがどっかーんですね。




##解決策
権限まわりの問題なので権限を与えてあげれば良いのです。
「パンがなかったらバター入りのお菓子を食べればいいのに」と同じで「権限がなかったらchownコマンドを打てばいいのに」ってやつです。

Dockerコンテナの中に

```
docker-compose exec app bash
```

で入って

```
chown www-data storage/ -R     
```

chownコマンドで権限を与えると…………

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621241/cc8429a8-cbd0-ff72-50a6-0b9a0b883ec3.png)


##できました！！！！
【設計検討2】PC操作自動化システムの設計検討2

#【設計検討2】PC操作自動化システムの設計検討2
【設計検討1】の要求仕様
https://qiita.com/asahi4549/items/42480f46e7d34b24551f
に基づいて基本設計を行った

#全体処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700308/38cc6eb7-e90f-f1b3-f2db-344b4e535feb.png)


#画像ファイル読み込み処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700308/dc4be21a-effb-5ab5-f23f-66eda6a4c662.png)




#コード実行処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700308/2ee49947-578f-e820-20db-ff581aa2587e.png)

#コード保存処理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700308/a4f0b1b6-158a-c5bb-2f5b-6b1354c308ed.png)
OpenPyXLで「ファイル内のイメージを圧縮しない」を設定したファイルを保存したい

# はじめに

OpenPyXLを利用して保存したxlsxファイルをデスクトップ版のExcelで開くと、「ファイル内のイメージを圧縮しない」のチェックボックスがオフになっています。
チェックボックスをオンにしているファイルを開いて保存した場合も、問答無用でオフとなります。
Excelで開いたときに詳細設定からチェックすれば済みますが、せっかくPythonで自動生成するので手動作業は省略したいですね。
しましょう。

## 確認した環境

|  | バージョン |
|:--|:--|
|Python | 3.8.1 |
|openpyxl | 3.0.5 |

## とりあえず対応方法

次のように記載をすることで、圧縮なし設定のxlsxファイルを作成できます。

```python:create_xlsx.py
#!/usr/bin/env python

import openpyxl

from openpyxl.workbook.properties import WorkbookProperties
from openpyxl.utils.datetime import CALENDAR_MAC_1904
from openpyxl.workbook._writer import WorkbookWriter

def write_properties_custom(self):
    props = WorkbookProperties()
    if self.wb.code_name is not None:
        props.codeName = self.wb.code_name
    if self.wb.excel_base_date == CALENDAR_MAC_1904:
        props.date1904 = True
    props.autoCompressPictures = False
    self.package.workbookPr = props

WorkbookWriter.write_properties = write_properties_custom


wb = openpyxl.Workbook()
wb.save("Sample.xlsx")
```

大事なのは`props.autoCompressPictures = False`の箇所になります。
このコードで作成したxlsxファイルの詳細設定をみると、ちゃんとチェックされていることが確認できます。
![Sample_xlsx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559409/6b41f5ea-f5bb-7000-d2bc-e8b3be73a3f2.png)

無理やりライブラリを書き換えているので、もしかしたら予期せぬ動作をするかもしれません。
念の為、注意してご利用ください。

# 調査結果備忘録

以下、調査した内容や詳細をダラダラと書きます。
特に読まなくても問題ないです。

## そもそもとして

OpnePyXLには[WorkbookProperties](https://openpyxl.readthedocs.io/en/stable/api/openpyxl.workbook.properties.html#openpyxl.workbook.properties.WorkbookProperties)というモジュールがあります。
ここにautoCompressPicturesという変数があったので、これにTrue/Falseを設定して保存すれば反映されると思いました。
しかし、workbookオブジェクトのプロパティには設定がありません。
とはいえ先程のモジュールには存在していたので、考慮されていないわけではないと考え色々見てみました。

## OpenPyXLの保存動作について

保存はWorkbookクラスのsaveメソッドを使いますが、

+ writer/excel.py
+ workbook/_writer.py

の2つのファイルを経由してWorkbookPropertiesクラスのwrite()を呼び出しています。
このwrite()から呼び出すwrite_properties()でプロパティを設定しています。
今回はこのメソッドに処理を追加してます。
WorkbookProperties()の初期値に設定するのでもいいかと思います。

## xlsxファイルについて

ワークブックプロパティの詳細については[こちら](https://docs.microsoft.com/ja-jp/dotnet/api/documentformat.openxml.spreadsheet.workbookproperties?view=openxml-2.8.1)に記載があります。
autoCompressPicturesは1またはTrueの時に圧縮する（デフォルトはTrue）のため、Flaseを設定しています。
ちなみにOpenPyXLのWorkbookPropertiesにある他の項目についても詳細が書いてあります。

## ライブラリの上書きについて

こちらの記事を参考にしました。
[Pythonでライブラリの処理を上書きする](https://qiita.com/Asayu123/items/8d8da9911dd0c3296a81)

ただ本来あるべき形としては、記載されている2種類の項目のように、self.wb.***で確認後に設定する形にするのかなぁと思っています。
今回は面倒だったので強制的にTrueとしてしまっていますけども。
VeleroでのKubernetesクラスターのリストア（Tips）

## はじめに
Kubernetesクラスター（EC2上にKopsで構築）環境において、Veleroを使ったクラスターのバックアップとリストアの検証を実施した際のメモです。
実際にご自身の環境や、本番環境等での利用を検討されている場合は、ご自身で最新の技術情報を確認および検証する必要があります。

本記事における前提
・Kubernetes 1.17.8
・Kops 1.18.2
・velero 1.4.0
・PV/PVCは利用しておらず考慮不要

## 概要およびTips
### 参考にした情報
- [VeleroのGitHubのReadme](https://github.com/vmware-tanzu/velero)
- [Backup and Restore with Velero - Suse](https://documentation.suse.com/suse-caasp/4.2/html/caasp-admin/_backup_and_restore_with_velero.html)

### 前提となるシナリオのイメージ
- クラスターのリストアということで、あるVPCのサブネット内に構築したクラスターAのバックアップをveleroにより日次で取得
- 別のVPCのサブネット内にkopsコマンドでクラスターBを作成（基本的なソフトウェアをインストール済み）
- クラスターAのバックアップをクラスターBにveleroコマンドを使ってリストア

### クラスターBのセットアップ
- 「Backup and Restore with Velero - Suse」の「11.1 Limitations 」の情報を参考に、基本的にNodeの構成（Master/Woerkerのスペックおよび数など）とソフトウェア（Kubernetes/velero/Helm/Istio）はバージョンを揃えて事前にインストールするようにした

### 基本のリストア手順
- クラスターAの所属するS3バケットからバックアップのオブジェクトをクラスターBの所属するS3バケットに事前にコピー（クラスターBのVeleroが参照するbackupファイル配置先となるS3バケットのディレクトリ内に配置）
- クラスターBに対する作業環境では、kopsコマンドが実行可能な状態、かつ、コピーしたバックアップ・ファイルが参照可能な状態とする
- リストアコマンドの実行

```bash
velero restore create --from-backup <backup file name> 
```

- リストア結果の確認（STATUSが「Completed」であること、「ERRORS」が0であることを確認）

```bash
velero restore get
```

- リストア後の稼働確認（pod等のリソースのステータス確認、アプリケーションの動作確認（必要に応じて関連するAWSマネージドサービスとのEndpoint等の調整を行う））

## 躓いたことなど
- IstioのCustom Resourceに関するエラーが発生
状況

・restore getすると「PartiallyFailed」の状態
・veleroのdescribe restoreコマンドで確認するとエラーメッセージは「 Cluster:  error restoring mutatingwebhookconfigurations.admissionregistration.k8s.io/istio-sidecar-injector: MutatingWebhookConfiguration.admissionregistration.k8s.io "istio-sidecar-injector" is invalid: webhooks[0].sideEffects: Unsupported value: "Unknown": supported values: "None", "NoneOnDryRun"」

Istioのバグのようである
・[sideEffects is not configurable and is used default (Unknown) in MutatingWebhookConfiguration for istio-sidecar-injector](https://github.com/istio/istio/issues/23485)
・[Patch to mutatingwebhookconfiguration istio-sidecar-injector's sideEffects for CI #7853](https://github.com/knative/serving/pull/7853)

リストア元環境でのIstio用のCDR「kind: MutatingWebhookConfiguration」の「sideEffects」の値を確認および修正し、修正済みの状態のバックアップを使いリストアするとエラーは解消
※「apiVersion: admissionregistration.k8s.io/v1beta1」の場合：「Unknown」、「None」、「Some」、「NoneOnDryRun」を選択
※「apiVersion: admissionregistration.k8s.io/v1」の場合：「None」もしくは「NoneOnDryRun」を選択

- Custom Resourceとして定義されているはずのvirtual service、Gatewayが新環境に存在しない（この件は別途詳細をまとめるつもり‥）
幻想をぶち壊す　イマージンブレカー(margin相殺について)　ネタです笑

# 概要(工事中だけどもう出します更新していきます！)
物語を読み進めることでCSSのmargin相殺について触れてみよう
####物語
俺の名前は**ジン**触れると間を相殺する力を持つ14歳だ。
間の相殺→margin相殺(ブロックレベル要素が接するときmarginが打消しあうこと)

```:Pタグの例
<p>テスト</p>
<p>テスト</p>
簡単に言うと重なっているてこと
```
<img width="700" alt="代替テキスト" src="https://dl.dropbox.com/s/hygy3dg7w4hqjmm/margin_p.png?dl=0">


###ブロックレベル要素　(要素の前後にmarginあり)縦並びに配置される
- **h1～h6・p・div・ul・lo・li・dl・dt・dd・table・from・hr・pre・brockquote　計14個**　

```java:ブロックレベル
<div>テスト</div><h1>テスト</h1>↓
テスト
テスト
```

###インライン要素　(要素にmarginなし)横並びに配置される
- **a・span・label・input・textarea・select・img・b**

```java:インライン
<span>テスト</span><span>テスト</span>↓
テストテスト
```
お名前.comで取得したドメインを使ってaws上でサービスを稼働させる際の構成を理解する

## 目的
ドメインをAWS以外のサービス(ここではお名前.com)で取得し、それをAWS上にデプロイしているサービスで利用するケースについて大まか構成を整理する。
設定方法などの詳細は他の方がまとめてくれているので大枠の構成の整理のみを目的とする。


#### ポイント
お名前.comで設定する箇所は以下のDNSの切り替えが基本。あとは、AWS側のRoute53で実施する。
(以下は、DNSからELBに接続するケース)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52335/df61d8dc-bb08-883e-1482-79463c9a7933.png)


※Google Search ConsoleなどでTXTレコードの追加もAWS側で行うこと。↑を理解しておけば、その辺も理解しやすいと思う。
https://qiita.com/yuta-38/items/31bdce8290e5d42156f5


その他、参考にしたサイト
https://qiita.com/sadayuki-matsuno/items/4c371ba984d9b22b3737
https://mel.onl/onamae-domain-aws-route-53/
【SVG制御妄想７】SVGの限界

この記事は「続・Mohoから出力したSVGを制御したい妄想の話」の一部です。

■実物
【GitHub】SourceOf0-HTML/path_control: SVGを制御したい願望
https://github.com/SourceOf0-HTML/path_control

【GitHub Pages】ベクターデータをいじり倒したい気持ち
https://sourceof0-html.github.io/path_control/


■記事一覧
【SVG制御妄想１】SVG解析しないと始まらない
https://qiita.com/flying_echidna/items/5a628db0d652d1558208

【SVG制御妄想２】Mohoから出力したSVGのマスクがバグる
https://qiita.com/flying_echidna/items/3930caf04626deec7bfb

【SVG制御妄想３】連番データをどげんかせんと
https://qiita.com/flying_echidna/items/ded3f3590c3d67fadb86

【SVG制御妄想４】変形させたいよなぁ？
https://qiita.com/flying_echidna/items/188634f35a05bbde9a51

【SVG制御妄想５】ボーンぐりぐり
https://qiita.com/flying_echidna/items/a34648da8a650fe34824

【SVG制御妄想６】助けてマルチスレッド
https://qiita.com/flying_echidna/items/80b101c1a1eedb534137

【SVG制御妄想７】SVGの限界
https://qiita.com/flying_echidna/items/2f53a461c5e6c05109df


■過去記事
【2019-03-06】「SVGでアニメーションさせたいんじゃ」の詳細報告
https://qiita.com/flying_echidna/items/ff3a061f4e348e62cca0

【2020-02-13】Mohoから出力したSVGを制御したい妄想の話
https://qiita.com/flying_echidna/items/da7ecc721650fa9ab651


#SVGをいじり倒してわかったSVGだと困ること

今まで散々いじり倒してきて。
いろんなことをやってきて。
やっぱり思うこと。

Mohoから出力したSVGにはバグもあるし、あくまで出力結果であって、編集データではない。

そんな部分についての話。


###マスクの出力不良

これは１つの記事まるまるで話したことなので、詳細割愛。

【SVG制御妄想２】Mohoから出力したSVGのマスクがバグる
https://qiita.com/flying_echidna/items/3930caf04626deec7bfb


###一回転オーバーしてても検出できない

主にボーンの話。
例えばボーンがアニメーションの中で360度以上回転してたとしよう。
でも出力されたSVGから無理やりボーンの角度を算出したところで、そのことは分からない。
Math.atan2()を使って角度を算出してる現状、返ってくる値は-PIからPIの間でしかない。

それじゃ困るんだよ。
特にスマートボーンは。

スマートボーンの角度によって、アクションの再生位置を制御している上、Moho上では一回転オーバーの値も設定できてしまう。
これが検出できないのは、正直困る。


###同シェイプ内の同位置にある点が消失する

一つの形を変形させていくアニメーションの途中で、点が同じ位置にくることがある。
だんだん小さくなっていく、なんてアニメーションだと、おもっきり重なる。
すると、どうなるのか。

出力したSVGだと1つの点として合体して出力される。

やめろーー！！
どの点がどこに移動したか分からなくなるだろーー！！
点の数は常に一定であれーー！！


###キーフレームが単純でもフレーム数が多いと重い

例えばMoho上で1フレーム目から100フレーム目にかけて一回転するアニメーションを用意したとしよう。
キーフレームとして見るなら、
1フレーム目：0度
100フレーム目：360度
程度の情報量なわけだ。

ところが、これをSVGで出力すると、100枚分のデータになってしまう。
1000フレーム使おうものなら、たかが一回転させるだけで膨大なデータになる。
ないわぁ。

イージングを実装した上で、キーフレームの情報が取れれば、もっと軽くなるんじゃねぇの？
と思うけど、Mohoから出力したSVGにキーフレームの情報なんて入れられるわけもなく…


###ボーンのデータ手動で書くのめんどくさすぎる

SVGにはどうあがいても入らないからということで、JSONファイルで設定を書いた。
でも、新しく作ったMohoのデータでも、また新しくJSONファイルを手書きするの？
あれでも大変だったのに、その数倍の数もあるボーンの設定を？
また各々のボーンが識別できるように命名を考えながら？？

めんどくせぇえええええ！！！！
そもそもこの時点でSVGだけで完結できてねぇんだよぉおおおおおお！！！


###レイヤー変形アニメーションが取得できない

一番我慢できなかったのが、正直これ。
全部がパスの変形データになってしまって、レイヤー変形情報が取れない。
正直これを口頭で説明するのは難しい。
当時の雑放送を見てもらった方が早い。

雑放送（2020/11/21：もうええSVG自力で出力したるわ！） - YouTube
https://www.youtube.com/watch?v=Rl-cxvuGnP8

配信のタイトルや後半でも言ってる通り、
最終的に「Moho上で動くLuaスクリプトを使って、自力でSVGを出力したるわ！」
という結論に至ってる。
が、それでもやっぱりSVGというフォーマットだとアンカーポイント（回転・拡縮の中心座標）の情報が入れられなかったりと、困ることが多すぎた。


#もう脱SVGしようぜ

そしてこの結論に至る。
MohoのLuaスクリプトにすら手を出すようになってしまった今、
ボーン用に用意していた三角のパスも、JSONファイルも、Mohoのメニューから選ぶだけで自動で出力できるようになった。
各アクションのSVGファイルを出力するために、各アクションのMohoファイルを自動で生成できるようになった。
Moho既存のレンダラーを使ってSVGを出力しなくても、自力でSVGのフォーマットをそれっぽく出力できるようになってしまった。
というか、わざわざSVGというフォーマットで出力している、と言ってもいい。

だったら、自分が扱いやすい新しいフォーマットを作った方がいいんじゃない？

ということで。
To be continued...

（WindowsでLuaから日本語パスを出力するのに苦労しまくったのは、また別のお話…）