OmniAICreator/Qiita-1.07M huggingface dataset:
【Azure】Red Hat でマルチNIC構成した場合の静的ルートの設定方法

# はじめに
本ページは、Azure上のRed Hat OSに対して、マルチNICを構成した場合の静的ルートの設定方法を記述したものである。

投稿した理由、Microsoft Azureの公式ドキュメント「[複数のネットワーク インターフェイス カードを使用して Linux 仮想マシンを Azure に作成する方法の複数の NIC 用にゲスト OS を構成する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/multiple-nics#configure-guest-os-for-multiple-nics)」では、下記の記載がある通り、詳細な手順が記載されておりません。

```html:引用
「オペレーティング システムに永続的なルートを追加する方法は、
ディストリビューションによって異なります。
 手順については、ディストリビューションのドキュメントを参照してください。」
```

Red Hat OSの手順を記載しますが、初めて操作する方にイメージがつけばいいなと考えております！

では、**Let's Study!**

# 設定手順
流れとして。
Azure ポータル上から追加しただけでは、NICが有効化されていないため、
OS上で「[1.追加したNICを接続する手順](https://qiita.com/drafts/877bbf01e3f5404e71d1/edit#1%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9Fnic%E3%82%92%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E6%89%8B%E9%A0%86)」を実施する。
その後「[2.永続的な静的ルートの設定手順](https://qiita.com/drafts/877bbf01e3f5404e71d1/edit#2%E6%B0%B8%E7%B6%9A%E7%9A%84%E3%81%AA%E9%9D%99%E7%9A%84%E3%83%AB%E3%83%BC%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%89%8B%E9%A0%86)」を実施する。


## 1．追加したNICを接続する手順

### 1-1.eth1が「切断済み」であることを確認する。
```
# nmcli d
DEVICE      TYPE      STATE     CONNECTION
eth0        ethernet  接続済み  System eth0
virbr0      bridge    接続済み  virbr0
eth1        ethernet  切断済み  --
lo          loopback  管理無し  --
virbr0-nic  tun       管理無し  --
```
### 1-2.Network Manager画面を表示し、eth1を接続する。
```
# nmtui
```
```
Network Manager画面上の設定

[接続の編集]-<追加>-<Ethernet>-<作成>を選択する。
Ethernet 接続 1　の設定画面が表示されるため、
デバイスに　eth1　と入力する。
また、IPv6設定を「無視する。」を選択し、<OK>を選択する。
<戻る>-<OK>を選択する。
```
### 1-3.eth1が「接続済み」であることを確認する。
```
# nmcli d
DEVICE      TYPE      STATE     CONNECTION
eth0        ethernet  接続済み  System eth0
eth1        ethernet  接続済み  Ethernet 接続 1
virbr0      bridge    接続済み  virbr0
lo          loopback  管理無し  --
virbr0-nic  tun       管理無し  --
```


## 2.永続的な静的ルートの設定手順

### 2-1.現状のルートを確認する。
```
# route -n
```
### 2-2.nmcliを使った静的ルートの設定
```
# nmcli device modify eth1 +ipv4.routes "10.0.0.0/24 10.0.0.1"
					"宛先アドレス/<プレフィックス> <GWアドレス>"
```
※GWのアドレスは、Azureではサブネットに対して定義されているアドレス範囲内の最初の IP アドレスとなる。

@angel_p_57様からいただいたコメントを検証した結果を反映しました。
RHEL7の推奨設定方法（ [4.2. NMCLI を使った静的ルートの設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/sec-configuring_static_routes_using_nmcli) ）

### 2-6.サービス再起動
```
# systemctl restart network
```

以降、設定したルートが反映されてeth1で接続ができるようになる！
（補足：プライマリはeth0 セカンダリーはeth1で固定です。）

# 参考文献
[・複数の NIC 用にゲスト OS を構成する(Windows版)](https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/multiple-nics#configure-guest-os-for-multiple-nics)
[・9.4.静的ルートおよびデフォルトゲートウェイ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/deployment_guide/s1-networkscripts-static-routes)
[・4.2.NMCLIを使った静的ルートの設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/sec-configuring_static_routes_using_nmcli)
【Node.js】文字列のハッシュ値を取得(SHA, MD5, RMD160)

## 関連

- [【Ruby】文字列のハッシュ値を取得(SHA, MD5, RMD160) - Qiita](https://qiita.com/kou_pg_0131/items/ad7a0fdd7b0a997cd5f4)
- [【Go】文字列のハッシュ値を取得(SHA, MD5, RMD160) - Qiita](https://qiita.com/kou_pg_0131/items/4ea1af8320bec60dd2f6)

## サンプルコード

```javascript
const crypto = require('crypto');

const plainText = 'password';

// サポートされているハッシュアルゴリズムを確認
console.log(crypto.getHashes());
// => [ 'RSA-MD4',
//      'RSA-MD5',
//      'RSA-MDC2',
//      'RSA-RIPEMD160', ...

// `crypto.createHash('アルゴリズム名').update('文字列').digest('hex')`
console.log('md5:    ' + crypto.createHash('md5').update(plainText).digest('hex'));
console.log('rmd160: ' + crypto.createHash('rmd160').update(plainText).digest('hex'));
console.log('sha1:   ' + crypto.createHash('sha1').update(plainText).digest('hex'));
console.log('sha256: ' + crypto.createHash('sha256').update(plainText).digest('hex'));
console.log('sha384: ' + crypto.createHash('sha384').update(plainText).digest('hex'));
console.log('sha512: ' + crypto.createHash('sha512').update(plainText).digest('hex'));

// => md5:    5f4dcc3b5aa765d61d8327deb882cf99
//    rmd160: 2c08e8f5884750a7b99f6f2f342fc638db25ff31
//    sha1:   5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
//    sha256: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
//    sha384: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc45583d446c598660c94ce680c47d19c30783a7
//    sha512: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
```

## 参考

- [Node.jsで暗号化とハッシュ - Qiita](https://qiita.com/_daisuke/items/990513e89ca169e9c4ad)
【Ruby】文字列のハッシュ値を取得(SHA, MD5, RMD160)

## 関連

- [【Node.js】文字列のハッシュ値を取得(SHA, MD5, RMD160) - Qiita](https://qiita.com/kou_pg_0131/items/174aefd8f894fea4d11a)
- [【Go】文字列のハッシュ値を取得(SHA, MD5, RMD160) - Qiita](https://qiita.com/kou_pg_0131/items/4ea1af8320bec60dd2f6)

## サンプルコード

```ruby
# frozen_string_literal: true

require 'digest'

plain_text = 'password'

puts 'MD5:    ' + Digest::MD5.hexdigest(plain_text)
puts 'RMD160: ' + Digest::RMD160.hexdigest(plain_text)
puts 'SHA1:   ' + Digest::SHA1.hexdigest(plain_text)
puts 'SHA256: ' + Digest::SHA256.hexdigest(plain_text)
puts 'SHA384: ' + Digest::SHA384.hexdigest(plain_text)
puts 'SHA512: ' + Digest::SHA512.hexdigest(plain_text)

# => MD5:    5f4dcc3b5aa765d61d8327deb882cf99
#    RMD160: 2c08e8f5884750a7b99f6f2f342fc638db25ff31
#    SHA1:   5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8
#    SHA256:  5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
#    SHA284: a8b64babd0aca91a59bdbb7761b421d4f2bb38280d3a75ba0f21f2bebc45583d446c598660c94ce680c47d19c30783a7
#    SHA512: b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86
```

## 参考

- [library digest (Ruby 2.6.0)](https://docs.ruby-lang.org/ja/latest/library/digest.html)
Yii1.1でSelect句で指定するカラムにSQL関数やCASE文を使用する方法


Yii1.1を使用する案件を対応しているのですが、ナレッジがあまりないので、まとめてみました。

## はじめに
Yiiでは[CActiveRecord](https://www.yiiframework.com/doc/api/1.1/CActiveRecord)や[CDbCriteria](https://www.yiiframework.com/doc/api/1.1/CDbCriteria)でSelect句を指定しますが、
`COUNT`関数や`SUM`関数を指定して取得する事は出来ましたが、
`CASE`文や`DATE_FORMAT`関数を指定した場合にエラーになったので、
対処方法をまとめてみました。

## 対応方法
[CDbExpression](https://www.yiiframework.com/doc/api/1.1/CDbExpression)を使用して対応します。

```
$criteria = new CDbCriteria();
$criteria->select = [
   new CDbExpression("DATE_FORMAT('%Y-%m', t.create_date) AS create_date"),
   new CDbExpression("CASE create_id WHEN create_id = 9999999 THEN 管理者 ELSE ... END AS create_user_name"),
   ...
];
...
$result = Post::model()->find($criteria);
```

[CDbExpression](https://www.yiiframework.com/doc/api/1.1/CDbExpression)は、[公式サイト](https://www.yiiframework.com/doc/guide/1.1/ja/database.ar)で`NOW`関数を使うパターンが紹介されています。
今回の実装方法はこの応用になるのかなと思います。
Vimgolf Add string initializers to an enumをやってみた

## 問: Add string initializers to an enum

Vimgolfの[以下の問題](http://www.vimgolf.com/challenges/5d7259d2c0248a000c157f9f)を解いてみたのでvimのキー操作について残しておく。

スタート

```
const enum TestkitType {
  vanilla,
  unidriver,
  protractor,
  puppeteer,
  unknown,
}
```

ゴール

```
const enum TestkitType {
  vanilla = 'VANILLA',
  unidriver = 'UNIDRIVER',
  protractor = 'PROTRACTOR',
  puppeteer = 'PUPPETEER',
  unknown = 'UNKNOWN',
}
```


## 解答

21キーストロークで現在最短(2019/09/15)

```
qq+ea = '<C-P>'<Esc>vbUq5@qZZ
```

## 解説

### `qq`

`q{0-9a-zA-Z"}`

タイプしたキーをマクロとして登録して記録する。
qでレコードを開始して次に押したキーに対してマクロを登録する、マクロの終了はqで行い今回はqキーに対してマクロを登録する。

### `+`

次の行の最初の文字にカーソルを移動する

### `e`

単語の最後の文字にカーソルを移動する

### `a = '<C-P>'<Esc>`

` = 'vanilla'` を入力してノーマルモードに戻る
`<C-P>` でvanillaをキーワード補完で入力している。

### `vbU`

ヴィジュアルモードでvanillaを選択して大文字に切り替える
`'vanilla'`  -> `'VANILLA'`

ヴィジュアルモードのUで大文字に切り替え、uで小文字に切り替える

### `q5@q`

ここまでの操作をマクロに保存し、qに登録されたマクロを５回繰り返す。
マクロの実行は `@q` で行う。

また、 `:reg` で登録されているマクロを確認することができる

```
:reg
--- レジスタ ---
"q   +ea = '^P'^[vbU
```

### `ZZ`

保存して終了する。
【Node.js】AWS SSMパラメータストアの値を取得する

## 関連

- [【Ruby】AWS SSMパラメータストアの値を取得する - Qiita](https://qiita.com/kou_pg_0131/items/1fa538c6fb7171e010e4)


## 使用するモジュール

- `aws-sdk`  
公式で提供されているライブラリ

```bash
npm i aws-sdk
```

## サンプルコード

今回はAWS SSM パラメータストアに以下のようなパラメータが作成してある。

| パラメータ名     | 値         |
| ---------------- | ---------- |
| sample-parameter | HOGEHOGE!! |

```javascript
const AWS = require('aws-sdk');

const main = async () => {
    // 認証情報
    // `~/.aws/credentials`に認証情報が設定されている場合、
    // または環境変数`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`に認証情報が設定されている場合は
    // `access_key_id`と`secret_access_key`は不要
    const credentials = {
        accessKeyId: 'xxxxxxxxxxxxxxxxxxxx',
        secretAccessKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
        region: 'ap-northeast-1'
    };

    // SSMクライアントを作成
    const ssm = new AWS.SSM(credentials);

    // リクエスト
    const request = {
        Name: 'sample-parameter', // パラメータ名
        WithDecryption: true      // 暗号化されている場合は復号し、暗号化されていない場合は何もしない
    };
    const response = await ssm.getParameter(request).promise();

    console.log(response);
    // => { Parameter:
    //      { Name: 'sample-parameter',
    //        Type: 'SecureString',
    //        Value: 'HOGEHOGE!!',
    //        Version: 1,
    //        LastModifiedDate: 2019-09-12T15:28:02.134Z,
    //        ARN:
    //         'arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:parameter/sample-parameter' } }

    console.log(response.Parameter.Value);
    // => HOGEHOGE!!
};
main();
```

## 参考

- [Class: AWS.SSM — AWS SDK for JavaScript](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SSM.html)
【ABC140復習】D - Face Produces Unhappiness

#ご注意
考えたことの羅列なので厳密で正しい言及がされているというわけではありません。悪しからず。
#答え(mainのみ)
```c++
int main(void) {
	int N, K;
	string S;
	cin >> N >> K >> S;

	int score = 0;
	for (int i = 1; i < S.size(); i++) {
		if (S[i - 1] == S[i]) score++;
	}

	int ans = min(score + 2 * K, N - 1);
	cout << ans << endl;
	return 0;
}
```

#ポイント
##反転した範囲内の幸福な人数が変わることはない
選んだ範囲の両端については、反転後に隣にいるひとが変化するので、幸不幸が変化する可能性がある。

逆に両端以外については幸不幸は変化しない。LLやRRが連続しているところに幸福な人がおり、これは反転したところでLLがRRに、RRがLLになるだけなので、結局のところ選択した範囲内については幸不幸は変わらない。つまり、両端の人がなるべく幸せになるように選べば幸福な人数は減ることはない。
よって、最初に幸福な状態の人数を計算しておき、増やした人数を足していく。

##連続したLと連続したRのグループに分け、そのグループを選択して反転させる方針で
この時、
・端っこに存在するグループを選んだ場合、幸福な人数は1人増える
→隣の1グループと結合するため。
$H =$幸せ、$U =$不幸とすると、

例1）
$(R,R)(L,L) = (H,U)(U,H)$
↓
$(R,R,R,R) = (H,H,H,U)$

・端っこ以外のグループを選んだ場合、幸福な人数は2人増える
→両隣のグループと結合するため。

例2)
$(R,R)(L,L)(R,R) = (H,U)(H,U)(H,U)$
↓
$(R,R,R,R,R,R) = (H,H,H,H,H,U)$


このため、端っこ以外のグループを優先して選んでいくのが最適となる。
2人増やす操作を進めていくと最終的にLとRのグループが一つずつの状態になり、この時は先述した通り1人しか増やせない。1人増やす操作の後は、LのみかRのみの状態になり、こうなるとグループが一つしかない以上グループを選んで反転させたところでLがRに、RがLになるだけで端の一人はどうあがいても不幸な状態のままである。

よって、操作回数に制限がない場合は、

$幸福な人の初期人数+2+2+2+・・・+2+2+1+0+0+・・・$←①

といった計算をすることになり、$K$回まで操作が行えるならば①の第$K$項までの和を求めればよいことになる。

##結局、(幸せな初期人数 + 2 * 操作回数, 人数 - 1)のうち、小さいほうが答え
最終的に、端っこの1人はどうあがいても不幸な状態のままである。
ということは、言い換えればこのとき1人を除いて幸せであり、以後この状態からは変化しないのだから、幸せな人数は操作回数が無制限の場合必ず$N-1$人に落ち着く。

ここで操作回数が$K$回であると考える。
2人増やす操作を$K$回行ったとすると、

$幸福な人の初期人数 +2K$ ←②

として表せる。

$K$が十分に大きいとき、①は②の数列と比較すると、明らかに+1以後の部分から和は小さくなっている。これを具体的に見ていく。

2人増やす操作をしている間は

①：$幸福な人の初期人数 +2K$ 
②：$幸福な人の初期人数 +2K$ 

であり、1人増やす操作以後は

①：$N-1$
②：$幸福な人の初期人数+2K(①<②)$

であることがわかる。
従って、どのタイミングでも①の答えが出力されるようにすることを考えると、最終的な答えは

$min(幸福な人の初期人数 +2K,N-1)$

となる。
【Ruby】AWS SSMパラメータストアの値を取得する

## 関連

- [【Node.js】AWS SSMパラメータストアの値を取得する - Qiita](https://qiita.com/kou_pg_0131/items/4bc1053678b34cbc59c2)

## 準備

`aws-sdk-ssm`をインストールする。

下記コマンドを実行するか、`Gemfile`に追記する。

`aws-sdk`をインストールしてもいいが、結構サイズが大きいので基本的には必要なものだけインストールするようにした方がいいと思う。

```bash
gem install aws-sdk-ssm
```

or

```ruby
gem 'aws-sdk-ssm'
```

## サンプルコード

今回はAWS SSM パラメータストアに以下のようなパラメータが作成してある。

| パラメータ名     | 値         |
| ---------------- | ---------- |
| sample-parameter | HOGEHOGE!! |

```ruby
require 'aws-sdk-ssm'

# 認証情報
# `~/.aws/credentials`に認証情報が設定されている場合、
# または環境変数`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`に認証情報が設定されている場合は
# `access_key_id`と`secret_access_key`は不要
credentials = {
  access_key_id: 'xxxxxxxxxxxxxxxxxxxx',
  secret_access_key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  region: 'ap-northeast-1'
}

# SSMクライアントを生成
ssm_client = Aws::SSM::Client.new(credentials)

# リクエスト
request = {
  name: 'sample-parameter', # パラメータ名
  with_decryption: true     # 暗号化されている場合は復号し、暗号化されていない場合は何もしない
}
response = ssm_client.get_parameter(request)

pp response
# => #<struct Aws::SSM::Types::GetParameterResult
#     parameter=
#      #<struct Aws::SSM::Types::Parameter
#       name="sample-parameter",
#       type="SecureString",
#       value="HOGEHOGE!!",
#       version=1,
#       selector=nil,
#       source_result=nil,
#       last_modified_date=2019-09-13 00:28:02 +0900,
#       arn="arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:parameter/sample-parameter">>

puts response.parameter.value
# => HOGEHOGE!!
```

## 参考

- [Class: Aws::SSM::Client](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SSM/Client.html#get_parameter-instance_method)
vue/dist/vue.esm.js って何~【とりあえず動くからいいや】からの卒業~

- [イチロー引退　グラウンドでの最後の勇姿　2019MLB開幕2戦目8回裏YouTube
](https://www.youtube.com/watch?v=DBWm0HoyJ6c)をBGMにモチベーション爆上がり中のsukezaneです。

# 本記事執筆の経緯
- こちらの素晴らしいチュートリアル記事の中で筆者さんがわからないって言っていたモノに対して調べようと思ったことがきっかけ
- [Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた](https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11)
- ※本記事のタイトルは決して上記の筆者さんを否定するものではないですし、むしろ自分で調べなかったら絶対気にすることなかったので感謝です！！

# 何についての記事か
### vueを読み込む際に使っているコレ
`import Vue from 'vue/dist/vue.esm.js'`

# 対象読者
- vueの入門者（わたし）

# どうやって使っているか
```javascript:app/javascript/packs/todo.js

import Vue from 'vue/dist/vue.esm.js'
import Header from './components/header.vue'

 var app = new Vue({
   el: '#app',
   components: {
    'navbar': Header,
  }
 });
```

### こんな感じで意味もわからずなんとなく使っている
### <font color="Salmon">でも時々`import Vue from 'vue'`って書いてるやん？</font>

# 何が違うか
- `import Vue from 'vue/dist/vue.esm.js'`: <font color="DeepSkyBlue">完全ビルド（vue.esm.js）</font>
- `import Vue from 'vue'`: <font color="DeepSkyBlue">ランタイム限定ビルド（vue.runtime.esm.js）</font>

###って呼ぶらしい。

# 何が違うかPart2
[公式](https://jp.vuejs.org/v2/guide/installation.html#%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0-%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%81%A8%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E9%99%90%E5%AE%9A%E3%81%AE%E9%81%95%E3%81%84)より抜粋

> ### ランタイム + コンパイラとランタイム限定の違い
もしクライアントでテンプレートをコンパイルする必要がある (例えば、 template オプションに文字列を渡す、もしくは DOM 内の HTML をテンプレートとして利用し要素にマウントする) 場合は、コンパイラすなわち完全ビルドが必要です。

```javascript:hoge.js
// これはコンパイラが必要です
new Vue({
  template: '<div>{{ hi }}</div>'
})

// これはコンパイラは必要ありません
new Vue({
  render (h) {
    return h('div', this.hi)
  }
})
```

# どうすればいいのか１

- html側に<font color="Salmon">テンプレートの参照</font>を書かずに単一ファイルコンポーネント側にまとめ、html側ではマウントするDOMの情報だけを書くようにする


- 例）クリックした時に何かするやつ（<font color="Red">修正前</font>）

```html:click.html
<div id=#app>
  <button v-on:click="myClick">Click me!</button>
</div>
```

```javascript:click.js
import Vue from 'vue/dist/vue.esm.js'

const app = new Vue({
  el: "#app",
  methods: {
    myClick() {
      alert("click")
    }
  }
})
```

- 例）クリックした時に何かするやつ（<font color="DeepSkyBlue">修正後</font>）

```html:click.html
<div id=#app></div>
```

```javascript:click.js
import App from '../app.vue'

document.addEventListener('DOMContentLoaded', () => {
  const app = new App
  app.$mount('#app')
})
```

```haml:app.vue
<template>
  <button v-on:click="myClick">Click me!</button>
</template>

<script>
import Vue from 'vue'

export default Vue.extend({
  methods: {
    myClick() {
      alert("click")
    }
  }
})
</script>

```

### 疎結合になってメンテもしやすそう！！

# どうすればいいのか2
- 一応エイリアスを作成すれば完全ビルドの書き方のままでも動くんだけど

> ランタイム限定ビルドは完全ビルドに比べおよそ 30% 軽量

と公式にあるため基本は1がいいと思うが `30%くらい別にいいわ`っていうときはエイリアスを作成すれば`import Vue from 'vue'`としてimportできるようになります。（`実態は完全ビルドなんですけどね`）

### エイリアスを作成する（パフォーマンス30%減）
- `webpack`の場合

```javascript:webpack.config.js
module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' webpack 1 用
    }
  }
}
```


### 2年目も後半になったので`とりあえず動くからいいや`は卒業しようと思います。
なんかあったらコメントくださいませ
以上。
Salesforce DX Project Templateを利用した開発をクイックスタートするシェルスクリプト

こんにちは。先日の記事で書いた [Salesforce DX Project Template for Remote Development on VS Code](https://qiita.com/takahito0508/items/f2bf8bbd503e8865747f) を利用して Salesforce のデモを作ることが増えてきました。毎回同じ作業を手動でポチポチやるのが面倒です。

そこで以下のようなスクリプトを作成しました。これを実行するだけで手間をかけずにクイックスタートできるようになりました。主に自分用に用意したものですので、よかったらカスタマイズしてご利用ください。

```sh:sfdx-project-template-quickstart.sh
#!/bin/sh

export PROJECT_ROOT=プロジェクトを作成したい場所のパス
export PROJECT_NAME=プロジェクト名
export DEFALT_ORG_ALIAS=デプロイ先の開発環境のエイリアス
export GIT_REMOTE=Gitのリモートリポジトリ

cd ${PROJECT_ROOT}

echo
echo -----------------------------------
echo install vscode-remote-sfdx-project
echo -----------------------------------
git clone https://github.com/takahitomiyamoto/vscode-remote-sfdx-project.git
mv vscode-remote-sfdx-project ${PROJECT_NAME}
rm -rf ${PROJECT_NAME}/.git

echo
echo -----------------------------------
echo install lwc-recipes
echo -----------------------------------
git clone ${LWC_RECIPES_DUMMY_URL}
rm -rf ${PROJECT_NAME}/force-app
mv -f ${LWC_RECIPES_DUMMY}/force-app ${PROJECT_NAME}
mv -f ${LWC_RECIPES_DUMMY}/data ${PROJECT_NAME}
rm -rf ${LWC_RECIPES_DUMMY}

cd ${PROJECT_NAME}

echo
echo -----------------------------------
echo set git remote repository
echo -----------------------------------
git init
git remote add origin ${GIT_REMOTE}

echo
echo -----------------------------------
echo install node_modules
echo -----------------------------------
chmod +x ./initNodeModules.sh
./initNodeModules.sh

echo
echo -----------------------------------
echo execute code format and test
echo -----------------------------------
npm run prettier
npm run test

echo
echo -----------------------------------
echo create scratch org
echo -----------------------------------
sfdx force:org:create -a ${DEFALT_ORG_ALIAS} -f config/project-scratch-def.json -s

echo
echo -----------------------------------
echo set defaultusername
echo -----------------------------------
sfdx force:config:set defaultusername=${DEFALT_ORG_ALIAS}

echo
echo -----------------------------------
echo deploy lwc-recipes
echo -----------------------------------
sfdx force:source:deploy -u ${DEFALT_ORG_ALIAS} -p force-app

echo
echo -----------------------------------
echo assign permission set
echo -----------------------------------
sfdx force:user:permset:assign -n recipes

echo
echo -----------------------------------
echo import data
echo -----------------------------------
sfdx force:data:tree:import --plan ./data/data-plan.json

echo -----------------------------------
echo open org
echo -----------------------------------
sfdx force:org:open -u ${DEFALT_ORG_ALIAS}
code .
```

Salesforce 画面と VS Code が立ち上がったら OK です。それでは。

Happy Coding!!
macOS Mojaveにバージョンアップ後、VirtualBox/Vagrantが動かない場合の解消方法


以前、macOSをMojaveにバージョンアップした際に、ローカルで開発環境で使っていたVirtualBox/Vagrantが動作しなかったため、その解消手順をまとめました。
使用していたバージョンが古かったこともありますが、以下の手順で解消したので参考にしてみてください。

## 原因
[こちら](https://applech2.com/archives/20180705-oracle-virtualbox-initial-support-macos-mojave.html
)の記事にあることが原因のようです。
私は以下を実行して解消しました。

## VirtualBoxのバージョンアップ

VirtualBoxのバージョンが古い場合は[公式サイト](https://www.virtualbox.org/wiki/Downloads)より最新バージョンをダウンロードしてインストールしましょう。


## Vagrantのバージョンアップ

VirtualBoxとVagrantを連携している場合は、以下の手順でVagrantのバージョンアップも実施しましょう。

1. [公式サイト](https://www.vagrantup.com/downloads.html)よりmacOSの最新バージョンをダウンロード&インストール
2. 以下のコマンドをターミナル上で実行

```
$ vagrant plugin repair
$ vagrant plugin expunge --reinstall
$ vagrant plugin update
```

こちらのコマンドはrepair出来ない場合に後述のコマンドを実行するようですが、
私の環境では改善出来なかったため、後述のコマンドも実行しました。

## 仮想OSの再インストール/ビルド

VirtualBox/Vagrantをバージョンアップしたら、仮想OSも再インストール/ビルドした方が良いでしょう。

## 参考
* [Oracle、macOS 10.14 Mojaveでインストールできない問題を修正した「VirtualBox v5.2.14」をリリース。 | AAPL Ch.](https://applech2.com/archives/20180705-oracle-virtualbox-initial-support-macos-mojave.html)
* [macOS 10.14 MojaveでVirtualBoxが動かなくて困った話](https://qiita.com/kai_kou/items/4f554a515ea7926702df)
* [VirtualBoxの不具合のフォーラム](https://forums.virtualbox.org/viewtopic.php?p=424309#p424309)
AppGoatで学ぶウェブサーバの異常終了（ヒープ領域）

# ヒープ領域とは？

『山積み』という言葉の中の『山』という意味であり、プログラムが実行時にサイズを指定して確保できるメモリ上の領域の一つです。
※セットで説明されるメモリ領域に、スタック領域が挙げられます。

AppGoatではC/C++を前提に学ぶため、プログラマーがメモリ領域の確保/解放を意識する教えとなっていますが、
例えば.Net系の言語ならガベージコレクションがこの辺りをやってくれます。
自分が良く使う言語はどの様な仕様なのだろう？と調べるきっかけを与えてくれるのが、AppGoatで学ぶ一番の利点なのかもしれません。

# C/C++でヒープ領域を扱うプログラム例

以下のCで書かれたコードを読んでみましょう。



```c:heap.c
 char* str_dup(char* string) {
      unsigned char size = 0;
      char* buffer = NULL;

      if (!string)
          return NULL;

      // ①変数sizeはunsigned char型で文字列の長さを受け取る
      // +1 は Null 文字分
      size = strnlen(string, 1000) + 1;

      // ②変数sizeを使ってバッファを確保
      buffer = (char*)malloc(size);
      if (!buffer)
          return NULL;

      // ③strcpy関数で受け取った文字列stringをコピー
      strcpy(buffer, string);
      return buffer;
  }
```

引数で渡された文字をコピーして返すC言語のソースです。
平成生まれ以降には少しなじみの浅い書き方なのかなと思います・・・


# 何が問題なのか？

1. 10行目で文字列の長さをunsigned char型のsizeで受け取っています。ここが諸悪の根源であり、unsignd charは255までしか入りません。
   ※300文字の文字列を受け取ったら、sizeに45が格納されます。

2. 13行目で(1)で確保したサイズ分mallocでメモリ領域を確保します。

3.18行目で受け取った文字列stringとstrcpy関数を使って変数bufferにコピーする訳ですが、仮に300文字来た場合、45バイトしかメモリを確保していないため、255バイト分溢れてしまい、バッファーオーバフローを引き起こしてしまいます。

# 打つべき対策
IPAにC/C++に詳しい対策が載っていますので、興味がある方はご確認ください。
https://www.ipa.go.jp/security/awareness/vendor/programming/index.html

C/C++以外の言語の場合、コードで担保というより言語での担保になるので環境のパフォーマンスチューニングの世界になるのかなと思います。

Javaの場合
https://qiita.com/opengl-8080/items/64152ee9965441f7667b

Goの場合(意識する必要ないといった記事もちらほらありますが、githubのソースを。)
https://github.com/golang/go/blob/master/src/runtime/malloc.go

Pythonの場合(メモリ管理の崩壊を避けるため、Python オブジェクトを C ライブラリが公開している関数で操作しようとしてはなりません。という注意書き付き)
https://docs.python.org/ja/3/c-api/memory.html

C/C++に存在した脆弱性を知ると、今流行りの言語の方針が知れてとても面白いです。
それではまた次回。
Eris+VoiceTextWebAPIでしゃべるDiscordBot

# DiscordBotをしゃべらせる
DiscordBotをボイスチャットに参加させて特定のチャンネルの内容を話させる。Node.jsを利用。
## 処理の内容
開始のコマンドでボイスチャットに参戦させる
↓
開始コマンドを打ち込んだチャンネルの投稿を取得する
↓
VoiceTextWebAPIで文字を音声に変換する
↓
ボイスチャットに流す
↓
(繰り返し)
↓
終了コマンドでボイスチャットから出る
## 下準備
DiscordBot用のAPIKEYを取得しておく。
参照→[簡単なDiscord Botの作り方（初心者向け）](https://note.mu/bami55/n/ncc3a68652697)

VoiceTextWebAPI用のAPIKEYを取得しておく。
[VoiceText Web API](https://cloud.voicetext.jp/webapi)
ここから無料利用登録するとAPIKEYがメールで送られてきます。

ffmpegを導入しておく
Windowsだけ挙げておく
[【windows】FFmpegをインストールする手順](https://fukatsu.tech/windows-ffmpeg)

npm等パッケージマネージャでeris,voice-textをインストールしておく

## 実際のコード
```javascript:server.js

const eris = require("eris");
let bot = new eris("<DiscordのAPIKEY>");

const {VoiceText} = require("voice-text");
const vt = new VoiceText("<VoiceTextWebAPIのAPIKEY>");

const VOICE_CONNECTION = null;
const TtoV_CHANNEL = "";


bot.on("ready", () => {
    console.log("bot is ready");
});

bot.on("messageCreate", (msg) => {
    // botのメッセージは無視
    if (msg.author.bot) return;
    // ボイスチャンネルに入っているかどうか
    let isConnection = !!VOICE_CONNECTION;
    // 開始コマンド !startspeech
    if(msg.content=="!startspeech"&&!isConnection)
    {
        const vc = msg.member.voiceState.channelID;
        // メッセージを書いた人がボイチャにいるかどうか
        if(!!vc)
        {
            // メッセージを書いた人のいるボイスチャットに入る
            TtoV_CHANNEL = msg.channel.id;
            bot.getChannel(vc).join().then(connection => {
                VOICE_CONNECTION= connection;
                bot.createMessage(TtoV_CHANNEL, "Start Speech");
            });
        }else{
            bot.createMessage(msg.channel.id, "You must join a voice channel before you use it.");
        }
    }else if(msg.channel.id==TtoV_CHANNEL)
    {
        // 終了コマンド　!endspeech
        if(msg.content == "!endspeech")
        {
            if(!!isConnection){
                VOICE_CONNECTION.disconnect();
                VOICE_CONNECTION = null;
                bot.createMessage(TtoV_CHANNEL, "End Speech");
                return;
            }
        }else{
            // ボイスで話している途中に追加で話されるとエラーが発生する。
            // 対策としてはスタックにどんどんメッセージを入れるようにするなど
            // ボイスが終了するイベントが取得できれば改善される（未実装）
            try{
                // APIの制限で200文字までしか話せない
                let stream = vt.stream(msg.content.slice(0,200), {
                    speaker: "hikari"
                });
                const dispatcher = VOICE_CONNECTION.play(stream);
            }catch(e){
                bot.createMessage(TtoV_CHANNEL, "Wait until the end of the voice.");
            }
        }

    }
});


bot.connect();
```

## まとめ
かなり少ない行数で実装可能。
ただし、ボイスで話している途中に追加で話されるときに出るエラーの対策ができていないので注意。
対策したら追記します。
jQueryのcssをJavaScriptで書き換えたらこうなる一例

自分自身の基礎力向上のために、jQueryで作ったコードがJavaScriptで書いたらどのようになるか書いてみています。もし、他にも方法がありましたら、ご教示いただけると嬉しいです。

# 結果
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127391/615ef629-b3f7-cf89-54d0-a377614572d7.gif)

# jQueryのhover
## jQuery

```javascript 
 $('button').hover(function () {
 //マウスカーソルが重なった時の処理
 $('button').css('background-color', '#f00');
 },
 function () {
 //マウスカーソルが離れた時の処理
   $('button').css('background-color', 'yellowgreen');
 })
```
## JavaScriptのみ
```javascript
 const target = document.getElementById('target');
 target.addEventListener('mouseenter', () => {
   target.style.backgroundColor = '#f00';
 }, false);

 target.addEventListener('mouseleave', () => {
   target.style.backgroundColor = 'yellowgreen';
 }, false);
```
[HTMLElement.style
](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/style)
RxSwiftをCarthageで入れたら実機で起動できなかったので、RxRelayも追加して解決した

RxSwiftとRxCocoaを追加後、ビルドはサクセスするのですが、実機で動作確認ししようとすると以下のエラーで落ちてしまいました。

```
dyld: Library not loaded: @rpath/RxRelay.framework/RxRelay
  Referenced from: /var/containers/Bundle/Application/xxxxxxx-xxxx-xxxx-xxxx-477EBE5CC202/xxx.app/xxx
  Reason: image not found
```
**今回の解決方法は、RxRelayも追加することでした。**

RxSwiftライブラリをビルドすると、以下の5つのフレームワークが生成されます。

- RxSwift
- RxCocoa
- RxRelay
- RxBlocking
- RxTest

RxSwift, RxCocoaのみXcodeで追加すれば良いと思っていたのですが、どうやらRxRelayも必要みたいですね🤔

`TARGETS -> General -> LinkedFrameworks and Libraries` にRxRelayも追加し、
Build Phases の Input Files Lists, Output Files Lists にも追記しました。

```input.xcfilelist
$(SRCROOT)/Carthage/Build/iOS/RxSwift.framework
$(SRCROOT)/Carthage/Build/iOS/RxCocoa.framework
$(SRCROOT)/Carthage/Build/iOS/RxRelay.framework
```

```output.xcfilelist
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxSwift.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxCocoa.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxRelay.framework
```

以上で、無事に実機での動作確認を行えるようになりました。
ドットインストールで構築したLAMP環境のPHPを最新バージョンにアップデートする手順

### 概要

[ドットインストール](https://dotinstall.com/)を参考にローカル開発環境を構築すると初めての人でも簡単にできますよね？私もお世話になった一人だったのですが、バージョンが古いのでいろいろと不都合があることもしばしば。

自分でアップデートしようにも、構築段階でブラックボックスな部分があって結局どうやってバージョンアップしたらいいのかわからない。という悩みを抱えている人は割と多いのかなって思います。

という事でこの記事では手っ取り早くドットインストールで構築したローカル開発環境のPHPバージョンを7.3にアップデートする手順を記載してます。

### 手順

#### 必要なリポジトリの追加

```console
$ sudo yum install epel-release
$ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
```

※REMIリポジトリのURLはCentOS 6.x用のためCentOS 7.xの場合は正しく追加されません（たぶん

#### 既存PHP環境の削除

```console
$ sudo cp /etc/php.ini /etc/php-old.ini
$ sudo yum remove php-*
```

#### PHP最新環境構築

```console
$ sudo yum install libxml2-devel libxslt-devel libedit-devel
$ sudo yum install --disablerepo=* --enablerepo=epel,remi,remi-safe,remi-php73 php php-mbstring php-mysqlnd php-intl php-gd php-xml php-pecl-zip php-devel
```



### 参考文献

この記事は下記記事を参考に執筆しています。

#### 既存PHP環境の削除、PHP最新環境構築

CentOS7のPHPを5.6／7.0／7.1／7.2／7.3系にバージョンアップする
https://qiita.com/heimaru1231/items/84d0beca81ca5fdcffd0

#### 開発版のインストール

CentOSにlxmlをインストールするときにlibxml/xmlversion.hがないと怒られる場合の対処法
https://qiita.com/zabeth129/items/da3e053e303f783af9a4

#### 追加しているリポジトリの詳細

CentOSのyumレポジトリ: EPEL, Remi, Software Collectionsの違いとまとめ
https://qiita.com/takeshi_nozawa/items/ee01981b4fc338209437
今回、アプリ内でQRコードを生成して表示する必要があったのでRSBarcodesを使いました

##バーコード生成用クラスを作成
```swift
import AVFoundation
import UIKit
import RSBarcodes

/// バーコードを生成する
final class BarcodeGenerator {
    
    /// 生成予定のコードを検証する
    func validateCode(_ code: String, codeObjectType: AVMetadataObject.ObjectType) -> Bool {
        
        return RSUnifiedCodeValidator.shared.isValid(
            code,
            machineReadableCodeObjectType: codeObjectType.rawValue
        )
    }
    /// コードを生成する
    func generateCodeImage(_ code: String, codeObjectType: AVMetadataObject.ObjectType) -> UIImage? {
        
        return RSUnifiedCodeGenerator.shared.generateCode(
            code,
            machineReadableCodeObjectType: codeObjectType.rawValue
        )
    }
    /// スケールを使ってリサイズする
    func resizeCodeImage(_ image: UIImage, scale: CGFloat) -> UIImage? {
        
        return RSAbstractCodeGenerator.resizeImage(image,
                                                   scale: scale)
    }
    /// サイズを指定してリサイズする
    func resizeCodeImage(_ image: UIImage, size: CGSize, contentMode: UIView.ContentMode) -> UIImage? {
        
        return RSAbstractCodeGenerator.resizeImage(image,
                                                   targetSize: size,
                                                   contentMode: contentMode)
    }
}
```
専用のクラスを用意して、ライブラリが持つ機能をメソッド化しました。
`import AVFoundation`は必須です。

QRコードを生成する場合は、`codeObjectType: AVMetadataObject.ObjectType`を`.qr`と指定します。
2進数


## PCの基礎

### 2進数

- なぜ2進数が必要なのか？
　- PCは全て数字で表現できる
　- 数字でモノを表現する事を`コード`という。
　  - 文字を数字で表したモノ = `文字コード`
　  　- ex) 【あ】、は数字で表すと【3041】になる
　  - 色を数字で表したモノ = `カラーコード`
　    - ex） 【黄色】は【#FFFF00】ここからまた数字にするのではなかろーか 



### 文字コード

文字コードはよく出てくるので少し深掘り

- 文字化けは何で起こるのか？
  - 文字にも種類がある
    - 英語、日本語など。
    - 英語 = 【ASCII】　日本語 =　【Shift-jis】

- 違いが起こると何が発生するか？
　- DBを使う時、デフォルトの文字コードは【ASCII】（多分）
　- 作る人はだいたい海外の人が先だからね。
　- それで日本語で何かをしようとすると【文字化け】が起こる　※メールとかも


### 2進数

前置きが長くなったけど、このように実はPCのベースは2進数で行われいるので、
2進数も基本ぐらいは理解しておく必要がある

- 2進数と10進数
　- 僕らが使っているのは10進数
　- 10進数（人間の数） と2進数（PCの数） を行き来する必要あり


ex）

10進数       2進数
8     =    1000


8は  2の3乗  2の1乗でできている

1000
Google Colaboratory を使う上で工夫したことのまとめ

## 概要

Google Colaboratory (以下、Colab と呼ぶ） は Google が提供するクラウド版 Jupyter notebook （的な）サービスである。いくつかの制約はあるが、GPUが無料で使えるのがすごい。最近、これを使う機会が多かったので、私なりの使いこなしのコツを書いていきたい。

## 使いこなしのコツ

### 1. Google Drive をマウントする

Colab は Docker のコンテナとして動いているらしい。numpy, pandas, sklearn, tensorflow, torch 等のパッケージはあらかじめインストールされているものの、計算に必要なデータはどこか他から持ってくる必要がある。一番簡単なのは、Google Drive をマウントするやりかたであろう。

```python
 from google.colab import drive
 drive.mount('/content/drive')
```

とすると、認証画面へのリンクが表示されるので、そこで必要な認証が行われる。あとは、`/content/drive/My Drive` に自分の Google Drive がマウントされているのが見えるはずだ。
（自分の Google Drive の全体がマウントされてしまうことに注意。一部のパスだけマウントできると聞いたこともあるが、やったことはない）

どうやら `My Drive` という名前は変えられないようなので、私は、

```
ln -s "/content/drive/My Drive" /content/gdrive
```
として、 `/content/gdrive` でアクセスできるようにしている。
(空白を含まないパスにするため）

### 2. Colab 上でもローカルPCでも動くようにする

Colab のファイルは拡張子が `.ipynb` であり、基本的には Jupyter notebook である。実際に、テキストエディタで開いてみると、これは JSON 形式で、Jupyter notebook に加えて、 Colab 特有の属性をいくつか書き加えたものであることがわかる。

Colab のファイルはデフォルトで、 Google Drive の `/Colab Notebooks` というパスに置かれる。通常は、ここからファイルとして直接ダウンロードしてもよい。 通常の `Jupyter notebook` と比較すると、こちらには改行がない。そこで `cat hoge.ipynb | jq . > hoge2.ipynb` などとして、JSON を整形すると見やすくなる。

ただ、どうも編集中の Colab のファイルは、直接 `/Colab Notebooks` からコピーすると、ファイルの中身が壊れていることがあった。そこで、 Colab の `.ipynb をダウンロードする` のメニューからダウンロードしたほうが安全である。また、ここからダウンロードすると、JSON にはちゃんと改行がある。

Colab 環境では `/content` がホームディレクトリになるので、私は、ローカルPC上でも `/content` ディレクトリを作っている。そして、その下に適当にディレクトリを作ることによって、 Colab でもローカル PC でも同じように利用することができる。

Colab かローカルPC かの判定のために次のようなコードを利用している。


### 3. 日本時間へタイムゾーン変更
Colab のタイムゾーンはデフォルトで UTC なので、これを日本標準時に変更。

```python
if on_colab:
    !rm /etc/localtime
    !ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
    !date
```

### 4.　起動時間表示 
Colab は最初に立ち上げたインスタンスが12時間後に強制シャットダウンされて、保存したデータもすべて失われるので、経過時間を知ることは重要。


```python
if on_colab:
    !cat /proc/uptime | awk '{print $1 /60 /60 " hours (" $1 "sec)"}'
```

### 5. 90分のアイドルタイムアウトに対応

連続12時間の制限とは別に、90分間、Colab に触らないでいると、強制的にシャントダウンされてしまう。
これを防ぐためには、別の Colab ノートブックを開いて（ただしハードウェアアクセラレーターの設定は同じにする必要がある）、そこで次のようなコードを実行する。

```python
import time


while True:
    time.sleep(3600):
    !date
    !ps ax # これはなくてもよい
```

こうすることでインスタンスをインスタンスを継続的に使うことができる。

### 6. Colab をずっと使っているとブラウザが激重になる現象

私の環境だけの問題かもしれないが、Colab で計算をしていると、ブラウザ(Google Chrome)がだんだん重くなっていく現象があった。どうも、Colab のノートブックをブラウザで開いていると、バックグランドで常に通信が発生して、それが重さの原因なるっぽい。画面表示があまりない場合には、ブラウザが重くなることはあまりなかった。そこで、計算に長時間要する場合には、5.のようにして、実行中のインスタンスが落ちないようにしたうえで、長時間の計算をしているノートブックを閉じてしまうとよい。インスタンスが落ちない限りはブラウザ上で表示されていなくても、計算は続行している。ふたたび、そのノートブックを開くと、閉じていたときに生成された画面出力も含めて、再びすべてが表示される。

## まとめ

他にもいろいろあったような気もするが、とりあえず以上である。また何か思い出したら追加する。
TypeScript導入編

Vue.jsで開発したアプリケーションにTypeScriptを導入したので、その備忘録を。

## TypeScriptをinstall

globalでinstallする記事がありましたが、ここはプロジェクトごとにinstallさせました。

``` terminal
$ yarn add -D typescript
```

## tsconfig.jsonを作成と設定

``` terminal
$ tsc --init
```

### 設定項目

- コンパイラが出力するJavaScriptのバージョンはes5を対象とする
- ブラウザ向けのプログラムなので`DOM`を指定
- source mapをtrueにする
- 厳格モードをtrue(必須)
- 対象ファイルをsrcディレクトリのtsファイルにする
- node_moduleの中のtsファイルは対象外
- angularのテストファイルは対象外

``` json:tsconfig.json
"compilerOptions": {
  "target": "es5",
  "module": "es2015",
  "lib": ["DOM", "ES2015"],
  "sourceMap": true,
  "strict": true,  
  "moduleResolution": "node",
},
"include": [
  "src/**/*"
],
"exclude": [
  "node_modules",
  "**/*.spec.ts"
]
```

## webpackでtsファイルをバンドル対象にする

webpackでバンドルするときにtsファイルも対象にしたいので指定

- ts-loaderをinstall
- webpackでtsファイルをバンドル対象にする
- ファイルをimportするときに拡張子を指定しなくてもいいようにextensionsを指定

``` terminal
$ yarn add -D ts-loader
```

``` javascript:webpack.config.js
module: {
  rules: [
    {
      test: /\.ts$/,
      use: 'ts-loader',
    },
  ]
}
resolve: {
  extensions: ['.ts'],
},
```

## npmのタスクランナーでwatchさせる

``` json:package.json
"scripts": {
  "start": "concurrently \"webpack-dev-server --config webpack.dev.js\" \"yarn run tsc -- -w\"",
  "tsc": "tsc -p ./"
}
```

## 設定時のエラー

コンパイルしたときに下記のエラーが出た場合

### moduleResolutionの設定

```
File change detected. Starting incremental compilation...
[1] 
[1] node_modules/@types/babel__core/index.d.ts(13,20): error TS2307: Cannot find module '@babel/types'.
[1] node_modules/@types/babel__core/index.d.ts(14,31): error TS2307: Cannot find module '@babel/parser'.
[1] node_modules/@types/babel__generator/index.d.ts(9,20): error TS2307: Cannot find module '@babel/types'.
[1] node_modules/@types/babel__template/index.d.ts(9,31): error TS2307: Cannot find module '@babel/parser'.
[1] node_modules/@types/babel__template/index.d.ts(10,54): error TS2307: Cannot find module '@babel/types'.
[1] node_modules/@types/babel__traverse/index.d.ts(10,20): error TS2307: Cannot find module '@babel/types'.
```

`tsconfig.json`の`moduleResolution`を`node`にすると解決

``` json:tsconfig.json
"compilerOptions": {
  "moduleResolution": "node",
```

### moduleの設定

```
Uncaught ReferenceError: exports is not defined
Object.defineProperty(exports, "__esModule", { value: true });
```

`tsconfig.json`の`module`を`es2015`にすると解決

``` json:tsconfig.json
"compilerOptions": {
  "module": "es2015",
```

## 参考サイト

- [jsで書いたフロントを徐々にtsに移行する](https://qiita.com/pokotyan/items/f568679cd27bbf888435)
- [typedoc throws "Cannot find module '@babel/types'." errors with jest 24](https://github.com/facebook/jest/issues/8218)
LWC Basic

先日 2019.09.11(水) 、弊社の大阪オフィスにてLightning Web Components初級レベルの勉強会を開催しました。
https://accenture-technology.connpass.com/event/142560/

コンセプトは、理解してから書くのではなく「書いてから理解する」 ことです。理解するまでに時間を使うよりも、とにかく書いて眺めることからはじめましょう、という想いを込めています。教材コンテンツは GitHub に公開していまして、これからも育てていきたいと思っています。
https://takahitomiyamoto.github.io/lwc-basic/

より多くの人の目に留まるよう、Qiita でも紹介させていただきました。フィードバックございましたらどうぞよろしくお願いいたします。

Happy Coding!!
Kotlinと図で学んでみるデザインパターン -1章 Iteratorパターン-


# Iteratorパターン
集合体の実装と、集合体を数え上げる実装を切り分ける

![update iterator.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187392/4a9482bf-4843-cb0c-27ca-0ad1a353dfcd.png)


```kotlin:
interface Aggregate {
    fun iterator(): Iterator
}
```
```kotlin:
interface Iterator {
    fun hasNext(): Boolean
    fun next(): Any
}
```
```kotlin:
data class Book(
        val name: String
)
```
```kotlin:
class BookShelf : Aggregate {

    private val books: MutableList<Book> by lazy {
        mutableListOf<Book>()
    }

    private var last: Int = 0

    fun getBookAt(index: Int): Book {
        return books[index]
    }

    fun appendBook(book: Book) {
        books.add(last, book)
        last++
    }

    fun getLength(): Int {
        return last
    }

    override fun iterator(): Iterator {
        return BookShelfIterator(this)
    }
}
```
```kotlin:
class BookShelfIterator(
        private val bookShelf: BookShelf,
        private var index: Int = 0) : Iterator {

    override fun hasNext(): Boolean {
        return index < bookShelf.getLength()
    }

    override fun next(): Any {
        val book = bookShelf.getBookAt(index)
        index++
        return book
    }
}
```

```kotlin:
fun main() {

    val bookShelf = BookShelf()

    bookShelf.apply {
        appendBook(Book("夜と霧"))
        appendBook(Book("愛と幻想のファシズム"))
        appendBook(Book("対岸の彼女"))
        appendBook(Book("不夜城"))
    }

    val iterator = bookShelf.iterator()

    while (iterator.hasNext()) {
        val book = iterator.next() as? Book
        println(book?.name)
    }

}
```

※ Java 言語で学ぶデザインパターン入門をKotlinと図で理解しようとしている学習用アウトプットです。
c++始めてみた：Visual Studio Code 使用方法２（c++erはどのExtensionを使うべき？？？）個人ノート1.9

# Visual Studio Code 使用方法２（c++erはどのExtensionを使うべき？？？）

諸事情でMacAirが使えなくなったのでUbuntuノートに変更しました。

ただOSが変わっただけなので、以前の流れで続けていきます。

あと、毎回Anaconda-Navigatorを起動するのが面倒になってきたので、
Ubuntuに直接VScodeをインストールしました

> 
[Linux(Linux)にVScodeをインストールする方法（英語）](https://code.visualstudio.com/docs/setup/linux)
    - 簡単に紹介するとterminalで
    - sudo snap install code --classic
    - これでTerminalからcodeとタイプするだけでVScodeが使える様になります

## 環境
Ubuntu 18.04.3 LTS
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
GNU Make 4.1

### 早速、（Visual studio code＋c++プログラミング）初心者が思った事１

c++erは、どのExtensionを使えばいいの？？？
必須、超役立つExtensionは？？？
なんか沢山のextensionがあって迷います
- microsoftが紹介するc/c++をinstall
- 終了
・
・
・
これだけ？？？

一応VScode自体をカスタマイズするのは楽しそうだと思ったので
（ゲームのアバターキャラをカスタマイズするみたいなので）

VScodeのオフィシャルサイトで紹介している「[イントロビデオクリップ集](https://code.visualstudio.com/docs?start=true)」を見た時に
file icon themeのカスタマイズ方法を紹介していたので
VScode Great Iconsをインストールしました！

あとは・・・分かりません！！！

## #追記
CMake関連のExtensionが必須との事で、良く使われている２つのCMake Toolを見つけました。

(1). https://marketplace.visualstudio.com/items?itemName=twxs.cmake#review-details
(2). https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools&ssr=false#review-details
Node.jsとは？

# 目的

- Slackでアプリを作成したときにNode.jsというものに触れたが不明なことが多かったため調べたことをまとめる。

# 特徴

- サーバで動くJavaScript
- 小さい計算が得意で速い
- マイクロソフトやYahooが推奨している
- リアルタイムWebの分野に強い
- 小規模で機動性の高いWebアプリで、リアルタイム性が求められるアプリに最適

# ちょっと深堀した特徴

- 非同期処理で動く(動作が高速な理由)
データベースからデータを取得するプログラムで同期処理の場合はデータベースからの反応を待つが、非同期処理だとデータベースからの反応を待っている間に別の処理を実行することができる。前述の方法をとっているため大量のアクセスを高速に処理することが可能。

- シングルスレットでメモリの消費効率化(小さい計算が得意な理由)
本来サーバに複数のアクセスがあった時にそれぞれにメモリを割り当てて実行する(マルチスレッド)が、１万人規模のアクセスがあるとメモリが上限にあたり効率が悪くなる。Node.jsでは一つのメモリでひとつずつアクセスを処理する方法をとることでメモリ効率を向上させている。  
一見一つのメモリで一つの処理しかできないため処理が遅そうに感じるが前述した非同期処理のおかげで、メモリでの処理を待たずして処理を実行できるため、少ないメモリ消費量を抑えて大量のアクセスを高速に処理できる。
PureJSでExcelライクなセル編集UIを実装

**※本記事の実装コードはこちら**：https://jsfiddle.net/jnado3g5/1/

# はじめに

個人的な興味がきっかけですが、Excelライクなセル編集UIをJavaScriptで作成する際の課題として、「**キー押下と同時にセル編集を開始する**」という仕様をどう実現するか、少々難しい問題があります。
厄介なのが**日本語入力**で、実際、（おそらく）有名な商用ライブラリである[Wijimo FlexGrid](https://demo.grapecity.com/wijmo/5/Angular/FlexGridIntro/FlexGridIntro/)でも、日本語入力を含むキー押下とセル編集開始は同時に行えないみたいです。
しかし、Googleスプレッドシートではそれが実現されているため、技術的に不可能ではなさそうです。

そこで、「キー押下と同時にセル編集を開始する方法」を調べて、実際に検証を行った結果を記します。

# 仕様
メインは「キー押下と同時にセル編集を行う方法」ですが、せっかくなので編集に関わるUIを一通り検証実装してみました。
なお、編集機能に焦点を当てているため、それ以外（行列追加削除等）は一切考えていません。

セル選択イメージ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299510/f2ff8c89-97ad-96bf-62eb-09aa86163338.png)

入力イメージ：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299510/f45d13b2-b258-ed60-fa6f-a4bc2aa5b86a.png)

- セル対してmousedownするとセルが選択されます
- セル選択された状態で次の動作をします
 - F2キーで既存の値の編集開始します
 - 通常の入力（Backspace、数値、アルファベット、日本語等）で新規入力開始します
 - セルをダブルクリックすると既存の値の編集開始します
 - Delキーで既存の値をクリアします（編集開始しません）
 - セルからフォーカスが外れる（セル部分以外をmousedownする）と、上記のようなセル編集開始が行われなくなります（編集開始には再度フォーカスが必要）
- セル編集中、次の動作をします
 - Enterキーを押されると入力終了して、入力された値をセルに反映します
 - Escapeキーを押されると入力終了して、入力された値を破棄します
 - フォーカスが外れると入力終了して、入力された値をセルに反映します

# 動作確認環境
次の環境で動作確認を行いました。なおOSはWindows10です。

- Chrome
- FireFox
- Edge
- IE11
- Opera

# キー押下と同時にセル編集を開始する方法
わかりやすく、実際は隠れている（y座標位置が-10000px）input要素を目に見えるようにすると、セル選択時は次のような状態になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299510/6874e7fb-9fe8-c4b3-4d84-a07bd5383bdd.png)

input要素にフォーカスが当たっているので、要素に対するinputイベントが拾えます。
初回inputイベント発生時、input要素をセルの位置に移動させれば、あたかも「キー押下と同時にセル編集を開始する」ようなUIが出来上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299510/5b9139f3-f260-c657-3cf7-a47dfca6c67e.png)

ただし、Backspaceキーではinputイベントが拾えないので、別途keydownイベントを拾って制御します。

# その他工夫
上記の方法で実装を行う場合、input要素に対して「編集前の待機状態　→　編集中　→　編集完了」と状態が遷移し、各状態で必要なイベントが異なります。
そのため、「次の状態に移ったら前の状態で登録していたイベントは破棄する」といった実装を組み込んでみました。
結果、ソースコードの見通しが良くなったかなという個人的な感想を持っています。

# おわりに
目指せ！個人開発でWijimo FlexGrid越え！（厳しい）
Mac開発 クイックスタートガイド

# はじめに
最近SIerを脱出しました。CLBです。
お仕事でMacを使いはじめましたが、セットアップする際に手間取ったのでメモを書きます。

# ターミナルの設定
初期状態のターミナルは白背景に黒文字と
とってもシンプルな感じですよね。いい感じにしましょう。

- ターミナルを開き、`ターミナル` > `環境設定` をクリックします。
- プロファイルタブのHomebrewテーマを選択し、設定画面下部の `デフォルト` をクリックします。

# lsコマンドに色を付ける
参考資料 https://qiita.com/cider-sk/items/9c6aaa66db80586399d8

Macのターミナル(Bash)の `ls` コマンド、ディレクトリとかに色が付かないんですよね。
実は `-G` オプションを付けることで、色を付けることができます。
手動で毎回オプションをつけるのは面倒なので、自動で付けるようにしましよう。
ホームディレクトリに`.bash_profile`ファイルを作成し、以下のように記述します。

```
alias ls='ls -G'
export LSCOLORS=gxfxcxdxbxegedabagacad
```

# キーボードのショートカット設定
デフォルト設定のMacで`ctrl` + `space` を同時押しすると、
スニペットではなく、スポットライトが起動してしまうので変更します。

- `設定` アプリ > キーボード をクリックします。
- ショートカットタブ > Spotlight の `Spotlightを表示` のショートカットを `command` + `shift` + `space` に変更します。

# 終わり
これで、基本的な初期設定は完了です。
あとは visual studio code(VSCode)の設定を行なって完了。
超初心者によるAWS EC2 Webサーバー構築メモ

こんにちは。Ideagearの林です。
今回は、AWS EC2でWebサーバーを構築するというミッションです。
が、単純に構築の方法は先人の方々によりとてもわかりやすくまとめられているのでこの記事には記しません。

この記事はちょっとタイトルでも専門用語が多くて狼狽えるという初心者による、初心者のための用語まとめと個人的に詰まったところの補足メモです。

#前提と環境
この記事は
[1](https://qiita.com/Arashi/items/629aaed33401b8f2265c)と[2](https://sil.hatenablog.com/entry/aws-ec2-free-webserver)と[3](https://bitwave.showcase-tv.com/aws%E5%88%9D%E5%BF%83%E8%80%85%E3%81%8C%E3%82%8F%E3%81%9A%E3%81%8B5%E5%88%86%E3%81%A7web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/)
これら3つの記事を参考にしています。

PuTTYを使います。OSはWindowsです。

#用語集
###AWS、EC2
AWS : Amazon Web Servicesのこと。
EC2(Amazon Elastic Compute Cloud)はAWSの機能の一つ。
クラウド上でサーバの作成、破棄、追加などが簡単に行えるサービス。

###インスタンス
EC2から立てられたサーバの一つを指すケースが多い。(必ずしもそうではない)

###S3
S3 : Simple Storage Serviceのことで文字通りストレージサービス。
クラウド上にデータを保存できる。

###SSHクライアント
SSHで接続「する方」のコンピュータや、接続するときに使うプログラムのこと。

###SSH
ネットワークを経由して他のコンピュータ(主にサーバ)に接続し、遠隔操作するための仕組み。やりとりする情報は全て暗号化してくれる。

#補足
とりあえず何も考えず[1](https://qiita.com/Arashi/items/629aaed33401b8f2265c)、[2](https://sil.hatenablog.com/entry/aws-ec2-free-webserver)、[3](https://bitwave.showcase-tv.com/aws%E5%88%9D%E5%BF%83%E8%80%85%E3%81%8C%E3%82%8F%E3%81%9A%E3%81%8B5%E5%88%86%E3%81%A7web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/)を参考に進めていたところ少々詰まってしまったところについて、解決方法をまとめます。

##インスタンス作成後、SSHでアクセス
全然読みもせず3つのサイトの通り実行していると、アクセスの仕方がわからないという沼にはまりました。他のターミナルで実行すればできましたが、PuTTYでアクセスする方法を書きます。
**1.秘密鍵の形式を変える**
PuTTYでは専用の鍵を使用するそうなので、ダウンロードした鍵を変換する必要があるようです。

1.1 "PuTTYgen"を開く(Windowsキー+rやProgram FilesのPuTTY内から探す)

1.2 下部の"Type of key to generate"で"RSA"を選ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/06a09b95-ccf3-c291-7ca9-f789551af3e4.png)
1.3 "Load"を押し、先にダウンロードした****.pemファイルを開く(デフォルトでは.ppkファイルのみになっており、All filesに変更しないと表示されないので注意)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/2e7f153d-f709-5fea-2a3a-966fdf01a75d.png)
1.4 "Save private key"を押し、"はい(Yes)"を押す。ファイル名は拡張子以外元のカギと同じ名前にして、任意の場所に保存する。

**2.鍵を選択して接続**
変換して作った鍵を使用し、SSHでアクセスします。

2.1 "PuTTY"を開く

2.2 左側で"Connection"の下の"SSH"の下にある"Auth"を選択し、右に出てくる"Browse"を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/927081a0-abc0-f4b3-106c-9d092858970e.png)
2.3 作成した鍵のファイル(.ppk)を開く

2.4 左側、一番上の"Session"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/03ab01aa-a111-0951-1065-38fab5d7431f.png)
2.5 右側の"Host Name"のところに、AWSのページに載っているアドレスをコピペします(画像の青選択の部分を参照 ※@の後には数字とドットが続きます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/d870ad0e-a87c-3432-902b-2204b499389a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/7e12c4bc-24cd-c5bd-3b97-be4422f27c36.png)


(2.5.5) この設定を毎回やりたくない(これ以降もアクセスする)方は、"Saved Sessions"に任意で名前を入力し、"Save"を押して設定を登録する

2.6 "Open"を押して開く


うまくアクセスできましたか？成功したら、上記3サイトと同じ画面が表示されるはずです。PuTTYはコマンドではなく最初から接続するので、少し方法が違うようです。
【VirtualBox, Ubuntu18.04】仮想マシンにコピペできない

#問題
VirtualBoxで作成したUbuntuの仮想マシンにコピペできない。
設定でクリップボードを共有できるようにしているのに・・・(/ω\)。

#環境
・ホスト側（仮想マシンを動かしているPC）のOS：Windows10
・ゲスト側（仮想マシン自体）のOS：Ubuntu18.04
・VirtualBoxのバージョン：5.2.18

#解決する前に
まず以下の設定が済んでいることを確認する。

1.VirtualBoxマネージャーで対象の仮想マシンを選択し、「設定」を押す。
2.設定画面が開いたら左の項目から「一般」を選択する。
3.「高度」タブを開き、「クリップボードの共有」の項目を「双方向」に設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/1c8766e9-6f25-50e6-8216-d6ce76457e21.png)

#解決
###解決方法の概略
解決策の概略を先に述べると、VirtualBox用の拡張ツールのイメージファイルをダウンロードし、それを仮想マシンのディスクドライブに入れて仮想マシンを起動し、仮想マシンでイメージファイルを実行する、という手立てです。

###手順
1.VBoxGuestAdditionsのイメージファイルを[このサイト](https://w0.dk/~chlor/vboxguestadditions/)からダウンロードする。
サイトは以下のようになっていて赤枠の部分をクリックするとダウンロードが開始される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/8201f284-b562-3b0e-b9fb-9e552c83a76f.png)



2.VirtualBoxマネージャーで対象の仮想マシンを選択し、ウィンドウ右上の「マシンツール」の▼を押下して「詳細」を開く。

3.詳細が開いたら「ストレージ」の項目の「IDEセカンダリマスター: [光学ドライブ]空」を右クリックし、「ディスクイメージを選択」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/b0058eed-dc40-6dd0-60f1-e5c74d7f27aa.png)

4.ファイル選択ダイアログで手順1でダウンロードしてきたイメージファイル(.isoのやつ）を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/fa8582ea-d491-f2ec-45fe-c16ffd589dc7.png)

光学ドライブにイメージファイルがセットされた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/ecebe819-15cc-c08c-b96f-bc88514bfeb1.png)

5.仮想マシンを起動し、普通にログインする。

6.デスクトップかどこかに前の手順で入れたイメージファイルが存在しているはずなので、それを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/26b7b698-453d-247e-5384-49a358fa16fe.png)
右クリックで「Open」押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/50a99c34-8b20-f995-b8cd-2389d3227bd1.png)

7.開いたら右上の「Run Software」を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/7c4c468a-10f5-d935-b8fc-33b72a7f21f3.png)

8.警告が開くが、「Run」を押して実行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/7193abde-cc63-63ec-4c19-75b51fab3335.png)

9.認証画面が開いたら、Ubuntuにログインするときのパスワードを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/1f23d452-8314-f44b-4062-4248d85130d3.png)

9.インストールが始まる。
たぶん青線を引いた当たりでいったん動きが止まるが、しばらく待てば大丈夫。
「Press Return to close this window...」が表示されたらEnterキーを押して仮想マシンを再起動する。
するとホスト側のPCと仮想マシンとの間でコピペ等ができるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/1e90bda9-b9e5-c4d6-b349-32c6d6d5a761.png)

#後片付け
今回使ったイメージファイルはドライブから除去しておく。
（普通のPCでもディスクを入れっぱなしにしてしまう自分に対する注意喚起）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424306/15827ae0-7cb7-775a-ce8e-7418aeb3ca55.png)