OmniAICreator/Qiita-1.07M huggingface dataset:
フォルダ内の画像を全て半分のサイズにする

#はじめに
業務でBackLogを使用していて、Wikiに業務手順を書くことが結構あります。
個人的にですが、手順書は行う手順と1つ先の作業がわかっていたほうがなんとなくわかりやすい気がします。
説明①→説明①の画像→説明②→説明②の画像→....のような構成になることが多いのだが、説明①の画像が大きすぎると次の手順が見えず、なんとなく見にくいなぁと感じます。

↓この説明文を
![000447.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311371/41852ea7-c82f-1e43-a0fa-98eba3e42623.jpeg)

↓こうしたい
![000449.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311371/9f5209cf-ec96-82a7-96b3-1107bd531ccc.jpeg)

しかし私のように説明に画像を多用する人は、1つ1つ画像をリサイズするの結構手間がかかっていたため、
フォルダ内の画像を全てリサイズするプログラムを作成しました。

##前提条件
python 3.6
pillow 
※pillowは```pip install pillow```でインストールできます。

#リサイズ対象ファイル
resize.pyと同じ階層のファイルは対象にしていません。
以下のような構成の場合

```
rezise/
├ フォルダA/
│　└ ファイル1.jpg
│　└ ファイル2.png
│
├ フォルダB/
│　└ ファイル3.jpg
│　└ ファイル4.png
│
├ resize.py←実際に動かすプログラム
└ ファイル5.jpg
```
フォルダA内のファイルとフォルダB内のファイルが対象です。

そのためリサイズされるファイルは
「ファイル1.jpg」 「ファイル2.png」 「ファイル3.jpg」 「ファイル4.png」です。

同じ階層内にある「ファイル5.jpg」はリサイズされません。



##コード

```
import os
from glob import glob
from PIL import Image

def resize(rename):
  for dir_name in all_dir:
    #リサイズする拡張子を指定
    extensions = ["/*.jpg", "/*.jpeg", "/*.png"]
    files = []
    #リサイズするデータをリストに入れる
    for extension in extensions:
      files.extend(glob(path + dir_name + extension))
    #resize
    for f in files:
      img = Image.open(f)
      #画像サイズを半分にする
      img_resize = img.resize((int(img.width/2), int(img.height/2)))
      if rename == "はい":
        #ファイル名と拡張子をわける
        ftitle, fext = os.path.splitext(f)
        img_resize.save(ftitle + '_half' + fext)
      else:
        img_resize.save(ftitle + fext)

#リサイズするフォルダを指定
path = ("./")
#path直下のフォルダ名、ファイル名を取得
all_file = os.listdir(path)
#ファイル名のみにする
all_dir = [f for f in all_file if os.path.isdir(os.path.join(path, f))]

save_name = input("別名保存にしますか？(はい or いいえ)> ")
if save_name == "はい":
  resize(save_name)
  input("処理が完了しました。元の名前 + halfという名前で保存されています。Enterを押してください。")

elif save_name == "いいえ":
  resize(save_name)
  input("処理が完了しました。Enterを押してください。")
else:
  input("はい or いいえで入力してください。処理を終了します。Enterを押してください。")


```

##プログラムの説明
元の画像サイズの半分で保存されます。
「2500px × 1250px」の画像の場合
「1250px × 625px」になります。

1/3にする場合、以下のコードの「2」を「3」にします。


```
 #画像サイズを半分にする
      img_resize = img.resize((int(img.width/2), int(img.height/2)))
```

指定サイズがある場合、横サイズは```int(img.width/2)```を数値(1250など)に
縦サイズは```int(img.height/2)```を数値(625など)にするとそのサイズにリサイズされます。

##使い方
プログラムを起動すると
```別名保存にしますか？(はい or いいえ)>```
とコンソールに表示されます。

```はい```を入力すると、元画像と同じフォルダに「元の画像名 + half + .拡張子」で保存されます。
```いいえ```を入力すると、元の画像に上書き保存されます。

##終わりに
とりあえず全ファイルを半分にするプログラムを作成しましたが、小さすぎるファイルは変換する必要がなく、大きすぎるファイルは2回変換にかける必要があります。

例えば「200px × 200px」半分にすると、小さすぎて画像が見にくかったり
逆に「3000px × 3000px」を半分にしても、「1500px × 1500px」なので、もう一度変換する必要があります。

特定の大きさ以上の場合1/3に変換し、特定のサイズ以下の場合変換を行わないなどすれば、より使いやすくなると思いました。
Redashの日時表示を日本形式 (YYYY-MM-DD)に変更する

Redashはデフォルトの設定によって日時表示が`DD/MM/YY`になっており、見慣れない形式で絶妙にストレスです。
非エンジニアもクエリを発行してデータ抽出しているのですが、わざわざコピーして書き換えたりしていてムダな作業が発生してしまう…！
設定で簡単に`YYYY/MM/DD`の日本で馴染みが深い形式に変更できたので、初期設定時にパッとやってしまうのが良さそうです。

# 方法
環境設定ファイルのパラメーターをの値で設定する。

```/opt/redash/current/.env
 REDASH_DATE_FORMAT="YYYY/MM/DD"
```

初期設定だと`/opt/redash/current/.env`が設定ファイルになっており、こちらを変更して再起動したら反映される。
ちなみに、時間フォーマットは`HH:mm`。こちらは変更する必要がなかったので変えなかったが、変えたい場合のパラメーターは`REDASH_TIME_FORMAT`。

**設定パラメーターの一覧**
[Environment Variables Settings](https://redash.io/help/open-source/admin-guide/env-vars-settings)
テキストアノテーションツールbratをwindowsで使う

# 動機
bratをwindowsでlocalhostとして使うことになった際にかなり手間がかかったので、メモとして残しておく。

# そもそもWindowsじゃ無理臭い
http://brat.nlplab.org/installation.html
↑チュートリアルに従って進むと.gzを解凍しないといけない場面がある。windowsだとソフトを入れないと解凍しないといけないのでめんどくさい。
仮に解凍して進めても、linuxでないと実行できないと言われる。https://github.com/rq/rq/issues/859

# じゃあ Ubuntu for windows 使いましょう。
参考にしたサイト　https://qiita.com/Aruneko/items/c79810b0b015bebf30bb

# 次は python2系 を導入しよう。
bratを実行するには**python2系**が必要（自分は3系だと勘違いして苦しんだ）なのでインストールする。でもイマドキ2系なんて使うかぁ・・・？普段使いするなら3系だから、安易に2系をインストールのはマズいと考えたためpyenvを使うことに。

# pyenvでpython2系を使うまで結構躓く
pyenvを導入するには　https://www.komee.org/entry/2018/10/25/120000
このサイト通りにやっていけば大丈夫だが、途中パッケージが足りないというエラーを吐かれた。
解決のために参考にしたサイト　
https://qiita.com/utgwkk/items/bf282ca95f64ef7dd594
https://www.systutorials.com/topic/how-to-install-the-zlib-library-in-ubuntu/

python2系が正しくインストールされたら、あとはチュートリアル通りにやれば良い。
【ln -s】世界一シンプルなシンボリックリンクまとめ [Linux]

#はじめに
すごくシンプルで簡単にシンボリックリンクについてまとめました。
とりあえず、これだけ押さえておけば、ここで紹介する用途以外にシンボリックリンクを利用する際にも、問題なく理解が進むでしょう。

**対象読者**
シンボリックリンクという言葉を聞いたことはあるが、いまいちどういう場面で利用するのかイメージが湧かない方。

#シンボリックリンクとは
ファイルの実体に直接名前をつけるのがハードリンク、
実体ではなく、ファイル名に対して間接的に名前をつけるのがシンボリックリンクです。

イメージとしては、
全てのファイルには**名前**がついており、**本名**と**別名**の２種類あった時に。
ファイルの本名が**ハードリンク**、別名が**シンボリックリンク**といった感じです。

そのうち、ファイルやディレクトリを管理する際には、シンボリックリンクが活躍することが多く、それはファイルやディレクトリの**代理人**としての役回りをします。Windowsにおける**「ショートカット」のUNIX系OSにおける呼び名**のようなものです。

###具体的な状況で理解しよう
データファイルは**Document**ディレクトリの下に用途別に分けて管理し、よく使うファイルだけは**Desktop**に**ショートカット**を置いておく、という使い方はGUI環境ではお馴染みですよね。ショートカットは**近道**をいう名前の通り、目的のファイルへの**パス**が入っており、CUIの環境ではそれを、シンボリックリンクで実現しようということです。

#作成

```
❯ ln -s Document/projects/projectX/data02.txt ./latest
```
もしくは

```
❯ ln -s Document/projects/projectX/data02.txt latest
```
あるいは、同じ名前で作成したい場合、第二引数は省略して良い。
（ここでは、latestという名前ではなく、data02.txtという名前のリンクが作成される）

```
❯ ln -s Document/projects/projectX/data02.txt
```

#削除

```
❯ unlink latest
```


#ディレクトリにシンボリックリンクを作成（主な用途）
主な用途に、ディレクトリにシンボリックリンクを作成することがあります。
プロジェクトの進行中など、ディレクトリの奥深くに目的ディレクトリがある場面は多いと思います。長期にわたってのプロジェクトなどは、毎回作業前にディレクトリへ移動するのは、地味に手間がかかるものです。その際、ディレクトリにシンボリックリンクを作成すると、移動の手間が省け、いくぶん楽になるのでおすすめです。

```
// 奥深いプロジェクト
❯ ls Document/projects/projectX
data01.txt data02.txt

// シンボリックリンク作成
❯ ln -s Document/projects/projectX

// 簡単アクセス
❯ ls projectX
data01.txt data02.txt
```
注： 上記の場合、同じ名前で作成したいので、第二引数は省略しています。

#補足（オプション）

| オプション | 意味 |
|:--|:--|
| -s (--symbolic) | シンボリックリンクを作成する  |
| -f (--force) | すでに登録名が登録されたものであった場合、強制的に上書きする  |
| -i (--interactive)  | すでに登録名が登録されたものであった場合、上書き前に確認する  |
| -v (--verbose)  | リンクを登録する際、登録する登録名とリンク先を表示する  |
| -b (--backup) | すでに登録名が登録されたものであった場合、元々のリンクをバックアップし新規にリンクを登録する |

#参考
- [【ln】コマンド -- ファイルのハードリンクとシンボリックリンクを作る](https://www.atmarkit.co.jp/ait/articles/1605/30/news022.html)
- [シンボリックリンクの作成と削除](https://qiita.com/colorrabbit/items/2e99304bd92201261c60)
- [lnコマンドについて詳しくまとめました【Linuxコマンド集】](https://eng-entrance.com/linux-command-ln)
ubuntu 18.04でredisインストールがunable to locate packageになる

```bash
$ sudo apt install redis
```

しようとしたところ

```bash
E: Unable to locate package redis
```
になってしまった

###原因

universeパッケージを無効になっているので、そのパッケージを有効にしなければならない。

###対策
以下を実行

```bash
$ sudo add-apt-repository universe
```

その後再度

```bash
$ sudo apt install redis
```

を実行するとすんなりインストールできた。

ついでにバージョンを確認

```bash
$ redis-server -v
```

###参考
https://askubuntu.com/questions/1073695/18-04-server-unable-to-locate-package-redis-server
lambdaについてのメモ

こんにちは！
未来電子テクノロジーというところで長期インターン中の大学三回生です。
今回は自分が**lambda**について理解するためにメモ程度に書いていこうと思います。

##lambdaとは
``lambda式とは関数に名前を付けずに定義するものです。``
僕が検索すると上記のような説明が出てきました。
僕の解釈では**def**を使わずに関数を定義する方式だと考えています。

##lambdaの使い方
lambda式の基本的な形式は``lambda 引数:処理``です。
では実際に使ってみたいと思います。
下記にコードを書いていきます。

```python


total_price = lambda price,tax: price+(price*tax)
lambda_tax = total_price(100,0.08)
print(lambda_tax)
#108.0
```
こんな感じで使います。
**def**で関数定義せずにlambda式で定義しています。
しかし、上記の例ではtotal_priceという名前をつけています。
これを一行で表すとこうなります。

```python

print((lambda price,tax:price + (price * tax))(100,0.08))
```
上記の例では名前を付けずに定義しています。
では、lambda式はどのようなところで役立つのでしょうか。
僕が検索した記事によるとsorted()などでよく使用されているようです。

##sorted()とlambda
まず、sortedの例から見ていきます。

```python

a=[(0, 5), (1, 4), (2, 3), (3, 2), (4, 1), (5, 0)]
print(sorted(a))
print(sorted(a, key=lambda x : x[1]))
#[(0, 5), (1, 4), (2, 3), (3, 2), (4, 1), (5, 0)]
#[(5, 0), (4, 1), (3, 2), (2, 3), (1, 4), (0, 5)]
```
上記ではキー引数を指定せずにsorted()にかけてソートしています。
すると、内側のタプルの最初の要素を昇順にソートしてくれます。
キー引数にlambda式を渡すことでタプルの二番目の要素で昇順にすることができます。

##まとめ
今回はlambdaについて少しだけご紹介しました。
これらは全て検索して出てきたものなので、もっと詳しく知りたい方は調べてみてはいかがでしょうか？
参考文献を載せておくのでそちらから飛んでみてください。
最後まで読んでいただきありがとうございました。

##参考文献
[Pythonのlambda（ラムダ）式の書き方と使い方まとめ](https://www.headboost.jp/python-lambda/)
[【Python入門】lambda(ラムダ式)の使い方](https://www.sejuku.net/blog/23677)
AWS EKS をはじめてみる

## はじめに

EKSをまだ試したことがなかったので、ドキュメントに従って、EKSを始めてみます。
躓いたら、下記の公式ドキュメントから読んでいくといいと思います。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/what-is-eks.html

コマンドの備忘レベルで、特別なことはしてません。すいません。

下記続編もあります。

- [AWS EKSにNLB入れて動かす](https://qiita.com/foursue/items/48b85ab85faca55ccd1e)

## インストール

私はMacなので、`eksctl`を`homebrew`でインストールしました。
`eksctl`をインストールすると一緒に`kubectl`もインストールされます。便利ですね。 

```bash
$ brew install weaveworks/tap/eksctl
$ which eksctl
/usr/local/bin/eksctl
$ which kubectl
/usr/local/bin/kubectl
$ eksctl version
[ℹ]  version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.3.1"}
```

## aws configure

すでにやってる人は必要ないですし、プロファイルを切り替えて操作する人は適宜対応してほしいです。

※下記は https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started-eksctl.html から持ってきたサンプル

```bash
$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json
```

## 作る

```bash
eksctl create cluster \
--name development \
--region ap-northeast-1
--version 1.13 \
--nodegroup-name standard-workers \
--node-type t2.micro \
--nodes 1 \
--nodes-min 1 \
--nodes-max 1 \
--node-ami auto
--profile ***（必要なら）

aws eks --region ap-northeast-1 update-kubeconfig --name development --profile ***（必要なら）
```

## 作った

```bash
$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   18h
```
[SQL][Postgre][Presto](初心者用よ) 縦持ちのデータを横持ちに持ち直す方法

## 前置き
MAなどにおいて、縦持ちのデータを横に持ち直さなければならないときってありますよね。
テーブルの名前を as で定義して、同じテーブルをいくつもJOINさせる方法もありますが、もう少し簡単な手法をご紹介します。
とっても初心者向けなので、つよつよな方・・・ごめんなさい。

## データセット
- user
    - ユーザーTBL
- visit
    - ユーザーのウェブサイト訪問記録TBL

### user

| id |
| :---: |
| 1 |
| 2 |
| 3 |

### visit

| id | user_id | view_page | created_at |
| --- | --- | --- | --- |
| 1 | 1 | A | 2019-08-01 |
| 2 | 2 | B | 2019-08-01 |
| 3 | 2 | C | 2019-08-02 |
| 4 | 1 | B | 2019-08-03 |
| 5 | 3 | B | 2019-08-04 |
| 6 | 1 | B | 2019-08-05 |

### Join

```.sql
select
  *
from
  user
  left outer join
    visit
    on  user.id = visit.user_id
```


## サンプル
A, B, Cページに訪れた回数を数えましょう。

### 期待結果

| user_id | visit_A | visit_B | visit_C |
| --- | --- | --- | --- |
| 1 | 1 | 2 | 0 |
| 2 | 0 | 1 | 1 |
| 3 | 0 | 1 | 0 |

### クエリ

```.sql
-- postgres
select
  visit.user_id
  , sum( case when view_page = 'A' then 1 else 0 end ) as visit_A
  , sum( case when view_page = 'B' then 1 else 0 end ) as visit_B
  , sum( case when view_page = 'C' then 1 else 0 end ) as visit_C
from
  user
  left outer join
    visit
    on  user.id = visit.user_id
group by
  visit.user_id
```

prestoではちょっと変わった書き方も可能です。
postgreと同じでも出力結果は変わりませんが、個人的にはこっちのほうが見やすくて好きです。

```.sql
-- presto
select
  visit.user_id
  , sum( if( view_page = 'A', 1, 0 ) as visit_A
  , sum( if( view_page = 'B', 1, 0 ) as visit_B
  , sum( if( view_page = 'C', 1, 0 ) as visit_C
from
  user
  left outer join
    visit
    on  user.id = visit.user_id
group by
  visit.user_id
```

今回はsumを使いましたが、countを使うほうがいいかもしれません。
そこまで細かくは検証していないので、気になる方がいたら、修正してもらえると嬉しいです。

なお、フラグを立てる場合にも役立つので便利ですね。

## 補足
max, minなどの集約関数を用いれば、もう少し難しいこともできますよ。
私も頑張ってやっていきます。
git環境で修正したファイルだけを対象にrubocopを実施する方法

前のコミットからの修正ファイルだけを対象にRubocopを実施したい
という人にオススメのコマンド。

```
$ git diff --name-only | xargs rubocop
```

`xargs`の利用が肝。
`xargs`(と '|')を使うと、`git diff --name-only`の結果を入力としてrubocopを実行できる。

ということでちょっとした派生として以下のようなことも可能。

```
# ステージングされたファイルを対象にしたい場合
$ git diff --cached --name-only | xargs rubocop

# 最新のコミットからの修正分全てを対象にしたい場合
$ git diff HEAD --name-only | xargs rubocop
```
【Mac】Numbersでプルダウンにフィルタを設定

メモ程度ですが、調べた限り情報が無かったので記載します。
**※OSやバージョンにより内容が異なる可能性があります**

Numbersにデフォルト機能として「クイックフィルタ」というものがありますが、これが非常に使いづらい。。
複数選択した後に一気に解除出来なかったり、

ということで、以下の方法で独自にプルダウン（ポップアップメニュー）にフィルターを設定しました。

#### 1. A1セルにプルダウンを設定
- 「フォーマット」→「セル」→「データフォーマット」→「ポップアップメニュー」
- 例：「All」「Filter１」「Filter２」...といった項目を作成

#### 2. B列のセルにフィルターの判定を設定
```
IF(OR(A$1="All",A$1="Filter1"),"○","")
```
- 「挿入」→「数式」→「新規数式」から設定
- A1セルが「All」または「Filter1」の時に ◯ をつけ、それ以外の時には空白にする（行に応じてFilter1の値を変更）
- **※そのままコピペするとセルを認識しないため、A$1部分は入力し直す必要あり**

#### 3. B列のクイックフィルタで ◯ を選択
- ◯ に設定以降は特にいじる必要無し

以上で設定完了です。
**※対象のセルは適宜変更してください**

仕組みとしては、以下の通りです。

1. A1セルのプルダウンを変更
2. B列のセルが ◯ or 空白になる
3. クイックフィルタによりB列が ◯ の行のみ表示

AppleScript使ったらもっとリッチなものが出来るかもしれませんが、簡単に出来る範囲ということで…
超劇的に使いやすくなる訳では無いですが、多少マシにはなったかなと…

#### まとめ
特にNumbersにこだわりがあるわけでは無いのですが、
仕事の都合上使うことになったのでこのようなものを作ってみました。

同じように困っている方がいればぜひm(_ _)m
Power BIのクエリーでデータソースを切り替える

##はじめに
Power BIで作成したダッシュボードを別のデータソースへ切り替えができると便利ですが、新規データを読み込むと新しいクエリーが作成されてしまいます。:cry:
パラメータを使い、データソースの切り替えができるクエリーを作成します。:smiling_imp:

##サンプルデータ
**Price1.csv**

|Item |Price |
|:----|-----:|
|A    |100   |
|B    |200   |
|C    |300   |

**Price2.csv**

|Item |Price |
|:----|-----:|
|A    |150   |
|B    |250   |
|C    |350   |

##サンプルデータの読み込み
ホーム>データの取得>テキスト/csvから price1.csvを読み込みます。

![Loadcsv.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/7eb09348-6258-bacf-b5d5-94f00f459b41.gif)



##方法1 ファイル名の変更による切り替え
Power Queryのデーターソース読み込みで、ファイル名を文字列パラメータに変更します。

1) ホーム>クエリーの編集でPower Queryエディターを開きます。

2) パラメータの管理>新しいパラメータで、パラメータを追加します。
 (名前:Price List File, 種類:テキスト,現在の値:price1.csvのパス)

3) 右側のクエリーの設定>適用したステップのソースを選択、クエリー文のFile.Contents()のファイル名をパラメータPrice List Fileに修正します。

|Power Query|
|:--:|
|= Csv.Document(File.Contents(#"Price List File"),[Delimiter=",", Columns=2, Encoding=932, QuoteStyle=QuoteStyle.None])|

4) データソースをprice2.csvへ変えるには、ホーム>クエリーを編集>パラメータの編集より、Price List Fileにprice2.csvのファイルパスを入力します。(変更の適用をクリックし、データを更新します。)

![SelectQuery1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/38c77930-23e2-5e83-4786-fa2a220251f2.gif)

##方法2 クエリーの条件分岐による切り替え
データソースが異なる手段（SQL ServerとCSVを切り替える等)の場合は、Power Queryのif then else文で記述して切り替える方法もあります。

1) ホーム>クエリーの編集でPower Queryエディターを開きます。

2) パラメータの管理>新しいパラメータで、パラメータを追加します。
(名前:Price List, 種類:10進数, 提案された値:値の一覧 {1: Price1 | 2: Price2}, 現在の値:price1.csvのパス)

3) 右側のクエリーの設定>適用したステップのソースを選択、クエリー文を以下のようにif then else文に修正します。
(csvファイルのフォルダ　c:\temp\としています）

|Power Query|
|:--:|
|= if #"Price List"="Price1" then Csv.Document(File.Contents("c:\temp\Price1.csv"),[Delimiter=",", Columns=2, Encoding=932, QuoteStyle=QuoteStyle.None]) else Csv.Document(File.Contents("c:\temp\Price2.csv"),[Delimiter=",", Columns=2, Encoding=932, QuoteStyle=QuoteStyle.None])|

4) データソースをprice2.csvへ変えるには、ホーム>クエリーを編集>パラメータの編集より、Price List Fileにprice2.csvのファイルパスを入力します。

![SelectQuery2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/c7b01bd2-9f7c-6878-cabf-9a925399e17d.gif)

##参考
Power Query M formula language
https://docs.microsoft.com/en-us/powerquery-m/expressions-values-and-let-expression#If
IT系用語を超ざっくり1行要約

#IT系用語を超ざっくり1行要約
##■打ち合わせなどでよく使われる用語編
###工数と人月
開発期間の見積もりに使われる
###デファクトスタンダード
多くの人に使われる
###カットオーバーとサービスイン
システムの開発終了と利用開始
###WBS
必要な作業を細かく分割する
###SLA
サービスの信頼性を示す
###SES
IT業界における働き方
###エンドユーザー
利用者のことを意識する
###トレードオフ
一方をたてればもう一方が立たず
###fix
仕様の変更を許さない
###アクセシビリティ
どんな人でも使えることを意識する
###ユーザビリティ
使いやすさを第一に考える
###しきい値
判断する基準
###リプレース
新たなシステムに置き換える
###プロトタイプ
試しにつくってみる
###HTTPとHTTPS
コンテンツを転送する
###プロキシサーバー
通信の代理人
###キャッシュ
一度使ったものは保存しておく
###アーカイブ
古いデータは大切に保管する
###レガシーマイグレーション
古いシステムを作り変える
###テキストとバイナリ
2種類に分けられるファイル形式
###gitとSubversion
バージョン管理システムの定番

##■ニュースでよくみる用語編
###機械学習
人間がルールを教えなくても自動的に学習
###ディープラーニング
第3次人工知能ブームの立役者
###AI
人間のように「賢い」動作をするコンピュータ
###RPA
事務処理などの業務を自動化する
###IoT
モノのインターネット
###ビッグデータ
記録や保管、解析が難しい巨大なデータ
###オープンデータ
誰でも自由に使えるデータ
###ブロックチェーン
取引データをまとめる技術
###仮想通貨
国家が管理しない暗号技術による通貨
###フィンテック
ITと金融の融合
###ドローン
遠隔操作ができる無人航空機
###VRとARとMR
現実と仮想世界の融合
###オフショア
拠点を海外に移す
###ロングテール
売れない商品も在庫を確保
###POS
店舗での販売数から分析する
###システムインテグレーター(SIer)
構築から運用まで一括で請け負う
##■ITパスポート、基本情報定番の用語編
###五大装置
どのコンピュータにも共通する装置や機能
###IC(集積回路)
小さな部品の組み合わせ
###デバイスとデバイスドライバ
PCの周辺機器を操作
###ストレージ
大容量が求められる記憶装置
###マウント
記憶装置を使える状態にする
###仮想マシン
ソフトウェア上でコンピュータを動かす
###仮想メモリ
ソフトウェア上で実現するメモリ管理
###カーネル
OSの中核部分
###フレームワーク
開発効率の向上に貢献
###手続き型とオブジェクト指向
ソースコードの保守性を高める
###関数型と論理型
手順よりも目的を記述する
###APIとSDK
開発に必要なライブラリを呼び出す
###キューとスタック
データを一列に格納
###モジュールとパッケージ
ライブラリを管理する
###シリアルとパラレル
データを高速にやり取りする工夫
###アダプタとコンバータ
データを変換する機器
###解像度と画素、ピクセル
写真や画像の綺麗さを決める
###VGAとHDMI
映像を出力する
###データマイニングとデータサイエンス
大量のデータから新たな知識を発見
###インターネットとイントラネット
複数のコンピュータや組織をつなぐ
###WANとLAN
ネットワークの範囲を表す
###ルータとスイッチ
ネットワークの経路を決める
###TCPとUDP
通信に求められる信頼性と速度を表現
###パケットとフレーム
通信の基本単位
###ドメインとセグメント
ネットワークの領域を識別する
###絶対パスと相対パス
ファイルの場所を示す
###可逆圧縮と非可逆圧縮
ファイルの容量を減らす
###文字コードと機種依存文字
環境によって文字が異なる
###著作権とクリエイティブ・コモンズ
盗作を防ぐ
###OSとアプリケーション
ソフトウェアの役割が違う
###正規化と主キー
扱いやすいようにテーブルを分割
###デッドロックと排他制御
同時更新を避ける
###リファクタリング
動作を変えずにソースコードを洗練
###カバレッジとモンキーテスト
網羅性を確認する
###リレーショナルデータベースとSQL
複数の票を紐づけで管理
Rails i18n 定数Hash値の対応

### はじめに

定数ファイルでConst値として管理しているHash値をHelperで使用するために方法の備忘録です。

### 最初の状態

まず定数ファイル

```ruby:constants.rb
module Constants
  # 性別を定義した定数ハッシュ
  SEX_HASH = { "male" => 0, "female" => 1 }
end
```

Viewに性別選択用のセレクトボッックスの値を渡すHelperのmethod

```ruby:account_helper.rb
module AccountHelper
  def select_sex
    [[I18n.t("dictionary.sex.male"), 0], [I18n.t("dictionary.sex.female"), 1]]
  end
end
```

そして言語ファイル

```yml:ja.yml
ja:
  dictionary:
    sex:
      male: "男性"
      female: "女性"
```

```yml:en.yml
en:
  dictionary:
    sex:
      male: "男性"
      female: "女性"
```

定数で設定しているハッシュとそれを参照していない同一意味を参照しているHelperのハッシュが存在する。

### 変更

まず、constants.rbを以下のように修正しました

```ruby:constants.rb
module Constants
  # 性別を定義した定数ハッシュ
  SEX_HASH = {   "dictionary.sex.male" => 0 \
               , "dictionary.sex.female" => 1 \
             }
end
```

Helperで呼び出す際に上記ハッシュを呼び出し、詰め直すように修正しました。

```ruby:account_helper.rb
module AccountHelper
  def select_sex
    sex_hash = Hash.new
    Constants::SEX_HASH.each do |key, value|
      name = I18n.t(key)
      sex_hash[name] = value
    end
    return sex_hash
  end
end
```

ハッシュの内容(key)が動的に変わるため、定数定義で定義ができませんでした。
なので、newしたHashに対してハッシュの内容を変更させてviewに渡すことで対応できました。
JavaScriptで数字の頭に0を加えて桁揃えする

練習でタイマーを作るために、
0:0:0となる数字表記を00:00.000と数字の桁を揃えたかったのですが、
ググってもなかなかヒットしなかったので、簡単に記録します。



##1.使用するメソッド
`String(xx).padStart(2, '0')`
そうです。padStart関数です。


##2.使用例（カウントアップのための関数）

```js
	function countUp() {
		const d = new Date(Date.now() - startTime + elapsedTime);
		const m = d.getMinutes(); // 分
		const s = d.getSeconds(); // 秒
		const ms = d.getMilliseconds(); // ミリ秒

		// タイマーの表示方法を指定 ★★★ここです★★★
		timer.textContent = `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}.${String(ms).padStart(3, '0')}`;

		// 再帰的な処理
		timeoutId = setTimeout(() => {
			countUp();
		}, 10);

	}
```
railsのローカルインストールを省力化

# 概要
Railsのバージョンを複数入れると付随するgemのバージョンも複数となり気持ち悪い
対処方法を調べていたところ、[こちらのサイト](https://qiita.com/emadurandal/items/a60886152a4c99ce1017)がとても参考になりました。
その中で繰り返しが面倒だと思った手順についてshell化したのでそのシェアになります。
（「RailsのローカルインストールとRailsプロジェクトの作成」の段）

# 前提
OS:Mac(Mojave)
Ruby環境:anyenv x rbenv

# 使い方
下記のshellをコピペして

```
./rails-new-blank.sh [railsのバージョン] [rails project名]

ex)
./rails-new-blank.sh 5.1.6 hello_app
```

# shell本体
zsh準拠なので１行目は環境に合わせて書き換えてください

```shell:rails-new-blank.sh
#!/usr/local/bin/zsh

# 引数
# 1:rails version, 2:rails project name

# railsのみgemインストールするためのGemfileを作成
cat << EOS > Gemfile
source "http://rubygems.org"
gem "rails", "$1"
EOS

# railsをローカルにインストール
bundle install --path vendor/bundle

# rails projectを作成（bundle installはしない）
bundle exec rails new $2 --skip-bundle

# 片付け
# これでローカルにインストールしたrailsは削除
rm -f Gemfile Gemfile.lock
rm -rf .bundle vendor

# Gitの対象からローカルにインストールしたgemファイルを除外
cat << EOS >> $2/.gitignore

/vendor/bundle
EOS
```

# 参考
[Rails開発環境の構築（rbenvでRuby導入からBundler、Rails導入まで）（Macport編）](https://qiita.com/emadurandal/items/a60886152a4c99ce1017)
いまさら人に聞けないMVVMの概要

# はじめに
Androidのアプリにおいて、これまではフレームワークを利用できていればよいといった感じでしたが、時代の流れやAndroidのライブラリの拡充によりアーキテクチャを考える機会が増えてきました。
世間では、様々なアーキテクチャが提唱されています。例えば、MVP、MVI、MVVM、クリーンアーキテクチャなどなど、人それぞれの設計で、アプリ開発を開発していくことになると思います。
しかし、増えすぎてしまい、どれを選んだらいいのかわからないということもあります。
今回は、今の所、優勢なMVVMの概要について簡単に説明します。


# レガシーなアプリ開発とMVVMの違い
MVVM設計を単純に説明するのであれば、書籍などを読めば問題ありません。しかし、書籍では、MVVMの設計概念はわかるのですが、 **何が嬉しいのか（メリット）** が分かりづらいです。
このメリットが理解できれば、MVVMの概要を理解する近道になります。

まずは言葉の整理をしておきます。
MVVMは、「Model + View + ViewModel」を組み合わせた言葉です。
それぞれに役割が明確化されています。
それぞれの役割をまとめてみました。

|用語|役割|
|---|---|
|Model(M)|ドメイン領域を担います。ドメイン領域と言われると始めて聞いた方からすると意味不明です。<br>要はビジネスロジックやデータを格納するクラス（データクラスやエンティティ）、DAOなどの処理を担当する部分です。MVCで言うところののModelです。|
|View(V)|ズバリ、見た目です。Androidであれば、レイアウトリソースファイルやそれをinflateしたものを考えておけばいいでしょう。XMLファイルで見た目を定義することが多いと考えられます。最近ではDSLで！ってこともあると思います。|
|ViewModel(VM)|一言で表すとビューの管理とイベント処理です。<br>主な作業は、以下の通りです。<br>・Viewに表示するデータの管理<br>・各種Viewのイベント処理<br>・データの取得やビジネスロジックの呼び出し|

用語と役割がわかったところで、レガシーなアプリとMVVMによる設計を図で確認してみましょう。

![MVVMのやりたいこと.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99960/53adb8b8-9e50-8324-a668-1078f274667c.png)


図からも理解できるように、レガシーなアプリはすべてActivityに処理を記述していたため、Activityが巨大化する傾向にありました。
しかし、MVVMにすることにより、それぞれの処理を役割ごとに分割し、クラスを疎結合に保ちます。

# ViewModelとActivityの比率
MVVMの概要が理解できると、次はこんなことに気がつくと思います。
このまま行けば、いずれViewModelが巨大化してしまうんでは無いだろうか？？と考えてしまいます。
上図を見るとなんとなく、ActivityとViewModelは1:1のようなイメージを抱きますが、そんなルールはありません。
必要に応じて、Activityに応じてViewModelを増やして問題ありません。
これらを図にまとめてみました。

![比率の問題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99960/7818f7a4-0058-ccb1-88f9-204071c6b452.png)


ViewModelを増やすと再利用の可能性が出てきたり、ViewModelは巨大化せずにすみます。しかし、数が増えればメンテナンスにコストがかかることも忘れないでおいてください。

# まとめ
MVVMは処理を明確にクラス分けすることにより、メンテナンス性を向上させる事ができます。
また、Activityの巨大化を食い止める事ができると考えてください。
Oracle接続を図解する＜概要＞

#Oracle接続の仕組み（概要）
クライアントからOracleに接続する時には、「リスナー」というプロセスが仲立ちをしてくれています。
最初にクライアントからは「リスナー」に接続して、接続したい「サービス」の名前を伝えると、その「サービス」の看板を出しているOracleインスタンスに接続してもらえる、という仕組みになっています。
さらに、「リスナー」に「サービス」の情報を予め教えておく役目を果たすプロセスもいます。

「クライアント」と「データベース(インスタンス)」だけじゃないところが、ちょっとややこしい。
どんな登場人物がいて何の役割を果たしていて、どんな設定をすればいいのか。
という概略を絵として頭の中に描けていると、個人的には作業イメージがつかみやすくなります。

そこで、自分の備忘録として、
クライアントからOracleデータベースに接続するまでの流れと、登場人物をお絵描きしてみました。


##Oracle接続の流れと、接続に関わるコンポーネント
![listener_abstract.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468682/6709621a-1dce-93a1-6325-2860b7369157.png)



この図に登場する登場人物とおおまかな役割は以下の通りです。
###クライアント

 * リスナーに対して接続要求を行い、接続したいOracleインスタンスに接続を転送してもらいます
 * 接続情報として、リスナーの「ホスト」「ポート番号」「プロトコル」と、接続先データベースの「サービス名」を指定する
 * 郵便の世界に例えると、「手紙を届けたい人」、「差出人」。

###リスナー

 * クライアントからの接続要求を受信し、DBサーバにルーティングしてくれるプロセス
 * 「どのOracleインスタンスがどのサービスを提供しているか」を知っています
 * クライアントから指定された「サービス名」のサービスを提供するインスタンスに対して、接続を転送してくれます
 * 構成情報(※)は、listener.ora ファイルに格納されています
 * 郵便の世界に例えると、「郵便配達人」
 
　(※)リスニング用プロトコル・アドレス、サービスの情報、実行時の動作を制御するパラメータ　など

###サービス

 * クライアントがOracleインスタンス（データベース）に接続するときに指定する名前
 * シングル構成なら、インスタンス名（SID）と同じ名前になっていることが多い
 * サービス名は初期化パラメータ service_names で宣言されていて、複数定義可能。
 * 郵便の世界に例えると、「インスタンス(データベース)」は本当の宛先であり、おうち。
 * 「サービス名」は、「インスタンス（≒おうち）」に対して「名札、表札」を立てるようなもの。
 * 1つの「インスタンス（おうち）」に対して、1つ以上の「名札、表札」を立ててOK

※リスナー（郵便配達人）と、サービス（名札）が定義されているだけだと、まだ、クライアント接続はデータベースにつなげてもらうことができません。
※リスナー（郵便配達人）が、クライアント（差出人）の要求通りデータベースにリクエストを転送できるのは、「どのサービス（名札）をどのOracleインスタンス（おうち）が提供しているか」の情報が登録されているからです。

###動的サービス登録

 * 「どのOracleインスタンスがどのサービスを提供しているか」の情報を、リスナーに自動登録する機能
 * 言い換えると、どの「おうち（←インスタンス）」に、何という名前の「名札（←サービス名）」がかかっているかの情報を、動的にリスナーに登録する仕組み。この仕組みによって、リスナー（郵便配達人）がクライアント接続をどこに送れば調べるためのいわゆる「住所録」ができます。
 * デフォルトでは、60秒間隔でLREGという名前のプロセスが動いて、サービス名が追加されていたらリスナーに教えてあげています(急ぐときは、alter system register; コマンドを実行します)

（補足）
   ・ 動的サービス登録された情報はファイルには書かれません。lsnrctl statusコマンド等で確認できます
   ・ listener.ora ファイルにサービスの情報（≒住所録の情報）を直書きすることもできる（いわゆる「静的な登録」）

　「動的サービス登録」の仕組みについてメモを起こしました ---->   [Oracle接続＜動的サービス登録＞](https://qiita.com/mi-kana/items/862305b7f5fdee8d080d)
　「静的な登録」の仕組みについてメモを起こしました ---->   [Oracle接続＜静的なサービス登録＞](https://qiita.com/mi-kana/items/6b1a39736df30ab21e35)

###接続方法（構文）
クライアントから接続要求を行うにあたり、宛先を指定してCONNECT文を書く必要があります。
「宛先」の書き方には、以下のバリエーションがあります。

　　 1. 簡易接続
　　 2. ローカル・ネーミング（tnsnames.ora に接続情報を記述する）
　　 3. ディレクトリ・ネーミング（LDAP）
　　 4. 外部ネーミング
　 
3. 4. を用いるケースは多くなく、1.と2.のお作法を知っていればだいたい困りません。
1. 2. の接続のために必要な設定は、[「Oracle接続＜接続情報の書き方＞」](https://qiita.com/mi-kana/items/0f79cafed1761a4531b1)で書きます。
Cognos Analytics ダッシュボード定義のクリップボードへのコピー

#Cognos Analytics ダッシュボード定義のクリップボードへのコピー
Cognos Analyticsのレポートでは、以下の記事の手順でレポートの定義(Spec)をXML形式で出力して、別の環境にコピーできることはご存じだと思いますが、ダッシュボードの場合の手順を共有しておきます。
**Cognos Analyticsでの「クリップボードにレポートをコピー」**
https://qiita.com/shinyama/items/b10a036acac4a2ea2ec7

Cognos Analytics 11.1.1以上で可能なようです。

#手順
まず普通にダッシュボードを開きます。
<img width="960" alt="001.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/2f43390d-1410-e615-b8dd-5f1caaee7fde.png">

Ctrl + q + / キーでできるらしいのですが、私の環境では、Ctrl + q キーを押した時点でこうなるので、
<img width="960" alt="002.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/d582543d-7063-3f1e-1bfa-ce0f088b826f.png">

もう一回、ダッシュボードのキャンバス上をクリックして戻ります。※この操作は一回必要
<img width="960" alt="001.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/5ac7b6f4-a770-e02c-dab1-cc97cf87c5c7.png">

次に、Ctrl + / キーを押します。
するとこの様にダッシュボード定義が表示されるので、「コピー」。
必要に応じてメモ帳等に貼り付け、別の環境にアクセスします。
<img width="960" alt="003.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/5f100efa-f5fa-c429-9f6d-9e5548104285.png">

別環境で、新規にダッシュボードを開き、同様に一回 Ctrl + q して戻ります。
<img width="960" alt="004.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/fd028844-55e3-9281-6479-a05c219fdd15.png">

Ctrl + / で開き、ダッシュボード定義をすべて先ほどメモ帳に貼り付けた定義で上書きして(メモ帳からCtrl + cでコピーし、Ctrl + vで貼り付け)、「更新」。
※元々の定義が残らないように完全に上書きが必要
<img width="960" alt="005.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/d405a610-af22-724e-8106-c300301cfd94.png">

この様にダッシュボードが復元されます。
<img width="960" alt="006.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/faf3f55a-1dd0-c5f6-89ca-c16ec649c560.png">

ご活用下さい。
パーセプトロンの要点まとめ

#最初に
以下は、ゼロから作るDeeplearning（オライリー）の学習メモです。ソースコードは、この本からほぼ写したものです。

#パーセプトロンとは
　パーセプトロンは複数の信号を受け取って、一つの信号を出力するもの。この信号は、「流す・流さない（１か０）」である。ニューロンでは、送られてきた信号の総和が計算され、その総和が限界値を超えると１を出力する。
　つまり、パーセプトロンは、入力信号に重みが乗算された値とバイアスの和が計算され、その値によって出力値が０か１か決まる。

#ANDゲート
　２つの信号が１の時だけ１を出力し、それ以外は０を出力する。ちなみに以下のような表を真理値表と呼ぶ。

| x1 | x2 | y |
|:-------------:|:------------:|:------------:|
| 0      | 0      | 0      |
| 1      | 0      | 0      |
| 0      | 1      | 0      |
| 1      | 1      | 1      |

Pythonによる実装例

```python
>>> import numpy as np
>>> def AND(x1,x2):
        x = np.array([x1,x2])
        w = np.array([0.5,0.5])
        b = -0.7
        tmp = np.sum(w*x) + b
        if tmp <= 0:
            return 0
        else:
            return 1
>>> AND(0.0)
0
>>> AND(1.0)
0
>>> AND(0.1)
0
>>> AND(1.1)
1
```

# NANDゲート
 NANDゲートの出力は、ANDゲートの出力を逆にしたものになる。２つの信号の両方が１の時だけ０を出力し、それいがいは１を出力する。

| x1 | x2 | y |
|:-------------:|:------------:|:------------:|
| 0      | 0      | 1      |
| 1      | 0      | 1      |
| 0      | 1      | 1      |
| 1      | 1      | 0      |

Pythonによる実装例

```python
>>> import numpy as np
>>> def NAND(x1,x2):
        x = np.array([x1,x2])
        w = np.array([-0.5,-0.5])
        b = 0.7
        tmp = np.sum(w*x) + b
        if tmp <= 0:
            return 0
        else:
            return 1
>>> NAND(0.0)
1
>>> NAND(1.0)
1
>>> NAND(0.1)
1
>>> NAND(1.1)
0
```

# ORゲート
　ORゲートは入力信号の少なくともひとつが１であれば、出力が１になる。

| x1 | x2 | y |
|:-------------:|:------------:|:------------:|
| 0      | 0      | 0      |
| 1      | 0      | 1      |
| 0      | 1      | 1      |
| 1      | 1      | 1      |

Pythonによる実装例

```python
>>> import numpy as np
>>> def OR(x1,x2):
        x = np.array([x1,x2])
        w = np.array([0.5,0.5]) # ANDと違うのは重みとバイアスだけ
        b = -0.2
        tmp = np.sum(w*x) + b
        if tmp <= 0:
            return 0
        else:
            return 1
>>> OR(0.0)
0
>>> OR(1.0)
1
>>> OR(0.1)
1
>>> OR(1.1)
1
```

#XORゲート
　入力値のどちらかが１の時だけ出力が１となる。多層パーセプトロンであり、AND, NAND, ORゲートの組み合わせで表現できる。

| x1 | x2 | y |
|:-------------:|:------------:|:------------:|
| 0      | 0      | 0      |
| 1      | 0      | 1      |
| 0      | 1      | 1      |
| 1      | 1      | 0      |

Pythonによる実装例

```python
def XOR(x1,x2):
    s1 = NAND(x1,x2)
    s2 = OR(x1,x2)
    y = AND(s1,s2)
    return(y)
>>> XOR(0.0)
0
>>> XOR(1.0)
1
>>> XOR(0.1)
1
>>> XOR(1.1)
0
```

#終わりに
・パーセプトロンは入出力のアルゴリズムである。
・重みとバイアスを設定する。
・XORゲートは、AND, NAND, ORゲートの組み合わせで表現できる。
・多層のパーセプトロンは、理論上コンピューターを表現できる。
codicがコーディング時の命名（ネーミング）に便利な件

プログラミングしている際に、
クラス名の命名や変数名の命名などネーミングに些細なことで悩むことありませんか？

些細な事ではありますが、直感的かつ要約された命名は可読性が上がるので大切ですよね。
プログラミングは書く時間よりも読まれる時間の方が圧倒的に多いので可読性の高いコードの寿命は伸びます。

それに、出来る人のコードって命名がカッコイイかつシンプルですよね！

ネイティブだとこう使うけど日本人だからこそ馴染みのある単語はこっちかな？
とか色々考えていると命名一つとっても奥が深いものです。

google翻訳で都度変換してもいいのですが
そんな時に便利なのがこちらの**codic**です。

https://codic.jp/engine

<img width="1379" alt="スクリーンショット 2019-08-14 10.38.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/f214d6a9-e509-6be7-2098-cbbb8d4bcf69.png">

- 軽い
- エディタとの連携しているものも多い
- 辞書の翻訳の質はgoogle翻訳と遜色ない（内部的にはgoogle翻訳なのかな…？）

などがおすすめポイントです。

Visual StudioやAtomなどでもプラグインがあるので連携可能です。
Azure Databricksでdbutils.fs.ls.help()の実行エラー時の対応方法【備忘録】

## 概要
 Azure Databricksにて、dbutils.fs.lsのヘルプを表示する方法を記載します。

## エラー時のコード 
```python
%python
dbutils.fs.ls.help()
```
## エラーメッセージ
```text
AttributeError: 'function' object has no attribute 'help'
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<command-3260864872878574> in <module>()
      1 
----> 2 dbutils.fs.ls.help()
AttributeError: 'function' object has no attribute 'help'
```
## 正常時のコード 
```python
%python
dbutils.fs.help("ls")
```
## 正常メッセージ
```text
/**
* Lists the contents of a directory.
* 
* Example: display(ls("/mnt/my-folder/"))
* 
* The FileInfo object that is returned has the following helper methods:
* val files = ls("/mnt/my-folder/")
* files.map(_.name) // [myFile, myDir/]
* files.map(_.length) // [1286, 0]
* files.map(_.path) // [/mnt/my-folder/myFile, /mnt/my-folder/myDir/]
* files.map(_.isDir) // [false, true]
* files.map(_.isFile) // [true, false]
* 
* @param dir FileSystem URI
* @return Ordered sequence of FileInfos containing the name and size of each file.
*/
ls(dir: java.lang.String): scala.collection.Seq
```

##参考リンク
- Azure Databricksのリンク
https://docs.azuredatabricks.net/user-guide/dev-tools/dbutils.html
- Databricksのリンク
https://docs.databricks.com/user-guide/dev-tools/dbutils.html
Azure DatabricksでDBFS内にあるマークダウンファイルの内容を出力する方法【備忘録】

  
    
    

## 概要
 DBFS内にあるマークダウンファイルの内容を表示する手順を記載します。
Databricksのドキュメントに記載されている手順を実施するだけです。
## コード 
```python
%python
with open("/dbfs/databricks-datasets/README.md") as f:
    x = ''.join(f.readlines())
print(x)
```
## 実行結果
```text
Databricks Hosted Datasets
==========================
The data contained within this directory is hosted for users to build 
data pipelines using Apache Spark and Databricks.
License
-------
Unless otherwise noted (e.g. within the README for a given data set), the data 
is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0),
which can be viewed at the following url:
[http://creativecommons.org/licenses/by/4.0/legalcode](http://creativecommons.org/licenses/by/4.0/legalcode)
Contributions and Requests
--------------------------
To request or contribute new datasets to this repository, please send an email
to: hosted-datasets@databricks.com.
When making the request, include the README.md file you want to publish. Make
sure the file includes information about the source of the data, the license, 
and how to get additional information. Please ensure the license for this 
data allows it to be hosted by Databricks and consumed by the public.
```
##参考リンク
- Azure Databricksのリンク
https://docs.azuredatabricks.net/getting-started/databricks-datasets.html#databricks-datasets
- Databricksのリンク
https://docs.databricks.com/getting-started/databricks-datasets.html#databricks-datasets
webpack 実行で Module not found: Error: Can't resolve 'fs' というエラー

## 概要
まずはこのエラーを見て欲しい

`Module not found: Error: Can't resolve 'fs'`

`'fs'` の部分は実に様々な内容に変わる

今日はこのエラーと向き合う

## 前提
node.js とかでフロントエンドとかバックエンドとか書いてて
トランスパイラ(babelとか)とモジュールバンドラ(webpackとか)の組み合わせで
開発する機会ってあると思うんだけど、
こいつらが何をしてるか？何が目的か？メリットは？デメリットは？って理解してないと
エラーが出た時焦るよな

ほんで今回はこのエラー、ぱっと見はすごく厄介そう

エラーを理解してないと間違った対処して、
babelやwebpackの恩恵を受けられていないことに気付けなくなる

## この対処法は違う（と思うんだ）
### fs: "empty" は間違い

この対応は臭いものに蓋をしているだけ
目を瞑ってる
根本的に何も解決できていないと思うんだ
もうちょっというと、自分で不具合の種を仕込んでる

私はこのコードがどう動いているかは理解できない

```webpack.config.js
node: {
    fs: "empty"
}
```

さらに、Angularとかだとwebpackとか意識せずに勝手にやってくれてる！みたいなイメージの人も多いと思う
`webpack.config.js` がないケースとかね

だからといって、
力技で`package.json` とかに書いちゃうのも違う気がする
だって、このコード違和感ない？

```package.json
"browser": {
    "fs": false
}
```

### target: 'node' は理解していないと危ない
ちゃんとしたドキュメントに書いてある対処法
https://jlongster.com/Backend-Apps-with-Webpack--Part-I

```webpack.config.js
var path = require('path');

module.exports = {
  entry: './src/main.js',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'backend.js'
  }
}
```

でも、`target: 'node'`って書くからにはなぜ、`target: 'node'`と書くと動くのか？を理解しておいてもらいたい

バックエンドならいいと思う
だって、node.jsで書いてるんだよな？
だから、`target: 'node'` は正しい

なぜこう書くか？を理解できているならこれでいいと思う

## こうじゃないか？

ここが重要
`externals: nodeModules`

これなら、`fs: "empty"` なんていう危険なコード仕込まなくたっていい
`target: 'node'` なんて決めつけなくていい

```webpack.config.js
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');

var nodeModules = {};
fs.readdirSync('node_modules')
  .filter(function(x) {
    return ['.bin'].indexOf(x) === -1;
  })
  .forEach(function(mod) {
    nodeModules[mod] = 'commonjs ' + mod;
  });

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'backend.js'
  },
  externals: nodeModules
}
```
iOSはChromeもSafariも同じレンダリングとかいう訳ワカメな件

Google ChromeのレンダリングエンジンはBlinkだと思っていたのだけど、iOS版Chromeについては、Safariと同じくWebkitらしい。どういうことか簡単にまとめてみた。

# 採用ブラウザとレンダリングエンジンの種類

|ブラウザ|レンダリングエンジン|
|-----------------|------------------|
|Chromium系（Google chrome, Operaとか）|Blink|
|Safari|Webkit|
|現世代Microsoft Edge|EdgeHTML|
|次世代Microsoft Edge|Chromiumをベースとして作成するので多分Blink使用|
|Firefox|Gecko使用、そして一部Servo使用|

参考： [Webブラウザ、レンダリングエンジン、JavaScriptエンジンを整理して図視化してみた](https://qiita.com/umashiba/items/8cb47825624c5cb043d6)

# iOSのみ例外ルールがある

iOSの制約で、iOSのレンダリングエンジンは常にwebkit（Apple開発）を使わなくてはいけない。サードパーティーのブラウザもwebkitを利用しなければならない。サードパーティーのブラウザは、webview機能を実装することでブラウザアプリとして存在している。

> 他のパソコン/スマートフォン向けには、Google Chromeでは「Blink」、Microsoft Edgeでは「EdgeHTML」（Blinkへ移行することが発表済みです）、Firefoxでは「Gecko」と、WEBブラウザ独自のレンダリングエンジンが利用されています。しかし、ChromeもEdgeもFirefoxも、あらゆるサードパーティー製WEBブラウザのiOS版はSafariと同じ「WebKit」なのです。
> 
> 参考： [iPhoneではあらゆるWEBブラウザのエンジンがSafariと同じ? - いまさら聞けないiPhoneのなぜ](https://news.mynavi.jp/article/20190331-iphone_why/)

# ちなみに

WebRTCはWebviewには対応してくれてないので、iOS Safariでは動くけどChromeでは動かないよ（もともとこの理由を調べていたところ、レンダリングエンジンの問題に行き着いたのでした）
【Kubernetes】初期構築時以降にNodeをクラスタにjoinさせる方法

Kubernetesの環境構築をした際に、途中からNodeを追加でjoinしたいと思ったときに躓いたので対処方法をメモします。

# 初期構築時にjoinさせる方法
Kubernetesを使うための事前設定をした後に、Masterで以下コマンドを実行するとランダムな文字列が記載されたjoin用のコマンドが出力される。そのコマンドをNodeで実行することで、当該Master配下のクラスタにjoinさせることができる。


```markdown:Masterで実行
# kubeadm init --apiserver-advertise-address=X.X.X.X - -pod-network-cidr=Y.Y.Y.Y/Z
～～～(略)～～～
Then you can join any number of worker nodes by running the following on each as root:

kubeadm join X.X.X.X:6443 --token <生成されたランダム文字列> \
    --discovery-token-ca-cert-hash <生成されたランダム文字列> 
```
ただし、上記コマンドには有効期限(?)があるらしく、数日後に同じコマンドを実行したらjoinされなかった。

# 初期構築時以降にjoinさせる方法
おそらくtoken(ランダム文字列)に有効期限が設定されているためと思われるので、以下コマンドでtokenごと新たにjoinコマンドを生成すればよい。

```markdown:Masterで実行
# kubeadm token generate
<ランダム文字列が出力される>
# kubeadm token create <上記で出力されたランダム文字列> --print-join-command --ttl=0
kubeadm join X.X.X.X:6443 --token <上記で出力されたランダム文字列>     --discovery-token-ca-cert-hash <ランダム文字列>
```

初期構築時に出力されるjoinコマンドのメモをなくしたりしたときにも、この方法で新たにjoinコマンドを発行できます。
IntelliJに複数のMavenプロジェクトを一気にインポートする

(1) IntelliJ起動画面で[Import Project]を選択

> 既存プロジェクトに追加する場合は
> 1. [File]-[Project Structure]
> 2. 画面左側の[Project Settings]から[Modules]を選択
> 3. [+]をクリック→[Import Module]を選択

(2) 適当なフォルダを選択
(3) [Import project from external model]を選択->[Maven]を選択->[Next]をクリック
<img width="467" alt="スクリーンショット 2019-08-14 9.56.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/4850fbc5-b54e-2bf0-f9cc-9544052e1902.png">
(4) [Search fro projects recursively]にチェックを入れて、[Next]をクリック
<img width="957" alt="スクリーンショット 2019-08-14 09.59.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/c92764f7-f8bb-2bb1-d1cb-c1f11690a263.png">
(5) インポートしたいプロジェクトが全て選択されていることを確認してから、[Next]をクリック
<img width="957" alt="スクリーンショット 2019-08-14 10.01.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/d81348a6-cf3b-e48b-e388-adaf4d4ad11a.png">
(6) そのまま[Finish]をクリック
ディープラーニングモデル構築のときに考えること

　先日、非常に分かりやすいディープラーニングの講義を聴く機会があり、モデル構築についていろいろと腑に落ちたので忘れないうちにメモしておこうと思いました。
　あくまでぼくの理解なので間違ってたら教えてください。

#活性化関数の特徴と選び方
　選び方も何もそもそも選択肢なんてなかった。
##中間層に使う人
　戦闘力が際限なく伸びていくので特徴量にガンガン差をつけていきたい中間層に向いています。というか一択でした。
###ReLU
　0より下の値を全部0にします。数学的に書くと`max｛0,x｝`、Excelの関数的に書くと`IF(A1<0,0,A1)`です。畳み込みの計算自体は小学生でもやれるような単純なアルゴリズム(詳しくは[Brandonさん](https://postd.cc/how-do-convolutional-neural-networks-work/)の以下略)なのですが、結合の途中で負の数字が計算に含まれるとマイナス×マイナスで符号が反転したり、分母に0が表れて数値が無限の彼方へさあ行くぞ！したりすることがあるのでそれを防ぐのにも役立ちます。
##中間層には(ほぼ)使えない人たち
　出力値がシーリングされたりその他の理由だったりで中間層には基本的に向きません。
###Tanh
　出力が-1～1の間になる関数です。上述の理由(マイナスが出てくる)で中間層には向きません。
###シグモイド
　出力が0～1の間になる関数です。ただし、総和は1になりません。昔は主役だったけど0～1の値にしてしまうということはつまり層が増えるほど細かい差が表現しきれなくなるということなのでディープラーニングの登場と同時にReLUに取って代わられた。
　とはいえ0～1にするということは処理が軽くなるということなので、DL以外の学習モデルでは出番があるかもしれない。
###ステップ
　出力が階段状になる関数です。単層ネットワーク問題で使います。**バックプロパゲーションできない**という致命的すぎる弱点があるのでディープラーニングでは使いませんていうか**使えません**。
##中間層には使えないが出力層に使う人たち
　回帰問題か分類問題かで選択します。
###恒等関数
　入力値をそのまま出力します。回帰問題で使います。
###ソフトマックス
　出力が0～1の間になり、かつ**総和が1になる**関数です。分類問題で威力を発揮し、ゆえに出力層の活性化関数として使われます。
##つまり
　中間層ではReLU、出力層ではソフトマックスを使う。回帰問題の時の出力層は恒等関数。ただ、DLで回帰分析…？という感じはある。

#ディープラーニングモデルの層の数
　決め方には**特にルールはありません。**アートです。フィーリングと試行錯誤で決めます。多ければ良いってものでもないですが、4層以上じゃない場合はディープラーニングとは呼びません。

#出力ノードの数の選び方
　**特にルールはありません。**アートです。2のn乗で表されることが多いですが別に2のn乗である必要すらありません。

#ディープラーニングモデル構築のときに考えることができる部分
　層の数と出力ノードの数をいい感じに調整すること。

#ディープラーニングに納得いかない気分になる理由
　主に↑のせいだと思う。ブラックボックス云々ていうよりも。

#結論
　ディープラーニングはアート。
モデルによらないあいまい検索をrailsで実装

# 概要
- Userモデルのnameカラムで検索したい
- Userモデルのemailカラムで検索したい
- Bookモデルのtitleカラムで検索したい

といったように、同じモデルの異なるカラムや、そもそも異なるモデルのカラムに対して、名称検索をかけたくなることはよくあると思います。
そこで使える手法を整理します。

# 動作環境
`Rails 4.2.11.1`
`ruby 2.4.5p335 (2018-10-18 revision 65137) [x86_64-darwin16]`

# 愚直に実装する
必要な場所で、必要な数だけ `scope` を生やします。

```user.rb
class User < ActiveRecord::Base
  scope :name_like, -> (value) {
    pattern = ActiveRecord::Base.send(:sanitize_sql_like, value)
    where('name LIKE ?', "%#{pattern}%")
  }

  scope :email_like, -> (value) {
    pattern = ActiveRecord::Base.send(:sanitize_sql_like, value)
    where('email LIKE ?', "%#{pattern}%")
  }
end
```

```book.rb
class Book < ActiveRecord::Base
 scope :title_like, -> (value) {
   pattern = ActiveRecord::Base.send(:sanitize_sql_like, value)
   where('title LIKE ?', "%#{pattern}%")
end
```

# module化する
例えば上の実装では `value` が nil や空文字の場合に検索結果がなくなってしまいますが、
そのような場合には何もフィルタリングしない、という仕様変更があったとします。

愚直な実装では、あいまい検索を行いたいモデルの全てで検索ロジックを実装していますから、
検索方法に変更が必要になってしまったことを想像すると・・・気が引けますね。

そこで、検索ロジック部分を `module` として切り離します。

```fuzzy_match_searchable.rb
module FuzzyMatchSearchable
  extend ActiveSupport::Concern

  class_methods do
    def fuzzy_match(column, value)
      return current_scope if value.blank?

      pattern = ActiveRecord::Base.send(:sanitize_sql_like, value)
      where(%("#{table_name}"."#{column}" LIKE ?), "%#{pattern}%")
    end
  end
end
```

各モデルでは、以下のように実装します。

```user.rb
class User < ActiveRecord::Base
  include FuzzyMatchSearchable
  
  scope :name_like, (value) -> { fuzzy_match('name', value) }
  scope :email_like, (value) -> { fuzzy_match('email', value) }
end
```

```book.rb
class Book < ActiveRecord::Base
  include FuzzyMatchSearchable
  
  scope :title_like, (value) -> { fuzzy_match('title', value) }
end
```

コードクローンを回避でき、とってもいい感じですね。

# 参考記事
[Rails] ActiveSupport::Concern の存在理由：https://qiita.com/castaneai/items/6dc121ce6ff100614f42
`sanitize_sql_like` について：https://apidock.com/rails/v4.2.1/ActiveRecord/Sanitization/ClassMethods/sanitize_sql_like
第１３回　Raspberry Pi で監視カメラを作ろう！　～サーボモータ制御編～

Raspberry Piと専用のカメラモジュールを使用し、ONVIF対応の監視カメラを作成する[シリーズ記事](https://qiita.com/lis-hanzomon/items/cc1f7f316fbeb9579b28)です。
本記事は[リンク情報システム株式会社](https://www.lis.co.jp/)の有志が作成しています。

---

カメラの首振り機能用にサーボモータを付けたので、サーボモータを制御して前後左右にカメラを動かします。

#サーボモータ制御 (I2C)
###サーボモータ制御
今回使用するPWMコントローラを搭載するボードはAdafruit社が発売しており、同社より、Adafruit_PWMServoDriver.cppと言うドライバのソースが公開されています。
参考元：[Adafruit-PWM-Servo-Driver-Library/Adafruit_PWMServoDriver.cpp at master · adafruit/Adafruit-PWM-Servo-Driver-Library · GitHub](https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/blob/master/Adafruit_PWMServoDriver.cpp)

このソースは、arduinoを対象として作成されておりますが、シンプルなC言語なので、大半の処理は流用する事が可能です。

サーボモータ制御処理の流れは以下のようになります。
　1.初期化
　2.サーボ移動

ポイントとなる実際の処理を抜粋して解説します。

#####1.初期化
RaspberryPiでI2C通信を行う場合、"/dev/i2c-1" をオープンし、スレーブアドレスの設定を行います。

```c++
i2c = open("/dev/i2c-1", O_RDWR);
ioctl(i2c, I2C_SLAVE, 0x40);
```

これで、PCA9685と通信できるようになりましたので、リセットしてから、サーボを動作させます。

```c++
// PCA9685をリセット
write8(PCA9685_MODE1, 0x0);

// サーボ制御パルス周波数設定
setPWMFreq(60);

// 中心に移動する
setPWM(1, 0, CalcPulseWidth(90));
setPWM(0, 0, CalcPulseWidth(90));
```

#####2.サーボ移動
角度を指定してサーボを移動させます。

```c++
// 1 = 左右用のサーボを移動
setPWM(1, 0, CalcPulseWidth([角度]));

// 0 = 上下用のサーボを移動
setPWM(0, 0, CalcPulseWidth([角度]));
``` 

角度は、90度が中央、45度 ～ 135度を指定して左右、上下に移動できると考えてください。
また、第一引数の 1 / 0 は、X方向のサーボかY方向のサーボかを示します。
今回の接続方法の場合、1チャンネルはX方向(左右)、0チャンネルはY方向(上下)に相当します。

###ドライバの移植について
今回使用したPCA9685のハードウェアのように、一般的にはメーカーからドライバのソースが公開され、ユーザが使用する事ができるようになっています。

ですが、I2CやGPIOでの通信制御は、それぞれの環境において提供されるライブラリが異なっているため、必ずしも全ての環境で、そのまま使用できるような形でドライバが提供される事はありません。
ですので、大抵のドライバのソースは、HAL(HardwareAbstrationLayer)と言うような形式で、通信部分を抽象化し関数を別に分け、その部分のみ改造することで、ドライバを移植できるような形式になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399637/72c73f7a-f5c1-d5ef-451d-b03e96875743.png)

今回のAdafruit-PWMのドライバの場合は、TwoWireと言うクラスを定義されており、そのクラスにI2C通信の処理を実装させているようでした。
ですので、このドライバをそのまま使用したいと考えた場合は、TwoWireクラスを実装する必要があります。

###注意事項
今回使用しているサーボは、起動の度にズレが発生するため、90度が必ずしも中央になるとは限りません。その為、何らかの機械的な仕組みやセンサーを利用して、電源ONの度に、トリム調整を行い、都度、ずれている分を角度に反映するなどの工夫が必要だと思います。（今回の試作ではそこまでの機能は用意しておりません。）

---
[インデックス記事へ](https://qiita.com/lis-hanzomon/items/cc1f7f316fbeb9579b28)
[第１２回記事へ](https://qiita.com/lis-hanzomon/items/d103e2d72c2f571dcba5)
[第１４回記事へ](https://qiita.com/lis-hanzomon/items/7454627183cf8ce9e9e8)

---
[リンク情報システム株式会社](https://www.lis.co.jp)では一緒に働く仲間を[随時募集](https://www.lis.co.jp/employ_top)しています！
また、お仕事のご依頼、ビジネスパートナー様も募集しております。[お気軽にご連絡](https://www.lis.co.jp/inquiry)ください。
LTE→5Gは直ちにはブレークスルーにならないけれど

[[@toast-uz]](https://qiita.com/toast-uz) さんの [[LTE→5Gはブレークスルーにはならない]](https://qiita.com/toast-uz/items/d096f69f846528e6214f) はとても参考になりました。
特に「LTE→5Gとは関係無く、常にブレークスルーはITから発生して、いつの間にか新たなインフラをフル活用するようになると思います。」という見方は勉強になります。

それを受けて、近々のキャッチアップ体験をいくつかご報告します。

6月20日発表の IDC Japan による [[国内5G市場予測発表]](https://www.idc.com/getdoc.jsp?containerId=prJPJ45262819) によると、確かに普及速度は緩やかです。
IDCは次のように言っています。
「5Gが広く普及するには、エリア展開が進むとともに、5G通信を利用できる通信サービスや多様な端末が普及価格で利用できる必要があります。加えて4K、8Kなど高精細映像を高速に処理できる映像機器やAI（Artificial Intelligence）など、5Gが可能にする新たなアプリケーションの構築に必要な製品やサービスの市場浸透も必要となります。」

エリア展開についは、2019年6月14日閣議決定による [[5Gと交通信号機の連携によるトラステッドネットの全国展開シナリオ]](https://www.kantei.go.jp/jp/singi/it2/5g_trustednet/dai1/shiryo1-1.pdf) が面白い動きだと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/6a0acbaf-400b-f6fa-b808-efe73a0cf462.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/5025c2e3-e9e6-fc14-0eec-32352fdf6a48.png)

東京ソラマチ5F にあるドコモの [[PLAY 5G]](https://www.play5g.jp/) がリニューアルされたと聞いたので8月10日に行ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/0319ab9e-a6d8-b03c-f013-d8e0fe774161.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/4445db15-58f9-a61d-8dff-65c9f6679555.png)
以前はテクノロジーをアピールした展示でしたが、リニューアルされてゲーム性が前面に出てきています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/0ae95469-ebd5-ddb3-1d23-8bbd8d357ec3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/9e753200-37a8-ed2a-e03c-77a439b52a54.png)

ヘッドセットを装着して太田選手と対戦してみました。7:5で勝ちました。
5Gはそんなユーザー体験の蓄積によって普及してゆくのかも知れませんね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/8a726599-ead4-3bfb-c6b5-955ae4f618f9.png)
Salesforce Developer Course Overview


Salesforce Developer Course Overview
Course Duration	20 hrs
Training Options
Live Projects

Salesforce Developer Course Curriculum
 Basics of programming (for those who never did any coding before)
  Basics of programming
  Variables
  Operators
  Expressions
  Looping Statement
  Controlling Statement
  Class
  Objects
  Functions

 Basics of Salesforce programming
  Architecture Apex / Force.com
  Data Types in Salesforce
  Collections
  List
  Set
  Map
  Debug process and methodology

 Building logic through programming
  APEX Class
  Triggers in Salesforce
  Invoking apex classes from Triggers
  Trigger handlers
  Trigger  Scope
  Trigger   Types
  Trigger Events
  Best Practices Triggers
  Governor Limits
  Understanding Trigger Context Variables in Salesforce
  Trigger.New
  Trigger.Old
  Trigger.New Vs Trigger.Old
  Trigger.NewMap Vs Trigger.OldMap

 Testing in Salesforce
  Understanding Test Classes in Salesforce
  Building Test Classes and execution
  Code coverage understanding
  Annotations
  Data Manipulation Language
  DML Statements
  Insert statement
  Update Statement
  Delete Statement
  Getting data from recycle bin
  MVC pattern in Salesforce
  Introduction to Visual Force
  Enabling VF for your Organization and Execution
  Creating First VF page

 Testing in Salesforce
 Working on UI with Visualforce Pages
  Building Page Block Table in VF page
  Building Form in VF page
  Apex:PageBlockSection and apex :PageBlockSectionItem
  Input Components
  InputText
  InputField
  OutputLabel
  Controllers
  Types of Controllers
  Standard Controllers
  Custom Controllers
  Controller Extension
  Rerender
  With sharing
  Without sharing
  VF page with multiple extension class
  Best Practices Visualforce
  Bulkification
  Exceptions

https://mindmajix.com/salesforce-developer-training
cordova-plugin-inappbrowserでシステムブラウザを起動する最善の方法？

相変わらずのcordovaメモ。
ていうかcordova-plugin-inappbrowserのメモ。

ちなみに
cordova:9.0.0
inappbrowser:3.1.1


inappbrowserはデフォルトの動作でwindow.openを暗殺する。
それはいい。（シャア的な口調で）

だがしかし、問題なのは
「InAppBrowser内でクリックされたＵＲＬをシステムブラウザから起動したい」
場合だ。

ここで大問題が発生したので苦しんでいる人がいたときのために共有したい。
cordovaなんて使わねえよという方ばかりの世の中だとしたらPOISION。


#InAppBrowser内で"_blank"が効かない

そうなんです。
window.open(url, "_blank");しても効かないんです。
なんかそういう風になってるんでしょうね。
細かいこと知らんよ。

というわけで、InAppBrowserではなくネイティブ側からシステムブラウザを起動することに。
InAppBrowser→Cordovaのブラウザ→システムブラウザ的な感じ。

伝達には"message"イベントを使う。
具体的には

```javascript

if(window.webkit && window.webkit.messageHandlers){

                var messageObj = {
                        "type": "newwindow"
                        , "data" : "https://xxxxxxxxx"
                };
                var stringifiedMessageObj = JSON.stringify(messageObj);
                webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj);
}
```


みたいな感じでアプリ側（local側？非InAppBrowser側）にメッセージを送ります。
処理してねイベント。

https://qiita.com/ookishin2018/items/1ba5dd0924373b67977e


#InAppBrowserでのシステムブラウザの開き方

んで、システムブラウザはこうやって開く。

```javascript
cordova.InAppBrowser.open('http://apache.org', '_system');
```

これは公式さんがいくらでも書いてくれてる。
https://github.com/apache/cordova-plugin-inappbrowser

しかしである。
残念な問題が一つある。多分ある。少なくとも自分の環境ではあった。
InAppBrowser.openをコールすると何故か既に起動中のInAppBrowserにくっつけていたイベントが吹っ飛ぶ。
つまり"message"イベントが動作しなくなる。
一度外部サイトをシステムブラウザで開くと、もう二度と外部サイトが開かないことになってしまう。
おそロシア。

window.open(url, "_blank")は使えない。
じゃあcordova.InAppBrowser.open('http://apache.org', '_system');の後にイベント定義しなおしたらいいやんと思ったけどダメ。
多分スレッドの都合だと思ってタイマーまで使ってイベント再定義してみたけど一度試したらダメだったし邪道っぽいからあきらめた。
別のInAppBrowserを立ち上げる…つまり複数のInAppBrowserを起動して一つはメインサイト、もう一つは外部サイトみたいな動きにしたかったけどダメ。（InAppBrowserって複数起動できないの？）
公式に書いてある"delete window.open"とかしてみたけどダメ。


１人日使って悩んだ。

答えは転がっていた。


↓神様
https://github.com/apache/cordova-plugin-inappbrowser/issues/315



つまり、javascript起動直後、devicereadyの発火前に、

```javascript

//起動前に退避
var DefaultOpen = window.open;

function openwork(){
     DefaultOpen(url, "_blank");
}
```

とかしておけばいいだけだった。
解決策をありがとう。
そしてデフォルトの挙動殺すのはどうしても賛同できんなあ。

<h2>2020.07.02WkWebViewの対応及びInAppBrowser最新版4.0.0</h2>

ところで上記の話はin-app-browser3.1.1の話です。
WkWebView対応を行うため、先日inappBrowserを4.0.0に上げたところ、上記の動作が一切動きません。
死んだ。

結論から言うと、最新版ではこう。


```javascript
cordova.InAppBrowser.open('http://apache.org', '_system');
```

なんだけど、これだと一度しか開けない。
本当に、一度別ブラウザで開いたら終わる。

なのでこうする。


```javascript
this.Ref = cordova.InAppBrowser.open('http://apache.org', '_system');

//イベントを再定義してやる。これマジで。しかしソースは動作未確認なのでタイポしてたら赦してください。
this.Ref.addEventListener("message", function(){ /* */ });
```

なんかシステムブラウザ起動時にイベントの関連付けが別インスタンスに飛んでしまうらしい。
ウソだと言ってよママン。

見たことも聞いたこともないObjectiveCのコードを必死にデバッグしたよ…(*´Д｀)
これ、6.0.1とかになったら再度動作しなくなるんじゃなかろうか…。