OmniAICreator/Qiita-1.07M huggingface dataset:
150+ posts on Qiita

Somehow or another, I've now reached 150+ posts on Qiita, posting only in English and quite a lot more frequently over the last three years. I like using this site, and its simple view count information gives me some idea of the popularity and exposure of my posts over time.

## Cons of English-only usage

Because all of my readers are reading in English, quite many of them harass me with comments about the word wrapping behavior. The fix is fairly simple:

```js
document.querySelector('.it-MdContent').style.wordBreak='normal'
```

But I don't quite know enough about how word wrapping behavior works for Japanese, so I don't know for sure if this can be applied broadly.

## なして日本語書かない

I am quite lazy and have not bothered to improve my Japanese. I visit Japan somewhat often, but living in Europe, I normally only use Japanese to watch YouTube videos. I will speak Japanese if spoken to, but generally I do not switch to Japanese unless I have to.

However, I really hope if people have some questions I can answer, they will ask me in either Japanese or English on Twitter. Please don't worry about "英語能力" or something, feel free to write anything.

## To another 50

I guess I will keep writing on Qiita as long as it is still here. I mostly write to be able to reference material myself, but hopefully some parts of some of my articles have been useful for others.
Shellの基本を学ぶ（２）Variables

先ほどのエントリにも書いたが、変数についてのアップデート

# 変数の型

Bash Variables に型は無い。単に String としてストアされる。

# 変数名

Case sensitive で大文字だと、pre-defined 小文字だと、自前というのが基本ルールらしい。文字、数字とアンダースコアが許されている。先頭文字は、文字、もしくはアンダースコア


# スペース

スペースは bash に置いて特別な意味を持つ。例えば次のコマンド。スペースを入れて変数を定義すると、下記の例では２つのファイルが出来ている。スペースを含むものはクオートが必要

```bash
$ files="file1 file2"
$ touch $files
$ ls
file1	file2
```

# 値の取得

`$` をつける

```bash
$ foo=bar
$ echo $foo
bar
```
# 大文字の変数を上書きしない

pre-defined の変数があり、大文字になっているので、気づかずに上書きしないこと。例えば `PATH, HOME, SECONDS, IFS` などがある。スクリプトでは、小文字スタートのものを使うと良い。

# 変数の読み込み

`read` 関数を使うと、ユーザに入力を求めて変数に代入する。現在のシェルと同じプロセスで実行される

```bash
read note
echo $note
```
# 変数の区切りを明確にする

`$variablename` は、`${variablename}` の省略形なので、一部のみを置き換えたいときは、次のようにする。`$(some)` は、Command Substitution. コマンドを実行した結果に置き換える。

```bash
date=$(date)
read -p "Your note: " note
echo $date: $note >> ~/${topic}notes.txt
```
## 結果

```bash
$ ./tn foo
Your note: bar
invincible:experiment ushio$ cat ~/foonotes.txt
Wed Mar 13 15:26:13 PDT 2019: bar
```
# Debug

最初の hashbang の行に

```bash
#!/bin/bash -x
```

もしくがデバッグしたい行に

```bash
 :
set -x
read -p "Your note: " note
echo $(date): $note >> ~/${topic}notes.txt
set +x
 :
```

## 結果

実行結果が見えるようになる

```bash
$ ./tn foo
+ read -p 'Your note: ' note
Your note: bar
++ date
+ echo Wed Mar 13 15:51:45 PDT 2019: bar
+ set +x
Note saved: bar
```

# クオートのエスケープ

`\` が有効

```bash
$ foo='bar baz'
$ buzz=\'$foo\'
$ echo $buzz
'bar baz'
```


# コマンドを探す

```bash
$ builtin
$ help read 
```
1. Google Kubernetes Engine（GKE）でJavaのWebモジュールをサッと動かしてみる

# はじめに
kubernetesはどういうものか軽く知ろうと思い、ひとまずGKEで簡単なWebモジュールを動かしてみました。
本記事の内容についてセキュリティや運用面、最適化等の考慮が抜けている箇所が多々あります。ご了承ください。

<< 環境 >>（2019年3月9日現在）
gkeマスターのバージョン：1.11.7-gke.4
jdk：openjdk-11.0.2
gradle：gradle-5.2.1
tomcat：apache-tomcat-9.0.17
DB：PostgreSQL-9.6 (cloud SQL)

<< 記事の構成 >>
1から順に読み進めてください。4で完結です。
1. [Google Kubernetes Engine（GKE）でJavaのWebモジュールをサッと動かしてみる](https://qiita.com/Turtle-child-No2/items/a5260ed94f01ccd5cfec)
2. [Dockerイメージの作成とRegistry登録](https://qiita.com/Turtle-child-No2/items/b8c307eb652e42420f7a)
3. [Webモジュールからアクセスするデータベースを作成](https://qiita.com/Turtle-child-No2/items/0fd09117beb74e848146)
4. [マニフェストの作成とWebモジュールの実行](https://qiita.com/Turtle-child-No2/items/23982059d188e44618df)
## 1-1. クラスタの作成
### 手順1-1.1
まずはWebモジュールを動かすクラスタを作成します。
Google Cloud Platform（GCP）の管理画面上部にてプロジェクトを選択します。
サイドメニューの「Kubernetes Engine -> Engine」を選択します。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/263269/290f4e70-6dc9-3aec-6b15-32a78b819deb.png)
### 手順1-1.2
少々待たされた後に「クラスタを作成」を押下します。
![002.png](https://qiita-image-store.s3.amazonaws.com/0/263269/008c7e15-a47f-c587-19cc-1447e02032d0.png)
![004.png](https://qiita-image-store.s3.amazonaws.com/0/263269/bd48f5b8-64be-fda8-4541-fae234d032a3.png)
### 手順1-1.3
サイドメニューの「標準クラスタ」を選択します。
![005.png](https://qiita-image-store.s3.amazonaws.com/0/263269/f5917e7f-072f-57bf-cf6f-881fcdbe59bf.png)
### 手順1-1.4
ロケーションタイプは「リージョン」、リージョンは「us-central1」、default-poolのノード数は「1」を選択します。
![006.png](https://qiita-image-store.s3.amazonaws.com/0/263269/92273be9-9170-26ce-2053-a221f5212c07.png)
### 手順1-1.5
「高度な編集」を押下し詳細画面にて管理の「自動アップグレードを有効化」と「自動修復を有効化」のチェックを外します。詳細画面の「保存」を押下します。
![007.png](https://qiita-image-store.s3.amazonaws.com/0/263269/92c4a03c-2333-8a24-ab25-4b92f7416043.png)
![008.png](https://qiita-image-store.s3.amazonaws.com/0/263269/7e3679a8-3d53-44d5-4478-24cc6752fd09.png)
![009.png](https://qiita-image-store.s3.amazonaws.com/0/263269/97d49236-5ad1-17c5-14c5-17e4956ef5fb.png)
### 手順1-1.6
最後に「作成」を押下します。
![010.png](https://qiita-image-store.s3.amazonaws.com/0/263269/72f72cc4-310a-eccd-25cd-5144a7333163.png)
### 手順1-1.7
しばらくするとクラスタの作成が完了します。
以上でGKEのクラスタの作成が終わりました。
![011.png](https://qiita-image-store.s3.amazonaws.com/0/263269/d523c3d8-223d-efdb-09a0-6247f1745e82.png)
### 手順1-1.8
クラスタを構成するノードを確認してみましょう。
サイドメニューの 「Compute Engine -> VMインスタンス」 を選択します。
![012.png](https://qiita-image-store.s3.amazonaws.com/0/263269/c15fef64-b3d5-48cd-aa10-14bd9741fada.png)
### 手順1-1.9
3つVMが作成されています。先ほどクラスタを作成する際に「リージョン」を選択し、さらにノード数（ゾーンごと）に「1」を入力したので、リージョンに属する3つのゾーン毎に1つノードが作成されました。
クラスタを構成するノードがゾーン別に作成されることでサービス停止のリスクを軽減しています。
![013.png](https://qiita-image-store.s3.amazonaws.com/0/263269/6c154304-6c95-ecd3-3d60-de92e22b3e96.png)
以上
３慣性モデルで工作機械の制御系を設計する(1)モデル定義

このようなモデルで制御系を設計します。
<img width="573" alt="スクリーンショット 2019-03-14 20.37.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/211702/c415937f-2b20-c864-7790-8e307342fba3.png">
実際のハードウェアとしては、３軸のNCフライス盤を想定しています。
今時の流行りだと３Dプリンタなのかもしれません。
直交３軸の機械の１軸分だと思ってください。

###なぜ３慣性モデルか
　モータ、ボールネジ、直動部の３慣性でモデル化しました。
　モータからツールのある手先までをモデル化する場合、ボールネジから直動部まで剛体締結として１つの慣性でモデル化する場合もあるのですが、今回は２つの理由から３慣性にしました。
　１つはリニアエンコーダの取り付け位置をボールネジの位置に設定するためです。HDDのモータなんかだと、一番先端のヘッドが位置センサも兼ねているので、フルクローズドフィードバックが可能ですが、工作機械の場合はエンコーダから先端の手先までが長く、セミクローズドフィードバックで設計する必要があるためです。
　もう１つはさらに上に乗っかる軸を想定しました。NCフライス盤は３軸がシリアルにY軸の上にX軸、その上にZ軸が乗っかるので、上の軸が乗っかっているイメージです。

###定義
Tm：モータのトルク[N*m]
Jm：モータの慣性モーメント[kg*m^2]
θm：モータの回転角[rad]
Dmb：モータとボールネジの間の粘性摩擦[N*m*s/rad]
Kg：ボールネジとモータの間のねじり剛性：[N*m/rad]
Jb：ボールネジの慣性モーメント[kg*m^2]
θb：ボールネジの回転角[rad]
Dbt：ボールネジと直動部の粘性摩擦[N*m*s/rad]
Kt：ボールネジと直動部の間の剛性：[N/m]
Mt：直動部の質量[kg]
xt：直動部の移動量[rad]


###目的
　今回作ったモデルはモータトルクTmを生成して、直動部の移動量xtを制御することになります。
　モータトルクの前には工作機械の移動パターンが定義されていて、時系列で移動パターンが渡されて、それに合わせてxtが動くような制御系を通してモータトルクTmが出力されます。


###制限
　フィードバックに使える信号を決めます。
　xtが使えれば一番楽なのですが、xtには工具などが鎮座してますので、xtは観測できません。

- モータにはロータリーエンコーダが付いているのでθmが観測できます。
- ボールネジの回転角θbはリニアエンコーダで観測できます。(R*θbが観測可能)

###まとめ
今回は直交３軸の機械の３慣性モデルの定義を行いました。
次回は今回定義した力学モデルについて説明していきます。
とあるエンジニアの問題意識 2019-03-13


# 子供の頃のゲームのやり方は、本当に エンジニア の気質に現れると思っている。
いや、物事に取り組む時の姿勢全般に関係すると言おうか。今の職場でもかつてゲームにドハマリしていたスーパーエンジニアがいる。特に戦略系のゲームと、エンジニア的思考の相性が良いように思う。 <https://t.co/KEBW8No3i6>。

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/766








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
kintone Café で kintone SDK のデモに刺激され、kintone API SDK for Node.js を使って見た。

先日、[kintone Café 浜松 Vol.16](https://www.kintonecafe.com/activities/4131) に参加した際に、ゲストスピーカーのサイボウズ 後迫さんが kintone SDK の話とデモを見せてくれました。
それに、刺激されて [kintone API SDK for Node.js](https://developer.cybozu.io/hc/ja/articles/360000511243) を使ってアプリの一覧情報を取得して見ました。

# インストールと設定
まずは [Node.js](https://nodejs.org/ja/) を macやPCにインストールして下さい。
今回はローカルにNodeのパッケージをインストールしていきます。

作業用のディレクトリを作成します。
次に、`npm init` してから（質問には全てEnter）、`npm install --save kintone-nodejs-sdk` として作業用のディレクトリにNodeパッケージをインストールします。

今回のサンプルコードでは、環境変数を [dotenv](https://www.npmjs.com/package/dotenv) を使って 環境設定ファイルから読み込みますので、そちらも `npm install --save dotenv` してインストールします。

# サンプルコード
kintoen アプリ情報の一覧を取得する [getApps(offset, limit)](https://kintone.github.io/kintone-nodejs-sdk/reference/app/#getappsoffset-limit) モジュールのサンプルコードです。
とりあえず、接続して全件取得するだけです。ここまでくれば後は何なりと、CSVに落とすもよし。

```javascript

require('dotenv').config();
const kintone = require('kintone-nodejs-sdk');
const env = process.env;

// Define Authentication object
let kintoneAuth = new kintone.Auth();
let username = env.USER_NAME;
let password = env.PASSWORD;
kintoneAuth.setPasswordAuth(username, password);

let DomainName = env.DOMAIN;
let kintoneConnection = new kintone.Connection(DomainName, kintoneAuth);
let kintoneApp = new kintone.App(kintoneConnection);

function fetchApps(optOffset, optLimit) {
    let offset = optOffset || 0;
    let limit = optLimit || 100;

    kintoneApp.getApps(offset, limit)
    .then((rsp) => {
        let apps = rsp.apps;
        if (apps.length === 100) {
            console.log(apps);
            return fetchApps(offset + 100, limit);
        }
        console.log(apps);
    })
    .catch((err) => {
        // This SDK return err with KintoneAPIExeption
        console.log(err.get());
    });

}

fetchApps();

```

# 実行結果（一部）

```
[ { appId: '1',
    code: '',
    name: '顧客管理ハンズオン',
    description: '<div><br /></div>',
    createdAt: '2017-06-24T08:36:29.000Z',
    creator: { code: '20170701', name: 'アプリ管理者' },
    modifiedAt: '2017-06-25T13:08:46.000Z',
    modifier: { code: 'Administrator', name: 'Administrator' },
    spaceId: null,
    threadId: null },
  { appId: '2',
    code: '',
    name: '日報ハンズオン',
    description: '<div><br /></div>',
    createdAt: '2017-06-24T09:32:24.000Z',
    creator: { code: '20170701', name: 'アプリ管理者' },
    modifiedAt: '2017-06-25T00:44:30.000Z',
    modifier: { code: 'Administrator', name: 'Administrator' },
    spaceId: null,
    threadId: null },
...
```

# 説明
使いたいのは、getApps() だけなのですが、それには前処理として下記の段階が必要です。

 1. 認証設定 [kintone.Auth()](https://kintone.github.io/kintone-nodejs-sdk/reference/authentication/)
 2. 接続設定 [kintone.Connection()](https://kintone.github.io/kintone-nodejs-sdk/reference/connection/)
 3. アプリ情報取得 [kintone.App()](https://kintone.github.io/kintone-nodejs-sdk/reference/app/)

kintone REST API の制限で100件づつの取得になりますので、100件以上あるときは再帰処理をして全件取得しています。

# まとめ
利用したいモジュールまでに、段階を踏まないといけないのが少し煩雑でしょうか。
ラッパーモジュールが欲しいですね。
Swift Int.randomの分散具合

# 概要
1〜2000のランダム値の分散具合を調べる。
# ソース
Playgroundで実行

```swift
import Foundation

for _ in 1...20 {
    var select = [Int](repeating:0, count:2000)
    for _ in 1...2000 {
        let selectNo = Int.random(in: 1...2000)
        select[selectNo - 1] = select[selectNo - 1] + 1
    }
    print("0 : \(select.filter({i in i == 0}).count) 2:\(select.filter({i in i == 2}).count) >=3:\(select.filter({i in i >= 3}).count)")
}
```

選択されないものが700くらい。
意外と分散されない
# 結果

```tex
0 : 734 2:376 >=3:152
0 : 733 2:365 >=3:158
0 : 764 2:397 >=3:162
0 : 766 2:379 >=3:172
0 : 735 2:374 >=3:156
0 : 729 2:360 >=3:163
0 : 743 2:389 >=3:159
0 : 728 2:335 >=3:176
0 : 752 2:384 >=3:165
0 : 740 2:374 >=3:163
0 : 727 2:358 >=3:163
0 : 747 2:381 >=3:164
0 : 750 2:363 >=3:164
0 : 758 2:363 >=3:174
0 : 722 2:374 >=3:152
0 : 743 2:356 >=3:166
0 : 739 2:346 >=3:168
0 : 721 2:357 >=3:162
0 : 749 2:354 >=3:171
0 : 743 2:390 >=3:159
```
[xcode] Automatic signing is unable to resolve an issue with the "プロジェクト名" target's entitlements.

# なんか突然エラーになった！(2019/3/13)
また認証周りでエラーが発生した...なんだこれ...
![image.png](https://qiita-image-store.s3.amazonaws.com/0/262908/2cf18d09-b53b-114a-288a-f4e7b6fbd6b6.png)

# 調べるとappleのサーバーの不具合らしい
は？なんやねんそれ！！
多数の人が同じ問題に直面してるらしい
待ってれば直るでしょうとのこと
それにしてもAppleの認証周りのめんどくささどうにかならんのか...

https://stackoverflow.com/questions/55132628/provisioning-profile-doesnt-include-the-application-identifier-and-keychain-acc
https://teratail.com/questions/179202
言語不問で実装する高速な移動平均処理

# はじめに
移動平均処理は色々な場面で出てきます。単純に実装すると、愚直に計算する畳み込み積分と同じ計算量になるので、少し工夫して高速化してみます。

# 移動平均処理とは
基本的な移動平均処理では1サンプルずつ移動しながら平均を求めていきます。画像処理で言えばぼかし処理の一種で、音声処理で言えばローパスフィルタの一種です。
FIRフィルタとして考えると、全ての係数が$\frac{1}{N}$のカーネルによる畳み込み（convolution）です。

以下は単純な実装例です。

```c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    #define WINDOW_SIZE (2000)
    #define NUM(fixed_array) ((int)(sizeof(fixed_array) / sizeof(fixed_array[0])))
    #define NUM_PROCESSED (NUM(samples) - WINDOW_SIZE + 1)
    int samples[20000];
    float processed[NUM_PROCESSED];
    int i, j;

    /* 乱数生成 */
    srand(1);
    for (i = 0; i < NUM(samples); i++) {
        samples[i] = rand() % 10;
    }

    /* 移動平均処理 */
    for (i = 0; i < NUM_PROCESSED; i++) {
        int sum = 0;
        for (j = 0; j < WINDOW_SIZE; j++) {
            sum += samples[i + j];
        }
        processed[i] = (float)sum / WINDOW_SIZE;
    }

    /* 結果を表示 */
    for (i = 0; i < NUM_PROCESSED; i++) {
        printf("%f\n", processed[i]);
    }

    return 0;
}
```

二重ループになっているところが重いです。
WINDOW_SIZE=2000はやりすぎにしても、samplesの要素数20000は少ない方で、音声データなんかだと１秒48000サンプルだったり、画像データだと1920x1080x3ピクセル/フレームだったりします。


# 高速化のアイディア
平均値の元となる総和に注目すると、窓をスライドするたび、窓から出ていく一番古いサンプルの値を総和から減じて、新しく窓に入ってくるサンプルの値を加えることで更新できそうなことがわかります。

データ構造としてはキュー（Queue）ですね。

でもキューなんて実装していられないので、単純に最初の移動平均値を求めたら、あとは総和を更新しながら処理していく形にしてみます。

```c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    #define WINDOW_SIZE (2000)
    #define NUM(fixed_array) ((int)(sizeof(fixed_array) / sizeof(fixed_array[0])))
    #define NUM_PROCESSED (NUM(samples) - WINDOW_SIZE + 1)
    int samples[20000];
    float processed[NUM_PROCESSED];
    int i, j;
    int sum = 0;

    /* 乱数生成 */
    srand(1);
    for (i = 0; i < NUM(samples); i++) {
        samples[i] = rand() % 10;
    }

    /* 移動平均処理 */
    for (j = 0; j < WINDOW_SIZE; j++) {
        sum += samples[j];
    }
    processed[0] = (float)sum / WINDOW_SIZE;

    for (i = 1; i < NUM_PROCESSED; i++) {
        sum -= samples[i - 1];
        sum += samples[i + WINDOW_SIZE - 1];
        processed[i] = (float)sum / WINDOW_SIZE;
    }

    /* 結果を表示 */
    for (i = 0; i < NUM_PROCESSED; i++) {
        printf("%f\n", processed[i]);
    }

    return 0;
}
```

これなら、最初の窓処理は窓サイズ分の処理負荷を避けられないものの、それ以降は窓サイズに関係なく加算2回と除算1回で移動平均値を求められるので、計算オーダーはほぼ$O(n)$だと言えそうです。

# おわりに
処理負荷がどれだけ改善したかは、面倒なので計測しません。2 $<$ WINDOW_SIZEであれば、後者の実装の方が多分速いです。あと、領域外アクセスやコーナーケースについては精査していません。

移動平均処理を畳み込み積分の特殊な場合と考えると、ここで紹介した高速化方法は一般化した畳み込み積分に応用できません。

それでも、移動平均自体はよく用いられる処理なので、特別に高速化する方法を知っていると、いざという時に役立つかもしれません。
Interactiveなグラフのフォーマット

#目的
1. 筆者がjupyter-notebookの使い方を覚えるために記述する
1. 様々なデータで応用できるテンプレートとする
1. もっと便利なツールあるよね（笑）

#内容
実際に使用する際は、parameterとresultの部分を実データに置き換えれば良い
Jupyter-notebookで実行すべし（labでは動かなかった）


## setting
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from ipywidgets import interact
import seaborn as sns
```


```python
%matplotlib inline
plt.style.use('bmh')
```



## parameter preparation
```python
#data numbers
n = 10000
```


```python
#parameter setting
x1 = np.random.randn(n) + 120.0
x2 = 1.3 * np.random.randn(n) + 110.0
x3 = 1.8 * np.random.randn(n) + 100.0
x4 = 0.5 * np.random.randn(n) + 90.0
x5 = 0.2 * np.random.randn(n) + 8.0
x6 = 0.3 * np.random.randn(n) + 70.0
```

```python
temp_dict = dict(x1=x1, x2=x2, x3=x3, x4=x4, x5=x5, x6=x6)
df = pd.DataFrame(temp_dict)
```

```python
import cufflinks as cf
cf.go_offline()

df.iplot()


```
![newplot.png](https://qiita-image-store.s3.amazonaws.com/0/312064/f5cc10f4-73ab-8898-100d-b81a974c2771.png)


### result preparation
```python
result_data = (10 * (x1 - 120) + 0.5 * (x2 - 110) ** 3 - np.exp((x3 - 102)) -  10 * (x4 - 90) + 15 *(x5 - 8.0) + -1 * (x6 - 70.0)) / 30 + 100
```


```python
sr_res = pd.Series(result_data, name='res')
df_res = df.join(sr_res, how='right')
```


```python
df_res.plot(kind='hexbin', x='x1', y='x2', C='res')
```
![output_9_1.png](https://qiita-image-store.s3.amazonaws.com/0/312064/a1a62a11-6a70-291e-df43-2a6b5f6b48b4.png)


## plot


```python
pg = sns.pairplot(df_res)
```
![output_11_0.png](https://qiita-image-store.s3.amazonaws.com/0/312064/c5826ad0-804d-b692-4af6-62c344bec884.png)


### interactive plot


```python
para_list = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6']
```

```python
import plotly
plotly.offline.init_notebook_mode(connected=False)
```

```python
@interact(para1=para_list, para2=para_list)
def plot_data(para1, para2):
    fig2, ax = plt.subplots(1,2, figsize=(10,5))
    ax[0].scatter(x=df_res.loc[:, para1], y=df_res.loc[:, 'res'], s=0.3)
    ax[0].set_xlabel(para1)
    ax[0].set_ylabel('Result')
    ax[0].set_title('Parameter Dependency')
    
    df_res.plot(kind='scatter', x=para1, y=para2, c='res', ax=ax[1], cmap='inferno')
    ax[1].set_xlabel(para1)
    ax[1].set_ylabel(para2)
    ax[1].set_title('Two Parameter Correlation')
    plt.tight_layout(w_pad=5)
    
    plotly.offline.iplot_mpl(fig2)
    

```
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/312064/0c17dc29-18de-ca89-78b6-cfa2b83b1d1c.png)
そもそもエンジニアって勉強しないとダメなんやって気づいた話

###ごあいさつ
初めまして、なかむらです。
東京で狂ったように人身売買されているエンジニア（）です。
もうすぐ新卒で入って2年経つしそろそろSier脱出すっかー、くらいのノリで今日からそろそろ本腰を入れて勉強しようと思ったので勢いでQiitaのアカウント作成しました。Markdown死ぬほど苦手なんでクソ読みにくいのは許してください。（この辺もクソ記事量産するうちに改善されればよりよい）


###なんでやる気出たのか
自分の会社はギリギリ黒くらいの会社だと思ってるんですけどなぜか決算賞与はもらえるみたいで今日上司と面談をしてきました。
この間営業の人にポロっと給料のテーブルやばいですよねって話をしたのが伝わってたみたいで
「給料あげるなら転職やで！」
って笑いながら普通に言われてしまいました。

この上司はほんとに尊敬できる人で話を聞くと
「転職するにしてもウチの会社の利益にはなるんだしちゃんと勉強するんやで～。まあでもウチの会社にいても給料はあがらんけどな～」
みたいな感じのことを言ってくれました。（この余裕がすごい）

あと普通に会社からは期待されとるやで、みたいなことを言われるとその場ではアハハーみたいな愛想笑いしかできないけどやっぱやる気出ますよね。その辺のマネジメントの本とかにも書いてありそうだけど。

###なにするか
とりあえず今までの現場ではJavaでバッチやらなんやらのサーバサイドって呼ばれるものを意味も分からずゴリゴリ書いてたんですけどそろそろフロントも触れるマンになりたいです。

そもそも文系卒なので、プログラミングなんて教養の授業レベルの知識しかないわけです。
研修も途中で打ち切られて現場でOJTという名の地獄に送り込まれたので基本も身についていないな、ってことでちょっと前にキンドルのセールで買って放置してた本をとりあえず進めていこうと思います。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/349816/2facb2a4-991f-5cdf-16e4-c70f5f9e8218.png)
https://www.amazon.co.jp/dp/4839959714/ref=cm_sw_em_r_mt_dp_U_.TtICbZRJ7MYC

この子ですね。がんばります。今日は20％くらい進んだのでさっさと基本は終わらせたいです。


###直近の目標
とりあえずHTML、CSSがこんなもんかーってわかったらJavaScriptの基本みたいな勉強していい感じにイマドキでオサレなフレームワーク（Vue.jsとかReactあたりがナウいっぽい）も軽く触ってポートフォリオみたいなの作れたらな～って感じです。
そのためにはインフラ回りもほぼ触ってないのでその辺の勉強も必要ですね。

いつSier脱出できるんやろか。。。

まあ気にしてもしゃーなしってことで30歳くらいまでにはイケイケエンジニアになっておこうと思います。
たぶん気が乗らなかったらQiitaも更新しないです。いい感じに勉強できたらいい感じにアウトプットすると思います。

###では
おわり。
Google ColaboratoryでDash等のlocalhostで起動したアプリケーションにアクセスする


# 概要

Colaboratoryで可視化方法を色々試している中で、Webアプリケーションを立ち上げるDashの結果を確認できるかを調査したので、その備忘録。

今回の内容は、localhost上のアプリケーションを実行する際なら応用がきくっぽい。

# 手順

実物は[サンプル](https://github.com/calderarie/ColaboratoryDash/blob/master/colab_dash.ipynb)参照。

1. ngrokをインストールする
  - localtunnelでも良い
  - 両社の違いはあまり把握してないです。。。
2. 実行したいDashコードを作成して、マジックコマンド(%%writefile)でファイルを作成
3. ngrokを起動する
4. 2で作ったコードを実行する
5. ngrokのURLへアクセスすると、Dashの可視化結果が見れる

# 余談

調べてる中で、[jupyter-plotly-dash](https://pypi.org/project/jupyter-plotly-dash/)を見つけたが、こちらは少し手間がかかりそうだったので今回は断念。

# 参考

 - [python - Launch a Dash app in a Google Colab Notebook](https://stackoverflow.com/questions/53622518/launch-a-dash-app-in-a-google-colab-notebook)
 - [Google Colaboratory のTips集その1 (GoogleDriveマウント、セッション継続、TensorBoard接続](https://www.mahirokazuko.com/entry/2018/09/07/223133)
水上ドローン作りたい11、カメラ組込み、浮力不足対策、動作テスト、今回の結論

# カメラ
最後のコンポーネントになります。なるべく高い位置で、真ん中に置いておくのが見やすいだろうという事でここに配置します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/359316/1f264167-a373-daf8-1280-5660370fa32b.png)
ケーブルははんだゴテで穴を開けて通しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/359316/a29ee7ed-d438-3e6f-c1a6-d6e762c121d0.png)
これで全てのコンポーネントを搭載できました。
# 浮力不足対策
多数の重量物を搭載したため、重量が改造前の1.7倍くらいに増加しています。追加のフロートを付けて浮力不足を補います。
## フロート
当初はビート板の素材をくくりつけて対応するつもりでした↓。浮力が全然足りず失敗。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/359316/ea18f56a-5d9b-398a-d56d-e8d6430014da.png)
結局ペットボトルをくくりつけました。くくりつけるのに結束バンドを利用。結束バンドの端っこ(赤丸の部分）を強力な接着剤で側面に貼り付けました。接着面積が小さいので不安ですが問題無さそうです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/359316/99c0ee3c-c5a7-3a6b-fa23-9bad2d9c04a1.png)

これでハードウェアの対応は完了です。

# 動作テスト
作成したので動作テストを行いましたが、L-02Cとカメラの同時使用が安定しません(動く時もある)。どうも電気が不足してるっぽいです。この対策を行う事も考えたのですが、作業時間を確保できないので1度中断する事にしました。仮に時間が合ったとしても、対策を取るスペースがボートの中にもう有りません。

4月になったら再度挑戦してみるつもりです。恐らく今回の経験を元に2号機を1から制作する事になるでしょう。
SwiftのCodableでCustomな型(ObjectじゃなくてPrimitiveなValue)を扱う方法

JSONのObjectに当たるもののclass(struct)を定義するのはわかるのだが、JSONのprimitiveValue(numberとかstringとか)に当たるもののclass(struct)を定義する方法が全然ドキュメントされていないのでメモ。

## まとめ
- CustomPrimitiveValueのCodable実装でinit(from decoder)とencode(to)を自分で実装しよう
- [singlevaluecontainer](https://developer.apple.com/documentation/swift/decoder/2894882-singlevaluecontainer)を使おう


## フルサンプル
PersonがObject．
NameがPrimitiveValue(string互換).

```:構造
person: {
  name: Name
}
```

です。以下どうぞ

```swift:Name.swift

// こいつはjson上Objectではなくstringと同様のprimitiveなvalueとして扱いたい
struct Name {
    let string: String
    
    init(_ string: String) {
        self.string = string
    }
}

extension Name: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        self.string = try container.decode(String.self)
    }
}

extension Name: Encodable {
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(string)
    }
}
```

```swift:Person.swift
struct Person {
    let name: Name? // ←独自の型且つOptionalだと自動的に動かない 独自の型がCodableである必要がある。 今回はNameをCodableにしたので自動的に動く
}

extension Person: Codable {
    enum CodingKeys: String, CodingKey {
        case name
    }
}
```

```swift:Test.swift
func testEncode() -> String {
    let person = Person(name: Name("taro"))
    let data = try! JSONEncoder().encode(person)
    return String(data: data, encoding: .utf8)!
}
testEncode() // => "{"name":"taro"}"


extension Person: CustomStringConvertible {
    var description: String {
        return "Person<name: \(name?.description ?? "nil")>"
    }
}

extension Name: CustomStringConvertible {
    var description: String {
        return "Name<\(string.description)>"
    }
}

func testDecode() -> Person {
    let json = "{\"name\":\"suzuki12\"}"
    let data = json.data(using: .utf8)!
    return try! JSONDecoder().decode(Person.self, from: data)
}
testDecode() // => Person<name: Name<suzuki>>
```

## 蛇足
[公式ドキュメント(Apple)](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types)でSingleValueContainerが触れられてないのどういうこと。流し読みしたら、primitiveな値にCodable使うべきではないのかなと勘違いするところだった。

独自のEncoderを作る方法はこちらがとてもわかりやすいです
https://stackoverflow.com/questions/45169254/swift-custom-encoder-decoder-to-strings-resource-format
Ubuntu18.04にrbenvを使ってRuby2.3インストールしたらコケた話

# はじめに
Ubuntu18.04にrbenv入れてRuby2.3をインストールしようとしたらコケた話です．
今回は，１時間奮闘の末，解決した方法を載せたいと思います．

~~もうDockerでいいんじゃない？~~

# エラー
Ruby2.3のインストール時，以下のようなエラーが出ました

```bash
~ $ rbenv install 2.3.1
Downloading ruby-2.3.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.bz2
Installing ruby-2.3.1...

BUILD FAILED (Ubuntu 18.04 using ruby-build 20181207-4-ge0071f5)

Inspect or clean up the working tree at /tmp/ruby-build.20190314005320.605
Results logged to /tmp/ruby-build.20190314005320.605.log

Last 10 log lines:
installing rdoc:              /userpath/.anyenv/envs/rbenv/versions/2.3.1/share/ri/2.3.0/system
installing capi-docs:         /userpath/.anyenv/envs/rbenv/versions/2.3.1/share/doc/ruby
The Ruby openssl extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Try running `apt-get install -y libssl-dev` to fetch missing dependencies.

Configure options used:
  --prefix=/userpath/.anyenv/envs/rbenv/versions/2.3.1
  LDFLAGS=-L/userpath/.anyenv/envs/rbenv/versions/2.3.1/lib
  CPPFLAGS=-I/userpath/.anyenv/envs/rbenv/versions/2.3.1/include
```

# 原因
どうやら，Ruby2.4未満のバージョンはoppenssl 1.1と互換性が無いっぽいです．

>Ruby < 2.4 is not compatible with openssl 1.1.
>You need to install libssl1.0-dev.
>https://github.com/rbenv/ruby-build/issues/1199

シェルでopensslのバージョン確認すると

```bash
~ $ openssl version
OpenSSL 1.1.0g  2 Nov 2017
```
1.1になっていますね・・・


# 解決策
以下のコマンドを打って互換性をもたせましょう! (もうこれだけっ！)

```bash
$ sudo apt install libssl1.0-dev
```

その後，もう一度Ruby2.3をインストールしてみると

```bash
~ $ rbenv install 2.3.1
Downloading ruby-2.3.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.bz2
Installing ruby-2.3.1...
Installed ruby-2.3.1 to /userpath/.anyenv/envs/rbenv/versions/2.3.1
```

# おわりに
バージョンで上手くいかなくて，それでもめげずに頑張って解決したときの達成感といったら( ´ー｀)ﾌｩｰ．．．


# 参考サイト
Ubuntu 18.04上においてruby-buildでruby 2.3.*をインストールする
https://arimasou16.com/blog/2018/04/30/00255/
jQueryを使用バリデーションをかける。

テキストエリア(.textarea)にある文字が０であればバリデーションをかける記述です。

条件分岐をし、judge = 0と置き、(textarea.length == 0)であればjudge += 1とし、judgeが０でない時(judge != 0)はe.preventDefaultしエラーテキストを表示する。

```
$(document).on("turbolinks:load",function(){
  //バリデーション
  $(".btn").click(function(e){
    var judge = 0; 
    var textarea = $(".textarea").val()
    if(textarea.length == 0) {
      $(".error-text").show();
      $(".textarea").css("border","1px solid red ");
      judge += 1;
    } else {
      $(".error").hide();
      $(".textarea").css("border","1px solid #ccc ");
    }
      if(judge != 0) {
      e.preventDefault();
      $('body, html').animate({ scrollTop: 0 }, 1);
      return false;
    }
  })
})
boolean型の列はNOT NULLにしておけという話

結論としてはタイトルの通りなのだが、実際にやばみを目視で確認してみた。

# NOT NULL のboolean型による真理値表
## 全パターン（4レコード）を持つテーブルを作成
~~~ sql
-- 2値テーブル作成
create table truth(
    condition_a boolean NOT NULL,
    condition_b boolean NOT NULL
);
INSERT INTO truth (condition_a,condition_b) VALUES(TRUE,TRUE);
INSERT INTO truth (condition_a,condition_b) VALUES(TRUE,FALSE);
INSERT INTO truth (condition_a,condition_b) VALUES(FALSE,TRUE);
INSERT INTO truth (condition_a,condition_b) VALUES(FALSE,FALSE);
~~~

## 真理値表を取得するSQL
作成したtruthテーブルに対して、真理値表を取得するSQLを叩いてみる。

~~~ sql
select 
 condition_a,
 condition_b,
 -- 論理積
 condition_a AND condition_b as cond_and,
 -- 論理和
 condition_a OR condition_b as OR,
 -- 排他的論理和
 condition_a <> condition_b as XOR,
 -- 否定排他的論理和
 condition_a = condition_b as XNOR,
 -- 否定論理和
 NOT condition_a AND NOT condition_b as NOR,
 -- 否定論理積
 NOT (condition_a AND  condition_b) as NAND
FROM 
 truth;
~~~

## 結果
はい。

||A  |B  |AND|OR|XOR|XNOR|NOR|NAND|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|1|TRUE|TRUE|TRUE|TRUE|FALSE|TRUE|FALSE|FALSE|
|2|TRUE|FALSE|FALSE|TRUE|TRUE|FALSE|FALSE|TRUE|
|3|FALSE|TRUE|FALSE|TRUE|TRUE|FALSE|FALSE|TRUE|
|4|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE|TRUE|TRUE|

# NULLABLE なboolean型による真理値表
今度は、Nullableなboolean型の2列を持つ、3値のテーブルを作ってみる。

~~~ sql
create table truth_with_null(
    condition_a boolean ,
    condition_b boolean 
);

-- 全パターン
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(TRUE,TRUE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(TRUE,FALSE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(TRUE,NULL);

INSERT INTO truth_with_null (condition_a,condition_b) VALUES(FALSE,TRUE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(FALSE,FALSE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(FALSE,NULL);

INSERT INTO truth_with_null (condition_a,condition_b) VALUES(NULL,TRUE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(NULL,FALSE);
INSERT INTO truth_with_null (condition_a,condition_b) VALUES(NULL,NULL);
~~~

## 
同じSQLを叩いてみる。

~~~ sql
select 
 condition_a,
 condition_b,
 -- 論理積
 condition_a AND condition_b as cond_and,
 -- 論理和
 condition_a OR condition_b as OR,
 -- 排他的論理和
 condition_a <> condition_b as XOR,
 -- 否定排他的論理和
 condition_a = condition_b as XNOR,
 -- 否定論理和
 NOT condition_a AND NOT condition_b as NOR,
 -- 否定論理積
 NOT (condition_a AND  condition_b) as NAND
FROM 
 truth_with_null
;
~~~

## 結果
やべえ

||A  |B  |AND|OR|XOR|XNOR|NOR|NAND|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|1|TRUE|TRUE|TRUE|TRUE|FALSE|TRUE|FALSE|FALSE|
|2|TRUE|FALSE|FALSE|TRUE|TRUE|FALSE|FALSE|TRUE|
|3|TRUE|||TRUE|||FALSE||
|4|FALSE|TRUE|FALSE|TRUE|TRUE|FALSE|FALSE|TRUE|
|5|FALSE|FALSE|FALSE|FALSE|FALSE|TRUE|TRUE|TRUE|
|6|FALSE||FALSE|||||TRUE|
|7||TRUE||TRUE|||FALSE||
|8||FALSE|FALSE|||||TRUE|
|9|||||||||

経験則として「boolean型をNullableにするな」で思考停止していたが、改めて確認してやばい動きをしているのが分かる。
(TRUE AND NULL) がNULL になり、
(FALSE AND NULL) がFALSE になるの、やばくないですか？

そして、
(TRUE OR NULL) がTRUEになり、
(FALSE OR NULL) がNULL になるのも、やばくないですか？


https://www.postgresql.jp/document/9.6/html/functions-comparison.html
https://qiita.com/kiimiiis/items/119cdbd51c588c4b1f62
Windows 10 Pro x64 + Python3 で selenium + chromedriver で画像をDLしてみる

#目的
画像ファイルをダウンロードしてみる
ファイル名を指定しないと C:\Users\User_Name\AppData\Local\Temp
にtmphogeとしてダウンロードされる
urllib.request.urlretrieve で明示的にファイル名を指定すればよいようだ
os.path.basename　はURLに対しても有効のようだ（なのかな？）
##サンプルコード
対象とするhtmlの抜粋
<pre>
&lt;img src="./eudv015s.jpg"&gt;
</pre>
コード

```python
# Windows Add env PYTHONIOENCODING = UTF-8 & restart vscode

import os
import time
import urllib.request
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome('C:\\Dev\\tool\\webdriver\\chromedriver.exe')  
driver.get('http://localhost:8080/')
try:

    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, 'img'))
    )

    elm = driver.find_element_by_tag_name('img').get_attribute('src')
    print(elm)          # http://localhost:8080/eudv015s.jpg

    # URLでも通るのか・・・
    print(os.path.basename(elm))    # eudv015s.jpg

    print(os.getcwd())              # c:\Dev\code\pytest
    print(os.path.join(os.getcwd() + '\\', os.path.basename(elm)))

    urllib.request.urlretrieve(elm, \
        os.path.join(os.getcwd() + '\\', os.path.basename(elm)))

    time.sleep(2) # 表示確認用のwait
finally:
    driver.quit()
```
##参考にしたサイトはこちら
[urllib.request --- URL を開くための拡張可能なライブラリ](https://docs.python.org/ja/3/library/urllib.request.html)
[ASP.NET][Entity Framework] ASP.NET Core で Code First のマイグレーション自動適用

Entity Framework Core で add されたマイグレーションは以下のコマンドでデータベースに手動適用できます。

[パッケージマネージャーコンソール]

```
Update-Database -Context FooContext
```

[CLI コマンド]

```
dotnet ef database update --context FooContext
```

ASP.NET Core でアプリケーション起動時にマイグレーションを自動適用させるためには、Program.Main メソッドに次のように記述します。

```c#
public static void Main(string[] args)
{
    var host = CreateWebHostBuilder(args).Build(); // ASP.NET Core 2.1～ の場合
 
    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<FooContext>();
 
            // 自動マイグレーション適用
            context.Database.Migrate();
 
            // 初期データ生成
            // ※Data フォルダ内にカスタムクラスを作成してデータ生成コードを記述しておく。
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "データベース初期構成中にエラーが発生しました。");
        }
    }
 
    host.Run();
}
```

※Startup.Configure に記述すると Add-Migration で実行されてしまいます。（ASP.NET Core 2.0 で確認）
AWSを使ってデプロイ　EC2インスタンス編　備忘録

AWSとはAmazonWebServiceの略称で、Amazonが提供するWEBサービスの総称です。

####今回のデプロイまでの大きな流れ
・AWSのアカウント作成
　※こちらについては[AWSのアカウント作成についてはAWS公式のガイド]
(https://aws.amazon.com/jp/register-flow/)を参考に
・EC2インスタンスの生成
・Linuxサーバーの構築
・Mysqlの設定
・EC２インスタンス内にGitからアプリをクローンしてRailsを起動
Nginxを使ってRailsを起動する
・自動デプロイ（Capistrano）

# EC2インスタンスの作成 
######1.EC2を選択
######2.インスタンスをクリック
######3.インスタンス作成をクリック
<img width="1407" alt="73e1c1ae8b89043d44fb12eff1b0729c.png" src="https://qiita-image-store.s3.amazonaws.com/0/341484/15670266-b7d9-a27c-0a0e-fd222b8273d4.png">
######4.AMIの選択
(AMIとは...OSがインストールされた状態のハードディスクの内容を丸ごと写しとったもので、Ubuntu LinuxやWindows Serverなど様々な種類から選択できる。)
今回は「 Amazon Linux AMI2 」ではなく、「 Amazon Linux AMI 」を選択
[Amazon Linux2とAmazon Linuxの違いについて](https://qiita.com/akira345/items/2a09c4d06d2e3415bc8d)は[Daisuke Ichimaru](https://qiita.com/iamdaisuke)さんの記事を参考にさせていただきました。
######5.EC2インスタンスのタイプ選択
　無料枠の「t2.micro」を選び「確認と作成」クリック
<img width="1395" alt="8e1c948bab8cac9db1c09ac225f238a0.png" src="https://qiita-image-store.s3.amazonaws.com/0/341484/48658adc-2a14-c0a0-3a24-5ddc18094d53.png">
######6.キーペアー
「確認と作成」をクリックすると
既存のキーペアーを選択するか、新しいキーペアを作成ます。
と出るので、「新しいキーペアの作成」を選択し、「キーペア名」に任意のキーペア名を入力。
「キーペアのダウンロード」をクリックしダウンロードする。
※キーペアとは、公開鍵と秘密鍵があり、その2つがワンセットになっている。インスタンスを起動する時に使用する。
 
###### ＋α.Elastic Ipとインスタンスの関連付けとセキュリティグループのインバウンドルールの編集
・ElasticIPとインスタンスを固定すること再起動してもIPアドレスが振られることはなく固定できる。
　固定する必要がない時は固定化する必要がない場合はパブリックIPアドレスを利用する。
　**今回はElasticIPを利用する。**
・セキュリティグループとは、同一グループ外のインスタンスと通信を行う際のトラフィック（インターネットやLANなどのコンピューターなどの通信回線において、一定時間内にネットワーク上で転送されるデータ量）を制御するファイアウォール（不正なアクセスから守るための仕組み）
・セキュリティグループのインバウンドの編集する事でWEBサーバを起動した時にアクセスできるようになる。
######ElasticIPとインスタンスの関連付け方法
1.ElasticIPをクリック
2.新しいアドレスの割り当てをクリック
3.割り当てられたアドレスを選択して、アクションをクリック
4.アドレスの関連付けをクリック
5.アドレスの関連付けと出てくるのでインスタンスの欄に先ほど作成したEC2インスタンスを選択
6.関連付けるをクリックすると関連付け完了

######セキュリティグループのインバウンドの編集
1.先ほど作成したEC２インスタンスを選択し、説明のタブの中にあるセキュリティグループのリンクをクリック
2.セキュリティグループの設定画面に遷移するので、「インバウンド」タブの中の「編集」をクリック。
3.編集ボタンをクリックし、ルールを追加をクリック
4.「タイプ:HTTP,プロトコル:TCP,ポート範囲:80,送信元:0.0.0.0/0」にして保存をクリック

これでEC2インスタンス編は完了
pluckとmap の違いを調査する

## pluck と map はどちらを使うべきなのか？

Userモデルの全レコードを取得して、idの配列を作成した時で試してみる

```rb
require 'bebnchmark'

Benchmark.bm 10 do |r|
  r.report "pluck" do
    User.all.pluck(:id)
  end

  r.report "map" do
    User.all.map(&:id)
  end
end
```


結果としてはこんな感じ


```rb
         user     system      total        real
pluck  0.003826   0.000972   0.004798 (  0.013440)

map    0.022315   0.002486   0.024801 (  0.070383)
```

mapの方がだいぶ長い。。。SQL的には何が違うんだろ

```sql

# pluck 
SELECT `users`.`id` FROM `games`

# map
SELECT `users`.* FROM `games`
```

なるほど。
`pluck`は指定したカラムのみをSQLで取ってきている。
また、`pluck`必要なフィールドだけを読み込むことで、メモリの使用量も削減できるとの事で
これが圧倒的に早い理由らしい
→ [pluckでメモリを大幅に節約する（翻訳）](https://techracho.bpsinc.jp/hachi8833/2018_09_26/62333)



### mapの方が早いパターン
上の例だけみると常に`pluck`の方が早そうだけど、`map`の方が早いパターンはあるのか？
調べてみた。


```rb

require 'bebnchmark'

users = User.all
Benchmark.bm 10 do |r|
  r.report "pluck" do
    2000.times { users.pluck(:id) }
  end

  r.report "map" do
    2000.times { users.map(&:id) }
  end
end
```
```rb
        user    system      total        real
pluck 4.725170   0.867798   5.592968 (  6.395219)
map   1.070974   0.006997   1.077971 (  1.079586)
```

この場合、`map`の方が断然早い！
繰り返し処理を実行する場合、`pluck`は毎回SQLを発行してしまう。（この場合だと2000回発行してしまってます）
一方、`map`は一回しか発行していない。

### まとめ
- SQLの段階で必要なカラムだけを取ってこれるので、対象のレコードを配列に整形する場合などは`pluck`が早い
- 一方、繰り返し処理のなかで`pluck`を使うと毎回SQLを発行してしまうので危険。その場合は`map`を使った方が断然早い
PyInstallerでexeファイル化

業務で使用するPythonスクリプトを作っても、誰もがpythonがインストールされているとは限りません。
そんなときは、PyInstallerでWindows用のexeファイル（実行ファイル）に変換して配布するのがよいと思われます。


# 環境
* OS : Windows 10 64bit
* Python 3.6.0 (Anaconda3-4.3.1)
* PyInstaller 3.4

# PyInstallerのインストール
1. コマンドプロンプトを起動
2. pipでPyInstallerをインストール

```
$ pip install pyinstaller
```

# exeファイルへの変換
ここでは、exe化したいpythonファイルをTest.py、作業フォルダをC:\PythonFilesとします。

1. 作業フォルダに移動
2. pyinstallerでexeファイルに変換

```
$ cd C:\PythonFiles
$ pyinstaller Test.py
```

# 結果

```
14719 INFO: Building COLLECT COLLECT-00.toc completed successfully.
```

実行後、completed successfullyと表示されたらexeファイル化完了です。
exeファイル化に成功すると、作業フォルダ内に下記のフォルダとファイルが生成されます。


>* pycache
>* build  
>* __dist__
>* Test.spec  

dist\Testフォルダ内にあるTest.exeファイルを実行するとスクリプトが走ります。
（配布するときはdistフォルダ毎配布します）

# オプション
### --onefile
onefileオプションを付けると、関連するファイルを１つにまとめてexeファイルを生成します。

```
$ pyinstaller Test.py --onefile
```

### --noconsole
noconsoleオプションを付けると、コンソール（コマンドプロンプト）の黒い画面を表示しません。

```
$ pyinstaller Test.py --noconsole
```

# その他備忘録
* 1ファイル化したexeファイルは、1ファイル化していないexeよりも起動が遅いようです。
* seleniumを含むpythonファイルをonefileオプションを付けて変換したところ、exeファイル化は成功しましたが、実行するとエラーになりました。seleniumを含むpythonファイルは1ファイル化できないようです。
* noconsoleオプションを付けても、実行中にエラーが出るとコンソールが表示されます。
micro:bit 4サーボ直刺し4足歩行ロボット


###■昨日4足歩行ロボットの記事を投稿をしました
https://qiita.com/Google_Homer/items/fad0c6de119d40c62cfd
###よくよくプログラムを見たら、左右の足の角度が同じではありませんか!!!
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234533/78d7273d-903f-8d15-f536-ea056a8e6130.png)

##■ということは
###①左右たこ足配線すれば、前用サーボ信号と後用サーボ信号の2つの信号を出すだけで行けるはず。
###②サーボ2信号だけなら拡張ボードなしで行けるはず。
###③ついでにmicro:bit本体の3vをサーボ電源に使っちゃおう。(無茶かな?)
###かなりちっちゃいやつができそうである。

##■ということで、サーボ4台直刺しのちっちゃい4足歩行ロボット作っちゃいました

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a> <a href="https://twitter.com/hashtag/4%E8%B6%B3%E6%AD%A9%E8%A1%8C%E3%83%AD%E3%83%9C%E3%83%83%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#4足歩行ロボット</a><br>4足歩行ロボット、サーボ4台直刺し(拡張基板レス)。micro:bit本体電源の単三乾電池1.5v×2本からの給電で4台のサーボSG90駆動できた。 <a href="https://t.co/ofU2Z8sF27">pic.twitter.com/ofU2Z8sF27</a></p>&mdash; Google Homer (@google_homer_) <a href="https://twitter.com/google_homer_/status/1105835147595665417?ref_src=twsrc%5Etfw">2019年3月13日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##■作り方
サーボはTower ProのSG90を使いました。
①サーボ4台を写真の方向と位置関係で電池BOXに両面テープで貼り付けます。
②足として、サーボ付属のホーンをネジ止めします。90°の位置で直立するようにして下さい。
③エッジのP1に、前足のサーボ2台のSignal端子を接続します。
④エッジのP2に、後足のサーボ2台のSignal端子を接続します。
⑤エッジの3V/GNDに、4台のサーボの電源端子を接続します。
➅電源は単三乾電池1.5v×2本です。***1.2vの充電池では動きませんでした***。
配線は、私はピンヘッダでうまくやりましたが、各自工夫してください。
後は、適当に盛り付けて完成。
![WIN_20190313_22_58_54_Pro.jpg](https://qiita-image-store.s3.amazonaws.com/0/234533/70d40ce3-2bfe-c8c2-5e46-f2197ac5b137.jpeg)
![WIN_20190313_22_58_24_Pro.jpg](https://qiita-image-store.s3.amazonaws.com/0/234533/a778fa11-61dd-62e4-bccc-eb7c1940e752.jpeg)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/234533/33974507-ac0c-ea2a-5c10-51239c41e622.png)

##■プログラム
ボタンAを押すと10歩あるきます。
コメント中の角度は直立90°からの相対角度です。
![microbit 4足ロボ(4サーボ直刺し).png](https://qiita-image-store.s3.amazonaws.com/0/234533/b43d30ae-ef7a-4e7b-d2b6-0867ce4e9470.png)

##まとめ
サーボSG90って3Vでも動くんですね、びっくりしました。ちっちゃいにはちっちゃいのですが、ケーブルが邪魔で、そんなにちっちゃくはなりませんでした。サーボのケーブルを切って短くするという邪心で揺れています。歩き方、少しあやしいのですが、角度微調整して何とかしてみて下さい。

以上です。
Jestでjsonファイルをmockする

# やりたいこと
Jestを使い、特定のモジュールでrequire()しているjsonファイルをmockしたい

# 解決方法
`package.json`に`jest`>`moduleNameMapper`を設定し、テスト実行時のみ、mockしたいjsonファイルのパスを書き換える

# 実装例
以下のモジュールをテスト対象とします

```javascript
//target.js
const json = require('./required.json');
/** 以降、処理が記載されているとする **/
```

テスト実行時に`target.js`が`require()`するjsonファイルを`mock.json`に差し替えたい場合、`package.json`に以下の設定を加えます

```json
{
  "jest": {
    "moduleNameMapper": {
      ".*/required\\.json$": "<rootDir>/mock.json"
    }
  }
}
```
`moduleNameMapper`のkeyには、差し替え前のモジュールのパス（正規表現）を、valueには差し替え後のモジュール（mock）のパスを記載します
（valueにある`<rootDir>`は`package.json`のある階層を示すエイリアスです）

上記の設定により、`require('./required.json')`で指定したパスが`moduleNameMapper`のkeyとマッチし、対応するvalueのパスに書き換えられて実行されます

# 参考
- [moduleNameMapperの公式資料](https://jestjs.io/docs/en/configuration.html#modulenamemapper-object-string-string)
- [\<rootDir\>の公式資料](https://jestjs.io/docs/en/configuration.html#rootdir-string)
睡眠の質を上げるライフハック

---

**2019/12/06更新**

[こちらの記事](https://qiita.com/am_nimitz3/items/8a2e8624e2f7376b22f7)に改めてまとめました。

---

良質な睡眠は、学習したものの吸収力、アウトプットの質の良さ、穏やかな心、生きてる心地良さなど、全てにおいて効果抜群を発揮します。

エンジニアは、学習など入力系の情報、コーディングなど出力系の情報を頻繁に取り扱うため、睡眠の質によりその質が左右されやすく、非常に重要になります。

以下では睡眠の質を上げるノウハウで、自分が調べたり試したことを書いていきます。

## 良質な睡眠に必要なこと

* 寝る前～寝ている間に、深部体温を落とし続ける （[参考論文](https://www.jstage.jst.go.jp/article/onki/78/1/78_6/_pdf)）
    * 体の芯まで十分に身体を温めておく
    * 手足を温め毛細血管を広げ、深部体温の熱を逃がしやすくする
* 寝る数時間前～寝る前に、副交感神経を優位にする（[参考資料](http://wwwtb.mlit.go.jp/chugoku/gian/2016seminar-koen3.pdf)）
    * 副交感神経を優位にするメラトニン・セロトニンの血中濃度を上げる
    * 交感神経神経を優位にするドーパミン・ノルアドレナリン等の血中濃度を下げる

### 良質な睡眠を獲得できた行動
自分が試して、効果があったと感じたものです。

* 銭湯で交互浴（サウナ↔水風呂）
    * 最低3セット
    * 水風呂は首筋につかるまで
* 自宅で交互浴（お風呂で全身浴↔隣にドラム缶型のビニール風呂を置いて水風呂）
* 入浴後に手足を冷やさないようにする
    * 下半身を布団の中に入れる
* 入浴中、十分に身体が温まったら冷水シャワーを頭から浴びる
    * 水温は徐々に下げるで良いが、心地良い温度 - 3°くらいがお勧め。
* 冷蔵庫で冷やした水枕で後頭部を冷やす
* 通気性のあるベッド・マットを使う
* 熱がこもりにくい寝具を使う
    * 綿・羽毛・シルクが入ったものを使う
    * ポリエステルの比率がなるべく少ないものを使う
* 自宅で交互浴（全身浴↔足湯）
    * 足湯中に汗がにじみ出るまで
* グリシンを摂取する
    * 初回は効果を比較的感じやすい
* 朝食にバナナ・果物を食べる
* 寝る前に深い呼吸をしながらストレッチをする
    * 前屈だけでも良い
* （夏場限定）冷房エアコンをつけっぱなしに、室温が上がらないようにする


## 睡眠の質が悪化する状態

[良質な睡眠に必要なこと](#良質な睡眠に必要なこと) で書いたことと逆の状態になります。

* 体温調整が利きにくくなる、深部体温が落ちにくくなる
* 寝る前にも交感神経が優位のまま

### 睡眠の質が落ちたと思える行動

個人的には以下は、睡眠の質を浅く・短くすると感じているので非常に注意しています。

* アルコールの摂取
* 寝る前に対戦ゲームをする
* 眠気を催すほどの食事をする（食後低血糖？この眠さの正体は不明だが、睡眠の質が上がると改善される）
* 手足が冷えている状態で寝る
* 暖房エアコンをつけて寝る
* カフェインの摂取
* 電気毛布をつけたまま寝る
* 寝る前に食事をする（水分・果物程度ならセーフ）
* 起きる時間を気にして寝る（十分な時間を取るなどして対策）
* その他仕事など、緊張状態で寝る（マインドフルネスが有効かもしれない）


## 終わりに

睡眠は全てにおいて優先したほうが良いと考えています。
仕事・恋愛・友人・勉強・ゲーム、これらのために睡眠を犠牲にしてはいけません。

継続的に睡眠の質を下げるモノはうまく調整するか、諦めてきっぱり別れましょう。

良い睡眠で快適な生活を！
iframeから親ウィンドウにメッセージを飛ばすクロスオリジン対応版

iframeを使って別のページを表示する場合、その中のページと外側のページは基本的に別物となり、通信をすることができません(同じサイトまたは、両方ローカルファイルである場合は除く)。

PythonのPyWebViewを使ってHTMLを表示している場合、一見両方ローカルのファイルですので、外側のページと内側のページで通信ができそうですが、ダメなようです(いわゆるクロスオリジンの状態とみなされてしまう)。

そこで、クロスオリジンの環境でも、iframeの内側のページから外側に通信をしたい場合、Window#postMessage()というメソッドを使用します。

[window\.postMessage \- Web API \| MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/postMessage)

このメソッドは指定した`Window`オブジェクトにメッセージを送信します(受信側のウィンドウは、イベントリスナで受け取ることができる)。つまり、iframeの内側のウィンドウから`parent.window.postMessage()`とすることで、フレームの外側のページにメッセージを送ることができます。

```js:内側ページのJavaScript
\document.addEventListener("scroll", function (e) {
  window.parent.postMessage(document.documentElement.scrollTop, "*");
})
```

```js:外側ページのJavaScript
var pos = 0;

window.addEventListener("message", function (e) {
  pos = e.data;
});
```

このようにすると、外側ページのposという変数に、内側ページのスクロール位置が入ります。

なお、内側のページと外側のページのサイトの~~ドメインが異なる・~~プロトコルが異なる場合は通信ができないようです。

# 参考資料

* [window\.postMessage \- Web API \| MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/postMessage)
* [javascript \- iframeのDOMContentLoadedが発火しません \- スタック・オーバーフロー](https://ja.stackoverflow.com/questions/31078/iframe%E3%81%AEdomcontentloaded%E3%81%8C%E7%99%BA%E7%81%AB%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93)
Struts1を選定するに当たってのデメリット

今更、こんな情報ほんとうにアレだけど、2019年にもなって、未だにStruts1も一部のオジサンに根強い人気がある？ようなので…。
セキュリティはそうなんだけど、それ以外の観点で。

# ActionFormやルーティングなど
## 特徴
XMLによるルーティングなどの設定
ActionFormというオブジェクトへリクエストパラメータを詰め込んでくれる
scopeをsessionにすると、リクエストパラメータが入ったActionFormをそのままセッションに詰め込んでくれたりする。リクエストパラメータが空だと、セッションからデータを取得するということをしてくれる。
サーバーサイドはGETなのかPOSTなのか意識しない。どっちできても同じように処理する。
## デメリット
XMLを記述する手間がある（XML地獄とも言われる）。別のAction(HttpServletを継承したStruts1独自のクラス)へ飛ぶようにしたりしまくったら、スパゲティ感ある。
ActionFormがPOJOじゃない。
使う人の使い方しだいなところもあるけど、ActionFormをscope=sessionにして、JSPで使う変数も全部ActionFormに詰め込んで、セッションじゃなくてもいいものもセッションに詰め込んでしまうことが…。変数のグローバル変数化！
ActionがHttpServletと密結合なため、JUnitによるテストがしづらい。
セキュリティ面の理由（CSRFなど）で、GETとPOSTは区別すべき。設計的にも、GETとPOSTは設計に組み込んだほうが良くて、たとえば、参照なのにPOSTだと、URLを叩いてもそのページへいけないなど、ユーザビリティにも影響。

# JSPカスタムタグ
## 特徴
HTMLタグを意識しない、フロントエンドを意識しない思想のように思える。
Javaのオブジェクトっぽく操作できるようにしている？。
## デメリット
そもそも、JSPのカスタムタグは好き勝手属性を付けたりできないので、HTML5のカスタムデータ属性が書けない。
JSPを評価した後のHTMLタグがJSPカスタムタグからは想像しづらい（フロントエンドを想像させない、意識させないという思想なのだろうけど）点が、色々な意味でデメリット。
教育の問題もあるが、新人がJSPを直接ブラウザが解釈するものと勘違いしてしまう。
JavaScriptからDOMを操作したい場合などに、ソースコード的にJSPカスタムタグと一致しない感が出てきてしまうことがある。
例えば、JSPカスタムタグのproperty属性は、HTML的にはname属性といったように違う言葉となってしまう。

# バリデーター
使ったこと無いからあまり知らないけど、XML書きまくるらしいのがなんとも…。

# 最後に…
可能であれば、他のFWに移行しましょう…。

Springが流行ってますが、大規模開発ではない場合や、FWの使い方からちょっと外れた使い方をしたい場合、起動時間おっそいのが嫌な場合は、Springは向いていないと思っております。
そういった場合は、Javaに限定するのであれば、以下のようなマイクロフレームワークがオススメです。

[jooby \- do more\! more easily\!\!](https://jooby.org/)
[Javalin \- A lightweight Java and Kotlin web framework](https://javalin.io/)
[Spark Framework: An expressive web framework for Kotlin and Java](http://sparkjava.com/)
AWS認定Big Data勉強記 - 1

みなさん、こんにちは、えいりんぐーです。
データ分析や機械学習周りの仕事をしています。

仕事でAmazon RedshiftやAmazon S3を触る機会が多いのですが、最近業界ではAmazon SageMakerなどAWS周辺のデータ基盤や機械学習基盤の話を聞くことが多くなりました。また、先日は[JAWS-DAYS 2019](https://jawsdays2019.jaws-ug.jp/)に参加して、データパイプライン周りのことも聞いて、色々とデータ処理基盤について興味が出てきました。

そこでこれからしばらく、AWSのビッグデータ関連の勉強をしつつ、[AWS認定ビッグデータ専門知識](https://aws.amazon.com/jp/certification/certified-big-data-specialty/)の取得するべく、資料やサービスの情報を簡単にまとめていきます。

なお、2018年10月16日より、プロフェッショナル資格と専門知識資格の両方で、受験にあたりアソシエイトレベルの資格が不要となったようです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/267335/e0c68e57-f2e1-29c8-a8df-f10df91e9973.png" width=75%>


とりあえず、以下のホワイトペーパーとre:Inventの動画は、AWSのビッグデータ関連サービスをざっと把握するのにとても便利でした。

[Big Data Analytics Options on AWS](https://d1.awsstatic.com/whitepapers/Big_Data_Analytics_Options_on_AWS.pdf)

[AWS re:Invent 2017: Big Data Architectural Patterns and Best Practices on AWS (ABD201)](https://www.youtube.com/watch?v=a3713oGB6Zk)

[AWS re:Invent 2018: Big Data Analytics Architectural Patterns & Best Practices (ANT201-R1)](https://www.youtube.com/watch?v=ovPheIbY7U8)

また、上記に目を通した後は、一度[サンプル問題](https://d1.awsstatic.com/training-and-certification/docs-bigdata-spec/BD-S%20Sample%20Questions%20for%20Web.pdf)を解いてみるのがよいかと思います。AWS-BDSは他の資格と違い、模擬試験が提供されていませんが、サンプル問題には解説付きの回答が載っていますので、とても参考になります。

試験ガイドでは以下のような比重になっているので、やはりセキュリティは重点的に勉強するほうがよさそうです。 

|分野|比重|
|---|---|---|
|分野1: 収集|17%|
|分野2: 格納|17%|
|分野3: 処理|17%|
|分野4: 分析|17%|
|分野5: 可視化|12%|
|分野6: データセキュリティ|20%|
|合計|100%|

次回はAWSのビッグデータサービスの概要をまとめようと思います。
Raspberryでpython GPIO出力使ってLED点滅

##モチベーション
ラズパイに各種センサー、アクチュエータをつないで、センシング、動作させるための基礎となる、GPIOを使ってみる。まずは出力。

##環境
- RaspberryPi3B+
- Raspbian 9.8
- RPi.GPIO

##GPIOのピン番号や状態を取得する
GPIOの状態は$gpio readallで見れる

```
pi@raspberrypi:~ $ gpio readall
 +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5v      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 0 | IN   | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | IN   | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 1 | OUT  | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | IN   | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI |   IN | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO |   IN | 0 | 21 || 22 | 0 | IN   | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK |   IN | 0 | 23 || 24 | 1 | IN   | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | IN   | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | IN   | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 3+--+---+------+---------+-----+-----+
pi@raspberrypi:~ $
```
- BCM : GPIO番号
- wPi : Wiring Piというライブラリを使う場合の番号

以下のようにLEDを接続し（簡単に回路図を書く方法があったら教えていただきたいです）、

```
GND ── 200Ω抵抗 ── │◀LED ── BCM17(GPIO. 0)
```
0.1sのsleepを挟んでLEDをON OFFするpythonコード

```gpio.py
# coding: utf-8
import RPi.GPIO as GPIO
import time

def main():
  # GBCMの番号で指定することを宣言
  GPIO.setmode(GPIO.BCM)  
  # BCMの17番ピンを出力に設定
  GPIO.setup(17,GPIO.OUT) 
  try:
    while True:
      GPIO.output(17,GPIO.HIGH)
      print("LED ON")
      time.sleep(0.1)
      GPIO.output(17,GPIO.LOW)
      print("LED OFF")
      time.sleep(0.1)

  except KeyboardInterrupt:
    GPIO.cleanup()
    print("stop")

if __name__ == "__main__":
    main()
```

実行して、カチカチと点滅しました。

```
pi@raspberrypi:~ $ python gio.py
```
puts:Rubyで文字を表示する

# puts:Rubyで文字を表示する
Rubyで文字や数字を出力する場合、putsメソッドを使用します。
- [目次]
	- [メソッドとは？]
	- [putsは何をしてくれるメソッドなの？]
	- [メソッドの書き方]
		- [引数？]
	- [putsを使って書いてみる]
		- [文字列の場合]
		- [数字の場合]
## メソッドとは？
メソッド(method)はコンピューターへの指示の事。
<br>コンピュータに行って欲しい動きに応じてメソッドを選びます。</br>
## putsは何をしてくれるメソッドなの？
タイトルにある通り、putsメソッドは**文字や数字を表示してくれるメソッド**です。
## メソッドの書き方
メソッドは
<br>`メソッド(引数)`</br>
という形で使用します。
### 引数？
引数は『ひきすう』と読みます。
<br>引数は**『メソッドに渡す値』**のことです。</br>
<br>**putsメソッド**を使用する場合であれば**『コンピュータに表示して欲しい文字・数字』**という事ですね。</br>

## putsを使って書いてみる
では具体的にputsを使用して、文字・数字を表示してみましょう。
### 文字列の場合
今回は無難に**Hello,World**と表示させてみましょう。
<br>その場合のコードは以下の通り</br>
<br>入力</br>
`puts("Hello,World")`
<br>出力結果</br>
`Hello,World`

ここで着目して欲しいのは、文字列がダブルクオテーション
(" ")で囲まれているというところです。

`文字列はダブルクオテーション
(" ")もしくはシングルクオテーション(' ')で囲みましょう`
### 数字の場合
数字を表示する場合はダブルクオテーション
(" ")もしくはシングルクオテーション(' ')で囲む必要はありません。
<br>数字を扱う場合、加減乗除などの計算を行うことができます。</br>
<br>入力<br>
`puts(4+2)`<br>
`puts(4-2)`
<br>`puts(4*2)`
<br>`puts(4/2)`</br>
<br>出力結果
<br>`6`
<br>`2`
<br>`8`
<br>`2`</br>

見慣れない記号があるかと思います。
<br>『*』は『×』、『/』は『÷』の意味です。
<br>このような記号を『演算子』と言います。
<br>演算子にはこの他にも色々な種類があります。
<br>今回はputsの基本的な使い方だけ。。。