OmniAICreator/Qiita-1.07M huggingface dataset:
[BluePrism]Webページのドロップダウンリストを選択するときの書き方 #blueprism

#追記
この記事は勤務先のブラウザがIE11のときに書いたものです。
Edgeでやるときは、記事中のCollectionの列名「Item Text」を「Text」に読み替えてください。あとは一緒で大丈夫です。

#これを書いた理由
よくこれを質問されるのです。
なので、たぶんここで詰まる人が多いのだろうなあというのと
自分が説明するときに「ここ見て！」って言って楽をしたいからです。

#使うWebページ
[UiPathCommunityEditionのダウンロードページ](https://www.uipath.com/ja/developers/enterprise-edition-download)
これの入力フォームの一番上の「国」ってところを使います。

#動き方
「選択したい国」のところに、選択肢の選びたい国名を入れて（一部でいいです。トリニタードトバゴだったら「Tobago」とか）
実行すると、リストが選択されます。
選択肢にない国名を選択したらビジネス例外がスローされます。
複数あてはまるような指定をしたら（「North」とか）最初に見つけたやつを持ってきます。VLOOKUPみたいな感じです。

#作り方

##用意する変数
- 選択したい国（テキスト型：これは実行前に入力しておいてください、部分一致でオッケー。ワイルドカード不要）
- 国（Collection型）
- 選択する国（テキスト型）

##アプリケーションモデラー
![apm01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/dfc05998-3c52-0cf6-6075-949ddb9f138c.png)

キモは、ドロップダウンリストのところを「HTML Combo Box」で取得することです。
これで取得すると、選択肢をまるっとCollectionに取得できるからです。
![apm02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/85a716e7-2918-167c-f97c-b26361040991.png)

##オブジェクト
ドロップダウンリストの選択肢をCollectionに入れて
そのCollectionをループでまわして
欲しい選択肢が見つかったらリストにセットして終了
という流れです。

※これはループでまわしていますが、選択肢はCollectionに取得しているので、Collection Manipulationの中に入っているFilter Collectionを使ってもいいと思います 

![flow00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/40a08abc-4168-f6ee-4c12-6ae19b1596bf.png)

###各ステージの中身

![flow01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/a3e5fa09-00f9-7b7c-89a0-668377cb10cf.png)

![flow02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/8b4072f5-c8c4-2b65-d235-6eb387ae6df6.png)

![flow03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/bb4239b2-09f8-7c06-738f-bbb1bf134a92.png)

「Item Text」にセットします。
セットする値はワイルドカードは使えないっぽいです。
![flow04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/a255238a-9c83-0f0b-07da-1ced9dfea407.png)

#実行結果

変数のところに、取得した選択肢の一覧と、選択する国名（選択肢のとおり）が入っています。
![OK01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/4da7ab43-ed68-c8aa-8291-01882a058b85.png)

選択されます。
![OK02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/3f2e96a5-1282-7ce9-dc97-3478c6dff63f.png)

#終わりです
ひとへの説明用と、自分用の備忘録です。
こっちのツールやってからしばらく別のツールやってってしてると
こういうのから忘れちゃうので……。

#追記
別にBlue Prismに限った話ではないのですが、ドロップダウンを選ぶと何か表示されるとか、チェックボックスにチェックを入れると表示が変わるとかいったonclickのイベントがある場合、select itemではイベントが発火しないことがあります。
VBAなどでも同じような「イベントが発火しない」というところで詰まることがあるのですが、これって物理的に「クリック」をしないとダメっぽいのです。
なので、そういうときは、select itemじゃなくてclick centreを使ったほうがいいみたいです。（「Webテキスト」に選択肢項目が入るようなので、その属性をDynamicにして、選択肢を入れてclick centre）
(作業中)rhel on virtual box 環境構築メモ


* subscription-managerを使ってサブスクライブするのではなく，epel等のリポジトリを使いたいというケースです．
※ *作業中でまだ詰まってます．* help
※ まとめ体部分からまとめていきます．
※ rhelのisoの準備とosインストールは省きます． 
※ Host only adapterと，ssh用のipアドレスの設定くらいは書くかも


# VirtualBox Guest Additionsをインストール

VirtualBox Guest Additionsをインストールする

- hostとのshareフォルダ等使えるようになる
- ...

## virtualbox に redhatのisoを装入

<img width="1392" alt="Screen Shot 2019-09-05 at 21.16.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481609/679ced77-ea7d-afb0-1ae5-b3b48b487106.png">


## mountする

```
mkdir /media/cdrom
mount /dev/cdrom /media/cdrom
```

## isoから必要なものをインストール

```
/etc/yum.repos.d/
vim /etc/yum.repos.d/iso-rlel.repo
yum repolist

rm -rf /var/cache/yum/*
yum clean all
yum install bzip2 gcc kernel-devel
```

# VirtualBox Guest Additionsのインストール 

```
mount /dev/cdrom /media/vb/
cd /media/vb/
sh VBoxLinuxAdditions.run
```

解像度の変更(必要なら)
```
vim /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg
```

```
umount /mnt/vb/
shutdown -r now
```

## sshの設定

host側で, share folder に public keyをおいて,

```
cd
mkdir .ssh
cd /media/sf_share_rhel/
cp id_rsa.pub ~/.ssh/
cd
chmod 700 .ssh
chmod 600 .ssh/id_rsa.pub
```

host コピペやいつも使っているショートカットが捗るので，ここからはrhelにsshで接続します．

```
ssh root@192.168.56.2 -i ~/.ssh/id_rsa
```

```
yum install wget
wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
rpm -ivh epel-release-7-11.noarch.rpm

rm -fr /var/cache/yum/*
yum clean all
yum repolist all
```

ここで

`yum install python` をすると以下のようなメッセージが

```
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
Nothing to do
```

で，とりあえず以下を実行

[5.2. Subscription Manager リポジトリーの無効化 Red Hat サブスクリプション管理 1](https://access.redhat.com/documentation/ja-jp/red_hat_subscription_management/1/html/rhsm/repos-disable)


```
subscription-manager config --rhsm.manage_repos=0
```

また，サブスクリプションマネージャーに登録できますというメッセージがも毎度毎度出てきて辛いので消す．
手順は２つのファイルを編集してenable=0にするだけである。

```
vim /etc/yum/pluginconf.d/subscription-manager.conf
```
```
[main]
enabled=0
```

で，再び`yum install python`を実行してみると

```
Loaded plugins: langpacks, product-id, search-disabled-repos
Nothing to do
```

つかれたので今日は終わり，
エンジニアのためのコミュニケーション①

#1.はじめに
ITエンジニアには、技術力とコミュニケーション力が求められます。特に、PM（プロジェクトマネージャ）の仕事の90%はコミュニケーションです。

・**コミュニケーション力 × 技術力 = 仕事のパフォーマンス**
PMだけコミュニケーション力が必要なのかと言われると、**むしろプログラマ等のエンジニアにこそ必要**です。どんなに技術力が高くても、コミュニケーション力が低いと仕事のパフォーマンスが低下します。


#2.どうすればいいの？
・**会話では解決を優先する**
エンジニアの会話は基本的に「正しいものを認めさせる会話」をしてしまいがちです。会話の目的は「何かを達成したり解決すること」です。これを間違えてしまうと、不毛な論争に突入します。

・**会話の前提として協力的な関係を構築する**
相談する相手と仲が良ければ、相談しやすいですよね。

#3.仲良くなるには？
・**最初に意見が対立しない話題を出す**
プロジェクトに新しくジョインした人に「出身はどちらですか？」とか聞きますよね。そんな感じの話題でOKです。

・**共通点を口に出す**
「出身はどちらですか？ → 埼玉です → 私も埼玉なんですよ！ → 同じですね！」という会話をすることで「この人は仲間だから、心を許して安心して話せる」というラポール（心の架け橋）が作られます。

#4.仲良くなったら？
・**会話の前にラポールを作る**
仲良くなった相手に説明や相談をする前に必ずラポールを作り、その後も会話が終わるまでラポールを維持しましょう。ラポールは「承認」や「共感」でも作ることができます。

#5.ラポールが壊れる原因
・**口に出したことを本心からそう考えていない**
口先で言っているのか、本心で言っているのか、相手にわかります。

・**自分を守るような態度をとってしまう**
「お仕事大変ですね → いや、そんなことないですよ」と否定されたくないから「こんな遅くまで働くなんて嫌ですよね、お仕事大変ですね」と言ってしまうパターン。その会話は誰のためなのか、考えてみましょう。

#6.見た目も大事
・**笑顔**
基本です。鏡を見て練習しましょう。

・**姿勢**
全身が移る鏡を見て練習しましょう。

・**頷き**
会話を頷きながら聞きましょう。最初は大げさに頷くのがポイントです。

・**視線**
基本です。しっかり相手の目を見て話しましょう。

#7.おわりに
次回は「聞く」ことについて書いていきます。
改行コードに関するTipsメモ

## はじめに
* 修正したメッセージ文言内容がテストコード上で担保したいため、UTを作成しました
* 結果、UT失敗して少々つまずいたのでTips的な備忘録として残します
* IDEは、PhpStormを使用しています

## メッセージ本文1行の場合
### Productionコード
* email.php

~~~php
/**
 * メッセージ本文
 */
$lang['message_body'] = "これはメッセージです！";
~~~


## テストコード
* MessageTest.php（dataProviderは省略）

~~~php
    /**
     * @test
     *
     * @dataProvider createDataProvider
     *
     * @param $param1
     * @param $param2
     * @param $param3
     * @param $expectedResult
     */
    public function testMessage($param1, $param2, $param3, $expectedResult)
    {
        $result = $this->model->createMessage($param2, $param1, $param3);

        foreach ($expectedResult as $key => $expectedValue) {
            $this->assertEquals($expectedValue, $result[$key]);
        }
    }

    /**
     * @param string $param1
     * @param int $param2
     * @param string $param3
     * @param int $id
     *
     * @return string
     */
    private function messageContent($param1, $param2, $param3, $id)
    {
        return "これはメッセージです！";
    }
~~~

### 結果
* 成功

![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/9a736e87-5533-3672-f36d-46fed36d4ecd.png)


## メッセージ本文複数行の場合
### Productionコード
* email.php

~~~php
/**
 * メッセージ本文
 */
$lang['message_body'] = "これはメッセージです！
以上、宜しくお願いいたします。";
~~~


## テストコード
* MessageTest.php（dataProviderは省略）

~~~php
    /**
     * @test
     *
     * @dataProvider createDataProvider
     *
     * @param $bankbook
     * @param $member
     * @param $emoney
     * @param $expectedResult
     */
    public function testMessage($param1, $param2, $param3, $expectedResult)
    {
        $result = $this->model->createMessage($param2, $param1, $param3);

        foreach ($expectedResult as $key => $expectedValue) {
            $this->assertEquals($expectedValue, $result[$key]);
        }
    }

    /**
     * @param string $param1
     * @param int $param2
     * @param string $param3
     * @param int $id
     *
     * @return string
     */
    private function messageContent($param1, $param2, $param3, $id)
    {
        return "これはメッセージです！
以上、宜しくお願いいたします。";
    }
~~~

## 結果
* 失敗

![failer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/787dc356-40e2-d05a-e499-e69d46f30cda.png)

## 対応策
* PhpStormの右下の設定で改行コードの設定箇所を変更する
    * デフォルト（CRLF）→ LFに！

![change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/5e38fbb2-7102-8198-6365-96bf5048b759.png)

## 再度実行
* 成功

![succ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87218/f06aac58-fb1b-8740-8653-9e260838286a.png)

## メモ
* https://marusunrise2.blogspot.com/2014/06/lfcrcrlf.html
PowerShellでFunctionにパラメータを渡してるんだけど、第2パラメータが$nullになってしまう件

# 事の顛末
普通に関数かいて、普通に呼び出しているつもりだったのだけど、実行結果が期待通りにならなくて。。

``` worng-sample.ps1
function SomethingToDo($param1, $param2) {
    Write-Host $param1
    Write-Host $param2
}
SomethingToDo("Hoge", "Gero")
```
```
# 出力結果 
Hoge Gero
```
Write-Hostを2回呼び出しているので、期待していた結果は、"Hoge"と"Gero"が2行に出力されることなんだけど、横に出力されている。。。
しまった、しまった。SomethingToDoの呼び出しで、( )をつけてしまっていた。。。またやってしまった。関数呼び出しは( )つけちゃダメだったですね。

``` fixed-Sample.ps1
SomethingToDo "Hoge" "Gero"
```
```
# 出力結果 
Hoge
Gero
```
これでよし。
# でも、なんでだろう?

SomethingToDoを( )付きで呼び出した時に渡されるパラメータの型を確認してみると。。

``` debug-sample.ps1
function SomethingToDo($param1, $param2) {
    Write-Host $param1.GetType().FullName # => こちらは System.Object[]
    Write-Host $param2                    # => こちらは $null
}
SomethingToDo("Hoge", "Gero")

```
\$param1の型は、Object[ ] になっているみたい。
さらに、中の値を確認してみると

``` debug-sample.ps1
function SomethingToDo($param1, $param2) {
    Write-Host $param1[0] # => "Hoge"
    Write-Host $param1[1] # => "Gero"
}
SomethingToDo("Hoge", "Gero")
```
配列になってしまっとる??? うーん。目を凝らして SomethingToDo("Hoge", "Gero")をしばらく眺めていると。。。
("Hoge", "Gero") って、配列の記法になってるね、ということに気づきました。実態としては、こんな感じで動作していたのと同じですかね。

```
$temp = ("Hoge", "Gero")
SomethingToDo $temp
```
言語仕様どおりに動いているんでしょうけど。。恐るべしPowerShell。やはり奥が深い。
# 参考文献
今回は自力解決(解釈)? してしまったので参考文献はございません。
[備忘録]chromeで画像のサイズを取得する

画像のロードが終わらないとサイズを取得できないそうなので、onloadを使う。



```javascript
var element = new Image();

// 画像のサイズが取得できたら処理続行
element.onload = function(){

	var width = element.naturalWidth;
	var height = element.naturalHeight;

	// 次の処理
}

element.src = (画像ファイルパス);

```
分割算法

               
调用例子：

~~~
  String[] groups = XXX.multisplit(
                  link,
                  new List<integer>{255, 255, 255, 255}
                );
~~~
可实现的操作是，分割成list里面规定的长度的字符串。
如果你给的String的长度不够，那么后面返回的都将是null。


算法例子：

~~~
public static string[] multisplit(string value, integer[] groupSizes) {
    integer groupi = 0;
    integer groupSizeAccumulatorPrev = 0;
    integer groupSizeAccumulator = groupSizes[groupi];
    list<string> groupValues = new List<string>();
    if (value == null) {
      return groupValues;
    }
    while (groupSizeAccumulatorPrev <= value.length()) {
      groupValues.add(
        value.substring(
          groupSizeAccumulatorPrev,
          Math.min(groupSizeAccumulator, value.length())
        )
      );

      groupSizeAccumulatorPrev = groupSizeAccumulator;
      if (groupi < groupSizes.size() - 1) {
        groupSizeAccumulator += groupSizes[++groupi];
      } else {
        break;
      }
    }
    return groupValues;
  }
~~~
Google Analytics で外部サイトへのリンク数を計測する（タグマネージャ不使用）

####更新(2019/9/17)
コメント欄に助言をいただいたので、タグをもう少し高度に＆記述も追加してみた。（@hareno 様ありがとうございました。）

#はじめに
Google Analytics （以下GA）を設置しているサイトで外部サイトリンクのクリック数（外部リンククリックイベント）を計測するニーズがあり、できるだけ手っ取り早く導入できる方法を検討した。
###目的
運営しているサイトに新しく追加する外部サイトへのリンクのクリック数を計測したい
###前提条件・制約

- GAoogle Analyticsのタグは設置済み
- 自分で管理している以外のGAタグも設置されている
- とりあえずお試しでリンクの効果測定
- 今後大量のリンクを置いたりそれを効果測定したりする見込みはない
- 運営者がコロコロ変わるのであまり難しいことはできない（特にGAは操作方法が分かっていないメンバーが多いため、できるだけjavascriptだけで設定したい）

これらの条件から、タグマネージャを導入するのではなく単発のイベント発火を仕込むことにした。 

#グローバルタグについて
入っている前提なので設置方法は省略。
###GAタグの種類
Google Analytics のタグは複数の種類がある。

- グローバル サイトタグ（gtag.js） ←最新機能が入っているタグ。ウチはこれ。
- analytics.js　←以前使われていたタグ。継続使用もできるが最新機能は使えない？
- その他　←タグマネージャのタグを入れるとかいろいろあるらしい。よく知らない。

###複数タグを埋め込む場合
お上から押し付けられたタグと自分で管理しているGAのタグが共存してるけど、今のところ目立った問題はない。
少なくとも自分で管理しているタグはログが取れている。

#リンクにタグを埋め込む
以下は[Google公式ドキュメント](https://developers.google.com/analytics/devguides/collection/gtagjs/events?hl=ja)を元に、自分なりにまとめなおしたもの。
###イベント送信の構文

```js:example.html
gtag('event', <action>, {
  'event_category': <category>,
  'event_label': <label>,
  'value': <value>,
  'send_to': <trackingID>
});
```
###引数
`<xxx>`は引数。`action`は必須、その他は任意だそうな。
また、`action`, `category`, `label`にはデフォルトで仕様を推奨された文字列がある。
イベント間の命名の一貫性を確保できる他、将来的な機能追加の際に便利になるんだとか（何が来るか楽しみ）。
デフォルトのイベントの一覧もあるのだが、 [このページ](https://developers.google.com/analytics/devguides/collection/gtagjs/events?hl=ja#default_google_analytics_events) と [このページ](https://developers.google.com/gtagjs/reference/event?hl=ja) でリストの中身が若干違う（執筆時）。eコマースに寄った項目が多く、外部サイトリンククリックは当てはまるものがない？
さらにリンクを辿ると [イベントの要素の詳細](https://support.google.com/analytics/answer/1033068?hl=ja#Anatomy) が書かれているページがあった。
（余談だが、構文上はアクション→カテゴリ→ラベルの順で登場するのにドキュメントではカテゴリ→アクション→ラベルの順になってるのでやや混乱した）
####(2019/9/17追記)
さらに、[gtag.js パラメータ リファレンス](https://developers.google.com/gtagjs/reference/parameter?hl=ja)によると、`gtag()` `event`に渡すことができるパラメータに`send_to`というのがあり、これを指定することで自分の管理しているGAにのみイベントを送信できるとのこと。お上のGAに自分のGAのイベントが紛れ込んだら何を言われるか分からないのでありがたく設定しておく。
なおここで渡すのは「トラッキングID」（管理>プロパティ>トラッキング情報>トラッキングコード　にある）というやつ。


ということで、最終的に下記の値を渡すことにした。

- カテゴリ : link
- アクション : click
- ラベル : リンクURL
- トラッキングID：自分のGAのトラッキングID



###完成形
ここまでで組み立てたイベント送信コマンドをリンクの`OnClick`に仕込む。改行は邪魔なので削除しておく。

```js:example_inline.html
<a href="https://xxx", OnClick="gtag('event', 'click', {'event_category':'link','event_label':'https://xxx', 'send_to':'xx-xxxxxxxxx-x'});" target="_blank">リンク文字列</a>
```

（外部リンクなので新タブで開くおせっかいを追加）


#結果確認
Analyticsのリアルタイム→イベントを開くとイベントが取れているか確認できる。
レポート画面は省略するが無事取得できていた。
####(2019/9/17追記)
`send_to`追加後もイベントはきちんととれている。一度間違えてアナリティクスアカウントの名前の方を入れてしまい取得できなかったので、むしろきちんと送り分けられていることが判明した。

###スクリプトの前後関係
ちなみに、[このページ](https://developers.google.com/gtagjs/devguide/snippet?hl=ja) に
> `gtag()` コマンドは、グローバル スニペットがページの `gtag()` コマンドが呼び出されるより前にない限り、データを送信できません。


とあり、グローバルスニペット＝グローバルサイトタグだと思うが、~~ウチではイベント送信が先でもログ取得できていた。~~ソース上の前後ではなく呼び出しの前後ということのようで、**ページ読み込み時にソース下部のスクリプトでグローバルスニペットが設定される → ボタン押下時にイベントが発火してデータ送信される** の順で動いているので問題ない模様。
（同じ結果でも理由が分かっていないのと分かっているのとでは安心感が違いますね……@hareno様ありがとうございます）
【GAS】Gmailの自動アーカイブ2

#概要
Gmailで特定のメールを寝ている間に自動でアーカイブしてくれるプログラムです。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242971/1f43be98-87ee-63a7-03af-320750949476.png)
autoArchiveとラベリングされたメールは実行時にすべてアーカイブされます。
#ソース

```javascript
function cleanGmail() {
  const myThreads = GmailApp.search('label:autoarchive in:inbox -is:starred -has:attachment ');
  myThreads.map(function(thread) {
    thread.moveToArchive();
  }); 
}
```
プログラムは受信トレイのアーカイブラベルを検索してアーカイブしてるだけです。
肝心のラベルはGmail側からフィルタで貼られる様に設定してください。
自動アーカイブしたいメールを開く→返信ボタンの横のその他ボタン→メールの自動振り分け設定→ラベル処理
Gmailの検索がそのまま使えるのでnoreply@, infomation@ など登録すると包括的に指定可。
この関数を日付タイマーで夜中に実行すればラベルが付いた受信トレイにあるメールはすべてアーカイブされます。
救済措置として添付ファイルがある場合とスターをつけたメールはアーカイブしません。
#終わりに
GASと連携しやすくスマホで通知が受け取れるGmailをもっと便利にしたい。
第3世代RyzenシリーズとRTX20系でWindows7を使う方法

Sandyおじさんがいきなり第3世代Ryzenお兄さんに圧倒的成長する物語｡

SandyBridge(Core i5-2400)を使い続けていたのですが､グラフィックボード更新を機に一気にアップグレードしました｡
備忘録というかやり方を書いておきます｡

# 0. 環境紹介
## 元環境
* ベースマシン: Dell Optiplex 990DT
* CPU: Core i5-2400
* GPU: GeForce GTX750Ti
* OS: Windows7 Professional 64bit

## 新環境
* CPU: Ryzen 5 3600
* GPU: GPU: GeForce RTX2060
* OS: Windows7 Professional 64bit

注: OSは再インストールせず､ストレージ差し替えだけで環境移行する

# 1. Windows7でWindowsUpdateをとりあえず全部当てる
一応抜け道はあるのですが､RyzenはWindows7がサポート対象外ということもあり､普通にしてるとWindowsUpdateが拒否られます｡念の為に最新にしておきましょう｡

# 2. チップセットドライバを準備

amd_chipset_drivers_v1.8.19.0915.zipという名前のものが､2019/9/3の段階では公式にあったのですが､9/5に見たところ消えていました｡
https://jp.msi.com/Motherboard/support/B450-GAMING-PLUS#down-driver&Win7%2064
まだMSIのサイトにあるので欲しい人は今のうちに｡

これを展開し､実行ファイルをCドライブ直下かなんかに入れておきましょう｡

# 3. レジストリエディタで普段読み込んでないドライバも読ませるようにする
これはRyzenに限らず､Windows7でマザーボードを変更するときに行う作業です｡
Windows8以上は確か自動で環境変更認識しますが､Win7はしないので普通にBSoD吐く気がします｡


レジストリエディタ(regedit)で､
```HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\
HKEY_LOCAL_MACHINE\System\ControlSet001\Services\
HKEY_LOCAL_MACHINE\System\ControlSet001\Services\```
の､以下の項目で**start**の値を**3**から**0**に変更します｡

* Aliide.sys
* Amdide.sys
* Atapi.sys
* Ataport.sys
* Cmdide.sys
* Intelide.sys
* Msahci.sys
* Pciide.sys
* Pciidex.sys
* Viaide.sys

存在しない項目があった場合は無視して下さい｡
一応書き換えたあと再起動し､ちゃんと起動することを確認してください｡

# 4. 環境を移行する
ここは割愛します｡普通に新マシンを組み上げ､今まで使ってたストレージをつなぎます｡

# 5. 起動とチップセットドライバのインストール
注意点として､初回起動の現段階では**PS/2キーボード･マウスしか認識しません｡**
USBしかもってない人は詰みます｡マウスはいらないかもしれませんが､キーボードは必須です｡
おそらく普通に起動します｡ グラフィックドライバが当たってなかったりしますが､とりあえずログオンしてデスクトップは出るはずです｡
そうしましたら､Winキー+Rから"ファイル名を指定して実行"を開いてコマンドプロンプトを起動(cmdでEnter)し､先程展開したチップセットドライバのインストーラを起動しましょう｡(エクスプローラー開いてTabキーを使って格闘してもいいですけど)

指示通り再起動したら､チップセット由来のUSBポートが使えるようになっているはずです｡(CPU直結の端子は使えませんが､それでも何個か使えるのでセーフ｡)

ちなみにNICが認識されていないなどの問題は､各自クリアしてください｡特に工夫するところはないです｡

# 6. グラフィックボードドライバのインストール
最近のドライバを入れている人は大丈夫という話もありますが､当環境ではグラフィックボードが認識されなかったので､ドライバのインストールをします｡
https://www.nvidia.co.jp/Download/driverResults.aspx/150587/jp
ここで落とせる```436.15-desktop-win8-win7-64bit-international-whql.exe```を利用しました｡
Windows7/8用のドライバなのに､中のファイル見てみるとRTX系の記載がちゃんとあり､インストーラにも認識されました｡
特段工夫するところもなく､普通にウィザードに従ってインストールを進めていけば､再起動後にちゃんと認識されているはずです｡
注意点として､DX12は使えません｡DX11までです｡レイトレはもちろん無理です｡ ですが､普通にゲームする分には問題ないです｡

作業は以上です｡お疲れさまでした!

# 7. 残りの5ヶ月をエンジョイする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300863/1ca5d680-42e6-1458-9e65-cd137eaa20e8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300863/69505bdf-4baf-275d-e31e-909fe98d0947.png)

Win7は御存知の通り2020年の1月にサポートが切れます｡
それまでの期間､めいいっぱい第3世代RyzenとRTX20系のグラボで楽しみましょう!

※ちなみに環境変更されたこともあり､ライセンス認証しろと言われますが､当環境ではオンライン認証で普通に通りました｡

# あとがき
SandyBridgeからマザボ変更の手順だけで普通に動くとは思いませんでした｡
Win7を使いたいけどRyzen使いたい･･･そんな人(いるかな)に役立てば幸いです｡

# 参考サイト
https://pcrepair.w-pickup.com/post-3295/
https://17inch.blog.so-net.ne.jp/2019-07-23
9/5 Tech Expert (事前学習) day 6　/　条件分岐

【学習アウトプット】

#今日の目標(やること)
rubyをすすめる。

##今日のまとめ
###STEP4 : メニュー画面をつくろう
####条件分岐
####if文
if文は条件式(基本文法で出てきた返り値がtrueかfalseの式のこと)で処理を分岐させることができます。
最も基本的なif文の書き方は以下です。


value = 3
  if value > 0 then
    puts "値は正です"
  end

条件式は真(true)となります。

値が正でないとき(false)ーelse使用

if 条件式 then
    # 条件式が真(true)のときに実行する処理
  else
    # 条件式が偽(false)のときに実行する処理
  end

'0'は正でも負でもない。しかし今のプログラムで値を0にすると"値は負です"と表示されてしまう。
よって条件分岐を以下のように3パターン考えます。


value > 0	値は正です
value < 0	値は負です
それ以外	値は0です


このような複数の条件分岐を書くときはelsifという文法を使います。

ユーザーから入力された値が'正'、'負'、'0'のどれかを判断する。
getsメソッドで得られるユーザーからの入力は文字列であるため、数値オブジェクトに変換しなければならない。

####to_iメソッド
文字列オブジェクトである返り値を数値オブジェクトに変換するメソッド
数字以外の文字列オブジェクトは全て0に変換される
 
string = "30"           # 文字列の30
number = string.to_i    # 数値の30に変換
puts number + 20        # => 50が出力


##〜独り言(まとめやら感想やら)〜
明日でようやく「Rubyでアプリケーションをつくる１」を終了させられそう。（メニュー画面の条件分岐~）
２に進む前に復習を詰めよう。
Treasure DataのPRESTO(SQL)でCREATE TABLEする時のタイムスタンプ項目について

PRESTOで、 **CREATE TABLE実行時に、タイムスタンプ項目があると、エラー** になリます。
クエリを書いていて、何度か同じ現象に悩まされることがあったので、対処方法をメモしておきます。

**※2019/10/1追記 PRESTO/hiveを利用した場合は上記問題は起こりません。**

## やりたい事
CREATE TABLE実行時にタイムスタンプ項目のフォーマットを変更してエラー回避する

## サンプルコード
```SQL
DROP TABLE IF EXISTS temp_tbl1;
CREATE TABLE temp_tbl1
AS 

SELECT
  id
  , target_date
  -- DATE_FORMAT関数でレイアウトをVARCHARに変換する→これでCREATE TABLEのエラーを回避可能
  , DATE_FORMAT(target_date_to_1week, '%Y-%m-%d %H:%i:%s') AS target_date_to_1week
FROM
  (
  SELECT 
    id
    , target_date
    -- DATE_ADDで1週間後の日時を取得する場合、このアウトプットはタイムスタンプ項目になる
    , DATE_ADD('week', 1, CAST(target_date AS TIMESTAMP)) AS target_date_to_1week 
  FROM
   table
  )
```
プログラミングを始めた頃の自分を振り返る

## 〜宣伝〜

:::note info
個人開発でエンジニア専門マッチングサービスを開発しましたので、是非未経験からエンジニア目指している人！現役エンジニアで教えたい人！使ってみてください！

:::
https://dokupro.dev/

## 目的

- プログラミングを始めた頃の自分に対して今思うことをまとめる。
- あの頃を見つめ直しどんなことに苦労を感じたかをまとめる。

## 苦労したこと

- 全くの初心者だったため、Hello Worldを出力したくてもどこにコードを書いていいかわからない。  
ほんとの初心者だとこれすらも分からない、、、聞くことにも抵抗がある
- 独特の言い回しが多い  
「インスタンス」とか「変数」とか「引数」とか、教えてもらっている先輩エンジニアのアドバイスが分からなくて申し訳ない気持ちになった
- 知識がないから自分に合った書籍の出会い方も知らない  
意外と自分が買った入門書は合わないことがあった
- プログラミングができる人たちのレベルが高すぎで、こんなこともわからない自分は向いていないんじゃないかと不安になる  
三歩進んで二歩下がる状態で勉強しているとプロのエンジニアとどうしても比較してしまい悲観的になったことが多かった
- 実務で使えるプログラミング知識は世間一般では枯れている技術であり、モダンな言語を学ぼうとすると「実務で使えないじゃん」と言われる  
社会人１年目の時は会社に貢献しようという考えがあったので結構これはメンタル的に来た

## 楽しかったこと

- パソコンさえあれば何もない状態から無料で作ることができた
- やったことをoutputすると同じ境遇の人から反応があった
- ShellScriptを最初に触れたが単純だった
- 積み重ねが好きな人が界隈に多くいることを知った
- 自分のやる作業を自動化できた

## あの頃の自分にアドバイス

- エディタはVisual Studio Codeを使おう
- やったことをTwitterでハッシュタグをつけてつぶやこう
- Progateを使って勉強しよう
- Twitterの情報は信用できる情報だけinputしよう
- 毎日ちょっとでもいいから技術に触れよう
- たくさんの言語をいっぺんに勉強しないようにしよう
- Githubを使ってバージョン管理をしよう

## これから

- 自分は物分かりが人より遅いので実際は三歩進んで四歩下がる状態、それでも続けることが大切
- できたこと、やったこと、できなかったこと、その日のモチベーションをTwitterに投稿する
- 自分の周りにはいなくても、今まさにこの瞬間に同じ境遇で頑張っている人が世界にはきっといることを想像する
- おなじ境遇、同じつまずきをする人が少しでも減るように自分がつまずいた内容についてまとめてQiitaに投稿する
vue-eslint-parserには@typescript-eslint v2との互換性がない

[`@typescript-eslint`]()は先日v2にメジャーアップデートしました。

それに伴って（？）、VueファイルをLintしようとすると以下のようにエラーが表示されるようになりました。

```sh
/myproject/src/components/partials/Base/BaseRadio.vue
  23:9  error  Parsing error: '>' expected
```

どうもこれ、`@typescript-eslint`のv2と`vue-eslint-parser`に互換性がないことが原因のようです。

> Incompatibility with typescript-eslint@2
> https://github.com/vuejs/eslint-plugin-vue/issues/944

ということで、`eslint-plugin-vue`側がv2に対応するまではバージョンをあげないほうが無難かもしれません。

対応したらそのときは、この記事を更新します。
人に見やすい表をPowerBIが読みやすい形に変える

# 背景・経緯

私の会社では[オービック社](http://www.obic.co.jp/)の[OBIC7](http://www.obic.co.jp/erp_solution/)が導入されていてプロジェクトの収支管理もコレで行われています。
労務費や外注費などが確認でき便利なんですが文字と数字が羅列された表でしか閲覧できず
割合や傾向を確認するのに難儀していました。  

そこで収支情報をPowerBIに突っ込んで視覚化を試みたのですが、早速壁にぶつかりました。

# 課題
OBIC7が出力する「プロジェクト収支表」は、ざっくり言うと以下のような形式の表になっています。

<center>表1:人が見やすい？表</center>

|お客さま|案件|要素|予実区分|1月|2月|3月|4月|
|:--|:--|:--|:--|:--|:--|:--|:--|
|A社|ポータル刷新|労務費|予定|300|200|300|400|
|A社|ポータル刷新|外注費|予定|0	|0	|100|100|
|A社|ポータル刷新|労務費|実績|300	|300|400|500|
|A社|ポータル刷新|外注費|実績|0	|0	|130|150|　　


これをそのままPowerBI突っ込むと、こんな形で「月」が別々の要素になってしまい、
月ごとの推移などが確認できません。

<img width="526" alt="月ごとの推移が表現されない.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159218/d638bf15-c60d-93a3-93e9-34a3a932c2ae.png">


# 解決にむけて

表を以下のように表せられれば良いんです。  
  
<center>表2:PowerBIが扱いやすい表</center>

|お客様|案件|要素|予実区分|対象月|金額|
|:--|:--|:--|:--|:--|:--|
|A	|ポータル刷新|労務費	|予定	|1月	|300|
|A	|ポータル刷新|労務費	|予定	|2月	|200|
|A	|ポータル刷新|労務費	|予定	|3月	|300|
|A	|ポータル刷新|労務費	|予定	|4月	|400|
|A	|ポータル刷新|労務費	|実績	|1月	|300|
|A	|ポータル刷新|労務費	|実績	|2月	|300|
|A	|ポータル刷新|労務費	|実績	|3月	|400|
|A	|ポータル刷新|労務費	|実績	|4月	|500|
|A	|ポータル刷新|外注費	|予定	|1月	|0|
|A	|ポータル刷新|外注費	|予定	|2月	|0|
|A	|ポータル刷新|外注費	|予定	|3月	|100|
|A	|ポータル刷新|外注費	|予定	|4月	|100|
|A	|ポータル刷新|外注費	|実績	|1月	|0|
|A	|ポータル刷新|外注費	|実績	|2月	|0|
|A	|ポータル刷新|外注費	|実績	|3月	|130|
|A	|ポータル刷新|外注費	|実績	|4月	|150|

Excel使ってちまちまやるのも手です。
実際、わたしも最初はそうしました。
１つのExcelファイルを作成して、そこにCSV出力したデータを貼り付ける。
そうすると上記のような表が埋められるという具合です。 

しかし、「毎週更新」×「複数プロジェクトが対象」となると、
毎週CSVを出力して1つのExcelファイルのコピペすることになります。
案件が増えると、それ用の手直しを加える必要があり時間を無駄にしすぎます。

# 救世主「列のピボット解除」で解決!

こんな便利がものがあるとは知りませんでした。
表1を表2に一発で変換してくれるのです。  

やり方はこんな感じ
1. PowerBIの「クエリを編集」から「PowerQueryエディター」を開く
1. 1月〜4月を選択
1. 「変換」メニューから「列のピボット解除」を選択
1. 「月」の部分が「属性」、「金額」の部分が「値」となるので、それぞれ名称を変更  

![列のピボット解除の手順](https://media.giphy.com/media/IgKvdGLb2zrPzT4CW3/giphy.gif)

これだけです。
知ってる人からすれば当然のことなんでしょうがメチャメチャ感動。  

PowerBIはデータの読み込み先にフォルダを指定することができるため、
プロジェクトが増えてもCSVを所定のフォルダに突っ込むだけで済みます。  

# 次なる課題
これで従来の作業を大幅に短縮化できました。  
残るは「CSV出力してフォルダに突っ込む」という部分です。
OBIC7にはAPIが用意されていない（私が使えないだけかも）ためCSV経由の取り込みしか思いつきません。
ロボットの手でも借りてどうにかしようと思っています。  



# 備考
この「列のピボット解除」はExcelでもできるようです。
(for Macではどこにあるのか見つけられませんでしたが）
fastTextのインストールエラー


#fastTextのインストール

```
$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ make
```

まず，上記のようにfastTextを`clone`し，`make`を実行します。

しかし，私の場合はここで，

```
error: no member named 'uint8_t' in the global namespace
error: no member named 'uint16_t' in the global namespace
...
fatal error: too many errors emitted, stopping now [-ferror-limit=]
```

と，大量のエラーが出てきてしまいました。

ここで，以下コマンドを実行後に再度`make`を実行するとうまくいきました。

```
$ sudo mv /usr/local/include /usr/local/include.org
```

どうもmacOSをアップグレードした際に残った古いヘッダファイルが原因のようです。
詳しくは以下リンクを見てください。
[macOSでコンパイルエラー: unknown typeとかno memberとかが大量に出たらやること](https://qiita.com/toast-uz/items/14c30eeb8b1337ecb398)

最後に，

```
$ pip install fasttext
```

を実行してください。


#参考
[macOSでコンパイルエラー: unknown typeとかno memberとかが大量に出たらやること](https://qiita.com/toast-uz/items/14c30eeb8b1337ecb398)
クラウド用語集

# 概要
クラウドの用語について、まとめました

# 用語

## オンプレミス
- オンプレミスとは、サーバーやソフトウェアなどの情報システムを使用者（ビジネス利用の場合は企業）が管理する設備内に設置し、運用することを指します。自社運用ともいいます。

	([IDCFrontier - 用語集｜オンプレミス](https://www.idcf.jp/words/on-premises.html))

## SaaS
- 「SaaS」（Software as a Service：「サース」または「サーズ」）とは、ソフトウェアを利用者（クライアント）側に導入するのではなく、提供者（サーバー）側で稼働しているソフトウェアを、インターネット等のネットワーク経由で、利用者がサービスとして利用する状況を指します。

	([IDCFrontier - 用語集｜SaaS](https://www.idcf.jp/words/saas.html))
## PaaS
- PaaS（パース）とは Platform as a Service の略で、アプリケーションを実行するためのプラットフォームをインターネットを介して提供するサービスのことです。

	([IDCFrontier - 用語集｜PaaS](https://www.idcf.jp/words/paas.html))

## IaaS
- IaaSとはInfrastructure as a Service の略で、「イアース」や「アイアース」と呼びます。
IaaSはクラウドコンピューティングのうちの1つで、仮想化技術を利用してハードウェアリソース（CPU／メモリ／ストレージ）などのITインフラをインターネット経由でオンデマンドで提供するサービスです。

	([IDCFrontier - 用語集｜IaaS](https://www.idcf.jp/words/iaas.html))

## SaaS - PaaS - IaaS 関連図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235774/78a034a6-0def-9717-8d7c-ada05b22173b.png)

([IDCFrontier](https://www.idcf.jp/words/f52ppe00000006c4-img/img_iaas_01.png))


## サーバーレス
- 「サーバーレス」とは、その名のとおり、サーバーを意識せずにシステムを構築・運用することを指します。

	([IDCFrontier - 用語集｜サーバーレス](https://www.idcf.jp/words/serverless.html))

- サーバーレスとは、一定のサーバー容量に依存することなく、稼働に必要なリソースを動的に設定し、マネージドサービスを利用する事でシステム構築をする運用方法と言えます。

	([SKYARCH - サーバーレス アーキテクチャ](https://www.skyarch.net/iot/serverless.html))

## SLA(サービス品質保証)
- Service Level Agreement
- サービスの提供者とその利用者の間で結ばれるサービス水準に関する合意である。
- 通信サービスやコンピュータ・アプリケーション・サービスなどで、サービスの定義、内容、範囲、品質、達成目標、稼働率などを記述する。
- 具体的な数値として平均故障間隔(MTBF)、平均修復時間(MTTR)などを利用する。  
	 ([Wikipedia - サービス水準合意](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E6%B0%B4%E6%BA%96%E5%90%88%E6%84%8F))

## スパイクアクセス
- スパイクとは英語で「波形の頂点」といいます。よって、突発的なアクセスの事を指します。

## ロードバランサ
- ロードバランサは、システムに対するリクエストを複数のサーバに分散させ、処理のバランスを調整するための仕組みです。

	([ロードバランサの仕組み – 「さくらのクラウド入門」(4)](https://knowledge.sakura.ad.jp/6274/))

## オートスケール
- オートスケールとはサーバー負荷に応じて、自動的にクラウドサーバーの台数を増減させる機能のことです。
- システムにアクセスが集中したときはサーバーを自動で増やし、アクセスが少ないときはサーバーを減らすことで、常に必要最小限のサーバー数でシステムを安定的に稼働させることができます。

	([IDCFrontier - 用語集｜オートスケール](https://www.idcf.jp/words/auto-scale.html))

## クラスタ
- クラスタとは、複数のコンピューターをまとめて1台のコンピュータシステムとしたものを指します。
- 個々のユーザーが独自開発して使用する場合と、企業がサービスとして提供する場合があります。

	([IDCFrontier - 用語集｜クラスタ](https://www.idcf.jp/words/cluster.html))

## スケーリング
- スケーリングとは、（規模などの）増減、（面積などの）拡大縮小、などの意味を持つ英単語。
- 情報システムの分野では、装置やソフトウェア、システムなどの性能や処理能力を、要求される処理量に合わせて増強したり縮減したりすることをスケーリングという。
- 処理能力を増強する際に、単体の性能を向上させることを「スケールアップ」あるいは「スケールイン」、（サーバなどの）稼働数を増やして処理を分散し、全体として処理能力を高めることを「スケールアウト」という。

	([IT用語辞典 - スケーリング](http://e-words.jp/w/%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0.html))

## RBAC
- ロール ベース アクセス制御 (RBAC) は、認証されていないユーザーによるシステムへのアクセスを制限するためのアプローチです。RBAC はロール ベース セキュリティと呼ばれることもあります。

	([GeneXus - Role Based Access Control (RBAC: ロール ベース アクセス制御)](http://wiki.genexus.jp/hwiki.aspx?Role+Based+Access+Control+(RBAC%3A+%E3%83%AD%E3%83%BC%E3%83%AB+%E3%83%99%E3%83%BC%E3%82%B9+%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E5%BE%A1),))

## ベアメタル
- 「ベアメタル」とは、OSやソフトウェアなどがインストールされていないまっさらなハードディスク（物理サーバー）を指します。

	([IDCFrontier - 用語集｜ベアメタルサーバー](https://www.idcf.jp/words/baremetal.html))
GCPのCompute Engine無料枠サーバでScala botを粘らせる

# 背景
- GCP Compute Engineの無料枠（f1 micro）を使い、[Scala製のslack botアプリ](https://github.com/v2okimochi/Scala-IshiiBot)を走らせていた
- 貧弱メモリにより~~`sbt assembly`が通らず、~~`sbt run`も数日で`insufficient memory for the Java Runtime Environment to continue`で`out of memory`エラーを吐き出す  
※[sbt assemblyは通せた。](https://qiita.com/v2okimochi/items/f78cb91b50773ed19767)が、数日で😇は相変わらず
- 具体的にはサーバで使えるメモリが512MB（実質これ未満）で、JVMやsbtで使うヒープメモリ最大量などを128MBまで絞っても平気で堕ちる
- 毎回手作業でbotをザオリクするのがつらい…つらい…


# 概要
- cronで自動化する
- 厳密には生かし続けるのではなく、毎日ころしては生き返らせてコブシで新鮮なメモリを保つ
- ~~なんでメモリが漏れていくのだろうか…~~

# 手順
今回は`sbt run`でやる場合を書く。

## bot再起動スクリプトを用意する

```shell:restart-bot.sh
date  # 実行日時を出力
pkill -KILL java  # `sbt run`で動いているはずのjavaプロセスを問答無用で黙らせる
export SCALA_BOT_TOKEN='...'  # slack botのトークン
cd ~/Scala-IshiiBot/  # build.sbtがあるディレクトリ（たとえばScala-IshiiBot/）へ移動
setsid nohup sbt -mem 200 run &  # sbt runをバックグラウンドで実行
```

exportでいちいち環境変数を設定し直している。
cron実行時のやつは使えなかった。。。なぜ。。。

SCALA_BOT_TOKENは[Scala製のslack botアプリ](https://github.com/v2okimochi/Scala-IshiiBot)で使うから入れた

`setsid nohup`により、sshを切ってもコマンドは持続する。

`-mem 200`を指定することで使用メモリ上限を抑えられる。
128MBだとプログラムのgoogle injectに押し潰されて😇となり、256MBだとGCP自体のメモリが耐えられず😇となる。
良い感じの落とし所は約200MBの模様。

## スクリプトに実行権限をつける
これでcronから実行できる。

```shell
$ chmod +x ~/restart-bot.sh
```

## cronを設定ファイルから登録

```shell
$ crontab setcron.txt
```

設定ファイルは予め作っておく。例えばホームディレクトリ名が`v2okimochi`の場合はこうなる。

```text:setcron.txt
00 00 * * * ~/restart-bot.sh >> cronlog
```

これは、毎日00:00に`ホームディレクトリ`にある`restart-bot.sh`を実行する＆結果出力は`cronlog`ファイルに追記していく、という意味。

`out of memory`などのエラー情報が追記されていくので、何かエラーを吐いたらここを見れば良い。
エラー以外の情報もあって膨大なので、`restart-bot.sh`側で実行日時を出力するようにした。これで日時から検索できる。

## 日本時間に合わせる
サーバがUTCなので、このままではUTC基準で動いてしまう。
日本時間JSTに合わせる。

```shell
$ sudo timedatectl set-timezone Asia/Tokyo
```

再起動が必要かもしれない。
再起動して再びssh接続すると、`last login`の日時がJSTに変わる。

## cronサービスが動いていることの確認

```shell
$ /etc/init.d/cron status
```

`active(running)`みたいなのが返ってくれば多分動いてる。おｋ。

もし止まってたら動かす。

```shell
$ /etc/init.d/cron start
```

# おまけ
毎回sbtするより`最初にsbt assemblyでjarファイル作っておいてjarを毎回叩いたほうが実は速かったりしない？`と思うこともある。

assemblyでやる場合は、`restart-bot.sh`はこうなる。

```shell:restart-bot.sh
date
pkill -KILL java
export _JAVA_OPTIONS='-Xms128m -Xmx200m'
export SCALA_BOT_TOKEN='...'
nohup java -jar ~/Scala-IshiiBot/target/scala-2.12/slack-bot-scala-assembly-0.1.jar &
```
【pacapt】他のディストリビューションでもpacmanを使いたい！（pacaptのインストール方法）

# 前置き
pacmanのオプションをUbuntuなどの他のディストリビューションで使用できるようにしたスクリプトがpacaptです。
pacaptはaptやpacman、yumなどをpacmanと同じように使用できるようにしてくれます。

[https://github.com/icy/pacapt](https://github.com/icy/pacapt)

このスクリプト、実はインストーラーなどがなくインストールや削除が少々面倒で、何度もこのコマンドを入力するのは面倒です。
そこでpacaptのインストールや削除が簡単に実行できるスクリプトを作成しました。

# スクリプトのダウンロード

ダウンロードはgithubから行います。（短縮URLを使用しています。）

```bash
wget -q https://0e0.pw/h0dT
chmod 755 pacapt-installer.bash
```

#使い方
pacapt-installerには4つのモードがあります。
引数無しで実行後にモード番号を入力するか、モード番号を引数として渡して実行するとその処理が行われます。

###Mode1：pacaptを直接配置
Mode1はpacaptを直接、ディレクトリにインストールします。
ディストリビューションに依存せず、殆どのディストリビューションで正常に動作します。

```bash
sudo ./pacapt-installer.bash 1
```

###Mode2：debファイルを作成してインストール
Mode2ではpacaptのパッケージを作成してインストールします。
Debian及びUbuntuの系列でしか動作しません。

```bash
sudo ./pacapt-installer.bash 2
```


###Mode3：debファイルを作成するのみ
Mode3ではdebファイルを作成するのみです。
複数のコンピューターにインストールする際に有効です。

```bash
sudo ./pacapt-installer.bash 3
```


###Mode4：Mode1でインストールしたpacaptを削除する。
ダウンロードしたファイルやシンボリックリンクを削除します。
debファイルを経由してインストールされたpacaptは削除できません。

```bash
sudo ./pacapt-installer.bash 4
```

### Mode5：アップデート
手動で配置されたかdebでインストールされたかを自動で判定してアップデート（再インストール）を行います

```bash
sudo ./pacapt-installer.bash 5
```
【Java入門】プログラミング14日目までで、ひっかかったことリスト

#目次 Java（手元の入門書を 参考にした。）
1. 初めに
2. 式
3. 条件分岐, 繰り返し
4. 配列
5. メソッド
6. パッケージ, クラス  ←今ここ
7. オブジェクト指向..... 16まで続く。

#1. 初めに
  データ型(int, double, boolean, String...)

#2. 式
  * 大きい方を代入: `int m = Math.max(x, y);`
  * 乱数(0~99): `int r = new java.util.Random().nextInt(100);`
  * (数値入力): `int input = new java.util.Scanner( System.in ).nextInt();`
  * (文字入力): `String input = new java.util.Scanner( System.in ).nextLine();`

#3. 条件分岐, 繰り返し
  * 文字列の比較(X = "Thanks";)
    
        X.equals("Thanks") == true;
  * `switch(num) {
         case 1:
             System.out.println(1);
             break;
         case 2:
             System.out.println(2);
             break;
         default:
             System.out.println("Other");
     }`
  * break, continue.
        

#4. 配列
       int[] nums1 = new int[x];
       int[] nums2 = new int[] {x, y, z};
       int[] nums3 = {x, y, z};
  * 拡張for文

      `for(int i : nums) {
           System.out.println(i)
           }`
*** 例 ***
 `for(int i=0; i < scores.length; i++) { sum += score[k] }
		for(int k : scores) { sum += k; }`
#5. メソッド
          スコープは、{}で囲まれた ブロックの中だけ。
#6. パッケージとクラス
  * パッケージ間でFQCNを省略する方法
    - `import package.Class;`
    - `import package.*;`
  * Java API
Androidの消せないアプリを消す方法(自分用)

## 前提
adbが使える環境

## アプリのパッケージ名を特定する
`adb shell`に入っておく。
消したいアプリを起動する。
`dumpsys activity | grep -B 1 "Run #[0-9]*:`
それらしき、パッケージ名をコピーする。
例 : `com.google.android.youtube`

## アプリを消す(無効化する)

完全なアンインストールも可能ですが、そちらは消したらダメなやつを消してしまった場合のリカバリーがちょっと手間がかかります。
なので、今回は無効化するだけにしておきます。

`pm disable-user --user 0 パッケージ名`

## アプリを戻す方法

`pm enable パッケージ名`


## 参考にしたサイト
[その1](https://hanpenblog.com/6488/)
DockerコンテナをローカルrunしたときECSと同じ様にSecretsManager/SSMパラメータストアの値を環境変数に展開


# やりたいこと

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/specifying-sensitive-data.html
> Amazon ECS を使用すると、AWS Secrets Manager シークレットまたは AWS Systems Manager パラメータストアのパラメータに機密データを保存してコンテナの定義でそれを参照することによって、コンテナに機密データを挿入できます。この機能は、EC2 および Fargate の両方の起動タイプを使用するタスクでサポートされています。

これ、Secrets ManagerやSSMパラメータストアに保存している値をECSで実行するコンテナに環境変数として展開できるので便利です。
ただ、開発中などコンテナをローカルPCで実行(docker run)したいことも多いので、ローカル実行時も同じように展開するシェルを書きました。

# やり方

## 要件
 - ServiceSettingsというパラメータを、dockerコンテナでSERVICE_SETTINGという環境変数に展開したい

## 前提条件
 - aws cliが入っていること

## シェル

aws cliで値を引っ張ってきて -e で割り当てる

### SecretsManagerの場合
```
setting=`aws secretsmanager get-secret-value --secret-id ServiceSetting --output text --query 'SecretString'`

docker run -it \
    -e  SERVICE_SETTING=$setting \
　　...
```
 --output textにするのがミソ

### SSM/ParameterStoreの場合
```
setting=`aws ssm get-parameter --name ServiceSetting --with-decryption --output text --query Parameter.Value | tr -d ' \n'`


docker run -it \
    -e  SERVICE_SETTING=$setting \
　　...
```

trでスペースと改行削除するのがミソ
暗号化してる前提で --with-decryption つけてます（してなかったらいらない）

# これで
ストアの値を環境変数へ展開して利用するアプリケーション(on Docker)のコードを、ECS/ローカル実行で共通にできます。
UITableViewを使った複数選択の仕方

#UITableViewでの複数選択

普段salesforceを使ってるのですが家に帰って勉強がてらswiftを
ぽちぽちしてるので知ったことを備忘録含めて共有します。

```ruby:UITableViewController
class UITableViewController: UITableViewDelegate,UITableViewDataSource {

    @IBOutlet weak var trainingView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()

    trainingView.delegate = self
    trainingView.dataSource = self
    trainingView.allowsMultipleSelection = true

    }

```

####trainingView.allowsMultipleSelection = true
が複数選択を可能にしてくれます。
これ以外にも
####allowsMultipleSelectionDuringEditing
はEditモードの時に複数選択を可能にする物です。

<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/WWVuLixsCF">https://t.co/WWVuLixsCF</a></p>&mdash; Mr.Brooks (@MrBrook27743251) <a href="https://twitter.com/MrBrook27743251/status/1170496857966952448?ref_src=twsrc%5Etfw">September 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

簡単ですがこんな感じで動きます。

よかったら参考にしてみてください。
Logstash では MySQL の DATE 型は使えないと思った方が良い

Logstash v6.7.2 の filter にて以下のエラーが発生し、調査したところ、
Jdbc_streaming filter pluginで参照していた先のテーブル定義に `DATE` 型のカラムが含まれていると、発生することがわかりました。

```
Missing Converter handling for full class name=org.jruby.ext.date.RubyDate, simple name=RubyDate
```

Jdbc_streaming filter pluginでのSELECT時にMySQLの `CONVERT()` で`DATE` 型のカラムを `DATETIME` 型にCONVERTして取り込むことでひとまずは回避ができます。

例）

```sql
SELECT CONVERT(hoge_date, DATETIME) AS hoge_hoge FROM hoge_table;
```
[selenium向け] ChromeDriverをpipでインストールする方法（パス通し不要、バージョン指定可能）

# はじめに
Pythonでseleniumを使いChromeを操作する際にはChromeDriverのインストールが必要です。
通常ChromeDriverをインストールする際にはバイナリを直接ダウンロードしてインストールしますが、ここではpipコマンドでインストールする方法を記載しています。
pipでインストールするとパスを通す必要がなくなります。

普通に`pip install chromedriver-binary`コマンドでインストールすると、ChromeとChromeDriverの互換性の問題でseleniumが使えないことが多々ありますが、バージョン指定の方法も記載しております。

# 手順
## seleniumインストール

```
pip install selenium
```

Jupyter-notebookで実行する際には以下のように、先頭に「!」をつけてください。

```
!pip install selenium
```

以下のように「Successfully」と表示されればインストールは成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/bfa58040-20c2-cca1-4bcb-de4b394745e1.png)

## Chromeのバージョン確認
「設定→ヘルプ→Google Chromeについて」を開くとバージョンが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/9d53a13d-aabd-d82c-3710-5062573b8f12.png)

## ChromeDriverのインストール
まず`pip install chromedriver-binary==<Chromeバージョン番号>` として実行してください。
私の場合はChromeバージョン番号は「76.0.3809.132」でしたので、以下のコマンドを実行します。

```
pip install chromedriver-binary==76.0.3809.132
```

Jupyter-notebookで実行する際には以下のように、先頭に「!」をつけてください。

```
!pip install chromedriver-binary==76.0.3809.132
```

たぶん以下のようなエラーが表示されると思います。
もしエラーが出なかった場合は「動作確認」の項目に進んでください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/d1fe0202-1d96-75bd-53c2-7eff6fd3e003.png)

## エラー内容の確認と、ChromeDriverを再度インストール
このエラー内に表示されているバージョン番号は、存在するChromeDriverのバージョン番号です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/967561cf-8492-c7ff-e015-e643ca84e936.png)

Chromeのバージョン番号と、ChromeDriverのバージョン番号を比較してください。
きっと同じバージョン番号はないと思います。
そこで、Chromeのバージョンより少し小さい数値のChromeDriverのバージョン番号を探してください。

私の場合はChromeバージョンが「76.0.3809.132」で、それより少し小さい数値のChromeDriverバージョンは「76.0.3809.126.0」がありました。

その後、そのChromeDriverのバージョン番号を用いて、再度以下のコマンドを実行してください。

```
pip install chromedriver-binary==76.0.3809.126.0
```

Jupyter-notebookで実行する際には以下のように、先頭に「!」をつけてください。

```
!pip install chromedriver-binary==76.0.3809.126.0
```

以下のように「Successfully」と表示されればインストールは成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/09379291-dacb-9dfc-a7fa-674d326bf1fb.png)

## 動作確認
以下のコマンドを実行してください。

```
from selenium import webdriver
import chromedriver_binary
driver = webdriver.Chrome()
```

以下の画面が表示された場合は「アクセスを許可する」をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/77d8792b-5d0b-9ce6-f947-d018202aeea3.png)

その後、以下のようにChromeブラウザが表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/e9d79ffc-8674-6bb3-ea80-250bc9cb613b.png)
Python3 requests 使い方メモ

基本的な使い方のメモです。

##requestsモジュールのインストール

```
$ pip3 install requests
```

##基本的な書き方(get)

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import json

# エンドポイント
url = 'https://XXXX-api/vX/XXXX'
  
# リクエスト
res = requests.get(url)

values = json.loads(res.text)
print(values)
```

##postの場合

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import json

# エンドポイント
url = 'https://XXXX-api/vX/XXXX'

data = {
    'id': '12345',
    'version': 'XXXXX',
    'item': 'XXXXX'
    }

# リクエスト
res = requests.post(url, json=data)
values = json.loads(res.text)

print(values)
```

##その他のHTTPメソッド

```python
res = requests.put(url)
res = requests.delete(url)
res = requests.head(url)
res = requests.options(url)
```

# カスタムヘッダーを使う場合

```python
headers = {
    'Authorization': 'Bearer XXXX'
}

res = requests.get(url, headers=headers)
```

##参考
requests クイックスタート
https://requests-docs-ja.readthedocs.io/en/latest/user/quickstart/
[Golang]DB操作に便利なパッケージ、「xorm」の動作確認サンプルコード

# はじめに

今回は、`xorm`というパッケージを使って、簡単にデータベース操作の確認をしてみたので、共有させて頂きます。

# いきなり結論のコード

```golang:今日のコード
package main

import (
	"fmt"

	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
)

func main() {
	engine, err := xorm.NewEngine("mysql", "root:password@/mydb")
	if err != nil {
		fmt.Println(err)
	}
	defer engine.Close()

	result, err := engine.Query("select * from users limit 1")
	if err != nil {
		fmt.Println(err)
	}

	for k, v := range result[0] {
 	 	fmt.Println(k, string(v)) // => 取得できているか確認
 	}
}
```

# 解説

## `xorm.NewEngine()`でエンジン作成

```golang:
engine, err := xorm.NewEngine("mysql", "root:password@/mydb")
```

`xorm`パッケージに用意されている、`NewEngine`関数でエンジンを作成します。
ここは、僕の実力ではうまく説明できない部分なのですが、DBに接続する前の準備のようなものかと捉えています。

ここで用意した`engine`変数を起点に、この後の処理が行われます。
今回は、xormの関数を使っているのがこの部分だけですが、xormパッケージのインポート確認が取れています。

## `engine.Close()`でクローズする

```golang:
defer engine.Close()
```

忘れる前に、大事なクローズ。
`defer`をつけて、最後に実行するようにしてます。

## `engine.Query()`でクエリ作成

```golang:
result, err := engine.Query("select * from users limit 1")
```

`Query`関数は、クエリをそのまま投げられます。今回は、生SQLを突っ込んで、とりあえずの動作確認をしてます。

## 取得できたデータの型に注意

```golang:そのまま出力
fmt.Println(result)
```

```console:出力結果
[map[birthday:[49 57 55 56 45 48 51 45 49 50 32 48 48 58 48 48 58 48 48] email:[115 104 105 98 97 115 97 107 105 95 97 115 97 104 105 64 101 120 97 109 112 108 101 46 99 111 109] first_name:[230 156 157 233 153 189] gender:[50] id:[49] last_name:[230 159 180 229 146 178] prefecture_id:[49]]]
```

そのまま出力してみると、バイト型になっている…
取得できているけど、値がわからない。


## とりあえずstring型にキャストして取得データの確認

```golang:valueのみstring型にキャスト
for k, v := range result[0] {
 	fmt.Println(k, string(v))
}
```

```console:出力結果
gender 2
birthday 1978-03-12 00:00:00
prefecture_id 1
id 1
email shibasaki_asahi@example.com
last_name 柴咲
first_name 朝陽
```

ちゃんと取れてました！
（もちろん、データは架空のものです。）

# さいごに

また、至らない点があれば、コメントなどでご指摘頂ければ嬉しいです。
最後まで、ありがとうございました。
CloudFrontのCORS対応

S3上に存在する動画を再生するアプリを作成中、
MediaConvertを利用して作成したMPEG-DASHが再生できない状況に。

エラーとしてはCORSの問題だったので、はじめはS3のバケットに
CORSの対応を施した。

別途、CloudFrontを利用しての再生においては、
CloudFront自体にもCORSの対応が必要だったのでメモ。

１．"CloudFront Distributions"にて対象を選択
２．遷移先にて、"Behaviors">対象behaviorを選択>"Edit"
３．"Allowed HTTP Methods"で、"GET,HEAD,OPTIONS"を選択
　ー＞これは、PUTなども必要であれば、もう一つの選択肢を選択
４．"Cached HTTP Methods"で、"OPTIONS"をチェック
５．"Cache Based on Selected Request Headers"で"Whitelist"を選択し、
　　"Whitelist Headers"で、"Origin"を Add。

その後アクセスすると、一発目はCORSのエラーが出るが、しばらくすると対象のコンテンツが表示され、
次回以降（キャッシュに存在するあいだ）は、問題なく再生できた。
【勉強会資料】Packet Tracerでルータを用いたネットワークの構築 - 全体の流れ

# はじめに

この記事は、2019年9月5日に開催の [サポーターズCoLab](https://supporterzcolab.com/)勉強会「[ネットワーク基礎実験ハンズオン - ルータを用いたネットワークの構築](https://supporterzcolab.com/event/925/)」のための資料です。勉強目的での利用をしていただくことは構いませんが、内容についてはサポートできかねますのでご了承ください。

# この記事の目的
Ciscoネットワーク機器のはじめの一歩として、パケットトレーサー上で簡単なネットワークを構築して通信を行う実験の手順を説明します。コマンドを含めた解説は[こちら](https://qiita.com/KozyCorner/items/417ffa37edb2f3c48ab7)

## 実験内容

- スタティックルーティングによるネットワーク構築
- ダイナミックルーティングによるネットワーク構築

# 事前準備

以下の記事を参考にPacket Tracerを入手しダウンロード・インストールを行い、起動してください。

[Cisco Packet Tracerの入手方法 - Qiita](https://qiita.com/KozyCorner/items/24716eacd2802c6f372c)

# 操作・コマンド集

この記事ではコマンドの使い方やパケットトレーサーの操作方法は解説しません。操作やコマンドについては、都度以下の記事を参照し、必要な変数を書き換えるなどして使ってください。

[Packet Tracerでルータを用いたネットワークの構築 - 操作・コマンド集](https://qiita.com/KozyCorner/items/8dd90cec20a9687c2972)

# 手順

<img width="479" alt="スクリーンショット 0031-09-05 18.59.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326374/0d82199c-ed4c-63bb-2e64-706673df771f.png">

## スタティックルーティングによるルーティング

1. ルータとPCを図のように接続し、各機器の電源を入れる
    - パケットトレーサー上では配置した瞬間に電源は自動でONになります

1. PCのIPアドレスとサブネットマスクを図の通り設定する

1. ルータの設定を行う
	1. ルータ起動時に`[yes/no]`のような確認が出た場合は`no`と入力する
	2. 特権モードに移行する
	3. グローバルコンフィグレーションモードに移行する
	4. 図中の各ポートの特定コンフィグレーションモードに移行し、図の通りIPアドレスを設定する

1. PCとルータの
間で`ping`が通るか確認する

1. 各PC間で`ping`を実行し、この時点でまだ通信が **できないこと** を確認する

1. チートシートを参考に、ルータのルーティングテーブルの設定を行う

1. 各PC間で`ping`が通ることを確認する

1. ルータで`show ip route`コマンドを、PCで`tracert`コマンドを実行し、結果を確認する


## ダイナミックルーティングによるルーティング

1. ルータとPCを図のように接続し、各機器の電源を入れる
    - パケットトレーサー上では配置した瞬間に電源は自動でONになります

1. PCのIPアドレスとサブネットマスクを図の通り設定する

1. ルータの設定を行う
	1. ルータ起動時に`[yes/no]`のような確認が出た場合は`no`と入力する
	2. 特権モードに移行する
	3. グローバルコンフィグレーションモードに移行する
	4. 図中の各ポートの特定コンフィグレーションモードに移行し、図の通りIPアドレスを設定する

1. PCとルータの
間で`ping`が通るか確認する

1. 各PC間で`ping`を実行し、この時点でまだ通信が **できないこと** を確認する

1. チートシートを参考に、ルーティングプロトコルを `RIP` に設定する

1. チートシートを参考に、 `RIP` でルーティングテーブルを設定する

1. 各PC間で`ping`が通ることを確認する

1. ルータで`show ip route`コマンドを、PCで`tracert`コマンドを実行し、結果を確認する
CWLで、ツールが複数のファイルを必要とするときなど、secondaryFiles について

# 概要

想定するのは、ファイルの拡張子がない部分を渡すと、ツールが拡張子をつけて、
必要なファイル群を探すというツールがある。

# 結論

`必要なファイル群` のうち、１つのファイルを指定し、
`文字列` は、その渡された１つのファイルから、生成し、
ほかの `必要なファイル群` は、`secondaryFiles` で指定するのがよさそうである。


# 考え方

この場合、ツールには `文字列` だけを引数として渡すので、
ツール定義(CommandLineTool)にも、 `文字列` を渡して、 `必要なファイル群` を、
ツール定義の中で生成したくなるが、その方向に進んで、いまだに成功していない。

ツールにとって必要なのは、以下のものなので、一番重要とおもわれる。ファイル群を指定する。

1. ファイル群
2. ファイル群のプリフィックス

# 実行するツールが使うファイルを指定し、そこから

`sample1.bwa` のファイルを指定して、
secondaryFilesに、 `sample1.bai` を指定するようにする。

```
inputs:
  - id: bwa_file
    type: File # .bwa を指定する
    secondaryFiles:
      - ^.bai # こちらは、ユーザーが明示的にしていしなくてよい。
```

## lastalの場合

このツールには、 `.prj` ほか、いくつかのファイルが、必要である。
この場合は、`.prj` ファイルを指定し、そこからほかのファイルを `secondaryFiles` としてステージングするようにする。

```
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [lastal]
arguments:
  - -Q$(inputs.query_sequences)
  - -e$(inputs.minimum_alignment_score)
  - -i$(inputs.batches)
  - $(inputs.dbname.dirname)/$(inputs.dbname.nameroot)
  - $(inputs.source)
inputs:
    - id: query_sequences
      type: int
    - id: minimum_alignment_score
      type: int
    - id: batches
      type: int
    - id: dbname
      type: File # .prj
      secondaryFiles:
        - ^.tis
        - ^.des
        - ^.bck
        - ^.sds
        - ^.ssp
        - ^.suf
    - id: source
      type: File
outputs:
    - id: outputmaf
      type: stdout
stdout: $(inputs.source.nameroot).maf
```

ただこの場合は、フルパス指定がかのうだったのよかった。
相対パス指定の場合は、また少し考える必要がある。

# 失敗談、ファイル名部分から拡張子をつけて必要なファイルを指定しようとした。

ファイル名を文字列として受け取り、拡張子部分を自動生成しようとしても、うまくいかない。（現状うまくいっていない）

例えば `sample1` だけを渡して、そこから、
- sample1.bwa
- sample1.bai
というファイルを指定するようにしてもうまく動かない。

これは、ファイルをステージングする段階よりあとに、
`sample1` という文字列から、`sample1.bwa`と`sample1.bai`を生成する順番になっていると考えられる。

## 実際の例

`test` という文字列を渡して、いかの３つのファイルをツールにわたしたかったが、うまくいかなかった。

- test.txt
- test.tsv
- test.csv

```
cwlVersion: v1.0
class: CommandLineTool
requirements:
  InlineJavascriptRequirement: {}
baseCommand: [cat]
arguments: []
inputs:
    - id: prefix
      type: string
      inputBinding:
          valueFrom: |
            ${
                return { class: "File", path: "test.txt", location: "test.txt"  };
            }

outputs:
  - id: out
    type: stdout
stdout: output.txt
```


# おまけ、重要とおもわれるファイルを探すこと

bwaとbaiなどは、関係性がわかりやすいとして、その他のケースで
最初に指定するファイルに関しては、ツールを使う人にどれが重要な
ファイルなのかを確認して、それだけCWLに明示的に指定する指定するようにするとよい。

専門家もいないようなときは、何もファイルをわたさずに、ツールを実行してエラーメッセージから推測するという方法がある。
gem,bundler,webpacker,yarn,Node.jsとはなんなのか

ubuntuでRails6.0.0のローカル開発環境を作るときに、webpackerが入っていないと言ったエラーが起こりRailsの最初のページを出すのに苦労しまして、その時に出てきた単語の意味を超簡単に纏めてみました。
ちなみにgemって結局何？ってレベルでしたので本当に簡単にです。

##目次
- gemとは
- bundlerとは
- webpackerとは
- yarnとは
- Node.jsとは

##gemとは
Rubyのライブラリの事です。
このライブラリとは、ある特定の機能を持ったプログラムを他のプログラムから呼び出して利用できるように部品化し、複数集めて1つのファイルに収納したもの。…

つまりgemとはRubyで使える誰かが作ってくれた便利なプログラムをいっぱい集めてるファイルです。

##bundlerとは
gemと依存関係とバージョンを管理するためのツールです。ちなみにbundlerもrubyのライブラリです。
bundlerを使うと依存関係にあるgemを一括でダウンロードしてくれるらしい。…

##webpacketとは
Railsプロジェクトでwebpackを導入する際に用いられるgem。恐らくインストーラーみたいな物かな？

###webpackとは
モジュールを一纏めにしてくれるツール。
これを使うと可読性や保守性が高くなるらしいです。

##yarnとは
JavaScriptのパッケージマネージャです。
パッケージマネージャとはインストールしたソフトを記録し、ソフトのインストール、更新、削除を簡単に行えるようにするツールです。

##Node.jsとは
サーバーサイドで動かせるJavaScriptの事です。

分からない単語を調べるとさらに分からない単語が出てくるのが中々難しいです…。

そのうちこれらのツールの使い方を投稿出来たらなと思います
window.onerror を Chrome の Developer console で発火させる方法

## window.onerror

window.onerror とは、処理を設定しておくことで UI 処理全体の `Uncaught Error (catch されなかった error)` を catch することができます。Global (ブラウザの window 全体) の Error handling です。

```javascript
window.onerror = function(errorMessage, filePath, rowNumber, columnNumber, errorObject) {
    alert(errorMessage);
};
```

## Chrome の Developer console で試してみる

Chrome の Developer console を開いて以下のように window.error を定義し、Error を throw してみます。

```javascript
window.onerror = function() {
  alert('Error has occurred!');
}

throw new Error('Boom!');
> Uncaught Error: Boom!
    at <anonymous>:1:7
```

alert dialog が出ませんでした... :thinking:

これは、同期処理に関しては Global にではなく、Developer console 内でエラー処理を完結しようとしているからのようです。
逆に言うと、window.onerror を発火させるためには非同期処理でエラーを起こせば良いと言うこと。

## setTimeout を使って非同期にする

setTimeout は ms (1/1000 秒) なので、1秒後に Error を throw してみます。

```javascript
window.onerror = function() {
  alert('Error has occurred!');
}

setTimeout(function() { throw new Error('Boom!') }, 1000);
```
.....
<img width="448" alt="スクリーンショット 2019-09-05 18.25.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182916/024b439d-e77e-df58-474a-50cc7107f0cd.png">
出ました！ :tada: :tada: 

思えば、Node.js でも以下のように同期処理だったら、もちろん throw した Error を catch してくれますが、

```javascript
// err_test.js

try {
  throw new Error('Error has occurred!');
} catch(e) {
  console.log(e);
} 
```

```shell
$ node err_test.js
> Error: Error has occurred!
```

非同期処理にすると、node の Context(環境) を突き抜けて Shell が status code 1 を返していました。

```javascript
// err_test.js

try {
  setTimeout(function() { throw new Error('Error has occurred!'); }, 1000);
} catch(e) {
  console.log(e);
}
```

```shell
$ node err_test.js
err_test.js:3
  setTimeout(function() { throw new Error('Error has occurred!'); }, 1000);
                          ^
shell returned 1
```

ある Context を逸脱し、それを包含しているより広い Context 影響を与えるには、非同期処理というのが一つキーポイントになるようです :thinking:

※ Node.js の件に関してはこの記事がとても勉強になりました。
https://techblog.yahoo.co.jp/programming/javascript_error/ 

## おまけ

非同期処理で Context を逸脱しなくても、ブラウザのアドレスバーに以下のように直接入力し、Grobal の Error handling を発火させるという荒技もあるようです。

```javascript
javascript: throw New Error('Error has occurred!');
```