OmniAICreator/Qiita-1.07M huggingface dataset:
[WIP]オレ的Markdownチートシート

### 記事内容
自分用によく使うMarkdownをまとめました。
今後も追加していくつもりです。。。(多分)

### Markdown

* リスト表示
```
(番号なし)
* list1
* list2
* list3

(番号あり)
1. list1
2. list2
3. list3
```

* チェックボックス
```
- [x] 実施済み
- [ ] 未実施
```

* テーブル
```
| 左揃え | 中横揃え | 右寄せ |
| :---- | :----: | ---:  | 
| row1  | row2   | row3  |
```

* 打ち消し
```
~~打ち消し文字~~
```

* アコーディオン（？）
```
<details>
<summary>
タイトル
</summary>
ボディ
</details>　　
```

* 引用
```
>引用本文１
>引用本文２  
>引用本文３
>引用本文４
```

* url
```
[Google](https://www.google.com) 
```
【Google Apps Script】スプレッドシートとの連携まとめ

## 事前準備
### スプレッドシートIDの取得
対象のスプレッドシートを開き、URLの以下の部分がシートIDにあたる。
`https://docs.google.com/spreadsheets/d/{シートID}/edit#gid=0`

スプレッドシートIDとシート名を定数定義しておく。
```
const GSS_ID = "シートID";
const GSS_SHEET_NAME = "sheetA";
```

## シートの取得
`openById`メソッド、`getSheetByName`メソッドを使う。
```
const book = SpreadsheetApp.openById(GSS_ID);
const sheet = book.getSheetByName(GSS_SHEET_NAME);
```

## 書き込み
`getRange`メソッド、`setValue`メソッドを使う。
以下を実行すると、A1セルに「Apple」が書き込まれる。
```
sheet.getRange("A1").setValue("Apple");
```

### 複数行への書き込み
```
sheet.getRange("A10:B11").setValues([["aaa", "bbb"], ["ccc", "ddd"]]);
```

### 最終行への書き込み
`appendRow`メソッドを使う。
配列で文字列を渡し、複数セルへの書き込みができる。
```
sheet.appendRow(["Pine", "Apple", "Banana"]);
```

## 読み込み
`getRange`メソッド、`getValue`メソッドを使う。
```
const a1 = sheet.getRange("A1").getValue();
console.log(a1);
```

### 複数セルの読み込み
`getRange`メソッドで範囲指定し、`getValues`メソッドで配列で値を取得できる。
```
const a1c2 = sheet.getRange("A1:C2").getValues();
console.log(a1c2);
```

なお、`getRange`メソッドは、数値での指定も可能。
A1セルが(1, 1)にあたる。
```
const a1c2 = sheet.getRange(1, 1, 2, 3).getValues();
console.log(a1c2);
```
Salesforceでカスタムオブジェクトを作ってみた

## カスタムオブジェクトとは

カスタムオブジェクトとはユーザーが自ら作成するオブジェクトのことで、会社の施策や案件に応じてオブジェクトの決まりごとなどカスタマイズすることできるオブジェクトのことです。
Salesforceにはオブジェクトと言われるものがもう一つあり、それは標準オブジェクトというものです。
標準オブジェクトとは、Salesforceがデフォルトとして持っているオブジェクトのことで取引先や商談などがあります。

今回は最初に説明したカスタムオブジェクトの作り方を紹介します。

## カスタムオブジェクトの作り方
では早速カスタムオブジェクトを作ってみましょう。
まずSalesforceを開き右上にある設定をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608548/d7c37f30-309f-bd2b-e7e9-30ded161c451.png)





設定にいったらオブジェクトマネージャーの作成をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608548/a4d4b11c-f883-8d6f-a546-d7d34f8e98de.png)






表示ラベルやオブジェクト名を入力し保存をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608548/4f490fb0-85cf-5523-dbda-3671f2466fad.png)





オブジェクトの作成オプション（カスタムオブジェクトが最初に作成されるときにのみ利用可能）のところは二つともチェック入れて保存をクリックすればカスタムオブジェクトの完成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608548/7df481af-bd93-3473-d747-f4ef26665dc6.png)
GitLabのCI/CDパイプラインで no alternative certificate subject name matches target host name が出る

GitLabとRunner (Docker) をDocker Composeで起動して、ゆるーくCI/CDパイプラインを試そうとしたときに出たエラー。
その原因と対応方法のメモ。

## このメッセージが出た環境
このメッセージが出た環境。
赤字部分が今回の原因に関連するところ。

* Docker Composeを使ってGitLabとRunner (Docker) を起動している。
* DockerホストはAWS EC2上の適当なUbuntu。
* <font color="Red">プライベートCAでGitLabの証明書を発行し、それを使っている。</font>
* <font color="Red">GitLabの`external_url`は**gitlab.example.com**。</font>

## メッセージ全文
`fatal: unable to access 'https://gitlab.example.com/privategroup01/privatepj01.git/': SSL: no alternative certificate subject name matches target host name 'gitlab.example.com'`
![qiita01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609745/8970b277-e208-483a-d49e-96b39de15eb4.png)

## 原因
プライベートCAで発行したGitLabの証明書のSANs (サブジェクト代替名) に`external_url`の**gitlab.example.com**が入っていなかった。
![26ca6041793a43749d8a8569290eb38b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609745/76f5d8da-52c2-e1a7-9e53-0d9c87db991b.png)

## 解決方法
メッセージに出ていたホスト名 (gitlab.example.com) をGitLabの証明書のSANsに追加して、発行しなおし。
発行しなおしたらそれをGitLab側に適用する。
コマンド `gitlab-ctl reconfigure` で設定反映させるか、もしくはコンテナ再起動する。
![34b44adc9d064da6bc5aa98116f10119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609745/0806021f-2124-0d0a-bab2-4d7d86c3135e.png)

以上。
設定画面から取得したログイン履歴とデータローダで取得したログイン履歴（LoginHistory）で差分がある

# 問題

設定画面から取得したログイン履歴とデータローダで取得したログイン履歴（LoginHistory）で差分がある。

データローダ→12,000件くらい
設定画面→17,000件くらい

# 解決策

設定画面からの取得だと「システムユーザ」のログインも含まれる。（Tableau CRMなど）
データローダで取得した場合だと、実在するユーザのログイン履歴が取得できる。

・設定画面→システム含めすべてのログイン履歴
・レポート→システム含めすべてのログイン履歴
・データローダ→実在するユーザのログイン履歴
・レポート→実在するユーザのログイン履歴

# 参考リンク

[1][ログイン履歴の監視](https://help.salesforce.com/s/articleView?id=sf.users_login_history.htm&type=5)

[2][Salesfoceのログイン履歴の確認方法とは？レポート表示や注意点など紹介](https://frogwell.co.jp/blogs/salesforce-login/)

[3][SFDC：Login Historyでログイン履歴を参照する](https://tyoshikawa1106.hatenablog.com/entry/2014/11/09/150436)
MacでPython環境作るならHomebrew + asdf + Poetryの組み合わせがいいかもしれない

Python環境の構築方法には、

- インストーラで本体をインストールしたり、
- Homebrewから本体をインストールしたり、
- HomebrewからインストールしたPyenvから本体をインストールしたり、
- HomebrewからインストールしたAnyenvからインストールしたPyenvから本体をインストールしたり、
- requirements.txtでパッケージを管理したり、
- pipenvでパッケージを管理したり、

様々な構築の仕方がありどれが最適なのかよく分かりません。
そこで2022年3月現在で一番それっぽいPython環境の構築方法を調べてみました。
あくまで自分調べなのでこれより良い方法がある可能性もあります。一つの参考として使ってください。

## 結論

**Homebrew(パッケージ管理) + asdf(実行環境管理) + Poetry(仮想環境・ライブラリ管理)の構成が強そう**

なので、

- Homebrewからasdfをインストールし、
- asdfからPython本体をインストールし、
- Poetryをインストールし、
- Poetryで仮想環境を構築してパッケージ管理をします。

## 手順

1.[Homebrew](https://brew.sh/index_ja)のインストール
```shell
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

2.[asdf](https://asdf-vm.com/)のインストール
```shell
$ brew install asdf
```

3.[asdfのパスを通す](https://asdf-vm.com/guide/getting-started.html#_3-install-asdf)
4.asdfでPythonプラグインを追加
```shell
$ asdf plugin-add python
```
5.asdfでインストールできるPythonのバージョンを確認
```shell
$ asdf list-all python
```
6.asdfでPythonをインストール
```shell
$ asdf install python 3.10.4
```
７.asdfでインストールしたバージョンをグローバル(ローカル)に指定
```shell
$ asdf global python 3.10.4 #　ローカルに指定したいときは"asdf local"を代わりに実行
$ asdf reshim python
```
8.シェル再起動
9.Pythonのバージョンが反映されていることを確認
```shell
$ python -V
Python 3.10.4
```
10.[Poetry](https://python-poetry.org/)をインストール
```shell
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
```
11.Poetryでプロジェクトディレクトリ内に設定ファイル`pyproject.toml`を作成
```shell
$ poetry init
```

以上でHomebrew + asdf + Poetry が構築できました。

## 各ツールについて

### Homebrew
https://brew.sh/index_ja

- macOS用でデファクトになっているパッケージマネージャ
- ターミナルからいろんなソフトをインストールできる

### asdf
https://asdf-vm.com/

- ランタイムバージョンマネージャ
- いろいろな言語をバージョン指定してインストールできる

### Poetry
https://github.com/python-poetry/poetry

- Pythonの仮想環境・パッケージマネージャ
- 作成した仮想環境内にパッケージをインストールし、仮想環境上でPythonスクリプトを実行できる

## 基本的な使い方

```sh
$ poetry add [package]
```
して
```sh
$ poetry run [command]
```
するだけで仮想環境内でのコマンド実行ができます。
その他のコマンドはヘルプか公式ページを参照ください。

## まとめ

**2022年3月現在だとHomebrew + asdf + Poetryの構成でPython環境を作るのがつよそう**

以上です。対戦ありがとうございました。
LoginGeo（ログイン履歴の位置情報）をレポートに表示したい

# 問題

設定画面→ログイン履歴→ダウンロードからとれるようなLoginGeo（ログイン履歴の位置情報）をレポートに表示したい。

ユーザからログイン履歴は出せるが、それに紐づくログイン履歴の位置情報の項目が無い。

# 解決策

できない。
必要な場合は、先述の設定画面から、またはApexのみ。
【継承の操作②】インターフェース

## はじめに
オラクル認定資格教科書 Javaプログラマ Silver SE８
第一章　Javaの基本　
第二章　Javaのデータ型の操作
第三章　演算子と判定構造の使用
第四章　配列の作成と使用
第五章　ループ構造の使用
第六章　メソッドとカプセル化の操作
第七章　継承の操作←　ｲﾏｺｺ！！
第八章　例外の処理
第九章　Java APIの主要なクラスの操作

## インターフェース
　インターフェースとは、クラスに含まれるメソッドの具体的な**処理内容を記述せず**、定数とメソッドの型のみを定義したもの。
・すべてのメソッドは抽象メソッドである
・基本的にフィールドを持たない（public static finalが付いたフィールドは持てる（定数））

#### インターフェースの定義
**メソッド**
　インターフェースで宣言するメソッドは抽象メソッドであり、中身を持つことはできない。注意点として、中カッコ「{}」だけを記述した場合（中カッコの間に処理を記述しない）は「処理なし」という中身とみなされるため、コンパイルエラーになる。
　インターフェースは継承される前提のものなので、インターフェース自体は暗黙的にpublicとみなされる。インターフェースに宣言されたメソッドは、自動的に**publicかつabstract**となり、「public abstract」を省略して書くことができる。
```java
interface インターフェース名{
  void hello(); // public abstract void hello();と同じ
  void sample(){} // 中カッコがついているため、コンパイルエラー
}
```
**フィールド**
 インターフェースでは以下の２つのルールを満たしたフィールドのみ記述できる。（ようは定数のみ）
　・**final**を使って、動的に値が変更されないこと（定数であること）
　・**static**を使って、インスタンスが生成されなくても使えること
`int NUM = 1;`左記のように記述した場合、自動的に「public static final」が付けられ、定数となる。
```java
public interface インターフェース名{
  int NUM1 = 1;
  int NUM2 = 2;
  public static final int NUM3 = 3; 
}
```
#### インターフェースの実現
　インターフェースを継承して子クラスを定義する場合は「implements」を使う。
　インターフェースに定義された抽象メソッドのアクセス修飾子と実装した具象メソッドは同じアクセス修飾子である必要がある。
```java
class クラス名 implements インターフェース名{
  public void hello() {
    System.out.println("hello");
  }
}
```
####　インターフェースの多重実現
　インターフェースの多重実現が可能。
　多重実現する場合は、カンマ区切りで列挙する。
```java
class クラス名 implements インターフェース名1, インターフェース名2{
}
```
#### インターフェースの継承
　インターフェースを継承し,より拡張した新しいインターフェースを定義できる。
 また、クラスの継承とは異なり、`**多重継承も可能**である。
　インターフェースの継承は、クラスと同様「extends」を使用する。
```java
public interface インターフェース名1 extends インターフェース名2 {
}
```

## リンク集
[【Javaの基本①】クラスの構造](https://qiita.com/vitamin_b12/items/3f920cd223fd3cc1ceae)
[【Javaの基本②】パッケージとインポート](https://qiita.com/vitamin_b12/items/be766c8c3ef2366d9fea)
[【継承の操作②】インターフェース](https://qiita.com/vitamin_b12/items/cdc76298d7f6a494dff2)
[【Javaのデータ型の操作①】プリミティブ型のデータ・参照型](https://qiita.com/vitamin_b12/items/f922ab56e4d8b6580f49)
[【演算子と判定構造の使用①】論理演算子(&&、||)、同一性（==）、同値性(equals)](https://qiita.com/vitamin_b12/items/9feb89e8fb1bc67a8d6d)
[【演算子と判定構造の使用②】分岐処理(if、swich)](https://qiita.com/vitamin_b12/items/523467908e683474eac7)
[【配列の作成と使用】](https://qiita.com/vitamin_b12/items/2fc45588640c479e1f4d)
[【ループ構造の使用】while文、do-while文、for文、拡張for文](https://qiita.com/vitamin_b12/items/23d853dda9baf727e4ac)
[【メソッドとカプセル化の操作①】メソッドの概要](https://qiita.com/vitamin_b12/items/215ad731221c2691c441)
[【メソッドとカプセル化の操作②】オーバーロード、コンストラクタ](https://qiita.com/vitamin_b12/items/e4fd3d51a35bb6a5566c)
[【継承の操作①】クラスの継承](https://qiita.com/vitamin_b12/items/19f8ad6f9801ac8f6a8f)
[【例外の処理】](https://qiita.com/vitamin_b12/items/f7ebf2c1106a7dcbdb41)
[【Java APIの主要なクラスの操作】](https://qiita.com/vitamin_b12/items/dcd3edfe2273e5a09231)
文系・インフラエンジニアは基本情報ではなく応用情報を取るべき

# 結論
- 我々は理系ではないので「計算全捨て」と「オール文系科目」で攻略する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354194/0ec4043e-157e-1dfd-312d-9368a8208e74.png)

# こういう人におすすめ
- 基本情報を受けたが、アルゴリズムに完敗して落ちている
- 計算問題に抵抗がある
    - よりによって大半の参考書の最初に計算問題がある、ここであきらめる人も多い
- 実務において全く役に立たない基本・応用は合格にスコープを絞って、さっさと高度資格を取りたい
    - 昇進に必要、報奨金目的なども同様
 
# 何故応用情報なのか
- マネジメント系の問題が多くなるため、計算問題/アルゴリズム問題が基本より圧倒的に少ない
  - コードを書かないSEがアルゴリズムをやるのは苦痛なのでそこを回避する
  - 応用情報を取るとオマケとして高度試験の午後1(応用情報の4択問題)免除が2年ある
    - 基本/応用と違って高度試験は実務にある程度近く役に立つから早くそっちをやるべき

- CBTではない
  - 基本情報はCBT受験になり、過去問が公開されなくなった、傾向が読みづらい
  - 応用情報はペーパーテストなので、過去問から傾向が類推できる
    - 国が作る試験なのだから「前例に基づいた軸」が存在 している、過去問から軸を捉える

- 基本情報は持ってて当たり前、応用情報は持っててちょっとやるじゃん、高度系は褒められる
    - 持ってて当たり前ならスキップしてしまえ 

## 勉強方法
- 2~3か月前から始める、それ以上前から始めると飽きる
    - [キタミ式](https://www.amazon.co.jp/dp/4297117835)を1日1章ずつ読む
    - 試験2週間前にもう一度行う

- 午前は過去問を覚える
  - [過去問道場](https://www.ap-siken.com/)で午前は10年分くらいやる 
  - 計算問題は問題文と回答の選択肢を語呂合わせで覚える、計算方法は完全に無視する

- 午後
  - 情報セキュリティは必須なので過去問を5年分2周する、他の午後科目も同じ
  - 5，6ジャンル対応できるようにしておくべきだが、嫌ならおすすめは経営戦略、プロマネ、サービスマネジメント、システム監査、(ネットワーク)
    - シス監は5年分くらいするとシス監筋(国語力)が育つのでそれで難なくとける
    - 経営戦略やサービスマネジメントも筋(国語力)をつければ対応できる
      - プロマネは計算問題が年度によってあったりなかったりするから運、計算が無ければ国語、運に頼りたくないなら他の科目もやっておくべき 
    - ネットワークは前提知識が必要だが、次ネスペ受けたいならやった方がいい、別解が存在せず一番入りやすい印象
    - 他に業務で触ってるならデータベース等でもいい

## 午後得点アップ方法
- 回答の語尾に気を付ける
    - 例えば～の理由を求めよという問題文なら「～のため」という語尾で回答する
- 記述は問題文に大体答えがある、それを逃してはならない

## 春IPA祭りまであと少し
- 受ける人も受けない人も頑張っていきましょう
タイプライターのようなエフェクト【CSSだけ】


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

`animation`と`@keyframes`プロパティを使用して、タイプライターのようなアニメーションができるようです。
CSSだけでこういったアニメーションができちゃうのは便利ですね。

入力する文字数に合わせて、CSSの`width`と`steps()`の数字を変更します。
空白スペースも1文字分とカウントします。
※変更しないとアニメーションが動きません。

## 参考記事
[最近のWebサイトで見かける！ フロントエンドのデベロッパーにもデザイナーにも役立つCSSの実装テクニックのまとめ](https://coliss.com/articles/build-websites/operation/css/10-useful-css-tricks.html)
Shifted BICG法の実装

$L \times L$行列$A$とN個の複素数$\sigma_i$からなる連立方程式

```math
(\sigma_i I + A)x_i = b
```
を解く方法として、シフトBICG法があります。これは、$\sigma_i$が複数あっても一度に解が得られるという面白い手法で、色々な応用がなされています。
この方法を提案した
A. Frommer, "BiCGStab(ℓ) for Families of Shifted Linear Systems", Computing volume 70, pages 87–109 (2003)
のshifted BICG法をJuliaで実装しました。
なお、shift部分を抜けばこれはそのままBICG法になります。BICG法のアルゴリズムがウェブ上で全然見つからなかったため、動くものとしてこちらに載せておきたいと思います。

# バージョン
Julia 1.6

# コード
以下がコードとなります。

```julia
using LinearAlgebra
using Random

function shiftedbicg_Frommer2003(σ,A,b;maxsteps=3000,eps = 1e-15)
    N = length(σ)
    btype = typeof(b)
    q = zero(b)
    x = zero(b)
    r = deepcopy(b)
    rt = deepcopy(b)
    u = zero(b)
    ut = zero(b)
    vec_u = Vector{btype}(undef,N)
    vec_x = Vector{btype}(undef,N)
    for j=1:N
        vec_u[j] = zero(b)
        vec_x[j] = zero(b)
    end
    ρkold = ones(ComplexF64,N)
    ρk = ones(ComplexF64,N)
    πkold = ones(ComplexF64,N)
    πk = ones(ComplexF64,N)
    πknew = ones(ComplexF64,N)
    ρold = 1
    αold = 1
    residual = 0

    for i=1:maxsteps
        ρ = dot(rt,r)
        β = -ρ/ρold    
        axpby!(1,r,-β,u)
        axpby!(1,rt,-β',ut)
        mul!(q,A,u)
        qrt = dot(rt,q)
        α = ρ/qrt
        axpy!(α,u,x)


        for k=1:N
            πknew[k] = (1+α*σ[k])*πk[k]+ (α*β/αold)*(πkold[k]- πk[k])
            βk = (πkold[k]/πk[k])^2*β
            αk =  (πk[k]/πknew[k])*α
            axpby!(1/πk[k],r,-βk,vec_u[k])
            axpy!(αk,vec_u[k],vec_x[k])
        end


        axpy!(-α,q,r)
        mul!(q,A',ut)
        axpy!(-α',q,rt)
        αold = α
        ρold  = ρ

        residual = dot(r,r)
        println(dot(r,r))

        if abs(residual) < eps
            println("Converged at $i-th step. eps: $residual")
            println("--------------------------------------")
            return vec_x
        end

        for k=1:N
            πkold[k] = πk[k]
            πk[k] = πknew[k]
        end

    end

    error("bicg is not converged. The residual is $residual")


end

```

この関数を確認するために、乱数で作った行列で確かめてみたものが以下のコードです。

```julia
function test()
    Random.seed!(123)
    L = 100
    A = rand(L,L)
    N = 10
    σ = rand(ComplexF64,N)
    b = zeros(ComplexF64,L)
    for i=1:L
        b[i] = rand([-1,1])
    end
        
    vec_x = shiftedbicg_Frommer2003(σ,A,b,maxsteps=4000)

    for i=1:N
        r = A*vec_x[i] + σ[i]*vec_x[i] - b
        println("i = $i, σi = $(σ[i])")
        println(norm(r))
    end

end

test()
```

# 解説

ここで、```axpby!(a,X,b,Y)```という関数は```Y = b*Y + a*X```と等価です。Yがすでに定義されているときに上書きする形でYを更新してくれます。また、```axpy!(a,X,Y)```という関数は```Y = Y + a*X```と等価です。そして、```mul!(y,A,x)```は```y = A*x```と等価です。

このコードが動くための条件としては、

- ```mul!(y,A,x)``` 
- ```axpby!(a,X,b,Y)```
- ```axpy!(a,X,Y)```
- ```dot(X,Y)```：XとYの内積
- ```x = zero(b)```:bと同じサイズで中身がゼロのxを作る

が定義されていることです。ですので、通常の行列はもちろんのこと、自分で定義したstructでも上の関数が定義されていればそのまま動くはずです。
model_to_dotで全範囲可視化されない時の、追加コード

下記図のように、model_to_dotでモデルの可視化が全範囲表示されなかったため、コードを追加しfix
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863223/7355d267-1548-2824-997e-06e6790ac5a4.png)

dpi=Noneをmodel_to_dotの設定に追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1863223/c1092bbc-7385-7504-7f34-605e72bf2379.png)
Rust試行錯誤


### RUSTのパッケージ管理ツール
cargoを使う。
```
# cargo install tokei
```

### RUST一式のインストール
自前でビルドするとき。  
```
# yum install -y gcc
# curl https://sh.rustup.rs -sSf | sh
# source $HOME/.cargo/env
# rustc --version
```

### シングルバイナリ化させる
muslを使えばOK。    
URL：https://github.com/emk/rust-musl-builder  

tokeiをビルドするときはこんな感じ。  
```
# git clone https://github.com/XAMPPRocky/tokei.git tokei
# cd tokei/
# alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src ekidd/rust-musl-builder'
# rust-musl-builder cargo build --release
```

### 参考URL
- https://github.com/emk/rust-musl-builder
- https://www.office-matsunaga.biz/dev/description.php?id=18
- https://blog.mamansoft.net/2018/08/20/rust-linux-single-binary/
- https://qiita.com/ismt7/items/a6b17b01b56f098b2dd5
コマンドでのワイルドカード、正規表現

コマンドラインで、いろいろやるときに、ワイルドカードと正規表現が自分の頭の中でごっちゃになるので、まとめておこうと思います。

# シェル

シェルはワイルドカードを展開します。
なので`echo *`とすると、カレントディレクトリ以下のファイルが(ディレクトリも)表示されます。

ほかにも、シェルで展開されるものがあり、チルダやブレースも展開されます。

```
[MacbookProKun]:/ % echo *
Applications Library System Users Volumes bin cores dev etc home opt private sbin tmp usr var
[MacbookProKun]:/ % echo ~
/Users/ユーザー名
[MacbookProKun]:/ % echo {1..10}
1 2 3 4 5 6 7 8 9 10
```

ここで重要なのが、ワイルドカードに関してはコマンドに渡される前に展開されますが、**シェルは正規表現を解釈できない**ということです。

# コマンド

`grep`では、ワイルドカードではなく、正規表現になります。デフォルトでは基本正規表現(オプションは`-G`)、また拡張正規表現(オプションは`-E`)、Perlの正規表現(オプションは`-P`)などがあります。

```
[MacbookProKun]:/ % echo "a\nab\nabb" | grep 'ab*'
a
ab
abb
```
bが0個以上繰り返されている

# まとめ

"コマンドで何かする時は正規表現"、でも"シェルでまずはワイルドカードが展開される"と覚えておけば良いと思います。

# 参考

https://se.cite.ehime-u.ac.jp/~aman/memo/bash/fundamental.html

https://milestone-of-se.nesuke.com/sv-basic/linux-basic/wildcard-regular-expression/
【Rails】checkboxのデザインを変更


## やりたいこと

checkboxのデザインを変更したい。

checkボックスの大きさや、位置は以下のように変更することはできる。

```scss
input[type=checkbox] {
  witdth: 20px
}
```

しかし、checkboxの枠の色とか、チェックした後の背景色など、細部のデザインを変更する方法にハマったので備忘録としてメモします。

## 方法

①デフォルトのデザインを消す
②labelを使って擬似的なcheckboxを作る
③labelのforにid指定をする
④check 後のデザインを作成する

## ①デフォルトのデザインを消す

以下を追加するだけ
```scss
input {
  display: none;
}
```

## ②labelを使って擬似的なcheckboxを作る

以下のように <%=check_box // %>と隣接するようにlabelを設置する。
このlabelが後々、checkbox のデザインになっていきます。
```html.erb
<td class="">
   <%= check_box "deletes_1" %>
   <label for=""></label>
</td>
```

その後、CSSは以下のように追加すると、checkboxの枠だけが出現します。ただ、現状では枠があるだけで、クリックしても何も変化はありません。

```scss
.checkbox {
  label {
    display: block;
    position: relative;
    margin-left: 16px;  //デザインに合わせる
    cursor: pointer;

    // ✔️ が入る前のデザインをあてる
    &:before {
      content: "";
      position: absolute;

      // 枠のデザインを変更できる
      border: 1px solid #000000;
      border-color: rgba(0,0,0,0.1);
      border-radius: 2px;
      width: 20px;
      height: 20px;
    }
  }
}
```

## ③labelのforにid指定をする

label タグのforに、input タグのidを当てはめ込むことで、inputタグのクリック領域がlabelまで拡張されます。つまり、labelをクリックするとcheckboxにチェックが入るようになります。
```html.erb
<td class="checkbox">
  <%= check_box_tag "deletes_1" %>
  <label for="deletes_1"></label>
</td>
```

## ④check 後のデザインを作成する

以下の変更点を反映させるために、CSSに以下を追加します。
・checkboxの背景色を変更する
・チェックマーク✔️を画像として表現する

```scss
.checkbox {

// 略

  // チェック後のlabelのデザインを以下に記述する
  :checked + label {
    

    // チェックボックスの背景色
    &:before {
      background: #007AFF;
    }
    // チェックマーク✔︎　を表示させる
    &:after {
      content: "";
      display: block;
      width: 20px;
      height: 20px;
      background-image: 'check.svg'
      background-repeat: no-repeat;
      background-position: center;
      position: absolute;
    }
  }
}
```

上記に出てくる `:after` とか、`:before`はcheckboxの挙動を観察すると分かりやすいです。

以下はチェックが入る前の状態で、`:before`のみが出現している様子がわかります。
つまり、最初から存在しているcheckboxの枠は`:before` に当てると良いと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508607/cc221e34-6cf0-1a8e-1dfa-f33a190d05fa.png)
以下はチェックが入った後の状態で、`:after`が追加された様子がわかります。
そのため、後から出現する✔️マークのデザインは`:after`に当てたら良いと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508607/f3aaf875-8a5e-ca45-c01c-bde4c0affc67.png)
## 全体像

CSSの全体像は以下のような感じになります

```scss
.checkbox {

  input {
    display: none;
  }

  label {
    display: block;
    position: relative;
    margin-left: 16px;  
    cursor: pointer;

      &:before {
      content: "";
      position: absolute;

      border: 1px solid #000000;
      border-color: rgba(0,0,0,0.1);
      border-radius: 2px;
      width: 20px;
      height: 20px;
      }
    }

    :checked + label {
    
      &:before {
        background: #007AFF;
      }

      &:after {
        content: "";
        display: block;
        width: 20px;
        height: 20px;
        background-image: 'check.svg'
        background-repeat: no-repeat;
        background-position: center;
        position: absolute;
      }
    }
  }

```

## 参考

[Railsでlabelタグ](https://blog.willnet.in/entry/20080911/1221111749)

[CSSでinputのcheckboxをデザインする（チェックボックス）](https://lpeg.info/html/css_checkbox.html)
【クエリビルダ】カスタムフィールドを定義してみる

ご存知のとおり [Sharperlight](https://sharperlight.jp/)は、独自のデータモデル階層を使用してデータソースと会話をしています。データモデル作成時には、対象となるデータソース(データベース)のテーブルおよびフィールド情報がデータモデルに取り込まれます。
しかしながらレポート等の作成上、フィールドの追加が必要になることが多々あります。
そのような場合、[Sharperlight](https://sharperlight.jp/)には、**カスタムフィールド**というものが存在します。
この記事では、**製品テーブル**の**製品コード**と**製品名**を結合した値を返す**カスタムフィールド**を作成します。
[Sharperlight](https://sharperlight.jp/)の拡張表現を使用してこれら二つのフィールドの値を結合することは、下図で示すように可能です。
しかし、複数のレポートを作成するにおいて、その複数のレポート全てでこのような結合値を使用するといった場合、各レポート作成時に毎回この拡張表現を繰り返し定義する手間が発生します。また変更が発生した場合、全てのレポートの変更が必要となります。このような場合、**カスタムフィールド**を一つ作成しておくと、そういった手間が発生しないことになります。
![2022-03-31 Figure 04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/eaa946c4-4ca2-6a50-c64f-730dd8be7dcb.png)
では早速見ていきましょう。先ずはクエリビルダを起動します。
**カスタムフィールド**を定義する対象となる製品とテーブルを選択します。
![2022-03-31 Figure 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/8fa0a0f6-6087-f04e-517c-9a751be37029.png)
ここで、**カスタムフィールド**の作成に入る前に、ある情報を収集しておきましょう。カスタムフィールドの定義時には、対象データベース内のフィールドの実名が必要となります。下図のように、右クリックメニューから[情報]を選択し、結合する二つのフィールドの実名を確認しておきます。
![2022-03-31 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3bac4478-dae5-8ef6-fe82-44b0dff89070.png)
[情報]ダイアログでは[技術的詳細]タブへ移動します。
![2022-03-31 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/cc344c8f-ab27-c430-a26c-dc1ba6a1a5b1.png)
フィールドの実名の確認が済んだら、選択領域の右クリックメニューから[カスタマイズ] -> [フィールドを追加]を選択します。
![2022-03-31 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b2facf11-d60a-9c2c-be7e-0dab7978f51e.png)
[カスタムフィールド編集]ダイアログでは、下図のように四つのプロパティに値を定義します。
![2022-03-31 Figure 07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3a93175e-3d19-d6a1-ef31-fb2d7fe6dd1a.png)
**Description:** クエリビルダの選択領域に表示される名称を記述します。
**Data Type:** 今回はStringですね。
**SQL Column:** 
ここで二つのフィールド値の結合を行います。ここでの構文はそのままSELECT文に使用されるので、対象となるデータベースエンジンに準じた構文を記述します。今回はMicrosoft SQLなので、
```
CONCAT({_Table.Alias}.[製品コード],' - ',{_Table.Alias}.[製品名])
```
となります。```{_Table.Alias}```は実行時に[Sharperlight](https://sharperlight.jp/)エンジンによって解決されるコントロールタグです。
**SQL Data Type:** Charを指定します。
上記四つのプロパティを記述し終えたら、[ok]ボタンで保存しましょう。
クエリビルダの選択領域に作成した**カスタムフィールド**が青字で表示されます。
![2022-03-31 Figure 08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/df8e018c-2123-0e4b-8558-ce421d66272a.png)
出力領域にドラッグ＆ドロップします。
![2022-03-31 Figure 09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/eeab6cd7-1366-b6e4-f63f-26de6225e218.png)
[プレビュー]ボタンで動作確認をします。
![2022-03-31 Figure 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/74ad1417-9a4a-dd85-90a2-026903e7ad4d.png)
生成および実行されたSQL文も確認してみます。
![2022-03-31 Figure 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d9daed5d-0be0-6cfd-d998-23175d9ac1a6.png)
以上が**カスタムフィールド**の定義および使用の簡単な説明です。
:postbox:[Sharperlight](https://sharperlight.jp/)
プログラマに必要なPC（動作環境、推奨環境）

# 2024年のプログラマに必要なPC

## 必須動作環境

- Windows11 Pro 以上のOS (win10ダウングレード可)
- Microsoft 365 (office) home 以上のライセンス
 onlineはだめ
- 仮想化が有効な 4コア以上の intel core 第8世代以降の CPU
 Celeronとかはダメ
- 16GB以上のメモリ
- 512GB以上のSSD
- FullHD を出力可能なグラフィック性能
- VPN（IPSec）が利用可能なネットワークインターフェイス
- 管理者権限を与えられたWindowsアカウント
- インターネットへの接続が可能なネットワーク
- ポインティングディバイス

## 推奨環境

- Windows11 Pro 以上のOS (win10ダウングレード可)
- Microsoft 365　(office) Business Basic 以上のライセンス
- 仮想化が有効な 4コア以上の intel core 第11世代以降の CPU
 Celeronとかはダメ
- 32GB以上のメモリ
- 900GB以上のSSD
- USB-c 給電
- FullHD を 2画面以上出力可能なグラフィック性能
- モニタ出力端子が2つ以上 (アダプタ可)
- デュアルディスプレイが使用可能な環境
- VPN（IPSec）が利用可能なネットワークインターフェイス
- 管理者権限を与えられたWindowsアカウント
- インターネットへの接続が可能なネットワーク
- ポインティングディバイス

尚可

- 動作してる事が分かるWEBカメラ
- ノイズキャンセル機能付きマイク
- モバイルディスプレイ
- 65w出力可能なモバイルバッテリー
- ChatGPTのライセンス
- AIを動作させるGeforce製VRAM12GB以上のグラフィックス

### macは？

MacBook Pro買っとけ

# 2022年のプログラマに必要なPC

## 必須動作環境

- Windows10 Pro 以上のOS
- Microsoft 365 (office) home 以上のライセンス
 onlineはだめ
- 仮想化が有効な 2コア以上の intel core CPU
 Celeronとかはダメ
- 8GB以上のメモリ
- 256GB以上のSSD
- FullHD を出力可能なグラフィック性能
- VPN（IPSec）が利用可能なネットワークインターフェイス
- 管理者権限を与えられたWindowsアカウント
- インターネットへの接続が可能なネットワーク
- ポインティングディバイス

## 推奨環境

- Windows10 Pro 以上のOS
- Microsoft 365　(office) Business Basic 以上のライセンス
- 仮想化が有効な 4コア以上の intel core 第8世代以降の CPU
 Celeronとかはダメ
- 16GB以上のメモリ
- 900GB以上のSSD
- FullHD を 2画面以上出力可能なグラフィック性能
- モニタ出力端子が2つ以上
- デュアルディスプレイが使用可能な環境
- VPN（IPSec）が利用可能なネットワークインターフェイス
- 管理者権限を与えられたWindowsアカウント
- インターネットへの接続が可能なネットワーク
- ポインティングディバイス

尚可

- 動作してる事が分かるWEBカメラ
- ノイズキャンセル機能付きマイク
- USB-c 給電

# なんでそんなスペック居るの？

Windows11を見据えてるため、必要なCPUに第8世代以降が必須
officeは仕様書を読み書きするため
CPUは仮想化対応しつつ余計なバグとか出さないようにするため
シングルコアなCPUは流石にもう無いハズだがそんなものがあれば人権侵害
SSDは基本的人権
ネットワークは推奨CPUついてるならクリアしてる
デュアルモニタは大切
メモリの多さは大切
特に統合開発環境とドッカーとか仮想化併用するともりもりメモリを使う

# 事務用PCをそのままプログラマに支給してる御社へ

一般的な事務業務で使う最安クラスのPCでプログラマに開発を行わせるのは基本的人権の侵害です
直ちに改善してください

SSDじゃなくてHDDなPCを支給してる会社
流石にもういねーよなっ？
STM32L010で9600bpsのソフトウェアシリアルのライブラリ化



x Mbed2


目的
ソフトウェアシリアルのテスト
シリアルの出力先は、PA_2


![o_con299.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/021f0643-4060-c510-26b0-d7b13824050d.jpeg)



メインプログラム



```c++



//SER_LB_9600_010_1

#include "mbed.h"

#include "SER_9600_010_1.h"

//メイン関数
int main()
{

    pc.baudNS(9600);
    
    //無限ループ
    while(1) {

        //文字列の表示
        pc.printNS("HELLO WORLD\r\n");
        
        //4桁の値の表示
        pc.printNS(  1234  );
        //リターン
        pc.printNS("\r\n");

        //1秒の待ち
        wait_ms(1000);

    } //while

} //main

//容量削減
void error(const char* format, ...) {}





```


SER_9600_010_1.hのプログラム



```c++


//SER_9600_010.h

//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)

char ch_hex_a_b[16];
char *ch_hex_a(int x)
{

    ch_hex_a_b[4] = 0;

    if       ( x >= 9000 ) {x = x - 9000; ch_hex_a_b[0] = '9';
    } else if( x >= 8000 ) {x = x - 8000; ch_hex_a_b[0] = '8';
    } else if( x >= 7000 ) {x = x - 7000; ch_hex_a_b[0] = '7';
    } else if( x >= 6000 ) {x = x - 6000; ch_hex_a_b[0] = '6';
    } else if( x >= 5000 ) {x = x - 5000; ch_hex_a_b[0] = '5';
    } else if( x >= 4000 ) {x = x - 4000; ch_hex_a_b[0] = '4';
    } else if( x >= 3000 ) {x = x - 3000; ch_hex_a_b[0] = '3';
    } else if( x >= 2000 ) {x = x - 2000; ch_hex_a_b[0] = '2';
    } else if( x >= 1000 ) {x = x - 1000; ch_hex_a_b[0] = '1';
    } else                 {              ch_hex_a_b[0] = '0';
    }//if

    ch_hex_a_b[3] = '0' + (  x - (DIV10(x) * 10)  );  // 3  <- 120 - 123
    x = DIV10(x);                                     // 12 <= 123 / 10
    ch_hex_a_b[2] = '0' + (  x - (DIV10(x) * 10)  );  // 2  <- 12 - 10
    ch_hex_a_b[1] = '0' +  DIV10(x);                  // 1  <- 12 / 10

    return(ch_hex_a_b);

} //ch_hex_a


#define UART_DELAY 101 //  1/9600 98-105

DigitalOut TX(PA_2);

//クラスの定義
struct _pc
{
  void baudNS(int sp);      //メソッドの宣言
  int  putcNS(char ch);      //メソッドの宣言
  int  printNS(char *str1);  //メソッドの宣言
  int  printNS(int num);     //メソッドの宣言 オーバーロード
};


//ポートをhiにする 初期化
//メソッドの定義
void _pc::baudNS(int sp)
{
  TX=1;
  wait_ms(1);
}//baudNS


//仮想シリアルへの一文字出力 9600bps
//メソッドの定義
int _pc::putcNS(char ch)
{
    TX=1;
    TX=0;//Start
    wait_us(UART_DELAY);

    for(int ii=0; ii<8; ii++) { //Data x 8
        TX=(ch>>ii)&1;
        wait_us(UART_DELAY);
    }; //for

    TX=1;//Stop
    wait_us(UART_DELAY);

    return(0);
}//putcNS


//文字列の表示
//メソッドの定義
int _pc::printNS(char *str1)
{
    //文字の中身がゼロか
    while(*str1) {

        //一文字出力
        putcNS(*str1 ++);

    } //while

    //戻り値
    return(0);  
}//printNS


//文字列の表示 オーバーロード 4桁
//メソッドの定義
int _pc::printNS(int num)
{
    if(num < 0) { putcNS('-'); num = 0 - num;   }
    
    char *str1 = ch_hex_a(num);
    
    //文字の中身がゼロか
    while(*str1) {

        //一文字出力
        putcNS(*str1 ++);

    } //while

    //戻り値
    return(0);  
}//printNS


//実体の作成
_pc pc;




```
Migrate to Flowでのエラー


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


きっと、今後はこのツールの問い合わせが多いはずだから...

+ [基準にクロスオブジェクト参照が含まれているため、このワークフロールールを移行できません。Migrate to Flowは、この構成をサポートしていません。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000G44zKSAR)

EmailMessageオブジェクトにレコードトリガーフローを作成します。
次に、フロー内で、ケースの親isClosed値を調べる決定要素を実行して、着信ロジックとケースクローズロジックを実行する必要があるかどうかを判断します。はいの場合は、オープンケースロジックを実行します。いいえの場合、ロジックがない場合はフローを終了します。

+ [Flowに変換する時に発生するエラーについて　Unsupported Formula error](https://qiita.com/Keiji_otsubo/items/5d3ac0ec32eda7cd2de1)
余ったPCをNASにする - TrueNASとUnraidの比較検討

# はじめに

10年ぶりにPCを新調しました。とはいえ以前のPCもまだまだ使える代物なので、NASにしてみようと思いました。

PCをRAID対応NAS化する場合、TrueNAS(旧名称FreeNAS)が鉄板のようですが、調べていると海外ではUnraidというNAS OSも結構人気なのが分かりました。

以下、自分都合でのTrueNASとUnraidのいいところ、いまいちなところです。なお、TrueNASを実際に使ったわけではないので印象レベルです。

# TrueNAS

https://www.truenas.com/

## TrueNASのいいところ

- エンタープライズ向けをターゲットにした本格的な設計で、耐障害性と高性能を両立。これにつきます。もちろんRAID6にも対応
- 一日24時間常に読み書きの高負荷がかかる環境でもばっちり
- ZFSなのでスナップショット機能がある
- TrueNAS COREは無料。個人利用ならこれでも十分以上
- Unraidに比べてGUIがかっこいい。特にダッシュボード
- GUIが一応日本語対応されてる
- blogなどでの日本語解説記事が比較的多い

## TrueNASのいまいちなところ

- 要求システムリソースが高い。その高性能を発揮するには最低でも16GBのRAMが必要。また、ネットワークも1Gbpsでは物足りない
- 使用するHDDはすべて同じサイズにする必要がある
- 後からディスクを追加することはできない
- 正直ガチすぎて家庭用としてはオーバースペックな印象
- FreeBSDベース。Sun-3以降BSD系のOSは使っていないのできつい（個人の感想です）。なお、LinuxベースのTrueNAS Scaleが2022年2月に正式リリースされてますが、肝心のNASとしてのパフォーマンスがかなり劣る模様（ただしβ版時点での話なので、現行版は違うかもしれません）
- Dockerが使えない（TrueNAS Scale除く）
- BSDの文化を感じさせる厳格なユーザコミュニティ（個人の感想です）

# Unraid

https://unraid.net/

## Unraidのいいところ

- TrueNASに比べると設定が比較的簡単
- 要求システムリソースが低く(RAMは4GB)、余ったPCで動かすのにちょうどいい
- 使用するHDDのサイズを合わせなくていい。サイズ違いのHDDを気軽に追加して後からNASの容量を増やすことができる
- USBメモリからブートするため、全てのSATAインタフェースをデータ用HDDにまわせる。システムのバックアップ・復旧も簡単
- Parityディスクを割り当てることで、RAID5やRAID6のようにHDDが1台もしくは2台故障しても復旧させることが可能
- １つのファイルは１つのHDD内に保存されるので、RAID5,6と違ってHDDの多重障害時にも全滅はしない
- HDDの分散アクセスをしないので、RAIDに比べてHDDのスピンダウン時間が増えやすい。また同様の理由でSMRのHDDでもさほど問題ないはず
- 慣れ親しんだLinuxベース（個人の感想です）。とはいえ懐かしのSlackwareだそうですが
- Dockerが使える
- Linuxの文化を感じさせる素人にやさしいユーザコミュニティ（個人の感想です）

## Unraidのいまいちなところ

- 有料。HDD 6台接続のライセンスで\\$59、12台で\\$89、無制限で\\$129。ただし30日のトライアルが可能です。
- HDDの分散アクセスをしないので、TrueNASに比べて読み書き速度がかなり劣る。読み込みは単体のHDDと同じ速度ですが、書き込み性能が悪くHDD本来の速度の半分以下になる。ただし、Turbo Writeモードか、SSDキャッシュの利用である程度対応は可能。
- SSDを使った読み書きキャッシュの機能が、TrueNASに比べてかなりいまいち
- ホットスワップには対応していない
- GUIの日本語対応無し（仕組みは用意されてるのですが...）
- 日本語での解説記事はTrueNASに比べて少ない

# Unraidにした理由

今回以下の理由からUnraidを使うことにしました

- バックアップ用途をメインとし、読み書きパフォーマンスはほどほどでいいとする
- 余り物のPCとHDDを有効活用できる
- 後からディスクの追加が行える
- 気合い入れなくてもゆるく運用できそう

# Unraidをお勧めしないケース

実際にUnraidをインストールして試してみたのですが、Sambaで小さいファイルを書き込むパフォーマンスがあまりにも悪く、1MB/s以下の速度になってしまいます。写真など比較的小さい大量のファイルを書き込む用途には全く向いていないことがわかりました。

https://forums.unraid.net/bug-reports/stable-releases/slow-smb-performance-r566/

Unraidの肝となる分散ファイルシステムの実装がいけてないのが理由らしいので、やっぱりTrueNASにしようかと正直かなり悩みましたが、適当にディスク入れて使える魅力には勝てませんでした。

# インストール編

https://qiita.com/tinoue@github/items/1f7955f0578a73cd398f

## 参考

https://p-side.net/posts/2020-12-04-nas-os-unraid/

https://jpblog.actiphy.com/archives/11622

https://ja.home-theater-designers.com/5-reasons-why-unraid-is-ultimate-home-nas-solution
【JUnit】ローカルでテスト成功するのにGitLabCIでは失敗する時の調べ方

# 結論
1. GitLab CIで実行したテストのレポートを表示する
1. レポートを元に原因突き止めて修正する！

## 前提
GitLabのfeatureブランチへpushすると、テストで失敗していてbuildできない。
ローカルでは全てテスト成功しているのに、、
### 環境
- Mac
- GitLab 14.10.0
- Java 11
- JUnit 5.8.1
- ビルドツール `Gradle`

### テスト失敗時の詳細
- ローカル
    - `プロジェクト/build/reports/tests/test/index.html`　で詳細が見れる
- リモート（GitLabCI）
    - 　どこで見るの？？

# GitLab上でテストレポートを確認したい
## 1 ） `.gitlab-ci.yml` に追記

```yaml:.gitlab-ci.yml（一部抜粋）

gradle_test:
  stage: test
  script:
    - gradle test
  artifacts:
    paths:
      - build
    when: always
    reports:
      junit: build/test-results/test/**/TEST-*.xml
```

（上記は、javaビルドツールが`Gradle`の場合。Mavenの場合は異なる。）
（GitLab Runner13.0以降では、`*`が使える）

 - `artifacts: paths:`
    - Jobが終了した後に作成されるファイルやディレクトリの一覧のパスを指定（リポジトリのルートからの相対パス）
    - 上記の場合、リポジトリ直下のbuildディレクトリを指定している




## 2 ） GitLab画面での詳細確認手順

- GitLab画面　`CI/CD` / `Pipelines` メニュー / `Tests`タブで、失敗したJob名をクリック
![Pipeline2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646452/77a8975d-f041-c6ad-d650-f1d375346678.png)

- 失敗したテストの詳細をクリック
    - ローカルテストと同じような詳細が確認できます
![Pipeline3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646452/38d21aed-2c0c-e0bd-35fe-be9ff7f32f12.png)


# さいごに
詳細を見て、原因判明。
原因：日付フォーマット変換と単体テストを追加してみたが、ローカルとリモートのTimeZoneが異なっていた。
確かに、ローカルでは通ったテストが、リモートでは通らないわけですね、、

SimpleDateFormatクラスで日付フォーマットの変換等をしているので、
TimeZoneを合わせる必要があるってこと（きっと常識の常識なんだろうな）勉強になりました。

失敗原因の調べ方さえ分かれば、どうにかなるかなと。今後のためのメモでした。




>参考
・[GitLabドキュメント/UnitTestReport](https://docs.gitlab.com/ee/ci/unit_test_reports.html#gradle)
・[Reporting test results in GitLab](https://medium.com/trendyol-tech/reporting-test-results-in-gitlab-6c1938a7472e)
cscの作法 その82

# 概要
cscの作法、調べてみた。
DateTimePickerやってみた。

# 参考にしたページ

https://uchukamen.com/Programming1/DateTimePicker/index.htm

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b4c31127-ed23-b95c-5355-94a343915be5.png)


以上。
Nginx - How to Setup Web Site with Single Page Application(SPA)?

When you serve a web site in SPA, you will get 404 after F5 refresh page.

For example: We want to access a url http://127.0.0.1:8080/taiwan

# 1. Modified Web Vue Project Code

```vue:router.js
new VueRouter({
  mode: 'history',
  base: '/taiwan',
  ...
)}
```

```javascript:webpack.config.js
...
output: {
  ...
  publicPath: '/taiwan'
},
...
```

# 2. Modified Nginx Configuration
```
location /taiwan {
  alias   /usr/share/nginx/html/taiwan/;
  try_files $uri $uri/ /taiwan/index.html;
  index  index.html;
}
```

# 3. Nginx Reload
```
# nginx -s reload
```


https://segmentfault.com/a/1190000040407832/en
IBM Cloud: VPC ALBを使ってVPC外部のIPアドレスに割り振りを行う方法

# 1. はじめに

VPC ALBは従来、UI上からはVPC上のサーバーにしかBackend poolに追加できませんでした。CLIであれば一応追加はできたのですが、その際にはサーバーのヘルスチェック状態をUI上から確認することができませんでした。
今回、新たにVPC ALBでは任意のIPアドレスをBackend Poolに追加することができました。これにより、Power Systems Virtual Serverを利用する際のシナリオも幅が広がります。例えば、

- Power Systems Virtual Serverへの割り振りが可能（Power Systems Virtual Serverにはロードバランサーサービスが存在しない）
- Power Systems Virtual Serverのサービスをインターネット(VPC ALB: publicタイプ)およびオンプレミス(VPC ALB:privateタイプ)に公開可能

というシナリオが容易に構成できるようになりました。本稿ではその機能を確認してみます。

# 2. 利用方法

前提として

- VPCとPower Systems Virtual ServerはDirect Linkでプライベート接続できている
- Power Systems Virtual ServerにはWebサーバーが構成済みであり、VPCからアクセス可能である。ここで、`192.168.50.223`がPower Systems Virtual ServerのIPアドレスです。

```
[root@new-syasuda-tok1-vpc1 ~]# curl http://192.168.50.223
This is an AIX server in Power Systems Virtaul Server
```

とします。VPC ALBのBackend poolにサーバーを追加する際に、`VPC devices`ではなく、`Other`というタブを選択し、Power Systems Virtual ServerのIPアドレスとポート番号を入力します。FQDNは指定できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/f7c1567b-64c9-a05a-5750-51c7330d890e.png)

サーバーが登録されてヘルスチェックが成功していれば以下のようになっているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/f552f11d-0bd9-cde0-e9c6-a9328ef16ebd.png)


# 3. テスト

（この結果を見ただけでは違いはわからないかもしれませんが）以下のパターンで実際にテストを実施。


```txt:VPC内部からのアクセステスト
VPC上のVSI -> ALB(Privateタイプ) -> (Direct Link) -> Power Systems Virtual Server

[root@new-syasuda-tok1-vpc1 ~]# curl http://xxxxxxxx-jp-tok.lb.appdomain.cloud
Hello! This is an AIX server in Power Systems Virtaul Server
```

```txt:on-premise(DirectLink経由)
on-premise上の端末 -> (Direct Link) -> ALB(Privateタイプ) -> (Direct Link) -> Power Systems Virtual Server

# curl http://xxxxxxxx-jp-tok.lb.appdomain.cloud
Hello! This is an AIX server in Power Systems Virtaul Server
```

```txt:インターネット経由
インターネット上の端末 -> ALB(Publicタイプ) -> (Direct Link) -> Power Systems Virtual Server

syasuda@ShinobunoMacBook ~ % curl http://yyyyyyyy-jp-tok.lb.appdomain.cloud:8080
Hello! This is an AIX server in Power Systems Virtaul Server
```
cscの作法 その81

# 概要
cscの作法、調べてみた。
プロセス一覧やってみた。

# 参考にしたページ

https://uchukamen.com/Programming1/ListView/index.htm


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c26d7ef6-495c-6e02-ac74-2521423d546d.png)

以上。
ROSについて学んだのでまとめてみた #1

# ROSとは何か
- 低階層のハードウェアと高階層のソフトウェアアプリをつなぐミドルウェア

- ROSの制限
    - 複数台向けに設計されていない
    - リアルタイム性がない
        - プロセスに優先度をつけるため特定の処理が遅れることがある
    - 信頼性の高いネットワークが必要

- ROS2への移行
    - ROS2はLinuxだけでなくWindows、Macでも使用可能
    - 複数台同時使用も対応
    - リアルタイム性の問題も解決
    - しかし世界での使用割合はROSが85%なのに対しROS2はまだ15%程度


# ROSのインストール
Ubuntu20.04へのインストールが推奨されていますが、18.04下でも問題なく動作しました。

## インストール方法
[インストールガイド](http://wiki.ros.org/noetic/Installation/Ubuntu)

以下、簡単にまとめます。

1. URLからのアクセスを許可
    ```
    sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros- 
    latest.list'
    ```

2. インストールキーを入手します。
    ```
    sudo apt install curl # if you haven't already installed curl
    curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
    ```

3. インストール（つけるオプションに選択肢があるようですが推奨されているもので良いです）

    ```
    sudo apt update
    sudo apt install ros-noetic-desktop-full
    ```

4. bashが通っているか確認

    ```
    source /opt/ros/noetic/setup.bash
    ```
通っていない場合

    ```
    echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
    source ~/.bashrc
    ```
cscの作法 その80

# 概要
cscの作法、調べてみた。
ドラッグアンドドロップやってみた。

# 参考にしたページ

https://maywork.net/computer/mediaplayer-playlist-prot/


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e5e26c82-3876-efc6-1612-377001743aa6.png)


# コンパイル手順


```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>csc lv0.cs


```

以上。
Azure AutomationでDSCを構成する

Azure Automation State Configuration(DSC)を利用すると、DSCサーバを用意することなくプルサーバ機能を用意することができます。

# 手順
1. Automationアカウントのデプロイ
1. VMのデプロイ
1. DSC構成ファイルのインポート
1. DSC構成のコンパイル
1. 管理対象ノードの追加
1. 結果の確認

# Automationアカウントのデプロイ
任意のパラメータでAutomationアカウントを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/5c49664f-ac70-bb1c-693c-0d2a3372500e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/bb822b1d-6d1a-e54e-6d01-215196c0e977.png)

# VMのデプロイ
DSC機能で構成する対象VMを作成しておきます。OSはWindows Serverを選択しておいた方が設定が楽です。

# DSCの追加
[構成]⇒[追加]からDSC構成用のファイルをインポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/a902924c-d7f3-7380-61ab-9f0e60bafe4c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/5440e612-3d4d-efaf-1f68-83852e9f8eae.png)

ここでインポートするファイルは下記のような宣言型のスクリプトです。
```powershell
Configuration SampleConfig {     
    Node "WebServer" {
        WindowsFeature IIS {
            Name = "Web-Server"
            Ensure = "Present"
        }
        WindowsFeature IISTools {
            Name = "Web-Mgmt-Tools"
            Ensure = "Present"
        }
        WindowsFeature xTelnet {
            Name = "Telnet-Client"
            Ensure = "Absent"
        }
    }
 
    Node "DNSServer" {
        WindowsFeature DNS {
            Name = "DNS"
            Ensure = "Present"
        }
        WindowsFeature DNSTools {
            Name = "RSAT-DNS-Server"
            Ensure = "Present"
        }
        WindowsFeature xTelnet {
            Name = "Telnet-Client"
            Ensure = "Absent"
        }
    }
}
```


# DSC構成のコンパイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/d473c6ea-7ce1-b53b-2669-075eb4250e73.png)
設定したConfigを元にプルサーバ上に展開する構成をコンパイルします。これにより各ノードがDSC構成を利用できるようになります。

# ノードの追加
[ノード]⇒[追加]から管理対象VMを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/36269b27-6367-3142-2ce8-1e876fa8a4d1.png)

# DSCが割り当てられていることの確認
時間がたつとDSC構成が反映されます。各ノードにレポートが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/8c7a72eb-9a5d-a39e-874b-9a74f95b687b.png)

NSGにて自宅環境のIPからのHTTPを許可するルールを追加してVMのパブリックIPにアクセスすると、確かに動いていることを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/d805b915-0e28-5d5b-aaf8-13a894e45866.png)
PHPにおけるDTOとはどうあるべきか？を今更考えてみた

今更ながらPHPにおけるモデル(DTO)とはどうあるべきか？を考えてみた。
(php8.0前提）

### 私の結論

まずは結論から。上司に怒られっからね！

```php
<?php
class Human {
    const NAME="name";      // DBのkey名
    const TEL="tel";        // DBのkey名
    private string $name;   // DB的にNOT NULLな項目
    private ?int $tel;      // DB的にNULL許容な項目
  
  private function __construct(){}
  
  /**
   * DBレコードからインスタンスを生成するメソッド
   **/
  public static function fromRow(array $row) :Human {
    $human = new Human();
    foreach ($row as $key => $value) {
        match($key) {
            self::NAME => $human->name = $row[self::NAME],
            self::TEL => $human->tel = $row[self::TEL],
        };
    }
    // $rowがSELECT * FROM human;で取得している可能性がある
    return $human;
  }
  
  public function getName() : string {
      return $this->name;
  }
  
  public function getTel() : ?int {
      return $this->tel;
  }
}

// 実際には「SELECT * FROM Human;」で取得したレコードを配列として食わせるけど、サンプルね！
$human = Human::fromRow(array(Human::NAME => 'taclose', Human::TEL => null));
echo "名前は？　".$human->getName()."\n";
echo "電話番号は？　".$human->getTel()."\n";
echo "\n";

// sample2:  SELECT name FROM Human; (連絡先一覧画面とか作りたい時かな）
$human = Human::fromRow(array(Human::NAME => 'taclose_2'));
echo "名前は？　".$human->getName()."\n";
echo "電話番号は？　".$human->getTel()."\n"; // 狙い通りFatal Errorが出る!!
            
```

### 解説・ポイント

#### __construct はprivateにする
データベースからレコードを持ってきてＤＴＯ生成するというパターンと、入力フォームから受け付けて生成するパターンが考えられるので複数のコンストラクタを実装出来ないPHPにとってはfromRowとかfromJsonとかそういうメソッド定義してあげて、constructはprivateにしちゃうのがかっこよさげ。

#### getterの型指定をしている
PHPって結構キャストや一度も代入されていない変数への参照に癖があり、verが上がる毎に見直しも入ったりと大変ですよね。
時代に沿ってgetterはmixed型ではなく、型指定を厳格に行う事でDTOを使う側の人間は安心して使えるようになり、余計なキャストやチェックで可読性を下げたり予期せぬ不具合を防止しています。

#### getterのdefault値は存在しない
SELECTされていない列の情報を参照しようとするとFatal Errorが発生するようにしています。
DB上でnullなのか空文字なのか0なのかわからないのに0だよ！とか返しちゃったら見つかりにくい不具合が増えるだけですからね！

あとはFatal Error発生しないでnull or 0 がデフォルト値で返るモードを用意してgetterで分岐っていう手もあるけど、これやりだすと毎回mode確認したりmode書き換えたりとかが出てきてDTOとしてはいかがなものかと思うわけでして。

以上！参考になるご意見もらえたら反映いたします！
KAGOYA KVMをスナップショットからリストアする方法を見つけた

# やりたいこと
KAGOYA KVMのインスタンスをスナップショットから復元（リストア）したい

# 状況
使用中のインスタンスは定期スナップショットを取得している
過去に取得したスナップショットまでインスタンスを戻したい

# 公式マニュアルに情報がない？

`「カゴヤ・ジャパン　＞　サポートセンター　＞　KVM」`
https://support.kagoya.jp/vps/manual/index.php?sid=2145624&lang=ja&action=show&cat=10

スナップショットからリストアしたいので、
`「カゴヤ・ジャパン　＞　サポートセンター　＞　KVM　＞イメージ　＞　スナップショット」`
とたどってみるが、
`スナップショットを保存する`
`スナップショットからインスタンスを作成する`
`スナップショットを削除する`
という項目しかなく、リストアする方法が掲載されていない

次に関係ありそうな
`「カゴヤ・ジャパン　＞　サポートセンター　＞　KVM　＞インスタンス」`
を見るが、
`インスタンス作成(Linux OS)`
`起動`
`再起動`
`停止`
`初期化`
`インスタンス削除`
`スペックの変更`
`コンソール`
`スワップ領域の設定`
どれも探している情報ではない

新たにインスタンスを作成したいわけではない
初期化したら消えてしまう
削除したいわけでもない

# 問い合わせた
サポートセンターに問い合わせた

数日後に返ってきた返信が、

「インスタンスを「初期化」することで、既存インスタンスをスナップショットからリストアいただくことが可能です。
◇インスタンス > 初期化
　https://support.kagoya.jp/vps/manual/index.php?action=artikel&cat=16&id=59&artlang=ja」

だそうです。

# スナップショットから復元する方法

### スナップショットの確認
コントロールパネルでログイン

トップ　→ イメージ　→ スナップショット

スナップショット一覧から復元したいスナップショットを確認

### 復元作業

トップ　→ KVM → インスタンス一覧

復元したいインスタンスをクリック
→ インスタンス情報

`停止`クリック

ステータスが「停止」になるのを確認

`初期化`クリック
項目を入力
「スナップショット」
「復元したい時刻のスナップショット」
「ログイン用認証キー」設定データよりコピペ
「virtio」復元するスナップショットが対応しているならON、対応していないならOFF
「コンソールログインパスワード」設定データよりコピペ
「ユーザーデータ」特になし
`初期化`クリック

ステータスが「初期化中」になったら待機

ステータスが「稼働」になったら終了

### ブラウザで確認

# 感想


普通、「初期化」というと「工場出荷状態に戻す」ことを意味するので、復元したい場合にヘルプの初期化を探したりしない
これではたどりつけないです…

まあ、わかってよかった。としよう
[WordPress][Nginx] パスワード付き記事に対応しつつ WordPress 管理画面にBASIC認証を設定する

WordPress 管理画面に BASIC 認証を設定するときは、以下のように設定していました。
( PHP は http://backend で動いているプロセスにリバースプロキシしているものとします )

```
    location = /wp-login.php {
        # BASIC 認証
        auth_basic    "Secret Area";
        auth_basic_user_file  "/etc/nginx/conf.d/.htpasswd";

        proxy_no_cache     1;
        proxy_cache_bypass 1;
        proxy_redirect     off;
        proxy_pass http://backend;
    }

    location ~* /wp-admin/(?!(admin\-ajax\.php|css/|js/|images/)).*$ {
        index index.php index.html index.htm;

        # BASIC 認証
        auth_basic    "Secret Area";
        auth_basic_user_file  "/etc/nginx/conf.d/.htpasswd";

        proxy_no_cache     1;
        proxy_cache_bypass 1;
        proxy_redirect     off;
        proxy_pass http://backend;
    }
```

ただ、これだと WordPress でパスワード保護された記事を書いた時にも BASIC 認証のダイアログが表示されてしまいます。

パスワード保護された記事を開くためには、WordPress では `/wp-login.php?action=postpass` に対して POST します。
そのため `/wp-login.php` に BASIC 認証がかかっていると、パスワード保護された記事を表示することができなくなってしまうのです。

そこで、以下のように変更し、 クエリストリングに `?action=postpass` があるときは BASIC 認証を無効にするように設定しました。

```
    location = /wp-login.php {
        # BASIC 認証
        set $auth "Secret Area";
        if ( $arg_action = "postpass" ) {
        	set $auth off;
        }
        auth_basic    $auth;
        auth_basic_user_file  "/etc/nginx/conf.d/.htpasswd";

        proxy_no_cache     1;
        proxy_cache_bypass 1;
        proxy_redirect     off;
        proxy_pass http://backend;
    }
```

参考URL: [wp-login.phpにベーシック認証をかけつつ「パスワード保護」を利用する](https://autumnsky.blog/2020/06/wp-login-with-basic-auth-htaccess/)
iTerm2のおすすめ設定　ホスト名をハイライトしてミスを防ぐ

Macのターミナルとして、iTerm2を愛用しています。中でも特定のキーワードに対して文字・背景色を変更する機能がとても重宝しています。

# はじめに
サーバ開発に携わっていると、開発環境、本番環境、さらには検証環境など、複数の環境で開発している場合があります。ターミナルから開発環境にsshしていたつもりが、実は商用環境で、マズい設定を実行してしまった、ギリギリ気づいた、みたいな経験ないでしょうか。iTerm2の設定で、そのリスクを減らそうと思います。

## 環境
Mac Catalina
iTerm2 Build 3.4.8

# iTerm2のTriggersでハイライトする
iTerm2では、設定により特定の文字列をハイライトすることができます。例えば、商用環境のホスト名には赤、開発環境のホスト名には青、などにハイライトします。色によって視覚に訴えることで、ミスを防ぎます。

## 設定手順
1. メニューバーからProfiles > Open Profilesを開く
2. Profileを選択して、Edit Profilesをクリックする
3. Advancedタブを選択し、TriggersをEditする
![スクリーンショット 2022-03-28 19.11.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/6f1d0bde-d0e6-6775-2b99-715d93056c88.png)
4. ＋を選択し「Regular Expression」にハイライトしたい文字列を入力、「Action」はHighlight Textを選択、「Parameters」に好きな文字色と背景色を選択し、「Instant」のチェックボックスはチェックしておく
![スクリーンショット 2022-03-29 10.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/c8eb3d25-a5be-dfa1-165c-00a67a0e17ad.png)

これで設定完了。
以降、ターミナルでこの文字列に一致した場合、ハイライトされるようになります。

:::note warn
Instantをチェックしないとリアルタイムにハイライトされないので注意。
:::

## 正規表現を使う
「Regular Expression」と言うくらいなので正規表現が使えます。例えば、サーバ名のルールが下記のような形式と仮定します。
* XXX-prd-front-a001
* XXX-dev-backend-c002

この場合、「Regular Expression」は、このように設定しておけば、良いと思います。
* XXX-prd-\D*-\D\d\d\d
* XXX-dev-\D*-\D\d\d\d

正規表現のルールは、[これに沿っている](https://unicode-org.github.io/icu/userguide/strings/regexp.html)ようなので参考です。
(?i)は、大文字小文字の区別なしの意味です。ERRORもerrorもハイライトしたい場合に使えます。

:::note
Triggerとなる文字列には正規表現が使える。
:::

# まとめ
ホスト名の他にも、「root」にハイライトしてrootユーザーであることや、「ERROR」「FAIL」にハイライトしてログを見やすくするなど、色々と捗るので、最適な設定をしてみて下さい。良いアイデアがあればぜひ教えて欲しいです。
styled-componentsでReactコンポーネントを継承したスタイル拡張

## 概要
タイトルの通り、styled-componentsを使ってReactコンポーネント（styledされていないものも含む）を継承してスタイルを拡張させる方法のメモです。

## 通常のstyled-componentを継承したスタイル拡張
まず、別のstyled-componentのスタイルを継承した新しいコンポーネントを作成する方法を見ていきます。

### 方法
継承させたいもとのコンポーネント名を`styled()`コンストラクタ内に書くだけ。

テンプレートリテラル` `` `内に拡張したいスタイルを書くと、追記したスタイルが継承もとのコンポーネントのスタイルに拡張されます。

👇公式のDEMOが分かりやすいのでどうぞ
https://styled-components.com/docs/basics#extending-styles

## （本題）Reactコンポーネントを継承したスタイル拡張
では、普通のReactのコンポーネント（styledされていないものも含む）を継承したいときはどうでしょう？

### 方法
この場合は、継承させたいもとのコンポーネントにpropsとして`className`を渡す必要があります。

👇検証DEMO
https://codesandbox.io/s/sweet-brattain-9be06u?file=/src/App.tsx

こちらのDEMOで試してみてもらうと分かりますが、
`ButtonBlue.tsx`から className の記述を削除すると、`ButtonRed`コンポーネントは赤ではなく青いままになります。

### 公式ドキュメント
styled-components、Emotionそれぞれの公式ドキュメントにもそのようなことが書かれています。

[styled-components](https://styled-components.com/docs/basics#styling-any-component)
>The styled method works perfectly on all of your own or any third-party component, as long as they attach the passed className prop to a DOM element.

[Emotion](https://emotion.sh/docs/styled#styling-any-component)

>`styled` can style any component as long as it accepts a `className` prop.

## （余談）コンポーネント呼び出し時のclassNameの指定を回避したい（TypeScriptを使用している場合）
classNameを渡せばよいのは分かったものの、コンポーネントを呼び出す際に毎度classNameを指定するのはなんか嫌だなぁ...という時の回避方法を考えました。
（わたしの場合は指定していないと「classNameがない！」と怒られました）

**※おことわり※**
ここで紹介するのは苦肉の策？のような感じなので、もっと良い方法あれば是非教えていただきたいです！

### classNameをオプショナルプロパティとする
コンポーネントに渡すpropsの型定義をする際に、classNameはオプショナルプロパティとして定義してあげます。

```ButtonBlue.tsx
type ButtonProps = {
  children: ReactNode;
  className?: string;  // オプショナルプロパティとして定義
};

export const ButtonBlue: React.VFC<ButtonProps> = ({ children, className }) => {
  return (
    <Button className={className}>
      <a href="https://relic.co.jp">{children}</a>
    </Button>
  );
};
```

これで、コンポーネントを呼び出す際は特にclassNameを渡さなくても怒られずに済みます。

```App.tsx
import { ButtonBlue } from "./ButtonBlue";
import { ButtonRed } from "./ButtonRed";

export default function App() {
  return (
    <div className="App">
      <ButtonBlue>ボタン1</ButtonBlue>
      <ButtonRed>ボタン2</ButtonRed>
    </div>
  );
}
```

## 参考
* https://styled-components.com/docs/basics#styling-any-component
* https://emotion.sh/docs/styled#styling-any-component
* https://open8tech.hatenablog.com/entry/2019/01/25/113916