OmniAICreator/Qiita-1.07M huggingface dataset:
optuna.visualizationのグラフを保存する方法（plotlyのグラフを保存する方法）

optuna.visualizationのグラフを保存しようとして、幾つか気づきがありましたので、記載します。

## 環境構築手順

### Optuna
Optunaは、Preferred Networksが提供する、ハイパーパラメータ自動最適化フレームワークです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493607/944251bf-2807-983e-a25d-84bd0d1a7a0d.png)

https://preferred.jp/ja/projects/optuna/
https://github.com/optuna/optuna

### optuna visualization
optunaのvisualizationは、最適化の工程をプロットするユーティリティ関数です。
様々なグラフを描画できます。
https://optuna.readthedocs.io/en/stable/reference/visualization/index.html

jupyter notebookのサンプルコードはこちら。
https://colab.research.google.com/github/optuna/optuna/blob/master/examples/visualization/plot_study.ipynb

### Plotly
visualizationは、内部でplotlyを利用します。
plotlyはグラフを作成するためのライブラリです。
https://plotly.com/python/

環境構築はこちらのインストールガイドが参考になります。
https://github.com/plotly/plotly.py#jupyterlab-support-python-35

### Kaleido
私はウェブブラウザではなく、コマンドプロンプトから、グラフを保存したかったので、Kaleidoをインストールし、無事、保存できました。

Kaleidoは画像を保存するためのライブラリです。
https://pypi.org/project/kaleido/

### 実行結果サンプル
#### optimization history
![optimization_history_ply.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493607/e0eab48e-a0ea-1341-788d-cd44af120b79.png)

#### contour
batch_sizeとlrの関係
![batch_size.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493607/2976b7d9-4feb-e306-a0aa-ade41f8756ab.png)

## 注意事項

以下をご注意ください。

plotlyはversion4.9以上を利用する必要があります。google colaboratoryのplotlyはversion4.4.1なので、アップデートする必要があります（2021/1/18）。
https://github.com/plotly/Kaleido

インストールガイドにはOrca/psutilを使う方法も記載されていますが、正しく機能しない場合があります。

Plotlyをオフラインで使う方法もありますが、ウェブブラウザが開かれてしまいます。

### optuna.visualization.matplotlib
matplotlibバージョンもあります。
stableバージョンでは、contour、sliceはサポートされていません。
https://optuna.readthedocs.io/en/stable/reference/visualization/matplotlib.html

latestバージョンでは、contour、sliceもサポートされています。
https://optuna.readthedocs.io/en/latest/reference/visualization/matplotlib.html

### 実行結果サンプル
matplotlibはplotlyより低品質な印象です。

#### optimization history
![optimization_history_plt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493607/51e06d6e-60a1-bdcd-f2c1-f8043a69611c.png)

## 参照
Static Image Export in Python
https://plotly.com/python/static-image-export/

Matplotlib backend for visualization functions
https://github.com/optuna/optuna/issues/1539
曜日を出力したい

今日の曜日をDateクラスを使って記述したいです。

土曜日だった場合だけ表示の内容を変更したいです。
例)
「今日は月曜日」
「今日は土曜日だ！！」

Dateクラスは、Rubyの標準ライブラリの機能です。使用するためには、

```ruby
require "date"
```

を記述します。

今日の曜日を取得するときは、

```ruby
Date.today.wday
```

のように記述します。
wdayは曜日を0(日曜日)から6(土曜日)の整数で取得することができるメソッドです。

例)

```ruby
require "date"
day = Date.today.wday
puts day
#曜日に合わせた数字が出力されます
```

曜日に合わせた数字は出力できるようになりましたが、文字を出力するにはどのようにすれば良いのでしょうか。

配列と、添字を使用したら取得できそうです。

```ruby
days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日" ]

puts days[0]
#日曜日が出力されます
```

あとは、土曜日だけ表示を変更する条件分岐を考えれば期待する出力結果になります。

```ruby
require "date"
day = Date.today.wday
days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日" ]

if day == 6
  puts "今日は#{days[day]}だ！！"
else
  puts "今日は#{days[day]}"
end
```

dayには今日の曜日の数字が代入されています。
daysには配列で日曜日から土曜日が代入されています。
daysの添字にdayとすることで、配列の中から指定の曜日を出力、if文を使って出力結果を変えれば曜日の出力と曜日によって出力内容を変更することができました。
Mac OS High SierraでWi-Fiからインターネットに繋がらなくなったときの対処記録（備忘メモ）

*High Sierraをサポート外にしたセキュリティソフト（カスペルスキー）をアンインストールすると繋がりました。Mac OSをバージョンアップするか、それが出来なければMac本体を買い替えですね。*

---

1. 他のPC, スマホでWi-Fiからインターネット接続できるか確認
2. 他のブラウザで確認
3. PC再起動
4. セキュリティソフトの無効化
5. ワイヤレス診断
6. Wi-Fi設定の削除、再登録
7. Wi-Fiルータの電源OFF-ON
8. 有線LANで接続
9. セーフブート
10. セキュリティソフトの更新
11. セキュリティソフトの終了
12. セキュリティソフトのアンインストール（公式に案内されている完全アンインストール）
Express Tour #1 Express

Expressの公式チュートリアルに沿ってexpressを体験してみる。
Node.jsはインストール済の状態で臨みましょう。

## Installing

アプリケーション用のディレクトリを作成しましょう。

```
$ mkdir myapp
$ cd myapp
```

次にnpm initコマンドでpackage.jsonを作成します。と、案内されていますがとりあえず全てデフォルトでよいと思いますが、
メインファイルの名前はapp.jsにしておきましょう。

```
$ npm init
```

次にExpressをインストールします。

```
$ npm install express --save
```

## Hello world example

下記のコードは最も単純なアプリの例です。
このアプリはサーバーを起動し、ポート3000で接続できます。 アプリは「Hello World！」で応答します。 

```Node.js
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})
```

### ローカルでの実行方法

myappディレクトリに、app.jsという名前のファイルを作成し、上記の例のコードをコピーします。

次のコマンドでアプリを起動します。

```
$ node app.js
```

ブラウザで以下にアクセスすることで出力結果を見ることができます。

http://localhost:3000

## 参考

http://expressjs.com/en/starter/installing.html
SuperCollider スパコちゃん2021 その2

※この記事では音響合成プログラミング環境＆言語のSuperColliderについて書いています。
※この記事ではMacOS版のSCを使っています。
※文中SuperColliderをSCまたはスパコと略しています。


アプリの起動、構成、基本操作

インストールしたアプリ（白と黒の丸い渦のようなアイコン）をダブルクリックしてSuperColliderのIDEを開きます。IDE（Integrated Development Environment）は、プログラミングのコードを記述するエディタ、プログラムを動作させるためのコンパイラ、ヘルプファイルやコードの出力結果を表示するものなど、プログラム開発ツールをひとまとめにした開発環境のことをいいます。SCのプログラミングに必要なもの一式が揃っています。ざっくりとSuperColliderのアプリ＝SC IDEだと思ってください。

SC IDEの画面は主に４つに分かれています。

標準ではA〜Cまでが表示されていますが、もし表示されていないものがあれば、SuperCollider > View > Dockletsから表示したいものを選んでください。既に表示されている場合はDockletsで表示されるリストにチェックマークがついています。

A. コードエディタ … SCファイルを表示し、プログラミングコードを記述する部分です。複数のファイルをタブで表示することもできます。SCのファイルの拡張子は.scdです。
B.  ポストウィンドウ … SCの起動時のメッセージ、コードの実行時の出力結果、エラーなどを表示するウィンドウ。
C.  ヘルプブラウザ … SCのヘルプファイルの検索や表示。
D. ドキュメント … 現在開いているファイルをリスト表示。


ポストウィンドウとヘルプブラウザは、各ウィンドウの上部のメニューをドラッグすることで、表示する位置を変更することができます。また各ウィンドウの文字の横の小さな四角をクリックすると「Undock（またはdock）/ Detach(Attach) / Close」が表示されますので、自分が作業したいレイアウトにしてみてください。

SC公式のヘルプの画像を貼っておきます。



クライアント / サーバー
さて、SCを起動すると自動的にアプリがもう１つ起動してきます。MacOSではDockに起動中のアプリのアイコンが表示されますが、白黒模様の立方体が増えているのが分かりますか？これはアクティビティモニタにはプロセス名「scsynth」として表示されているもので、SuperColliderのシンセ部分、音響合成の処理をしています。

実はSuperColliderは２つの部分に分かれています。１つ目は先に紹介したプログラミングコードを書いて実行する部分でsclang（SCラング）と呼んでいます。langはlanguageの略で言語の部分です。２つ目、は自動的に起動したscsynth（SCシンス）で、オーディオの処理を行っている部分です。この２つはOSC（Open Sound Control）というプロトコルを使って内部的に通信しています。

初期のSuperColliderでは、lang部分とsynthの部分は一体化した一つのアプリケーションでした。ライブ中にSCのプログラムがクラッシュをすると音もその場でプチン… と終わって無音になってしまっていたのですが、これらの２つのパートが分離したことで、万が一クラッシュしても音は生成され続け、なんとか最悪の自体を免れることができるようになりました。


またパソコン内の別のアプリや、ネットワークの向こうのsclangから一つのscsynthを動かしたり、プログラミング言語としてのSCを使わずに別の言語からscsynthを使い、SuperColliderのサウンドを利用することもできるようになりました。その利点を活かしたOvertone（https://overtone.github.io）は、Clojureというプログラミング言語でSCのオーディオエンジンを扱うことができます。またライブをしながらコーディングを行う演奏スタイル、ライブコーディングをする人の中には、ライブコーディングに特化した言語を用いてscsynthで音を生成している場合も少なくありません。
MkDocsでPlantUMLを表示させる

自分はドキュメントを書く際にはPlantUMLを結構使います。
ちょっと久々に結構な量のドキュメントを書く必要性が出てきたのでMkDocsで環境整えようと思ったときに躓いたので備忘録。

環境はすべて[docker](https://github.com/shun/docker-example/tree/master/docker-mkdocs)で作成します。

## dockerで環境を整える

### PlantUML Serverを建てる

今回の本筋ではないのですが、念の為立て方を書いておきます。
以下をyamlファイルを用意してdocker-compose up -d でPlantUML Serverを起動させておきます。

```yaml:docker-compose.yaml
version: "3.7"

services:
  plantuml:
    image: plantuml/plantuml-server
    ports:
      - 18080:8080
```

サーバが起動してブラウザでアクセスし、以下のようなページが表示されればOKです。
ここで、サーバのIPアドレスは *192.168.1.100* とし、ページは http://192.168.1.100:18080 でアクセスできるものとし説明を続けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65929/0b5fbc88-9e49-248e-9e23-ed20a5fa930c.png)

### MkDocsのコンテナ環境を作成する

MkDocs用のコンテナのDockerfileは以下になります。
公式のpythonのdockerイメージをベースに使用するパッケージを追加します。
今回はMkDocsをマテリアルデザインのテーマとPlantUMLを使えるようにするだけにとどめてあります。

```Dockerfile:Dockerfile
FROM python:3-buster

WORKDIR /

RUN pip install -U \
        pip \
        mkdocs \
        mkdocs-material \
        plantuml-markdown \
    && mkdocs new docroot

WORKDIR /docroot
```

次に、docker-compose.yamlは以下になります。
docroot のディレクトリは *mkdocs new* で作成したMkDocsのプロジェクトのディレクトリをローカルに保持してマウントするようにしています。
コンテナを起動すると *mkdocs serve* でサーバが起動するようにしています。
http://192.168.1.100:18000 でアクセスするとページが表示されます。
単純に mkdocs serve だけだとlocalhost:8000 でlistenするのでコンテナ外からアクセスできません。
そのため、コンテナ外からアクセスできるように -a のオプションを追加しています。

```yaml:docker-compose.yaml
version: "3.7"

services:
  mkdocs:
    build:
      context: ./
      dockerfile: ./Dockerfile
    volumes:
      - ./docroot:/docroot
    ports:
      - 18000:8000
    tty: true
    command: bash -c "mkdocs serve -a 0.0.0.0:8000"
```

### PlantUMLと連携する

PlantUML と連携するためには以下の準備が必要です。

- plantuml-markdown のインストール
- mkdocs.yml にplantuml_markdownのextensionの追加

plantuml-markdownのインストールはDockerfile ですでに済んでいるため割愛します。

#### plantuml_markdown のextensionの追加

mkdocs.yml に以下を追加します。
以前だと、serverに設定するのが http://192.168.1.100:18080/plantuml のように最後に「plantuml」がついている必要がありました。
PlantUML Serverの仕様が変わったのかこのままだと動かなく自分は躓いていました。
あと、個人的にダイアグラムはsvg で表示したいので、 以前は http://192.168.1.100:18080/plantuml/svg/ のようにURLにsvg を追加していた気がしたのにexceptionだらけで表示されず、うーんとなっていました。

この辺も仕様が変わったのか特に何も追記する必要はなく、 http://192.168.1.100:18080 のみを指定します。
注意点としては、最後のスラッシュも不要です。

```diff
site_name: My Docs
theme:
  name: material

+ markdown_extensions:
+  - plantuml_markdown:
+      server: http://192.168.1.100:18080
```

フォーマットの指定がない場合は、デフォルトpngのようです。
自分のようにデフォルトをsvgにする場合は、方法は二通りあるようです。

- フォーマットを毎回指定する
- デフォルトのフォーマットを指定する

フォーマットを毎回指定するには以下のように「format」で指定します。

```markdown

    ```plantuml format="svg"
    @startuml
    Bob -> Alice : hello
    @enduml
    ```
```

デフォルトで指定するにはmkdocs.yml で以下のように指定します。

```diff
site_name: My Docs
theme:
  name: material

markdown_extensions:
 - plantuml_markdown:
     server: http://192.168.1.100:18080
+    format: svg
```

以上で、たぶん現時点での最新のMkDocs と PlantUML を使った環境でドキュメントが作成できるかと思います。
長くなりましたが、ここまでお付き合いしていただきありがとうございました。
RaspberryPi OKdo スターターキット買ってみた

しかだよ。

RaspberryPi2B+くらいから触ってなかったので復習も兼ねて最新端末であるRaspberryPi4を買いました。気がつけば
- 電源はType-C
- micro HDMI ポートが２つ
になってました。GPUがある程度使えるみたいで、機械学習も結構できるらしい。

ケースやケーブルを個別に買うのがめんどいのでセットにしました。買ったのはこちら。（公式サイトより）
[OKdo Raspberry Pi 4 4Gb Model B Starter Kit \- OKdo](https://www.okdo.com/p/okdo-raspberry-pi-4-4gb-model-b-starter-kit/)
![](https://www.okdo.com/wp-content/uploads/2019/10/drive-download-20190925T132924Z-001_F-64.jpg?fit=2000%2C2069&resize=1296,866)

## 開封の儀
![PXL_20201226_083827369.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16532/0312ae1e-3477-d0d0-6583-e55325e3c4c9.jpeg)


- RaspberryPi4 4GB
- ヒートシンク
- ファン
- HDMIケーブル2本
- Type-C 電源ケーブル
- USBメモリ
- アルミケース
- SDカード

RaspberryPi4は電力使うみたいだけど、AC100V給電なので安定しそう。しかし、ラズパイでヒートシンクつける日が来るとはおもわなかった・・・かなり熱くなるのだろうか。

冷えやすいアルミケースに装着。
![PXL_20201226_085206893.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16532/53f140f5-6169-84cd-9062-16dcbb08eb75.jpeg)

ヒートシンクとCPUクーラーを装着。ほんと、小さいデスクトップマシンのようだ・・・。
![PXL_20201226_085913628.MP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16532/28a91388-abe2-329a-90d7-1c8418d23d7d.jpeg)

虹色の画面になって失敗したかと思いきや、しばらくまったら起動しました。
![PXL_20201226_085917083.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16532/5220b03a-11ed-8193-c0fe-1cbb164e303c.jpeg)

![PXL_20210102_102427577.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16532/e73f90cf-5f04-21a0-50d2-f23ee2ce628d.jpeg)

勢い余って[13インチのポータブルモニター](https://amzn.to/2L99ome)も買ってしまった。
<a href="https://www.amazon.co.jp/gp/product/B08K74SQCT/ref=as_li_ss_il?ie=UTF8&psc=1&linkCode=li2&tag=shikajiro-22&linkId=38607f5f6189e43bc5ef2e74665fa376&language=ja_JP" target="_blank"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B08K74SQCT&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=shikajiro-22&language=ja_JP" ></a><img src="https://ir-jp.amazon-adsystem.com/e/ir?t=shikajiro-22&language=ja_JP&l=li2&o=9&a=B08K74SQCT" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
IBM i (旧AS400）の自己学習メモ　コマンド／ツール／運用　長めのコマンドを入力したい（CALL QCMD）

# 自己学習メモインデックス

[IBM i (旧AS400）の自己学習メモ　インデックス](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

# 概要

[IBM i (旧AS400）の自己学習メモ　コマンド／ツール／運用　CPYFでテーブルデータのバックアップなど](https://qiita.com/You_name_is_YU/items/d563dd0b95ffebcf6093)で紹介しているCPYFの条件指定した場合のコマンドのように、それなりに長文となるコマンドを手元に控えておき、それを実行したいケースがあります。

```
CPYF FROMFILE(YAMAGUCHI1/MTOKISKP) TOFILE(YAMAGUCHI1/MTOKISKP@1)
MBROPT(*REPLACE) CRTFILE(*YES) INCREL((*IF TOKRMT *GT 1200000))
```

PDMなどの画面を表示している際など、画面下部にあるコマンド入力エリアが1行程度しか無いような場合、上記のような長いコマンドをコピー＆ペーストして実行しようとすると、パラメータが欠落して正常にコマンドを実行することができないことがあります。（場合によっては誤ってコマンドが実行されてしまうようなケースもあります。）

このように、コピペしたコマンドが欠落してしまい、思ったようにコマンドを実行することができないケースに便利な操作を紹介します。

# CALL QCMDで長いコマンドを入力可能に

今回は非常にシンプルです。
以下のコマンドを実行します。

```
CALL QCMD
```

すると、Command Entry（コマンド入力）画面が表示されます。
![スクリーンショット 2021-01-01 14.00.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/202f5e47-a9dd-c43b-ddc8-41dbb3ed34c3.png)

この画面をみると、最大で4行ほどのコマンド入力エリアが表示されていることが確認できます。
これだけあれば、それなりに長いコマンドをコピペしても、欠落することなく実行できると思います。

4行程度では実行したいコマンドが欠落しちゃうよ？という人は、さらにF11キーを押下することで、画面いっぱいにコマンドが入力できるようになりますので、これだけあれば十分ではないかと思います。
![スクリーンショット 2021-01-01 14.02.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/a2150fc7-2cf4-2369-af4b-bb74cea56f14.png)

# コマンドの実行履歴を取得（F9）との組み合わせでさらに効率アップ

とあるコマンドを実行したい場合、オプションを指定せずに、コマンドだけを入力し、オプションはF4キーを押下して、オプションを指定する画面から実行するケースがあると思います。
複雑なオプションを指定する場合は、どうしてもコマンドよりもGUIからオプションを指定する方が安全で確実だったりしますよね。

画面からオプションを指定して、Enterで実行し終わったあと、また同じような処理を実行したい場合、コマンドの実行履歴から発行されたコマンドを取得して、そのコマンドを加工して実行することが可能です。
F9キーを押下することで、過去実行したコマンドの実行履歴を、一番新しいものから順番に確認することが可能です。
（F9キーは何度も押下することで、履歴を遡っていくことができます。）
![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/094cb05f-6344-2c2c-9d3d-b55e36ba33c5.gif)

複雑なオプションを指定している場合など、Command Entry画面でF9キーを押下し、過去の実行履歴から、その対象のコマンドを表示して、コピーして手元に控えておくことができますので便利だと思います。
※1行しかコマンドが入力できないような場所でF9キーを押下する場合、表示しきれないオプション部分などは・・・表記となってしまうため、Command Entry画面で実行履歴を確認するのがおすすめです。
クラスとインスタンスを用いたコードの作成

クラスとインスタンスを使用して著者、タイトル、本文を出力させたいと考えています。

```ruby
class Article

  def initialize(author, title, content)
    @author = author
    @title = title
    @content = content
  end

end

#出力結果は
#著者: 鈴木
#タイトル: Hello Ruby!
#本文: こんにちは、Ruby
```

期待する結果を出力するために、newメソッドを使用して
インスタンスを生成して変数articleに代入します。

```ruby
article = Article.new("鈴木", "Hello Ruby!", "こんにちは、Ruby")
```

この時に実引数（("鈴木", "Hello Ruby!", "こんにちは、Ruby")）を指定します。
実引数として指定した値は、仮引数のauthor, title, contentに渡されます。

```ruby
def initialize(author, title, content)
    @author = author
    @title = title
    @content = content
  end
```

initializeメソッドで宣言されたインスタンス変数に仮引数に渡された値が代入されます。

インスタンスの値を返すメソッドをそれぞれ定義していきます。

```ruby
def author
  @author
end

def title
  @title
end

def content
  @content
end
```

最後に定義したメソッドを呼び出す記述をすれば出力されます。

```ruby
class Article

  def initialize(author, title, content)
    @author = author
    @title = title
    @content = content
  end

  def author
    @author
  end

  def title
    @title
  end

  def content
    @content
  end
end

article = Article.new("鈴木", "Hello Ruby!", "こんにちは、Ruby")
puts "著者: #{article.author}"
puts "タイトル: #{article.title}"
puts "本文: #{article.content}"

#式展開を使って呼び出します
```
回路図作成ソフトFritzingで遊んでみた

ブレッドボードを使った結線図でよく見る [Fritzing](https://fritzing.org/) 。
このソフトを使い、文字を書いてみました。
ジャンパー線や電子部品を使い、「WELOCOME TO 2021」というフレーズを作りました。
また、電子工作ぽくするために、"Raspberry Pi Zero"にGPIOピンで繋げてみました。
文字の見やすさを意識したので、電気的には繋がっていません…

##作品！
![welcome_to_2021実装.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549741/1424a088-4f78-9587-9829-5b5edb1e4e1e.png)

※ 無断転載・無断使用はご遠慮ください。

##作ってみて

"Fritzing"は、直感的に操作ができるので、使いやすいと思いました。
さまざまな電子部品や、"Raspberry Pi","Arduino"といったパーツが用意されています。
基板の回路図を描画することもできるようなので、電子工作をする際に便利そうです。

##補足

Fritzing 0.9.3 64bit で使用しました。
FiraCodeフォントを利用するメモ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691360/b5197479-251a-5fe6-197c-3d942240d895.png)
<details>
<summary>天気いいから、...</summary>
天気いいから、~~散歩しましょう！~~のれんがを運ぶましょう！
小さいお茶を浸して、土下座をして、しばらくプログラミングをやるつもりです　が、が...
FiraCode、Windows Terminal、powershell7を見ながら、道に迷いました。コードは少しも運んでいません。あ～また0コードの一日です。
</details>

:head_bandage:健忘症候群の一員ですから、メモします。

##Fira Codeとは

FiraはMozilla社(FireFoxのお父さん)が主に進めフォントシリーズです。Fira Monoはその中の一つです。

Fira codeがFira Monoフォントに基づいて、演算子に特別な扱いをしました。こうすれは通常の読む習慣に合っています。(プログラマーとしては、2つの文字が1つの意味を表すことに慣れているかもしれません。)

Fira codeがプログラムを書くために生まれました。等幅などの基本的な属性を持つほか、プログラミングの連字特性も盛り込まれています（ligatures）。

Fira Codeはこの特性を利用してプログラミング中の常用記号を最適化します。例えば、入力した「！=」を直接「≠」と表示したり、「>=」を「≧」に変えたりして、コードの可読性を高めます。

私たちがプログラムを書くとき、->、=>、::、>=、.=、+=など複数の文字を持つ演算子をはしばしば使用しますが、これらの演算子は実際には1つの意味しかありません。一般的には、一つの意味を表すなら、 一つのポジションを占めるのは当然です。 これがFira codeの目的です。

これから効果を見てみましょう！

![](https://raw.githubusercontent.com/tonsky/FiraCode/master/extras/ligatures.png)
![](https://raw.githubusercontent.com/tonsky/FiraCode/master/extras/samples.png)

##Fira Codeのインストール
######1.ダウンロード：https://github.com/tonsky/FiraCode.git
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691360/1d078bda-1f9c-d94d-3b34-514879a1e2fd.png)

######2.ダウンロードしてきたFira Codeのインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691360/cfbe9675-fcc0-0ac0-a936-baeb8e8431e2.png)



######3.Fira Codeの使用
　　*例：Windows Terminalの設定にFira Codeを使います。*("fontFace": "Fira Code")

```
"list": [
	{
		// Powershell 7
		"guid": "{5069adab-e9f0-4c71-b999-f0771f15f6f9}",
		"hidden": false,
		"name": "pwsh",
		"commandline": "pwsh.exe -nologo",
		"startingDirectory": ".",
		"fontSize": 11,
		"snapOnInput": true,
		"useAcrylic": false,
		"fontFace": "Fira Code",
	}
]
```
Prettierが動かない？！どうして？！

今回は便利な拡張機能「Prettier」をインストールしたけど動かないそこのあなたにぴったりの記事になってあります。
自分もインストールしたけど動かなくて目の前の壁に穴を開けちゃいまs、、、嘘です。
壁に穴を開ける前にこの記事を読んで解決しちゃいましょう！
早速おそらく原因はこのどれかです。

1.Vscodeの設定画面を開いて「Editor:Format On Save」にチェックを入るのを忘れていませんか？

2.Vscodeの設定画面を開いてEditor:Default Formatterが「null」になっていないかチェックが入っていませんか？『ちなみに自分はこれが原因でした。』

どうでしょうか？こちらの方法で直ってくれれば良いのですが。。。
もし直らなければ他者さんのページをご覧ください。（無責任）
こちらは保存時にインデントを揃えてくれるという非常に便利な拡張機能となっておりますで、是非ご活用ください！
それでは！
AIにふれてみるMicrosoftAIの活用事例と実践

##今日はAIにふれてみるMicrosoftAIの活用事例と実践をやってみた
２０２１年正月。
以下リンクの内容でAIをしてみた。
https://www.fsi.co.jp/blog/5044/

###MicrosoftAI:Azure Cognitive Service
とまあ、資料に従い、ジャンケン認識アプリを作成してみる。
まず、無料アカウントを作成。
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/91c37502-dfab-5ec7-f18f-e4af3a54ddba.jpeg)
####まず、リソースグループを作成
特に気を付ける部分はない。作成！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/1ac2502e-2751-62b8-df05-792fa1043fa6.png)
####Custom Visionを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/d26d1c38-5320-47d8-24c7-2691d0e07875.png)
ここでｈｓ、先ほど作成したリソースグループを指定するが、ここでもリソースグループの追加ができるようだ。
そのた注意するところはないが、freeを選択していけばいい感じだ。
####Custom Vision ポータルにログインしてプロジェクトの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/95b4a63a-e85c-cedd-b9de-86f5d12219d2.png)
どうもここからが分かりにくいが、また別のポータルにつながないといけない。
で、ここでプロジェクトを作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/2bb0e606-acb7-9a1d-5a7e-38efeaf2c741.png)
ここでの注意点も特にない。
あえて言うなら、以下の物体検出（object detection）を選ぶとこころか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/163988ac-e779-0084-f1e1-a9797cec0ff7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/9731d988-c4ea-8a81-843b-4da759b20b04.png)

####データの収集
ここからプロジェクトに画像データを読み込ませるのだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/d60d8f7d-70f0-fdf6-b827-57ef6540e1f5.png)
で、ここからが面倒で時間がかかるのだが、写真にこんな風にタグ付けをしていくのだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/6a7a6447-c8fd-a0f9-565e-955ee0411ef7.png)

####学習
学習ボタンを押すとなっているが、トレイン＝列車とは。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/d9a44bcb-e088-008f-70cd-f61ca209bb36.png)
####評価
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/ec98c8e8-0c80-a5eb-4813-0e698699fce9.png)

そうするとこんな評価画面が表示される。
で、簡単に説明を書くと。

* Precision：適合率
 * AIが判断した結果で正しかったものの割合。例えばAIが１０匹を猫と判断したけど、9匹が本当の猫だった場合は90%になる。
* Recall：再現率
 * 正解データのうち、AIが正しく検出した割合。 例えば正解が１０匹の猫であるデータでAIが9匹の猫を判断た場合は90%になる。

つまり今回のプロジェクトでは78.6%の適合率＝AIが100のグーヲ判断したがで本当のグーは78だった。
５０％の再現率＝グーが100のうちAIが50しかグーと判断できなかったことになる。
【Java】Optionalの使い方②

#プログラミング勉強日記
2021年1月2日
[昨日の記事](https://qiita.com/mzmz__02/items/dc19895fc608d0ae87a3)同様にJavaのOptionalクラスの使い方について簡単にまとめる。昨日扱っていないメソッドでの使い方を紹介する。

#orElseThrowメソッドの使い方
　orElseThrowメソッドは、引数の有無で処理が異なる。

　引数がない場合は、nullのときにNoSuchElementExceptionをスローして、nullでないときは値を返す。

```java:引数なしの場合
import java.util.NoSuchElementException;
import java.util.Optional;
 
public class Sample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        try {
            str = value.orElseThrow();
            System.out.println(str);
        } catch (NoSuchElementException ex) {
            System.out.println("nullです");
        }
    }
}
```

```:実行結果
nullです
```

　引数がある場合は、例外をスルーする例外クラスのオブジェクトを指定できる。

```java:引数ありの場合
import java.util.Optional;
 
public class Sample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        try {
            System.out.println(value.orElseThrow(() -> new RuntimeException()));
        } catch (RuntimeException e) {
            System.out.println("nullです");
        }    
    }
}
```

```:実行結果
nullです
```

#streamメソッドの使い方
　nullチェックをせずにOptional型のオブジェクトからnullでないものだけを取り出すことができる。

```java
import java.util.List;
import java.util.Optional;
 
public class Sample {
    public static void main(String[] args) {
        List<String> list1 = List.of("Tanaka", "Yamada");
        List<String> list2 = null;
        
        Optional<List<String>> value1 = Optional.ofNullable(list1);
        Optional<List<String>> value2 = Optional.ofNullable(list2);
        
        value1.stream().flatMap(x -> x.stream()).forEach(System.out::println);
        value2.stream().flatMap(x -> x.stream()).forEach(System.out::println);
    }
    
}
```

```:実行結果
Tanaka
Yamada
```

#ifPresentメソッドの使い方
　nullではない場合にのみ引数に指定した処理を行う。

```java
import java.util.Optional;
 
public class Sample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        value.ifPresent(System.out::println);
    }
 
}
```

```:実行結果
strがnullなので処理は行われない
```

#ifPresentOrElseメソッドの使い方
　nullの場合でも処理を行える。nullでない場合の処理を第1引数に指定し、nullの場合の処理を第2引数に指定する。

```java
import java.util.Optional;
 
public class Sample {
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        value.ifPresentOrElse(
            System.out::println, 
            () -> System.out.println("nullです"));
    }
 
}
```

```:実行結果
nullです
```


#参考文献
[JavaでOptionalクラスを使う方法【初心者向け】](https://techacademy.jp/magazine/18612)
[JavaのOptionaとは？使い方をパターン別にわかりやすく解説](https://www.sejuku.net/blog/60892)
`bind': Address already in use - bind(2) for 127.0.0.1:3000 (Errno::EADDRINUSE)エラーの対処法

# 事象
何かしら処理をしている最中にサーバーを止めてしまった時、再度サーバーを立ち上げようとすると次のエラーが発生した。

```
`bind': Address already in use - bind(2) for 127.0.0.1:3000 (Errno::EADDRINUSE)
```

# 原因と対処法
既に3000番ポートが使われているというエラー。
解決方法は2つ

1. 別ポートを使用する
2. 使用されているプロセスを切る

## 1. 別ポートを使用する
3000番ボートが使用されているのなら別のポートを使用してサーバーを立ち上げればいい、という話。
※だが、根本的な解決にはなっていないので、2の方法をするのがいい

```
# ３０００番以外のポートで立ち上げる
rails s -p 8000
```

## 2.使用されているプロセスを切る

現在動いているrubyのプロセスを確認する

```
$ ps -ax | grep ruby
```

動いているプロセスがあれば次のように表示される。

```
6462 ttys011    0:12.64 /Users/*****/.rbenv/versions/2.5.3/bin/ruby bin/rails server
8380 ttys011    0:00.00 grep ruby
```

動いているrailsプロセスをkillします。

```
$ kill 6462
```

プロセスがkillされたか確認する


```
$ ps -ax | grep ruby
6462 ttys011    0:12.64 /Users/*****/.rbenv/versions/2.5.3/bin/ruby bin/rails server
8380 ttys011    0:00.00 grep ruby
```

切れていないようなので、killコマンドにオプションをつけて強制的にkillする

```
# "-9"は強制終了のオプション
$ kill -9 6462

# プロセスを再確認
$ ps -ax | grep ruby
 8405 ttys011    0:00.00 grep ruby
```

これでrailsプロセスは切れたのでrailsサーバーが立ち上がるようになっているはずです。

# 参考

- [rails s 時のエラー「Address already in use - bind(2) for "0.0.0.0" port 3000」の解決法【初心者】](https://qiita.com/shota0701nemoto/items/5fa5025cfd4783417b33)

- [rails sが通らない](http://hyottokoaloha.hatenablog.com/entry/2015/09/17/144100)

- [【kill】Linuxでプロセスを終了させるコマンド](https://uxmilk.jp/50638)
F*(f star) の処理系をインストールする

# Update(2022/11/09)
この記事はやや古くなっています。

ubuntuにおいて、2022/11/09に以下のリポジトリの手順で動くことを確かめました。
https://github.com/yuchiki/fstar-install-battle

# 前置き

F* とは、マイクロソフトとInriaが開発している強い型システムを備えたF#ライクな依存型言語です。
F*という言語の特徴については弊記事[F*(F Star)の複雑な型システムの何が嬉しいのか？](https://yuchiki1000yen.hatenablog.com/entry/2018/07/07/155854)をご覧ください。

インストール手順は[公式のrepositoryのインストール手順](https://github.com/FStarLang/FStar/blob/master/INSTALL.md) に従います。
$HOME/fstar というレポジトリが生成されますが、これにはライブラリが含まれています。削除すると実行ファイルがコンパイルできなくなります。

# linux

```sh
cd $HOME
wget https://github.com/FStarLang/FStar/releases/download/V0.9.7.0-alpha1/fstar_0.9.7.0-alpha1_Linux_x86_64.tar.gz -O - | tar -xz
sudo cp fstar/bin/fstar.exe /usr/local/bin/fstar.exe
sudo cp fstar/bin/z3 /usr/local/bin/z3
```

# Mac

```sh
cd $HOME
wget https://github.com/FStarLang/FStar/releases/download/V0.9.7.0-alpha1/fstar_0.9.7.0-alpha1_Darwin_x86_64.tar.gz -O - | tar -xz
sudo cp fstar/bin/fstar.exe /usr/local/bin/fstar.exe
sudo cp fstar/bin/z3 /usr/local/bin/z3
```

# 動作確認

動作確認用のレポジトリを用意しました。

```sh
git clone git@github.com:yuchiki/fstar_sample_repository.git
cd fstar_sample_repository
```

静的検査が通ることは以下で確かめられます。

```sh
make check
```

ocamloptなどがインストールされており、ocamlファイルをコンパイルできる環境が整っていれば、以下でコードを実行することができます。

```sh
make execute
```
[React] 「チュートリアル：React の導入」をやってみる (3)

#「チュートリアル：React の導入」

Reactの公式チュートリアルをやってみています！

リンク ： [チュートリアル：React の導入](https://ja.reactjs.org/tutorial/tutorial.html "チュートリアル：React の導入")

前回の記事0 ： [[React] 「チュートリアル：React の導入」をやってみる (npx create-react-app my-appについて)](https://qiita.com/IwashiMorino/items/0add4eb89f7e0ef3d883 "Qiita")

前回の記事1 ： [[React] 「チュートリアル：React の導入」をやってみる (1)](https://qiita.com/IwashiMorino/items/f100cb28c8a0085a198b "Qiita")

前回の記事2 ： [[React] 「チュートリアル：React の導入」をやってみる (2)](https://qiita.com/IwashiMorino/items/f100cb28c8a0085a198b "Qiita")

このチュートリアルは三目並べのゲームを作ってみようというものです。

###関数コンポーネント、 手番の処理、 ゲーム勝者の判定

今日は、関数コンポーネント、 手番の処理、 ゲーム勝者の判定までをやってみました。
基本的には、チュートリアル通りにコーディングしていけば、その通りに動くわけですが、JavaScript初学者にとっては、チュートリアルに書かれているコードがまず良くわからないわけですね。

> squares[i] = this.state.xIsNext ? 'X' : 'O';

例えば、上記の　?　ですが、これは JavaScript reference にある The conditional (ternary) operator（条件演算子 (三項演算子) ）を使っているのでしょうか？たぶん、きっとそうだろうと思います。

リンク　：　[JavaScript reference](http://qiita.com "JavaScript reference")

あと、ゲーム勝者の判定のコードも「下記のコードを貼り付けてください」となっていますが、非常に洗練されたコードではありますが、私のような素人には「やっていることは分かるけれど、何でこれで勝者の判定ができるのか？」ピンとこないです。

それで、非常に原始的な方法ですが、handleClick(i) の render() に下記のコードを加え、

```javascript:index.js
render() {
    const statuslog0 = this.state.squares[0];
    const statuslog1 = this.state.squares[1];
    const statuslog2 = this.state.squares[2];
    const statuslog3 = this.state.squares[3];
    const statuslog4 = this.state.squares[4];
    const statuslog5 = this.state.squares[5];
    const statuslog6 = this.state.squares[6];
    const statuslog7 = this.state.squares[7];
    const statuslog8 = this.state.squares[8];

    let status0;
    let status1;
    let status2;
    let status3;
    let status4;
    let status5;
    let status6;
    let status7;
    let status8;
    
    status0 = 'status0: ' + statuslog0;
    status1 = 'status1: ' + statuslog1;
    status2 = 'status2: ' + statuslog2;
    status3 = 'status3: ' + statuslog3;
    status4 = 'status4: ' + statuslog4;
    status5 = 'status5: ' + statuslog5;
    status6 = 'status6: ' + statuslog6;
    status7 = 'status7: ' + statuslog7;
    status8 = 'status8: ' + statuslog8;
```

return に {status0}から{status8} を書き加えました。

```javascript:index.js
return (
      <div>
        <div className="status">{status}</div>

        <div className="status">{status0}</div>
        <div className="status">{status1}</div>
        <div className="status">{status2}</div>
        <div className="status">{status3}</div>
        <div className="status">{status4}</div>
        <div className="status">{status5}</div>
        <div className="status">{status6}</div>
        <div className="status">{status7}</div>
        <div className="status">{status8}</div>
```

→→すると、ゲーム開始時には下図のようにすべての status が null になっていて、
![012a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/897250/3356e32f-5dbd-3d2e-3707-238ca15d6143.png)

→→ゲームを進めていくと下図のように status に値が入っていくのが分かりますね。
![013a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/897250/1c28f6c2-af87-b315-542b-b6490ed9d39e.png)

これで、このプログラムがやっていることが、少し分かりやすくなるかもしれませんね。

チュートリアルは、まだ続きますが、とりあえずひとまずここら辺りまでにしておこうかな、と思っています。そのうちもしかしたら続きをやるかもしれません。
Apacheでサーバーを立ててみる

# やりたかったこと
- ServerPCにApache等でサーバーを立て、WAN側からホームページを閲覧する

# ネットワーク構成のイメージ
- ServerPC はDeginnosスティックPC(OS:Win10)

![ネットワーク構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258852/240dce72-577a-9e69-f712-29689667eb37.png)

# 必要だった作業
## ServerPCにApacheをインストールし、初期設定後に起動した状態にする
- インストール方法、初期設定は、以下ページを参考に作業

https://www.adminweb.jp/

## ServerPCに固定IP(プライベートアドレス)を割り振る
- ONUの設定画面で、DHCPの固定割り当てで、MACアドレスと、割り当てたいIPアドレスを指定
- ServerPCのIPv4ネットワークプロパティで、IPアドレスを指定と、DNSアドレスを指定

## ONUにWAN側からのパケットを特定ポートで通過させる
- ONUのポートマッピングの設定という項目で、LAN側ホストのIPアドレス(ServerPCのIP)と、ポート番号とプロトコル(TCP)を指定

- ここでwifiルータより奥にServerPCをもっていきたい場合は、<BR>ONUとルータに、それぞれポートマッピングの設定が必要になるのかも。知らんけど。

## ServerPCのApacheサンプルのホームページにアクセスする
- スマホ等で、wifiを切断した状態で、http://[グローバルIP]:[ポート番号]でアクセスすると<BR>ページに接続できることが確認できた<BR>
[グローバルIPの確認は、確認できるサイトで調べる](https://www.cman.jp/network/support/go_access.cgi)
例)
http://xxx.xxx.xxx.xxx:8000 みたいな感じで指定する
ポート番号は省略すると、デフォルトで80番のポートが指定されるらしい
http://xxx.xxx.xxx.xxx:80

- ドメインを取得しておけば、IP直打ちではなく、http: //hogehoge.com などで、アクセスできるようになる<BR>
ドメインの取得は、お名前.com などのサービスで年間1000程度~ 契約できる。
ハードウェアとソフトウェアの切り分け

# ソフトウェアによるハードウェア機能の代替
組み込み用マイコンの性能が向上し、ソフトウェアの処理速度が速くなるにつれて、これまでハードウェアで処理しなければ速度的に間に合わなかった機能をソフトウェアによって代替できるようになった。
例えば、スイッチのチャタリング処理がある。押しボタンスイッチの構造上、一度しかスイッチ操作を行っていないにもかかわらず、短時間に接点が開閉してしまうことにより、複数回押したものと認識されてしまうチャタリングという現象が発生してしまうことがある。この現象を抑えるために従来はチャタリング除去回路というハードウェアを採用していたが、スイッチの数が多い製品や、量産品ではその生産台数分の部品が必要となり、コストアップにつながっていた。そこで定常状態を検出するプログラムによって代替させているのが一般的である。
そのため、ハードウェアはソフトウェアでどうしても代替することが困難であり、かつ、今後も変更することがなさそうな基本的な部分の最小限とし、それ以外はソフトウェアで代替させてしまうという傾向になってきている。
ソフトウェアは開発コストが比較的高めと言われているが、一度開発してしまえばいくらコピーしても費用がかからない。また、ハードウェアを変更することなく機能変更やバージョンアップを自由に行うことができるため、ソフトウェアはハードウェアに対して柔軟性とコストの両面で有利になる。
# ハードウェアとソフトウェアの特徴
||ハードウェア|ソフトウェア|
|---|---|---|
|変更|費用と日数が余分に必要になるため、作成した回路を変更するのは困難。|ROMRAMの容量が間に合えばプログラムの変更は可能。|
|並列操作|並列動作が基本であるため、高速処理が可能。|順番に処理を行うのが基本であるため、並列処理は困難。|
|デバッグ|回路図で動作の把握が比較的容易であるため、支援を得てのデバッグが可能。|チャートで可視化しても処理の把握は困難。他人の作成したプログラムは特に困難。|
|コスト|部品数に比例してコストがかかる。|プログラムはコピーするので数によらない。|
|大きさ|部品数が増加すると大型化する。|ハードウェアの一部をソフトウェアで代替することで部品数を減らせるので小型化が可能。|
# ハードウェアとソフトウェアの切り分け
生産数が多い場合、開発期間が長く取れる場合はソフトウェアの比率が高くなる。
生産数が少ない場合、開発期間が短い場合はハードウェアの比率が高くなる。
# 参考文献
坂巻佳壽美, トコトンやさしい組込みシステムの本, 今日からモノ知りシリーズ, 日刊工業新聞社, 2019年.
動画技術 (圧縮，ストリーミングなど) を学ぶ情報源

動画技術を学ぶ際に役立つ情報源のリストです。

# Webサイト
## [FFmpeg encoding and editing course](https://slhck.info/ffmpeg-encoding-course)
FFmpegの基本を学べる。

## [ffmpeg-libav-tutorial](https://github.com/leandromoreira/ffmpeg-libav-tutorial)
FFmpegのライブラリ (libav*)のAPIやffmpegの内部構造へ理解が深まる。

## [Awesome Video](https://github.com/krzemienski/awesome-video)
コーデックからストリーミング，エンコード，DRMまで網羅している情報源のリスト。

## [Demuxed](https://www.youtube.com/channel/UCIc_DkRxo9UgUSTvWVNCmpA)
動画技術に関するカンファレンスの講演。[LCEVC](https://www.youtube.com/watch?v=9BGfduVMKKY)など面白い講演が多数ある。

# Podcast
## [The Video Insiders](https://thevideoinsiders.simplecast.com/)
[Beamr](https://beamr.com/)のホスト2人が動画技術の専門家のゲストにインタビュー。

## [Demuxed](https://www.heavybit.com/library/podcasts/demuxed/)
Demuxed主催者，video.jsを始めたエンジニアがゲストにインタビューするPodcast。HLSなどストリーミング系の話が多い。
librosaの基本処理

## librosaの基本処理

### インポート
```
import librosa
```


### データ読み込み
```
y,sr = librosa.load(file, sr=None)

# yは振幅
# srはサンプリングレート
```

### 波形の描画
```
fig, ax = plt.subplots(figsize = (16, 2))
fig.suptitle('Sound Waves', fontsize=16)

librosa.display.waveplot(y = y, color = "b")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684234/8bd2d293-4d66-74a8-eb1c-e09bbb9eff9f.png)

### メルスペクトログラムの作成
```
y = librosa.feature.melspectrogram(y,n_mels=256)
# メル周波係数の計算

y = librosa.power_to_db(y).astype(np.float32)
# dB(デジベル、音圧)に変換
```

### メルスペクトログラムの表示
```
plt.figure(figsize=(12, 4))
librosa.display.specshow(y)
plt.title('mel power spectrogram')
plt.colorbar(format='%02.0f dB')
plt.tight_layout()
```
![ダウンロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684234/bfbf5d58-9833-e3d9-4c4b-20e21c84aec4.png)
TortoiseGitのマージツールをその都度選択して起動できるようにする

# 概要
TortoiseGitを使っている。
競合が発生した際にはマージツールによってマージ作業を行う必要がある。
単純なマージ作業(いずれかを選択する、もしくは両方を採用する等)であれば、P4Mergeが断然使いやすい。(※個人の見解です)
一方、単純でないマージ作業(変更点を部分的に採用する等)の場合、普段使っているEmacsを使いたい。(※個人の見解です)
そこで、TortoiseGitのマージツールに選択起動できるツール(マージツールセレクタ)を設定することを思いついた。

私の場合、最初はP4Mergeを起動したく、diffを見て本気のマージが必要、と判断したときにemacsを起動したい。

Python/PyQt5 で作ってみた。

# ツール

P4Merge、emacsのパスが決め打ちだが、アップしてみた。

https://github.com/wurly200a/MergeToolSelector

# 使用例

## マージツールセレクタが起動

いずれかのボタンを押すことでマージツールが起動する。

![MergeToolSelector01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201153/088d433a-0b43-85f7-5f77-e01119bb8a7f.png)

## P4Merge

P4Mergeを起動した例。
このような単純な例であれば、P4Mergeがdiffも見やすいしマージもし易い。

![mts_p4merge01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201153/87b6371c-e4f7-81b0-1cb3-5ffe332742b7.png)

## emacs

単純でない場合には、普段使っているエディタで編集したいところ。自分の場合にはemacs。

![mts_emacs01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201153/4cd4e78f-1f01-af78-f244-0c5ee99b505c.png)


# 設定方法

`mergeToolSelector.bat %base %theirs %mine %merged %bname %tname %yname %mname`

![MergeToolSelectorSetting01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201153/5fc621ab-8608-92bd-6a22-20c7503efdbe.png)

# 改善点

- defaultのマージツール(自分の場合はP4Merge)が自動で起動するようにしておき、必要に応じて別のツールを選択起動できるような機能を盛り込みたい
- さすがに決め打ちはどうかと思うので設定ファイルでマージツールのパスを指定できるようにする
- その他のツールも指定できるようにする
    - TotoiseGitMerge や WinMerge とか
- 引数も任意に指定できるようにして、より汎用的にしたい
Rubyの2重ハッシュ

配列の中に、複数のユーザーの情報をハッシュとして持つuser_dataがあります。

```ruby
user_data = [ {user: {profile: {name: 'Ken' }}}, 
              {user: {profile: {name: 'Ichiro' }}},
              {user: {profile: {name: 'Yuki' 
 }}},
]

#ターミナルでの出力結果
Ken
Ichiro
Yuki
```

user_dataを利用して、全てのユーザーの名前だけが出力されるようにRubyでコーディングを行いたい場合どうしたら良いでしょうか。



ハッシュから特定の値を取得するには、

```ruby
ハッシュ[取得したい値のキー]
```

で取得ができます。2重ハッシュから特定の値を取得したい場合は、取得したい値のキーまで連続して指定すると取得することができます。

```ruby
ハッシュ[取得したい値のキー][取得したい値のキー]
```

今回の場合、名前を取得したいので、

```ruby
ハッシュ[:user][:profile][:name]
```

で取得ができます。


また、配列の中にハッシュが格納されているためeach文でハッシュの一つ一つを取り出して名前を取り出す必要があります。

よって

```ruby
user_data = [ {user: {profile: {name: 'Ken' }}}, 
              {user: {profile: {name: 'Ichiro' }}},
              {user: {profile: {name: 'Yuki' 
 }}},
]

#の中の名前は

user_data.each do |u|
  puts u[:user][:profile][:name]
end
```
のように記述することで名前を取り出すことができます。
pybind11 で py::dict を扱うメモ

## 背景

設定パラメータや関数の引数を `py::dict` で C++ に渡したい.
たとえば JSON データを python 側でパースして dict にしておき, C++ 側に dict で渡すなど.

例によってドキュメントにはほとんど記載が無いので, ソースコードを見たりして解決する必要があります.

## dict の作成と, 要素の追加

```c++
  py::dict d;

  d["bora"] = "yes";
```

C++ `std::map` のように使えます.

string や double など基本型の場合は C++ の型そのままでいけるはずです!


## キーがあるかのチェック

contains を使います.

```
if (d.contains("bora")) {
  // got it!
}
```

## 要素の型チェック

要素は `std::any` 的な感じで `py::object` なオブジェクトになっています.

要素が求める型かどうかのチェックは `py::isinstance` を使うのがよいでしょう.

```c++
if (py::isinstance<py::str>(d["bora"])) {
  std::cout << "got str type\n";
}
```

`py::type::of(h)` での比較もできるようですが... テストコードなどにも例がなかったので諦めました.

### None かのチェック

`is_none` があります.

```c++
d["bora"].is_none()
```

## 要素の値の取得

要素の値を取得する場合は, 具体的な型を指定する必要があります.

`py::cast` を使います.

```c++
std::cout << "bora? " << d["bora"].cast<py::str>() << "\n";
```

## イテレートする

`std::map` のように `begin()`, `end()` で iterate できます. `first` に key, `second` に要素があります.

```c++
for (auto it = d.begin(); it != d.end(); it++) {
  std::cout << "key: " << it->first << "\n";
}
```

## まとめ

他にも API ありますが, だいたいはこれでいけるでしょう!
AUv3環境下でのJUCEのAudioProcessorEditorのwidthおよびheight

iOS 14がインストールされた実デバイスでの計測値は下記。AudioProcessorEditorのresized()でgetWidth()/getHeight()にて取得。

| App                                 | iPad Pro 9.7       | iPhone 11 Pro   |
|:------------------------------------|-------------------:|:---------------:|
| Standalone (Landscape)              | 1024 x 768 (1.33) | 812 x 375 (2.17) |
| Standalone (Portrait)               | 768 x 1024 (0.75) | 375 x 812 (0.46) |
| GarageBand 2.3.10                   | 1024 x 335 (3.06) | 667 x 202 (3.30) |
| Cubasis 2.8.4                       | 1024 x 342 (2.99) | -                |
| Cubasis 2.8.4 (with side bar)       | 811 x 342 (2.37)  | -                |
| Camelot 2.0.1 (Landscape)           | 1018 x 334 (3.04) | -                |
| Camelot 2.0.1 (Landscape, Expanded) | 1018 x 718 (1.42) | -                |
| Camelot 2.0.1 (Portrait)            | 762 x 462  (1.65) | -                | 
| Camelot 2.0.1 (Portrait, Expanded)  | 762 x 974  (0.78) | -                |
credentials.yml.encとmaster.key＜備忘録＞

# 概念
### credentials.yml.encとmaster.key
Rails5.2から登場したアプリの秘密情報を管理するための仕組み

#### master.key
credentials.yml.encに書かれた暗号化された秘密情報を、複合化するための秘密鍵が書かれたファイル

#### credentials.yml.enc
`credentials.yml`を暗号化したファイル

#### credentials.yml
秘密情報が書かれたファイル

# 使用方法
### 秘密情報を編集する時
直接`credentials.yml.enc`を編集するのではなく、以下のコマンドで編集する

```
EDITOR='vim' rails credentials:edit
```
#### なぜ直接`credentials.yml.enc`を編集しないのか？
`credentials.yml.enc`は暗号化されたファイルでありそれを編集する事はできないから。(.encは暗号化されたファイルという意味)

### 秘密情報を呼び出す時
Rails consoleを起動した後、下記のコマンドを打つ

```
Rails.application.credentials[:取得したい秘密情報]
```

### 参考
https://hirocorpblog.com/rails-credentials-master/#toc1
Dockerのコンテナ同士をネットワーク接続できるようにする

# 初めに
docker composeで同時に作らなくても、後からコンテナ同士をネットワーク接続できる方法

## 以下のような状況と仮定して
- mysqlのコンテナ`db-mysql` と php のコンテナ `app-php` のコンテナがあると仮定する
- `app-php` のコンテナから、`db-mysql` DB接続したい
- 各コンテナは別々で管理（作成）されている
- wslのように、ローカル端末を使っている

### 特定コンテナの所属ネットワークグループを調査
```shell
docker inspect --format '{{ .NetworkSettings.Networks }}' [コンテナ名]
```

- 実行例
```shell
docker inspect --format '{{ .NetworkSettings.Networks }}' db-mysql
# map[mysql_default:0xc000548000]
# 上記のような実行結果が出る
```
このような場合、db-mysqlコンテナの属するネットワークグループは`mysql_default`になる

### コンテナにネットワークグループを追加
```
docker network connect [ネットワークグループ] [コンテナ名]
```

- 実行例
```
docker network connect mysql_default app-php
```
上記のようにコマンドを実行すると、app-phpのコンテナ内から、ホストに db-mysql を指定すると、接続することができる。
こうすることで、composeで作成した時と同じように名称でIP引用できる仕組みになる。
本来は expose のように、コンテナからしか接続できない仕組みにしたいときに使うのが一般的ではあるのでしょうが、ローカルの時はこんな風にやってしまってもよいのかと。
 
- 確認例
```shell
# コンテナ内に入る
docker exec -ti app-php bash
# 疎通確認
curl db-mysql:3306
```

# 最後に
過去記事をシナリオベースに改編。。。
ホストからコンテナにはlocalhostでつなげるが、コンテナ同士はlocalhostでつなげない。これ大事。
ちなみに、Linuxのようなサーバー上ではホストのLANのIPを指定すると問題なくつながるので、そんなやり方でもよいのでしょうが、、
忙しい研究者のためのテストコードとドキュメントの書き方、Elixir編

@hmkz さんの「[忙しい研究者のためのテストコードとドキュメントの書き方](https://qiita.com/hmkz/items/0689cd85fb3e1adcda1a)」が素晴らしかったので、Elixirでのやり方をまとめておきます。

# Step 0: 環境構築

## テスト環境：doctest

Elixir標準のdoctestマクロを使います。（後述するため、ここでは何もしません。


## ドキュメント生成ライブラリ：[ExDoc](https://github.com/elixir-lang/ex_doc)

「[Using ExDoc with Mix](https://github.com/elixir-lang/ex_doc#using-exdoc-with-mix)」に従って、depsにex_docを追加し、 "mix deps.get" するだけです。


## サンプルプロジェクト

使い方を見ていくためにサンプルプロジェクトを作っておきます。

~~~ 
$ mix new sample
# 中略
$ cd sample
$ vim mix.exs # ex_docをdepsに追加して
$ mix deps.get
~~~

# Step 1: 関数を書く

算術関数を集めたMathモジュールを作ってみましょう。

モジュールを作り、

~~~
$ mkdir lib/sample
$ vim lib/sample/math.ex
~~~

欲しい関数のガワだけを作っておきます。

~~~ elixir
defmodule Sample.Math do
  def add(x, y) do
    :not_implemented
  end
end
~~~


# Step 2: ドキュメントを書く

関数のドキュメントを書きます。
そして、その使用例を iex> で始まる行に、その結果を次の行に書きます。（これが後にテストされるようになります。

~~~ elixir
@doc """
# 足し算
addは引数を2つ取り、足し算した結果を返します。

      iex> Sample.Math.add(1,2)
      3
"""
defmodule Sample.Math do
  def add(x, y) do
    :not_implemented
  end
end
~~~

# Step 3: テストする

対象モジュールをテスト対象に含めるために test/sample_test.ex に一行追加すれば、

~~~elixir
defmodule SampleTest do
  use ExUnit.Case
  doctest Sample
  doctest Sample.Math # 追加行、doctestマクロの後に対象モジュール名を書く

  # 略
end
~~~

テストできるようになります。

~~~
$ mix test
Compiling 1 file (.ex)
warning: variable "x" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/sample/math.ex:9: Sample.Math.add/2

warning: variable "y" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/sample/math.ex:9: Sample.Math.add/2

.

  1) doctest Sample.Math.add/2 (1) (SampleTest)
     test/sample_test.exs:4
     Doctest failed
     doctest:
       iex> Sample.Math.add(1,2)
       3
     code:  Sample.Math.add(1, 2) === 3
     left:  :not_implemented
     right: 3
     stacktrace:
       lib/sample/math.ex:6: Sample.Math (module)

.

Finished in 0.04 seconds
2 doctests, 1 test, 1 failure
~~~

関数のロジックが未実装なので、ドキュメントの使用例とその結果が一致せずテストが失敗しています。


# Step 4: 実装する

テストをパスするように実装します。

~~~ elixir
defmodule Sample.Math do
  @doc """
  # 足し算
  addは引数を2つ取り、足し算した結果を返します。

      iex> Sample.Math.add(1,2)
      3
  """
  def add(x, y) do
    x + y
  end
end
~~~

実装できたら、再度テストしましょう。

~~~
$ mix test
Compiling 1 file (.ex)
...

Finished in 0.04 seconds
2 doctests, 1 test, 0 failures
~~~

テストがパスするようになりました♪


# Step 5: ドキュメントを生成する

ドキュメントの生成は "mix docs" でできます。

~~~
$ mix docs
# 中略
Generating docs...
View "html" docs at "doc/index.html"
View "epub" docs at "doc/sample.epub" # epubも出力できるんですね！
~~~

index.htmlをブラウザで開いて該当モジュールを見ると、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369713/939dafcd-8bcc-4e3a-9977-419025730ee6.png)

キレイなドキュメントが出力されています。いぇい！

# 参考

doctestの書き方は以下が参考になります。

* @ma2ge さんの [Elixir の doctest 書き方まとめ](https://qiita.com/ma2ge/items/b6b26335ecc1b2181897) 
* 公式の [ExUnit.DocTest](https://hexdocs.pm/ex_unit/ExUnit.DocTest.html)

Elixirのドキュメントの書き方は以下が参考になります。

* 公式の [Writing Documentation](https://hexdocs.pm/elixir/writing-documentation.html)

以上です。

**Happy Hacking with Elixir!!**
【PHP】メソッド内で関数の呼び出し　Fatal error: Call to undefined functionエラー

メソッド内で関数を呼び出そうとすると、「Fatal error: Call to undefined function...(未定義の関数を呼び出そうとしている)」というエラーになります。

```.php

//Fatal error: Call to undefined function...
class Example
function a(){ 
  echo 'Hello';
}
function b(){
  a();
}

```

メソッド内で異なるメソッドを呼び出す場合は、「$this->メソッド名()」と明記するとエラーを解決できます。

```.php

class Example
function a(){ 
  echo 'Hello';
}
function b(){
  $this->a();
}

```
macOS Big Sur にてUnityLoader.js が原因でWebGLが動作しないとき

## Unityで作られたファイルがブラウザで動作しない
Unity WebGLをブラウザで開こうとしたところ、動作しなかった。最初は、WebGLがChromeやSafariでアクティベートされていないのが問題だと思い、再設定をしてみたが改善せず、、、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M1 Mac (Big Sur)とChrome , safariで、Unity のWebGLが動いてくれないんですが、同じ症状の方いますか？</p>&mdash; 伊藤光平｜Kohei Ito (@acetrigger_99) <a href="https://twitter.com/acetrigger_99/status/1344860334570409989?ref_src=twsrc%5Etfw">January 1, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

そんなことをつぶやいたら、@gtk2kさんがエラーをもとに解決方法を教えてくれた。

## 解決方法

指示通りブラウザのコンソールを確認したら、以下のエラーが出力された。

```
Uncaught TypeError: Cannot read property '1' of null
    at UnityLoader.js?t=1591981784037:3
    at UnityLoader.js?t=1591981784037:4
```

Unity WebGLでは、`index.html`にて`UnityLoader.js`がローディングされる。ここで、OSやブラウザのバージョン判定を行っている。
以下のように`UnityLoader.js`を修正すると動作が確認された。

```UnityLoader.js
// 修正前
case"Mac OS X":p=/Mac OS X (1０[\.\_\d]+)/.exec(a)[1]

// 修正後
case"Mac OS X":p=/Mac OS X (1[\.\_\d]+)/.exec(a)[1]
```

macOS Big Surは11.xとなっており、修正前の正規表現`(10[\.\_\d]+)`だと10.xしか認識されないことになってしまう。

**追記（2020/01/10）**
@aguroshou0413さんにコメントで以下のコードだと、Big SurだけではなくCatalinaでも動くと教えていただいた。
`(1[0-1][._\d]+)/`だと、10.xも11.xも内包する。

```UnityLoader.js
case"Mac OS X":p=/Mac OS X (1[0-1][._\d]+)/.exec(i)[1];
```

以下で、MacのOSを確認できる。

```bash
$ sw_vers
ProductName:    macOS
ProductVersion: 11.1
BuildVersion:   20C69
```

アドバイスを下さった@gtk2kさん、@aguroshou0413さん、ありがとうございました！

## ビルドしたファイルの実行

ビルドしたファイルのディレクトリ上で、以下のコマンドを実行。

```bash
python3 -m http.server 8000
```
その後、以下のリンクをブラウザで開く。
[http://localhost:8000](http://localhost:8000)

## 参考記事
[Bug? Generated UnityLoader.js fails in iOS 14 public beta](https://forum.unity.com/threads/bug-generated-unityloader-js-fails-in-ios-14-public-beta.942484/#post-6152134)

[JavaScriptでブラウザとOSを判定する2つの方法](https://qiita.com/TD12734/items/671064e8fce75faea98d)
Laravelで正しくルーティングしているのに404エラーが出る時

#原因
**public以下に同名フォルダやファイルがある(場合がある)。**

Laravelでは実在するディレクトリへ優先的にアクセスされるので、

``` php
Route::get('/dir/file', function () {
    return view('dir.file');
})->name('dir.file');
```
このようにルーティングしておき、`https://domain.com/dir/file`へアクセスするとき、

`/public/dir/`というディレクトリが存在していると、
`/public/dir/file`という**実在するファイル**を探しに行ってしまう模様。
当然、`file`などという実ファイルは設置していないので404エラーになる。

#解決方法
・public以下の同名フォルダやファイルを削除またはリネームする
・競合しないPATHに変更する

#あとがき
一部のURLだけ404になる場合などは、上記のような原因が多いと思います。

「Laravel 404 route」などで検索しても、次のような原因のものばかりだったので、今回記事にしました。
参考: [【Laravel】ルーティングをしているはずが404エラー？](https://qiita.com/msht0511/items/b32122413745d0a3d50a)
PlantUMLの環境構築

# はじめに
先日ユースケース図を書く機会がありました。今回PlantUMLというツールを使うことになったので、環境構築した際のメモになります。

# PlantUMLについて
公式ホームページを確認してください。ブラウザで動作するジェネレータが用意されているので、イメージがつきやすいかと思います。

[https://plantuml.com/ja/](https://plantuml.com/ja/)

# 前提
使用しているOSはmacOS Big Surです(M1チップ)。エディタはVisual Studio Codeを使用します。

# 環境構築
### Javaをインストールする

PlantUMLを実行するためにはJavaが必要になりますので、以下のコマンドでバージョンを確認します。

```
java --version
openjdk 15.0.1 2020-10-20
OpenJDK Runtime Environment (build 15.0.1+9)
OpenJDK 64-Bit Server VM (build 15.0.1+9, mixed mode, sharing)
```

もしJavaがインストールされていないようでしたら、下記リンク先からダウンロード可能です。

[https://java.com/ja/](https://java.com/ja/)

### Graphvizをインストールする

PlantUMLが図を描画するために必要なようです。下記リンク先からインストールします。

[http://www.graphviz.org/download/](http://www.graphviz.org/download/)

### PlantUMLをインストールする

下記リンク先からインストールします。

[https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml)

Visual Studio Code上のMarket PlaceでPlant UMLと検索してインストールすることもできます。
※インストール後、VSCodeのリロードが必要です。

これで optionキー + d でユースケース図をプレビューすることができるようになります。

### Markdown Preview Enhancedをインストールする

このエクステンションを導入することで、MarkdownとPlantUMLを合わせてプレビューすることができるようになります。下記リンク先からインストールできます。こちらもPlantUML同様にVisual Studio Code上のMarket Placeからも入手可能です。

[https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)

右クリックして「Markdown Preview Enhanced: Open Preview to the Side」をクリックする、もしくはCommandキー + K + V でプレビューが表示されます。

## 最後に

以上、PlantUMLの環境構築でした。見ていただきありがとうございました。
【Mac】MacのデスクトップにあるDockを隠す

<< [【Mac】MacOSの基本操作を覚える](https://qiita.com/hiroyuki-eguchi-0731/items/99a0d771fda18adac9f0)

# MacのデスクトップにあるDockを隠す

![スクリーンショット 2021-01-02 16.58.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406574/7fc88486-725e-dd63-f126-b75832babc40.png)

そろそろこいつ（↑）存在が気になりだしてきた。
名前がわからなかったけど、調べてみるとDockというらしい。

便利なのかもしれないけど、Windowsのタスクバーに相当するものは画面上部にあるので、これが画面下に鎮座していると何か違和感を感じるんですよね。

ということで、こいつを非表示にすることができないのか調べてみることにしました。

## Dockの設定ができるメニューを探す

こういう設定はOS標準だろうから、左上のリンゴマークから［システム環境設定］をクリックしてみる。

![スクリーンショット 2021-01-02 17.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406574/ad138993-949c-7552-3d4f-af2bb4a78cbd.png)

「Dockとメニューバー」ってのがありますね。早速表示してみる。

## Dockを自動的に表示

発見。

![スクリーンショット 2021-01-02 17.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406574/2ea30b47-5d94-2419-3d0b-20c2e9f1fdef.png)

「Dockを自動的に表示/非表示」の項目があるのでチェックしてみると画面下にまでマウスを持っていかない限りは画面表示しないようになった。

他にも色々と設定ができるようなので自分好みにカスタマイズすれば良さそうですねー。

---

2021-01-02 初稿
JRubyでLibreOffice Calcのfodsファイルを読み書きするサンプル 2021

sonota88/libreoffice-jruby-sample (tag: 20210102)
https://github.com/sonota88/libreoffice-jruby-sample/tree/20210102

以前書いた↓これのアップデートと、「2021年初でも動きましたよ」という動作報告です。
[JRubyでLibreOffice Calcのfodsファイルを読み書きするサンプル 2019](https://memo88.hatenablog.com/entry/2019/12/02/230545)

# 変更点

- JRuby のバージョンアップ
    - 9.2.9.0 → 9.2.14.0
- 機能追加: `Sheet#used_row_index_max` , `Sheet#used_column_index_max`
    - 使用している範囲内の行・列の最大インデックスを取得
- `XDesktop.terminate()` を使って終了するようにした
- サンプルファイルもリポジトリに追加
- Docker 対応
- その他、細かい変更・リファクタリングなど

---

Docker 対応してみました。 Ubuntu 18.04  ベースです。

Docker 化すると、`libreoffice-dev` や JRE など必要なパッケージも Dockerfile 見ると分かるようになって、よいですね。

```bash
# イメージのビルド
docker build -t my:libo-jruby .

# サンプルの実行
docker run --rm -it -v "$(pwd):/root/work" my:libo-jruby \
  bash jruby.sh dump.rb sample.fods Sheet1
```

# 参考

- [LibreOffice 6.4 SDK - Developer's Guide Examples](https://api.libreoffice.org/examples/DevelopersGuide/examples.html#OfficeDevelopment)
    - TerminationTest.java を参考にした




# この記事を読んだ人はこちらも読んでいます（たぶん）

- [LibreOffice Calcのfodsファイルを読み書きするサンプルをweb API化してみた](https://qiita.com/sonota88/items/2412dc6389d9bae3add6)
- [JavaでLibreOffice Calcのfodsファイルを読み書きするサンプル 2021](https://memo88.hatenablog.com/entry/2021/01/01/155345)
- [Ruby+PyCall.rbでLibreOffice Calcのオートメーションをやってみた（Ubuntu 18.04）](https://memo88.hatenablog.com/entry/2020/12/20/111104)
- [LibreOffice Calcの入ったDockerイメージを作ってヘッドレスで動かす](https://memo88.hatenablog.com/entry/2019/11/03/090019)




# 他に LibreOffice 関連で書いたもの

https://memo88.hatenablog.com/archive/category/LibreOffice

# 他に Ruby 関連で書いたもの

https://memo88.hatenablog.com/archive/category/Ruby