OmniAICreator/Qiita-1.07M huggingface dataset:
【Python入門】while文（繰り返し処理）の使い方

※こちらの記事は、プロスタ編集部が現在大変人気の高いPythonの文法記事を公開することで、皆様の学習にお役に立ちたい意図で投稿しております。

参考サイト：[【Python入門】while文（繰り返し処理）の使い方]
(http://programming-study.com/technology/python-while/)

#【Python入門】while文（繰り返し処理）の使い方

Pythonに限らず、プログラミングの基本は「条件分岐」と「ループ処理」です。Pythonでの条件分岐にはif文、ループ処理には「for文」と「while文」の2つの種類があります。今回はwhile文についてご紹介します。

while文は主に、「無限ループ」や「ある条件の間繰り返す」といった処理によく使われます。

目次 
1 [while文の書き方](##while文の書き方)
2 [while文を使ってみる](##while文を使ってみる)
3 [breakを使ってみる](##breakを使ってみる)

##while文の書き方

```
while 条件式:
    繰り返したい処理
```
という書き方をします。

「条件式」の部分には名前のとおり、条件を書きます。その条件式がTrueとして評価されている間、延々と「繰り返したい処理」を行います。

例えば、以下のような場合ですが

```
while 条件式:
    処理A
処理B
```

この場合は、処理Aが繰り返され、条件式がFalseになったら繰り返しが終わり、処理Bへと移ります。
繰り返しが行われるのは、あくまでwhileのブロックです。

##while文を使ってみる

1から5までを表示するwhileループを作ってみましょう。

```py3
index = 1
while index <= 5:
    print(index)
    index += 1
print("終了")
```

```text:実行結果
1
2
3
4
5
終了
```

処理の流れは以下のようになります。

1行目 index = 1　で、変数indexに1を代入する

2行目 while index <= 5:は、indexが5以下（5のときも含む）の間はwhileブロックを実行する、という意味です。
現在のindexは1なので、5以下です。3行目へ移ります。

3行目 print(index) indexを表示します。現在はindexに1が入っているため、1が表示されます。

4行目 index変数に、1を足します。この時点で、index変数の値が2になります。

2行目へ まだindex変数は2です。5以下なので、また3行目へ

この後、index += 1で6になるまで同様の続きます。

2行目 indexが6で、5以下ではありません。なので、3行目には行かず5行目へ飛びます。
breakを使ってみる

whileループでは、break文を使うことでループから抜けることができます。
先ほどの例を改造し、以下のようにしてみます。

```py3
index = 1
while index <= 5:
    print(index)
    index += 1
    break
print("終了")
```

4行目のindex += 1までは同じなのですが、5行目のbreak のところまでいくと、すぐさまループを抜け、6行目に移ります。
そのため、結果は以下のようになります。

```text:実行結果
1
終了
```
今までは

```
while 条件式:
    処理A
```

という書き方をしていますが、このbreakを使うことで

```
while True:
    if 条件式:
        break
    処理A
```

という書き方ができるようになります。
while Trueで無限ループをしつつ、中のif文でbreakし、ループを抜けるという方法です。この方法もよく使われるので、ぜひ覚えておきましょう。
Angular1 UI-Router によるネストルーティング

* `/page1`
* `/page1/:id`
* `/page2`

の三つのルーティングを設定するデモ。`page1` の子として `page1/:id` が存在する。

```html
<!DOCTYPE html>
<html ng-app="App">

<head>
  <meta charset="UTF-8">
  <title>UI Router</title>
</head>

<body>
  <a ui-sref="page1">page1</a>
  <a ui-sref="page2">page2</a>

  <ui-view></ui-view>

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
  <script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
  <script src="script.js"></script>
</body>

</html>
```

```js
angular.module('App', ['ui.router'])
  .config(function ($stateProvider) {
    $stateProvider
      .state({
        name: 'page1',
        url: '/page1',
        template: '<h2>page1</h2><a ui-sref=".detail({id: 12345})">detail</a><hr><ui-view></ui-view>'
      })
      .state({
        name: 'page1.detail',
        url: '/{id}',
        resolve: {
          val: function ($stateParams) {
            return 'id is : ' + $stateParams.id;
          }
        },
        template: 'details {{$ctrl.val}}',
        controller: function (val) {
          this.val = val;
        },
        controllerAs: '$ctrl'
      })
      .state({
        name: 'page2',
        url: '/page2',
        template: '<h2>page2</h2>'
      });
  });
```
【Python入門】if文を使った条件分岐の書き方

※こちらの記事は、プロスタ編集部が現在大変人気の高いPythonの文法記事を公開することで、皆様の学習にお役に立ちたい意図で投稿しております。
参考サイト：[【Python入門】if文を使った条件分岐の書き方](http://programming-study.com/technology/python-if/)

#【Python入門】if文を使った条件分岐の書き方

プログラミングの基本は、「条件分岐」と「繰り返し」です。繰り返しにはfor文または while文で行い、条件分岐にはif文を使います。他の言語ではswitch文という機能もありますが、Pythonではシンプルにif文のみが用意されています。

目次 
1 [Pythonのif文とは？](##Pythonのif文とは？)
2 [実際にif文を使ってみよう](##実際にif文を使ってみよう)
3 [複数の条件分岐の書き方](##複数の条件分岐の書き方)
4 [演算子について](##演算子について)
4.1 [比較演算子](###比較演算子)
4.2 [論理演算子](###論理演算子)

##Pythonのif文とは？
```
if 条件:
    処理A
    処理B
処理C
```
という書式です。
処理A、処理Bは条件がTrueの場合のみ実行されます。条件の場合に行う処理は、必ずインデントがされている必要があります。インデントされていない処理Cは、条件がTrueでもFalseでも実行されます。もし「条件」だったら、「すぐ下のインデントされた処理をする」と英語っぽく覚えてしまっても大丈夫です。

##実際にif文を使ってみよう

```py3
your_age = 23
print('年齢確認')
if your_age >= 20:
    print('二十歳以上です')
print('年齢確認 終了')
```
このコードは、your_ageの値により2種類に分岐されます。
(1)your_ageが20以上の場合

```text:
年齢確認
二十歳以上です
年齢確認
終了
```
と表示がされます。

(2)your_ageが20未満の場合

```text
年齢確認
年齢確認
終了
```
と表示されます。


##複数の条件分岐の書き方

今度は、条件分岐が複数の例です。

```py3
your_age = 41
if your_age >= 40:
    print('40代')
elif your_age >= 30:
    print('30代')
elif your_age >= 20:
    print('20代')
```

この例であれば、「40代」と表示がされます。
条件をいくつか書きたくなった場合は、このように「elif」と続けていきます。
（elifは、else ifという意味です。「もしくは…」のように考えましょう）

さらに、どの条件にも当てはまらない場合のみ処理を行うことも可能です。

```py3
your_age = 15
if your_age >= 40:
    print('40代')
elif your_age >= 30:
    print('30代')
elif your_age >= 20:
    print('20代')
else:
    print('未成年')
```

一つ注意することは、if文は上から順番に条件を確かめていき、どれか一つに入れば、他のelif、elseは実行されません。
ですので、以下のコードは「your_age >= 20」がTrueとなってしまい、「20代」と表示されて終わってしまいます。

```py3
your_age = 50  # 50歳！
if your_age >= 20:
    print('20代')  # ここにきてしまう！
elif your_age >= 30:
    print('30代')
elif your_age >= 40:
    print('40代')
else:
    print('未成年')
```

##演算子について

###比較演算子

「>=」や「==」という記号を使用しましたが、これは比較演算子と呼ばれるものです。
以下は全てif文の条件式として記述できます。

|演算子|	表示|
|---|---|
|A==B	|AとBが等しいならばTrue|
|A != B	|AとBが等しくないならばTrue|
|A >= B	|AがB以上ならばTrue (AとBが同じ値はTrue)|
|A > B	|AがBよりも大きいならばTrue (AとBが同じ値はFalse)|
|A <= B	|AがB以下ならばTrue (AとBが同じ値はTrue)|
|A < B	|AがBよりも小さいならばTrue (AとBが同じ値はFalse)|
|A in B	|BにAが含まれていればTrue（これは少し特殊で、Bがリスト、Aが文字列、等の場合によく使います)|

###論理演算子

また、論理演算子と呼ばれるものもあります。こちらもif文の条件式として記述できます。

|演算子|	表示|
|---|---|
|A and B|	AとBがTrueならば、True|
|A or B	|AかBのどちらかがTrueならば、True|
|not A  |	AがFalseであれば、True|

if文はプログラミングにおいて最も重要といっても過言ではないです。こちらの記事が皆様の理解に役立てばと思います。

参考サイト：[【Python入門】if文を使った条件分岐の書き方](http://programming-study.com/technology/python-if/)
Pythonでリセットできる(元に戻せる)shuffleをつくった

Numpyのshuffleでリセットできるものがなかったようなので作ってみました。
そもそもあったり、もっといい書き方があったら教えてください。

resettable_shuffleでシャッフルして、reset_shuffleで元に戻します。

```python:test.py
import numpy as np

# arrayは普通の1次元のリスト
# 破壊的メソッド
def resettable_shuffle(array, seed):
	np.random.seed(seed)
	np.random.shuffle(array)

# arrayは普通の1次元のリスト
# 非破壊的メソッド
def reset_shuffle(array, seed):
	seq = np.arange(len(array))
	np.random.seed(seed)
	np.random.shuffle(seq)
	tmp = np.c_[seq.T, np.array(array).T]
	tmp = np.ndarray.tolist(tmp)
	tmp = sorted(tmp)
	tmp = np.array(tmp)
	return np.ndarray.tolist(tmp[:,1])

seed = 321654
a = ["a","b","c","d","e","f"]

resettable_shuffle(a, seed)

print(a)

a = reset_shuffle(a, seed)

print(a)
```


出力結果

```
['a', 'b', 'c', 'd', 'e', 'f']
['c', 'f', 'd', 'e', 'a', 'b']
['a', 'b', 'c', 'd', 'e', 'f']
```

# 宣伝
フォローお願いします:golf: [@redshoga](https://twitter.com/redshoga)
PaaS の OpenShift(v3) Origin クラスタ を OSX 上に構築する

# PaaS の OpenShift(v3) Origin クラスタ を OSX 上に構築する
## 1. はじめに
PaaS の１つである OpenShift(Origin)をオンプレミス（ローカル）のOSX上に構築する方法を記載します。

なお、OpenShift(Origin)の使い方については本記事では取扱いません。

クラスタ用サーバを別途自分で準備してAnsibleを利用してプロビジョニングする方法で
何度か実施しましたが（Ansibleのバージョンが低かったからか？）、
AnsibleのPlaybookが途中で失敗してしまったため

https://github.com/openshift/openshift-ansible-contrib/tree/master/vagrant

の方法でVagrantとAnsibleを利用してVirtualBox上に複数ノードクラスタ環境（デフォルトのCentOS）を構築します。

検証環境等でのデモ、素振り用などの参考にして頂ければと思います。

## 2. 環境
+ OSX Yosemite
+ VirtualBox バージョン 5.1.4
+ Vagrant 1.8.5
+ Ansible 2.3.0 (devel 324702c38f) last updated 2016/11/22

今回インストール

+ OpenShift Origin
  + OpenShift Master: v1.3.1
  + Kubernetes Master: v1.3.0+52492b4

## 3. 前提条件、事前準備
1. OSX にVirtualBox, Vagrant ,Ansibleがインストールされている前提です。
2. Vagrantへ`vagrant-hostmanager`,`vagrant-sshfs`,`landrush`のプラグインをインストールしておきます。

インストール方法は以下

```
vagrant plugin install vagrant-hostmanager
vagrant plugin install vagrant-sshfs
vagrant plugin install landrush
```
なお、`landrush`のプラグインについて、自分の環境ではインストールに失敗してしまいました。
Vagrantfile上では必須ではなかったため、深追いはせずにインストールせずに進めました。
`landrush`がインストールされていない場合
Vagrant up時に
`note: landrush plugin is not installed, run `vagrant plugin install landrush` to install it.`
と出ますが
今回作成されるVMの名前解決に必要な情報についてホストOSX上の`/etc/hosts`へ
以下が追記されますので動作確認にあたっては特に問題ないと思います。

```
192.168.50.23	admin1.example.com
192.168.50.23	admin1
192.168.50.20	master1.example.com
192.168.50.20	master1
192.168.50.21	node1.example.com
192.168.50.21	node1
192.168.50.22	node2.example.com
192.168.50.22	node2
```

## 4. 手順
Terminalで以下を実施します。

```
# 公式のGithubから　Git clone と　Vagrantfileのディレクトリへ移動
git clone https://github.com/openshift/openshift-ansible-contrib.git ; cd openshift-ansible-contrib/vagrant
# VMの作成とプロビジョニング
vagrant up
```

(参考)　以下Ansibleのプロビジョニング結果
<img width="746" alt="oc_ansible.png" src="https://qiita-image-store.s3.amazonaws.com/0/117986/c6dcbd57-069a-2ea0-1e52-9756591b8280.png">

## 5. ブラウザよりログインして確認

1. ブラウザより`https://master1.example.com:8443`を入力してログイン画面を表示します。
<img width="793" alt="oc_web01.png" src="https://qiita-image-store.s3.amazonaws.com/0/117986/b7f409b5-8e33-6223-fd62-9409c45addf4.png">

2. adminアカウント（初期admin/admin123)でログインします。
<img width="793" alt="oc_web02.png" src="https://qiita-image-store.s3.amazonaws.com/0/117986/5fb12501-da63-b860-8155-d34a0cec7670.png">

## 6. 参考

公式サイトドキュメント
https://docs.openshift.org/latest/welcome/index.html

Github
https://github.com/openshift/openshift-ansible-contrib


---
以上
キャプチャ画像のやり取りで疲弊した方たちへ(Windows編)

最近仕事の関係で、障害や操作を一連の流れで説明することがおおく、キャプチャをやり取りする機会が増えたのですが、
「いちいちペイントからＯｆｆｉｃｅに貼り付けるのも面倒、、でも仕方ないか、、、」ということがよくあります。

そんなとき、Win7 (以降) の標準機能で「問題診断記録ステップツール」というツールが、
とても便利だったので紹介します。

# 内容

・ 効果的なケース
・ 問題診断記録ステップツールの使い方
・ まとめ

# 効果的なケース

・一連の流れを説明したい、けど文書にするとすごい量になってしまう。
ただ、キャプチャをとるとなると一連の流れでキャプチャを取り、
それらを一枚一枚 Word なり、Excel なり、に貼り付けるのでとても面倒なケース

・とくにクライアントに提出するためのものではなく、とりあえずキャプチャをとって見せたい、残しておきたいという場合

# 問題診断記録ステップツールの使い方

１.  ファイル名を指定して実行 (Windows + R キー) で、psr を入力して起動します。
<br>

![src1.png](https://qiita-image-store.s3.amazonaws.com/0/133676/21d27191-180b-1247-7436-220ccfc3e65b.png)
<br>


２． [記録の開始] をクリックすると、開始状態となり
クリックをするたびにキャプチャが取れます。(記録はいつでも一時停止して、後で再開できます。)

３． [記録の停止] をクリックして、[名前を付けて保存] します。(zipファイルで保存されます)
<br>

![src2.png](https://qiita-image-store.s3.amazonaws.com/0/133676/3cff3d07-acbc-cede-1462-0bddee73d26b.png)
<br>


４．zip ファイルを開き、mhtmlファイルを開くと、記録の開始をしてからの、
クリック毎スクリーンショットが一連で表示されます。
<br>

![src3.png](https://qiita-image-store.s3.amazonaws.com/0/133676/6a182716-5a0a-4450-0155-a141bd6caff6.png)
<br>


![src4_4.png](https://qiita-image-store.s3.amazonaws.com/0/133676/ec356e80-04c0-d287-d534-9268696a1182.png)


<br>
■スクリーンショットのキャプチャ数について

psr.exe の設定から、キャプチャ取得数を変更することが出来ます。

![src5.png](https://qiita-image-store.s3.amazonaws.com/0/133676/65eabe9c-3dec-e6bf-aa7e-319ea30a9c3f.png)



# まとめ

このツールをつかってから、キャプチャ取得にかかる時間が結構削減されたので、
みんなもガンガン取っちゃってね！！
秀丸でIPアドレスを検索させる正規表現

# 概要
秀丸でIPアドレスを検索させる正規表現です。
必要な際いつもググっている自分への備忘録です。

# IPアドレスの正規表現

`(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])`

#正規表現のバージョン

`HMJRE.DLL V4.10`
# 参考にしたサイト

http://www.arearesearch.co.jp/learn/program/07.html
Oracle RDBMSに格納したJSONデータへの索引作成 (Update 12c R2対応)

# JSON形式のデータをOracle Database に格納したのち検索高速化のために索引の作成が可能
## ２種類の索引
### 定型検索のための索引
- JSON_VALUE()関数 を使ったファンクション索引
- Bツリー索引、または、ビットマップ索引
- JSON_EXISTS()関数を 使ったビットマップ索引
- IS JSONを使ったビットマップ索引

### アド・ホック検索のための索引
- ドキュメント上では"JSON Search Index" と表記
- JSONドキュメント全体のどこかに特定の文字列が含まれるか?
- 任意のプロパティに特定の文字列が含まれるか?
- 実体はOracle Text索引(Oracle Textの有効化が必要)


アド・ホック検索用索引のコマンドリファレンス (12.2)

```
CREATE SEARCH INDEX <索引名> ON <表名> (<JSONが格納されている列名>) for JSON;
```

コマンド例

```
CREATE SEARCH INDEX JSON_IDX ON JSON (doc) for JSON;
```


アド・ホック検索用索引のコマンドリファレンス (12.1)
`CREATE INDEX <索引名> ON <表名> (<JSONが格納されている列名>) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('section group CTXSYS.JSON_SECTION_GROUP')`
コマンド例
`CREATE INDEX JSON_IDX ON JSON (doc) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('section group CTXSYS.JSON_SECTION_GROUP')`

### 索引が使われている例
検索SQL

``` sql
select * from json where json_value(doc,'$.lastName') = 'Venzl';

実行計画
-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |     1 |  2014 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| JSON      |     1 |  2014 |     4   (0)| 00:00:01 |
|*  2 |   DOMAIN INDEX              | JSON_IDX1 |       |       |     4   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(JSON_VALUE("DOC" FORMAT JSON , '$.lastName' RETURNING
              VARCHAR2(4000) NULL ON ERROR)='Venzl')
   2 - access("CTXSYS"."CONTAINS"("JSON"."DOC",'{Venzl} INPATH(/lastName)')>0)
```

参考
[Oracle RDBMS に JSONデータを格納する](http://qiita.com/kenwatan/items/1bb8e78cf311d9bbbd71)
PHPのフィルタ関数の、「文字列に変換してる箇所のコード」の自己解釈

[FILTER_CALLBACKで受け取る変数は常に文字列になる](http://qiita.com/ndxbn/items/6c0cec139607420634f9)でコード見たので、せっかくなので、自己解釈のコメントを入れてみたのを書いておきます。  

```cpp:フィルタリング関数に渡す前に、文字列に変換してる
  /* #49274, fatal error with object without a toString method
    Fails nicely instead of getting a recovarable fatal error. */
  /* https://bugs.php.net/bug.php?id=49274 */
  /* オブジェクトの場合は、文字列に変換できないかもしれないので、
      convert_to_string()の直前で確認する。
  */
  if (Z_TYPE_P(value) == IS_OBJECT) {
    zend_class_entry *ce; /* たぶん、Class Entry の略 */

    ce = Z_OBJCE_P(value);
    if (!ce->__tostring) {
      /* なんでrefcounterをデクリメントしてるのかはわからない */
      zval_ptr_dtor(value);
      /* #67167: doesn't return null on failure for objects */
      /* https://bugs.php.net/bug.php?id=67167 */
      if (flags & FILTER_NULL_ON_FAILURE) {
        ZVAL_NULL(value);
      } else {
        ZVAL_FALSE(value);
      }
      /* 文字列に変換できない場合は、convert_to_stringを通したくない。 */
      goto handle_default;
    }
  }

  /* Here be strings */
  /* 事前にStringにしてから、各filter関数を適用する */
  convert_to_string(value);
  filter_func.function(value, flags, options, charset);
  
  /* 「フィルタが失敗した場合に返す値」を指定するオプション の処理
  http://jp2.php.net/manual/ja/filter.filters.validate.php
  */ 
  /* 文字列に変換できなかった場合に、ここまで飛んでこれるようにしたいので、ラベル */
handle_default:
    /* 中身のコードはif文の条件式のネストが深くて厄介なので、次のコードの方に分ける */
```

```cpp:handle_defaultラベルの中身
  if (
    /* オプション（PHPのfilter関数の第3引数）が指定されてて */
    options
    &&
    /* そのオプションが配列orオブジェクトで指定されてて（≒optionの型のValidate） */
    ( 
      Z_TYPE_P(options) == IS_ARRAY
      || Z_TYPE_P(options) == IS_OBJECT
    )
    &&
    /* フィルタリングに失敗していて */
    (
      (
        flags & FILTER_NULL_ON_FAILURE
        && Z_TYPE_P(value) == IS_NULL
      )
      ||
      (
        !(flags & FILTER_NULL_ON_FAILURE)
        && Z_TYPE_P(value) == IS_FALSE
      )
    )
    &&
    /* 「デフォルト値」の設定がある */
    zend_hash_str_exists(HASH_OF(options), "default", sizeof("default") - 1)
  ) {
    zval *tmp;
    if ((tmp = zend_hash_str_find(HASH_OF(options), "default", sizeof("default") - 1)) != NULL) {
      ZVAL_COPY(value, tmp);
    }
  }
```

goto使って無理やり経路追加してるあたり、良くも悪くもC言語っぽい感じしますね（笑）。`php_zval_filter` だと、プリミティブ型なやつとそれ以外（オブジェクトと配列）が混ざるし、あんまよくないのかなぁとか思います。

[laruence氏が最後にリファクタしたのが2014年5月7日](https://github.com/php/php-src/commit/ed5b6af8af6a0b8c331e692cd0a81daeef59dcff)なので、気になるんならPR投げつけてもいいかなぁとも思ったりしました。しらんけど。
初めて詐欺ネットショップに遭遇してしまった...！（TwTlll）

# 購入に至るまで - 事件の始まり -

デスクチェアにこだわりが強すぎて、Amazonでも楽天でも見つからなかった。

iPhoneでGoogle検索したら理想のチェアがヒット！
なんか動かないボタンがあるな...と思いながらも、カートイン。

##会員登録画面
メールマガジンが「HTMLメール」「テキストメール」だけな上に必須になってたから
受信しないって選択肢がないことに

（強制感強いショップだな〜）

と感じる。

## 購入フロー
クレジットカード決済にする予定だったけど、
表示されず「購入完了」ボタンが表示されたので

（購入完了後に決済URLにジャンプするパターンかな）

と、思いきや、なにもなく終了。
マイページボタンがなくて、会員情報どこから見るんだよw　と心でツッコむ。

## ほどなく、購入完了自動配信確認メールが来て
ここにきて、購入履歴へのページURLが表示された（そういうパターンもあるのか

で、最初に気づいたのは、「購入NO.16」
あら。番号が若い。
できたばっかり？　→　PCで検索して会社情報を見る。

東京の会社なんだ。　→　会社名でググる。
社長の名前が違うんだ。→　兄弟かな？

振込先は、別メールで来ると書いてあるから、待ちましょ。
てか、クレジットカードも楽天決済もNP決済も使えないんぢゃんw
と、ツッコミつつ、まあ銀行振込でもいいや。と思う。

## 振込先記載メール受信

・・・ヤダ。この子(´・ω・`)

運営会社が東京なのに、振込先支店が愛知県清須。
そのうえ振込名が、外国人の個人名。

だめ元で振り込んでみるか？とも思ったけど、やっぱり念のため…と思って記載の電話番号に確認
　→　電話出ないし(´・ω・`)！！

## 現時点にて思ったこと
いやいや、ここまでの条件だけで十分なにかここおかしいでしょ。

* 注文番号が若い。
* SNSをやってないから歴史が見えない。
* なんなら押せないボタンがある（よくあることけどw
* 記載電話番号が不通。他のこの会社の電話番号と違う。
* 電話番号検索にヒットしない。
* 運営会社が東京だったら支店がない限り東京の銀行になるでしょ。
* 支店が清須ってえらい田舎にあるし。てかうちから近いな。
* そもそもどこから配送してくるんだ？清須？？どこにも記載がないし検索にもかからない。

どれかひとつだけとか、数点でもそんなにおかしくないけど、
これだけまとまると十分おかしいし、怪しくも感じるさ。

逆に制作側からいうなれば、上記が怪しくてはいけないということですね。

## 納得するまで確認してみましょう
だんだん疑心も深まってきたところで、ここの会社の電話番号を改めて調べよう。
と、同名・同住所で調べると、とってもまともな会社がヒット。

ECやってるみたいだけど、住所みるときちんと事務所の部屋番号まで載ってる。
さっきの店は部屋番号の記載がなかった。

というわけで、早速電話。
数コールで感じのいいお姉さんが出てくれたので、丁重にご質問。

Q. 「失礼ですが、そちらの会社で◯◯というオンラインショップの運営はされていますか？」

そしたらなんと・・・！

## A.そういった店舗は運営しておりません

実はなんと、今日お昼の時点で2回目の被害確認電話ですと...！

まあ！！ビックリ！


## ネットショップを運営するときの基本
私ネットショップの運営に携わってるからこそ思うところもあるけど
開店直後は、ただでさえこうやって怪しいところがある。

だからこそ、
* 電話はちゃんと出る！
* 運営会社が明記されている「特定商取引に関する法律に基づく表記」もきちんと書く！
* SNSやブログもがんばって！
* Yahoo!やAmazon、楽天などモール店舗も持っておくとなお良し！

無料でサクッと作れるネットショップは
嘘で固めて責任を取らないことも可能だし、逃げることも可能。
本当に商品が届くかもわからない。

ドメイン持ってるのが信頼になるかって、いまはならないから。
個人事業主でも法人でも、きちんと登録して先を見て運営してるところは、責任取りますよ。
絶対ではありませんが、まだ信頼できます。将来がかかってますしね。
投資した金額が大きいと、社名だって大切な資産ですからね。
そうやすやすと捨てられないという考え方もできます。

## スマホで買う？PCで買う？
スマホで購入する層と
PCで購入する層との違いは、購入時間までの時間もひとつある思う。

PCで購入する場合は比較検討を結構するけど
スマホで購入する場合は、案外気軽に購入してしまったりしない？

そんな記事を最近読んだ気がするんだけど、
今回、私もスマホでサクッ！と購入して、
カード払いOKとあるのに、カード払いの手続き案内がないまま購入完了したことによって
銀行振込になってしまった。
それでもいいやと思ったんだけど、振込先で疑問にぶち当たったというわけ。

## まとめ
その後、そのオンラインショップの情報をいただけますか？と言われたので、詳細までご説明して完結。

## 
お客様ナメんなよ〜！
と、言いたいところだけど、
こういう被害が増えた場合、EC業界にも打撃がある。
ちょっとそれすごく迷惑=3

真面目にやってるうちら関連業者にまで被害が及ぶ。
より良く、便利にって精一杯がんばってるのに邪魔されてはたまらんですわ。

てか、成りすまされた会社さんは、とても丁寧な電話対応をされているまともな会社さんに思えただけに、とてもかわいそう。。

会社情報をきちんと公開しているみんなが対象になりますぇ。。

成りすまし被害者は、明日は我が身かと思うと震えが来るわ。。。
CORS簡易まとめ

# 読みは？
こるす？

# CORSの対応をしないとどうなるのか
APIにアクセスできずにJSでエラーが起きたりする。
じゃあどうやって解決するのか・・・。
↓を読んで簡単にお勉強。

# 「オリジン」を知ろう
スキーム(例：http)、ホスト(例：example.jp)、ポート(例：80)
の組み合わせのこと。
オリジン内であれば、保護範囲内のリソースとして取り扱う。

逆に異なるオリジンの場合「クロスオリジン」という。

# Same-Origin Policy(SOP)という決まりを知ろう
SOPは、クロスオリジンの場合、リソースの読み書きを禁じることのこと。

XMLHttpRequestやCanvasは、
このオリジンの制約に依存してしまうため、
APIGatewayを使う場合、SOPを考える必要がある。

※CookieやHTTP認証はオリジン以外を動作の制約としている

# つまり、CORS(Cross-Origin Resource Sharing)とは
JSONPに替わる方法として、
XMLHttpRequestで異なるドメイン同士でリソースを共有する仕組み。

**ブラウザはCORSを検出すると、実際にメソッドを投げる前に、
OPTIONSメソッドによる検査を行う。(ここ重要)**

# CORSの対応まとめ

1. OPTIONSメソッドを用意
2. OPTIONSメソッドの検査を通るようにCORSの対応を実装
3. 使いたいHTTPメソッドでもCORSの対応を実装

CORSに必要なレスポンスヘッダ

|レスポンスヘッダ|値|説明|
|:--|:--|:--|
|Access-Control-Allow-Origin|*|必須であり、基本。<br>許可したいオリジンを指定するのだが、どこからでも良いなら「*」|
|Access-Control-Allow-Headers|Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token|使用できるヘッダであることを認めるもの。<br>クライントによって、Originのみだと動作しない時があるため、コレも追加で指定。|
|Access-Control-Allow-Methods|POST,GET,OPTIONS|許可されるHTTPリクエストメソッド|
新人エンジニアが教える本当に賢い1日の使い方

[新人エンジニア Advent Calendar 2016](http://qiita.com/advent-calendar/2016/freshman_engineer)の7日目記事です。
当日になっても誰も書く雰囲気なかったんで、書いちゃいます。
そこ、パディングとか言わない

現在進行形で書いてるなうです！ライブライティングです！
なんだかドキドキしますね。私が。

# はじめに
業務効率化という視点で、今日一日の業務を追っていこうと思います。

「業務効率化だけど、わざわざ言うほどでもない...」

そんな心の隙間を埋めていこうと思います。


# ～9:00 通勤
果たして通勤は業務に含まれるのかの是非は、一度置いておきます。
朝の通勤ラッシュ混雑中の時間は、何もすることができず、人生において無駄な時間となりがちです。
**朝の通勤ラッシュ混雑をいかに回避するか**、私の工夫を載せておきます。
なお、「早く家を出ればいいんじゃない？」という指摘はスルーします。

> 1. 事前準備
>   - 降車駅で、自分が乗る電車のどの車両が改札に最寄りなのかを把握しておく
>   - 降車駅で、自分が乗る電車のどちら側の扉が開くのかを把握しておく
> 
> 1. 乗車
> 改札最寄り車両の隣接車両の内、空いてる所に乗る
> 
> 1. 車両移動
> 「降車駅より前の駅」 かつ 「降車駅と同じ側の扉が開く駅」で一度降りて、改札最寄り車両に移動
>   - これにより、降車駅でスムーズに降車、改札に移動できる
>   - ただし、多くの場合この車両は激混みなので、頑張る。
> 
> 1. 誰よりも素早く改札に移動


# 9:00～ 業務開始。
メール等チェック、朝会、スケジュール確認など
この世には星の数ほどの新人エンジニアがいらっしゃいますが、ほとんどの人はこの辺の作業から始めるはずです。

**朝のこの時間は非常に集中力が高い時間帯なので、この時間帯に頭を使う作業を行うようにしています。**
今日はこの後にチームのMTGがあったので、その資料準備をしていました。


# 10:30～ チームMTG
暖房が効きすぎてて、眠たかった。

# 12:00 ～ 13:00 お昼
## お昼
お昼はエレベータ、お店が混雑して、非常に多くの時間をロスしてしまいますよね。
なので、お弁当なりコンビニ飯なり、必ず事前にお昼を調達しておきます。
**お昼混雑に絶対に巻き込まれてはいけません。**

また、食事中も手と顎を動かすだけだと時間がもったいないので、
資料を読んだり、動画を見たりなど、**食事中もできるだけ作業を進めます。**

外食派？そんなの知らry

## 昼寝
できるだけ素早く食事を済ませたら、可能な限りお昼寝をします。
同期や先輩が談笑して盛り上がっていても関係ありません。寝ます。

これによって、**午後一の作業の集中力が、体感で3倍は向上させることができます。**


# 13:00 ～ 16:00 記事執筆、勉強会の資料修正
「昼一は眠たくなるよねぇ～」などと府抜けたことを言う人もいますが、昼寝した私には無縁です。

**朝ほどではありませんが、この時間帯も集中力を保てる時間帯です。
頭を使う作業をガンガンやります。**

その他工夫としては、

- カフェインを取る
- 締め切り効果 + 適度に休憩をとる

# 16:00 ～ 17:45 事務作業、部内業務
この時間帯から疲れて頭回らなくなってくるので、**事務作業など頭を使わない作業を行います。**

事務作業、部内業務など、エクセル系・マウスをカチカチする系の業務をやってました。

# 17:45～ 残業
この記事を書いてますよ。
残業じゃないですよ。業務効率化できてますから。ええ。

業務効率化に余念のない皆さまは、是非この言葉をお持ち帰り下さい。
*「残業は仕事のできないやつの言い訳」*


# まとめ
こいつエンジニアなのに、技術的なことあんまやってなくね？
TensorFlowのinitialize_all_variablesがDeprecatedになった件

先日(2016/11/29)TensorFlowの最新版r0.12がリリースされました。

TensorFlow r0.11で開発していたアプリケーションを本番リリース前のテスト環境として用意したr0.12で実行したところ、起動時に見覚えのない警告メッセージが表示されました。

## WARNINGの内容

>WARNING:tensorflow:From <stdin>:1 in <module>.: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed after 2017-03-02.
Instructions for updating:
Use `tf.global_variables_initializer` instead.

initialize_all_variablesは2017/03/02以降に廃止される予定とのこと。

**initialize_all_variablesはチュートリアルやサンプル実装、それにネットの記事などで頻繁に見かける変数初期化命令ですが、3ヶ月後には使えなくなる恐れがあります。**

## 新しい初期化命令

上記WARNINGに記載されている通り、r0.12からはglobal_variables_initializerを使用せよとのこと。

## r0.12で試してみた

```
>>> tf.__version__
'0.12.0-rc0'
```

まずはもう一度従来の初期化命令であるinitialize_all_variablesを実行。

```
>>> tf.Session().run(tf.initialize_all_variables())

WARNING:tensorflow:From <stdin>:1 in <module>.: initialize_all_variables (from tensorflow.python.ops.variables) is deprecated and will be removed after 2017-03-02.
Instructions for updating:
Use `tf.global_variables_initializer` instead.
```
やはりWARNING発生。

次に新しい初期化命令のglobal_variables_initializerを実行。

```
>>> tf.Session().run(tf.global_variables_initializer())
>>> 
```
こちらはWARNINGも無く正常に実行終了。

## r0.11でも試してみた

```
>>> tf.__version__
'0.11.0'
```
まずは従来の初期化命令であるinitialize_all_variablesを実行。

```
>>> tf.Session().run(tf.initialize_all_variables())
>>> 
```

これは当然正常終了する。

次に新しい初期化命令のglobal_variables_initializerを実行してみる。

```
>>> tf.Session().run(tf.global_variables_initializer())

AttributeError: module 'tensorflow' has no attribute 'global_variables_initializer'
```

**global_variables_initializerはr0.11ではまだ実装されていないためエラーになる。**

## まとめ
r0.11を使い続けるならinitialize_all_variablesを使うしかない。
r0.12に乗り換えるならglobal_variables_initializerに早めに変更しよう。

## どうしても共通化したい場合
r0.11とr0.12でどうしても共通化したければinitialize_variablesを使おう。
この命令は、初期化すべき変数をリストで指定する必要があるが、
少なくともr0.10からr0.12までは互換性が保たれておりDeprecatedにもなっていないので、
当面は使い続けられるらしい。

## r0.12のその他の変更点

こちらからどうぞ。
[TensorFlow v0.12.0 RC0](https://github.com/tensorflow/tensorflow/releases/tag/0.12.0-rc0)
Google App Scriptでフォルダ、ファイルの一覧を取得する

GAS(Google App Script)でフォルダやファイル操作をする機会があったのでそのときのメモ。
Google Driveを扱う場合にはDriveAppを使用する。
[Google App Script Reference -Class DriveApp-](https://developers.google.com/apps-script/reference/drive/drive-app)
## 任意のフォルダを取得する。
getFolderByIdで指定したfolderIdのフォルダを取得出来る。

```
function myFunction() {
  var folder = DriveApp.getFolderById('*****'); // folderId
}
```
## 任意のフォルダの子フォルダを取得する。
子フォルダは、folderIdで指定したフォルダに対してgetFoldersで取得できる。
※getFoldersの戻り値はFolderIterator

```
function myFunction() {
  var folder = DriveApp.getFolderById('*****'); // folderId
  var childFolders = folder.getFolders();
}
```
## 任意のフォルダのファイルを取得する。
ファイルは、folderIdで指定したフォルダに対してgetFilesで取得できる。
※getFilesの戻り値はFileIterator

```
function myFunction() {
  var folder = DriveApp.getFolderById('*****'); // folderId
  var files = folder.getFiles();
}
```
## 取得したフォルダ、ファイルを操作する。
getFolders、getFilesで得られるのはIteratorなので、何か操作したい場合はhasnextやnextを用いる。

```
function myFunction() {
  var folder = DriveApp.getFolderById('*****'); // folderId
  var childFolders = folder.getFolders();
  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    // do something
  }
}
```
```
function myFunction() {
  var folder = DriveApp.getFolderById('*****'); // folderId
  var files = folder.getFiles();
  while (files.hasNext()) {
    var file = files.next();
    // do something
  }
}
```
TAPL9-1.純粋単純型付きラムダ計算(λ->)

```math
\begin{array}{l|l}
\begin{array}{llr}
構文\\
t ::= &             & 項：\\
      & x           & 変数\\
      & λx:T.t      & ラムダ抽象\\
      & t\;t        & 関数適用\\
v ::= &             & 値：\\
      & λx:T.t      & ラムダ抽象値\\
T ::= &             & 型：\\
      & T\text{->}T & 関数の型\\
Γ ::= &             & 文脈：\\
      & ∅           & 空の文脈\\
      & Γ,x:T       & 項変数の束縛\\
\\
\end{array}&
\begin{array}{l}
\begin{array}{cr}
評価 \hspace{240px} & \bbox[3px,border:1px solid black]{t  \longrightarrow t'}\\
\dfrac{t_1 \longrightarrow t_1'}
{t_1\;t_2 \longrightarrow t_1'\; t_2} & \text{(E-App1)} \\

\dfrac{t_2 \longrightarrow t_2'}
{v_1\;t_2 \longrightarrow v_1\;t_2'} & \text{(E-App2)} \\

(λx:T_{11}.t_{12}) v_2 \longrightarrow [x\mapsto v_2]t_{12} & \text{(E-AppAbs)} \\
\\
型付け\hspace{228px} & \bbox[3px,border:1px solid black]{Γ ⊢ t : T}\\
\dfrac{x : T ∈ Γ}
{Γ ⊢ x : T} & \text{(T-Var)}\\

\dfrac{Γ,x:T_1 ⊢ t_2 : T_2}
{Γ ⊢ λx:T_1.t_2 : T_1 \text{->} T_2} & \text{(T-Abs)}\\

\dfrac{Γ ⊢ t_1 : T_{11} \text{->} T_{12} \quad Γ ⊢ t_2 : T_{11}}
{Γ ⊢ t_1\;t_2 : T_{12}} & \text{(T-App)}\\

\end{array}

\end{array}
\end{array}
```

```prolog:tapl09_1.pl
/*
構文

t ::=       項：
  x         変数
  (x:T)->t  ラムダ抽象
  t $ t     関数適用
v ::=       値：
  (x:T)->t  ラムダ抽象値
T ::=       型：
  T->T      関数の型
Γ ::=       文脈：
  []        空の文脈
  [x:T|Γ]   項変数の束縛
*/
:- op(500, yfx, $).
:- op(900, xfx, [ : ]).
:- op(910, xfx, [ ⊢ ]).
:- op(920, xfx, [ ==>, ==>> ]).
:- op(1200, xfx, [ -- ]).
:- style_check(-singleton).
term_expansion(A -- B, B :- A).

v((_:_)->_).

% 評価 t ==> t'
\+v(T1), T1 ==> T1_
--%-------------------------- (E-App1)
T1 $ T2 ==> T1_ $ T2.

T2 ==> T2_
--%-------------------------- (E-App2)
V1 $ T2 ==> V1 $ T2_.

copy_term(X->T12, V2->T12_)
--%-------------------------- (E-AppAbs)
((X:T11)->T12) $ V2 ==> T12_.

% 型付け Γ ⊢ t : T
member(X : Ty, Γ)
--%------------------------------- (T-Var)
Γ ⊢ X : Ty.

[X:Ty1|Γ] ⊢ T2 : Ty2
--%------------------------------- (T-Abs)
Γ ⊢ ((X:Ty1)->T2) : (Ty1 -> Ty2).

Γ ⊢ T1 : (Ty11 -> Ty12), Γ ⊢ T2 : Ty11
--%---------------------------------- (T-App)
Γ ⊢ T1 $ T2 : Ty12.

T ==>> T3 :- T ==> T2, T2 ==>> T3.
T ==>> T.

run(T:ExpectedTy==>>ExprectedResult) :-
  [] ⊢ T : Ty,
  T ==>> T2,
  writeln(T:Ty==>>T2),
  Ty=ExpectedTy,
  T2=ExpectedResult.

:- run(((X:T)->X) : (T->T)==>>((X:T)->X)).
:- run(((X:(T->T))->X) $ ((Y:T)->Y) : (T->T) ==>> ((Y:T)->Y)).
:- halt.
```
JSにおける [] == ![] がわからなかったので、true に至る道を辿ってみました。

参考にしたページはこちらです。
- http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness


# 問題

```js:問題
[] == ![] // これはなんですか？
```

## 道のり1

まず、右辺が考えやすいので、右辺を考えます。


```js
Boolean([]) // => true
```

ですので、

```js
![] // => false
```

となります。よって

```js:書き換え1
[] == false
```

## 道のり2

ここで [11.9.3 The Abstract Equality Comparison Algorithm](http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3) によります。 ※ 以下、何度か参照します。

![スクリーンショット 2016-12-07 12.47.37.png](https://qiita-image-store.s3.amazonaws.com/0/45822/2ded5b08-4afc-21c3-08a4-077b520b2879.png)

> 7: If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

上の項目に該当すると思います。それに沿って右辺を number にします。

```js
Number(false) // => 0
```

ですので、次のように書き換えれます。

```js:書き換え2
[] == 0
```

## 道のり3

続いて

> 9: If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.

上に該当します。

ここで、挫折しました。 `ToPrimitive(x)` が全然分かりません。

しばらく迷子になった後、

以下の記述を [Equality comparisons and sameness](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) に出会いました。

> ToPrimitive(A) attempts to convert its object argument to a primitive value, by attempting to invoke varying sequences of A.toString and A.valueOf methods on A.

「ToPrimitive(A)は、 toString や valueOf メソッドをつかって、 A を primitive な値に変換しようとする。」と解釈しました。

ですので、以下の操作から、 [] の primitive値は "" となります。

```js:primitive値をもとめたい
[].valueOf() // => [] これは primitive じゃない
[].toString() // => "" これは primitive です
```

したがって、左辺を primitive にして以下のようになります。

```js:書き換え3
"" == 0
```


## 道のり4（おしまい）

最後に、

> 5: If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.

こちらに従うことで、

```js
Number("") // => 0
```

```js:書き換え4（おしまい）
0 == 0 // => true
```


以上です。ありがとうございました。
もう `apt-get` とか `apt-cache` とか書かなくていいんだよ

Ubuntu 14.04 から `apt` コマンドが標準で使えるようになってるから、もう

```
apt-get install なんちゃら
```

ってやらなくても

```
apt install なんちゃら
```

で行けるようになりましたね。楽ちん。


> Most used commands:
  list - list packages based on package names
  search - search in package descriptions
  show - show package details
  install - install packages
  remove - remove packages
  autoremove - Remove automatically all unused packages
  update - update list of available packages
  upgrade - upgrade the system by installing/upgrading packages
  full-upgrade - upgrade the system by removing/installing/upgrading packages
  edit-sources - edit the source information file
TAPL5-3. 型無しラムダ計算(λ) 

```math
\begin{array}{l|l}

\begin{array}{l}
構文\\
\begin{array}{llr}
t ::= &         & 項：\\
& x             & 変数\\
& \lambda x.t   & ラムダ抽象\\
& t\;t          & 関数適用\\
v::= &          & 値：\\
& \lambda x.t   & ラムダ抽象値\\
\end{array}
\end{array}&

\begin{array}{cr}
評価 \hspace{180px} & \bbox[3px,border:1px solid black]{t \longrightarrow t’} \\

\dfrac{t_1 \longrightarrow t_1’}
{t_1 \;t_2 \longrightarrow t_1’ \;t_2} & \text{(E-App1)} \\

\dfrac{t_2 \longrightarrow t_2’}
{v_1 \; t_2 \longrightarrow v_1 \; t_2’} & \text{(E-App2)}\\

(\lambda x.t_{12}) v_2 \longrightarrow [x \mapsto v_2]t_{12} & \text{(E-AppAbs)}\\
\\
\end{array}
\end{array}
```


```prolog:tapl05_3.pl
:- op(500, yfx, $).
:- op(920, xfx, [ ==>, ==>> ]).
:- op(1200, xfx, [ -- ]).
:- style_check(-singleton).
term_expansion(A -- B, B :- A).
/*
構文
t ::=     項：
  x       変数
  x -> t  ラムダ抽象
  t $ t   関数適用
v::=      値：
  x->t    ラムダ抽象値
*/

t(X) :- var(X).
t(X->T) :- var(X), t(T).
t(T1$T2) :- t(T1),t(T2).
v(X->T) :- var(X), t(T).

% 評価 t ==> t’

\+ v(T1), T1 ==> T1_
--%---------------------------------------- (E-App1)
T1 $ T2 ==> T1_ $ T2.

T2 ==> T2_
--%---------------------------------------- (E-App2)
V1 $ T2 ==> V1 $ T2_.

copy_term(X->T12, V2->T12_)
--%---------------------------------------- (E-AppAbs)
(X->T12) $ V2 ==> T12_.

T ==>> T3 :- T ==> T2, T2 ==>> T3.
T ==>> T.

run(T) :- T ==>> T2, writeln(T==>>T2).

:- run(X->X).
:- run((X->X) $ (Y->Y)).
:- halt.
```
ソフトウェア営業に技術力が必要な3つの理由

本記事は [アプレッソAdvent Calendar](http://qiita.com/advent-calendar/2016/appresso) 第9日目の記事にするつもりで書いていたものです。

当初はこちらを公開する予定でしたが、他に書きたいことができてしまったのでお蔵入りとなっていたものです。
せっかく書いたものですし、世の中の多くの営業マンに対して発信したいことでもあったので公開させていただくことにしました。
***
###**営業に求められるスキル**
ソフトウェア業界の営業にとって大切なスキルはどういったものでしょうか？

「コミュニケーション力」「業務知識」「提案力」など、人によって答えは異なると思いますし、正解は1つではないと思います。

今回はその中でも「技術力」についてお話したいと思います。
※決して「技術力」が一番大事だと思っているわけではありません。

「営業には技術力は必要ない！」「営業は技術を持ったエンジニアをアサインしたり段取りすることが仕事」とおっしゃる方もいらっしゃるとは思います。

私もデモや製品紹介のために技術力が必要だと言っている訳ではありません。
（それぐらいはメーカーの営業ならできて当然です）

では、なぜ私が技術力が必要だと思うのか？
理由は大きく3点あると思っています。順にお話したいと思います。
###**製品を作る**
まず 1つめの理由は「製品を作るため」です。

製品の機能を理解しお客様の課題に対する解決策を提案する、これは営業として当然できないといけないことです。

では、お客様の求めることが自社の製品ではできない場合、どうしたら良いでしょうか。
私が SIer の営業であればスクラッチ開発で補う、商社の営業であれば解決できる商品を探してきて提供する、それで良いと思います。

しかし、私はソフトウェアメーカーの営業です。したがって、「お客様の求めるものを正しく把握し、開発にフィードバックする」というのがとても重要な仕事です。

お客様が「こんな機能が欲しい！」と言ってる場合、営業は「その機能があると何故嬉しいのか？」「他の機能では何故いけないのか？」を正しく把握し、開発に伝える必要があります。
（このあたりの話は[去年土岐さんが書いてくれました](http://appresso.hatenablog.com/entry/2015/12/01/100326)ので、詳しくは触れません）

これができないと有名な↓の風刺画のようなことになります。
![20040516.gif](https://qiita-image-store.s3.amazonaws.com/0/129487/e9bb63c8-af42-acdc-d103-7e186e108377.gif)

ということで、「製品を作る」ためには営業が技術を理解していることはとても重要になります。

###**社内を牽制する**
2点目は「社内を牽制する」ということです。
こう書いてしまうととても感じが悪いですが、営業・開発間にかぎらず常に社内で刺激し合える関係というのが健全な組織だと思います。

ソフトウェアメーカーで仕事をしていると、当然のことですがそのソフトウェアに関しては自分たちが一番詳しくなります。そのため、お客様が自身の意図した通りにソフトウェアが動かない、と言ってきた場合には「お客様の使い方が理解できていないからだ」などとお客様の言っていることを疑いがちです。（もちろん、そういうケースもあります）

営業は社内ではお客様に一番近い場所にいます。そのため、お客様の状況を一番正しく把握できている可能性が高いです。

しかし、技術的なことが全くわからないと、お客様の言うことを社内へ、社内の開発・技術メンバーの言うことをお客様へ、そのまま伝えることしかできないため、伝言ゲームとなり結果として認識の齟齬が生まれ得ます。

ここで営業が技術的なことを理解できていると、
　・お客様の言ってる情報は正しいのか？
　・社内の開発・技術が言っていることはお客様への回答になっているのか？
を精査できるためトラブルを未然に防ぎ、早期の問題解決に繋がります。

先程書いたように 開発=>営業 の間でも同じことが言えると思っています。営業が行っている活動が適切なのか、もっと良い販売方法・提案方法があるのではないか、というのを開発側が助言できる組織はとても強くなると思います。

###**顧客の課題を発見する**
最後になりますが、これが一番大きな理由になります。
「お客様自身が気づいていない課題を発見する」という点が一番重要だと思います。

1番目の話とも通じる部分はありますが、「データ連携をしたいです」と言っているお客様に DataSpider を買ってもらうことは簡単です。
（「簡単ならもっと売り上げ伸ばせ」とか言わないでください・・・）

営業の本当の価値は「こんなところがデータ連携できるとこんなに便利になるのか」「言われてみればこんなことで無駄に時間を取られていたんだ」という、お客様自身が気づいていなかった課題に気づき、気づかせてあげることにあると思います。

これをやるためには、お客様の業務を良く理解することも当然必要ですし、その課題を解決するための方法についての知識が不可欠になります。

###**最後に・・・**
今年はハッカソンやハンズオンなど多くのエンジニア向けのイベントに参加しました。

「技術より営業の方が楽しいと思って営業をやっているのになんでこんなにイベントに出てるんだろう？」「技術的な知識が深まるとなんでこんなに楽しいんだろう？」と思い、振り返りながら書いてみました。

偉そうなことをたくさん書いてしまいましたが、アプレッソの営業はこんな気持ちで日々活動しているんだ、ということを知っていただけますと幸いです。
TAPL3.bigstep

```math
\begin{array}{l}
評価規則\\
\begin{array}{cr}
v \Downarrow v                             & \text{(B-Value)} \\
\dfrac{t1 \Downarrow true \quad t2 \Downarrow v2}
{if\;t1\;then\;t2\;else\;t3 \Downarrow v2} & \text{(B-IfTrue)} \\
\dfrac{t1 \Downarrow false \quad t3 \Downarrow v3}
{if\;t1\;then\;t2\;else\;t3 \Downarrow v3} & \text{(B-IfFalse)} \\
\dfrac{t1 \Downarrow nv1}
{succ t1 \Downarrow succ nv1}              & \text{(B-Succ)} \\
\dfrac{t1 \Downarrow 0}
{pred \; t1 \Downarrow 0}                  & \text{(B-PredZero)} \\
\dfrac{t1 \Downarrow succ \; nv1}
{pred \; t1 \Downarrow nv1}                & \text{(B-PredSucc)} \\
\dfrac{t1 \Downarrow 0}
{iszero t1 \Downarrow true}                & \text{(B-IszeroZero)} \\
\dfrac{t1 \Downarrow succ \; nv1}
{iszero \; t1 \Downarrow false}            & \text{(B-IszeroSucc)} \\
\end{array}
\end{array}
```

```prolog:tapl03_bigstep.pl
/*
構文

t ::=                項：
　true               定数真
　false              定数偽
　if(t,t,t)          条件式
  0                  定数ゼロ
  succ(t)            後者値
  pred(t)            前者値

v::=                 値：
　true               定数真
　false              定数偽
  nv                 数値
nv ::=               数値：
  0                  ゼロ
  succ(nv)           後者値

*/
:- op(920, xfx, [ ⇓ ]).
:- op(1200, xfx, [ -- ]).
:- style_check(-singleton).
term_expansion(A -- B, B :- A).

t(true).
t(false).
t(if(T1,T2,T3)) :- t(T1),t(T2),t(T3).
t(0).
t(succ(T)) :- t(T).
t(pred(T)) :- t(T).
v(true).
v(false).
v(NV) :- nv(NV).
nv(0).
nv(succ(NV)) :- nv(NV).

v(V)
--%---------------------------------------- (B-Value)
V ⇓ V.
T1 ⇓ true, T2 ⇓ V2, v(V2)
--%---------------------------------------- (B-IfTrue)
if(T1,T2,T3) ⇓ V2.
T1 ⇓ false, T3 ⇓ V3, v(V3)
--%---------------------------------------- (B-IfFalse)
if(T1,T2,T3) ⇓ V3.
T1 ⇓ NV1, nv(NV1)
--%---------------------------------------- (B-Succ)
succ(T1) ⇓ succ(NV1).
T1 ⇓ 0
--%---------------------------------------- (B-PredZero)
pred(T1) ⇓ 0.
T1 ⇓ succ(NV1), nv(NV1)
--%---------------------------------------- (B-PredSucc)
pred(T1) ⇓ NV1.
T1 ⇓ 0
--%---------------------------------------- (B-IszeroZero)
iszero(T1) ⇓ true.
T1 ⇓ succ(NV1), nv(NV1)
--%---------------------------------------- (B-IszeroSucc)
iszero(T1) ⇓ false.

run(T,V2) :- T ⇓ V, writeln(V), V=V2.

:- run(true,true).
:- run(if(true,false,true),false).
:- run(if(false,false,true),true).
:- run(if(if(true,false,true),if(true,false,true),if(true,false,true)),false).
:- run(0,0).
:- run(succ(0),succ(0)).
:- run(pred(succ(0)),0).
:- run(iszero(pred(succ(0))),true).
:- run(iszero(succ(0)),false).
:- halt.
```
swiftのenumについて(3.0.1)

## 背景
swiftの勉強を始めてみて、enum（列挙型）の仕様や使い方がよくわからなかったので、公式ドキュメントを読みながらまとめてみました。

[Appleの公式ドキュメント](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html#//apple_ref/doc/uid/TP40014097-CH12-ID145]）)を参考にしました。

## enumの概要
swiftのEnumerationsの説明の一行目には以下とあります。
>An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.

つまり、列挙型は関連する値の集合を共通するタイプとして定義し、それらの値を型安全に使用することができます、ということでしょうか。

## 仕様・使い方

### 基本の使い方

単純な形としては以下のように使うことができます。
・enum名の最初の文字は大文字で書く

```swift:swift
enum CompassPoint {
    case north
    case south
    case east
    case west
}

var cPoint = CompassPoint.north
print(cPoint) //north
```

１行で複数のケースを定義することもできます。

```swift:swift
enum Week {
    case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
var today = Week.monday
print(today) //monday

//enum型が代入された変数に対しては、別のケースを代入する場合はenum名を省くことができます。
today = .saturday
print(today) //saturday
```

enum型が入った変数には、そのenum型内で定義されているケースのどれかが入っているため、switch文と一緒に使うことで、Aの場合A+をする、Bの場合B+をするという処理が記述しやすくなります。

```swift:swift
enum Week {
    case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}

var today = Week.monday

switch today {
case .monday :
    //here
    print("Today is monday")
case .tuesday :
    print("Today is tuesday")
default:
    print("The day of today is unknown")
}
```

### 関連型enum（Associated Values）
[Appleの公式ドキュメント](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html#//apple_ref/doc/uid/TP40014097-CH12-ID145]）)では「Associated Values」と書かれていましたが日本語にするとどうなるのでしょうか。今回は関連型enumと訳しました。

関連型enumでは、定義したケースに関連する値を付けることができます。
株の取引における以下のようなケースを考えてみましょう。

```swift:swift
enum Trade {
    case Buy
    case Sell
}
func trade(tradeType: Trade, stock: String, amount: Int) {}
```

このような記述は間違いではありませんが、trade関数にenumのtradeTypeと一緒に渡すstockとamountは、caseがBuyにしろSellにしろ必ずついてくるもので、それを別々の引数として渡すことは不必要です。こういった場合、関連型enumを使うとスッキリと記述することができます。

```swift:swift
enum Trade {
    case Buy(stock: String, amount: Int)
    case Sell(stock: String, amount: Int)
}
func trade(type: Trade) {}

var action = Trade.Buy(stock: "Apple", amount: 100)
```
[参考サイト](https://appventure.me/2015/10/17/advanced-practical-enum-examples/)

enumに定義されるケースがクラスにおけるプロパティーを持つことができる、というようなイメージでしょか。

### 値型enum（Raw Values）

 値型enumの仕様は以下になる。
・デファルト値（raw value）の代入ができる
・全ての値は同じ型でなければならない
・型は文字列型、キャラ型、整数、浮動小数点型でなければならない
・全ての値はユニークでなければならない

```swift
enum Week : Int {
    case monday = 1
    case tuesday = 2
    case wednesday = 3
    //以下は型が違うのでコンパイルエラー
    //case thursday = "4"
    //以下はユニークにならないのでコンパイルエラー
    //case thursday = 3
}

//raw valueは以下のように.rawValueで取得できる。
var tomorrow = Week.monday.rawValue
```
Unity ParticleSystemで作った打ち上げ花火に音を付ける

[Unity ParticleSystemで打ち上げ花火(Unity5.5対応)](http://qiita.com/ELIXIR/items/f28c98196540e31d4fc8)で作った花火に音をつけたかったのですが、~~SubEmitterで機能するのはParticleSystemだけなので~~ParticleSystemだけでは完結できませんでした。

・まずベース（ひゅるるるの部分）についていたLoopを外します（つまり打ち上げ花火一つ毎にInstantiateする必要があります）。
![2016-12-07_121041.png](https://qiita-image-store.s3.amazonaws.com/0/59911/69367cc6-357a-4d93-9795-3af056552d1e.png)

・鳴らしたいAudioSourceのついたGameObjectを追加します。
![2016-12-07_121131.png](https://qiita-image-store.s3.amazonaws.com/0/59911/5a77f8c1-b685-e07d-ca3d-678bdf32c746.png)

・下記のソースコードを追加し、上記GameObjectをアタッチます。
![2016-12-07_121250.png](https://qiita-image-store.s3.amazonaws.com/0/59911/3503cff8-43d9-4a7a-aa3e-cfe24d4c33d9.png)

*[修正]dozeou_monさんにいただいたアドバイスを元にコルーチン化しました*

```FireworksSeed.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireworksSeed : MonoBehaviour {
    [SerializeField]
    private GameObject explodeAudioObj;
    private ParticleSystem seedPs;

    // Use this for initialization
    void Start () {
        seedPs = GetComponent<ParticleSystem>();
        StartCoroutine(ProgressCo());
    }

    // Update is called once per frame
    void Update () {
    }

    private int getSubEmitterParticleNum()
    {
        int ptNum = 0;
        ParticleSystem[] psArr = GetComponentsInChildren<ParticleSystem>();
        foreach (ParticleSystem ps in psArr)
        {
            ptNum += ps.particleCount;
        }
        return ptNum;
    }

    IEnumerator ProgressCo()
    {
        // ひゅるるる待ち
        while (seedPs.particleCount == 0)
        {
            yield return null;
        }
        // ひゅるるるの間は音の位置を移動
        while (seedPs.particleCount > 0)
        {
            ParticleSystem.Particle[] pps = new ParticleSystem.Particle[seedPs.particleCount];
            explodeAudioObj.transform.localPosition = pps[0].position;
            yield return null;
        }
        // 爆発待ち
        while (getSubEmitterParticleNum() == 0)
        {
            yield return null;
        }
        // 爆発音
        explodeAudioObj.GetComponent<AudioSource>().pitch *= Random.Range(0.8f, 1.2f);
        explodeAudioObj.GetComponent<AudioSource>().Play();
        // 消滅待ち
        while (getSubEmitterParticleNum() > 0)
        {
            yield return null;
        }
        // 消滅
        Destroy(gameObject);
    }
}

```
![2016-12-07_125250.png](https://qiita-image-store.s3.amazonaws.com/0/59911/2e6f36dd-405b-01e6-e157-6a1c8d9ef713.png)
socket.io-redis使用時にクライアント数を取得する

# 検証環境

* socket.io@1.5.0
* socket.io-redis@1.1.1

# 内容
socket.ioをシングルプロセスで起動してるときは以下でクライアント数を取得できる。

```js
logger.info(io.engine.clientsCount) // 1
```

socket.io-redisを使ってマルチプロセスで起動してセッション共有してるときは上記ではプロセスによって0が返ってくる。

以下のPRでクライアント数（というかクライアントID列）を取得できるようにしてくれてる。
https://github.com/socketio/socket.io-redis/pull/109

以下のようにすると取得できる。

```js
io.of('/').adapter.clients((err, clients) => {
  logger.info(clients) // [ 'Hi0cwijtw48cgIUTABAA' ]
  logger.info(clients.length) // 1
})
```
Office-Saas 連携No.2 ~ Excel からTwitter に連携してデータの取得や投稿をする方法

#Twitter API をExcel から利用#
CData のExcel Add-in for Twitter を使って、Excel から直接Twitter データに連携することができます。この記事では、自分のTwitter アカウントに出てくるtweet をエクセルに一覧表示させる方法、またExcel に表示したtweet テーブルに新しいTweet を書き込むことでTwitter に投稿する方法を説明します。

#CData Excel Add-in for Twitter の設定#
まずは[Excel Add-in for Twitter](http://www.cdata.com/jp/drivers/twitter/excel/) をダウンロードします。30日の無償評価版があります。
インストール後にExcel を開くと、CDATA タブとリボンができます。［Twitter］のアイコンをクリックします。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/152422/36951cd7-fa86-e1de-5ddb-bf5055ae8be6.png)
クリックすると、［接続ウィザード］が開きます。
ここにTwitter アカウントの認証情報を入力します。OAuth 2.0 認証です。
* OAuthClientId：アプリケーション設定のConsumer key に設定。
* OAuthClientSecret：アプリケーション設定のConsumer secret に設定。
* CallbackURL：アプリケーション設定で指定したコールバックURL に設定。
詳細は製品ヘルプの［twitter への接続］
(http://cdn.cdata.com/help/GTB/xls/pg_connectingtotwitterxls.htm) を参照してください。
今回は更新などを行うので、挿入と更新にチェックを入れて権限を付与することを忘れないでください。

認証情報の入力が完了したら、OK をクリックして接続を確立します。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/152422/242bf406-1024-6df6-d728-0a8416138e0e.png)
#Excel からTweet テーブルの取得#
［CDataデータ選択］ウィザードにて、テーブルを選択します。Twitter API のエンドポイントがテーブルにモデル化されており、ドロップダウンリストから取得を希望するテーブルを選択します。　ここでは［Tweetsテーブル］を選択します。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/152422/8872549a-c1fd-03f2-8c37-121c5cc36c99.png)

選択するとTweetsテーブル内のカラムが表示されます。取得したい項目をチェックして選択します。選択すると自動的に［クエリー(Q)］欄にSQL クエリが作成されます。Where 句などを書き込むことも可能です。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/152422/043b7c35-c50a-3a24-92d2-0ff8aa7e3d3e.png)
テーブル選択、カラム選択、クエリ設定が終わったら、OK をクリックします。Excel 上にTwitter のtweet がテーブルとなってロードされました。

![5.png](https://qiita-image-store.s3.amazonaws.com/0/152422/5573183c-6b69-833c-e0b0-8eb9c48409ef.png)

#ExcelからTwitter にツイートする#
取得したテーブルの［Text］カラムに新しいテキストを入力して、CDATA リボン内の［行の挿入］をクリックすると、Twitter にtweetをすることができます。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/152422/f77b2159-2647-e44d-e986-b0d5287e51d5.png)

ブラウザのTwitter 画面で投稿を確認します。
![スクリーンショット (154).png](https://qiita-image-store.s3.amazonaws.com/0/152422/e28d206d-d159-8907-3b3a-46355478d88b.png)
docker Image build時のyum connection timeout を解消する方法

# 発生した事象

Dockerfileをdocker buildした際に`yum`で詰まりました。

エラーログはこちら。

```
[0m[91mhttps://[IP]/mypath/rhel/7Server/repodata/repomd.xml: [Errno 12] Timeout on https://[IP]/mypath/rhel/7Server/repodata/repomd.xml: (28, 'Connection timed out after 30001 milliseconds')
Trying other mirror.
[0m[91m

 One of the configured repositories failed (myrepo Repo),
 and yum doesn't have enough cached data to continue. At this point the only
 safe thing yum can do is fail. There are a few ways to work "fix" this:

     1. Contact the upstream for the repository and get them to fix the problem.

     2. Reconfigure the baseurl/etc. for the repository, to point to a working
        upstream. This is most often useful if you are using a newer
        distribution release than is supported by the repository (and the
        packages for the previous distribution release still work).

     3. Disable the repository, so yum won't use it by default. Yum will then
        just ignore the repository until you permanently enable it again or use
        --enablerepo for temporary usage:

            yum-config-manager --disable reponame

     4. Configure the failing repository to be skipped, if it is unavailable.
        Note that yum will try to contact the repo. when it runs most commands,
        so will have to try and fail each time (and thus. yum will be be much
        slower). If it is a very temporary problem though, this is often a nice
        compromise:

            yum-config-manager --save --setopt=reponame.skip_if_unavailable=true

failure: repodata/repomd.xml from myrepo: [Errno 256] No more mirrors to try.
https://[IP]/mypath/rhel/7Server/repodata/repomd.xml: [Errno 12] Timeout on https://[IP]/mypath/rhel/7Server/repodata/repomd.xml: (28, 'Connection timed out after 30002 milliseconds')
```

## 環境

* OS: RHEL7.2
* docker:

```
# docker version
Client:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-44.el7.x86_64
 Go version:      go1.4.2
 Git commit:      7ffc8ee-unsupported
 Built:           Fri Jun 17 15:27:21 2016
 OS/Arch:         linux/amd64

Server:
 Version:         1.10.3
 API version:     1.22
 Package version: docker-common-1.10.3-44.el7.x86_64
 Go version:      go1.4.2
 Git commit:      7ffc8ee-unsupported
 Built:           Fri Jun 17 15:27:21 2016
 OS/Arch:         linux/amd64
```

# 原因

Dockerは外部と通信する際にiptablesのNATテーブルにルールを追加し外部への通信を実現します。ここで罠なのが、iptablesの設定はメモリ上にしか載っていないためiptablesのみをrestartするとdockerが設定したNATルールが綺麗さっぱり消え去ります。

そのため、yumで使われる外部通信向けのNATルールもないのでyumが失敗するわけです。

そのため再度Dockerのルールをiptablesに載せてあげましょう。

# 解決策

dockerサービスをrestartする。

`systemctl restart docker`



※「あくまで今回の事象ではこうだったよ」という切り口の一つです。
[C++]ある値がvector内の要素に含まれているか否か判定する

vector内にある要素が含まれているか否かを知りたいことがよく有りました。
そういえばC++だとfindとかなかった（ような気がする）ので、下記のような関数に投げてあげると便利だったのでメモ。
例はint型で固定しています。

```c++
int vector_finder(std::vector<int> vec, int number) {
  auto itr = std::find(vec.begin(), vec.end(), number);
  size_t index = std::distance( vec.begin(), itr );
  if (index != vec.size()) { // 発見できたとき
    return 1;
  }
  else { // 発見できなかったとき
    return 0;
  }
}
```

使用例としてはこんな感じ。

```c++
int main(int argc, char const *argv[]) {
  std::vector<int> data{4, 6, 5};
  std::cout << vector_finder(data, 3) << std::endl;
  // => 0
  std::cout << vector_finder(data, 6) << std::endl;
  // => 1
  return 0;
}
```
DartでChrome拡張機能でBackgroundとContent Scriptの通信をする

# 背景 
DartでChrome拡張機能を作るときには[chrome](https://pub.dartlang.org/packages/chrome)パッケージを使うと思いますが
sendMessageAPI周りが正しく動かないのであきらめてdart:jsパッケージを使って手動で解決する方法です。

# 正しく動かないコード

```content.dart
main() async {
  var res = await chrome.runtime.sendMessage('soy source');
  print(res);
}
```

```background.dart
main() async* {
  await for (var msgEvent in chrome.runtime.onMessage) {
    print(msgEvent.message);
    msgEvent.sendResponse('hello' + msgEvent.message);
  }
}
```
Uncaught Error: Could not establish connection. Receiving end does not exist.(...)というエラーが出ます。
<img width="532" alt="error.png" src="https://qiita-image-store.s3.amazonaws.com/0/100021/a6ee2170-2e36-2272-802d-a920143f05ef.png">

# 動くコード
context["chrome"]からメッセージング用のAPIを取り出して使います。
## Content Script -> Background -> Content Script
```content2.dart
void main() {
  context['chrome']['runtime'].callMethod('sendMessage',
      [ "soy source", (result) => print(result)]);//二秒後に "hello tab: xxx name:soy source" と表示されます。
}
```

```background2.dart
void main() {
  var jsObject = context['chrome']['runtime']['onMessage'];
  (jsObject is JsObject ? jsObject : new JsObject.fromBrowserObject(jsObject))
      .callMethod('addListener', [onMessage]);
}

bool onMessage(request, sender,JsFunction response) {
  var tabID = new JsObject.fromBrowserObject(sender)["tab"]["id"];
  new Timer(new Duration(seconds: 2), () {
    response.apply(["hello tab: $tabID name:$request"]);
  });
  return true; //trueにしないと非同期でレスポンスを返せません。
}

```

## Background -> Content Script -> Background
```content3.dart
void main(){
  var jsObject = context['chrome']['runtime']['onMessage'];
  (jsObject is JsObject ? jsObject : new JsObject.fromBrowserObject(jsObject))
      .callMethod('addListener', [onMessage]);


}

void onMessage(request, sender,JsFunction sendResponse) {
  print("request $request");
  sendResponse.apply(["hey $request"]);
}
```

```background3.dart
void main() {
  new Timer(new Duration(seconds: 5),(){ //拡張機能をリロードしてから五秒以内にContent Scriptが挿入されているページをリロードしないとうまく動きません。
    context['chrome']['tabs'].callMethod( 
        'sendMessage', [ 376, "マヨネーズ",(result) => print(result)]); //"hey マヨネーズ"と表示されます
  });
}
```