OmniAICreator/Qiita-1.07M huggingface dataset:
matlabのData Acquisition Toolboxを使う④ Analog Discovery 2

 アナログ入力を手軽に得る方法に、Analog Discoveryを使う方法があります。現在Analog Discovery2（写真左）が市販されています。もうすぐAnalog Discovery Proが発売されます。
![AD1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/470d1ef7-07ae-4e43-4a8c-a406fa0f21af.png)

　Analog Discovery2は、オシロスコープだけではなく、スペアナやネットワーク・アナライザなど多くの機能が使えます。
![ad102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/33dd1f28-1047-ad65-74fb-c9c5eaa85633.png)

###Analog Discovery2の機能を使う準備
　Data Acquisition Toolbox（有料）に加えてData Acquisition Toolbox Support Package for Digilent Analog Discovery Hardware（無料?）をインストールします。
![ad103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/1405a0bc-f0cc-272f-4047-b704a79e2ee7.png)
　Analog Discovery2のソフトWaveforms のバージョンは3.12.2です。ひとつ古いままです。

　Data Acquisition ToolboxのアプリAnalog Input Recorderからは探し出してくれませんでした。ライブエディタで直接記述します。

　ファンクション・ジェネレータFGX-2005の出力を、Analog Discovery2のCh1につないでいます。
###プログラム

　Analog Discovery2をUSBケーブルでPCにつなぎます。

```matlab
daqlist("digilent")
```

で探してきます。
　ch1入力の設定をします。±2.5Vレンジです。

```matlab
dq = daq("digilent");
ch_in = addinput(dq, "AD1", "1", "Voltage");
ch_in.Name = "AD1_1_in";
dq.Rate = 1e6;
ch_in.Range = [-2.5 2.5];
```

　データを1秒間読み出します。全部プロットすると波形がわからないので、100個ほど取り出しています。

```matlab
samplingTimes = 1;
AD1_1_in = read(dq, seconds(samplingTimes))
%summary(AD1_1_in)
data = AD1_1_in(10:100,:)

plot(data.Time, data.AD1_1_in);
xlabel('時間 [秒]');
ylabel('電圧 [V]');
title(['Clocked Data Triggered on: ' datestr(data.Time(1))]);
grid on
```

　ファンクション・ジェネレータは20kHz、デューティ20%の方形波です。ほぼ正しく取り込めています。

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/a4ea1b8c-c287-e69e-a256-6c7ee316fe8f.png">


　FFTを掛けます。fft関数を使うとマイナスの値も計算するので、プラス側だけのデータを取り出しています。

```matlab
fs = 1000000;
data0 = AD1_1_in.AD1_1_in;
Y = fft(data0);
L = length(data0);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);

f = fs*(0:(L/2))/L;
plot(f,P1) 
title('Single-Sided Amplitude Spectrum of X(t)')
xlabel('f (Hz)')
ylabel('|P1(f)|')
grid on
```

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/f693986c-0568-1965-b6d3-21fb1c6b475e.png">

両対数グラフにします。

```matlab
loglog(f,P1)
xlabel('f (Hz)')
ylabel('|P1(f)|')
grid on
```

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/939de52a-1923-a281-e292-07dd401f61c2.png">

　左右を広げました。
![ad107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/a66c9106-0b27-a4f4-ed87-275fdd4a5b45.png)






（※）matlabはR2020bアップデート4です。
2列のCollectionViewの余白を埋めて横幅いっぱいにする（伝われ

Storyboardだけでは固定値しか設定出来ない関係で不可。古いやり方でAutoResizingというのもあったそうだが、[今は基本は3つくらいのやり方に集約されているようだ](https://techlife.cookpad.com/entry/2017/06/29/190000)。

Storyboardを使っていて、ViewControllerの中にCollectionViewとCellを入れている場合（Xibを使っていない）場合はデリゲート`UICollectionViewDelegateFlowLayout`を使うのがよさそう。
![スクリーンショット 2021-01-26 16.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/c3bb66ae-43e2-0a81-297f-39fb2844fbb2.png)


```swift
extension ViewController: UICollectionViewDelegateFlowLayout {
	
	func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
		let spaceForCells: CGFloat = 3
        let cellWidth: CGFloat = (self.view.bounds.width / 2) - (spaceForCells / 2)
		let cellHeight: CGFloat = (cellWidth * 235 / 156)
        return CGSize(width: cellWidth, height: cellHeight)
    }
	
	func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
		return 3
	}
}
```

##Cellの横幅
まずCellの横幅は画面横幅の半分から余白分を引いた長さになる。ただし、デフォルトでは左右それぞれにCellがひっついているレイアウトになり、1つ目のCellは右側に余白ができ、2つ目のCellは左側に余白ができる。なので引くべき値はStoryboard上での`Min Spacing For Cells`にあたる値の半分となる。
![スクリーンショット 2021-01-26 17.08.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/ad99eb20-f183-168c-b4c4-c8312fd21776.png)
（↑セクションの左のセルは右余白のみが、右のセルは左余白のみができる）

ちなみに余白を引かずに画面横幅のピッタリ半分にしてStoryboardで`Min Spacing For Cells`を0以上とかに設定しちゃってると1列になっちゃう。

##Cellの縦幅
今回はすべてのCollectionViewの縦横比を固定したい。インスタのストーリーなどは「1080 x 1920」の「9:16」だが、最低3列は見えてほしかったので「156:235」にした。ここは任意で変えてほしい。


##参考リンク

- https://qiita.com/Coolucky/items/a709802ffa526098c370
p5.jsでラインで結ばれたパーティクルを実装する

ラインで結ばれたパーティクルの実装の仕方を紹介します。ちょっと言葉でうまく説明できないので、画像をみてみましょう。

![wip_p5js_210126.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241879/a76bd871-591d-06e6-5b46-40a3fe16f7d3.gif)

Webサービス系とか情報、未来を連想させるイメージとしてよく背景に設定されていたりしますよね。

**コード**
https://editor.p5js.org/mtoutside/sketches/sEhRVPhl

## 実装のポイント
今回はパーティクルを表示させるためクラスを使います。コンストラクターのほか4つの関数を持ちます。

- update -> 描画を更新する
- draw   -> 描画する
- edge   -> 境界線の判定
- checkParticles -> パーティクル同士の距離を計算して、パーティクル同士が一定距離近づいたらラインで結ぶ


## コード
```particle.js
const particles = [];
function setup() {
  createCanvas(window.innerWidth, window.innerHeight);
  
  const particlesLength = Math.floor(window.innerWidth / 10);
  
  for(let i = 0; i < particlesLength; i++) {
    particles.push(new Particle());
  }
}

function draw() {
  background(50, 90, 180);
  particles.forEach((p, index) => {
    p.update();
    p.draw();
    p.checkParticles(particles.slice(index));
  });
  
}

/*
 * パーティクルクラス
 */
class Particle {
 constructor() {
   this.pos = createVector(random(width), random(height)); // 画面上のランダムの位置を初期ポジションに設定
   this.vel = createVector(random(-3, 3), random(-3, 3));  // -3 ~ 3 の値でパーティクルが動く速度を設定
   this.size = 10; // パーティクルのサイズ
 }

 update() {
   this.pos.add(this.vel); // パーティクルの位置に速度を足す
   this.edge();
 }
  
 draw() {
   noStroke();
   fill('rgba(255, 255, 255, 0.5)');
   circle(this.pos.x, this.pos.y, this.size);
 }
  
 // 境界線判定
 edge() {
   // 画面の左右端までいったら進む方向を反転
   if(this.pos.x < 0 || this.pos.x > width) {
     this.vel.x *= -1;
   }
   // 画面の上下端までいったら進む方向を反転
   if(this.pos.y < 0 || this.pos.y > height) {
     this.vel.y *= -1;
   }
 }
  
 checkParticles() {
    particles.forEach(particle => {
      // 自分の位置と他のパーティクルとの距離を求める
      const d = dist(this.pos.x, this.pos.y, particle.pos.x, particle.pos.y);

      // 他のパーティクルとの距離が120以下ならラインで結ぶ
      if (d < 120) {
        stroke('rgba(255, 255, 255, 0.1)');
        line(this.pos.x, this.pos.y, particle.pos.x, particle.pos.y);
      }
    });
  }
}
```


## 参考
[Particles Effect With P5.js](https://youtu.be/H-9jCNhLe-Q)
Dynamics 365 設定方法まとめ(リンク集)

向井です。

いくつかDynamicsの設定方法に関する記事を書いたので、こちらにリンクをまとめておきます。

[Dynamics 365 の Outlook 連携の方法](https://qiita.com/kumukai/items/89d1d503766a06a2ddb0)

[Dynamics 365 の Teams 連携の方法](https://qiita.com/kumukai/items/7debb2f8db9b8f7d7d32)

[Dynamics 365 に自社のロゴやカラーを設定する方法](https://qiita.com/kumukai/items/ff387e7a2d4e53eea026)

[Dynamics 365 の表示形式の追加方法](https://qiita.com/kumukai/items/2e6d44e364ecf6f02bf8)
Unity2020でGradleビルドエラー

# ことの発端
ずっとUnity2019（1.5f1）でアプリを開発していたので、新規のアプリでUnity2020（2.1f1）を使ってみたくなった。Android向けにビルドしたところ、`CommandInvokationFailure: Gradle build failed.`とやらが出てビルドが成功しない。

ビルド時に複数エラーが出ていたが、主なのは下の2つ。

```
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':launcher:processReleaseResources'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > Android resource linking failed
```

```
CommandInvokationFailure: Gradle build failed. 
/${OpenJDK_PATH}/bin/java -classpath 
"${Gradle_PATH}/lib/gradle-launcher-5.6.4.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
```



# 調べたこと
独自のAndroidManifestを使っており、Assets/Plugins/Androidフォルダに置いて、Player Settings > Publishing Settings > Custom Main ManifestのチェックボックスもONにしている。

にも関わらず、ビルド失敗後Temp/gradleOut/launcher/src/mainのAndroidManifest（ビルド時に作られたAndroidManifest）には独自のAndroidManifestが反映されていない。

正しく動いていれば、ここに反映されるはず。
エラー内容で色々ggってみたが、他のSDKと競合してないか〜、カスタムのGradle Templateを定義して〜みたいなのが多かったが、どれも根本的な解決策に至らなかった。

# 解決策
~~Assets/Plugins/Androidフォルダに配置している`AndroidManifest.xml`を**`LauncherManifest.xml`**に書き換え、Player Settings > Publishing Settings > **Custom Launcher ManifestのチェックボックスをONにする**（Custom Main ManifestはOFFにする）。~~

### 【3/4 追記】
上記手法は場合によっては、Unityの定義に反する使い方になるため、解決策を修正。
また、上記解決策では実機確認の際にアイコンが2つ出てしまう、動作が安定しないなどの場合は下記を参照。

従来の`AndroidManifest.xml`の中からiconなどの情報を`LauncherManifest.xml`として外出しする。外出しする項目は[公式のページ](https://docs.unity3d.com/Manual/android-manifest.html)を参照。

Player Settings > Publishing Settings > **Custom Launcher Manifest と Custom Main ManifestのチェックボックスをONにする**

ビルドを再実行！

# 原因
どうやらUnity2019.3以降はGradle実行時にLauncherManifestとLibraryManifestという2つのManifestファイルを生成するらしい。詳細は[公式のページ](https://docs.unity3d.com/Manual/android-manifest.html)を参照。
従来はAndroidManifest1つ定義するだけで良かったのだが、項目によって分けられてビルド時にそれをマージする仕様に変わったことを知らなかったのが原因。

# それでもエラーが出る場合
### Minimum APIがどうこうのエラー
置き換えるLauncherManifestからminimum API Levelの指定を取り除く

### Gradle周りのエラーや上記対応ができない場合など
まず、[ここ](https://docs.unity3d.com/ja/2019.4/Manual/android-gradle-overview.html)で自分が使っているUnityに対応した**Gradleのバージョン**を調べる。
なんでUnity2020が書かれてないんだ・・・ちなみに2.1f1のGradleバージョンは5.6.4っぽい。
【追記】[英語バージョンのサイト](https://docs.unity3d.com/Manual/android-gradle-overview.html)に書かれてました。

次に、[ここ](https://developer.android.com/studio/releases/gradle-plugin?hl=ja#updating-gradle)でGradleバージョンに対応した**Gradleプラグインのバージョン**を調べる。
ややこしいというツッコミはなしで。

次に、Player Settings > Publishing Settings > Custom Base Gradle TemplateのチェックボックスをONにする。

Assets/Plugins/Androidフォルダに`baseProjectTemplate.gradle`なるものが生成されているのでそれを開き、dependenciesのclasspathのXの部分をさっきのGradleプラグインのバージョンに差し替える。

```
classpath 'com.android.tools.build:gradle:X.X.X'
```

再度ビルド。
これで動くようになればご喝采。
vim, viコマンドで保存、終了を行う。

はじめに
---
　vimコマンドでファイルを編集する際、意外とつまづく"保存して終了する"操作を解説していきます。

操作
---
 下記のコマンドを実行すると、下に表示した'コマンドモード'へ移る。
※カレントディレクトリにhello.pyのファイルが自動で作成される。

```
$ vim hello.py
```
![command_mode_F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056362/f0277fcd-e017-4e91-d1f3-8df86743faae.png)

vimには主に'コマンドモード'と'入力モード'がある。
ファイルを編集するには、現在の'コマンドモード'から'入力モード'へ移る必要がある。

キーボードの"i"をタイプすると下のような'入力モード'に移る。
下方に--INSERT--と表示されれば、'入力モード'に移っている。
'入力モード'でPythonのコードを入力した。
![insert_mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056362/8d4b2e2e-62df-98b3-51bc-d6aa61db9753.png)

さて、本題の保存と終了をするだが、それを実行するには'コマンドモード'へ戻る必要がある。
現在の'入力モード'の状態で、キーボードの"escキー"をタイプすると、--INSERT--の文字が消える。これで'コマンドモード'へ戻ってくることができた。
![command_mode_L.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056362/306bd8af-fa6d-f537-0e95-0de4bf6a533c.png)

あとは簡単。保存と終了のコマンドに関しては[こちら](https://qiita.com/hide/items/5bfe5b322872c61a6896)の記事を参考にするといいだろう。
'コマンドモード'でキーボードで":wq!"を入力し、キーボードのEnterボタンを押下するとvimが終了し、いつものターミナルに戻ってくる。
![last.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056362/029bd53b-4956-3822-e522-543e84384338.png)

あとは、Pythonのファイルを実行すれば、Hello World!と表示されたことだろう。

```
$ python hello.py
Hello World!
```

おわりに
---
vimの記事の多くはコマンドの話や操作方法について載っているが、肝心なモードとコマンドを両方記載したものが少ないと感じる。そして自分自身、'入力モード'で":wq!"をタイプしていたり、'コマンドモード'で入力しても何も表示されない！と感じていたことから、今回のような記事を書くことにした。
Rails6 Webpackerでmanifest.jsonがありませんのトラブルシューティング


## 環境

Ubuntu16.04.7 LTS
Windows10 + Vegrant
Rails 6.0.3

## トラブル内容

**rails new**した直前であれば、**rails s**で問題なく起動してくれるが、**rails g controller top index**で、コントローラとビューを作った後に、**rails s**すると、このようなエラーが出て来ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/f0b7ef85-1d06-4ab6-c88c-31b05c6d5c0e.png)
色々ググってみると、**rails webpacker:install**をして、webpackerを再インストールすればOKとの情報があるが、それでも上手くいかなかった場合はどうする？

## 解決内容
**application.html.erb**でエラーが出ているこれ１行をコメントにすればOKみたいです。自分もこれで解決しました。だがしかし、これが最終回答ではないようです。続きは参考URLを最後まで読んでみて下さい。

```
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

## 参考URL
https://www.spritle.com/blogs/2019/11/25/how-webpacker-and-Rails-6-tortured-me-and-how-i-survived/

https://stackoverflow.com/questions/58506351/webpacker-throws-application-css-not-found-in-manifest-json-in-rails-6-applica
batファイルとは難やねん！※スーパー初心者の適当まとめ

# はじめに
1、言っておきます、全くの初心者がまとめてますので知識を振りかざしたい方は、一刻も早く退場して下さい。（※自分的に変な理解で解釈してますので....）

2、まず、batファイルってなに、、、、そもそも調べてもこう書けば、こうなると手順に沿えば出来るが中身の意味（※知識レベル2の僕はチンプ感奮）なんやねんとなったので自分なりのまとめ的解釈をかく、、、


##＊んじゃ、まとめます＊
1、`バッチファイル`やら`.bat`なに？
・まず、一緒らいしい※意味的に
・バッチ＝windows環境下で動作する
基本的にPC（パソコン）を触る初心者レベルの僕は、マウス操作以外触れないから。。
意味が分からない、、ｗｗ

以上！！
Dynamics 365 を Teams と連携する方法

向井です。

今回は **Dynamics 365 の Teams 連携の方法**をご紹介します。

#1. Microsoft Teams 統合機能を有効にする

このチャプターの内容は[こちら](https://docs.microsoft.com/ja-jp/dynamics365/teams-integration/teams-install-app)のDocsの内容を初心者の方向けに解説したものです。

Dynamics 365 の画面から
歯車マーク＞詳細設定
![詳細設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/94978e02-713e-72b5-8a22-b1419db49046.png)

設定＞管理
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/655d7a20-972f-aa02-8263-c6ca0b0ea7f1.png)

システム設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/58ee9873-e280-b4f6-9425-031d8e2762a1.png)

Microsoft Teams 統合 ＞
「基本的な Microsoft Teams 統合を有効にする」を「はい」に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/3441471a-19be-5355-9b14-2ae0bb6d3202.png)

OKを押してしばらく待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/6414d60f-af42-ece8-f7e3-c6dd821e5684.png)

完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/528a3dc4-2ba9-3ab7-06ac-10d7059fe9e4.png)

※必要に応じて、「拡張された Microsoft Teams 統合を有効にする」を「はい」に変更します。
今回はこちらもはいに設定しています。
参考：[チームとの拡張された共同作業エクスペリエンス Microsoft Teams](https://docs.microsoft.com/ja-jp/dynamics365/teams-integration/teams-collaboration-enhanced-experience)


OKを押してウィンドウを閉じます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/eabf3f43-992b-f401-fec8-2ceaeb70fe5b.png)


#2. Dynamics 365 側の設定
Dynamics 365 の画面から、対象のレコードを開き、「共同作業」を押します。
※「共同作業」が表示されていない場合はキャッシュが残ってしまっている可能性があるので、一度ブラウザを閉じてから開き直してみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/801b9687-99a0-1f4d-2152-e8dda75cd252.png)

始める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/04c92dd1-37c3-bc5f-0498-4d33f8358926.png)

対象のチームを選択し、次へ
※今回はあらかじめ作成しておいたチームを選んでいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/38ce85cb-c15f-e9fd-e824-8b0d1a395b60.png)

対象のチャンネルを選択し、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/342527c6-99af-fd42-4240-fc26d4fcd77c.png)

対象のメンバーを選択し、完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/ec8dbc17-6b53-6332-a00e-c4d10d8148b4.png)

完了画面が表示され、しばらく待っていると、Teamsに画面が移行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/e4f242a3-f3a4-9110-fc77-4aa89b1feaea.png)

Teams に Dynamics を埋め込むことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004488/9af55acb-296c-a136-aeb9-da43df920811.png)
GitHubでよくあるミスの対処法をまとめてみた

プログラミングを始めたての私のような人はついついmasterブランチでコードを書き始めてしまうものです。
この記事は、GitHubでソース管理していて思わずやらかしてしまったときの対処法を共有しています。
**ターミナルでのコマンドではなくGitHub Desktopアプリで作業しています。**

# masterブランチでコードを誤って記述してしまった場合
ブランチを作成せずにmasterのままコードを書いてしまったことありませんか。
大丈夫です。新しいブランチにそれまでのコードを引き継げます。
### 具体的な手順
#####①新しいブランチを作成
とりあえず新しいブランチを作りましょう。

#####②「Bring my changes to」を選択
①で新しいブランチを作ると２択を迫られますので、「Bring my changes to」を選択。
これは、①で作った新しいブランチにそれまでのコードを引き継ぐという選択肢になります。
これでmasterでコードを書き始めてしまっても取り返しが付きます:relieved:

#誤ったコミットをしてしまった場合
コミットしたくないのにコミットしてしまった場合です。まだプッシュしていないのであれば簡単に取り消せます。
###方法
コミットボタンの下に「Undo」というボタンが表示されていますので、これを押すと直前のコミットを取り消せます。
![スクリーンショット 2021-01-26 16.44.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/788596/8c5a7b65-953d-b00c-a82d-8509c555e6e3.png)


#誤ったコミットをプッシュしてしまった場合
誤ったコミットをして、さらにプッシュしちゃった場合です。
「History」を確認して誤ったコミットを見つけましょう(画像参照)。
右クリックして「Revert Changes in Commit」を実行するとすぐ上に新しいコミットが行われます。このコミットをプッシュしてあげます。
![スクリーンショット 2021-01-26 16.38.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/788596/d381a93a-7059-6923-4ed8-257084df276a.png)


#####なぜさらにコミットしているのか
「誤ってコミットしたものは消すのでは？」と思った方もいるかも知れませんが、上記で行ったことは変更の上書きです。
誤ったコミットは残したまま、その内容を上書きするような新しいコミットをプッシュすることでファイルの内容を実質的にもとに戻している、ということです。
【E資格取得勉強】情報理論

#目的
E資格取得を目指して学習した内容をメモとして残し、後から振り返れるようにする。

#目次
[0. 参考資料](#0-参考資料)
[1. 情報理論でいうところの情報量とは何か？](#1-情報理論でいうところの情報量とは何か)
[2. 確率関数間の擬距離](#2-確率関数間の擬距離)


#0. 参考資料
こちらのサイトの情報エントロピーに関する説明が、大変わかりやすく参考になる。

http://www.gms-jp.com/MemCalc_HP/5-1.htm

#1. 情報理論でいうところの情報量とは何か？
情報がもたらされることにより不確定さの減少する分を情報量と定義する。

日常的には、情報量は情報を受け取る人にとっての価値を意味しているが、情報理論における情報量は事象の発生する確率にのみ依存する。つまり、情報量$ I $は確率$ p $の関数になるため、$ I(p) $と表記される。

より稀な事象が発生したことを知らせる情報は、情報量がより多くなる必要がある。例えば、６面体のサイコロを振った時に１の目がでる確率$ p_1 $は$ 1/6 $で、奇数の目がでる確率$ p_2 $は$ 1/2 $である。１の目が出る確率の方が稀な事象であるため、この場合情報量$ I(p_1) $、$ I(p_2) $は下記を満たす。

```math
I(p_1) > I(p_2)
```

また、確率$ p_0 $が$ p_1 $と$ p_2 $の積となるとき、つまり

```math
p_0 = p_1 \times p_2 
```

であるとき、情報量は下記の加法性が成り立つ必要がある。

```math
I(p_0) = I(p_1) +　I(p_2)
```

以上を満たす関数は対数関数であることから、確率$ p $で発生した事象の情報量を

```math
I(p) = - \log(p)
```

と定義する。また、これを自己情報量と呼ぶ。

自己情報量の期待値をシャノンエントロピーと呼び、下記式で表す。

```math
H(p) = E(I(p)) 
```

ここで、確率$ p $が離散型確率変数$ X $の関数で表される場合、

```math
H(p) = - \sum p(X) \log(p(X))
```

となる。

#2. 確率関数間の擬距離
ある確率変数$ X $の確率関数が２つあるとする。それぞれを$ p_1(X) $と$ p_2(X) $とする。

カルバック・ライブラー擬距離は以下の式で表される。

```math
D_{KL}(p_1 || p_2) = E_{p_1}( \log (p_1) - \log(p_2))
```

確率変数$ X $が離散型確率変数とすると、

```math
D_{KL}(p_1 || p_2) = \sum p_1(X) \log \frac{p_1(X)}{p_2(X)}
```

と表される。ここで、


```math
D_{KL}(p_1 || p_2) \geqq 0
```

であるが、

```math
D_{KL}(p_1 || p_2) \neq D_{KL}(p_2 || p_1)
```

となり、距離の公理を満たさないことから「擬距離」と呼ばれる。

カルバック・ライブラー擬距離を式変形すると、

```math
D_{KL}(p_1 || p_2) = \sum p_1(X) \log p_1(X) - \sum p_1(X) \log p_2(X)
```

となる。この式の第2項目を交差エントロピーと呼び、以下のように表す。

```math
H(p_1, p_2) = - \sum p_1(X) \log p_2(X)
```

これは$ p_2 $の自己情報量を$ p_1 $の分布で平均していることを意味する。
🩰GoとSwiftで簡単なアプリを作る

## おはようございます🌿
バックエンドとフロントエンド両方の勉強を兼ねてiOSアプリを作ります．


## なにをつくるか
開脚のやわらかさを競うiOSアプリをつくります．
<img width="600" alt="yawarakasa" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/7a979300-f748-d2c9-0960-9d09ed5c16af.jpeg">
やわらかさを競うということでYawarakasa Competitionからの**yawacom**と名付けました．変えるかも🥺
なんでやわらかさ？というと，バレエを昔少しだけ習ってたにも関わらずとっても体が硬いためストレッチしようかな…と思ったからです．
今後，関連するQiitaの記事にはバレエ🩰のマークを付けていきます．

### 技術選定
* Swift
* Go
* MySQL

### なぜGoか
「**軽量・高速・シンプル**」と謳われ，流行ってたからです．
▽Go言語と調べるとこんな感じでいいところがたくさんでてきます
[2019年大注目のGo言語(Golang)！入門者も知っておきたい特徴や強みはコレ！](https://proengineer.internous.co.jp/content/columnfeature/13619)

あとGopherくんがかわいいからです．
<img width="200" alt="Gopherくん" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/d8a295a4-d1cb-2a0d-fd1c-246e2b94b46c.png">
おめめがかわいいですね〜

## 作っていこう！
記事を細かく分けました．また書いたら追記していきます．
🐭はGopherくんをイメージしてバックエンドの記事を，🐥はSwiftの鳥をイメージしてフロントエンドの記事を表しています．

### フロントエンド
<a href="https://qiita.com/kno3a87/items/4f6706d1e504556e9390">🩰yawacom - 🐥iOSアプリの準備</a>
<a href="https://qiita.com/kno3a87/items/bdb803bb8c4180ea6da7">🩰yawacom - 🐥Storyboardを使わず画面遷移を行う</a>
<a href="https://qiita.com/kno3a87/items/071f2221d0b322ce3097">🩰yawacom - 🐥画面を作っていく</a>

### バックエンド
<a href="https://qiita.com/kno3a87/items/248e7615a9b7eef9b9d6">🩰yawacom - 🐭どんな値がデータベースに入るのか</a>
<a href="https://qiita.com/kno3a87/items/4b0e127f4fb3982cba06">🩰yawacom - 🐭APIの設計書を書く</a>
🩰yawacom - 🐥iOSアプリの準備

# 準備
XcodeでAppを新規作成し，必要そうなライブラリをPodsで導入します．
▽参考文献
<a href="https://qiita.com/ShinokiRyosei/items/3090290cb72434852460">【Swift】CocoaPods導入手順</a>
とりあえず使いそうな'RxSwift'と'RxCocoa'を導入しておきます．

```text:Podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'yawacom' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for yawacom
  pod 'RxSwift'
  pod 'RxCocoa'

  target 'yawacomTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'yawacomUITests' do
    # Pods for testing
  end

end
```
`Pod installation complete!`と表示されたらyawacom.xcworkspaceのほうを立ち上げて作業していきます．（Podsを使う際はhoge.xcodeprojのではなくhoge.xcworkspaceを使うので注意！）

次にPROJECTのGeneralでiOSのターゲットを決めたり，Singing&CapabilitiesのTeamに自分のdevelopment team（Appleのアカウント）を選択します．
![スクリーンショット 2021-01-26 21.32.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/02d16021-7622-6c2b-dbdb-df19257847bb.png)
![スクリーンショット 2021-01-26 21.34.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/eb60631b-74c1-8bc1-517b-15b7ce295ae7.png)

# アプリデザイン
Figmaでモックアップをささっと作ってみました（デザインはのちのちブラッシュアップ予定です）．
![スクリーンショット 2021-01-26 16.13.42（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/70ee2340-769f-202a-c757-73460f4a3d79.png)
▽Figmaの簡単な使い方はここにまとめました
<a href="https://qiita.com/kno3a87/items/1342c59a4c898bc96319">Figma使い方</a>

# 開発フロー
miroを使ってどんな流れになるのかをまとめてみました．以降これに沿って作っていきます．
![スクリーンショット 2021-01-26 16.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/81a13e13-eb41-4629-7d75-9e5d49c10239.png)


# next記事
<a href="https://qiita.com/kno3a87/items/bdb803bb8c4180ea6da7">🩰yawacom - 🐥Storyboardを使わず画面遷移を行う</a>
fsevents.nodeが読み込めなくてyarnコマンドができない時→yarn upgrateで解決！

##背景
他人のvue.jsのプロジェクトのコードを添削することになったので、zipファイルから解凍し、そのプロジェクト上で`yarn serve`を実行した。
その時`fsevents.node`のファイルの関係で`yarn serve`ができなかった。
##模索
コードをみてもエラーがないので、コマンドの実行結果をみると、

```
Note that the development build is not optimized.
  To create a production build, run yarn build.
```
と書かれていたので、`yarn build`を実行してみました

特にエラーもなく完了したので、再び`yarn serve`を実行してみても上手くいきませんでした。
##対処法

その後下記記事を読んで`yarn update`を実行してみました

https://qiita.com/akameco/items/301aff5f30d673c6ab17

そうすると問題なく`yarn serve`ができてローカルホストのURLも発行できました！

##考察
改めて振り返ってみると、`fsevents.node`に関するエラーのポップアップが出てきてその下にはローカルのURLが発行されていました。`yarn serve`自体は実行されていたのですが、上記の記事にも関連するような`yarn`のバージョンが古いということに関連しているのかなと思いました。

```
warning Your current version of Yarn is out of date. The latest version is "1.22.5", while you're on "1.22.4".
```
この結果が`yarn update`の実行結果にも出ていました。

もし、`yarn`に関するエラーでバージョンを最近アップデートしていなかったという自覚があるなら

```
yarn update
```
を実行してみるのもいいかもしれません！
Cisco ACIによるネットワーク構築 -ACIとは

# Cisco ACIとは？
Application Centric Infrastructure の略語であり、Ciscoが提供するSDNの1つ。
ACIとは１つの機器名ではなく、Ciscoが販売する機器及びサーバを組み合わせて提供するプロダクト名。
主にAPICとNexusでFabricが構成される。Nexus はデータ転送用のL2/L3 スイッチとなり、SpineとLeafで
役割が分かれる。Nexus 9500、Nexus 9300 の一部がSpine、Nexus 9300 の一部がLeafとなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056057/320136e8-62f0-c0cf-6f57-48fdd2967723.png)

- APIC  
Application Policy Infrastructure Controllerの略語で、エーピックと呼ばれる。  
UCSサーバであり、ACI Fabricの設定を管理する為のコントローラとなる。  
GUI、CLI、APIによる設定に対応し、後述するSpine/Leafに対して設定を行う。  
3台以上のクラスタを組んでの使用が推奨されており、必要に応じてクラスタサイズを増やすことができる。  
※３，５，７台での使用が推奨されており、２，６台といった偶数台は推奨されない。  
- Spine  
ACI Fabricにおけるコアスイッチの役割を担う。外部ルータやネットワーク機器、サーバがSpineに接続される事は無く、Leaf間でのデータ転送、中継、同期を行う。
- Leaf  
ACI Fabricにおけるアクセススイッチの役割を担う。従来のL2,L3スイッチとして機能する部分であり、  
外部ネットワーク機器やサーバ等が接続される。収容ポートが足りなくなればLeafスイッチを増設していく。  
収容する機器のポート、SFPの種類に応じて対応するLeafを選定する。  
Nexus 9300シリーズに関しては以下Ciscoページを参照ください。  

https://www.cisco.com/c/ja_jp/products/collateral/switches/nexus-9000-series-switches/datasheet-c78-738259.html

# APICとCIMC
APICはSpine,Leafに対して設定・制御を行うUCSサーバに対し、CIMCはUCSサーバを設定・管理・モニタする管理サービスです。
CIMCはサーバ（APIC)内で動作し、GUIもしくはSSHベースのCLIで接続します。
APIC筐体にはAPICに接続するマネジメントポートと、CIMCへ接続する専用管理ポートがあります。
APICとCIMCにはそれぞれ別のIPを割り振る形となり、バージョンもそれぞれ専用の物があります。

TeraTerm等のターミナルからCIMCへコマンドでSSH接続する場合には、SOLを有効化する必要があります。

https://www.cisco.com/c/ja_jp/td/docs/ucs/ucsc-integratedmgmtcntrller/ucsc-integratedmgmtcntrll/cg/004/b_Cisco_UCS_C-Series_CLI_Configuration_Guide_141/b_Cisco_UCS_C-Series_CLI_Configuration_Guide_141_chapter_0110.html#d40967e812a1635

# ノードの管理

ACI FabricにLeafやSpineを追加する事をコミッションと呼び、取り外す事をデコミッションと呼ぶ。
各APICやLeaf、SpineにはノードIDと呼ばれる数値を割り振り、Fabric内ではこのノードIDで各機器を識別します。Fabric内でノードIDは重複させる事ができず、ユニークな値である必要があります。

ノードIDはAPICとNexusで、以下の範囲から割り振りが可能です。
APIC : 1 ~ 100
Leaf/Spine : 101 ~ 4000
rails6を使おうとしたら、Webpackerがインストールできない。

#Rails6使いたい
rails6を使ってシステムを使おうとすると、
Webpackerがインストールできない事態に遭遇しました。

```
rails webpacker:install
```
してくださいと言われたので、してみると...

```
sh: /usr/local/heroku/bin/node: cannot execute binary file
sh: nodejs: command not found
Node.js not installed. Please download and install Node.js https://nodejs.org/en/download/
```

と表示されインストールできません。

Node.jsをサイトからインストールしたり、

```
alias nodejs='node'
```


というエイリアスも追加してみましたが、変化はありませんでした。
#解決策


```
sh: /usr/local/heroku/bin/node: cannot execute binary file
```

上のエラー文がどうやら関係していたようで

```
rm -rf /usr/local/heroku /usr/local/lib/heroku /usr/local/bin/heroku ~/.local/share/heroku ~/Library/Caches/heroku
```

上記のコマンドでherokuのアンインストールを試してから
もう一度

```
rails webpacker:install
```

してみると

```
Webpacker successfully installed 🎉 🍰
```
と表示され見事Webpackerがインストールできました！
SPRESENSE で Software I2C ライブラリを使う 

Sony Spresense ボード上で、Software I2C を使う方法です。

## Software I2C とは

Software I2C とは、ソフトウェアで GPIO 信号をパタパタさせて、I2C 通信をエミュレートしてしまうというものです。I2C Bitbang などとも呼ばれます。もちろん Hardware I2C と比べると、CPU はこの処理に占有されてしまいますし、パフォーマンスもそれなりにしか出ません。

ですが、物理的に I2C 専用ピンが空いていないときなどは、余っているピンで I2C デバイスを制御できると便利です。また、Spresense ボードの場合はマルチコアが使えるので、MainCore では別の処理を行い、SubCore に Software I2C の処理を割り当てる、といった使い方をすれば CPU 処理の負荷について特に気にせず利用することができます。

## ライブラリ

Arduino libraries にインストールしてください。

https://github.com/baggio63446333/SlowSoftI2CMaster

- ゼロベースで自作しても良かったのですが、felias-fogg さんのを流用させて頂きました。
- オリジナルは、脱ボード依存を目的として、Arduino標準APIだけを使うというコンセプトをもつライブラリなのですが、それだとパフォーマンスが出なかったので、ifdef で括って Spresense 依存コードをブチ込んでみました

https://github.com/felias-fogg/SlowSoftWire

- 標準の`Wire`ライブラリとインターフェース互換で使うためのラッパーです。これはそのまま利用します。

## 使い方

使い方はかんたんで、SDA, SCL として使うピン番号を指定して、SlowSoftWire のインスタンスを生成するだけす。第3引数は、チップの内蔵プルアップ機能を使うかどうかのフラグですが、`true` を入れてください。それ以外の使い方は、標準的な Wire ライブラリと同じです。

```cpp
#include <SlowSoftWire.h>

#define I2C_SDA_PIN 5
#define I2C_SCL_PIN 6

SlowSoftWire Wire = SlowSoftWire(I2C_SDA_PIN, I2C_SCL_PIN, true);
```



## サンプル
I2C Scanner サンプルスケッチを貼っておきます。

```cpp:I2cScanner.ino

#include <SlowSoftWire.h>

#define I2C_SDA_PIN 5
#define I2C_SCL_PIN 6

SlowSoftWire Wire = SlowSoftWire(I2C_SDA_PIN, I2C_SCL_PIN, true);

void setup()
{
  Wire.begin();
  Serial.begin(115200);
}

void loop()
{
  uint8_t error;
  int nDevices;
  int addr;
  int upper, lower;

  printf("I2C Scanning...\n\n");

  nDevices = 0;
  printf("     -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -A -B -C -D -E -F\n");
  for (upper = 0; upper < 8; upper++) {
    printf("%d- :", upper);
    for (lower = 0; lower < 16; lower++) {
      addr = upper * 16 + lower;
      Wire.beginTransmission(addr);
      error = Wire.endTransmission();
      if (error) {
        printf(" --");
      } else {
        printf(" %02x", addr);
        nDevices++;
      }
    }
    printf("\n");
  }

  printf("\nthe number of found I2C devices is %d.\n\n", nDevices);

  delay(5000);
}
```

正しく動けば、接続されているI2Cデバイスのスレーブアドレス一覧がシリアルモニタ上に表示されます。

```
I2C Scanning...

     -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -A -B -C -D -E -F
0- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 0f
1- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1f
2- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
3- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
4- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
5- : -- -- -- -- -- -- -- -- -- -- -- -- -- 5d -- --
6- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
7- : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

the number of found I2C devices is 3.
```
🎨Figma使い方

# 基本動作
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/5b1fa7df-1513-36ee-b414-091d47920701.png" width=80%></img>
左上のFrameを押すと
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/2b8f3cf0-ae58-633d-8d66-47148320d1d3.png" width=30%></img>
右にいっぱい実機サイズがでてくるので
![_2020-12-17_0.12.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/430154ca-4c72-74c6-319c-0722f42c2a2e.png)
押すとそのサイズの枠ができます．

# スクロールさせる
![_2020-12-17_0.14.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/8ae42179-3abc-4f4e-6808-c8290217eac1.png)
スクロールさせたかったら枠のはじっこをドラッグで引き伸ばすことで，その分スクロールできるようになります．
![_2020-12-17_0.15.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/6f17073f-8801-43d5-502f-d7aadb4a1801.png)
スクロール中に固定させたいものはContainsのFix positionに✅を入れると固定されます．

# 画面遷移
![_2020-12-17_0.26.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/83b936f1-5993-6ad1-42a0-fa35cc4e23f2.png)
右に書かれている文字を**Design**から**Prototype**にすると画面遷移を作れます．
![_2020-12-17_0.27.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149433/bd0c98ec-5da6-fb21-0dfe-3930ca18a95a.png)
図形にある丸から動かしたい先のビューまで導線をつなげます．
この時右に書かれているTapってところは『タップしたら画面遷移』などを表します．ここでは『新規登録』ボタンを押すと『くのさんのやわらかさ』の画面へと遷移します．


# 参考文献
[UI/UXデザインツール『Figma』入門](https://chot.design/figma-beginner/9039108315c1/#id4)
[Figmaのプラグインをいろいろ触ってみました](https://devblog.thebase.in/entry/2019/08/14/132811)
[Figmaのプロトタイプ~スクロール編~](https://tsubasashiraishi.medium.com/figma-prototyping-4c7745c0534e)
[Figmaのおすすめデザイン素材・UIキットまとめ](https://webdesign-trends.net/entry/10918)
[Figmaで基本の定番UIアニメーション7つをデザインしよう 無料サンプルデモ有](https://photoshopvip.net/124900)
herokuにデプロイするもassets:precompile errorがでた。

# 初めまして
現在、個人でアプリ制作をしておりherokuにデプロイした時に「assets:precompile error」が出たのでそれの解決した方法について共有したいと思います。
また、私はまだまだ初心者の為、至らない箇所があると思いますが、ご容赦ください。


#「We’re sorry, but something went wrong.If you are the application owner check the logs for more information.」とデプロイ画面遷移後に出た表示

デプロイ後に、アプリを開いて上記のような画面が出て最初は「？？？」でしたが、言われた通りターミナル上でlogを確認しました！

```
heroku logs --tail
```

上記を入力することにより、どのようなことが起こったのかターミナル上に表示してくれます。

読んでいると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1043417/56aeb2eb-a688-fe64-7396-7948de08fa56.png)

ActionView::Template::Error (The asset "motivate.jpeg" is not present in the asset pipeline)とでてました。

「motivate.jpegが存在しないよ」と怒られました。


また、asset pipline(アセットパイプライン)という言葉がキーになります。

このアセットパイプラインが本番環境（デプロイ後）では自動で処理されず、画像がうまく読み込めていなかったみたいです。

#解決方法

```
config.environments.production.rb

config.assets.compile = false
↓へ変更
config.assets.compile = true
```
config.assets.compile = trueにすることにより自動的にコンパイルしてくれるようです。

#最後に

この方法によって無事にデプロイ後正常に動作を行うことができました。
しかし、少し動作が重くなったように感じられました。
この解決法が絡んでる可能性もあるので、今後わかり次第また記事にまとめます！

ここまで読んでいただきありがとうございました！
Autowareデモを実行

# 目標
Autowareデモを実行する

# 動作環境
- Windows10 Pro Insider Preview バージョン2004
- Intel(R) Core(TM) i7-8750H
- Ubuntu 18.04
- メモリ32.0 GB
- GPU RTX1060

# データの入手
https://github.com/Autoware-AI/autoware.ai/wiki/ROSBAG-Demo
上記URLからmapデータとROSBAGデータをダウンロードする
ダウンロードしたファイルを~/dataに解凍します(外部HDDに保存した場合読み込み速度の関係で動作しない可能性があります)
ダウンロードしたファイルを解凍する

```
$ mkdir ~/data
$ cd ~/Downloads
$ sudo apt install pigz
$ tar -I pigz -xvf sample_moriyama_150324.tar.gz -C ~/data
$ tar -I pigz -xvf sample_moriyama_data.tar.gz$
$ mv data/* ~/data/
```

# Runtime Managerの起動

```
$ cd ~/autoware.io
$ source install/setup.bash
$ roslaunch runtime_manager runtime_manager.launch
```
![RuntimeManagerTop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/346b5f7b-59c0-23b5-61cf-a557cac74310.png)


Runtime Managerは昨日の種類ごとにタブで分けられている

**Quick Start**
 自動運転に必要な機能を一通り集めたもの

**Setup**
 センサと車両の制御軸と位置関係やrvizに表示する車両モデルなどの初期設定を行う

**Map**
 3次元地図の読み込みを行う

**Sensing**
センサドライバの起動やセンサから得られるデータのフィルタリングを行う

**Computing**
センサから得られた情報を処理し自己位置推定や車両検知、経路追従といった実際に自動運転を行うための判断に必要な処理を起動する

**Interface**
Autowareが対応する車両との接続を行う

**Database**
Mapの読み込みをクラウド上のデータベースから動的に行う設定をする

**Simulation**
rosbagデータの再生を行う

**Status**
Autowareを起動しているホストマシンの状態の詳細が表示される

**Topics**
Autoware上で扱われるトピックの情報を確認できる

**State**
自動運転のふるまいを設定する

# Autowareデモの実行

#### rosbagの再生と一時停止
Simulationタブに移動してRefからrosbagファイルを選択してPlayボタンを押した後にPauseボタンを押して一時停止する。
![RuntimeManagerSimulation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/da19bee9-03f2-cf4e-dda3-d955dbfc866a.png)


#### 車両の制御位置とLiDARの設定
Setupタブに移動する

- Localizer：Velodyneを選択 
- TF：x:1.2、y:0、z:2、yaw:0、pitch:0、roll:0を指定
- Vehicle Model：何も指定しない
![RuntimeManagerSetup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/aa46fe09-6218-7472-499d-d1ec276ec8c3.png)


#### 地図データとTFのロード
Mapタブに移動してPointCloudとTFのロードを行う
PointCloudのRefボタンをクリックし~/data/map/pointcloud_mapにあるデータをすべて選択する
TFのRefボタンをクリックし~/data/map/tf/tf.launchを選択する
![RuntimeManagerMap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/9fcfcb82-7cbf-b31b-b875-e5a748089b95.png)


#### スキャンデータのダウンサンプリングノードの起動
Sensingタブに移動しvoxel_grid_filterにチェックを入れる
![RuntimeManagerSensing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/52943c12-d337-1709-1858-ab4ca33d578a.png)


#### GNSSのNIMEAセンテンスから3次元座標への変換ノードと自己位置推定ノードの起動
Computingタブに移動
nmea2tfposeのappをクリックしPlanenumberが「7」になっていることを確認しチェックを入れる
ndt_matchingのappをクリックし「initialPos」が選択されていることを確認しチェックを入れる
![RuntimeManagerComputing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/5e3fefb6-e662-e96d-14f7-3cdc59abea98.png)


#### rosbagの再生とrvizの起動
Simulationタブに移動しPauseを解除する
RVizボタンを押すと画像の左側のウィンドウが起動し自己位置推定のデモが開始される
![RuntimeManagerSimulationRviz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794741/8406eade-18ae-a226-4031-e2a388d43e1b.png)
mysqlのdumpファイルから、特定のテーブルのdumpファイルを再構築する

mysqlのテーブル指定をしていないdumpファイルから、指定したテーブルに該当するdumpだけを取り出す方法。

| 項目 | 例 |
|:--|:--|
| データベースのdumpファイル | all.dump |
| 抽出したいテーブル | HOGE |


```
# "Table structure for table *****"の行で分割
$ csplit all.dump '/Table structure for table/' {*}

# 分割したファイルから、抽出したいテーブル名が含まれるファイル名の確認
$ grep -il 'HOGE' ./x*

# dumpファイルのヘッダを作成
$ head -16 > HOGE_tables.dump

# 結合
$ grep -il 'HOGE' ./x* | xargs -I {} cat {} >> HOGE_tables.dump


# dumpインポート
$ mysql --user=USER --password=PASSWORD DATABASE < HOGE_tables.dump

```

※ head -16 の行数は、mysqlのバージョンによるかもしれないので適宜調整する
※ HOGEがvalueとして含まれているファイルもマッチするので、その場合は適宜grepコマンドを調整する
Python3でログファイルに出力しつつ、コンソール画面にも表示する（basicConfigを使用）

Python3でlogging × basicConfigを使用してログファイルに出力しつつ、画面にも表示したい場合は、logging.basicConfigでhandlersを使う（要Python3.3以上）。

```python
import logging
from time import strftime

# ログ設定
logformat = '%(asctime)s : %(levelname)s : %(message)s'
logfile = 'hoge_{}.log'.format(strftime('%Y%m%d'))

logging.basicConfig(level=logging.INFO, format=logformat, 
                    handlers=[logging.FileHandler(logfile), logging.StreamHandler()])

# ログ出力
logging.info('info %s %s', 'hoge', 'fuga')
```

`logging.basicConfig(filename='xxxx.log')`と一緒に使うとエラーになるので注意。
AWS Lambdaをコマンドラインから実行してログを標準出力する

## 概要
CDKでdeployしたLambdaをローカルPCからAWS CLI（version 2）でコマンドラインから実行して結果ログを確認することがあり、これまでは

* AWS CLIでLambdaをInvoke
* AWS CLIでCloudWatch Logsの直近実行ログを出力

をおこなっていた。

この方法だとログ出力までに若干タイムラグがあるのと、CloudWatchのログはLambda名で検索するため実行したLambdaの結果ログが一意に定まらないのが若干気になっていた。

単純に知らなかっただけではあるのだが、ドキュメントを見たらコマンドラインから実行してそのまま結果ログを標準出力することが可能だったので、やり方とコマンドをまとめておく。

## やり方
* `--log-type Tail` を指定
* 中身の `LogResult` をデコードして出力

参考：https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-awscli.html

## コマンド
### 実行してログを標準出力
```shell
aws lambda invoke --region ap-northeast-1 --function-name ${Lambda名} out --log-type Tail --query 'LogResult' --output text | base64 -d
```

### 実行してログを標準出力（AWSプロファイル指定）
```shell
aws lambda invoke --profile ${AWSプロファイル名} --function-name ${Lambda名} out --log-type Tail --query 'LogResult' --output text | base64 -d
```

### 実行してログを標準出力（AWSプロファイル指定、Lambdaに渡すパラメータあり）
```shell
aws lambda invoke --profile ${AWSプロファイル名} --function-name ${Lambda名} --payload `echo -n '{"param1": "hoge", "param2": "huga"}' | base64` out --log-type Tail --query 'LogResult' --output text | base64 -d
```

----

プロファイルは `AWS_PROFILE=${プロファイル名}` の環境変数渡しも可能
Schemeで引数のデフォルト値的なことをするマクロ

以下がソース。

	(define-macro (bind-rest rest binds . body)
	  (let loop ((binds binds))
	    (if (null? binds)
	      `(begin ,@body)
	      (let ((ret (loop (cdr binds)))
	            (bind (car binds)))
	        (let ((var (car bind))
	              (val (cadr bind)))
	          `(let ((,var (if (null? ,rest) ,val (car ,rest)))
	                 (,rest (if (null? ,rest) rest (cdr ,rest))))
	             ,ret))))))

使い方は、

	(bind-rest リスト ((変数名 値)
	                  ...)
	  [手続き ...]
	  戻り値)
	  
例：

	(define (hoge a b . rest)
	  (bind-rest rest ((c 3)
	                   (d 4))
	    (+ a b c d)))
	    
	(hoge 1 2)
	-> 10
	
	(hoge 1 2 4 8)
	-> 15

もちろん値は関数の呼び出しでもいい。あと、restの余りはrestとして再度束縛されるので、bind-restを複数箇所で呼び出すこともできる。なので例えば処理の中で何か実行時の状況に依存する値取得（ユーザーからの入力とか）を行う関数があった場合に、単体テストの時だけその値を外部から引数で与えるとゆうことが簡単にできるわけ。

いじょう
Fess 差分クロールを考える

:::note info
コメント欄にも情報があります。あわせてご覧くださいませ。
:::

# 結論

https://fess.codelibs.org/ja/13.9/admin/general-guide.html
> 最終更新日時の確認
差分クロールを行う場合に有効にします。

公式ドキュメントには上記のように記載されているが、あくまでクロールを行った際にインデックスの作成を行うか否かの判定にのみ影響しているようで、クロール自体は対象パス内の全ファイルに対して行われている模様。
その為**「差分だから処理速度が速い」**ということはない。
（検証結果は後述）

得てして、差分クロールを求める背景には以下の要件があることと思われる。

- 新たに追加・更新されたファイルを一定間隔で検索インデックスへ反映したい
- ただし、処理時間・負荷は可能な限り短く・低くしたい

結論として現在の Fess で上記のような差分クロールを行う為には**「ファイルクロール」**ではなく、あらかじめクロール対象のファイル一覧を用意した上で**「データストアクロール」**を使用することになると思われる。
（有識者の方、ベストプラクティスがあれば教えていただきたい）

# 検証
## 検証環境
- Fess 13.9.3
- Elasticsearch 7.9.3

## 検証方法
以下、3ステップにてクロール完了に要する時間を計測した。

## 初期クロール
`C:/fess-search/dummy/` 配下に `dummy0001.txt` ～ `dummy1000.txt` を作成。
ファイルクロールを実施。
![crawl01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243093/c1e119b8-1495-20d9-f4b7-c0533bbebb66.png)
約4分弱で 1000ファイルのインデックス作成が完了。

## ファイルクロール
`dummy0100.txt` の内容を変更（ファイル内に modify と追記）した後、ファイルクロールを実施。
![crawl02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243093/c23946ff-5c3c-5f52-e8b0-550ebc1b51b6.png)
約4分弱で 変更された 1ファイルのインデックス作成が完了。初期 1000件クロールと同程度の処理時間を要した。

![search1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243093/78288ff3-63f1-6d3a-bd2e-e7d677e088a1.png)
更新が反映されていることを確認。

## データストアクロール
データストアクロールの設定は以下を参考に実施。
https://fess.codelibs.org/ja/13.9/admin/dataconfig-guide.html

アクション、クロール対象を記載した CSV を `C:/fess_crawl_list/` 配下に作成する。

```/fess_crawl_list/update.csv
modify,file:/C:/fess-search/dummy/dummy0200.txt
```

クローラ ＞ データストア ＞ 新規作成

インデクシング対象のファイルパスを記述した CSV ファイルをクロールする「CsvListDataStore」を使用する。

|項目|設定値|
|---|---|
|名前|任意|
|ハンドラ名|CsvListDataStore|
|パラメーター|directories=C:/fess_crawl_list <br> fileEncoding=UTF-8|
|スクリプト|event_type=cell1 <br> url=cell2|
|ブースト値|1.0|
|パーミッション|{role}guest|
|状態|有効|



`dummy0200.txt` の内容を変更（ファイル内に modify と追記）した後、データストアクロールを実施。
![crawl03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243093/24417b59-b009-42be-7071-a2ceb06f1eeb.png)
一瞬で変更された 1ファイルのインデックス作成が完了。

![search2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243093/1baac55e-eb5e-758e-94ac-f06d7e6dc7aa.png)
更新が反映されていることを確認。
【E資格取得勉強】確率・統計

#目的
E資格取得を目指して学習した内容をメモとして残し、後から振り返れるようにする。


#目次
[1. 確率変数](#1-確率変数)
[2. 期待値](#2-期待値)
[3. 分散・標準偏差](#3-分散標準偏差)
[4. 条件付き確率](#4-条件付き確率)

#1. 確率変数
出る目が$ a, b, c, d, e, f $のいずれかになるサイコロを考える。このとき、サイコロの出目の集合は$ \\{ a, b, c, d, e, f \\} $である。$ \\{ a, b, c, d, e, f \\} $を標本空間と$ \Omega $と呼ぶ。

この標本空間$ \Omega $を、$ 1 $から$ 6 $の整数の集合$ E = \\{ 1,2,3,4,5,6 \\} $に対応づける関数(写像)を確率変数$ X $と呼び、$ X : \Omega \rightarrow E $と表現する。

例えば、サイコロの出目が$ a $であるとき、それを数$ 1 $に確率変数$ X $が対応づけるとすると、

$ X(サイコロの出目=a)=1 $

となる。

ここで、サイコロの出目$ a, b, c, d, e, f $がそれぞれ同じ確率で出るとすると、
$ P(X=1)=1/6 $
であり、この$ P(X) $を確率分布関数と呼ぶ。

確率変数$ X $が$ 1,2,3,4,5,6 $の離散的な値をとることから、特にこの確率変数を離散型確率変数と呼ぶ。



確率変数$ X $が$ X \in \mathbb{R} $となるとき、この確率変数を連続型確率変数と呼ぶ。
ここで$ \mathbb{R} $は実数全体の集合を表す。
また、その場合の確率関数$ P(X) $を確率密度関数と呼ぶ。



#2. 期待値
離散型確率変数$ X $の期待値は、$ x \in X $とすると
$ E(X)= \sum_{x \in X} x \times P(X=x) $
となる。

一方、離散型確率変数$ X $の期待値は、$ x \in X $とすると
$ E(X)= \int_{x \in X} x \times P(X=x) dx $
となる。


#3. 分散・標準偏差
分散$ Var(X) $は下記の式で表すことができる。
$ Var(X)= E(x-E(X))^2 = E(x^2) - (E(x))^2 $

標準偏差は下記式で表される。
$ \sqrt{Var(X)} $


#4. 条件付き確率
ある事象$ X=x $が与えられた下で、$ Y=y $となる確率は下記となる。


```math
P(Y=y | X=x) = \frac{P(Y=y \cap X=x)}{P(X=x)}
```

2つの事象が独立である場合、同時確率は$ P(Y=y) $と$ P(X=x) $の積となる。

```math
P(Y=y \cap X=x) = P(Y=y)P(X=x)
```
VirualBoxのブリッジ接続でホストOSの外と通信ができない場合

# インターネット接続できなかったり、ホストPCの外からsshで接続できなかったり
- そのゲストOSにpingは通るんだけどなぁ
 
# 色々ググってできなかったら、、、
- Symantec Endpoint Protection　が邪魔しているのかも。

>パケットキャプチャしてみるとゲストOSへのARPのクエリがゲストOSに届いておらず
>ホストOSのSEPがドロップしてくれちゃってるらしい？
>通信シーケンスが逆になるが、realmコマンドやdigコマンドも同様の理由で
>ゲストOSからADサーバに接続できない（応答がゲストOSまで返ってこない）
EC2にDocker&docker-composeをインストールするコマンド


# EC2にDocker&docker-composeをインストールする



EC2(Amazon Linux)を立ち上げてDockerないしdocoker-composeをインストールすることは結構あると思います。
怠惰なあなたに送るdocker&docker-composeを一括で導入するためのコマンドです。

```sh:ワンライナー
$ sudo yum update && sudo amazon-linux-extras install -y docker && sudo service docker start && sudo usermod -a -G docker ec2-user && sudo chkconfig docker on && sudo yum install -y git && sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose && docker-compose version && sudo reboot
```

上と下のコマンドは同じことをしております。

```sh:一つずつ
$ sudo yum update
$ sudo amazon-linux-extras install -y docker
$ sudo service docker start
$ sudo usermod -a -G docker ec2-user
$ sudo chkconfig docker on
$ sudo yum install -y git
$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose version
$ sudo reboot
```

以上です。
あとは、rebootしているのでちょっとまってから再度、EC2に接続するといいでしょう:coffee:


### 補足
```sh
# docker-composeの最新版を取得するためのコマンド
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
```
[Swift]クイズアプリ 難易度に合致した問題を取得し、シャッフルしたあと数問ピックアップして返すやり方

クイズをJSONファイルに作成し

```Quiz.json
{
    "fourChoice": [
        {"question": "問題文", "answer": "答えの中身", "difficulty": "難易度", "commentary": "問題の解説"},
        {"question": "問題文", "answer": "答えの中身", "difficulty": "難易度", "commentary": "問題の解説"},
        {"question": "問題文", "answer": "答えの中身", "difficulty": "難易度", "commentary": "問題の解説"}
        以下続く
]
```
という具合に書いてあります。



_[Quiz]の中にはクイズのArrayが入っています。_

```QuizBox.swift
func getQuestionsForGeneral() -> [Quiz] {
    return Array(getQuestionsByDifficulty(difficulty: 1).shuffled().prefix(10))
}
```

↑難易度を引数に受け取り、その問題リストを作成し、shuffled()をして問題をランダムにしてから、前の１０個を取った上でArrayにして返す感じですね。

---

shuffled()
に関してはこちらの記事が参考になります。
>https://capibara1969.com/2033/

つまり、shuffled()は、要素をシャッフルした配列を新たに生成します。

prefix()
に関していうと、最初からいくつ取り出すか、ということですね。今回は10問取得するので10としています。
【VSCode】ディレクトリ作成、ファイル作成、VSCodeでのファイルオープンまで一気通貫でやる方法【Mac】

## はじめに

ディレクトリ作成と、ファイル作成を素直に行うと次のように複数行が必要で面倒くさい

```sh
$ mkdir parent
$ mkdir parent/child
$ code parent/child/sample.txt
```

一気通貫に、ディレクトリ作成、ファイル作成、VSCodeでのファイルオープンまでを行うコマンドを備忘録として残しておく[^1]
[^1]: codeコマンドはVSCodeを開くVSCode公式コマンドです。導入方法は[ターミナルからVisual Studio Codeを起動する方法【公式の方法】](https://qiita.com/naru0504/items/c2ed8869ffbf7682cf5c)を参照してください

## 方法

~/.zshrcファイルに次を追記して再起動

```sh:~/.zshrc
function mkdir-code() {
    mkdir -p "$(dirname "$1")";
    code $1;
}
```

再起動後に次のコマンドを叩いて動きを確認

```sh
$ mkdir-code parent/child/sample.txt
```

## おわりに

個人的に一番詰まったところは.zshrcではなく、.bashrcを誤って編集していたこと・・・最近のMacの標準はzshというものなのね
それでは楽しいVSCodeライフを続けていきます！
Cloud Logging の WARNING以上のログを Pubsub経由でslackに通知するCloud FunctionのPython実装メモ

# 背景
Cloud Functionをいくつか実装していて、個別にslack通知の実装するのがアレになってきたので、Cloud LoggingのWARNING以上はSLACKに通知される仕組みを構築する。

やりたい流れ

Cloud Logging -> Pubsub -> Cloud Function -> Slack


参考: [GCP の Error Reporting に飛ぶエラーを Slack に通知したい](https://buildersbox.corp-sansan.com/entry/2020/06/25/110000)

> ①. Cloud Logging -> Cloud Logging の Log Router -> Cloud Pub/Sub -> Cloud Functions -> Slack
> ②. Cloud Logging -> Cloud Logging の Log Router -> Cloud Monitoring -> Slack
> ③. Cloud Logging -> DataDog -> Slack
> ④. Sentry などのエラートラッキング用のツール/サービスを導入する

> ②も具体的に検討しましたが、エラーの発生を Slack に通知することはできてもエラーの詳細は通知できなさそうだったので諦めました。

こちらの記事にもあるように、 ②のCloud Logging -> Cloud Monitoring -> Slack というのが一番さくっと実装できるのですが、ログの詳細をSlack上に出せないので、今回は①のPubsub + Cloud Functionを経由してSlackに通知することにしました。

# 準備
Logging -> Pubsub -> Functionへの連携方法は[上記参考記事](https://buildersbox.corp-sansan.com/entry/2020/06/25/110000)や、以下の記事に非常にも丁寧に書かれている。

参考2: [Stackdriver Logging, Cloud Pub/Sub, Cloud Functionsで特定のイベント時にSlack通知する](https://blog.jicoman.info/2019/01/slack-nofity-using-stackdriver-logging-cloud-pubsub-cloud-functions-when-specific-event-occurs/)

今回はPythonでログの詳細をSlackに通知する実装をメモ。

# 実装

```py:main.py
import os
import json
import requests
import base64
from log_by_pubsub import LogByPubsub


def main(event, context):
    log_dict = json.loads(base64.b64decode(event['data']).decode('utf-8'))

    log = LogByPubsub(
        function_name=log_dict.get('resource', {}).get('labels', {}).get('function_name'),
        severity=log_dict.get('severity'),
        json_msg=log_dict.get('jsonPayload'),
        txt_msg=log_dict.get('textPayload')
    )

    requests.post(
        SLACK_WEBHOOK_URL,
        data=json.dumps(log.get_slack_data()),
        headers={'Content-Type': 'application/json'}
    )

    return "OK."
```

```py:log_by_pubsub.py
from typing import Final
import json


class LogByPubsub:
    SEVERITY_WARNING: Final[str] = 'WARNING'
    SLACK_COLOR_WARNING: Final[str] = 'warning'
    SLACK_COLOR_DANGER: Final[str] = 'danger'

    def __init__(self, function_name: str, severity: str, json_msg: str, txt_msg: str):
        self.function_name = function_name
        self.severity = severity
        self.json_msg = json_msg
        self.txt_msg = txt_msg

    def get_msg(self) -> str:
        if not self.json_msg:
            return self.txt_msg
        return json.dumps(self.json_msg)

    def get_color(self) -> str:
        if self.severity == self.SEVERITY_WARNING:
            return self.SLACK_COLOR_WARNING
        return self.SLACK_COLOR_DANGER

    def get_slack_data(self) -> dict:
        return {
            "attachments": [
                {
                    "title": f"[{self.severity}] Cloud Function: {self.function_name}",
                    "title_link": f"https://console.cloud.google.com/logs/query;query=resource.type%20%3D%20%22cloud_function%22%0Aresource.labels.function_name%20%3D%20%22{self.function_name}%22%0Aseverity%3E%3DWARNING",
                    "text": self.get_msg(),
                    "color": self.get_color()
                }
            ]

        }
```
[備忘録] OpenShiftでマスターノードのNoSchedule Taintを外す

マスターノードのTaintを外す。

```console
oc adm taint node <node-id> node-role.kubernetes.io/master:NoSchedule-
```
または：

```console
kubectl taint node <node-id> node-role.kubernetes.io/master:NoSchedule-
```

Taintが外れたかどうかを確認。

```console
oc get node <node-id> -o yaml | yq e .spec -
```

### Taintが外れない場合

デフォルトスケジューラで`mastersSchedulable: false`に設定されている可能性がある。

```console
oc get schedulers cluster -o yaml | yq e .spec.mastersSchedulable -
mastersSchedulable: false
...
```

これでマスターノードにもスケジューリングされるようになる。

```console
oc patch schedulers cluster --type=merge -p '{"spec":{"mastersSchedulable":true}}'
```
Basic認証を結合テストコードで通す方法

####参考にさせていただいた記事
+ [Basic認証を交えたテストコードの書き方](https://qiita.com/taka_no_okapi/items/b4cab8e2a451b3f1b88e)
+ [Capybara + Headless Chrome (System Spec) で Basic認証 を通過する方法](https://obel.hatenablog.jp/entry/20190721/1563652800)

ユーザー登録の結合テストコードを実装しようとしたところBasic認証を入れていたことを忘れていました。

#### 実装手順
１：自身で設定した環境変数を変数に入れる

```ruby:users_apec.rb
def basic_pass(path)
  username = ENV["BASIC_AUTH_USER"]
  password = ENV["BASIC_AUTH_PASSWORD"]
  visit "http://#{username}:#{password}@#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}#{path}"
end
```

visitを使用して環境変数を入力するためのURLに遷移すればOKとのことでした！

２：結合テストが読み込まれる前にbasic_pathを読み込ませる

```ruby:users_spec.rb
# 省略
RSpec.describe "ユーザー新規登録", type: :system do
  before do
    @user = FactoryBot.build(:user)
  end
  context 'ユーザー新規登録ができるとき' do
    it '正しい情報を入力すればユーザー新規登録ができてトップページへ移動する'do
    # トップページへ移動する
    basic_pass root_path
    visit root_path
# 省略
```

自分の場合はroot_pathから新規登録画面に遷移するため、

```ruby
basic_pass root_path
```

としています！


備忘録もかねて投稿しました。
よく使う編集画面テンプレート

#データ編集画面5パターン
自分用によく使う編集画面を整理しておこうと思います。

大まかには、次の5パターンが考えられます。

どのパターを採用するかについては、データの件数、1件当たりの項目数によって決まります。

##1.フォーム型
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/dbe96834-a5e8-bb90-6a76-cbd84bd4b7ec.png)

##2.表型
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/a87f5952-9263-3b68-ff03-d54d9b6dd52c.png)

##3.表型（検索条件付き）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/71a3a666-21dd-6432-07a8-d8241c2bbd11.png)

##4.フォーム表型(簡易)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/bfaf3460-3b3b-d79d-55ce-0713e9c948d0.png)

##5.フォーム表型(分離)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93227/39ebc4f4-ceb2-7bb3-708e-eb4bd80d17fd.png)
Ubuntu Administer 備忘録

高性能のマシンを購入し、複数のユーザーを作って運用しはじめた。試行錯誤しながら設定していく備忘録。

- Ubuntu 20.04
- 複数ユーザを設定
- イメージとしては、プロジェクトごとにユーザを使い分ける

## ユーザーを設定

```
$ sudo adduser [新しいユーザー名]
```

## sudo ユーザーlist

```
$ grep -Po '^sudo.+:\K.*$' /etc/group
```