OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder ABC 247E - Max Min : 一方を固定して条件を満たす範囲の探索 O(NlogN)解

https://atcoder.jp/contests/abc247/tasks/abc247_e

# この解法は？
https://atcoder.jp/contests/abc247/editorial/3736
の最後にある$O(NlogN)$の解法です。

# 前処理
解説の前半(Bを求めること)と同じです。

例えば、A=$[10, 3,2,4,3,4,3,2,1, 3, 6, 2,4, 4]$という入力があり、$X=4, Y=2$だったとすると、2未満、5を超過する数でこの配列を分割し、$[3,2,4,3,4,3,2,1]$と$[3]$と$[2,4,4]$を得ます。それぞれの配列に対して、問題と同じ組み合わせの数を求めてその和が最終的な答えとなります。(ある区間が分割する対象の数というのはその数を含んだ瞬間にそれ以上の条件を満たす区間が作れなくなるためです)

補足：この発想は次の処理を簡単にするために非常に有効なので、「次の処理を思い浮かんだからこの前処理をしたのか？」と思われるかもしれませんが私はこの問題を読んだときに、分割できるな。と思い分割しました。
明らかに一般性を失わずに入力を分割できる場合、実装を簡単にできる(例えばindexの調整や境界の配慮をしなくていい)ため、明確であればこのように分割を行うことは適切です。


# 各区間内の処理
今、$[3,2,4,3,4,3,2,1]$に対する組み合わせの数を考えます。この入力に対してすべての条件を満たすindexの対$(L,R)$をすべて求めたいですが、2重ループではこの長さNに対して時間計算量$O(N^2)$となってしまいます。

$L$を固定することを考えます。
- Lを含めて右にある最初のX及びYの位置を`ix`, `iy`とします。(含めて、なので、`iX`=Lや`iy`=Lになることもあります)
- ixとiyが片方でも見つからない場合、Lを固定した範囲は存在しません。なぜなら、(XかYがLより後に含まれないkからです)
- 両者のmaxよりも後のRはすべて条件を満たします。なぜなら、すでにXもYも含まれており、前処理によってX未満、Yより大きい数は排除されているため、この区間内の最後まで条件を満たせることは明らかです。

これを例に示します。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/0d8ac5fd-f144-c916-6d90-5d922fc33921.png width=70%>
- L = 0と固定します(緑字)。最も近いXであるindex ix=2, Yであるindex iy=1であるため、max(ix,iy) = 2です。このため、(L,R) = (0,2)は条件を満たし、それ以降のRも条件を満たします。つまり、(0,2)...(0,6)の5通りが考えられます。
    - 先の繰り返しになりますが、(0,2)の区間ですでにX,Yの最大・最小の条件は満たせており、この区間には最大・最小を変化させる値は(前処理をしたので)ありません。
- L = 3の時(青字)を考えます。この時、ix, iy = 4, 6です。(L,R) = (4,6)は条件を満たし、Rはこれ以上の値をとれないので、L=3の時は(3,6)のみのただ1通りとなります。
    - これよりも前のRを考えると例えば(3,5)では、最小値が3となり、条件を満たせません。
- L = 5(紺色)を考えます。この時、ixが見つかりません。(L=5以降にX=4は存在しません)。このため、条件を満たすような(L,R)=(5,k)は存在しません。

# 実装方針と計算量の検討
前処理について、入力された配列を見ていきYからXの範囲を超える値でsplitすればよいです。

前処理の後の各区間の処理は、最初にすべての要素を$O(N)$で操作し、X, Yと一致するindexをリストの形で持ちます。各Lに対してそれぞれのリストを二分探索してやれば$O(logN)$でそれぞれixとiyが求められます。各LはN個であるので、$O(NlogN)$です。

# 実装

前処理はよくある配列の分割を行います。

前処理は上記の実装方針の通りに行います。lower_bound(bisect_left)で結果が見つからなかった時の処理に気を付けます。

<details><summary>実装(Python)</summary><div>

```Python
from bisect import bisect_left
n, x, y = map(int, input().split())
dat = list(map(int, input().split()))
buf = []
q = []
# 入力の配列を、min未満, max超過の数字でsplitする
for val in dat:
    if y <= val <= x:
        q.append(val)
        continue
    if len(q) > 0: buf.append(q)
    q = []
if len(q) > 0: buf.append(q)
# 各分割について数を計算する
ans = 0
for dat in buf:
    milist = []  # minのindex list
    malist = []  # maxのindex list
    for i in range(len(dat)): # を作る
        if dat[i] == y: milist.append(i)
        if dat[i] == x: malist.append(i)
    for l in range(len(dat)):  # lを固定して満たせるrを探索
        r = bisect_left(malist, l) # index=l以上のxのindex見つける
        if len(malist) <= r: continue # xが見つからない時は無理
        a = malist[r]
        r = bisect_left(milist, l) # index=l以上のyのindex見つける
        if len(milist) <= r: continue # yが見つからないときは無理
        b = milist[r]
        r = max(a, b) # xかyの見つかったindexの大きい方
        ans += len(dat) - r #それ以上は全部良いRなので組み合わせの数としてadd
print(ans)

```
</div></details>

https://atcoder.jp/contests/abc247/submissions/30915794
Can't connect to MySQL server エラーの解消

mac上で、pythonを利用してmysqlにデータを書き込もうとしたところ、下記エラーが発生しました。

```
mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'localhost:3306' (61 Connection refused)
```

実行したファイルは、下記になります。

```update_sql_from_csv.py
### インポート
import csv
import mysql.connector
 
### ファイルオープン
file = open("bme280_db.csv", "r")
 
### ファイル読み込み
members = csv.reader(file)
 
### DB接続
cnx = mysql.connector.connect(host='localhost', user='root', password='', database='bme280db')
 
### カーソル作成
cursor = cnx.cursor()
 
### INSERT文作成
sql = "INSERT INTO weather_forecast ( date_time, pressure, temperature, humidity) VALUES (%s, %s, %s, %s)"
 
### データ挿入
data_count = 0
for value in members:
        if not data_count == 0:
        ### データ挿入実行
            cursor.execute(sql, value)
        data_count += 1

### コミット
cnx.commit()
 
### カーソルクローズ
cursor.close()
 
### DB切断
cnx.close()
 
### ファイルクローズ
file.close()
```

# 環境
環境は、下記の通り。MANPを利用し、サーバーは、起動済みです。
OS: macOS Catalina version 10.15.7
デバイス : MacBook Pro (Retina, 13-inch, Early 2013)
PHP version: 8.0.8

# 原因調査
[こちら](https://casualdevelopers.com/tech-tips/how-to-fix-2003-error-when-connecting-to-mysql-server/)の記事を参考に、ひとつづ原因を潰していきました。

## MySQLのポート番号
MySQLのデフォルトのポートは、3306。こちらが正しいかどうか調べてみました。

```
mysql> show variables like 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port          | 8889  |
+---------------+-------+
1 row in set (0.01 sec)
```

違っていました。pythonのファイルの一部を下記のようにportを指定するように変更し、再度実行すると、エラーは解消しました。
cnx = mysql.connector.connect(host='localhost', <font color="Blue">port='8889',</font> user='root', password='', database='bme280db')
ATtiny84にArduinoを使って書込してみた 

今回は、ATtiny84に書込をしてみたのでそれの記録。
意外とATtiny84に書込をした記述は少ない！
なんで？！

# 配線
![スクリーンショット 2022-04-04 22.30.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/3f75f9a5-9261-e637-be22-d21af23013b3.png)

![スクリーンショット 2022-04-04 22.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/376364e5-58fc-ca1e-2cb4-2c5400081c1f.png)

# 書込設定

### 1、まずはArduino unoに「ArduinoISP」を書き込む。
  ファイル＞スケッチ例＞11.ArduinoISP＞ArduinoISPを選択し、マイコンボードに書き込むボタンをクリック。
![スクリーンショット 2022-04-11 22.32.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/a03ebc6d-6cd4-b815-f0f9-77ad564f50b0.png)


### 2、ボード環境の構築
Arduino＞Prefrencesをクリックして、追加のボードマネージャのURLに以下を追加。
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

![スクリーンショット 2022-04-11 22.36.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/fa58abbd-7490-00ea-9eb8-55fa953c2824.png)

### 3、ブートローダの書込
以下の画像の設定で、「ブートローダを書き込む」をクリック。
![スクリーンショット 2022-04-11 22.40.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/9e46b553-bb25-05d7-baea-a327c4ae4f75.png)

### 4、Lチカのサンプルプログラム書込
```c
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(7, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(7, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}
```

### 5、サンプル用の配線
電池で動作する配線接続を行いました。
![スクリーンショット 2022-04-11 22.47.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/9924b838-ccd9-4052-1d4b-2c71e9340733.png)



# 注意点
ATtiny84のピン番号は少し変わっていますのでその点だけ要注意です。
ピン番号は以下のサイトを参考にして下さい。
https://create.arduino.cc/projecthub/Arnov_Sharma_makes/programming-attiny84-088482

#### ATtinyを使った開発依頼お待ちしております〜＾＾
DockerとVScodeの接続方法

VScodeでDockerの環境を開きたい場合があったので、共有できたらと思います。手順は大きく3つありますが、VScodeとDockerの環境構築ができている方は、5分もかからずに完了すると思います。

## 手順1：拡張機能「Remote-Containers」をインストール
VScodeの拡張機能検索欄から、「Remote-Containers」をインストールします。
![拡張機能_ Remote - Containers - Visual Studio Code 2022_04_11 22_34_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607750/2be03ab6-6d5b-8528-f41e-353d63c12ca2.png)

## 手順2：Dockerを起動
「Remote-Containers」をインストール後、Dockerを起動し、VScodeと接続したいコンテナを開きます。

## 手順3：VScodeとDockerを接続
コンテナを起動後、VScodeの左下の緑のマークをクリックします。そしたら、「Attach to Running Container」をクリックします。
![Qiita - Google Chrome 2022_04_11 22_36_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607750/69d70fb0-84d3-ab74-41ec-5ef304b211cb.png)

そうしたら、先ほど起動したコンテナ名が表示され、そこをクリックすることで接続することができます。


以上が、DockerとVScodeの接続方法となります。
.pyファイルからexeファイル化の方法とNo moduleエラーについて

## 初めに
pythonを使って業務効率改善できそうなプログラムを作ったはいいけど、全くプログラミングの素養のない人にどうやって使ってもらえばいいのか…

方法としてはいくつか考えられるが、exeファイル化というものが一番簡単そうだったので、その手順のまとめと、躓いたところについて記載する。
（注：初心者なので、間違いなどあるかもしれません。また、間違いなどあればご指摘頂ければ幸いです。）

## exeファイル化概要
簡潔に述べると、下記コマンドを実行するだけ。
```
pyinstaller test.py --onefile
```
細かい手順については、こちらに関しては下記サイトに簡潔にまとまっているので、こちらを参照頂いた方が良いと思われます。
[【自動化】pythonコードをexeファイル化する](https://qiita.com/konitech913/items/6259f13e057bc25ebc23)

## 躓いたところ
exeファイル化までは問題なく実施できたが、実行してみたところ、下記のエラーが発生した。
```
moduleNotFoundError: No module named 'sklearn.utils._typedefs'
```
色々と確認したところ、下記サイトに解決策が記載されていた。
https://localcoder.org/pyinstaller-modulenotfounderror-no-module-named-sklearn-utils-cython-blas

要は足りないモジュールを追加で入れ込めば何とか解決できる模様。
幾つか方法があるようだが、自分の作成したコードに直接importする方法が分かりやすかったので、こちらを採用し、無事に実行できた。  

具体的には
```
import sklearn.utils._typedefs
```
を1行目に足すだけ。
確認はできていないが他のモジュールに関しても同様に対応可能だと思われる。
No module系のエラーは多いようなので、自分の備忘録を兼ねて記録しておきます。

余談ですが、exeファイルを実行した際に、コマンドプロンプトがすぐに消えてエラーが確認できない場合は、exeファイル化する際に下記のように--debug allをつけると、実行ログが出力されて確認できるようになります。
```
pyinstaller test.py --onefile --debug all
```
## その他参考サイト
・https://qiita.com/fault/items/030616a85c91ebe04296
 ジュピターノートブックのファイル（.ipynb）から.pyファイルへの変換について
・https://www.wantanblog.com/entry/2022/01/21/205628
　pyinstallerのエラーについて。importの明示が必要らしい…
Re: Rを用いた複数回答可能なアンケートのクロス集計

https://qiita.com/NEM_Harvest/items/b1ee886a2598f9008b14

base-R で書いてみる

```R
> sapply(3:7, function(k) by(rawdata[, k], rawdata[, 2], sum))
     [,1] [,2] [,3] [,4] [,5]
1.男    2    1    2    1    0
2.女    1    0    0    1    1
```

項目が数百あっても

```R
  summarise(`q1-1` = sum(`q1-1`, na.rm = TRUE),　
            `q1-2` = sum(`q1-2`, na.rm = TRUE),...
```

って書き続けるのか？耐え難い。
PHPで乱数の生成

<h1>PHPで乱数の生成の備忘録</h1>
<p>PHPで乱数を生成する必要があったので自分用にまとめです。<br>mt_rand()で生成できることはなんとなく知っていたので調べてみました。<br>自分用なので簡単にまとめます。</p>
<h2>mt_rand()じゃなくてrandom_int()</h2>
<p>調べているとmt_rand()よりrandom_int()の方がセキュリティが高いらしいのでrandom_int()を使っていきます。<br></p>

```php
$number = random_int(0, 2); //0から2の間の数で乱数生成し$numberに格納
echo $number; //0から2の値のどれかが入っている$numberを出力
```

<h3>最後に</h3>
<p>簡単でしたね。これからも勉強内容を忘れないためにqiitaに残していきたいと思います。</p>
sam local start-api で hot reload されない

## 環境
```
OS: Windows10 Home
SAM Version: 1.43.0
```

## 現象

`sam local start-api` で API Geteway のローカルインスタンスを起動後、`app.py`を修正してもホットリロードされない。

```
PS C:\xxxx> sam local start-api                                   
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello1 [GET]
Mounting HelloEfsFunction at http://127.0.0.1:3000/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
```

厳密にいうと、`sam build`しなおさないとホットリロードされない。  
調べると「そういうもんだ」って言ってる人が多く、当たり前の話なのかもしれないし、環境構築がミスってるのかもしれないが、仕方ないのでPowerShellでファイルの変更をトリガーに`sam build`やっちゃう。
:warning: 私はsamもdockerも勉強し始めたてなので、何いってんだ・・・？というレベルの内容でしたらすみません。


## PowerShell

```powershell
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = "C:\xxxx"
    $watcher.Filter = "*.*"
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true  

    $action = { sam build -t ./xxxx/template.yaml }    

    Register-ObjectEvent $watcher "Created" -Action $action
    Register-ObjectEvent $watcher "Changed" -Action $action
    Register-ObjectEvent $watcher "Deleted" -Action $action
    Register-ObjectEvent $watcher "Renamed" -Action $action
    while ($true) {sleep 5}
```

`$watcher.Path = "C:\xxxx"` ここにファイルの変更を監視する対象ディレクトリのパスを入れる。
`$action = { sam build -t ./xxxx/template.yaml } ` ここにはps1ファイルからtemplate.yamlへの相対パスを入れる。

### 参考元
https://superuser.com/questions/226828/how-to-monitor-a-folder-and-trigger-a-command-line-action-when-a-file-is-created

## おわり
もっと、根本的な改善方法があれば教えてください・・・！
【メモ】Laravel開発環境の必要物を学ぶ

web系のサーバーサイドエンジニアを目指す奴のメモ書きです。

Laravelの開発環境を構築をしたいので何が必要かを調べる。

開発環境構築ので必要なのは
・XAMPPインストール
・Composerインストール→Laravelインストール

# XAMPPとは
XAMPPは頭文字をとってる。
「X」：様々なOSに対応する「クラスプラットフォーム」を意味する「X」を使用
「A」：Webサーバソフトウェアの「Apache」の頭文字を使用
「M」：データベース管理システムの「Maria DB」の頭文字を使用
「P」：アプリ開発で多く使われるプログラミング言語の「PHP」の頭文字を使用
「P」：アプリ開発で多く使われるプログラミング言語の「Perl」の頭文字を使用

### XAMPPのメリット
PHP開発環境構築 = XAMPP これが過言ではない
WebサーバーやDB、PHPを個別にインストールしなくてもXAMPPをインストールすればすべてそろうので超らくちん。XAMPPだけあれば開発できる。さらに便利にしたい場合、これに加えてLaravelとかのフレームワークをインストールする。
Webサーバーは別のがいい！とかDBはやっぱOracleでしょみたいなこだわりがある場合は、それらを個別でインストールすればよし。

### XAMPPの注意点
自分で最新のXAMPPに変更しないうちはずっとインストールしたときのままなのでXAMPPに入っているソフトウェアのバージョンが古いままになってしまう。なので久しぶりに触るときとかは注意。
これを機に各バージョンを意識してみようと思う。
あとは便利な反面、何が動いてるのかとか設定値とか分からないまま触るのは、いざ本番で環境構築するときに詰むのでそこだけは念頭に。

### XAMPPのインストール方法
公式サイトからインストーラーをダウンロード(バージョン意識！)
https://www.apachefriends.org/jp/index.html
インストーラーはウィザード形式
詳細は環境構築を実施するときにメモ。

# Composerとは
PHPのパッケージ管理ツール。開発でライブラリやフレームワークを使わないということはまずないはず。
ライブラリやフレームワークは開発を楽にする為のもの。でもライブラリやフレームワークを開発するときも楽したいからまたライブラリを使っていたりする。これが依存関係。
パッケージ管理ツールを使えばライブラリの依存関係を把握して必要なものをまとめて用意してくれる。
もしパッケージ管理ツールがなかったらあちこちに散らばるライブラリを集める摩訶不思議アドベンチャーが始まる。

### Composerのインストール方法
これも公式サイトからインストーラーをダウンロード
https://getcomposer.org/download/
インストーラーはウィザード形式
詳細は環境構築を実施するときにメモ。

# Laravelとは
未調査分はあるけど大体調査済み
https://qiita.com/4U5zo/items/9b724c9462e8ca488edc

### Laravelのインストール方法
LaravelはComposerでパッケージ管理されている状態でインストールしたいので先にComposerのインストールを実施する。
ComposerをインストールしたらコマンドプロンプトでComposerのコマンドでLaravelをインストールする。(バージョン意識！)
コマンドを実施するだけでインストール完了。
詳細は環境構築を実施するときにメモ。


参考資料
https://chigusa-web.com/blog/laravel-setup/2/
https://hnavi.co.jp/knowledge/blog/xampp/
https://weblabo.oscasierra.net/php-composer-1/
https://blog.senseshare.jp/laravel-install.html
【Stimulus】Stimulusをクリックした要素を取得する方法

# はじめに

Rails7 でデフォルトでインストールされるようになった Stimulus でクリックした要素を取得する方法を忘備録として残しておきます。

## 環境

Rails 7.0.2
Ruby 3.1.1
Stimulus-rails 1.0.4

# 取得方法

ボタンが４つあり特定のボタンをクリックした時だけ、アクションを発動させる時、通常なら`data-target`を利用することで javascript 側で要素を取得できます。
ですが、それが使えないときは`Stimulus`のメソッドの引数を利用することで取得できます。

## html

```html: button.html
<div data-controller='button'>
  <button id='1' data-action='click->button#next'>
    1
  </button>
  <button id='2' data-action='click->button#next'>
    2
  </button>
  <button id='3' data-action='click->button#next'>
    3
  </button>
  <button id='4' data-action='click->button#next'>
    4
  </button>
</div>

```

## javascript

メソッドの引数の`currentTarget`にクリックした要素が入っています。

```javascript:button_controller.js
import { Controller} from '@hotwired/stimulus';

export default class extends Controller {

  next(event) {
    const button_id = event.currentTarget.id;
    if (button_id == 1) {
      console.log(button_id)
    }
  }
}

```

# 参考

やっぱり困った時は、公式サイトのリファレンスを見るのが一番です。

[公式サイト](https://stimulus.hotwired.dev/reference/actions)
Ruby-Graphviz でサブグラフを描く

# ゴール
[Ruby-Graphviz](https://github.com/glejeune/Ruby-Graphviz) で[サブグラフ](https://graphviz.org/Gallery/directed/cluster.html) を描きたい

# まずは、dot 言語で書いてみる
[Graphviz 解説記事](https://qiita.com/rubytomato@github/items/51779135bc4b77c8c20d#%E3%82%B5%E3%83%96%E3%82%B0%E3%83%A9%E3%83%95%E3%81%AE%E5%AE%9A%E7%BE%A9)を参考にして

```dot
digraph node_sample {
...
  subgraph cluster_1 {
    label = "clu1";
    labelloc = "t";
    labeljust = "l";
    fillcolor = "#888888";

    nu [label = "nu", shape = "trapezium"];
    xi [label = "xi", shape = "trapezium"];

    nu -> xi;

    subgraph cluster_2 {
      label = "clu2";
      labelloc = "t";
      labeljust = "l";
      fillcolor = "#888888";

      nu2 [label = "nu2", shape = "trapezium"];
      xi2 [label = "xi2", shape = "trapezium"];

      nu2 -> xi2;

     subgraph cluster_3 {
        label = "clu3";
        labelloc = "t";
        labeljust = "l";
        fillcolor = "#888888";

        nu3 [label = "nu3", shape = "trapezium"];
        xi3 [label = "xi3", shape = "trapezium"];

        nu3 -> xi3;
      }
    }

    nu -> nu2
  }
}
```

`dot -T png sample.dot -o sample.png` して `open sample.png` すると

![20220325153803.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627625/33041b37-3d92-f851-a514-1a6eb00ef4e2.png)

# 次に、Gem で書いてみる
```ruby
require 'ruby-graphviz'

# Create a new graph
g = GraphViz::new(:G, type: :digraph, use: :dot, rotate: 0, rankdir: :LR)

# setting sub-graph
g.add_graph('cluster_1', label: "clu1", labelloc: "t", labeljust: "l", fillcolor: "#888888")
sub1 = g.get_graph('cluster_1')
hello1 = sub1.add_nodes( "Hello1" )
world1 = sub1.add_nodes( "World1" )
sub1.add_edges( hello1, world1 )

sub1.add_graph('cluster_2', label: "clu2", labelloc: "t", labeljust: "l", fillcolor: "#888888")
sub2 = sub1.get_graph('cluster_2')
hello2 = sub2.add_nodes( "Hello2" )
world2 = sub2.add_nodes( "World2" )
sub2.add_edges( hello2, world2 )

sub1.add_edges( hello1, world2 )

# Generate output image
g.output( :png => "./tmp/hello_world.png" )
```
ポイントとしては、[add_graph](https://rdoc.info/github/glejeune/Ruby-Graphviz/GraphViz#add_graph-instance_method) を使う際、第一引数として渡すグラフ名を `cluster` から始まる文字列にすること（そうしないとサブグラフとして機能しない）

![20220325154111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627625/58004593-06c3-d2a0-de0a-e1af59f9ea47.png)
Unity バージョンの選び方

##0.0　はじめに
Unityはダウンロードできるバージョンがたくさんあります。
いざ使い始めようと思ったけどどのバージョンを使えばよいか分からない、という時に参考になる記事です。

##1.0　バージョン
バージョンとはUnity2018.4のようにUnityの隣に付いている数字、2018.4の部分です。2018の部分は基本的にリリースされた年を表しています。
その隣の.4はバージョンの通し番号です。2018.4の次は2018.5です（リリースされていればですが）。.4の後ろにも.14のように数字が付いています。これはマイナーチェンジ（小規模変更）の通し番号です。その後ろにアルファベットのa（社内試作用）とかb（市場試作用）とかf（LTS）とかが付いています。

**バージョンの例：**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352037/a41c882b-7a61-143f-214d-4cc36538be42.png)


##2.0　LTS
UnityにはLTSと呼ばれるバージョンがありますが、これはLong Term Support(ロング・ターム・サポート)の略で、Unityが2年間の長期サポートを付けています。Unityエディタで何か問題があったとしても、この期間内はアップデートが行われるのでそれが解消される可能性が高いです。完成品なので最新とはいきませんが完成された機能を使うことができます。バージョンの最後にf（f1）が付いています。

##3.0　バージョンの選び方
さてバージョンの選び方ですが、単純にゲームをリリースするならサポートが付いているLTSのバージョンを選びましょう。最新の機能を使いたいのであればその機能が追加されたバージョンを使いながら、もしゲームをリリースするのであればその機能を網羅したLTSを選択することがおすすめです。
Braveはフォントを取得できないようにした。いっぽうChromeはフォントを根刮ぎ取得しようとしている。

JavaScriptから、現在[表示されている](https://qiita.com/life5618/items/3c86c136ed5afd848981)[フォントを取得する](https://s8a.jp/javascript-is-installed-font)[ことが可能です](https://webutubutu.com/webdesign/4369)。

仕組みを簡単に説明すると、フォントによって文字の横幅は異なるので、`font-family`を変えてみて`width`が変わったらそのフォントがインストールされている、みたいな識別方法です。

つまり、フォントを表示させて、そのフォントが入っているかどうかをチェックすることで、ブラウザフィンガープリントになります。

# Braveはフォントを取得できないようにした

[How Brave defends against font fingerprinting](https://brave.com/privacy-updates/17-language-fingerprinting/#how-brave-defends-against-font-fingerprinting)の記事において、Braveはフォントによるフィンガープリント防止について解説しています。

# How Brave defends against font fingerprinting

フォントは3種類に分類することができます。

## Web Fonts

Webサイトが提供し、そのWebサイトで使用するフォント。
ユーザから来たものではないので、フィンガープリントとしては使用できません。

## OS Fonts

OSによってインストールされるフォント。
トラッカーは既にユーザエージェントからOSを知っているので、このフォントが取得されたとしてもプライバシーに影響することは基本的にありません。

## User Fonts

ユーザがWebサイトからダウンロードしてインストールしたり、Officeスイート・その他のソフトウェア等がインストールするフォント。
これらはフィンガープリントとして有効です。

現在、BraveはAndroid、macOS、Windowsにおいて、フォントフィンガープリントプロテクトを適用しています。
iOS版に適用していない理由は、プラットフォームの制限によりできないこと、および[WKWebView](https://developer.apple.com/documentation/webkit/wkwebview)が、Braveほど厳格ではないもののある程度のプロテクトを行っていることです。
Linux版に適用していない理由は、ディストリビューションによってOSフォントが全く異なるため、どれがOSフォントであるか識別することが困難だからです。


# いっぽうChromeはフォントを根刮ぎ取得しようとしている

このようにBraveがプライバシー保護に努める一方で、Googleは例によって[Local Font Access API](https://wicg.github.io/local-font-access/)というトンデモAPIを提案しています。


# Local Font Access API

```js
const array = await self.queryLocalFonts();

array.forEach(font => {
  console.log(font.postscriptName);
  console.log(` full name: ${font.fullName}`);
  console.log(` family: ${font.family}`);
  console.log(` style: ${font.style}`);
});
```

たったこれだけで、PCにインストールされている全てのフォントを根刮ぎ奪われます。


## [Permissions Integration](https://wicg.github.io/local-font-access/#permissions-integration)

Local Font Access APIの使用にはパーミッションが必要です。

```js
const status = await navigator.permissions.queryLocalFonts({ name: "local-fonts" });
if (status.state === "granted")
  console.log("permission was granted 👍");
else if (status.state === "prompt")
  console.log("permission will be requested");
else
  console.log("permission was denied 👎");
```

何度でも言うが、 **ユーザの同意に頼ることは安全策ではない** 。


# 今もJSでフォント取得可能じゃん？

冒頭で解説したように、今でもフォントの取得自体は可能です。

しかし、これはあくまで『フォント名を指定して、それがインストールされているか』を調べる方法です。
これも十分問題ではあるのですが、しかし『インストールされている全てのフォントを根刮ぎ取得する』Local Font Access APIに比べれば遥かにマシと言えるでしょう。
たとえば自作したテスト用フォントが入っていたとして、普通のフィンガープリントライブラリはそんな独自のフォント名など知りませんから、フィンガープリントとして使用することはできません。
しかしLocal Font Access APIを使えば、あなたを完全に特定することが可能です。


# 対策案

[なかなか面白い対策案](https://srad.jp/comment/4228557)を出している人がいました。

```text
指定した一群のフォント(絶対使わなさそうなネタ的フォント)を、再起動のたびにランダムに入れ替えるスクリプトとか作ったら需要ありそう。
```

# 設定で禁止する

プライバシーとセキュリティ → サイトの設定 → その他の権限 の下のほうにフォントの設定があります。
必ず『デバイスにインストールされたフォントの使用をサイトに許可しない』に設定しましょう。

| ![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/3ea8a9fd-68d7-4eba-91df-596589c15fbe.png) |
|---|
簡易コマンドパレットを秀丸エディタとサクラエディタとMeryに実装した(experimental)


# 3行くらいで説明
- VSCodeのコマンドパレットのようなものが、[秀丸エディタ](https://forest.watch.impress.co.jp/library/software/hidemaru/)や[サクラエディタ](https://forest.watch.impress.co.jp/docs/news/1248206.html)や[Mery](https://forest.watch.impress.co.jp/library/software/mery/)で使えると面白そうです。（ファジーファインダーとも呼ばれるそうです、後述します）
- というわけで作りました。こちらからインストールできます：
    - [秀丸エディタ用](https://github.com/cat2151/mini-command-palette-hidemaru)
    - [サクラエディタ用](https://github.com/cat2151/mini-command-palette-sakura-editor)
    - [Mery用](https://github.com/cat2151/mini-command-palette-mery)
    - （実験的で、起動は遅く機能も限定的ですので、使うには遊び心が必要です）

# 3行くらいで魅力を説明
- 好きな単語をタイプするだけでOK。操作や階層は覚えなくていい。
    - （というようなマクロファイル名や、マクロタイトル(Mery)や、カスタマイズ(当アプリ)にしていれば、の話）
    - [階層化マクロメニュー(Mery)](https://www.haijin-boys.com/wiki/%E9%9A%8E%E5%B1%A4%E5%8C%96%E3%83%9E%E3%82%AF%E3%83%AD%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC)のほうが有効な局面も多い感触。
        - 適宜使い分けるとよさそうです。
- カスタマイズできます。[migemo](https://qiita.com/otakumesi/items/2f3104b6978e4af28b9d)も対応（自動インストールします）。
    - カスタマイズでマクロに日本語aliasをつけてmigemoで選ぶ、という用途で威力を発揮しやすい、かもしれません。
- 編集中ファイルを絞り込み一覧表示できます。
    - 例えばエラーのあるログファイルで `error` とタイプするだけで、`ERROR` `error` `エラー`(migemoなので)のある行を一覧表示できます。そこからさらにAND検索で絞り込みができます。

# どれくらい便利なの？
- `マクロ一覧から選べる` のは、ちょっと便利です。
- `編集中ファイルを絞り込みできる` のは、なかなか便利です。
- 「VSCodeのコマンドパレットに比べると機能が少なすぎる」という感じはあると思います。（実験段階なので）

# インストールの最大の壁は？
- テキストエディタの `CTRL + SHIFT + P` にマクロを割り当てる作業です。そこは自動化できませんでした。あとはだいたい自動化したのでコマンド1行でいけます。

# 関連リンク
- [コマンドパレットやファジーファインダーのようにインクリメンタルサーチして絞り込むWindowsアプリを作った](https://qiita.com/cat2151/items/b898f34d7a0da69c43e1)
- [秀スクリプトを楽にビルドして実行する方法](https://qiita.com/cat2151/items/ee78cb7c9ae414d86220)
- [afxtools](https://github.com/yuratomo/afxtools)（afxfazzyが便利で使っています。当ツールはafxfazzyの影響を受けています）
## ファジーファインダー
- こういった機能はVimだと`ファジーファインダー`と呼ばれ、活発に開発が進んでいるようです。
- [ファジーファインダー系プラグインとは（Vimにたくさんあるファジーファインダー系プラグインを比較してみる より）](https://zenn.dev/yutakatay/articles/vim-fuzzy-finder#%E3%83%95%E3%82%A1%E3%82%B8%E3%83%BC%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%80%E3%83%BC%E7%B3%BB%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A8%E3%81%AF)
- [ファジーファインダーとは（TypeScriptでVimのファジーファインダーを実装して開発体験が最高になっている話 より）](https://zenn.dev/yano/articles/vim_with_fzf_preview_is_best_experience#%E3%83%95%E3%82%A1%E3%82%B8%E3%83%BC%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%80%E3%83%BC%E3%81%A8%E3%81%AF)
2022年に開催される全国のPHPカンファレンスのまとめ

# 2022年に開催される全国のPHPカンファレンスのまとめ

## [PHPerKaigi 2022](https://phperkaigi.jp/2022/)
- 開催日 : 2020年4月9日(土)～4月11日(月) 
- 開催場所 : 練馬区立区民・産業プラザ Coconeriホール・ニコニコ生放送（ハイブリッド開催）
- Twitter : https://twitter.com/phperkaigi
- ハッシュタグ : [#phperkaigi](https://twitter.com/hashtag/phperkaigi?src=hash)

## [PHPカンファレンス沖縄 2022](https://phpcon.okinawa.jp/) 
- 開催日 : 2022年7月予定
- 開催場所 : 沖縄県内の会場で調整中
- Twitter : https://twitter.com/phpcon_okinawa

## [PHP Conference Japan 2022](https://phpcon.php.gr.jp/2022/) 
- 開催日 : 2022年9月24日(土)～2022年9月25日(日)
- 開催場所 : 未定
- Twitter : https://twitter.com/phpcon/


## 過去のPHPカンファレンスまとめ
- [2020年に開催される全国のPHPカンファレンスのまとめ](https://qiita.com/akase244/items/05c6090486b4c893be04)
- [2019年に開催される全国のPHPカンファレンスのまとめ](https://qiita.com/akase244/items/d74316f6ee8fa464cfa3)
- [2018年に開催される全国のPHPカンファレンスのまとめ](https://qiita.com/akase244/items/8b17a7caa7223574e22f)
- [2017年に開催される全国のPHPカンファレンスのまとめ](https://qiita.com/akase244/items/274e11da0196a4c26b2a)
- [2016年に開催される全国のPHPカンファレンスのまとめ](http://qiita.com/akase244/items/a390b775267ab095e912)
- [2015年度 全国の PHP カンファレンス のまとめ](http://qiita.com/mukaken/items/71dbe2dde462d459adc8)
ラズパイとmac間のファイル操作


macとラズパイ間でファイル移動します。FTPソフトは、cyberdockを使用しました。

1.macに[cyberdock](https://cyberduck.io/)をダウンロードします。
2.下記のように入力すると、ファイルの操作ができます。。

プロトコル : SFTP
サーバー : ラズパイのIPアドレス
ユーザー名 : ラズパイのログインしたいユーザー名
パスワード　: ラズパイのログインしたいユーザーのパスワード
FlaskでWebauthn

## はじめに
最近では様々なサイバー攻撃が起こっており、セキュリティに対する意識も高くなってきているかと思います。
その中でもユーザー認証というところに着目してみたいと思います。

## ユーザー認証方法の代表例
| # | 認証方法 | セキュリティリスク | 備考 |
| ---- | ---- | ---- | ---- |
| 1 | ユーザーID + パスワード | 中 | 言わずもがな、某アプリでパスワード漏洩で大変なことになってましたね。。。 |
| 2 | 多要素認証 | 低 | ユーザーID + パスワード + SMS認証などで現在はこの方法が推奨されていますね。 |
| 3 | 生体認証 | 低 | ここ数年で出てきたのかなと思っています。Yahoo!などがいち早く取り入れていましたね。 |

まだまだあると思いますが主にということでここまでにしておきます。
※セキュリティリスクは主観でざっとつけたのでご意見等あるかもしれませんがお見逃しください。。。

## どれがいいの？
利用されるサイトの質などにもよると思うので、一概にどれが一番ということは言えませんが、一つずつ見ていきましょう。

### 1. ユーザーID + パスワード
最近ではあまり推奨されていないですね。
ただし、外部公開しないような企業のイントラサイトなどでは以下の点に留意すればある程度は問題ないのかなと個人的には思っています。

- パスワードの複雑化（大文字小文字を含む英数字＋記号など）
- パスワードの定期更新（3か月に一度など）

ただ、パスワードって基本的には同じもの（あるいは似たもの）を使い回す方が多いですよね。
そうすると一つのサイトでパスワードが漏洩してしまうと様々なサイトで不正アクセスされてしまうリスクがあります。
これが一番のデメリットだと思います。

### 2. 多要素認証
多要素というくらいなので様々な要素を掛け合わせて複雑化するといったイメージでしょうか。
よく見るのは「ユーザーID + パスワード」で認証後、SMSでPINコードを送付して認証する2段階のものですね。
SMSで送付されるPINコードはワンタイムのものが基本で有効期限もかなり短いものとなっています。
これであればスマホ端末を他人に利用されていない限りは本人しか認証することは難しいですよね。
そのため、この方法が推奨されているのだと思います。

ただ、上記で挙げた例で言えばPINコードも数字の4桁や6桁であることが多く適当に入力すれば当たってしまう可能性がないわけではないです。
この部分がどうにかならないのかとモヤモヤしていました。。

### 3. 生体認証
そこで生体認証です。
2018年頃から[Webauthn](https://developer.mozilla.org/ja/docs/Web/API/Web_Authentication_API)という技術が出てきたようです。
簡単に説明すると、「Webブラウザ上で端末の生体認証機能を利用して認証することができる」ものです。
ということは端末を持っていて、かつ自身（指紋や顔などで認証）でないと認証不可ということです。

しかしサイトの構築方法によりますが、他端末でアカウントの共有が難しかったり、生体認証に対応してない端末だと利用できないというデメリットはあります。
後者はガラケーやらくらくフォン、キッズケータイなどでなければ、最近のスマホは基本的には対応しているかと思います。
前者も対応できないことはないのでこれは試す価値ありですね。


## 実際に書いてみた
ということで先人の方々が情報やライブラリを残してくださっていたのでそれを利用してやってみました。
動作確認用なのでDBを使わずにファイルIOだけでデータ管理を行なっています。
参考になれば幸いです。

https://github.com/oj-free-oj/webautn_sample
19歳でLPIC 303に合格した話

# この記事の目的

私はプロではないので、初心者に向けてレベル感や目安を知ってもらえたらと思い書きました。
これをきっかけにlinuxを知っていただけたら幸いです。

# 勉強期間
### LPICレベル1
計2ヶ月

【内訳】
101：1ヶ月
102：1ヶ月

### LPICレベル2
計3ヶ月

【内訳】
201：1.5ヶ月
202：1.5ヶ月

### LPICレベル3
計1.5ヶ月

【内訳】
303：1.5ヶ月


# 勉強方法
すべてのレベルで参考書を読み、ping-tの問題を解きました。
最短の道はありません。毎日1時間やりました。

# 各試験の感想
### レベル1
とても簡単だったが、初めてなので緊張した。
オプションを暗記しようとすると難易度は上がる気がする。

### レベル2
とくに202試験が難しかった。普通だったら触れることのない範囲の知識だったので知的好奇心がくすぐられました。
201, 202どちらも合格ラインギリギリだった。ツールや機能の仕組みをある程度抑えると楽かも。

### レベル3
範囲が狭いので簡単。レベル2のほうが難しかったです。
私はver2.0を受験しましたが、最新のver3.0の教材は書籍もeラーニングもなかったことが不満です。
80%の正解率なので余裕をもって合格できました。

一応セキュリティ分野の資格ですが、学べるのは侵入検知・パケットキャプチャ・解析ツール・アクセス制御等でした。
脆弱性・インシデント・監査等に対する記述はなかったので、こちらを学びたいのであれば別の試験を検討してみてください。

# 感想
私はlinuxの実務経験はないのですが、十分活かせる知識を学べたと思います。
資格取得が目的ではなかったので、寄り道もいっぱいできました。

レベル1はとても簡単なので、興味があればぜひ！
Wordpressの記事の見出しを正規化する

### 見出しってよくわかってない？

なんとなく、昔からある <font size=7>とか

とりあえず、&lt;h1&gt;が最初の見出しだな、とか
CMSで書いているとおかしくなるので、
正規化できるようにしました。

:::note info
この記事も、わざと見出しがわかってないフリして記述しています。
:::


# 対象

- HTMLの見出しの仕組みをよくわかってない社員や記事執筆者がいる方へ
- 自作テーマを使用中

## 最適化をする

ここにおいては、最大の見出しレベルは &lt;h3&gt; と仮定して
&lt;h1&gt; もしくは &lt;h2&gt; レベルのを強制的に &lt;h3&gt; にして
それ以下のレベルの見出しも適切に置換する非常に単純な記述です

ここでは、サイトのタイトルを &lt;h1&gt;、記事のタイトルを &lt;h2&gt; で既に使用してしまってる場合を想定しています。


```single.php
<?php
	$wpcontent = apply_filters( 'the_content', get_the_content() );
	$wpcontent = str_replace( ']]>', ']]&gt;', $wpcontent );

	// 見出しを h3以下に正規化する
	$hh=0;
	if(strpos($wpcontent, '<h2') !== false) {
		$hh=2;
	}
	if(strpos($wpcontent, '<h1') !== false) {
		$hh=1;
	}
	$hharray=array();
	if($hh==1) {
		$wpcontent = str_replace(
			['<h5','</h5','<h4','</h4','<h3','</h3','<h2','</h2','<h1','</h1'],
			['<h6','</h6','<h6','</h6','<h5','</h5','<h4','</h4','<h3','</h3'],
			$wpcontent);
	}
	if($hh==2) {
		$wpcontent = str_replace(
			['<h5','</h5','<h4','</h4','<h3','</h3','<h2','</h2'],
			['<h6','</h6','<h5','</h5','<h4','</h4','<h3','</h3'],
			$wpcontent);
	}

	echo $wpcontent;
?>
```
【CentOS7】VPSでssh公開鍵認証ログイン


## 前提条件
・Linuxディストリビューション：CentOS7
・VPSにUSER、PASSWORDでログインできる状態

## 鍵認証の流れ
### ①サーバにSSHログイン（USER,PASSWORD）
今回は「RLogin」というフリーソフトを使っていきます。
SSHクライアントソフトは他にも色々あります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234354/5d296210-a692-5324-b7c7-c1a77d9c9c4f.png)

### ②今回はユーザ追加せずにrootユーザで作成
今回利用したサーバで用意されているrootユーザ。
ユーザを新規で作成する場合`useradd<ユーザー名>`で作成可能。

### ③SSH鍵フォルダ作成
`/root`に`mkdir .ssh`でフォルダ作成
ユーザ作成している場合、`mkdir /home/<ユーザー名>/.ssh`でフォルダ作成

### ④SSH鍵フォルダに公開鍵、秘密鍵作成
`ssh-keygen`コマンドで公開鍵、秘密鍵を作成。
`-t`で[RSA]や[ecdsa]の暗号方式を指定可能だが今回は指定なしで作成。
以下のファイルが作成され`pub`がついているほうが公開鍵、ついていないほうが秘密鍵となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234354/8ee34c88-52f2-330c-be7e-f493e177d8ae.png)

### ⑤authorized_keysファイル作成
ファイル作成
`cat id_rsa.pub >> authorized_keys`

### ⑥権限の変更
chmodで権限の変更が可能。`.ssh`を700、`authorized_key`を600にする必要がある。
なぜ変更が必要かは、何も制限がない場合、セキュリティ面での不安が残るからと認識している。
`chmod 700 .ssh`
`chmod 600 authorized_keys`

### ⑦SFTPツールで公開鍵をサーバからダウンロード
ログインする際④で作成した秘密鍵を取得する必要がある。
今回は「WinSCP」を使用して取得。こちらもSFTPツールは色々あります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234354/60327a09-6e3b-5b9f-7ee2-8c49a3a26c91.png)


##
以上の処理でSSHログイン可能です
LinuxのディレクトリをWindowsフォルダへマウントする

# 1. はじめに
本記事では、LinuxのディレクトリをWndowsフォルダへマウントして共有する手順を公開します。
自宅のラズパイ環境のディレクトリをWindowsPCへ共有させているのですが、たまに設定しようとすると忘れそうになるので、備忘録として残しておきます。

# 2. 概要
***■ 目標***
Linux(Ubuntu)の指定のディレクトリをWindowsOSのフォルダへマウントして共有させる。

***■ 実行環境***
- Ubuntu
- Windows10, 11

***■ 前提***
- Linux機とWindows機は同じNWセグメントに存在する前提とする

# 3. Windows側での作業
先にWindows側のフォルダで、他のユーザからの共有を許可させるように設定します。
前提として、フォルダでの設定以前にWindowsPCのOS設定でそもそものファイル共有を有効化する必要があります。
上記手順は下記リンク先の記事にて詳細に記載されていますので、記事を参考に手順を実施して下さい。
- [[Windows 10] 他のパソコンとフォルダーを共有する方法を教えてください。](https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=4510-8381#tejun3)

1. 共有を許可するフォルダを右クリックし、「プロパティ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570694/2a3a0b66-22d3-36de-82d9-964043d2bc6f.png)

2. ポップアップが表示されるので、「共有」タブ --> 「詳細な共有」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570694/38b040ea-8b83-2e06-8a6f-f05765269245.png)

3. 各項目に従い共有設定を行い、ポップアップ下部「適用」をクリックします。
    - 「このフォルダーを共有する」にチェックを入れる
    - 「共有名」を任意の名前に更新する
    - 「アクセス許可」をクリックし、用途に応じて許可設定を行う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570694/b7c34f22-354c-d45a-fe19-87f3d026b3ac.png)

# 4. Linux側での作業

1.  Linuxへssh接続します。

1.  Windowsへマウントする共有ディレクトリを作成します。
    ```
    mkdir /mnt/windir
    ```
1. mountコマンドを実行します。
    ```
    # 基本構文
    mount <マウント先のフォルダパス> <マウント元のディレクトリパス> cifs username=<ユーザ名>,password=<パスワード>,vers=2.1,rw,noperm 0 0
    # 例
    mount //192.168.1.10/document/windir /mnt/windir cifs username=user,password=passwd,vers=2.1,rw,noperm 0 0
    ```
1. dfコマンドでディレクトリがマウントされていることを確認します。 
    ```
    df
    ファイルシス    1K-ブロック    使用    使用可    使用%    マウント位置
    ～～～
    //192.168.1.10/document/windir  244196348  170249932  73946416  70%  /mnt/windir
    ～～～
    ```
## 4.1 マウントの常時有効化
mountコマンドでのディレクトリのマウントはOSの再起動がかかると解除されてしまいます。
なので、起動時に自動でマウントを行う設定をします。
/etc/fstab にマウントコードを記載することで、OSの起動時に自動的にマウントを実行するようになります。

```
vi /etc/fstab
----
proc            /proc           proc    defaults          0       0
PARTUUID=861a68f2-01  /boot           vfat    defaults          0       2
PARTUUID=861a68f2-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off]  for that
//192.168.1.10/document/windir /mnt/windir cifs username=user,password=passwd,vers=2.1,rw,noperm 0 0
```
Centos 8 iso

# Centos 8 iso

[URL](http://mirror.nsc.liu.se/centos-store/8.5.2111/BaseOS/x86_64/os/images/)
*boot.iso*

## 関連記事

[【2022年】CentOS後継問題から学ぶ最適なLinux OSとは？](https://www.kagoya.jp/howto/it-glossary/server/linux_os/)

## ネットワーク関連

*検索キーワード「virtualbox ゲストos 外部から接続」*


[Virtual Box上のWebサーバに外部から接続する](https://hi97.hamazo.tv/e8211801.html)
[VirtualBoxでGuestOSのアプリケーションに外部からアクセスする方法](https://qiita.com/daijinload/items/85f6e84926f41812ed70)
cypressのfilterの中でlog出力するとfilterがnullを返すのでやめましょう。

一覧から複数の条件にマッチするレコードのメニューをクリックするテストを以下のように書いたら動かなくてはまりました。


```js
    cy.find('tr')
      .filter((_, tr) => {
        const $tr = $(tr)
        const column1 = $tr.find(':contains("あのデータ")').length
        const column2 = $tr.find(':contains("このデータ")').length
        // ここでデバッグしてた
        cy.log(`${column1} && ${column2}`)
        return column1 && column2
      })
      .should('have.length', 1)
      .contains('メニュー')
      .click()
  })

```

`filter()` のなかでlogを呼び出したら結果を返さないバグがあるようです。
デバッグのlogを消したらすんなり動きました。

https://github.com/cypress-io/cypress/issues/20985
UE5のプロジェクトをOSDNとSVNでバージョン管理する（SSH接続）

OSDNとEpicGamesのアカウント作成は出来ている人向けに書いています。


# １．ソフトウェアの準備
UE5のインストール
TortoiseSVNのインストール
PuTTYのインストール

# ２．プロジェクトの準備
OSDNでリポジトリを作る
UE5でプロジェクトを作る

# ３．SSH公開鍵の作成と登録
SSH公開鍵の作成
SSH公開鍵の登録

# ４．ssh-agentの設定
ssh-agentのスタートアップ設定と開始
ssh-addで秘密鍵ssh-agentに追加

# ５．PuTTYの設定
PuTTYgenで秘密鍵を変換
Pageantに秘密鍵を追加

# ６．TortoiseSVNのSSHクライアントの設定
TortoiseSVNにplinkを設定

# ７．最初のリポジトリへのコミット
TortoiseSVNでリポジトリをチェックアウトする
TortoiseSVNでAddする
TortoiseSVNでCommitする

# ８．UE5でソースコントロールに接続する
画面右下のボタンを押す
プルダウンからSubversionを選択する

# 補足
環境変数を設定するとUnrealEngineが使用するSSHクライアントを変更できる
なぜかわからないけどバックスラッシュを2つ入れて区切る
変数名
SVN_SSH
値
C:\\Program Files\\PuTTY\\plink.exe
または、
C:\\Program Files\\TortoiseSVN\\bin\\TortoisePlink.exe
Gitを使ってやらかした時、git reflogさえ使えればわりかしなんとかなる

## これは何
新人プログラマ応援イベントの参加記事です。

https://qiita.com/official-events/3f21c92121aa125807b4

gitにはreflogというコマンドがあります。このコマンドを学んでおくとやらかしちゃった時も大体なんとかなるので記事にします。

## git reflogってなに？
`git reflog`とは、Gitで操作履歴を見ることができるコマンドです。
例えば

- `branch1`にチェックアウト
- `branch1`で`branch1.txt`を作成し、コミットを作る
- `master`にチェックアウト

をすると、以下のようなreflogになります。



```sh
$ git reflog
4a4125a (HEAD -> master) HEAD@{0}: checkout: moving from branch1 to master
826a9dc (branch1) HEAD@{1}: commit: Create branch1.txt
4a4125a (HEAD -> master) HEAD@{2}: checkout: moving from master to branch1
```


このコマンド自体はそれだけなのですが、他のコマンドで一緒に表示される作業番号（`HEAD@{0}`）は`HEAD`などと同じ作業ポインタとしてさまざまなコマンドに指定できます。
その特性を生かしたやらかし解決法を紹介していきます。

## やらかしをなんとかする

:::note info
@ryozi_tn さんに、より詳しい説明や、注意点、参考資料についてコメントいただいたので、本文と合わせて読んでみてください
https://qiita.com/getty104/items/cfd98f5f0ea89ef07bf0#comment-8585c38b84ae67c281f0
:::

### 間違えて`git reset --hard`で必要な変更も消しちゃった
上の例で、例えば`branch1`で`git reset --hard HEAD~`を実行し、間違えてコミットした変更を削除してしまったとします。しかし変更した内容は必要なものだったので、このままだと全く同じ作業をまたやらないといけなくなります。最悪です。
しかしこんな場合も`git reflog`を使えばなんとかなります。
まずは`git reflog`で作業ログを出します。

```sh
$ git reflog
4a4125a (HEAD -> branch1, master) HEAD@{0}: reset: moving to HEAD~
826a9dc HEAD@{1}: checkout: moving from master to branch1
```

この`git reflog`を見ると、`HEAD@{0}`という作業番号で誤った`git reset --hard HEAD~`を行っていることがわかります。この作業を取り消し、コミットを復活させたいです。
`git reflog`の作業番号、実はそのまま`git reset`の引数に指定することで、その作業を行っていた時の状態に戻せます。
今回は`HEAD@{1}`に戻りたいので、`git reset --hard HEAD@{1}`を実行します。

実行を行うことで、コミットも元通り、変更内容も復活します。

### 間違えて必要なブランチ消しちゃった
続いて、間違えて`master`にいる状態で`branch1`を削除してしまった場合を考えます。
削除後の`git reflog`の結果は以下の通りです。

```sh
$ git reflog                                                                                                                                                                                         
4a4125a (HEAD -> master) HEAD@{0}: checkout: moving from branch1 to master
9d0bac1 (branch1) HEAD@{1}: commit: Create branch1.txt
4a4125a (HEAD -> master) HEAD@{2}: checkout: moving from master to branch1
```

間違って削除をしてしまったブランチに戻りたいです。
`git reflog`を見ると、`HEAD@{1}`で`branch1`でのコミットを作っていたようです。
そこで、`git branch branch1 HEAD@{1}`を実行します。そうすることで、`HEAD@{1}`までの作業履歴を`branch1`としてコピーすることができるので、ブランチが復活します。


### `git commit --amend`でコミットに不要な変更混ぜちゃった
`branch1`で`branch1-2.txt`というファイルを作成し、新たにコミットを作るはずが誤って`git commit --amend`を用いて一つ前のコミットに変更を混ぜてしまったとします。

`git reflog`の結果は以下の通りです。

```sh
a04365e (HEAD -> branch1) HEAD@{0}: commit (amend): Create branch1.txt
9d0bac1 HEAD@{1}: checkout: moving from master to branch1
```

一旦コミットを取り消し、再度コミットを作り直したいです。
`HEAD@{1}`に作業だけ戻り、ファイルの変更は残しておければそのままコミットを作り直せそうです。
そこで`git reset --soft HEAD@{1}`を実行し、作業だけ巻き戻します。
これでファイルの変更は残しておいたまま、作業だけ取り消せたのでコミットを作り直すことができます。


## まとめ
`git reflog`自体はただ履歴を確認するためのシンプルなコマンドですが、それを応用することでいろんなやらかしを取り消すことができます。
ここで紹介したやらかし以外でも解決できることはたくさんあるので、もしGitを使って何かやらかしてしまった際は`git reflog`を使ってなんとかできないか考えてみてください。
新規投稿時にundefined method `upload' for nil:NilClassエラーについて

## 解決したいこと
料理投稿サイトで新規投稿画面にてタイトル、紹介文、画像の情報を入力し新規投稿したところundefined method `upload' for nil:NilClassエラーが出て解決をしたい。
前提・・・Active Strage導入済

## 試して見たこと
データの流れを確認するためにテーブル、モデル、コントローラの記述を一通り確認。
＝＞これといった間違いはないような感じが。モデルにも has_one_attachedの記述があり問題はなさそう。
コントローラもストロングパラメータは大丈夫。

*/CookOP/app/models/dish.rb
```ruby
class Dish < ApplicationRecord
  has_one_attached :dish_image
  belongs_to :user#, optional: true
  has_many :comments, dependent: :destroy
  has_many :favorits, dependent: :destroy

end
```

*/CookOP/app/controllers/dishes_controller.rb
```ruby
class DishesController < ApplicationController
  def new
    @dish = Dish.new
  end

  def create
    @dish = Dish.new(dish_params)#ここでエラー
    @dish.save
    redirect_to user_path(current_user.id)
  end

  private

  def dish_params
    params.require(:dish).permit(:dish_name, :introduction, :user_id, :dish_image).merge(user_id: current_user.id)

  end

end

```
## 解決方法
結局完全にお手上げ状態でメンターの方に見ていただきました。
すると私が前提としていたActive Strageに問題がありました。手順通りに進めてインストールをしたはずだったのに、、、

インストールはしていたけれども必要なものが全て揃っていなかったとのことでした。
以下の手順で進めました。

『手順』
config/environments/development.rbに追記
```ruby
config.active_storage.service = :local
```
config直下にstorage.ymlを作成し以下を記述
```ruby
test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>
```
これで先ほどのエラーは解決されました。
手順通りに進めてもうまくいかない時はわかりません、、、

以上です。
Laravel(7.x) Database:seeding 個人的まとめ

## 基本的なシーダーファイル作成コマンド
```php
php artisan make:seeder UserSeeder
```

## ファクトリーを使用する
50人分ユーザーを作成し、それぞれにリレーションをアタッチします。
```php
/**
 * Run the database seeds.
 *
 * @return void
 */
public function run()
{
    factory(App\User::class, 50)->create()->each(function ($user) {
        $user->posts()->save(factory(App\Post::class)->make());
    });
}
```

## 追加のシーダーを呼び出す
簡潔に書けて、簡単に呼び出せます。
```php
/**
 * Run the database seeds.
 *
 * @return void
 */
public function run()
{
    $this->call([
        UserSeeder::class,
        PostSeeder::class,
        CommentSeeder::class,
    ]);
}
```

## シーダーを走らせる
シーダーを作成したら、dump-autoloadコマンドを実行して、Composerのオートローダーを再生成する必要がある場合があります。
```
composer dump-autoload
```
デフォルトでは、db:seedでDatabaseClassのrunが実行されますが --classオプションで、個別にシーダーを走らせることもできます。
```php
php artisan db:seed
 
php artisan db:seed --class=UserSeeder
```
このコマンドは全てのテーブルをドロップし、マイグレーションを行うので、完全にデータベースを再構築したい際に役立ちます。
```php
php artisan migrate:fresh --seed
```
### 本番環境で強制的にseedするためのコマンド
--forceフラッグをつける
```php
php artisan db:seed --force
```
A5:SQL Mk-2 でテーブル定義書をMarkdownで出力

# はじめに
A5:SQL Mk-2がMarkdown形式でテーブル定義書を吐けるようになったので使ってみる。


<!-- 各チャプター -->
<a id="#使い方"></a>
# 使い方
メニューから
``データベース(D) → テーブル定義書作成 (S)``
出力方式で``Markdown``を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/cc91de2a-df98-0006-4d36-2e3743c7cfe3.png)

テーブル定義書作成をクリックして出力。

<a id="#Markdownビューアーで開く"></a>
# Markdownビューアーで開く
A5:SQL Mk-2 の作者が作成したMark-Vで開いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/758d572d-1a19-2899-b601-f5ba88374847.png)

ExcelとHTMLより見やすいしReadMeに貼り付けたり出来るので使いどころがありそうです。

<a id="#reference"></a>
# 参考
- [A5:SQL Mk-2](https://a5m2.mmatsubara.com/beta/)
Effective Java 第3版まとめ（項目2）

# 項目2.多くのコンストラクタパラメータに直面したときにはビルダーを検討する

## 書かれている内容

* staticファクトリメソッドとコンストラクタは、多くのオプションパラメータに対しては、どちらもうまく対応できない
* テレスコーピング・コンストラクタ・パターンは、コードを書くのが困難になり、加えてそのコードを読むのはさらに困難になる
* JavaBeansパターンは生成過程の途中で不整合な状態にあるかもしれない
* JavaBeansパターンはクラスを不変にする可能性を排除してしまう
* ビルダーはテレスコーピング・コンストラクタ・パターンの安全性とJavaBeansパターンの可読性を組み合わせている

## 個人の見解

ビルダーを検討しないといけないようなオプションパラメータが多い状況は、オブジェクトの責務が大きすぎるように思う。
まずはオブジェクト指向エクササイズの「１つのクラスにつきインスタンス変数は２つまでにすること」を心がけた上で、選択肢の1つとしたい。

## オブジェクト指向エクササイズとは

### ９つのルール

1. １つのメソッドにつきインデントは１段階までにすること
1. else 句を使用しないこと
1. すべてのプリミティブ型と文字列型をラップすること
1. １行につきドットは１つまでにすること
1. 名前を省略しないこと
1. すべてのエンティティを小さくすること
1. １つのクラスにつきインスタンス変数は２つまでにすること
1. ファーストクラスコレクションを使用すること
1. Getter, Setter, プロパティを使用しないこと

https://connpass.com/event/28737/

### リファクタリング用コード

https://gist.github.com/i-takehiro/3ccb2ece25c89d4ed41c
ONKYO の 32bit efi なマシンに 64bit の ubuntu をインストールする

いわゆる Atom + 32bit efi マシンに 64bit な Ubuntu をインストールします。

今回インストールを行う機種はこちらになります。

[ONKYO TW08A-55Z8](https://www.jp.onkyo.com/pcbiz/slatepc/TW08A-55Z8/index.htm)

CPU自体は64bitに対応はしているものの、ブート部分が32bitでないと起動しないという代物です。

久しぶに Ubuntu20.4.4 でインストールを試みたところ、どうしてもGPUドライバの関係でログアウトが頻繁に発生したため、今回はインストールが簡単な lubuntu で行いました。

lubuntu の場合、インストール時に grub メニューの編集作業がいらないのもあり、こちらがオススメです。
まずは lubuntu + 32bit efi でインストールするのが無難でしょう。

#### 下準備

- １．lubuntu の iso ファイル ( [ダウンロード](https://lubuntu.me/downloads/) )
- ２．Windows で lubuntu を　unetbootin を使用して、USBなインストールメディアを作成 ( [unetbootin](https://unetbootin.github.io/) )
- ３．USBメモリ内の /EFI/BOOT/ に 32bit efi ファイルの bootia32.efi を設置 ( [32bit eft](https://github.com/jfwells/linux-asus-t100ta/blob/master/boot/bootia32.efi) )

となります。

#### １．lubuntu の iso ファイルのダウンロード

以下より lubuntu をダウンロードをします。

- [lubuntu](https://lubuntu.me/downloads/)

中身は Ubuntu20 でいろいろと軽量化がされているようです。また、起動関係も ubuntu よりも lubuntu のほうが面倒見が良いです。

#### ２．Windowsで lubuntu を unetbootin を使用して、USBなインストールメディアを作成

unetbootin をダウンロードして、４GB程度のUSBメディアを差してそこにISOファイル選択してインストールします。

- [unetbootin](https://unetbootin.github.io/)

#### ３．USBメモリ内の /EFI/BOOT/ に32bit efi の bootia32.efi を設置

以下から32bit用の efi ファイル bootia32.efi をダウンロードして、先程作成したUSBメディアの /EFI/BOOT/ に配置します。
/EFI/BOOT/ には 64bit版の efi ファイルが確認できるかと思います。

- [32bit efi](https://github.com/jfwells/linux-asus-t100ta/blob/master/boot/bootia32.efi)

### ONKYO タブレットへのインストール

大まかな流れとしては
- １ nomodeset を選択してインストール（ログアウト等を防ぐため）
- ２ ubuntu-desktop のインストール
- ３ ubuntu で起動する際のオプションの変更
- ４ ログイン画面の変更

となります。

### １．safe mode を選択してインストール（ログアウト等を防ぐため）

今回インストールする ONKYO のタブレットがどうしても Ubuntu の GPUドライバと相性が悪いため、それをオフにしてインストールしていきます。副作用として、画面の自動回転ができなくなります。

インストール作業は起動後のデスクトップにあるインストールアイコンをクリックします。
日本語を選択して、自動ログインもお好みで設定します。

インストールが終わったら再起動を行います。

### ２．ubuntu-desktop のインストール

lubuntu は軽量で良いのですが、ubuntu のような便利な機能がないので、切り替えを行います。
以下のコマンドでインストール（だけ）が行えます

```
sudo apt update ;
sudo apt upgrade -y ;
sudo apt install -y ubuntu-desktop ;
```

これでまずは通常の ubuntu がインストールされます。
ログアウトをすれば、左上のプルダウンメニューに ubuntu が選択できるようになります。
ただ、GPUドライバの関係ですぐにログアウトされたりするので、次の項目の nomodeset での起動を設定します。

３．ubuntu で起動する際のオプションの変更

lubuntu にログインを行い、ターミナルから

```
sudo nano /etc/default/grub ;
```

```
GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash”
↓
GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash nomodeset”
```

```
sudo update-grub2 ;
```

を行います。

これで、GPUオフモードとなります。

### ４．ログイン画面の変更

タブレット起動の際に自動で ubuntu が起動するようにします。

ubuntu は gdm3 ですのでそれに切り替えます

```
sudo dpkg-reconfigure gdm3 ;
```

これで ubuntu への変更が完了となります。
再起動を行うと lubuntu ではなく ubuntu が起動します。

### ワンライナーでの実行

lubuntu で行う上記のコマンド群をシェル化してあります。
下記コマンドで自動でインストールから設定までできます。

lubuntu -> ubuntu desktop

```
wget https://raw.githubusercontent.com/mugimugi555/ubuntu/main/onkyo/install.sh && bash install.sh ;
```

中身はこちら
- [ubuntu/install\.sh at main · mugimugi555/ubuntu](https://github.com/mugimugi555/ubuntu/blob/main/onkyo/install.sh)

### 不具合
現状以下の不具合があります。
- GPS使用不可
- カメラ使用不可
- 画面回転不可（lubuntuは手動で可）

他にもいろいろとあるかとは思いますが、もし Windows の状態で眠っているのなら ubuntu で遊んでみるのも良いかと思います。
Photoshop｜カスタムシェイプを定義したい（シェイプの結合）

Photoshopにある既存のシェイプツール（長方形ツール、楕円形ツール...）で意図的な図形を描き、それをカスタムシェイプツールへ登録する方法（カスタムシェイプを定義）の手順を記します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/92865009-bc10-8dfa-d800-673f67e43140.png)

# カスタムシェイプを定義の手順

## 0） （例）枠を作る
例として『The 枠』を作りたいと思います。
枠線部分（外周部分）は塗りで、中央部は抜き（透明）の形状です（色は何でも結構です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/b60e0ec9-4af3-44fe-fa0e-b074adc9b178.png)


## 1） シェイプを重ねる
まずは、長方形ツールを使って大小の長方形を２つ作成し、中央寄せで重ねて配置します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/c8e2e18a-0902-1a26-ef9a-c48a667116dc.png)


## 2） シェイプを結合（前面シェイプを削除）

作成した２つの長方形を選択した状態で、
`メニュー > レイヤー > シェイプを結合 > 前面シェイプを削除`を実行

すると、シェイブが結合され『The 枠』のシェイプが完成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/ea2fe432-afea-af01-2a97-103e7642a347.png)


## 3） カスタムシェイプに定義する

結合されたシェイプを選択した状態で、
`編集 > カスタムシェイプを定義`を実行

任意のシェイプ名を入力して`OK`をクリックすると、カスタムシェイプの一覧へ登録されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/98c3fd79-43bb-9dd4-2b3e-00e7aa795806.png)


# 注意！）パスファインダーは使わないよ！

本稿を投稿しようと思ったキッカケが`パスファインダー`でした。

`シェイプを結合`に似た機能に`パスファインダー`があります。
`パスファインダー`を使っても、同じような図形を作成することができますが、この方法では`カスタムシェイプの定義`ができないので、注意が必要です（よく見ると、実行した結果も異なります）

「カスタムシェイプの定義ができない！なんで？」と思われた方は、`パスファインダー`を使っていないかも確認しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/69fc3a88-d7cd-3acb-10a4-4cf25d96ca91.png)
Python-SciencePlotsで論文用の図を作成してみた

# この記事について
- pythonユーザーであれば可視化ツールmatplotlibの利用者は多いだろう。しかし論文用の「良い感じの図」を作成するには細かいパラメータをいじる必要があり手間がかかる。そこで今回はSciencePlotsという、簡易的に「良い感じの図」を出力してくれる拡張パッケージを紹介する。
- 導入することで、NatureやIEEEの規定に従った図を簡単に作成することができる。

# 導入方法
## SciencePlotsのインストール
[公式PyPIページ](https://pypi.org/project/SciencePlots/)からインストールできる。
もしくは以下のコマンドを実行する。
```bash
pip install SciencePlots
```

## latex関連パッケージのインストール
SciencePlotsはlatex環境で動作するため、以下のコマンドで必要パッケージをインストールする。
```bash
sudo apt-get install dvipng texlive-latex-extra texlive-fonts-recommended cm-super
```

# 使い方
- プログラム内で説明する。

```python
import matplotlib.pyplot as plt
import numpy as np

#ここでスタイルを指定する
#今回は'science'と'ieee'を利用してみる
plt.style.use(['science','ieee'])

#適当に3Hzと4Hzの信号を作成
x = np.linspace(0,1,100)
y = np.sin(2*np.pi*3*x)
y2 = np.sin(2*np.pi*4*x)

#図の表示
fig = plt.figure()
ax = fig.add_subplot(1,1,1) 
ax.plot(x,y,label = '3 Hz') #3Hzの波を表示
ax.plot(x,y2,label = '4 Hz') #4Hzの波を表示
ax.legend(title = 'Sine Wave',loc = 'upper right',fancybox = False, frameon = True) #凡例の細かい設定
ax.set(xlabel = 'Time (s)') #x軸のラベル
ax.set(ylabel = 'Amplitude') #y軸のラベル
fig.show() 
```

# 実行結果
- SciencePlotsの有無で出力結果を比較してみた。
- 利用した場合だと自動的にフォント、破線、軸の間隔、アスペクト比等を設定してくれて「良い感じの図」になっている。

## 'science'と'ieee'スタイルを利用した場合
<img width="500" alt="withscience.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242913/4eb781d4-7db2-0750-bec6-fa964dfecea2.png">

## 何も利用しない場合
<img width="500" alt="withoutscience.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242913/5d23b2a5-34ab-b7e0-15a2-29b76e1d715b.png">



# 補足

- IEEEの会議等に提出する場合、図表は白黒で印刷したときに読みやすくなければならないとされている[(IEEE公式：図の規定)](https://mentor.ieee.org/myproject/file/Public/mytools/draft/stylegraph.pdf)。また図の幅を1段に収まるようにする必要がある。'ieee'スタイルを設定すると規定に従った図を出力してくれる。
- [SciencePlotsのgithubページ](https://github.com/garrettj403/SciencePlots)に'science'+'何かしらのスタイル'の例が多数紹介されているので各自試してみてほしい。
テンプレートメソッドとは

## 概要
テンプレートメソッドとはOOPの代表的なデザインパターンの一つで、

CSVインポートとXMLインポートなど、**大まかな流れは似てるけど細かいところが違う処理**を複数作成する必要があるときに、
- 一つのクラス内で各ステップをメソッド化し、同じクラス内の別のメソッドでそれらを順番に実行するようにする
- 上記のクラスの子クラスでメソッドの内容を適宜上書きすることでいろいろな仕様に対応できるようにする

というものです。特に親クラスの「それらを順番に実行する」メソッドが「テンプレートメソッド」と呼ばれます。

親クラスが「我々を呼ばないでください、我々が呼びます」と言っているという意味で「ハリウッド原則」と呼ばれることもあるようです。

これはデザインパターンを知らなくても似たようなことをやったことがある人が多いのではないかなと思います。

## 埋め込み方法
### 親クラス
- 必要なステップをそれぞれメソッドに格納する。
- テンプレートメソッド内で上記の処理を実行する。
- 絶対上書きしてほしいメソッドは抽象メソッドにする。
- 上書きしなくてもいいメソッドはデフォルトの処理を書く。
- テンプレートメソッドは上書きされたくないので言語に上書きを防ぐ仕組みがあれば利用する。（javaやphpの`final`など）
- 適宜フックを埋め込んでもいい（※後述）

```java
public class Cat {
        public final void introduce(){
                 String name = getName();
                 String meow = getMeow();
                 System.out.println("My name is %s. I meow like this: %s", name, meow);  
        }
        public abstract String getName();
        public abstract String getMeow();
}

public class Koro extends Cat {
        public String getName() {
                 return "Koro";
        }
        public String getMeow() {
                 return "Meah";
        }
}


public class Chobi extends Cat {
        public String getName() {
                 return "Chobi";
        }
        public String getMeow() {
                 return "Mee";
        }
}
```

### フック
以下のように子メソッド内で親メソッドの前後の処理などをカスタマイズしたい場合は、
```java
class Subclass extends Superclass
{
    ...
    void something() {
        // 前処理したい 
        super.something();
        // 後処理したい
    }
}

```
親メソッドの実装を読まなくてもよくするためあらかじめフック（空のメソッド）を用意するのもアリ。その場合は`pre`や`post`のような前置詞を使ってわかりやすくする。
```java
class Superclass
{
    ...
    protected void preSomethingHook(){}
    protected void postSomethingHook(){}
    void something() {
        preSomethingHook();
        // なにかする
        postSomethingHook();
    }
}
class Subclass extends Superclass
{
    protected void preSomethingHook()
    {
        // 前処理
    }
    protected void postSomethingHook()
    {
        // 後処理
    }
}
```


## 参考
https://refactoring.guru/design-patterns/template-method
https://www.oodesign.com/template-method-pattern.html