OmniAICreator/Qiita-1.07M huggingface dataset:
SpringBatchのJunitテストの書き方（Step構成がJavaで書いた場合）

SpringBatchの公式ドキュメントを参考して、JunitでSpringBatchのテストをやって見たが、Step構成ファイルがjavaファイルで書いた場合、「@ContextConfiguration」でStep構成ファイルを指定するとエラーがいろいろ出ました。
解決方法を調べたが、Step構成ファイルの作成がいくつ注意点があることがわかりました。

## サンプルコード

```Configuration.java
@Configuration
@EnableBatchProcessing
//注意点１：@ComponentScanを追加し、全プロジェクトのBeanをスキャンすること
@ComponentScan("com.example.パス") 
public class Configuration{

  @Autowired
  private JobBuilderFactory jobBuilderFactory;

  @Autowired
  private StepBuilderFactory stepBuilderFactory;

  @Autowired
  private Step010 step010;

  @Bean
  public Step step1() {
    return stepBuilderFactory.get("step1")
        .tasklet(step010)
        .build();
  }

  @Bean
//注意点２：@QualifierでBeanを強く特定すること
  public Job job(@Qualifier("step1") Step step1) throws Exception {
    return this.jobBuilderFactory.get("job")
        .start(step1)
        .build();
  }
}
```

```SpringBatchApplicationTests.java
@SpringBatchTest
@RunWith(SpringRunner.class)
//注意点３：@ContextConfigurationではBeanをうまく特定できないそうで、@SpringBootTestを使う
@SpringBootTest(classes = { Configuration.class })
public class SpringBatchApplicationTests {

  @Autowired
  private JobLauncherTestUtils jobLauncherTestUtils;

  // Jobテスト
  @Test
  public void testJob() throws Exception {
    // launchJobでJob全体を実行する
    JobExecution jobExecution = this.jobLauncherTestUtils.launchJob();
    //実行結果と予想値と比較
    Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
  }
  // Stepテスト
  @Test
  public void testStep1() throws Exception {
    // テストしたいStep名を引数に指定する、Step名は@Qualifierで指定したStep名と一致すること
    JobExecution jobExecution = this.jobLauncherTestUtils.launchStep("step1");
    Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
  }

}

```
生JavaScriptのみでなんちゃってスライドショーを作ってみた

GWも変わらず勉強続けるのみ。
最近は暖かいのか寒いのかよくわからない季節ですね。

今回は[Swiper]("https://swiperjs.com/")や[Keen-Slider]("https://keen-slider.io/")などプラグインを使わず気合いでVanillaJsでスライドショーを作るという試みをしました。

### なぜプラグインを使わないのか
最初はプラグインを使って質の良いスライドショーにするつもりだったんです。私は[Keen-Slider]("https://keen-slider.io/")を使おうとnpmインストールを使ってどうたらこうたらしようとしました。
でも実際にインストールしてみるとオプションがたくさんあって何が何だか分からなくなり、「これもう自力で作った方が早いんじゃね？」と思ったのがきっかけです。もっとjsでのモジュールとかの扱い方に慣れてからにしようかなという次第。

### こうなったら自力で…
早速本題に入ります。まずHTMLで要素を並べる。
同時にスライド用のボタンも実装します。画像の領域にボタンを入れたいので同じ箱に入れました。
```html:HTML
<!-- 箱 -->
<div class="image_box">
  <!-- スライド用のボタン -->
  <div class="slidebtn_wrap">
　　　　　　　　<!-- ここのスタイルはあまり関係ないので省略 -->
    <button class="prev"></button>
    <button class="next"></button>
  </div>
  <!-- カルーセル -->
  <div class="carousel">
    <img src="ex1.png" alt="写真" class="__img">
    <img src="ex2.png" alt="写真" class="__img">
    <img src="ex3.png" alt="写真" class="__img">
    <img src="ex4.png" alt="写真" class="__img">
    <img src="ex5.png" alt="写真" class="__img">
  </div>
</div>
```
通常は`display:none;`としてスライド時にjsによって`open`クラスが渡されたらその写真だけ`display:block;`としたいので、CSSにスタイルを追加。
紛らわしくなるのでアニメーションとか装飾的なものはなしにします。
```css:CSS
.__img {
   display: none;
}
.__img.open{
   display: block;
}
```
ここから自己流っぽくなりますが、JSにて
* 現在表示されている画像のインデックス番号を`x`とする。（初期値を0にセット）
　
* 進むボタン`next`をクリックすると`x`番目の画像の`open`クラスを除去、`x+1`番目（次）の画像に`open`クラスを追加するようにする。
* 上の処理が完了するたび`x+=1`を代入し足していく。
　
* 戻るボタン`prev`をクリックすると`x`番目の画像の`open`クラスを除去、`x-1`番目（前）の画像に`open`クラスを追加するようにする。
* 上の処理が完了するたび`x-=1`を代入し引いていく。
　

この処理で`prev/next`ボタンを押し続けるといづれは`x<0 / x>example.length`となり、
今回の例でいうと「0枚目の写真なんてないし6枚目もないから表示されないよ」状態になるので、それぞれに達したら`prev`では5枚目の写真を表示し`next`では1枚目の写真を表示してリセット状態にしてあげれば良いのです。

以下のコードでできました。
```js:JavaScript
//全ての__imgクラス（写真）を取得
const images = document.querySelectorAll('.__img');
//進む戻るボタン
const prev = document.querySelector('.prev');
const next = document.querySelector('.next');

let x = 0;
prev.addEventListener('click', ()=> {
  if (x === 0) {
      // スライドしてインデックス番号が0に達したらループ
      // ここの-1はindex番号が0から開始するため
      x = images.length - 1;
      images[images.length - 1].classList.add('open');
      images[0].classList.remove('open');
  } else {
      images[x].classList.remove('open');
      images[x - 1].classList.add('open');
      x -= 1;
  }
},false);

next.addEventListener('click', ()=> {
  if (x === images.length - 1) {
      // スライドしてインデックス番号がMAXに達したらループ
      x = 0;
      images[0].classList.add('open');
      images[images.length - 1].classList.remove('open');
  } else {
      images[x].classList.remove('open');
      images[x + 1].classList.add('open');
      x += 1;
  }
},false);
```

仕組みとしては単純ですが、やや冗長になってしまったかもです。ここまで書いておいて「自信がない」という感想が正直なところですw
スライドの動きを加えるとなるとさらに複雑化しそうですな
Google認証するサイトのログインを半自動化したかった

#### あらすじ
お小遣い稼ぎに登録しているクラウドソーシングサービスサイトでは、  
ID/Pass認証のほかにもGoogleとかソーシャル系のアカウントを使って
アカウント作成ができたりする。

![Login画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377966/6990817d-7c16-c98d-4988-cf8637b9ff33.png)

こんなの。

普通にID/Passでログインするならば、Selenium使って
ID/Passの入力欄の情報を取ってそこに自分のログイン情報を突っ込んで、
ボタン押下するコードを書いてやれば大した苦労もなくログインできるはず……

しかし、Googleでログインは自動化しようとすると一筋縄ではいかなさそうだった。
特に対策もせずにその先の画面で同じことをしようとすると認証の画面でエラーが出る。
それに対しては、一度ログインに成功したブラウザのユーザプロファイルを使用して
Chromeを起動させれば認証を飛び越えてログイン後のページに遷移することができる模様。

#### 環境
 - Python 3.x
 - selenium 3.141.0
 - Chrome 100.0.4896.127 (Official Build) （64 ビット） (cohort: Stable) 

#### 手順
##### 目的のサイトにGoogle認証でログインする  
まずは、いつもの手順でログインしておく。

##### Chromeのプロファイルを確認する
```:Chromeのアドレスバーに入力
chrome://version
```
遷移したページから「プロフィールパス」を確認してメモしておく
```:出力例
プロフィール パス	C:\Users\<ユーザ名>\AppData\Local\Google\Chrome\User Data\Default
```

##### ブラウザ起動のコードに組み込む
```python:ブラウザ起動
def getDriver():
    options = webdriver.ChromeOptions()

    # 前の手順で控えたプロファイル情報を持ったパスの一つ上を指定する。
    # ※\はエスケープしておく
    profileFolder = '--user-data-dir=C:\\Users\\<ユーザ名>\\AppData\\Local\\Google\\Chrome\\User Data'
    options.add_argument(profileFolder)

    driver = webdriver.Chrome('chromedriver.exe',options=options)
    
    return driver
```
こいつを呼び出すと、Chrome起動時にChromeで使用しているどのユーザで
Chromeを起動するか聞かれるので、いつも使っているユーザを指定すると
Googleログイン認証をスキップしてログイン後のページにログインできる。
![User選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377966/7bc4949e-65d8-5a35-07cf-b91f8a087657.png)

※同じユーザで別の作業をしているときは
　その作業を全部落としておかないとコケるので
　普段別のことでタブをミリサイズにしている人は注意。。。

#### おまけ
> ※同じユーザで別の作業をしているときは
> 　その作業を全部落としておかないとコケるので
> 　普段別のことでタブをミリサイズにしている人は注意。。。

……って書いた後に検証がてらやってみたんだけど、
なんか再現しなかったので以下の感じで行けるかも。

 1. あらかじめ認証できるユーザで認証しておく。(そのブラウザは閉じずにおいておく
 1. Chromeで利用している別のプロファイルを使用するように書き換える
```diff_python:Option書き換え
def getDriver():
    options = webdriver.ChromeOptions()

    # 前の手順で控えたプロファイル情報を持ったパスの一つ上を指定する。
    # ※\はエスケープしておく
-   fileFolder = '--user-data-dir=C:\\Users\\<ユーザ名>\\AppData\\Local\\Google\\Chrome\\User Data'
+   fileFolder = '--user-data-dir=C:\\Users\\<ユーザ名>\\AppData\\Local\\Google\\Chrome\\User Data\\Profile 4'
    options.add_argument(profileFolder)

    driver = webdriver.Chrome('chromedriver.exe',options=options)
    
    return driver
```
 
Profileの数字はそれぞれのパスをGUIで見ると
使っているアイコンのファイルがあるのでそれを参考にして選択しよう。
特に別のアカウントを使わずにやっている人は
chrome://versionの時にDefaultが選択されているはず。

最近自分でID/Passを作成せずにGoogleアカウントで
サクっとやっちゃうことが多くてついに弊害が出始めたかと思ったけど
自動でログインする仕組みがちゃんとあってよかったです。
できることが増えると情報収集の幅がどんどん広がっていって楽しいですね。
mysql レプリケーションでエラーコード 1535

# はじめに

mysql レプリケーションの、サブ（スレーブ）でエラーコード 1535 が出て更新が止まりました。
(ER_BINLOG_ROW_WRONG_TABLE_DEF)

```
yymmdd hh:mi:ss [ERROR] Slave SQL: Table definition on master and slave does not match: Column 9 type mismatch - received type 17, dddd.tttttttt has type 7, Error_code: 1535
```

レアケースと思いますが、ウチの原因を記述します。

# 発生条件

●条件１
メイン（マスタ）とサブ（スレーブ）で mysql のバージョンが異なり、サブが古い。
しかもウチは MariaDB（メイン）と MySQL（サブ）の組み合わせ・・・。

●条件２
バイナリログが混合形式。(`binlog_format = mixed`)

●条件３
datetime か timestamp を含む新規テーブルを create する。
（見た目はメインもサブも同じテーブル定義ですが、細かいところで異なるのでしょうね。）

●条件４
条件３のテーブルにデータ更新する際、何かしら一時テーブル(`CREATE TEMPORARY TABLE`)を開いている。

以上の条件が重なると、サブにバイナリログが行ベースで渡り、エラーコード 1535 が発生します。

# 暫定対応

データ更新前に一時テーブルを drop します。
これでバイナリログがステートメント形式で渡るので、エラーは起きません。

条件２で `binlog_format = statement` にしてもよいはずですが、試してません。

余談ですが、ウチではデータ削除(delete)なのにバイナリログが行ベースでした。
行ベースって insert, update だけと勝手に思ってましたが関係ないんですね。

# 参考

https://dev.mysql.com/doc/refman/5.6/ja/replication-features-temptables.html
https://dev.mysql.com/doc/refman/5.6/ja/binary-log-setting.html
Seleniumで実行中の画面を録画する

# はじめに
Seleniumでテストを実行した時などに、テストエビデンスやテストが失敗した原因を探すために有用となる、実行時の画面を録画する方法について書きます。
Seleniumの[DockerイメージのGitHub](https://github.com/SeleniumHQ/docker-selenium#video-recording)ページに説明されている方法を利用します。

![selenium-video.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1423540/2508eb8f-2ac3-68f0-15da-b92dbf72b7a5.gif)


## 環境
- Python 3.6.8
- CentOS 7.9

# 準備: Seleniumインストール
前提として、DockerとPythonは利用できる環境とします。
pythonの[seleniumパッケージ](https://pypi.org/project/selenium/)をインストールします。
```console
$ pip3 install selenium --user
```

手元の環境では、`pip3 install selenium`と実行すると、`PermissionError: [Errno 13] Permission denied: '/usr/local/lib/python3.6'`というエラーになったため、以下の記事を参考にして、`--user`オプションを付与してインストールしました。

https://engrowth.me/tech/pip_installerror/

# 実行
SeleniumのDokerイメージのGitHubページにある[ドキュメント](https://github.com/SeleniumHQ/docker-selenium#video-recording)の説明に従って、以下のように実行します。

```console
$ docker network create grid
$ docker run -d -p 4444:4444 -p 6900:5900 --net grid --name selenium --shm-size="2g" selenium/standalone-chrome:4.1.4-20220427
$ docker run -d --net grid --name video -e FILE_NAME=chrome_video.mp4 -v /tmp/videos:/videos selenium/video:ffmpeg-4.3.1-20220427
$ python3 selenium-record-video.py
$ docker stop video && docker rm video
$ docker stop selenium && docker rm selenium
$ docker network rm grid
```

- `-e FILE_NAME=chrome_video.mp4`の環境変数の指定で、動画ファイルの名前を指定します。
- 上記を実行すると、`/tmp/videos`に動画ファイルが生成されます。
- 生成されたMP4ファイルをアニメーションGIFに変換したものが「[はじめに](https://qiita.com/mochi_yu2/items/e6849e662d07d66df063#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)」の画像です(動画の前後をカットしています)。

# テストコード
上記の手順中で利用したテストコードです。

```python:selenium-record-video.py
from selenium import webdriver
import os
import time

# Chromeのオプション
options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")

with webdriver.Remote(
            command_executor='http://localhost:4444/wd/hub',
            options=options) as driver:
    # Qiitaにアクセス
    driver.get('https://qiita.com/')
    assert driver.title == "Qiita"
    # スクリーンショットを取得し保存
    filename = os.path.join(os.path.dirname(os.path.abspath(__file__)),
            "screenshot_qiita.png")
    driver.save_screenshot(filename)

    # 検索窓に「Selenium」と入力し、検索
    search_box = driver.find_element_by_name("q")
    search_box.send_keys('Selenium')
    search_box.submit()

    # 検索結果の1件目にアクセス
    driver.find_element_by_xpath('//h1[@class="searchResult_itemTitle"]').click()
    time.sleep(3)
    # スクリーンショットを取得し保存
    filename = os.path.join(os.path.dirname(os.path.abspath(__file__)),
            "screenshot_article.png")
    driver.save_screenshot(filename)

```
- Qiitaトップページにアクセスし、「Selenium」と検索して、検索結果の1件目にアクセスします。
- Qiitaのトップページと検索結果の1件目のサイトのスクリーンショットを保存します。

# 参考
本記事の作成にあたり、以下を参考にさせていただきました。

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0662
ssh接続の際のコマンド入力を簡単にする(macOS, Linux向け)

"ssh -i id_rsa username@remote" とかいちいち書くのめんどくさい！
そう思ったので、コマンド入力を短縮する方法を記事にまとめてみます。

macOSやLinux向けの説明になりますが、Windowsでも同様のことができます。

## .ssh/configの設定
まずホームディレクトリ直下の.sshディレクトリに移動します。
```
$ cd ~/.ssh
```
新たにconfigという名前のファイルを作成。
```
$ touch config
```
テキストエディタなどでconfigファイルの中身を編集します。
```
$ vim config
```
中身は以下のように作成します。Hostの部分は覚えやすい名前にします(ここではfuga)。
```
Host fuga
  HostName       接続先IPアドレス or 接続先ドメイン
  Port           ポート番号
  User           ログインするユーザー名
  IdentityFile   id_rsaファイル(秘密鍵)のフルパス
```
これで保存すればどのディレクトリからでも以下のコマンドを入力するだけでssh接続ができます！
```
$ ssh fuga
```
オプションをつけることも可能。
```
$ ssh -Y fuga
```

## scpしたい場合
ファイルをローカル-リモート間でコピーしたい時にも
"scp -i id_rsa filePath username@remote:Path" とか長いコマンドを入力する必要はなくなります。

リモートからローカルへコピーする場合は
```
$ scp fuga:コピー先パス ローカルのファイルパス
```
ローカルからリモートへコピーする場合は
```
$ scp ローカルのファイルパス fuga:コピー先パス
```
これだけでscpができます！
Windows 10で複合機からのドキュメントスキャンが失敗する


んーまたか…
最近Windows10を20H2から21H2にしたら
複合機（DocuCentreIV C-5573）からスキャンしたらファイルの書き込みに失敗するようになった…

1903→20H2にした時も同じことが起きていろいろやったけど今回の原因はなんだ？


今回はググってもあまり効きそうにない（既にやってある）対策がいろいろ出て来たけど
結局やったのは
・ポート445を開ける
　　ファイルとプリンタの共有を有効にしてるから既に空いてるはず
　　それ以外のリモート監視？とかの445を使うルールが無効のままだったので有効にした
　　これは多分違うな…

・SMBファイル共有のサポートのインストール
　　PowerShellでWindowsの機能の追加具合が確認できると聞いたので
　　以下のコマンドを管理者モードで打ってみたけど

　　　Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol

　　機能は既に有効っぽい。

　　ならばと一旦無効化して有効化したらどうなるか試してみた。

　　　Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol

　　　Enable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol

　　※それぞれ再起動を要求される

　　再起動後スキャンしてみたら成功した時に鳴る音が聞こえるじゃない！


　　Windowsの機能追加入れた時はオプション機能入れなおさんといかんのか？
　　なんか釈然としないけど一応解決したから忘れないようにメモ。
Cloud SQL Auth Proxyを利用してCloud SQLをローカル環境っぽく利用してみた

　Cloud SQLはGoogle Cloudが提供するフルマネージドのデータベースサービスです。利用できるデータベースもMySQL、PostgreSQL、SQL Serverなど主要どころが選択可能となっています。このデータベースサービスですが、以下の通り利用方法が複数あります。
**接続方式**
- パブリックIPを利用した接続
- プライベートIPを利用した接続

**接続許可方式**
- Cloud SQL Auth SQL
- SSL/TSL証明書
- データベースの組み込み認証（ユーザ、パスワード）

　今回は「Cloud SQL Auth SQL」を利用してローカルから安全、手軽に接続する方法を紹介したいと思います。

### 事前準備①
　接続対象であるCloud SQLインスタンスを作成します。今回データベースは、PostgreSQL12を選択しました。
![CloudSQL1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541501/95a3d70c-d912-4dd0-5e8f-66203b2d0dc7.jpeg)

　バージョンが古いのは、現在別件で動作検証しているPythonパッケージの兼ね合いなので、あまりお気になさらず。あと、構成部分はCloud SQLの選択可能なもので一番安いものにしました。お金がもったいないのでお許しを・・・

### 事前準備②
　接続に必要なサービスアカウントを準備します。接続に必要な権限は「cloudsql.instances.connect」であり、この権限を含むロールは以下のものがあります。

- Cloud SQLクライアント
- Cloud SQL編集者
- Cloud SQL管理者

　今回紹介する内容程度であれば、Cloud SQLクライアントで十分だと思います。ちなみに、私はCloud SQL管理者の権限で実行しました。


### Cloud SQL Auth Proxyのダウンロード
　 [Googleのドキュメント](https://cloud.google.com/sql/docs/mysql/sql-proxy#install)に従ってcloud_sql_porxyをダウンロードします。OS別に手順が分かれているので、利用している環境に合わせてダウンロードしてください。
　また、ダウンロードしたファイルは作業フォルダに入れておくといいです。PATHを通してもいいですが、個人的にそこまでする必要はないかなーって感じです。

### Cloud SQL Auth Proxy起動
　私の環境はWindowsなので、ここからはその前提でお読みください。Cloud SQL Auth Proxy起動に必要な情報は以下の通りです。

- GCPのプロジェクト名
- Cloud SQLのインスタンスが存在するリージョン名
- Cloud SQLのインスタンス名
- 利用ポート
- サービスアカウントキーのパス

　上の情報をもとに、以下のコマンドでCloud SQL Auth Proxyを起動します。

```powershell:connect-cloudsql.ps1
.\cloud_sql_proxy.exe -instances='プロジェクト名:リージョン名:インスタンス名=tcp:ポート番号' -credential_file='サービスアカウントキーファイルのパス'
```
　-instances引数の「プロジェクト名:リージョン名:インスタンス名」は、Cloud SQLの概要画面の接続名と同じなので、コピーするといいと思います。=以降は、自身の環境での未使用ポートを指定してください。私は今回11111ポートを利用しました。
　コマンドが地味に長いので、私はシェル化しています。実行すると以下のようなメッセージが出ます。
```text
2022/05/02 07:43:43 using credential file for authentication; email=XXXXXXXXXXXXXX
2022/05/02 07:43:44 Listening on 127.0.0.1:11111 for プロジェクト名:リージョン名:インスタンス名
2022/05/02 07:43:44 Ready for new connections
2022/05/02 07:43:45 Generated RSA key in 1.0022478s
```
　これで準備完了です！！！

## 接続確認
　psqlとpgadminで動作確認したいと思います。

### psqlでの接続確認
　以下のコマンドでデータベースに接続できました！
```powershell
PS C:\Users\xxxxx> psql -h localhost -p 11111 -U postgres -d reserve_parking
ユーザ postgres のパスワード:
psql (13.2、サーバ 12.10)
"help"でヘルプを表示します。
reserve_parking=>
```

### pgadminでの接続確認
 以下の情報で接続設定を行います。ホスト名とポート番号を間違えないようにしてください。
![CloudSQL2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541501/7eafe245-295f-8d3c-5598-6ee28e335612.jpeg)
![CloudSQL3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541501/88852475-a42d-0ded-8188-8aed93870622.jpeg)
　これで、saveを押すと・・・
![CloudSQL4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541501/48fce402-8a56-1d56-3393-068356fe5776.jpeg)
　うまくデータベースを認識させることができました！

## 最後に
　なんとかうまくできました。今Webアプリを勉強中で、手軽に構築、削除できるDBが欲しかったので、非常に便利です。Dockerとかでもいいんですけどね。
Windows10でPython環境構築など

### Windows10でのPython環境構築メモ
Python 3.8.5をダウンロードしてインストールします。
Windows10のスタートメニューからPowerShellを起動します。


まず、インストールができたかバージョン確認します。
ここで悩んだ事ですが、バージョンが何も表示されません。
これは良く分かりません。。とりあえずインストールは出来ている様です。
```shell
> python -V
Python ※何も表示されない
```

次に、jupyterをインストールします。
Windowsの場合は、「py -m」がないとインストールに失敗するようです。
<font color="red">※これは重要です。</font color>
```shell
> py -m pip install jupyter
～インストールログが色々でます～
> py -m pip install jupyterlab
～インストールログが色々でます～
```

インストールが出来たらjupyterlabを起動します。
```shell
> py -m jupyter lab
```
仮想マシンとは

# 仮想化
サーバなど(CPU、メモリ、ディスクなど)を
大事な要素を抜き出して他を捨てることで、
物理的な制限にとらわれずに、ソフトウェア的に
統合・分割できるようにした技術
>メリット
 ・機器の数、管理のコストを抑えられる
・速くコンピューティング環境を構築できる
>
## 仮想化を実現する方法
→仮想マシン、コンテナがある！
>今回は仮想マシンについて重点をおく
>
仮想マシン(VM)
　　ハイパーバイザ上で仮想的なハードウェアを起動して、
　　ゲストOSを動作させる方式
　　　　※ハイパーバイザ
　　　　　　　コンピュータを仮想化するためのソフトウェア

　　ゲストOSからは通常の物理マシン上で動作しているように見えるので、
　　環境を構築・運用できる

　　また、ハイパーバイザがサポートしているOSなら、ホストOSとは違う種類の
　　ゲストOSが使える

## ハイパーバイザの種類
>ネイティブ型

ハードウェア上で直接ハイパーバイザを起動して、その上で
仮想マシンとゲストOSを動かす
ホスト型に比べて、パフォーマンスがいいので、仮想化の主流になっている
例)Xen、Hyper-Vなど

>
>ホスト型

ホストOS上に仮想化ソフトウェアをインストールして、その上で、
仮想マシンとゲストOSを動かす
手軽に仮想環境を作ることができるけど、ネイティブ型に比べて
余分な処理量が大きくなる
例)Oracle VM Virtualboxなど
crt,ca,keyをpfx形式に変換する方法


# 変換コマンド
WSL2などopensslを使用できる環境で下記のコマンドを入力します。
testの部分は適宜書き換えて実行して下さい。
```
openssl pkcs12 -export -inkey test.key -certfile test.ca -in test.crt -out test.pfx
```

# 用語
## pfx形式とは
Microsoft系のサービスで利用されることが多い、サーバ証明書と秘密鍵が1つになったファイルになります。
※中間証明書も追加することができます。
Linux Ping-t勉強の記録5 プロセスの生成、監視、終了

# 覚えるものを記録
### pstree (ps axf)
動作中のプロセスを階層で表示するコマンド
## psコマンド
実行中のプロセスを表示
### psコマンドオプション
#### a
端末操作のプロセスを表示
#### x
端末操作以外のプロセスを表示
#### f
プロセスを階層で表示
#### -f
プロセスを完全なフォーマットで表示
#### u
プロセスの実行ユーザ名も表示
#### -p (p)
指定したプロセスIDのプロセスだけを表示
#### -e
全てのプロセスを表示
#### -l (l)
親プロセスのPIDやnice値(NI)も併せて表示
#### pgrep
指定した名前のプロセスのPIDを表示する
___
### psコマンドの組み合わせ
#### ax -ef
実行中のすべてのプロセスを表示
___
## fg・bg・jobコマンド
#### fgコマンド
バックグラウンド、一時停止中のジョブをフォアグラウンドに切り替える
引数を指定しない場合、カレントジョブが変更される
#### bgコマンド
一次停止中のジョブをバックグラウンドに切り替える
引数を指定しない場合、カレントジョブが変更される
#### jobsコマンド
ジョブを一覧表示
#### Ctrl+z
フォアグラウンドジョブを一時停止
___
## topコマンド
#### メモリやスワップ領域の使用状況を表示する
一定時間ごとに更新して表示する
qで抜け出せる
## uptimeコマンド
システムの稼働時間や負荷平均を表示する
※topコマンドの1行目とほぼ同じ内容
___
## 仮想端末制御プログラム
Linuxは複数人で同時に接続、操作できるようになっている
通常は一つの端末で一つの端末を利用するが、仮想端末制御プログラムでは一つの端末で複数の端末を利用できる。
#### screen
#### tmux
___
## シグナル
### killall
全てのプロセスにシグナルを送信するコマンド
#### killallとpkillの違いは何？
pkillの場合対象のプロセス名を指定できる
___
#### HUP(SIGHUP)
端末の切断による終了
#### INT(SIGINT)
割り込み終了
Ctrl+cでもシグナル送信可能
#### KILL(SIGKILL)
強制終了(クリーンアップしない)
シグナル番号9
#### TERM(SIGTERM)
KILLの反対(クリーンアップする)
シグナル番号15
シグナルを指定しない場合このシグナルが使用される
#### STOP(SIGSTOP)
一時停止
#### TSTP(SIGSTP)
STOPと一緒？
#### cont(SIGCONT)
一時停止しているプロセスを再開
___
### pgrep
プロセスIDを表示する
-u ユーザ名 で、記述したユーザが実行したもののみを表示する
___
#### nohup
ログアウト後もジョブを実行させる
PowerVC Tips: イメージのインポートでは サーバーのボリュームとデフォルト・ストレージ・テンプレートのストレージ・プールが同じである必要があるようです

##### はじめに

PowerVC のイメージ・インポートでは、PowerVC サーバー上にイメージの書き出し、一時的なボリューム・ドライバー(ストレージ・テンプレート)の接続、ボリューム作成、書き出しが行われています。

・Export and import images using CLI
https://www.ibm.com/docs/en/powervc/2.0.2?topic=images-export-import-using-cli

---
##### 環境

PowerVC 2.0.2 (RHEL 8.4 ppc64le)


----
##### 発生した事象

事象：CLI でイメージのインポートができない

以下のようなログが出力されました。

```
# powervc-image import -p /var/opt/ibm/powervc/imgstaging/work/AIX-testimage.ova.gz 
 -t a1baxxxxx3-341a-4dxx-bf54-12dxxxxx45xx

[このプロンプトを回避するには OS_PASSWORD 環境変数を設定します] 「root」のパスワードを入力してください: 
一時ステージング・ディレクトリー /var/opt/ibm/powervc/imgstaging/tmpmvbcclro が作成されました
圧縮されたアーカイブが検出されました。
パッケージの内容を一時ディレクトリーに抽出しています。
n OVF 記述子を解析しています。
.meta ファイル記述子の解析中です。
一時ファイル・コピー・ボリューム・ドライバーを登録します。
登録済み一時ドライバー PVC-Lite-File_tmpmvbcclro サービス・ロケーション /var/opt/ibm/powervc/imgstaging/tmpmvbcclro
Begin processing image volume 'Image_AIX-testimage_volume_1'.
ステージング・ファイル「Image_AIX-testimage_volume_1」の一時コピー・ソース・ボリュームを作成します....作成が完了しました。
「Image_AIX-testimage_volume_1」のボリューム・データを「ファイル・システム」からターゲット・ストレージ・テンプレート「SVC_1 ベース・テンプレート」にマイグレーションしてください。
コピーするサイズは 100.00 GiB です。
ターゲット・ボリュームを作成および接続しています。.
Copying Image_AIX-testimage_volume_1 [100%] Rate: 5.61 GiB-per-S, ETA: 0:00:00 [H:MM:SS]
ボリュームを切り離して、メタデータをファイナライズしています...
0:00:22 [H:MM:SS] の待機後にコピーが完了

イメージのコピー用に GiB が残っています: 0
Image_AIX-testimage_volume_1 のボリューム・データは正常にコピーされませんでした。そのストレージ・テンプレート「PVC-Lite-File_tmpmvbcclro ベース・テンプレート」は、予期されたストレージ・テンプレート「SVC_1 ベース・テンプレート」ではありません。外部ボリュームを接続できなかったか、外部ボリュームを PowerVC サーバー・インスタンスから正しく切り離すことができなかったか、またはボリューム作成をドライバーに対してスケジュールできなかった可能性があります。/var/log/cinder にある Cinder のスケジューラー・ログおよびボリューム・ドライバー・ログでエラーの詳細を確認してください。
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/powervc_glance/cmd/image.py", line 845, in import_image_to_provider
    else False)
  File "/usr/lib/python3.6/site-packages/powervc_glance/cmd/agility_flows.py", line 649, in import_from_folder_flow
    vol['path'])
  File "/usr/lib/python3.6/site-packages/powervc_glance/cmd/agility_flows.py", line 1198, in retype_volume
    expected=target_type.name), rc=47)
powervc_glance.cmd.agility_flows.AgilityException: Image_AIX-testimage_volume_1 のボリューム・データは正常にコピーされませんでした。そのストレージ・テンプレート「PVC-Lite-File_tmpmvbcclro ベース・テンプレート」は、予期されたストレージ・テンプレート「SVC_1 ベース・テンプレート」ではありません。外部ボリュームを接続できなかったか、外部ボリュームを PowerVC サーバー・インスタンスから正しく切り離すことができなかったか、またはボリューム作成をドライバーに対してスケジュールできなかった可能性があります。/var/log/cinder にある Cinder のスケジューラー・ログおよびボリューム・ドライバー・ログでエラーの詳細を確認してください。
一時ファイル・ドライバー「PVC-Lite-File_tmpmvbcclro」を登録抹消します。
一時ステージング・ディレクトリーのクリーンアップ中...
```


----

##### 解消方法

検証で試行錯誤しましたが、PowerVC のイメージ・ステージング領域があるボリュームと、PowerVC デフォルト・ストレージ・テンプレートを同じストレージ・プールを使用するように設定すると、インポートが成功しました。

ログ内でボリューム・データのコピーが行われていますが、ここで同じプールであることが必要なのではと推測します。


---

(参考) Storage templates
https://www.ibm.com/docs/en/powervc/2.0.2?topic=powervc-storage-templates


イメージ・インポート、エクスポートはストレージ周りの設定が影響しやすいですね。


以上です。
【mySQL】SQLでFizzBuzz問題にチャレンジ

# コード
可読性的には以下が一番かなー
```SQL
CREATE TABLE new_tbl  
    SELECT @n := 1 num
    UNION
    SELECT @n := @n + 1
    FROM information_schema.COLUMNS
    LIMIT 100;
    
SELECT
    case
        when num % 15 = 0 then 'FizzBuzz'
        when num % 3 = 0 then 'Fizz'
        when num % 5 = 0 then 'Buzz'
        else num
    end num
FROM new_tbl 
```

```SQL
   SET
	 @n15 = 15,
	 @n3 = 3,
	 @n5 = 5;

    SELECT @n := 1 id,@a := 1 num
    UNION
    SELECT @n := @n + 1,
      case
        when @n % @n15 = 0 then 'FizzBuzz'
        when @n % @n3 = 0 then 'Fizz'
        when @n % @n5 = 0 then 'Buzz'
        else @n
    end 
    FROM information_schema.COLUMNS
    LIMIT 100

```


```SQL
select
  case
    when n % 15 = 0 then 'FizzBuzz'
    when n % 3 = 0 then 'Fizz'
    when n % 5 = 0 then 'Buzz'
    else n
  end n
from (
    SELECT @n := 1 n
    UNION
    SELECT @n := @n + 1
    FROM information_schema.COLUMNS
    LIMIT 100
) t;

```

```SQL
select
  case
    when n % 15 = 0 then 'FizzBuzz'
    when n % 3 = 0 then 'Fizz'
    when n % 5 = 0 then 'Buzz'
    else n
  end n
from (
  select @num := @num+1 n
  from (select @num := 0) t0,
    (select 1 union select 2 union select 3 union select 4) t1,
    (select 1 union select 2 union select 3 union select 4) t2,
    (select 1 union select 2 union select 3 union select 4) t3,
    (select 1 union select 2 union select 3 union select 4) t4
    limit 100
) t;

```

# 結果
```
n
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz

```
Bronze DBA 模試 復習アウトプット 2回目も間違えた群

# UNDO/REDO
UNDO:変更を元に戻すため(一貫性を保つ)
REDO:変更を再現するため(データ損失から守る)

# 自動セグメントアドバイザ
表領域の管理が有効になっている場合のみ、評価する。
# ロールフォワード
データベースがマウントされた後の起動時の順序
順序自体は覚えているが、
ロールフォワードの認識が曖昧。
正：データファイルに反映されていないすべての変更
引っ掛け：データファイルに反映されていないコミット済みのトランザクション。
コミット済みかどうかはロールバックでは気にするが、ロールフォワードの段階で気にしない。

# MMON/PMON
ポケモンの仲間にも見えなくもないが、暗記できなかったので
再度それぞれの役割を確認する。
| 名称 | 役割 |
|:-:|:-:|
|  MMON |  管理性モニター |
|  PMON |  プロセスモニター | 

MMONの「M」　管理は英語でManagement、その頭文字M
PMONの「P」　プロセスそのまま。

クライアントが電源を切った場合というのは
ユーザープロセスが強制遮断されたことになる。
PMONがプロセスをリカバリしようとする。

# REDOログ
インスタンスリカバリで使用される。
これもUNDO/REDO問題の類。

# EMDEとEMCCの違い
よく隣に出てくる用語で、ツールの役割を調べたが下記。
| 名称 | 役割 |
|:--|:--|
|  Enterprise Manager Data Express |  パフォーマンス監視ツール |
|  Enterprise Manager Cloud Control | oracleインフラストラクチャ全体を単一のコンソールから監視、管理することが可能 |

どちらも監視できるツールのようですが、できることが違うらしいくらいで覚えておく。
というのも、内容がそこまで深く問われないから。
大体EMCCの方が色々できること多いので、EMDEの印象がないものはEMCCにする。 

# ディスク障害
クリティカル領域(SYSTEM)のデータファイルの破損
→再起動してMOUNT状態にする必要がある。

# UNDO
またもや、UNDO。
ロールバックもUNDOデータを使用するものの一つ。
メディアリカバリはロールバックは、使うが、ロールフォワードの段階ではないことを覚えておこう。

# ロールの付与パターン
認証認可。
ロール付与できるもの。
・ユーザー
・ロール

# オーバーヘッド
表領域の自動拡張の場合、オーベーヘッドする(負荷がある)。
負荷を減らすため、手動対応が必要。
オーバーヘッドとは？↓

https://wa3.i-3-i.info/word12471.html

# ネーミングメソッド　読み方
①ドメイン
②サーバー
③インスタンス

順序
②/③.①

# 環境変数
誤：ORACLE_SIDは、データベース名
正：ORACLE_SIDは、インスタンス名
[備忘録]Nuxt3のRC版で「Cannot find module 'nuxt'」エラーが発生して動かなくなった

Nuxt3のRC版を試してる際に以下のエラーが出るようになりましたが、解決できたので備忘録を残しておきます。

```shell
ERROR  Cannot start nuxt:  Cannot find module 'nuxt'
```

# 解決策

以下で解決できました。
https://github.com/nuxt/framework/discussions/3060#discussioncomment-2606906

実際に試した手順を記載しておきます。

①依存パッケージの定義方法を変更

```package.json
{
  "devDependencies": {
    "nuxt": "npm:nuxt3@latest"
  }
}
```

②nuxt3をインポートしている個所の修正 

```nuxt.config.js
// 「from 'nuxt3'」から「from 'nuxt'」に変更
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({ ... })
```

③いったん依存パッケージをすべて削除する

```shell
rm -rf node_modules
rm yarn.lock
rm package-lock.json
```

④再度依存パッケージをインストール

```shell
npm install
# or
yarn install
```
エンジニア面接 質問集

私が実際に面接で聞かれた質問事項をまとめました。
エンジニアの面接ってどんなこと聞かれるんだろう？ 
何を準備しておけばいいんだろう？
って思ってる方の助けになれば幸いです。

## 事前情報
面接当時のエンジニア歴： 1年3ヶ月
面接企業数： 3社（自社開発）
応募職種： Androidエンジニア
経歴：
 2017年4月：鉄道企業に総合事務職として新卒入社 (3年半）
 2020年10月：受託アプリ開発会社に転職、エンジニアにジョブチェンジ。(1年半)
 2022年5月：自社開発企業にAndroidエンジニアとして転職。

## 技術以外の質問
### 自身について
* PRも含めた自己紹介
* 前職を選んだ理由
* エンジニアを目指した理由
* 転職動機
* 志望動機
* なぜtoCではなくtoBを希望しているのか
* 人生で一番の失敗
* 将来のキャリア

### チームマネジメントについて
* チーム内での立ち位置
* メンバーにタスクを振る上で意識していること
* メンバーへ振るタスクと自分でするタスクの線引き
* メンバー間での進捗共有で意識していること
* マネジメントに一番必要なものは何だと思うか

### これまでとこれからの働きかたについて
* プロジェクトで大変だったこと
* 仕事を進める上で一番大切にしていること
* PMやクライアントとの接し方
* 違う業界に入った時にギャップをどう埋めていくか
* 他のプラットフォームに興味があるか

### 会社に求めること
* どういう条件下だと自分のパフォーマンスを発揮しやすいか
* どういうプロジェクトチームだと理想か


## 技術質問（Android）
### 設計関連
* アーキテクチャ選定の理由、意図
* MVVMの利点とは
* ViewModelが肥大化しないために工夫していること
* Repositoryの役割とは
* Dagger Hiltを選んだ理由

### 非同期関係
* Coroutineを選んだ理由
* CoroutineFlowにまとめた理由
* StateFlowでなくLiveDataを選んだ理由
* RxJavaからCoroutineに変えてよかったこと

### テスト
* テストはどうやって書いてるか
* テストしづらい・しやすいときはどんなときがあったか
* テストでDIの恩恵はうけているか
* UIテストを書かない理由

### レビュー
* コードレビュー受けてためになったこと
* レビューする中で心がけていること
* 人のレビューを見て、学んだこと

### ライブラリ類
* 使ったことのあるJatpackライブラリは何があるか
* WorkManagerつかったことあるか
* Glideつかったことあるか
* Firebaseつかったことあるか
* Realmつかったことあるか

### エンジニアの仕事について
* 一番大変だった実装経験
* エンジニアの仕事で好きなことと苦手なこと

### その他
* 日頃の技術のキャッチアップ方法
* onCreate()とonCreateView()ではどんな処理を書いているか
* CI自動化の経験
* Materialデザインをつかって開発したことはあるか
* 大規模なリファクタ経験はあるか
Gitのマージに関して

・Gitのマージに関して
●マージ・・・他の作業者の変更内容を取り込む作業

●コマンド
git merge ブランチ名
git merge リモート名/ブランチ名
例)
git merge origin/master
=>作業中のブランチにoriginリポジトリのmasterブランチをマージする

●マージの種類
マージには3種類存在する。
①Fast Foward
=>枝分かれしていないブランチを最新の状態に更新するマージ
```
git pull リモートリポジトリ名 ブランチ名
```
で可能
②Auto Merge
=>最も基本的なマージで、枝分かれしているブランチを1つにまとめるマージ
※git mergeコマンドを使用
③Conflict
=>同じファイルの同じ行に対して異なる編集を行った複数のファイルをAuto Mergeした際に起こるエラー
※マージ後のファイルを編集後、再度git add, git commitすることにより解決する
SmartyでPHPからテンプレートへ値を渡す

## 用途
SmartyでPHPからテンプレートに値を渡したい時に使う。
PHPで処理したものなどをSmartyでテンプレートに渡したい時に使う。

## 使用方法
```php:phpファイルでの渡し方
$smarty->assign("変数名", "値");
```
渡す際は、`assign` の第1引数に「変数名」、第2引数に「渡したい値」を指定する。
```html:テンプレートファイルでの受け取り方（表示の仕方）
{$変数名}
```
受け取る際は、phpファイルで指定した変数名の先頭に `$` をつけて `{}` で囲む。

---------------------------------------

### 文字列を渡す
```php:phpファイルで文字列を渡す
$smarty->assign("hoge", "abcdefg");
```

```html:テンプレートファイルで文字列を受け取る
{$hoge}です。

// 結果
abcdefgです。
```
-------------------------

### 配列を渡す
```php:phpファイルで配列を渡す
$array = ["a", "b", "c", "d", "e"]
$smarty->assign("hoge", $array);
```

```html:テンプレートファイルで文字列を受け取る
{$hoge[0]}です。<br>
{$hoge[1]}です。<br>
{$hoge[2]}です。<br>
{$hoge[3]}です。<br>
{$hoge[4]}です。

// 結果
aです。
bです。
cです。
dです。
eです。
```
-------------------------

### 連想配列を渡す
```php:phpファイルで連想配列を渡す
$array = ["name"=>"tanaka", "color"=>"red", "number"=>"1"]
$smarty->assign("hoge", $array);
```

```html:テンプレートファイルで文字列を受け取る
名前は{$hoge.name}です。<br>
色は{$hoge.color}です。<br>
数字は{$hoge.number}です。

// 結果
名前はtanakaです。
色はredです。
数字は1です。

```

-------------------------

### デフォルト値を設定する
```php:phpファイルで文字列を渡す
$smarty->assign("hoge", "");
```

```html:テンプレートファイルで文字列を受け取る
{$hoge|default:"ない"}です。

// 結果
ないです。
```
※変数の値が空だった場合に、デフォルト値が表示される。

-------------------------

### フォーマットを指定する
```html:テンプレートファイル
{$smarty.now|date_format:"%H時%M分"}
{$smarty.now|date_format:"%H:%M:%S"}

// 結果
10時10分
10:10:10
```
※`smarty.now` は現在時刻を表します

-------------------------

### if文
```php:phpファイルで文字列を渡す
$smarty->assign("hoge", "abc");
```

```html:テンプレートファイルで文字列を受け取る
{if $hoge == "123"}
  123です。
{elseif $hoge == "abc"}
  abcです。
{else}
  当てはまりません。
{/if}

// 結果
abcです。
```

-------------------------

### foreach
```php:phpファイルで文字列を渡す
$array = ["a", "b", "c", "d", "e"]
$smarty->assign("hogehoge", $array);
```

```html:テンプレートファイルで文字列を受け取る
{foreach from=$hogehoge item="hoge"}
  {$hoge}です。
{/foreach}

// 結果
aです。bです。cです。dです。eです。
```
※`from=phpファイルで指定した変数名` , `item=foreach内で使用する名前` のように書く。
foreach内では `item` で指定した名前の先頭に `$` をつけて、 `{}` で囲む。

-------------------------

### メモ書き（コメントアウト）
```html:テンプレートファイルで文字列を受け取る
{*メモをここに書く*}
```
※メモとして残しておきたい文を `{*` と `*}` で囲む。（開発者のメモなど）
Wireguardで構成したVPN経由でUbuntu20.04(xrdp)へRDP接続するとブラックスクリーンになる問題の対応方法

## はじめに
Ubuntu 20.04上で動作するxrdpに対して、Wireguardで構成したVPN経由でリモートデスクトップ(RDP)接続を行おうとすると、以下のようにブラックスクリーンとなる場合があります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/536be431-8a75-9317-ac0e-c79569d5a656.png" width="500">

しかし、VPNを経由せずにSSHポートフォワーディングでRDP接続した場合は、問題なく接続できます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9af5a711-e132-dee5-93f8-70a8e33ef69b.png" width="500">

また、WANとなる回線を変更すると（例えばフレッツ光→CATVやNUROなどに変更すると）、VPN経由であっても問題なくRDP接続できる場合があります。

以上のような事象が発生している場合、Wireguardの設定によって事象が生じている可能性があります。

## 原因
MTUがデフォルト値の場合や、回線の上限を超えた値が設定されている場合、上記のようにVPN(Wireguard)経由のRDP接続に失敗する場合があります。

## 対応
Wireguardの設定ファイル ( `/etc/wireguard/wg0.conf` など)の `[Interface]` に対して `MTU=1420` （ `1420` の値は、回線に応じて適切な値を調整）を追加し、Wireguardを再起動することで、事象が解消されます。

```
[Interface]
Address = <Wireguardの接続元IPアドレス>
ListenPort = <Wireguardのポート>
PrivateKey = <接続先の公開鍵>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
MTU=1420

[Peer]
PublicKey = <接続元の秘密鍵>
PresharedKey = <事前共有鍵>
AllowedIPs = <許可IPリスト>
Endpoint = <接続先IPアドレス:ポート>
```

なお、Wireguardに限らず他のVPNプロトコル（OpenVPNやIPSecなど）においても同様の事象が発生する可能性があります。そのような場合は、同様にMTUを調整することで事象解消が期待できます。

本ページにたどり着いた方の中には、Googleなどで「xrdp blackscreen」や「xrdp 真っ黒」などのキーワードで検索し、そこから得られた結果をもとにいろいろと試された（しかしどの方法を行っても事象が解消されなかった）方もいたものと思います。また、ブラックスクリーンでありながらもRDP接続が一応確立するため、アプリケーションの問題（設定の不備やパッケージ更新の影響等）と判断してしまい、ネットワークの問題に気づくまでに時間を要した方もいたのではないかと思います（中途半端に繋がってしまうところが、この問題の質の悪いところです）。

もしVPN経由でUbuntu等のLinuxに対してRDP接続を行おうとして事象が発生している場合は、ぜひ本ページの内容をお試しください。
CloudKitで自動連携されない問題の対策　CloudKit - "Invalid bundle ID for container"

CloudKitを用いてCoreDataをクラウドに自動バックアップしようとしたができない場合があった。

デバッグ画面を眺めていたら、「Invalid bundle ID for container」とあったのでこのエラーが出た場合の対策をメモしておく。

内部で紐付けがうまくいってないのか分からないけどこれで上手くいった！

## 対策
① Xcodeでコンテナの選択を解除する
② developer.apple.comでコンテナの選択を解除し、保存する

Certificates, Identifiers & Profiles→Identifiersから対象のアプリを選択すれば以下のような画面が現れる。
Editからコンテナの選択を解除できる

![Screen Shot 2022-05-02 at 15.35.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426420/76c7c1ba-d32f-e25e-6739-6a5834dc1a3f.png)

③ 2で選択を解除したコンテナを再度選択し、保存する
④ 全く同じコンテナ名でコンテナを作成する（新しくコンテナが作成されるわけではない）
⑤ Xcodeで再度コンテナを選択する

## 参考
https://stackoverflow.com/questions/46144170/cloudkit-invalid-bundle-id-for-container
Java コレクションについてまとめる

備忘録
## ArrayList
Listとは、配列と同じようにインデックス番号の順序に要素を管理するコレクション
Listは、重複した要素を保持できる

配列との違いは、オブジェクト生成時に要素数を指定しなくてよい

### add
- 配列ver

```java
// 生成時要素数は3
int[] nums = new int[3];
nums[0] = 3;
nums[1] = 6;
nums[2] = 1;

for(int value : nums) {
    System.out.println(value);
}
```
- ArrayList

```java
// 生成時中身は空
List<Integer> list = new ArrayList<>(); 

// 指定しない場合は末尾に追加
list.add(3);
list.add(6);
list.add(1);

// 位置を指定して要素を追加する
list1.add(1, 999);

for (int value : list) {
    System.out.println(value);
}
```

### get
- 配列

```java
int num = nums[1];
```

- arraylist

```java
 int num = list.get(1);
```

### remove
- 配列
機能なし

- arraylist

```java
list.remove(1);
```

### size
要素数を取り出す
```java
System.out.println(list.size());
```

## map
Mapとはキーと値の組み合わせで要素を管理するコレクション
キーは重複して保持できないが値の重複はできる


```java
Map<String, String> johnDoe = new HashMap<>();
johnDoe.put("name", "John Doe");
johnDoe.put("gender", "male");
johnDoe.put("hobby", "programming");
johnDoe.put("favorite_food", "apple");
```

- HashMapの生成
- 要素の追加 (put)
- 要素の取り出し (get)
- 要素を全て取り出す (拡張for文使用)
- 要素の削除 (remove)
- 要素数の取得 (size)

### 取り出し
```java
public class HashMapEntrySample {
public static void main(String args[]) {
    Map<String, Integer> numOfUser = new HashMap<>();
    numOfUser.put("A駅", 100000);
    numOfUser.put("B駅", 130000);
    numOfUser.put("C駅", 20000);
    for (Entry<String, Integer> entry : numOfUser.entrySet()) {
       String key = entry.getKey();
       int value = entry.getValue();
       System.out.println(key + "の乗降客数：" + value + "人");
    }
 }
}
```

## set
Setとは、重複のない要素を管理するコレクション

```java
Set<String> ipAddresses = new HashSet<>();
 
String[] accessLog = { // 1日分のアクセスログ
    "202.4.x.x", "202.4.x.x", "49.33.x.x", "202.4.x.x", "49.33.x.x", "222.34.x.x", "180.8.x.x", "202.4.x.x",
    "222.34.x.x", "83.217.x.x", "222.34.x.x", "49.33.x.x" };

for (String ipAddress : accessLog) {
    // セットに全てのアクセスログを1つずつaddする。
    ipAddresses.add(ipAddress);
}
```

## ネスト
```java
ArrayList<ArrayList<Integer>> twoDimenArrayList = new ArrayList<>();
 
ArrayList<Integer> row0 = new ArrayList<>();
row0.add(10);
row0.add(20);
row0.add(30);
ArrayList<Integer> row1 = new ArrayList<>();
row1.add(100);
row1.add(200);
row1.add(300);

twoDimenArrayList.add(row0);
twoDimenArrayList.add(row1);

for (ArrayList<Integer> arrayList : twoDimenArrayList) {
  for (Integer integer : arrayList) {
    System.out.println(integer.intValue());
  }
}
```

### 備考
```
LinkedList という仲間が同様の機能で、特定のシチュエーションで高速で動作
LinkedListは、 要素の追加や削除が頻繁に行われる ときに有用なクラスです。
```
JS7® JOCコックピット Git連携 記事公開

JS7® V.2.2.2よりGit連携機能のサポートが追加され、さらにV.2.3.0より、JOCコックピットより、Git操作できるようになり、ジョブ定義のCI/CDが可能になりました。

弊社山下が連携方法記事を公開しましたのでお試しください。
https://qiita.com/Yoshitami/items/4c71039acb401bfca660
薬価を調べるLINE公式アカウントを短時間で作ってみた

# 作ったもの
薬価（薬の値段）を調べることが出来るLINE公式アカウントを作ってみました。
短時間である程度動くものを作ることを目的として、いろいろ拘らずにサクサクと動くものを作り上げました。
尚、薬の情報は、[薬価サーチ](https://yakka-search.com/)のデータを使用しています。

実際に作成したものは以下になります。

https://protopedia.net/prototype/3007

# システム構成
LINE公式アカウントで、「薬の名前」を入力すると、薬価サーチの検索結果のURLがかえってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21408/dc3b55db-ed1a-2215-0daf-8b706d80bfac.png)


# 開発全体の流れ

1. LINE公式アカウントを開設します
1. Azure上で Azure Functions の環境を構築します
1. Azure Functionsを使って、薬価サーチの検索URLをリプライする処理を実装します
1. LINE公式アカウントの「チェンネルトークン」「アクセストークン」をコード内で使用します
1. LINEのWebhookにAzure Functionsの関数読出しURLを設定します

以上で完成です。
慣れている人であれば、約１～２時間程度で構築完了です。

# ポイント
いろいろしっかり実装を考えると難しい課題も出てきますが、今回は、LINEで入力された薬の名前に対して、[薬価サーチ](https://yakka-search.com/) の検索結果のURLをリプライするというシンプルな作りとします。なので、薬の名前ではないものも入力できて、リプライも来ますが、「データが見つかりませんでした」というURLがかえってきます。ただ、薬の名前をちゃんと入力すれば、薬の情報にすぐにたどり着けますし、スマホなので音声入力とかで薬の名前を読み上げれば、薬価の情報が帰ってくるので、割りと使いやすいのではと思っています。

# 詳細１：LINE公式アカウントの開設
LINE公式アカウントの開設方法はいろいろなサイトで紹介されていますが、今回の方法では LINE Messagging API を使用して薬価サーチの検索結果をLINE側にリプライする為、以下のサイトが良くまとまっていて分かりやすいと思います（LINE公式アカウントの開設や、Azure Functions の設定までが詳しく記載されています）。

https://qiita.com/RyogaTakao/items/a86522d560178f83652c

# 詳細２：Azure Functions を使ったURLのリプライメッセージ
「薬価サーチ」の検索結果は、以下のようなURLで取得することが出来ます（hogehoge で検索した場合）。
```
https://yakka-search.com/index.php?s=hogehoge&stype=1
```

その為、LINEから受け取ったメッセージ（薬の名前）を、上記の「hogehoge」の部分に入れて、URLをリプライする処理を、Azure Functions 上で実装します。上記の記事の続編ですが、以下の記事の場合は、受信したメッセージに絵文字を付けて返信しているので、URLを処理する参考になると思います。

https://qiita.com/RyogaTakao/items/041fa30e967aa73b5c18

# 最後に
今回は、触ったことがあるユーザが多いLINEを入り口として、薬価サーチの検索結果と連動させることで、手軽に薬価の情報を調べられる公式アカウントを作成してみました。
あとは、URLパラメータを使って、検索結果を表示するサイトは結構多い気がするので、こういった方法でも簡単に検索用ボットが作成できることが分かりました。LINEを入り口にして少し便利にするようなことにはアイデア次第でいろいろ使えそうな気もしています。
Ref, Refのフォワーディングを理解する



## 役割
 - reactの要素(子要素)にアクセスする方法の一つ。
 - 一般的には、親から子にpropsを渡して子をレンダリングするが、その方法以外で子にアクセスする。親から子を命令型のコードを使って操作する。

## いつ使うのか
 - フォーカス、テキストの選択、メディアの再生の管理
 - アニメーション発火
 - サードパーティのDOMライブラリとの統合

## Refの使い方
 - 特定の操作で反応させたいDOMにアクセスするために使う。

##### 関数コンポーネントにはrefを渡すことができない。
 - なぜ？
  - 関数コンポーネントはインスタンスを持たないobjectのため。
  - Refは通常、コンポーネントの構築時にインスタンスプロパティに割り当てられる
    - [Refを作成する](https://ja.reactjs.org/docs/refs-and-the-dom.html#creating-refs)

#### どうすれば子をrefで操れるの？
 - インスタンスを持たない関数コンポーネントに対してRefを使いたい場合、 `forwardRef` を利用する or クラスコンポーネントに書き換える。

```
*公式引用
- React 16.3 以降を使用している場合[ref のフォワーディング](https://ja.reactjs.org/docs/forwarding-refs.html) を使用するのがよい
- Ref のフォワーディングを使うと、コンポーネントは任意の子コンポーネントの ref を自分自身の ref として公開できるようになります
```

## フォワーディングを試す

子供のコンポーネントとして `FancyButton` を用意した。
関数コンポーネントなので、通常では親からrefを渡すことはできない。これはDOM同士を依存させないためのReactの仕様となる
とはいえ、様々な箇所で再利用可能なボタンやinputコンポーネントを作成する場合、refをとれたほうが都合がよい場合が多い。

```tsx
const RefChild = () => {
  const ref = useRef<HTMLButtonElement>(null!)

  const catchRef = () => {
    console.log(ref.current) // FancyButton
  }
  return (
    <>
      <button onClick={catchRef}>親ボタン</button>
      <FancyButton ref={ref} type="submit"><span>子供ボタン</span></FancyButton>
    </>
  )
}

type FancyButtonElementType = HTMLButtonElement | null
type FancyButtonProps = JSX.IntrinsicElements['button']

const FancyButton = forwardRef<FancyButtonElementType, FancyButtonProps>((
  props,
  ref
) => {
  return (
    <div>
      <button ref={ref} data-fancy='fancy2'{...props} />
    </div>
  )
})

FancyButton.displayName = 'FancyButton'
```

下記スクショの通り、親ボタン押下にて、子コンポーネントのbuttonの情報を取得できた。
forwardRef の型に関しての理解はもっと深める必要あり。

![スクリーンショット 2022-05-02 15.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206790/261ac5e7-b6e4-b8eb-6c61-7549c32d53a7.png)
Bootstrapとは？

# bootstrapについて学んだこと
## bootstrapとは
HTML／CSS／JavaScriptから
構成される最も有名なWEBフレームワーク
###### フレームワークとは
概念的な意味で、何かの枠組みのこと。雛形等
可視化できるもので表現すると
履歴書に引いてある罫線、項目。
雛形を導入することで工数が減る手伝いをしてくれる。

## Bootatrap　メリット
##### コーディング量を減らせる
 HTMLファイルととCSSファイル２つに記述しなければならない場合もBootstrapで予め用意されたクラスというものを、HTMLファイルに書くだけで簡単に作成することができます。

##### レスポンシブ対応のデザインを簡単に作れる
レスポンシブ対応とは、PCやスマートフォン、タブレットなど様々なデバイスに適したWebページを制作することを言います。

##  Bootstrap デメリット

##### 画一的なデザインになりがち
近年Bootstrapを使用している人は多数いますので、自分なりにカスタマイズしないと、有益なものになりにくくなります。カスタマイズするには、CSS や JavaScriptの知識が必要になります。


# この記事の参考文献

##### Webデザインの知識がなくてもOK！Bootstrapの使い方【入門者向け】
https://techacademy.jp/magazine/6270
##### Bootstrapとは？メリットとデメリットそれぞれ3つを解説
https://www.acrovision.jp/career/?p=2852#:~:text=Bootstrap%E3%81%A8%E3%81%AF%E3%80%81web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3,%E3%81%93%E3%81%A8%E3%81%8C%E3%81%82%E3%81%92%E3%82%89%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82
AIX (VIOC)の fcs が どのVIOS のfcs, vfchost に繋がっているかを確認する方法

##### はじめに

AIX (VIO Client) から、VIOS の fcs、vfchost のマッピングが AIX から確認できます。
今まででは VIOS や HMC を含めて確認していましたが、この方法ではAIX (VIOC)からのみで確認が可能す。

他の方から以下のリンク教えていただいた内容ですが便利なので情報共有でこちらにも記載します。

・Which VIOS serves my Virtual FC adapters?
http://gibsonnet.net/blog/cgaix/html/lsviofcs.html



---
##### 環境

VIOS - VIOC 構成

・AIX 7.2 TL5SP3 以降
・VIOS 3.1.3.00 以降


---
##### 確認方法

/proc/sys/adapter/fc/fcsX/hostinfo の内容を確認します。
fcs の数だけ実施


```
# export myfcslist=`cd /proc/sys/adapter/fc ; ls -d fcs*`

# for i in $myfcslist
> do
> echo $i
> cat /proc/sys/adapter/fc/$i/hostinfo
> echo
> done
```

実行結果の出力

```
fcs0
VFC client adapter name                   : fcs0
Host partition name  (VIOS)               : VIOS1
VFC host adapter name                     : vfchost0
VFC host adapter location code            : U9009.22A.XXXXXXX-V1-C2
FC adapter name on VIOS                   : fcs3
FC adapter location code  on VIOS         : U78CD.001.FZXXX49-P2-C2-T1

fcs1
VFC client adapter name                   : fcs1
Host partition name  (VIOS)               : VIOS2
VFC host adapter name                     : vfchost0
VFC host adapter location code            : U9009.22A.XXXXXXX-V2-C3
FC adapter name on VIOS                   : fcs1
FC adapter location code  on VIOS         : U78CD.001.FZXXX87-P2-C5-T1

fcs2
VFC client adapter name                   : fcs2
Host partition name  (VIOS)               : VIOS1
VFC host adapter name                     : vfchost1
VFC host adapter location code            : U9009.22A.XXXXXXX-V1-C3
FC adapter name on VIOS                   : fcs1
FC adapter location code  on VIOS         : U78CD.001.FZXXX87-P1-C2-T1

fcs3
VFC client adapter name                   : fcs3
Host partition name  (VIOS)               : VIOS2
VFC host adapter name                     : vfchost1
VFC host adapter location code            : U9009.22A.XXXXXXX-V2-C4
FC adapter name on VIOS                   : fcs3
FC adapter location code  on VIOS         : U78CD.001.FZXXX58-P1-C2-T1
```

上の例では VIOC の fcs0 は VIOS1 の vfchost0 と fcs3 に紐づいています。





ご参考まで、以上です。
【リファレンス】よく使うGitコマンド

### 編集済みファイルをステージング
```
git add -A
```

### ステージングされたファイルをコミット
```
git commit -m "comment"
```

### リモートリポジトリにアップ
```
git push origin <ブランチ名>
```

### リモートリポジトリからダウンロード
```
git pull origin <ブランチ名>
```

### ブランチ切り替え
```
git checkout <ブランチ名>
```

### 管理対象から指定したファイルのキャッシュを削除
```
git rm --cache <ファイル名>
```

### 管理対象から指定したディレクトリのキャッシュを削除
```
git rm --cache -r <ディレクトリ名>
```

### 管理対象から全てのファイルのキャッシュを削除
```
git rm --cache -r .
```

### 作業ブランチに指定したブランチをマージ
```
git merge <マージしたいブランチ名>
```

### 作業ブランチに指定したコミットのみをマージ
```
git cherry-pick <コミットID>
```

### 一時的に退避
```
git stash
```

### 一時的に退避したものを適用
```
git stash pop
```
moby-engineインストールでエラー

# 事象

[reComputer Jetson-10-1-H0](https://www.seeedstudio.com/Jetson-10-1-H0-p-5335.html)にAzure IoT Edgeをインストール中、[moby-engineインストール](https://docs.microsoft.com/en-us/azure/iot-edge/how-to-provision-single-device-linux-symmetric)で下記エラーが発生した。


```bash
$ sudo apt-get update; sudo apt-get install moby-engine
...
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 moby-engine : Depends: moby-containerd (>= 1.4.3) but it is not going to be installed
               Depends: moby-runc (>= 1.0.2) but it is not going to be installed
               Recommends: moby-cli but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
```

# 解決方法

依存パッケージを順にインストールすればOK。

```bash
$ sudo apt-get install moby-runc
$ sudo apt-get install moby-containerd
$ sudo apt-get install moby-engine
```

# 参考

https://github.com/Azure/iotedge/issues/5011
C++開発であると便利な機能

### はじめに
C++であると便利な機能を書きたいと思います。
詳細については都度追加していこうと思います。

### 機能一覧（随時追加予定）
・バイナリデータをログに出力
・処理時間を計測

### 処理時間を計測する
アプリの開発をしていと単体試験の時点では問題ないのに、
結合試験や、システム試験などでデータ量が増えたりした場合に、
処理が重くなって、どうしよう。。って事がよくあります。

そういう場合に、どこで処理が遅いかを調べる為に使います。
タイマー開始⇒重い処理⇒タイマー停止⇒停止から開始の時間をログ出力という流れです。

重い処理をどうやって軽くるするんだ？という問題は色々考えないといけないです。。

■手順：
VisualStudio2019を起動しファイル＞新規作成＞プロジェクトを選択します。
コンソールアプ（C++）を選択し次へを選択します。
適当にプロジェクト名を決めて作成を選択します。
ソースコードを書いて実行します。

```diff_cpp:main.cpp
#include <iostream>
#include <windows.h>
#pragma comment(lib, "winmm.lib")
int main()
{
    // 10回実行
    for (int i = 0; i < 10; i++)
    {
        DWORD startTime = timeGetTime();

        // 重い処理
        for (int j = 0; j < 1000 * 1000 * 1000; j++)
        {
            int a = 0;
            a %= 2;
        }

        // 掛かった時間を表示
        printf("number:%d, time:%d\n", (i + 1), (timeGetTime() - startTime));
    }
}
```

■結果
```
number:1, time:1669
number:2, time:1625
number:3, time:1641
number:4, time:1612
number:5, time:1623
number:6, time:1610
number:7, time:1663
number:8, time:1640
number:9, time:1590
number:10, time:1647
```
定期的に全EC2サーバを停止する設定

# 内容
AWS検証環境でEC2の停止を忘れてしまうことがあるので、全EC2サーバを1日1回停止する運用をいれます。
EventBridgeの「EC2 StopInstances API呼び出し」を使用しようと思いましたが、全てのインスタンスIDを指定する方法が分からなくlambda関数を作成しました。

# コード
同一AWSアカウント内で起動中の全EC2サーバを停止します。

```python
import boto3

client = boto3.client('ec2', region_name = 'ap-northeast-1')

def lambda_handler(event, context):
    ec2_list = client.describe_instances()
    for ec2_reservation in ec2_list['Reservations']:
        for ec2_instance in ec2_reservation['Instances']:
            ec2_instance_id = ec2_instance['InstanceId']
            ec2_instance_state = ec2_instance['State']['Name']

            if ec2_instance_state == 'running':
                response = client.stop_instances(InstanceIds = [ec2_instance_id])

```

# 設定方法
* Lambda用のIAMロールを作成します。（EC2アクセス用）
* Lambda関数を作成します。
![lambda1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/e965e818-7b95-ea99-d465-ac22560bbbff.png)

* EventBridgeで定期実行の設定をします。
![lambda2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/e3587855-e7f6-1ffb-1b11-a5f7315ea13e.png)
【使い方】SchemaSpy

SchemaSpyを使ったDB設計書を出力する方法はいくつかありますが、Dockerを利用する方法をお勧めします。

# 公式サイト
https://schemaspy.org/

# 前提
- Dockerが利用できること

# 準備

schemaspy.propertiesを用意します。

```properties:schemaspy.properties
# データベース種類
# mysql（MySQLの場合）
# pgsql（PostgreSQLの場合）
schemaspy.t=mssql
# JDBCドライバファイルパス
schemaspy.dp=path/to/drivers
# ホスト名
schemaspy.host=localhost
# ポート番号
schemaspy.port=1433
# データベース名
schemaspy.db=db_name
# ユーザ名
schemaspy.u=database_user
# パスワード
schemaspy.p=database_password
# 出力先（Docker利用の場合は指定不要）
#schemaspy.o=path/to/output
# 出力対象スキーマ名（複数の場合はカンマ区切り）
schemaspy.s=dbo
```

# 実行

以下のコマンドを実行する。

```
docker run -v "/path/to:/output" -v "/path/to/schemaspy.properties:/schemaspy.properties" --rm --net="host" schemaspy/schemaspy:latest
```

|オプション|説明|
|:--|:--|
|-v "/path/to:/output"|/path/toに出力したいディレクトリ|
|-v "/path/to/schemaspy.properties:/schemaspy.properties"|/path/toに上記で作成したプロパティがあるディレクトリ|
|--rm|実行後、コンテナを削除|
|--net="host"|コンテナのネットワークをホストと共有（DBをDocker上で稼働している場合に必要）|
Homebrew でインストールできる Scheme 処理系リスト

Homebrew でインストールできる Scheme 処理系をリストアップしてみました。もちろん処理系はこれ以外にも沢山あるわけですが、ぱっと思いつく限りというところです。並び順は直近一年間のインストール数の降順にしてあります。

|処理系|Installs (365 days)|最終リリース日(2022/05/02 現在)|対応規格|License|
|---|---|---|---|---|
|[Guile](https://formulae.brew.sh/formula/guile)|2747689|2022-02-11 (3.0.8)|R5RS/R6RS|LGPL-3.0-or-later|
|[MIT/GNU Scheme](https://formulae.brew.sh/formula/mit-scheme)|4501|2021-03-08 (11.2)|R7RS (small)|GPL-2.0-or-later|
|[Chez Scheme](https://formulae.brew.sh/formula/chezscheme)|2496|2022-04-21 (9.5.8)|R6RS|Apache-2.0|
|[Gauche](https://formulae.brew.sh/formula/gauche)|1578|2021-12-28 (0.9.11-p1)|R7RS|BSD-3-Clause|
|[CHICKEN](https://formulae.brew.sh/formula/chicken)|1185|2021-11-18 (5.3.0)|R5RS/R7RS|BSD-3-Clause|
|[Gambit Scheme](https://formulae.brew.sh/formula/gambit)|459|2022-01-03 (4.9.4)|R7RS|Apache-2.0|
|[Chibi-Scheme](https://formulae.brew.sh/formula/chibi-scheme)|204|2021-05-11 (0.10)|R7RS (small)|BSD-3-Clause|
|[Sagittarius](https://formulae.brew.sh/formula/sagittarius-scheme)|77|2021-09-03 (0.9.8)|R6RS/R7RS|BSD-3-Clause|

インストール数だけで見れば、Guile のインストール数が他を圧倒していました。GNU Makeからの依存があるからでしょうか。Scheme 処理系はものによって用途もそれぞれなので、好きなものを使えばよいのだと思います。
[Simulink]連続時間で相補PWM波形を出力するモデル

自分用のメモだけど、使い勝手の良いモデルが公式に無い（見つけられないだけ？）ので良かったらどうぞ。

### 考え方
![kangaekata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533492/69accbdb-5e90-64d5-e1ef-a087fea59b1a.png)
三角波が点線よりも上にあるのか下にあるのかを判定すれば良い。

### ブロック配置
![triangle_wave_generator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533492/f7338ad7-bda2-0545-4aad-d10b2da2e1a0.png)
![complementary_pwm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533492/e6b2e88e-ef80-e97a-7aec-a16f4e2ae147.png)
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2533492/b151a0b5-b6a5-41d6-7a2c-a22ab6bd82c2.png)
「command not found: rubocop」のエラーが出てしまい、rubocopコマンドが実行できない

# 背景
- 下記の手順でRubyのコード解析ツール「Rubocop」の利用を試みたが、表題のエラーが出てしまい実行できませんでした。

```:Gemfile
group :development do
  gem 'rubocop'
  gem 'rubocop-rails'
```
```
$ bundle install
```
```
$ rubocop
zsh: command not found: rubocop
```

# 解決策

以下のコマンドを実行したところ、`rubocop`コマンドが使えるようになりました。
```
$ rbenv rehash
$ rubocop
Inspecting 44 files
.
.
.
```
- rbenvを利用している場合、`bundle install`を実行しただけではshimディレクトリが更新されないため、実行できないようです。
- `rbenv rehash`を実行することで、どのディレクトリにいても`rubocop`コマンドが使えるようになりました！

参考になれば幸いです。
VisualStudioでPythonを使う

#### 使用する環境
Windows10
VisualStudio2019

#### セットアップ
VisualStudioを起動します。
表示＞その他のウィンドウ＞Python環境を選択します。
環境を追加を選択します。
Conda環境を選択します。
1つ以上のAnacondaパッケージ名にnumpy pandas openpyxlを入力します。
作成を選択します。
Python環境ウィンドウに追加した環境が表示されます。
これで、pandas、numpyなどが使用可能になりました。