OmniAICreator/Qiita-1.07M huggingface dataset:
【UiPath】設定ファイルの書き方（応用編）

# はじめに

この投稿は、RPAツール「UiPath」での 設定ファイルの書き方 について記事です。
今回は、細かいTipsを紹介したいと思います。

UiPathのコミュニティ「UiPath Friends」が企画する「UiPathブログ発信チャレンジ2021サマー」の 21日目の投稿でもあります。

企画の内容は [**こちら**](https://note.com/shumpei_w/n/n651cbdbec4e8) 。カレンダーのURLは [**こちら**](http://u0u1.net/sUwZ) です。

https://twitter.com/ShumpeiWatanabe/status/1405168150736359427

# 設定ファイルを書きながら設計をする

設計をする際に「何を設定ファイルに持たせようかな」とイメージして設定ファイル書くと、素早く実装に入れます。

「良い設計」がされているフローは、設定ファイルを見ただけで、処理内容を理解できます。 `流れ・ポイントが明確になっていて、ある意味「設計書的な役割」を果たすから` です。

どう書くのが良いのか？はチームによって違いますが、例えば以下のようにして書くと良いかも知れません。

```
　- 設定項目を「処理の単位」でをまとめる
　- 空白行を入れて「処理の切れ目」を表現する
　- 「入出力の情報」はまとめて、InOutが分かるようにする
　- 項目に対して「極力シンプルな説明」が書かれている
```


# 設定ファイルの値チェックは「必要最低限」で良い

設定ファイルの項目は「実装中」も「仕様変更」の際も容易に増減します。そして「値のチェック」を実装するのは結構面倒です。 `RPAはローコードのスピード開発なので、手間は極力省きたい。`

そもそも設定値を間違えていたら「実行エラー」で止まれば良く、思い切って「値の事前検証チェックは無し」でも大丈夫だと思います。だって、チェック実装してる時間がもったいないから。

ただし「この項目だけは保証しておきたい」という項目は、初期処理の中でチェックするほうが安心だと思います。（例えば「入力ファイルのフォルダ有無」など）

また、エクセルの特性を生かして「入力規則」でエラー値を防ぐという方法もあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/2907f605-2e83-cdb6-f749-5bd213af29ad.png)


# 設定ファイルはプロジェクト内に置くべきか？

Reframework等のテンプレートプロジェクトはその便宜上、設定ファイルをプロジェクトに含んでしています。（じゃないと仕組みを説明しにくいから）

デメリットとして「設定ファイルもxamlファイルと同じ扱いになり、気軽に変更できない」というものがあります。先に書いたように「設定ファイルには、後で変更する可能性を書く」もので、変更したいときにはプロジェクトを再生成＝パブリッシュしないといけないのは少し残念です。

なので、以下のような方法で「設定ファイルをプロジェクトに含まない」とする選択肢もあります。

```
1）設定ファイルのパスを固定にする
　　例）デスクトップ、共有フォルダの固定パス

2）Orchestratorのアセットにパスを記述し、フローの内部で取得する
　　例）[Name]ConfigPathOfProcessA   [value]z:\robot\ConfigOfProcessA.congfig

3）実行マシンのレジストリにパスを記述し、フローの内部で取得する
　　例）[Name]ConfigPathOfProcessA   [value]z:\robot\ConfigOfProcessA.congfig　
```

# 設定ファイルの内容をログ出力する

処理結果を後で見た時に「その処理が、どういう設定内容で実行されたか」を記録として残しておくと、エラーの把握、原因調査時に有益です。具体的には「設定ファイルの内容をログ出力しておく」と便利です。

個人的には以下のような方法で、設定ファイルを読み込んだ際に内容を出力しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/8774cb0f-e0e1-26c7-248f-b64ea61d611b.png)

```
＜メッセージに設定している値＞
"ReadAndOverrideConfig - 設定内容：" & Environment.NewLine & String.Join(Environment.NewLine, From kv In out_dicConfig Select " - " & kv.Key & "：" & if(kv.Key.Contains("パスワード"), new String("*"c, kv.Value.Length), kv.Value))
```

※ 項目名に「パスワード」を含む場合はアスタリスクで伏せ字にしています


# 設定ファイルパスとシート名も格納しておく

設定ファイルの読み込み時に、コードの中で「設定ファイルの場所・シート名」を設定ディクショナリに入れておくと、追加で設定シートを読み込みたくなった場合に便利です。
![ini.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/7b399746-6c65-f567-bfcd-2cc4ffec9163.png)

デバッグのログ出力と合わせると「どの設定ファイルを読んで実行されたのか」も分かり便利です。

# 終わりに

いかがでしたでしょうか。

運用も含め「設定ファイルをどう扱うか」は、要件によって考える必要がありますが、その際に参考になれば幸いです。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
Red Hat Enterprise Linux 8をWSL2で使う

# 目的

WSL2でRHEL8を使えるようにします。当手順では試用版サブスクリプションを使い続けることを想定します。もちろん無料です。

# 手順

## RHEL8イメージのダウンロード

Red Hat Customer Portalのアカウントを作ってログインします。

> https://access.redhat.com/

ISOイメージをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/bbe08823-b865-1252-4802-bb606505ead5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/edef758c-2e5a-c090-04b1-e2b6d03db650.png)

## アーカイブの作成

Hyper-VやVirtualBoxなどを使って、ISOイメージからRHEL8の仮想マシンを作成します。最小インストールでよいです。

OS起動後、/以下の指定のディレクトリをアーカイブします。

```
# cd /
# tar cvfzp rhel8.tar.gz bin dev etc home lib lib64 media opt run root sbin srv usr var
```

## WSL2へのインポート

アーカイブをWindowsの任意のフォルダにコピーします。

コマンドプロンプトでアーカイブをインポートします。

```
>wsl --import RHEL8 . rhel8.tar.gz --version 2
>wsl -l
Linux 用 Windows サブシステム ディストリビューション:
docker-desktop-data (既定)
docker-desktop
RHEL8
```

## ディレクトリ・ユーザーの設定

そのままではrootユーザーで実行されますので、普段利用する非rootユーザーを作成します。パスワードなしでsudoするためにwheelの設定もします。

```
>wsl -d RHEL8

# mkdir /tmp
# chmod 1777 /tmp
# echo "%wheel ALL=(ALL) NOPASSWD: ALL" >/etc/sudoers.d/wheel
# useradd -G wheel teruz
# exit
```

ユーザーを指定してRHEL8を実行して動作確認します。

```
>wsl -d RHEL8 -u teruz
$ sudo ls /
$ exit
```

## ショートカットの作成

毎回コマンドを打つのは面倒なので、ショートカットを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/b53fd141-ab25-9b10-2c50-9fa4cf242de6.png)

作業フォルダを上記のように指定するのがポイントです。さもないと起動時のカレントディレクトリがWindowsユーザーのDesktopになってしまい、RHEL8のホームディレクリまでわざわざcdしないといけなくなるためです。

## サブスクリプションの更新

Trialサブスクリプションは60日しか有効ではありません。

```
# subscription-manager list
+-------------------------------------------+
    インストール済み製品のステータス
+-------------------------------------------+
製品名:           Red Hat Enterprise Linux for x86_64
製品 ID:          479
バージョン:       8.4
アーキテクチャー: x86_64
状態:             サブスクライブ済み
状態の詳細:
開始:             2021年06月11日
終了:             2021年08月10日
```

サブスクリプションが切れるとdnfを使ったパッケージのインストールやアップデートができなくなります。そのため、少々面倒ですが、定期的に下記のようにサブスクリプションを更新してください。

```
# subscription-manager unregister
登録の解除中: subscription.rhsm.redhat.com:443/subscription
システムの登録は解除されました。

# subscription-manager register --username ******** --password ********
登録中: subscription.rhsm.redhat.com:443/subscription
このシステムは、次の ID で登録されました: ********-****-****-****-************
登録したシステム名: ********

# subscription-manager role --set="Red Hat Enterprise Linux Server"
role を "Red Hat Enterprise Linux Server" に設定しました。

# subscription-manager service-level --set="Self-Support"
service_level_agreement を "Self-Support" に設定しました。

# subscription-manager usage --set="Development/Test"
usage を "Development/Test" に設定しました。

# subscription-manager attach
インストール済み製品の現在の状態:
製品名: Red Hat Enterprise Linux for x86_64
状態:   サブスクライブ済み

# subscription-manager list
+-------------------------------------------+
    インストール済み製品のステータス
+-------------------------------------------+
製品名:           Red Hat Enterprise Linux for x86_64
製品 ID:          479
バージョン:       8.4
アーキテクチャー: x86_64
状態:             サブスクライブ済み
状態の詳細:
開始:             2021年xx月xx日
終了:             2021年yy月yy日
```

# 参考

> https://access.redhat.com/discussions/5398621
JSONデータへのアクセス方法


JSONデータへのアクセス方法

```javascript

  const jsonData = { firstName: 'Tanaka' };

  console.log('OK:', jsonData.firstName) //OK: Tanaka
  console.log('OK:', jsonData.age) //OK: undefined
  console.log('OK:', jsonData['firstName']) //OK: Tanaka
  console.log('OK:', jsonData['age']) //OK: undefined
  console.log('NG:', jsonData.age.year) //TypeError: Cannot read property 'year' of undefined
  console.log('NG:', jsonData['age'].year) //TypeError: Cannot read property 'year' of undefined

```

APIのレスポンスで想定していないケースが発生した場合はどうするのがベストなのだろう。
・ネストが正しいかどうかをまず判断する？
・forやmapで要素を取得しに行く時などは、いちいちtry-catchなどをすべき？
Rails  resourcesのexceptとonlyの使い方

#resources
resourcesメソッドを使用した際、indexアクションとshowアクションだけを
指定したいときには下記のように記述する.

```routes.rb
puts 'The best 
Rails.application.routes.draw do
  resources :コントローラー名, only: [:index, :snow]
end
```


または

```routes.rb
puts 'The best 
Rails.application.routes.draw do
resources :コントローラー名, except: [:new, :create, :edit, :update, :destroy]
end
```

onlyが指定したいアクションを　exceptが指定したくないアクションを適用します。
onlyを使ったほうが使用するアクションがわかりやすいのでこちらを使うのが思います。
LWCでのStyling Hooks

# 1.目的
今回```Lighting Desigin System```で提供された標準デザインを変えようと思います。
基本的には**スタイルフック**を使って、標準のデザインを変えます。**但しこの方法ではSalesforce側しか使えないので。使う時にご注意ください。**

# 2.ソース構成図
```
lwc
 └─stylingHooksDemo
```

#### stylingHooksDemo
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1767576/49f39a88-45c1-8b2f-daba-9b43244756f1.png)

```stylingHooksDemo.css
.my-css {
    --sds-c-button-brand-color-background: #BB00FF;
    --sds-c-button-brand-color-background-hover: #8700B8;
    --sds-c-button-brand-color-border: #BB00FF;
    --sds-c-button-brand-color-border-hover: #8700B8;
  }
```
```stylingHooksDemo.html
<template>
    <div class="slds-card">
        <button class="slds-button slds-button_brand slds-m-bottom_medium">Normal Button</button>
        <button class="slds-button slds-button_brand slds-m-bottom_medium my-css">Styled Button</button>
    </div>
</template>
```
```stylingHooksDemo.js
import { LightningElement } from 'lwc';

export default class StylingHooksDemo extends LightningElement {}
```
```stylingHooksDemo.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>
```

# 3.Salesforce側動作確認
#### Salesforce側Lightning コンポーネントタブを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1767576/d9c94e6c-8bfd-d3e9-a8db-f1a22c1338ad.png)

#### タブを開く
左は標準ボタンのデザイン、右はカスタマイズデザイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1767576/82850682-57bd-be99-af8b-7bd3b1548ca1.png)

# 4.参考
```Lighting Design System``` **Styling Hooks**

https://www.lightningdesignsystem.com/platforms/lightning/styling-hooks/#site-main-content
【Java】継承まとめ（abstract、interfaceについて個人的メモ）

abstract、interfaceの使いどころについて学んだのでメモ兼アウトプット。
abstract
- 
- abstractはメソッドとクラスに対して使用する。
    - メソッド
        - 実装の必要があるメソッドに対して、動作の詳細が決まってない場合、そのメソッドに対してabstractを指定する。
        - abstractが指定されたメソッドを**抽象メソッド**という。
    - クラス
        - クラス内に抽象メソッドが一つでもあればそのクラスに対してabstractを指定する。
        - abstractが指定されたメソッドを**抽象クラス**という。

　　※ ちなみにabstractとは、抽象、あいまい、という意味
       
```java:Character.java
public abstract class Character {
   public abstract void attack();
}
```
- abstractが指定されているクラスはインスタンス化（new）することができない。

```java:Main.java
Character c = new Character();
// 以下のエラーが発生
// Main.java:3: エラー: Characterはabstractです。インスタンスを生成することはできません
```

- abstractクラスを継承する際、子クラスでabstractのメソッドをオーバーライドをしなければコンパイルエラーとなる（この特徴により親クラスに書かれているメソッドが子クラスに実装されることが担保される）。

interface
- 
- abstractクラスの中でも、以下の条件を満たす場合はinterfaceクラスとして指定することができる（interface化するメリットについては後述）
    - メソッドの全てにabstractが指定されている
    - フィールド値がない

書き方は以下の通り、interface内のメソッドでは`public abstract`を省略することができる。(省略するのが慣例っぽい）

```java:Creature.java
public interface Creature {
   void run();
}
```

- interface化を行うメリットは、**多重継承**を行うことができる点。
- Javaでは多重継承（複数の親クラスから継承すること）が禁止されているが、親クラスがinterface化されていれば子クラスは複数の親を持つことが可能。<br>※ interface化された親を継承し、子クラス内で抽象メソッドを実装する際はクラス名の後に`implements`を付ける。それ以外の継承では`extends`。

```java:PrincessHero.java
public class PrincessHero implements Princess, Hero {
   // インターフェースの実装
   public void run(){
      System.out.println("スカートの裾をきつく結んで逃げ出した。");
   }
}
```
```java:Princess.java
// Princessインターフェース
public interface Princess {
   void run();
}
```
```java:Hero.java
// Heroインターフェース
public interface Hero {
   void run();
}
```
- interfaceと前述のabstractを同時に継承することも可能。（以下の例では`Character`を継承）

```java:PrincessHero.java
public class PrincessHero extends Character implements Princess, Hero {
   // abstractの抽象メソッドを実装
   public void attack() {
      System.out.println("モンスターに攻撃。１０のダメージ！");
   }

   // interfaceの抽象メソッドを実装
   public void run() {
      System.out.println("スカートの裾をきつく結んで逃げ出した。");
   }
}
```
Julia言語の実行環境をお手軽に構築する

# 概要

- 良い良いと噂のJuliaの実行環境を作ってみました
- 最速で動作環境を作るということを目標に、Dockerを使って超お手軽に実行環境を構築します（最適化とかはまだ何も考えてない）
- まだ環境を作っただけでJuliaの嬉しさは何も理解できてないので、今後使ってみる


# 動作環境

- macOS Big Sur (11.4)
- Mac mini (M1, 2020)
- チップ　Apple M1
- Docker
    - Engine 20.10.6
    - Compose 1.29.1
- IDE
    - Visual Studio Code + [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)
    - Jupyter lab


# Julia開発環境構築

目標構成として以下の構成を目指します

- jupyter labでインタラクティブに動作確認が行える
- ソースコードの開発はVSCodeを利用する

Juliaのインストールについて公式には、[Downloadページ](https://julialang.org/downloads/)からバイナリを入手するか、[Github](https://github.com/JuliaLang/julia)でソースコードを入手してビルドする方法が挙げられています。
しかしここでは、ポータブルな環境にしたかったのと、インストールの手間を省きたかったのでDockerを利用します。

ということで、DockerでJuliaの動作するコンテナを立ち上げ、VSCodeのRemote開発を使ってコンテナに直接入ってソースコードの開発と実行をする構成を作ります。


## Docker Image

Imageは[jupyter/datascience-notebook](https://hub.docker.com/r/jupyter/datascience-notebook/)を利用します。

jupyter/datascience-notebookはdatascience向けの言語（R, Python, Julia）と基本的なパッケージが備わっていて、jupyter labを立ち上げるとそれぞれの言語のカーネルが選択できるようになっています。
めちゃくちゃお手軽。というか、これを立ち上げるだけです。


## docker-compose.yml

オプションの設定をいちいち覚えるのはめちゃくちゃ手間なので、docker-composeを使います。docker-compose.ymlは以下の構成で作ってみました。

```yaml
version: '3'

services:
    jupyter:
        image: jupyter/datascience-notebook:latest
        user: root
        ports:
            - "8101:8888"
        environment:
            - GRANT_SUDO=yes
            - JUPYTER_ENABLE_LAB=yes
        volumes: 
            - $PWD:/home/jovyan/work
        command: start-notebook.sh --NotebookApp.token='' --NotebookApp.notebook_dir='/home/jovyan/work'
```

`jupyter/datascience-notebook`はセキュリティの観点でrootユーザではなくデフォルトで`jovyan`ユーザでjupyterを立ち上げます。なので、そのままだとapt-getなどできないので、rootユーザを指定しています。
また、`jovyan`にsudo権限を与えています(RANT_SUDO=yes)。

環境変数についての詳細は[公式ドキュメント](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/common.html#Docker-Options)を参照してください。

これで以下のコマンドでコンテナが立ち上がります。上記の設定では、localhostの8101番でjupyter　labにつながります。

```bash
docker-compose up -d
```

# Hello Juliaする

## jupyter

ということで、Hello Juliaをしてみました。

<script src="https://gist.github.com/tok41/4a611f245ffdf38b7730774a182e90c5.js"></script>

Gistでnotebookを貼っていたのですが、なぜか埋め込まれないのでリンクを置いておきます。

https://gist.github.com/tok41/4a611f245ffdf38b7730774a182e90c5


## スクリプトファイル

次に、VSCodeでソースファイルを作成して実行してみます。

例. `sample.jl`

```julia
println("Hello $(ARGS[1])!")
```


Pythonのように`julia`コマンドの後にファイルを指定するだけです。

```bash
> julia src/sample.jl Julia

Hello Julia!
```


# 今回はここまで

とりあえず実行環境をお手軽に構築してみたというだけです。
先にも書きましたが、まだまだJuliaの嬉しさがわかっていないので、今後触ってみようかなと思います。

MCMC(Gibbs Sampling, Metropolis法)を実装して遊んでみることが目下の目標。
イヤフォンを接続しても、自動起動した「MaxxAudio Pro」が真っ黒で困った話

# 事象発生環境
* ノートPC(DELL、inspiron)
* Windows 10 Pro
* 64ビット

# 発生事象
* 前日までは使用できていた。
* イヤフォンを接続しても自動起動した「MaxxAudio Pro」が真っ黒で困った。
* 「×」を選択してもすぐには終了せず。※体感、1分後くらいに終了。
* イヤフォンを接続していない状態で「MaxxAudio Pro」を起動しても真っ黒で同じ状態。
* 「リセット※」や「終了」しても直らず。
* 「アンインストール」「再インストール」しても直らず。
* イヤフォンは認識されなかったが、PCからは音声出力できた。

# 対処方法

(※2021/07/21現在は、以下の方法で改善済み。)

* 「MaxxAudio Pro」をアンインストールする。
* [[ サイト ]](https://www.dell.com/support/home/ja-jp/drivers/driversdetails?driverid=xf4rr)でRealtek-High-Definition-Audio-Driver_XF4RR_WIN_6.0.8984.1_A02.EXEをダウンロードする。
* Realtek-High-Definition-Audio-Driver_XF4RR_WIN_6.0.8984.1_A02.EXEをインストールする。
* 指示通りPCを再起動する。
* イヤフォンを接続する。
* 認識し、前日と同じように使用できた。
Dockerの設定ファイルを読む

## この記事の内容
今業務で触っているアプリに色々不具合が出てきたのですが、土台になっているDocker（←他の人が設定）がよくわかリませんでした...:sweat_smile:そこで、ソースコードを読み解きながら改善の方法を探りました。本記事はその時に調べた内容のメモです。

なお、筆者のレベル感はCIツールのyamlは記事を参照しながらギリギリ構築でき、dockerは基礎書籍を１回読んだ程度です。

## yamlの読み方
まず、yamlがなかなか読めませんでした...。新しく覚えたものはこちらに記しますが、それ以外は拙著ですがこちらをご覧ください。

- [【初心者向け】CIツール構築に必要なYAMLの読み方](https://qiita.com/tanutanu/items/7e8ba32e89186e3eb4df)

### &(アンパサンド)
**アンカー**というらしいです。`&`でマークをつけて、`*`で後で参照できます。
こんな感じで出てきました。

```yaml
app: &app
  # 色々な設定が続く
webpack:
 <<: *app
```
上記の設定では、`webpack`のビルドが始まる前に、`app`の諸々の設定を読み込んでいます。

### <<
読み方わかりませんでした...^^;
連想配列をマージする時にこの書き方をするらしいです。

```yaml
app: &app
  # 色々な設定が続く
webpack:
 <<: *app
```
上記の例では、`app`内の諸々の設定を `webpack`下にマージしていますね。
▼参考記事

- [yamlの書き方(コメント, 配列, アンカー, エイリアス)](https://www.wakuwakubank.com/posts/488-it-yaml/)

## コマンドの読み方
`docker-compose.yml`内に書かれていた、様々なコマンドの意味も調べました。
↓こちらの[公式ドキュメント](https://docs.docker.jp/compose/reference/overview.html)(?)の力も大きいです。

- [docker-compose コマンド概要](https://docs.docker.jp/compose/reference/overview.html)

また、`Docker`コマンドを丁寧にまとめてくださっている人もいました。これを見れば他の記事本とんどいらないんじゃないかと思います。

- [Docker Compose - docker-compose.yml リファレンス](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa)

### build

```yaml
build: .
```
**Dockerfile のあるディレクトリのパスを指定**します。ここでは、カレントディレクトリに`Dockerfile`があるので、値に`.`（ドット）を使用しています。

### depends_on
コンテナの作成順序を決めます。例えばこのように書かれていたら

```yaml
app:
  # 諸々の設定
  depends_on:
    - webpack
    - db
```
`app`の諸々の設定は`webpack`や`db`の後に実行されます。

### env_file
外部ファイルに書かれた環境変数をコンテナ内に取り込みます。

```yaml
env_file: .env
```
例えば、↑上記の設定では`.env`の中に書かれている環境変数をコンテナ内に取り込みます。

### environment
コンテナ内で使用する環境変数を設定します。

```yaml
environment:
  - LANG=C.UTF-8
```
例えば、↑上記の設定では環境変数`LANG`に`UTF-8`を設定します。

### image
使用するdockerイメージです。ローカルになければ[dockerhub](https://hub.docker.com/)からイメージがpullされます。

```yaml
image: postgres:9.6
```

↑上記の例では、`postgres:9.6`のイメージが使用されています。
### stdin_open: true
### tty: true

2つまとめて紹介します。

```yaml
stdin_open: true
tty: true
```
`stdin_open`とは標準入出力とエラー出力をコンテナに結びつける設定です。
`tty`とは、擬似端末(キーボードによる入力)をコンテナに結びつける設定です。
ソースは[こちら](https://qiita.com/yuki_0920/items/dc3f32667d004979cc5a)。キリの良いところでまた振り返ろうと思います。

### volumes

これは、[先の引用記事](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa#volumes)によると

> パスをボリュームとしてマウントします。オプションとしてホスト側のパスを指定（ホスト:コンテナ）したり、アクセスモードを指定します（ホスト:コンテナ:ro）。

ということのようです。例えば

```yaml
volumes:
 - .:/usr/src/app:cached
```

だと、イメージ内の`.`(カレントディレクトリ)に、Dockerの`/usr/src/app`を紐づけます。そして`:cached`はオプションです。

と書かれていて、[公式ドキュメントの記載](https://docs.docker.jp/compose/compose-file.html#volume-configuration-reference)もなんだかお手上げだったので、後日ゆっくり理解することにします。

### working_dir
特定のサービスの作業用ディレクトリを指定します。例えば

```yaml
app:
 working_dir: /usr/src/app
```
とあったら、`app`が動作するディレクトリは`/usr/src/app`になります。


**...以上で`docker-compose.yml`内のわからない表現は制覇です！**
これで、設定ファイルが読めます！やったー！！:v:

## で、結局不具合は直ったの？
...直りませんでした:joy:

読み解いた後、さらに記述に関する知識が必要だったので。。。。
引き続きデバッグを頑張ろうと思います！！:muscle:
[Rails] ActiveStrageの画像の保存先をAmazon S3にする③~S3に保存する~

##はじめに
これは前回の続きです。①、②がいわば下準備です。後はアプリの方に記述をするだけです。
よろしくお願いします。

##S3に保存するための記述を書く
まず、RailsアプリにGemを入れます。
Gemfileに下記を追記し、bundle installしましょう。

```:Gemfile
gem "aws-sdk-s3", require: false
```

```:ターミナル
% bundle install
```

続いて```config/environments/development.rb```の記述を編集します。
下記の記述を確認してください。

```:config/environments/development.rb
# ~省略~

config.active_storage.service = :local

# ~省略~
```

この記述を下記のように編集します。

```:config/environments/development.rb
# ~省略~

config.active_storage.service = :amazon

# ~省略~
```

次に```config/storage.yml```に追記します。
追記するのは**amazon:〜**からです

```:config/storage.yml
test:
 service: Disk
 root: <%= Rails.root.join("tmp/storage") %>

local:
 service: Disk
 root: <%= Rails.root.join("storage") %>

amazon:
 service: S3
 region: ap-northeast-1
 bucket: ご自身の「バケット名」を入力

 ~省略~
```

bucket:のところは②の記事で作成した名前を入力してください。

最後にS3にアクセスするための認証情報を設定します。
今記述したstrage.ymlファイルに記述しますが、直接記述するとセキュリティー面で危険なので、環境変数に入れて、ここにはあとで変数を記入するようにします。

①の記事でダウンロードした```new_user_credential.csv```ファイルを開くと「Access key ID」と「Secret access key」があるはずです。

これが環境変数に代入する値になります。

ここからはmacOSがCatalina以降とMojava以前ではコマンドが違うので気をつけてください。

ターミナルの開発中のアプリのディレクトリで下記を実行します。

```terminal:ターミナル（MacOSがCatalina以降の場合）
% vim ~/.zshrc
```

```terminal:ターミナル（MacOSがMojava以前の場合）
$ vim ~/.bash_profile
```

ターミナル上で.zshrcファイル、もしくは.bash_profileファイルが開けたら「iキー」を押して入力可能な状態にします。

下記を追記します。

```terminal:
export AWS_ACCESS_KEY_ID="CSVファイルのAccess key IDの値を貼り付け"
export AWS_SECRET_ACCESS_KEY="CSVファイルのSecret access keyの値を貼り付け"
```

貼り付ける際、値のダブルクォーテーションは必要です。

追記が完了したら「escキー」→「:wq」でファイルを保存します。
先ほどの記述を実行するために下記のコマンドを実行します。

```terminal:ターミナル（MacOSがCatalina以降の場合）
% source ~/.zshrc
```

```terminal:ターミナル（MacOSがMojava以前の場合）
$ source ~/.bash_profile
```

ターミナルがいくつも開いている場合は全てのタブでこのコマンドを実行します。
そして、もう一度storage.ymlを編集します。```amazon:```のところです。

```:config/storage.yml
# ~省略~

amazon:
 service: S3
 region: ap-northeast-1
 bucket:  （自身のバケット名が記載されている状態です）
 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
 secret_access_key:  <%= ENV['AWS_SECRET_ACCESS_KEY'] %>

#~省略~
```

これで完了です。
ローカル環境でアプリのActiveStorageを利用した投稿機能などで、画像を保存してみてください。

その後①で作成したIAMユーザーでAWSでログインしS3のページへ移動します。
②で作成したバケットをクリックしてオブジェクトというところに、保存されているはずです。↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1552346/ea537657-ecc9-8078-0353-1026b68197e4.png)

中身も気になる方は、チェックボックスにチェックを入れて「開く」をクリックをすると確認することができます。
これでS3に保存することができました。
DockerでPostgreSQLの環境構築

# 動作環境
```
mac osx 10.15.7
Docker 20.10.5
```
# テーブル作成までの流れ

```
$ docker network create db
```

```
$ docker run --name db -p 5432:5432 --network=db -v "$PWD:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=password -d postgres:alpine
```

```
$ docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                    NAMES
56014f6ccde1   postgres:alpine   "docker-entrypoint.s…"   15 seconds ago   Up 10 seconds   0.0.0.0:5432->5432/tcp   db
```
```
$ docker run -it --rm --network=db postgres:alpine psql -h db -U postgres
--'password'を入力
```

```
postgres=# create database student;
CREATE DATABASE
```
```
postgres=# \c student
You are now connected to database "student" as user "postgres".
```
```
student=# create table student(id BIGSERIAL PRIMARY KEY, name TEXT);
```
```
student=# \dt
          List of relations
 Schema |  Name   | Type  |  Owner
--------+---------+-------+----------
 public | student | table | postgres
(1 row)
```
```
student=# insert into student (name) values ('Alex'),('Maria');
INSERT 0 2
```

```
student=# select * from student;
 id | name
----+-------
  1 | Alex
  2 | Maria
```

#　おまけ
使わなくなったら消しましょう

```
postgres=# drop database student;
DROP DATABASE
```
```
postgres=# exit
```
```
$ docker rm -f db
db
```
```
$ docker network rm db
db
```
Ubuntu 20.04でイヤホンから音が出ない場合の解決例

自分の環境でオーディオ端子にさしたイヤホンから音が出ず、音声出力がHDMI経由しか選択できなかった際の解決例。
**中身を十分理解せず対処療法的にやったので参考程度にお願いします（自己責任で）**

**①`/proc/asound/modules`を確認**
`cat /proc/asound/modules`で内容を確認。たぶん`snd_hda_intel`が出てくる
**②`/etc/modprobe.d/alsa-base.conf`を確認**
`cat /etc/modprobe.d/alsa-base.conf`で内容を確認。イヤホンから出力ができないのであれば、おそらくここに`snd_hda_intel`がない。
**③`/etc/modprobe.d/alsa-base.conf`をコピー**
`cp /etc/modprobe.d/alsa-base.conf ~/Documents`等で`alsa-base.conf`をどこかの場所にコピーしてバックアップする。
**④`/etc/modprobe.d/alsa-base.conf`に追記**
`nano /etc/modprobe.d/alsa-base.conf`等で`alsa-base.conf`をエディタで開き（場合によってはsudoが必要）、

```
options snd slots=snd_hda_intel
options snd_hda_intel index=0
```
を最終行以降へ追記
**⑤再起動**
上記の変更を保存後に再起動。うまく行けば設定からアナログ出力が選択できるようになる

**2021/11/08 追記**
上記の設定をしたうえで、起動した後にイヤホンを差して音声が確認できない場合にはPulseaudioの再起動で音が出るようになることがあるのでお試しを。

```
pulseaudio -k
pulseaudio --start
```

参考：
・https://wiki.archlinux.jp/index.php/Advanced_Linux_Sound_Architecture#.E3.83.87.E3.83.95.E3.82.A9.E3.83.AB.E3.83.88.E3.82.B5.E3.82.A6.E3.83.B3.E3.83.89.E3.82.AB.E3.83.BC.E3.83.89.E3.81.AE.E8.A8.AD.E5.AE.9A
・https://wiki.archlinux.jp/index.php/Advanced_Linux_Sound_Architecture/%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0
・https://wiki.archlinux.jp/index.php/PulseAudio/%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0#pulseaudio_.E3.82.92.E5.86.8D.E8.B5.B7.E5.8B.95.E3.81.97.E3.81.A6.E6.96.B0.E3.81.97.E3.81.84.E8.A8.AD.E5.AE.9A.E3.82.92.E9.81.A9.E7.94.A8.E3.81.99.E3.82.8B_.284.2F5.29
UIImage と CIImage の変換（nil 回避方法）

## はじめに

Swift で画像を扱うと、色々な型を使うことになります

- UIImage
- CGImage
- CIImage

通常、画像を画面に表示したいだけなら UIImage だけで問題ありません

画像処理をしようと思うと CGImage を使ってみることになり、

更に複雑さや高速さを求められるようになると CIImage を使うことになります

特にリアルタイム処理では CIImage を使わないと追いつきません

それぞれの違いについては以下の記事が参考になります

https://qiita.com/hrichii/items/c77a7cd07a42767985d5

さて、では相互に変換するにはどうするか

以下の記事にまとめられていますが、情報が古いのと、場合によって結果が nil になることがあるため、補足します

https://qiita.com/imanishisatoshi/items/34d1e488d412cd23fd8d

## 実装環境

- macOS Big Sur 11.4
- XCode 12.5.1
- Swift 5.4.2

## nil 回避方法

stack overflow にも出ていますが、 UIImage から CIImage を取り出そうとしたとき、 nil になることがあります

https://stackoverflow.com/questions/15651228/could-anyone-tell-me-why-uiimage-ciimage-is-null

CIImage を元に作られた UIImage であれば問題ないのですが、そうではない（画像ファイルから読み込んだ場合など）は nil が返ります

というわけで、変換は以下のようにする必要があります

Extension にしておきました

UIImage -> CIImage

```swift
import UIKit

public extension UIImage {
    func toCIImage() -> CIImage? {
        if let ciImage = self.ciImage {
            return ciImage
        }
        if let cgImage = self.cgImage {
            return CIImage(cgImage: cgImage)
        }
        return nil
    }
}
```

CIImage -> UIImage

```swift
import UIKit

extension CIImage {
    func toCGImage() -> CGImage? {
        let context = { CIContext(options: nil) }()
        return context.createCGImage(self, from: self.extent)
    }

    func toUIImage(orientation: UIImage.Orientation) -> UIImage? {
        guard let cgImage = self.toCGImage() else { return nil }
        return UIImage(cgImage: cgImage, scale: 1.0, orientation: orientation)
    }
}
```

CIImage は画像の向き、という概念を持っていませんが、 UIImage は向きの概念があるため、引数にしています

色々やっていると、この画像の向きの概念がややこしくなってくるわけですが、、、
tailwind.config.jsにsmより小さいブレイクポイントを追加する方法

#結論
以下のコードで、tailwindcssにデフォルトで用意されている最小のレスポンシブ用のクラスであるsm（640px）よりも小さいブレイクポイントを追加することができる。

```
// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    screens: {
      'xs': '375px',
      ...defaultTheme.screens,
    },
  },
  variants: {},
  plugins: [],
}
```
https://tailwindcss.com/docs/responsive-design

#抑えておくべき点
* tailwindcssにデフォルトで用意されているブレイクポイントよりも小さいブレイクポイントを追加したい時は、**デフォルトのブレイクポイントをスプレット構文で展開して、その一番先頭に追加する**こと。
* 変更が終わったらビルド&デプロイを忘れずに

```
npx tailwindcss build "ビルド対象" -o "出力先" && theme-deploy--allow-live
```
【Kotlin】16進数文字列をByte配列に変換する

# 初めに
16進数文字列とは、0~9,a~f で書かれた文字列。なので、1文字あたり4bitで構成可能。
4bit per one →8bit(1byte) per one の変換となるので、Byte配列に変換するには16進数文字列の長さが偶数である必要がある。



# コード

ここに書いてある通り。

https://stackoverflow.com/questions/66613717/kotlin-convert-hex-string-to-bytearray


```sample.kt
fun String.decodeHex(): ByteArray {
    check(length % 2 == 0) { "Must have an even length" }

    return chunked(2)
        .map { it.toInt(16).toByte() }
        .toByteArray()
}
```

chunked関数初めて知りました。
Railsのコントローラーの作り方

# コマンド

コントローラーを作りたいならば以下をターミナルに打ち込むべし！

```
rails g controller 作りたいコントローラの複数形の名前
```
これで完成！

ちなみに「g」は「generate(生み出す、生成する)」の略
"conda install -c bioconda fastp" が意味するとこ。

何度も同じことを調べているので、覚書として投稿します。

#環境
iMac (2017)
macOS Big Sir ver 11.4
miniconda3

#"conda install -c bioconda fastp" の意味
condaの仮想環境に、Anacondaのリポジトリのbiocondaチャネル（-c）からfastpツールをinstallしてね。

#####一般化すると．．．．
現在有効になっているcondaの仮想環境に、ダウンロード元のAnacondaレポジトリから指定した[チャネル名]から、パッケージをインストールする

```:Terminal
conda install -c [チャネル名] [パッケージ名]
```

#miniconda3とは何か。
* miniconda3は、Anacondaの最小構成版。
* conda、Python、それらが依存するパッケージ、および pip、zlib、その他のいくつかの有用なパッケージのみを含む。
* 今回の目的としているバイオインフォマティクスに関しては、minicondaで十分であり、余計なパッケージをはじめから入れさせないためにminicondaを選択。

miniconda詳細→<https://docs.conda.io/en/latest/miniconda.html>

#condaとはそもそも何か。
Anacondaディストリビューションには、1,500個以上のパッケージがあり、condaはその一つのオープンソースパッケージ。
conda詳細→<https://docs.conda.io/en/latest/>

##condaコマンドとは何か。
有効になっているcondaの仮想環境を操作するコマンド。
Anacondaの実行環境は Anaconda-Navigatorというディストリビューションでも操作できるが、condaコマンドを使うことでパッケージのインストールなどがターミナル上で行える。

#####condaの仮想環境について
用途によって利用するパッケージや言語のバージョンが違っていることはよくある。そのため、「開発に合わせて専用の仮想環境を作成し、環境を切り替えながら利用する方法」を用いる。仮想環境はpyenvやvirtualenvを使う方法もあるが、Anacondaを利用している場合はcondaを使った管理ができる。

私が現在使っている仮想環境の一覧を表示させてみると、

```:Terminal
% conda env list
# conda environments:
#
base                  *  /Users/user_name/miniconda3
```
現在有効になっている環境には、アスタリスク（*）が付いている。
私の場合、新たな仮想環境を構築していないので、デフォルトの環境しか存在せず、それが有効になっています。


#biocondaとは何か。　
* condaチャネルの中のディストリビューションのひとつ。
* バイオインフォマティクス関係のツールが登録されているパッケージマネジャー
* 現在、8000以上のBiology関連のソフトウェア・パッケージが登録されている
* conda内のパッケージは個別のチャネル名がついたリポジトリにホストされている。パッケージを使うときは、そのパッケージがホストされているチャネルを確認し、そのチャネルをconda環境に追加することでパッケージのインストールが可能になる（チャネル追加の仕方は下記の「biocondaの使い方」参照）。

bioconda詳細→<https://anaconda.org/bioconda>

##biocondaの使い方
condaがパッケージを探すレポジトリにチャネル名'bioconda'を追加する。
※　--addを使うと追加したチャンネルが# highest priorityになる。
※　--add のかわりに --append をつかうと、# highest priorityを移動させずにチャネルを追加。

```:Terminal
$ conda config --add channels bioconda
```

そして、condaがパッケージを探すレポジトリを表示させてみた。

```:Terminal
% conda config --get channels
--add channels 'defaults'   # lowest priority
--add channels 'conda-forge'
--add channels 'bioconda'   # highest priority
```
現在、'defaults''conda-forge''bioconda'の３つのチャネルが設定されていることがわかった。

この状態でconda installコマンドを実行すると、Anacondaディストリビューションの3つのチャネルのうち、私のconda環境でpriorityの高いチャネルであるbiocondaから順にパッケージを探し、インストールしてくれる。
biocondaを指定してインストールすれば、パッケージのバージョン管理も行ってくれる。

私のPCで表示されたその他のチャネルについては以下の通り。
'defaults'は、condaがデフォルトで探すレポジトリ。
'conda-forge'は、github上のコミュニティ主体のパッケージコレクションのレポジトリ。

※conda-forgeは、以前に追加したので表示されています。defaultsに含まれないパッケージがconda-forgeに含まれていたり、新しいバージョンが登録されていたりする場合も多いので、こちらも以前に追加してました。

以上です。



#参考
<https://imamachi-n.hatenablog.com/entry/2017/01/14/212719>

<https://toufulog.com/archives/840>
RがTerminalから起動できなくなった

#環境
iMac (2017)
macOS Big Sir ver 11.4
miniconda3

#状況
これまで使えていたのに突然Rがterminalから起動しなくなった。
（miniconda3環境下でRを使っています）

```:Terminal
% R
dyld: Library not loaded: @rpath/libncurses.6.dylib
  Referenced from: /Users/user_name/miniconda3/lib/libreadline.8.1.dylib
  Reason: image not found
zsh: abort      R
```
なぜ突然起動しなくなったかの理由はわからない。
ひとまずRコマンドのフルパスを表示してみる。

```:Terminal
% which R
/Users/user_name/miniconda3/bin/R
```
やはりRはあるみたい。

#解決法
調べてみたら以下コマンドで解決するらいい。
意味はわからないけど、とりあえず実行してみた。

```:Terminal
% conda update -c rdonnellyr -c main --all
```

一旦、ターミナルを終了してもう一度起動し直す。
Rは動くかな？

```:Terminal
% R

R version 4.1.0 (2021-05-18) -- "Camp Pontanezen"
Copyright (C) 2021 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin13.4.0 (64-bit)

R は、自由なソフトウェアであり、「完全に無保証」です。 
一定の条件に従えば、自由にこれを再配布することができます。 
配布条件の詳細に関しては、'license()' あるいは 'licence()' と入力してください。 

R は多くの貢献者による共同プロジェクトです。 
詳しくは 'contributors()' と入力してください。 
また、R や R のパッケージを出版物で引用する際の形式については 
'citation()' と入力してください。 

'demo()' と入力すればデモをみることができます。 
'help()' とすればオンラインヘルプが出ます。 
'help.start()' で HTML ブラウザによるヘルプがみられます。 
'q()' と入力すれば R を終了します。 

> 
```

動いた！！
突然動かなくなった理由も、なぜ動くようになったかも謎だけど、ひとまず解決。
以上です。

#参照
以下の記事を参考にしました。
https://github.com/conda/conda/issues/6183
【備忘録】Androidで魔法を使っているみたいなタッチエフェクト

##画面に触るたびに散る光の粉っぽいエフェクト
例
![screencast-Genymotion-2021-07-21_17.25.14.665.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391023/d66fba1d-6670-bf46-dd44-8a596ac4be81.gif)

こんな感じのエフェクト。

```MyEffect.kt

@SuppressLint("ViewConstructor")
class MyEffect(context: Context, private val eventX: Float, private val eventY: Float): View(context) {
    private var paint = Paint()

    override fun onDraw(canvas: Canvas?) {
        canvas?.drawColor(Color.TRANSPARENT)
        val color = Color.WHITE
        paint.apply {
            setColor(color)
            alpha = 200
            isAntiAlias = true
            style = Paint.Style.FILL
        }
        canvas?.drawCircle(eventX, eventY, 2f, paint)
        for (count in 1..4) {
            val scatter1 = (-30..30).random().toFloat()
            val scatter2 = (-30..30).random().toFloat()
            val size = (1..6).random().toFloat()
            canvas?.drawCircle(eventX + scatter1, eventY + scatter2, size, paint)
        }
    }
}

```

```MainActivity.kt

 override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event?.action == MotionEvent.ACTION_UP || event?.action == MotionEvent.ACTION_MOVE) {
            val myEffect = MyEffect(this, event.x, event.y)
            binding.parentLayout.addView(myEffect)
            myEffect.run {
                animate().alpha(0f).setDuration(800)
            }
            handler.postDelayed({ binding.parentLayout.removeView(myEffect) }, 810)
            return true
        }
        return false
    }

```
TypeScript+ReactでのReact HooksとuseState(転何知人T+Rその5)

# [前回](https://qiita.com/botanic7arc/items/4affa706a0e9c95cab54)までの状態

関数コンポーネントとクラスコンポーネントについて学習した。

# 今回の目的

- React Hooksについて
- useStateについて

# クラスコンポーネントの問題点

クラスコンポーネントを使用すれば、state(状況によって変わる値)を使用した状態の管理が可能。
しかし、クラスコンポーネントには問題点があり(詳細は[参考文献](#参考文献)参照)、関数コンポーネントでも状態の保存ができるフック機能(React Hooks)が追加された。

# React Hooksについて

React Hooksとは、クラスコンポーネントの使用なしに状態管理を可能にするもの。

# useState

stateを使用する際に使う。書式は以下の通り。

const [stateの変数名, stateを更新する関数名] = useState(stateの初期値);

## 作成物

[完成品](https://botanic7arc.github.io/ts-react05/)

テキストボックスに入力した相手に挨拶するページ。


## 手順

適当な場所でnpx create-react-appし、React用のプロジェクトフォルダを作る。

```
npx create-react-app react05 --template typescript
```

srcフォルダにあるファイルを全て削除し、index.tsxを作成し、以下の内容を書き込む。

``` tsx
import ReactDOM from 'react-dom';
import { useState } from 'react';

const TextOutput = ({ name }: { name: string }) => {
  return (
    <p>Hello, {name}!</p>
  );
}

const TextInput = () => {
  const [str, setStr] = useState('初期値');

  return (
    <div>
    <form >
      <label>
        入力欄<br />
        <textarea
          value={str}
          onChange={event => setStr(event.target.value)}
        />
      </label>
    </form>
    <TextOutput name={str} />
    </div>
  );
}

ReactDOM.render(
  <TextInput />,
  document.getElementById('root')
);
``` 

いつも通り、npm startでプロジェクトを実行する。
完成品と同じものが表示されれば成功。

# 解説

``` tsx
import { useState } from 'react';
``` 

useStateを使用するため、インポートしている。

``` tsx
const [str, setStr] = useState('初期値');
``` 

strというstateを'初期値'で初期化し、setStrという関数でstrを更新することを宣言している。

``` tsx
<textarea
  value={str}
  onChange={event => setStr(event.target.value)}
/>
``` 
str('初期値')が値として入っているテキストエリアで、入力欄に変更があった場合、setStr()によってstrがevent.target.valueに変更される。

# 要約

関数コンポーネントで状態管理を行う場合、React Hooksを使用する。
useStateで状態管理用の変数と値更新用の関数名を宣言できる。

# 次

- [useEffect](https://qiita.com/botanic7arc/items/ac5f8431c5fde5a561bd)

# 参考文献

- [フックの導入 – React:クラスは人間と機械の両方を混乱させる](https://ja.reactjs.org/docs/hooks-intro.html#classes-confuse-both-people-and-machines)
- [Reactでクラスコンポーネントより関数コンポーネントを使うべき理由5選](https://tyotto-good.com/blog/reaseons-to-use-function-component)
- [なぜクラスコンポーネントより関数コンポーネントが推奨されるのか？](https://zenn.dev/swata_dev/articles/7f8ef4333057d7)
- [Reactでinputを扱う(TypeScript版) - Qiita](https://qiita.com/takaki@github/items/9ac4e3f1e461fdaf7c30)
- [はじめてのReact #10「フォームと連動する」テキストボックス編](https://blog.katsubemakito.net/react/react1st-10-form-textbox)
- [ReactアプリをGitHub Pages(Project Pages)で公開する - Qiita](https://qiita.com/EisKern/items/15dcf7864fa49df8f247)
- [ReactHooksについてまとめた！ - Qiita](https://qiita.com/pasha/items/160356e4e29a0ee72f5d)
- [フック API リファレンス – React](https://ja.reactjs.org/docs/hooks-reference.html)
【初心者】Laravel　データベースへ（DB）の接続方法

# まずすること

ターミナルでこの順番にコマンドを打っていく。

**・artisanコマンドはどこで打つ？**
→docker-compose.ymlがあるディレクトリ

まずそのディレクトリに移動する

```
 $ cd （docker-compose.ymlがあるディレクトリ）
```


**・artisanコマンドを打つためにはコンテナに入る必要性がある**


```
 $ docker ps 
```
```
docker exec -it （↑ NAMES　ほとんどwebの方） bash
```
```
:/var/www/html# （artisanコマンドを打つ）
```



# 〜マイグレーションの手順〜
**①マイグレーションファイルを作成**

下記コマンドを実行し、postsテーブル作成のためのマイグレーションファイルを作成します。

```
$ php artisan make:migration ファイル名 --create=テーブル名
```

すると、「database/migrations」ディレクトリ内に「2019_02_04_030213_create_posts_table.php」のようなファイル名のファイルが作成されます。


**②DB接続**

workbenchでスキーマを作成する。（手動）

スキーマー名＝データベースの名前

`trainig_docker_mysql_1（DB担当）`と`Laravel`を繋げる

`env.` を`docker-compose.yml`を確認しながら書き換える

```php:env.(8〜13行)
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=kita
DB_USERNAME=root
DB_PASSWORD=admin
```

**③マイグレーションを実行**

```
$ php artisan migrate
```

→migrateが成功したら自動的にworkbenchのスキーマの配下にテーブルって作られる。

# その他
【Docker-Compose】コンテナ起動から入るまで
・https://qiita.com/tsuboyataiki/items/90dbe94553d3dea39b19
【Google Map Api】

# エラー内容
ローカル環境では、GoogleMapApiを使用してマップが表示されていたのですが、`aws amplify`でデプロイすると、マップが表示されなくなりました。

# 解決方法
`Google Cloud Plarform`にて、自身のプロジェクトを選択し、左側の`ナビゲーションメニュー`一覧より`APIとサービス`をクリック。

次に、その画面で`Maps JavaScript API`を選択。

左側のメニューより`認証情報`をクリックすると使用している`APIキー`が表示されるので、そちらをクリック。

`ウエブサイトの制限`にて`項目を追加`を選択し、そのAPIキーを使用しているアプリのURLを入力。

最後に`保存`を押して完了です。

# まとめ
教訓： エラーが出ても慌てずに、エラー内容をコピぺ、検索。
Railsの楽観的ロックと悲観的ロック

Active Recordには、楽観的ロックと悲観的ロックの2通りのロックがある。
Railsの楽観的ロックが他の楽観的ロックと異なる点は、lock_versionというカラムを用いて楽観的ロックを行う点である。
悲観的ロックは、他の言語と同じである。

### 楽観的ロック
複数のユーザーが同じレコードを編集する事を許容するロック。
レコードが変更されたかどうかをチェックする仕組みになっている。
更新されたが無視された場合、ActiveRecord::StaleObjectError例外が発生する。

#### 楽観的ロックカラム
楽観的ロックを使用するにあたって、テーブルにlock_versionというinteger型のカラムを作成する必要がある。
レコードが更新されるたびに、lock_versionカラムの値を1ずつ増やす。
更新リクエストが発生した時のlock_versionの値がDB上のlock_versionカラムの値よりも小さい場合、更新リクエストは失敗し、ActiveRecord::StaleObjectErrorが発生する。
def change
 ~
 t.integer :lock_version, default: 0
end

### 悲観的ロック
データベースが提供するロック機能を利用する。
悲観的ロックでは、他ユーザーが更新対象のデータを取得できないようにロックがかかる。
そして、ロックはデータの更新が完了するまで解除されない。


Railsガイド
https://railsguides.jp/active_record_querying.html
lock_versionを使って排他制御(楽観的ロック)を行う方法
https://pote-chil.com/rails_optimistic/
排他制御について（楽観的ロック・悲観的ロック ）
https://www.ryotaku.com/entry/2019/08/07/000000
【Numpy】.shapeで得られる値の理解

#本記事は
会社である研修を受けた際の教材の``shape``で得られる結果の解説　~~が不親切だった~~　にもう少し説明が欲しかったので、自分の理解のために整理します。
いろんなサイトで見ても、例とする配列に入っている数字が1～12の連番かつ、``reshape``で指定する数値が2とか3なので、何を指定しているのか混乱してしまいます。（私だけ？）

#Numpyの.shapeコマンド
配列の各次元の要素数を返します。
簡単に言えば、配列の行数、列数、奥行き数を返してくれるもの。
「奥行き数」と言うのが正しい呼称かはわかりませんが、私のイメージです。

Numpyはインポートして使います。
よく``np``としてインポートして使います。

```python
import numpy as np
```

#実際にどんな結果が得られるか確認してみる


（個人的に）わかりやすくするためにランダムな値が入った配列を作ります。
``.random.randint()``で整数の乱数を発生させます。
ちなみに``(開始値, 終了値, 要素数)``の順で、開始値から終了値までの範囲で要素数の数だけ乱数を得るという、指定方法です。

```python
x = np.random.randint(10, 50, 24)
print(x)
```
結果は以下。
ランダムな24個の要素が入った配列を得ました。

```
[29 39 42 12 45 44 21 45 32 16 45 38 23 17 29 20 26 47 38 10 22 28 29 44]
```

##単純なshapeを使ってみる
まずは単純にshapeの結果を見ます。

```python
print(x.shape)
```

結果は以下
一次元の要素が24あるということがわかります。

```
(24,)
```

##reshapeで2次元の配列にしてみる

``reshape``で形状を変換して確認してみます。

```python
a = x.reshape(6, 4)
print(a)
print(a.shape)
```
結果は以下。
6行、4列の行列になりました。

```
[[29 39 42 12]
 [45 44 21 45]
 [32 16 45 38]
 [23 17 29 20]
 [26 47 38 10]
 [22 28 29 44]]
(6, 4)
```

##reshapeで3次元の配列にしてみる
同じく``reshape``で3次元に変換して確認してみます。
ここで重要なのは、奥行き数を一番初めに指定すること。
``.reshape(奥行き数, 行数, 列数)``です。
~~不親切な教材にはここの解説がなかったので、何を指定している理解が難しかった。~~
~~あと、どのサイトや教材も要素の数が2,3とかで、なんの値を指定しているかがわかりにくい。もっと極端な値にすればわかりやすいのでは？~~

```python
b = x.reshape(2, 3, 4)
print(b)
print(b.shape)
```
結果は以下。
``print``で行列を表示すると、奥行きが別の行列が改行されて表示されますね。
``shape``で得られる結果では、奥行き数が一番頭に来ています。


```
[[[29 39 42 12]
  [45 44 21 45]
  [32 16 45 38]]

 [[23 17 29 20]
  [26 47 38 10]
  [22 28 29 44]]]
(2, 3, 4)
```

###いろんな解説はもっと極端にしたらどうですか？
極端に奥行き数を6に変更して確認してみます。

```python
c = x.reshape(12, 1, 2)
print(c)
print(c.shape)
```
結果は以下。
1行×2列の行列が12個表示されますね。
これで``reshape``で指定する順番が理解できました。
``shape``で得られる結果の順番も同様です。

```
[[[29 39]]

 [[42 12]]

 [[45 44]]

 [[21 45]]

 [[32 16]]

 [[45 38]]

 [[23 17]]

 [[29 20]]

 [[26 47]]

 [[38 10]]

 [[22 28]]

 [[29 44]]]
(12, 1, 2)
```

#終わりに
本記事は個人の理解のための整理です。
色々勉強していると、こんな例題で本当に教える気があるのか？という教材も見かけます。
（私の理解力が足りないだけかもしれませんが）初学者は極端な例を使うことで理解が進む、というのはあるあるだと思います。
今後もこのように理解しにくかったこと、気になったことを整理したいと思います。
どなたかのお役に立てれば幸いです。
[息抜き]乃木坂工事中一覧を制限のある環境でスクレイピングとデータ整理

- 技術の発展に伴い様々な学習を続けているが、結局データの取得・整理・検索に魅力を感じる。
- その醍醐味であるスクレイピングを息抜きとして利用しているが、pythonやruby,node等のライブラリが豊富な言語がない環境でも利用したい。
- 今回は最低限のLinux環境での機能やコマンドを利用してスクレイピング及びデータ整理を行う。

## 環境
- Alpine Linux 3.14.0
- curl 7.77.0
- **※Macでも動作加納**

## 手順

### データの要件決め
- 取得したいデータ要件は以下。
  - 形式 : TSV
  - 1列目 : 日時(xxxx年xx月xx日)
  - 2列目 : タイトル

### ファイル用意
- 以下のように、任意のフォルダに新規のshellファイルを作成する。

```shell
mkdir ~/ng; cd $_
touch get_kojichu.sh
```

- 作成後、中身を以下のようにする。

```shell
#!/bin/sh

set -e

current_year=$(date '+%Y')
page_data=$(curl -s 'https://ja.wikipedia.org/wiki/乃木坂工事中の放送日程一覧')
search_command="grep -A 1 -E '<td style=.+>[0-9]+月[0-9]+日' | sed -r -e 's/<[^>]+>//g' -e 's/&#.+//g' -e '/--/d' | tr -d '\"' | awk '{if(NR%2)ORS=\"\t\"; else ORS=\"\n\"; print}'"

for i in `seq 2015 $current_year`; do
  [ $i -ne $current_year ] && {
	echo "$page_data" |
	sed -n "/<span class=\"mw-headline\" id=\"$i年\">/,/<span class=\"mw-headline\" id=\"$((i+1))年\">/p" |
	eval ${search_command} |
	sed "s/^/$i年/"
  } || {
	echo "$page_data" |
	sed -n "/<span class=\"mw-headline\" id=\"$i年\">/,/<span class=\"mw-headline\" id=\"脚注\">/p" |
	eval ${search_command} |
	sed "s/^/$i年/"
  }
done
```

- 中身記述後、`chmod 755 get_kojichu.sh`で実行権限を与える。

## 結果
- 以下で結果を確認

```shell
# 最初の10件を表示
$ ./get_kojichu.sh | head

2015年4月20日	ななせまると愉快な仲間たち
2015年4月27日	狩野英孝のリアクション塾
2015年5月4日	生田絵梨花vs催眠術師
2015年5月11日	12thシングル選抜メンバー発表乃木坂46センター討論会
2015年5月18日	松井玲奈の世界一教えたい授業乃木坂監視中・特別編

# TSVデータに書き出す。過通信を防ぐため以下からはこちらを使用。
$ ./get_kojichu.sh > kojichu_list.tsv

# 最新日時順
$ cat kojichu_list.tsv | sort -Vr

2021年7月19日	上半期・私の反省大賞!
2021年7月12日	松村沙友理 卒業記念! 完結編
2021年7月5日	松村沙友理 卒業記念! 設楽王決定戦 
2021年6月28日	奇想天外！与田クイズ
2021年6月21日	27thシングルヒット祈願! 完結編
*******

# タイトルのみ抜き出す
$ cat kojichu_list.tsv | awk -F '\t' '{print $2}'

ななせまると愉快な仲間たち
狩野英孝のリアクション塾
生田絵梨花vs催眠術師
12thシングル選抜メンバー発表乃木坂46センター討論会
******

# 検索
$ cat kojichu_list.tsv | grep '選抜メンバー'

2015年5月11日	12thシングル選抜メンバー発表乃木坂46センター討論会
2015年8月31日	13thシングル選抜メンバー発表初めてのWセンター西野・白石ガチンコチーム対決 前編
2016年2月1日	14thシングル選抜メンバー大発表
2016年6月6日	15thシングル選抜メンバー大発表
**********
```

## まとめ
- 最低限の環境でも動作する記述を意識するようになった。
- 年情報も必要であり記述が冗長となったため、より良い記述を今後考える。
- 息抜きは重要。

## 参考
- [乃木坂工事中の放送日程一覧](https://ja.wikipedia.org/wiki/%E4%B9%83%E6%9C%A8%E5%9D%82%E5%B7%A5%E4%BA%8B%E4%B8%AD%E3%81%AE%E6%94%BE%E9%80%81%E6%97%A5%E7%A8%8B%E4%B8%80%E8%A6%A7)
ESP32 に同じバイナリを連続書き込みする方法

## はじめに
Arduinoでコンパイルしたバイナリを複数のESP32に連続書き込みする方法です。
毎回，コンパイル→リンク→UPLOADすると時間がかかり過ぎますが，
esptool.exe に引数を書くのは難しく，ある程度，簡単に実現できる方法をメモします。

## 開発環境
Arduino IDE 2.00(beta.9) on windows10　　2021/07/21 確認 
IDE のバージョンは問わないと思いますので読み替えてください。

## 手順
#### 1．Arduino IDE 設定
コンパイルの詳細表示をオンにします。
<img width="400" alt=[image.png] src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186241/e83c003c-713a-0d6b-8c5a-3b3c7b08f90d.png">

#### 2.コンパイル→書き込みスクリプトコピー
１回目は通常のコンパイル→UPLOADを実行します。
成功するとUPLOADスクリプトが生成され実行され ESP32に書き込まれるので，
画像の行をクリップボードにコピーします。
ダブルクリックすると1行まるごと選択されますが，かなり長いです。

<img width="500" alt=[image.png] src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186241/b0b1e71b-0100-1ee9-9361-51e1ba3d288b.png">

#### 3.スクリプト編集
(Arduino 1.x 系はここは不要と思います)
スクリプトにダブルクオーテーション(") が含まれるので消去します。
メモ帳を開き，コピーしたスクリプトをペースト。
編集(E)→置換(R) (CTRL+H) により(") を消去します。
<img width="500" alt=[image.png] src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186241/7f390a64-deda-007c-5ef7-7b3e3b5dca5e.png">

#### 4.upload
コマンドプロンプトを開き，3で修正したスクリプトを実行します。
・スタートメニューに"cmd" と入力するとコマンドプロンプト（通称：黒い画面）が現れます。
・コピーしたスクリプトはコマンドプロンプト画面で右クリックすると，いきなり実行されますので，ESP32を接続しておくと良いでしょう。

#### 5.繰り返し
コマンドプロンプト画面でカーソルの上を押すたびに履歴が表示されますので，１つ前の履歴を表示，そのままENTERキーで連続書き込みができます。
後は無心で書込マシーンになりましょう。

## 何をやっているの？
スクリプトを見てみます。
esptool.exe を実行，大量の引数が生成されていて，
おおまかに以下の２ブロックになっています。
・ESP32の設定  (ArduinoIDE の設定から変更できます)
・それぞれのアドレスに4つのバイナリを書込

```
C:\Users\xxxx\-------\esp32\tools\esptool_py\3.0.0/esptool.exe
 --chip esp32
 --port COM3
 --baud 921600
 --before default_reset
 --after hard_reset write_flash
 -z
 --flash_mode dio
 --flash_freq 40m
 --flash_size detect
  0xe000 C:\Users\xxxx-------\esp32\1.0.6/tools/partitions/boot_app0.bin
  0x1000 C:\Users\xxxx-------\esp32\1.0.6/tools/sdk/bin/bootloader_qio_40m.bin
  0x10000 C:\Users\----\Temp\arduino-sketch-xx/ABCD.ino.bin
  0x8000 C:\Users\-----\Temp\arduino-sketch-xx/ABCD.ino.partitions.bin
```
書込アダプタに依存しますが，baud 1500000 などでちょっとだけ高速化できます。 

## まとめ
ESP系は特にコンパイルが遅いので何台か作る時は有効なので，覚えておくと良いでしょう。

## 注意事項
・書込エラーを見逃しやすいので，注意しましょう。

## 参考資料
【amplify】デプロイ失敗の解消法

# エラー内容
ビルドの段階でエラーがいくつか発生しました。

#### 1つ目

```
tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
```
package-lock.jsonを削除したら、このエラーは表示されなくなりました。

#### 2,3つ目
```
warning " > @testing-library/user-event@12.8.3" has unmet peer dependency "@testing-library/dom@>=7.21.4".

warning "recharts > react-smooth@2.0.0" has unmet peer dependency "prop-types@^15.6.0".
```
https://qiita.com/hayato94087/items/82c36b4063ef935515fa
こちらの記事にこのエラーの解消方法が載っていました。

#### 4つ目
```
2021-07-21T07:11:33.617Z [INFO]: ./src/App.tsx
                                 Cannot find file './components/currentWeather/CurrentWeather' in './src'.
2021-07-21T07:11:33.634Z [WARNING]: error Command failed with exit code 1.

```
githubのリモートリポジトリを見たら`Currentweather.tsx`と、`w`が小文字になっていました。
それがローカルのファイルと整合性が取れなくて、エラーになっていたみたいです。

### 変更方法
githubの`CurrentWeather.tsx`のファイルを開くと、そのファイルを編集できます。
そこで、`Currentweather.tsx`を`CurrentWeather.tsx`に書き換え、保存しました。

その後、一度ローカルで`git pull`をして、`readme`などを少し変更して、再度`push`し、`amplify`を再デプロイしたところ、無事にデプロイが完了しました。

# まとめ
以上が今回のエラーとその改善方法になります。
Power Query でテーブルをマージしたいが遅いんだよね。それは仕方がないとして、できることを考える。

クエリフォールディングがサポートされないデータソース もしくは クエリフォールディングが機能できない状態のクエリで、テーブルのマージ処理をすると遅いのだ。Power Query 自体はデータベースではないし、有限リソースであるメモリ上だけで処理するので遅くなるのは当たり前である。扱う行数が少なければ気にならないけれども、行や列はいつも少ないとは限らないから、なんで遅くなったのだと考えてしまうのかもしれないね。

# いわゆる表引き
**マージ処理後に展開する列だけに制限する**
案外簡単に試せる Excel ワークシート上のテーブルからマージ結果を出力例を提示するので試してみてね。

- Sales テーブルには ProductID を含む行が 1,000,000 行。Excel でも扱える行数よね
- Products テーブルには ProductID をプライマリキーとして 100,000 行。ちょっと盛ったけど異常な行数ではない。
- Products テーブルには 属性値 29 列存在し、30列になる。列数は確認できるように盛った。

そこで、マージをして Products の属性値 Column2 を追加する。で、次の通りになるはず。

```text
let
    Source = Table.NestedJoin(
        Sales, {"ProductID"},
        Products,
        {"ProductID"},
        "Products",
        JoinKind.LeftOuter
    ),
    ExpandedProductsColumn2 = Table.ExpandTableColumn(
        Source,
        "Products",
        {"Column2"}
    )
in
    ExpandedProductsColumn2
```

私の環境では、おおむね 13 から 14 sec ほど。
そこで、マージに利用するキー列とマージ後展開する属性値の列のみで処理を試みる。

```text
let
    Source = Table.NestedJoin(
        Sales, {"ProductID"},
        Products[[ProductID], [Column2]], // 👈ココ
        {"ProductID"},
        "Products",
        JoinKind.LeftOuter
    ),
    ExpandedProductsColumn2 = Table.ExpandTableColumn(
        Source,
        "Products",
        {"Column2"}
    )
in
    ExpandedProductsColumn2
```
おおむね 7 から 8 sec になる。

なぜ速く処理されるかは、プロセスのメモリ利用状況を確認するとよい。マージ処理はすべてメモリ上で行われていて、このとき明示的に指定しない限りすべての列を読み込んでいるのでしょう。結果として、メモリが必要以上に消費され、特に Excel の場合はプロセス当たりのキャパシティがさほど大きくないから、遅い動作になると。

Sales テーブルにも属性値の列盛ってみた。当然だけどマージ先の列も制限するとよいかもだけど、

```text
let
    Source = Table.NestedJoin(
        Sales[[ProductID], [Column3]], // 👈ココも
        {"ProductID"},
        Products[[ProductID], [Column2]], // 👈ココ
        {"ProductID"},
        "Products",
        JoinKind.LeftOuter
    ),
    ExpandedProductsColumn2 = Table.ExpandTableColumn(
        Source,
        "Products",
        {"Column2"}
    )
in
    ExpandedProductsColumn2
```

これでもよいかもね。

```text
let
    Source = Table.NestedJoin(
        Sales, {"ProductID"},
        Products[[ProductID], [Column2]], // 👈ココ
        {"ProductID"},
        "Products",
        JoinKind.LeftOuter
    ),
    ExpandedProductsColumn2 = Table.ExpandTableColumn(
        Source,
        "Products",
        {"Column2"}
    ),
    // 👇 ココ
    RemovedOtherColumns = Table.SelectColumns(
        ExpandedProductsColumn2,
        {"ProductID", "Column3", "Column2"}
    )
in
    RemovedOtherColumns
```



# 思ったこと🙄
必要以上にマージしたがるのはなぜなんだぜ？と思うのです。みんな大好き VLOOKUP のノリでしょうか？ 今でこそ Excel の VLOOKUP は速くなったとされているのだけど、それまでは工夫をしてたよね。じゃぁ、なんで Power Query でも工夫をしないんだい？

# その他
https://powerbi.connpass.com/

http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981

http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
C# Word文書の段落を削除

<p><strong>今日はSpire.Doc for .Net という無料のライブラリを利用して、Word文書の段落を削除する方法を紹介します。指定する段落と、文書内の段落全体の削除方法を紹介させていただきます。</strong></p>
<h4><strong> 下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/download-word-for-net-free.html">Free Spire.Doc for .NET</a>無料版をダウンロードしてください。</strong></p>
<p><strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210721/20210721154816.png" alt="f:id:lendoris:20210721154816p:plain" width="517" height="239" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></strong></p>
<p><strong>2.Visual Studioを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいDoc.dllを参照に追加してください。（Net 4.0を例としたら、デフォルトパスは“Bin→NET4.0→Spire.Doc.dll”というようです。）</strong></p>
<p><strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210721/20210721154822.png" alt="f:id:lendoris:20210721154822p:plain" width="274" height="216" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></strong><strong> </strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210721/20210721155213.png" alt="f:id:lendoris:20210721155213p:plain" width="554" height="575" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>指定する段落を削除</strong></h4>
```C#

//Document objectを作成します。
Document document = new Document();
//Wordファイルをロードします。
document.LoadFromFile("Input.docx");

//一つ目の段落を削除します。
document.Sections[0].Paragraphs.RemoveAt(0);

//保存します。
document.SaveToFile("RemoveParagraph.docx", FileFormat.Docx2013);
```

<h4><strong>実行結果</strong></h4>
<p><strong> </strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210721/20210721155156.png" alt="f:id:lendoris:20210721155156p:plain" width="554" height="550" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>段落全体を削除</strong></h4>
```c#
// Document objectを作成します。
Document document = new Document();
// Wordファイルをロードします。
document.LoadFromFile("Input.docx");

//文書をループして、段落全体を削除します。
foreach(Section section in document.Sections)
{
    section.Paragraphs.Clear();
}

//保存します。
document.SaveToFile("RemoveAllParagraphs.docx", FileFormat.Docx2013);
```


<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210721/20210721155327.png" alt="f:id:lendoris:20210721155327p:plain" width="554" height="524" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p>
<p> </p>