OmniAICreator/Qiita-1.07M huggingface dataset:
【Oculus Go】Buttonにイベントをつける

# はじめに
Canvasの上にButtonとTextを配置し、ボタンを押下すると、Textの文字を変更するサンプルを作ります。

# 準備
* [【Oculus Go】コントローラを表示する](https://qiita.com/eKushida/items/0ba3599536c3aef51f04)
* [【Oculus Go】コントローラからレーザーポインタを表示する](https://qiita.com/eKushida/items/ba58949dc2d85ee39f6f)
* [【Oculus Go】Canvasを表示する](https://qiita.com/eKushida/items/ec22a2ece770883918d8)

# 手順
## 1. Canvas上にボタンを配置する
今回は、PosX, PosY, PosZ = (0,20,0)に配置しました。
また、ボタン名は「Push Me!」としました。

<img width="366" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/71694/335e5135-3512-85fa-aeb0-3f053526baed.png">

## 2. Canvas上にテキストを配置する
今回は、PosX, PosY, PosZ = (0,-100,0)に配置しました。

<img width="367" alt="2.png" src="https://qiita-image-store.s3.amazonaws.com/0/71694/ecdbc7df-5f07-aacf-fabe-e35d4da0a9bd.png">

## 3. イベント用のオブジェクトを作成する
Hierarchy上で「Create Empty」し、オブジェクト名を「GameController」とします。

## 4. GameControllerにイベント用のコンポーネントを追加する
Assets > OVRInputSelection > Scripts > UIInteractionを追加します。

<img width="371" alt="スクリーンショット 2019-02-09 13.46.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/71694/94a684a7-7641-1c38-bb51-ba1823f91900.png">

## 5. Textとソースコードを関連付けする
GameControllerのOut Textに2.で配置したTextを登録します。

<img width="374" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/71694/af9336f3-5631-6b6d-dadc-a54595dae631.png">

ここで、UIInteractionクラスのoutTextとHierarchy上のTextが関連づけられるようです。

```c#:UIInteraction.cs
using UnityEngine;
using UnityEngine.SceneManagement;

public class UIInteraction : MonoBehaviour {
    public UnityEngine.UI.Text outText;

	public void OnButtonClicked() {
        if (outText != null) {
            outText.text = "<b>Last Interaction:</b>\nUI Button clicked";
        }
    }

    public void OnSliderChanged(float value) {
        if (outText != null) {
            outText.text = "<b>Last Interaction:</b>\nUI Slider value: " + value;
        }
    }

	public void OnToggleChanged(bool value) {
		if (outText != null) {
			outText.text = "<b>Last Interaction:</b>\nUI toggle value: " + value;
		}
	}

	public void OnClearText() {
		if (outText != null) {
			outText.text = "";
		}
	}

    public void OnBackToMenu() {
        SceneManager.LoadScene("main", LoadSceneMode.Single);
    }
}
```

## 6. ButtonにOnClickイベントを追加する

| 項目名 | 値 |
|---|---|
| Object| GameController|
| Function | UIInteraction > OnButtonClicked|

そのままだと味気ないため、テキストを下記のように変更しました。

```c#:UIInteraction.cs
	public void OnButtonClicked() {
        if (outText != null) {
            outText.text = "ボタンを押しました。";
        }
```

## 7. 実行

![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/71694/4b16df3c-4201-cc15-73e7-32f1ef49d33a.jpeg)

ボタンを押下すると、テキストの文字が変わりました。

![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/71694/6e613ad2-6c34-ceba-9ea7-b103dfd0b298.jpeg)


## 参考
[Oculus_GoのコントローラからレーザーポインタによりUIを操作するまで](https://scrapbox.io/oculusgogo/Oculus_Go%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%81%8B%E3%82%89%E3%83%AC%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%AB%E3%82%88%E3%82%8AUI%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%99%E3%82%8B%E3%81%BE%E3%81%A7)
SharedPreferencesの反映はapplyを使おう

SharedPreferencesへの書き込みの反映には下記2点のメソッドが用意されています。

* [SharedPreferences.Editor#commit][2]
* [SharedPreferences.Editor#apply][1]

業務で以下のようなコードでcommitの方が使われており、PlayConsoleにANRのレポートが上がってきました。
commitは[ドキュメント][2]にもあるように同期的にファイルへ書き出しを行っているため、書き出しに時間がかかりレポートされたと考えられます。

```kotlin
fun save(context: Context, value: Int) {
    val pref = context.getSharedPreferences("PREF", Context.MODE_PRIVATE)
    val editor = pref.edit()
    editor.putInt("KEY", value)
    editor.commit()
}
```

そこで、非同期で書き込みを行うapplyに置き換え対応しました。

```kotlin
fun save(context: Context, value: Int) {
    val pref = context.getSharedPreferences("PREF", Context.MODE_PRIVATE)
    val editor = pref.edit()
    editor.putInt("KEY", value)
    editor.apply()
}
```

[1]:https://developer.android.com/reference/android/content/SharedPreferences.Editor.html#apply()
[2]:https://developer.android.com/reference/android/content/SharedPreferences.Editor.html#commit()
OSSのライブラリを使う前に知っておくべきこと

## はじめに

私はOSSのライブラリが大好きでよく使わせてもらっています。
でもライブラリを使わずに済むのなら、使わないに越したことはないとも思っています。

本記事では、OSSのライブラリを使うことによるデメリットとメリットを紹介します。

## OSSのライブラリを使うデメリット

OSSのライブラリには様々なデメリットがあります。
これらを乗り越えてまで導入する価値があるのか、しっかりと考えるべきです。

一部OSS関係なくライブラリ導入のデメリットも混ざっていますが、ご容赦ください。

### 導入コストがかかる

まず、導入コストがかかります。
パッと思いつくだけでも以下が挙げられます。

- ライブラリの信頼性を確認するための調査
- セットアップにかかるコスト
- 使えるようになるまでの学習コスト

### 保守コストがかかる

ライブラリまたはプログラミング言語をバージョンアップするたびに、再度テストを実施する必要があります。
メジャーバージョンアップの場合には使い方が変わってしまい、修正が必要になることもあります。

これは導入しているライブラリが多ければ多いほど大変です。
リグレッションテストが完全に自動化されていればいいですが、そうでない場合はなかなかのコストがかかります。

### メンテされなくなるリスクがある

有名なライブラリではあまりないかもしれませんが、メンテされなくなる可能性も0ではありません。
例えばSwift 5.0がリリースされて対応するときに、「このライブラリはSwift 5.0に対応しません」となってしまったら非常に困ることになります。

### 不具合が潜んでいる可能性がある

OSSのライブラリはソースコードを見ることができますが、全てを把握してから導入することはないと思います。
そのため、全て自前で実装している場合より不具合に気づきにくいです。
有償のライブラリとは異なりサポートがないため、自分たちで解決しなければなりません。

業務で導入している場合、ステークホルダーをうまく説得できないと、そのライブラリを使うのをやめさせられるかもしれません。

### ビルド時間が増える

最近はCI/CDによる自動化が進んでいます。
環境によってはライブラリを多く導入しているとビルド時間が劇的に増え、費用とデプロイまでの時間が増えてしまいます。

iOSアプリの場合、CocoaPodsやCarthageで多くのライブラリを管理していると、なかなかにビルド時間がかかります。
→こちらの解決策があれば教えてほしいです。。

### ライセンス違反になることがある

GPLやBSD、MITなどOSSのライセンス体系は多岐にわたります。
ライセンス条項を守っているつもりでも、知らず知らずのうちに違反していることがあります。

トラブルを避けるためにも、自分が理解していないライセンスのOSSは使うべきではありません。

## OSSのライブラリを使うメリット

ここまでデメリットを紹介しましたが、当然それを上回るであろうメリットが存在します。
そうでないとここまで流行りません。

### 無料で使える

何と言っても無料で使えるのは嬉しいです。
個人で導入するときは手軽に使えますし、業務で導入するときも認められやすいです。

コントリビューターさまに感謝です:bow:

### 実装コストを減らせる

ライブラリを導入することで複雑な処理を簡潔に書けるようになります。
それにより、テストコードを含む実装時間が短縮されます。

### 何か楽しい

新しいライブラリに触れる楽しさ、有名なアプリに使われているライブラリを使う謎の充実感、みんなが使っていることによる一体感…

エンジニアの本質は楽しさを追求することだと思っているので、ここに尽きます。
OSSのライブラリを使う以外にも「楽しいことをする」ために必死でみんなが納得するメリットを探している自分がいます。

## おわりに

OSSのライブラリをたくさん使えばいいわけではない、ということがわかってもらえたと思います。
用法・用量を守って適切に使いましょう！
質問です。

SwiftでtableView使ってアプリを作成しようとしている者です。
以下のコードを書いた後、DataSourceとDelegeteを設定してTableViewに値をセットしようとしたら、
Signal SIGABRTが出てしまいました。
どうしたら解決できますか？
教えてください。

import UIKit

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource{

    @IBOutlet weak var tableView: UITableView!
    
    
    let places = ["yuy","ii","i","j"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return places.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "placeCell", for: indexPath)
        cell.textLabel!.text = places[indexPath.row]
        return cell
    }
}
マイクロサービスの粒度

`Microservice`の粒度について以下の記事から学んだことを、知識整理のために投稿。
[Microservices antipatterns and pitfalls](https://www.oreilly.com/ideas/microservices-antipatterns-and-pitfalls)

## Microserviceはどれくらいの大きさか
- `Microservice`アーキテクチャにおいてサービスの粒度は非常に大切。
- その粒度はプロダクトの性能、変更容易性、安定度など様々な面に大きく影響してくる。
- ではどれほどの粒度で`Microservice`を作れば良いのだろうか。


## `Microservice`における1サービスとは
- 開発者たちは、よくサービスをjavaで言う所の`class`と混同して考えがち。
- `Microservice`におけるサービスは単一の責任を持ち、明確で簡潔な役割を持つシステム全体のうちの1コンポーネント。別に`class`の数は関係ない。
- `class`の数がサービスの粒度ではないとしたら、何が粒度を決定するのか


## サービスの粒度が正しいかを検証する3つの分析

#### 1.Service Scope and Function
- そのサービスは何をするのか。文字に書き起こしてみるのが最良の方法。あれもこれもと色々とサービスの担っている仕事が書けるようであれば、そのサービスは役割を持ちすぎている。
- サービスの`凝集`を考えることはサービスの担う機能や役割を分析するのに、非常に大切。

以下の機能を`Microservice` で構築するとするといくつのサービスに分割できるか。

- ユーザ情報登録
- ユーザ情報更新
- ユーザ情報取得
- ユーザ情報の通知
- ユーザのコメント登録
- ユーザのコメント取得

上の3つはユーザ情報の単純な`CRUD`。
下の2つもユーザのコメントの単純な`CRUD`。
真ん中の1つは上で記載した2つのグループには属していない。
つまり、この機能群は3つのサービスに分離できる。

サービスについての理解度が上がっていけば、機能はより正確に小さく分離することができるようになっていく。

#### 2.Database Transactions
- データベースのトランザクションは`ACID`な操作になっていなければならない。データベースの更新は`unit of work` を実現でき、トランザクション中に何かエラーが起きれば適切にロールバックできる必要がある。
- `Microservice`アーキテクチャにおいてはサービスはアプリケーションとして物理的に分離されている。複数のアプリケーションで単一のトランザクションを実現するのは非常に難しい。
- `Microservice`アーキテクチャは一般的に`BASE`なシステムとして構築する。それぞれのサービスが単一のアプリとして動くわけだから、`Consistent`ではなく`Eventually Consistent`しか保証できないのは当然な気がする。
- 分割したサービスが複数のサービスのデータベースにまたがってトランザクションを保持しなければ`Eventually Consistent`を担保できないならば、サービスの粒度を大きくすることを検討すると良いだろう。

※[この記事](https://qiita.com/suziq99999/items/2e7037042b31a77b19c8)が`ACID`,`BASE`について端的に記述されていてわかりやすかった。

#### 3.Service Choreograohy
- サービス全体の構成の話だと思う。
- サービス間の連携について考える必要がある。前提として、あるサービスがあるサービスを呼び出すとき、システム全体のレイテンシは下がるということ。`HTTP`プロトコルで5つのサービスがシーケンシャルにイベント処理を行ったとして、サービス間のイベント発行に`100ms`かかるとしたら、システム全体で`0.5`秒かかってしまう。
- 一つの業務リクエストで5,6個のサービスが処理を行うような構成になっているとしたら、サービスの粒度をもう少し大きくした方が良い。そうすることで、システム全体の信頼性・安定度・パフォーマンスは向上する。
- しかし同時に大量のリクエストがシステム内に流れ込んでくる場合はサービスの粒度を大きくすると、レスポンシビリティは下がってしまう。そこで、リアクティブアーキテクチャと融合したアーキテクチャにするという選択をすることで、レスポンシビリティを損なわない構成にすることもできる。
- 重要なことはシステム全体の信頼性とレスポンシビリティはトレードオフになっているということ。

## `Microservice`の粒度の落とし穴にはまらないためには

#### アーキテクチャにおける全ての決定はトレードオフになっているということ
- `Service Choreography`でも記載したが、一つの業務リクエストを複数のサービスで処理をしなければいけない構成のパフォーマンスの問題を解決するために、複数の十分に小さいサービスを集めて一つのサービスに固めることでパフォーマンスの問題は解決できるかもしれないが、リリースしやすさ・テストのしやすさを犠牲にしてしまう。
- 上の例のようにアーキテクチャにおける全ての決定にはトレードオフが発生するということを開発者・アーキテクトは理解しておくべきだ。
- このトレードオフは何を基準にどちらを取ると判断するべきなんだろうか。

#### トレードオフの取捨選択
開発者・アーキテクトは`Microservice`アーキテクチャを採用する場合に以下の3つの質問に答えられるようになっているべき。

- `Microservice`で何をするのか
- 達成したい最も重要なビジネス要求は何か
- アーキテクチャ特性のうち最も重要視するものは何か。

これらが答えられていれば、自ずと自分たちが`Microservices`に求めるものがなんなのか、わかってくる。そしてトレードオフの発生する決定は、`Microservice`に求めるものに合わせて行っていけばいい。

## `Microservice`の粒度について思ったこと
結論、`Microservice`の粒度を決定するのは`Microservice`アーキテクチャに移行するアプリケーションを考えるにあたって、非常に重要で難しいことだと思う。
そしてどういう粒度で`Microservice`に切り分けると決定しても、完璧な粒度の設計は不可能だと感じる。
自分達に必要なものが何で、それを達成するためにどうして`Microservice`に移行したいのか。
これを軸にして`Microservice`アーキテクチャの設計を行うことを忘れてはならないと思った。(まあ、`Microservice`に限った話ではないかw)

記事の中では`Microservice`アーキテクチャは、現在紛う事なく産業の主流になっていると述べており、全てのエンジニアはこの流れに乗るべきだそうだ。

`Microservice`に特化したフレームワークも多く作られている世の中なので、実際に今度は物を作ってみようと思う。
React Navigationでのナビゲージョンの実現について

本エントリでは作成したアプリで使用したいくつかのテクニックの一つのナビゲーションについて記載します。
React Nativeでナビゲーションを実現するには幾つか方法があるようですが筆者は[React Navigation](https://reactnavigation.org/)を使用しました。
React Navigationは3.x系になって前バージョンと随分趣が変わったようですが幸か不幸か筆者は3.xからのスタートだったのでネットの情報が少ない以外はそれほどに大きな困難を抱えることはありませんでした。
以下ナビゲートのを定義したApp.jsとメイン画面のソースです。
#App.js
```
import React, {Component} from 'react';
import {Platform, StyleSheet, Text,View} from 'react-native';
import { createStackNavigator, createAppContainer } from "react-navigation";
import HomeCamera from "./src/HomeCamera.js";
import HomeConf from "./src/HomeConf.js";
import HomeScreen from "./src/HomeScreen.js";
import HomeList from "./src/HomeList.js";

const AppNavigator = createStackNavigator(
  {
    Home: HomeScreen,
    Camera:HomeCamera,
    Conf: HomeConf,
    List: HomeList
  },
  {
    initialRouteName: "Home"
  }
);

const AppContainer = createAppContainer(AppNavigator);

type Props = {};
export default class App extends Component<Props> {
  render() {
   return (
    <AppContainer />
   );
 }
}
```
#HomeScreen.js

```
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, TouchableOpacity, View,Image} from 'react-native';
import { NavigationActions } from "react-navigation";

export default class HomeScreen extends Component<Props> {
  //コンストラクタ
  constructor(props){
    super(props); //必ず呼ぶ
  }

  render() {
   return (
     <View style={styles.container}>
     <Image style={{ width: 400, height: 200}} source={{uri:'https://yuap.jp/blog/wp-content/uploads/2018/09/reactnative.png'}}/>
     <TouchableOpacity onPress={() => this.props.navigation.navigate("List")} style={styles.capture}>
       <Text style={{ fontSize: 14 }}> List</Text>
     </TouchableOpacity>
     <TouchableOpacity onPress={() => this.props.navigation.navigate("Camera")} style={styles.capture}>
       <Text style={{ fontSize: 14 }}> Camera</Text>
     </TouchableOpacity>
     </View>
   )
 }
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent:'center',
    backgroundColor: 'white',
  },
  capture: {
    flex: 0,
    backgroundColor: 'aliceblue',
    borderRadius: 5,
    padding: 15,
    paddingHorizontal: 20,
    alignSelf: 'center',
    margin: 50,
  },
});
```


App.jsで定義している createStackNavigator 辺りが2.x系と大きく変わったようですね。
HomeScreen.jsのポイントは他のコンポーネントに遷移する時には

```
this.props.navigation.navigate("List")
```
というようにnavigateを使用することで、本関数は

```
import { NavigationActions } from "react-navigation";
```
とインポートすると使えるようになります。

以上でナビゲーションについての篇を閉じます。
Raspberry Pi（Raspbian）でLEDを点灯/消灯させるプログラムを作る

#はじめに
Raspberry Pi（Raspbian）でLEDを点灯/消灯させるプログラムの紹介です。

#必要なもの
- RaspbianがインストールされているRaspberry Pi
- ブレッドボード
- LEDx2
- 抵抗（100Ω）x2
- ジャンパー線（オス/メス）x3
- ジャンパー線（オス/オス）x2

#配線
GPIOとGNDならどこでも可ですが、今後の拡張性などを考えるとGPIOのみのピン（3, 5, 8, 10, 19, 21, 23, 24, 25以外）を使う方が無難だと思います。
この投稿では33（GPIO13）, 35（GPIO19）, 39（GND）ピンを使用しています。
![DSC_0203.JPG](https://qiita-image-store.s3.amazonaws.com/0/263360/ab2f6e54-d616-4949-11a2-2771d0c17e5b.jpeg)
![LED_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/263360/8d57024c-7afd-162f-ecf2-7b10b30765c7.png)

#プログラム
```led.py
#Import Files
import RPi.GPIO as GPIO
import time

#GPIO Settings
GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)

#Main
try:
    while True:
        GPIO.output(13, GPIO.LOW)
        GPIO.output(19, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(13, GPIO.HIGH)
        GPIO.output(19, GPIO.LOW)
        time.sleep(1)
        
except KeyboardInterrupt:
    GPIO.cleanup()
```

#解説
1. スイッチの制御に使用する`RPi.GPIO`ライブラリをインポートする
2. 時間を取得するために使用する`time`ライブラリをインポートする
3. GPIOのモードをBCMに設定する（物理的なピン番号ではなく、GPIO**を使用する）
4. GPIO13, GPIO19を出力端子に設定する（Hi=点灯, Low=消灯）
5. LEDを点滅させ続けるので`while True:`で無限ループさせる
6. LEDを1秒周期で交互に点滅させる
7. 解説6に遷移 or プログラムが終了するのを待つ
8. Control+Cが押されたらGPIOを解放してプログラムを終了する

#プログラムを実行してみる
1. プログラムを実行する
2. LEDが1秒周期で交互に点滅する![DSC_0207.JPG](https://qiita-image-store.s3.amazonaws.com/0/263360/27213475-9d3f-c76e-6a00-4d374c28dbef.jpeg)![DSC_0208.JPG](https://qiita-image-store.s3.amazonaws.com/0/263360/2c127781-430b-8040-b3ac-3088c81d3e27.jpeg)

#写真を撮るプログラムに組み込んでみる
以前作成した[写真を撮るプログラム](https://qiita.com/Yuta_Chief/items/97192cd1f1b719538629)のcamera_func(x)にLEDの点灯/消灯処理を組み込んでみた。
![DSC_0206.JPG](https://qiita-image-store.s3.amazonaws.com/0/263360/497ecf8d-dbf3-f7a4-76a6-44bcdc293725.jpeg)
![SW_LED_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/263360/b2783cc9-81f1-dbf1-50ac-d2f4e952c989.png)

```camera_v2.py
#Import Files
import RPi.GPIO as GPIO
import picamera
import time

#GPIO Settings
GPIO.setmode(GPIO.BCM)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

#Camera Settings
CAM_DIR  = "/home/pi/python/_photo/"

camera = picamera.PiCamera()

#Camera Function
def camera_func(x):
    if GPIO.input(26) == 0:
        GPIO.output(19, GPIO.HIGH)
        filename = time.strftime("%Y%m%d%H%M%S") + ".jpeg"
        save_dir_filename = CAM_DIR + filename
        camera.capture(save_dir_filename)
        GPIO.output(19, GPIO.LOW)
    else:
        GPIO.output(13, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(13, GPIO.LOW)

#Interrupt
GPIO.add_event_detect(26, GPIO.FALLING, callback=camera_func, bouncetime=200)

#Main
try:
    while True:
        pass

except KeyboardInterrupt:
    GPIO.cleanup()
```
変更前はスイッチを押しても写真を撮れているのかわからなかったが、変更後はスイッチを押した際、正常（写真が撮れている場合）なら緑色、異常（写真が撮れていない場合）なら赤色のLEDが点灯するので、何も無いよりはわかりやすくなった。

#参考
- [Raspberry Pi（Raspbian）で写真を撮るプログラムを作る](https://qiita.com/Yuta_Chief/items/97192cd1f1b719538629)
Gitlabとpythonでの開発

※Git初心者の備忘録なので悪しからず。

#初めてファイルをあげる

.gitigonoreの設置は以下を参照
・あとからまとめて.gitignoreする方法
[https://qiita.com/yuuAn/items/b1d1df2e810fd6b92574]
(https://qiita.com/yuuAn/items/b1d1df2e810fd6b92574)
・github/gitigonre
[https://github.com/github/gitignore/blob/master/Python.gitignore](https://github.com/github/gitignore/blob/master/Python.gitignore)


```
#gitの準備
$ cd existing_folder
$ git init                                           //gitリポジトリの作成
$ git remote add origin <GitURL>                     //リモートリポジトリの指定

#git ignore の設置
$ vim .gitignore
#vimが開くので、iキーを押してインサートモードにしたのち、
https://github.com/github/gitignore/blob/master/Python.gitignore
をコピーして貼り付け
escキーを押してモードを切り替え
:wq!キーで保存


#initial commit
$ git add .                                          //変更対象のファイル等を指定する
$ git commit -m "Initial commit"                           //変更状態の保存
$ git push -u origin master                          //リポジトリアップロード

#.gitignoreの設置

 
```

#ブランチの作成
```
$ git checkout -b 作成するブランチ名
```

#編集していくとき
・まず、全ブランチを引っ張ってくる
※参考
全ブランチをリモートリポジトリからpullする
[https://qiita.com/muraikenta/items/e590a380191971f9c4c3](https://qiita.com/muraikenta/items/e590a380191971f9c4c3)

```
$ for remote in `git branch -r`; do git branch --track ${remote#origin/} $remote; done
$ git fetch --all
$ git pull --all
```

・編集したいブランチに移動し、devブランチの状態に合わせる。

```
$ git checkout 作業ブランチ名
$ git merge dev
```

・内容に何らかの変更を加える

```
#任意の編集作業
```

・変更内容をローカルに保存

```
#add -Aは変更を全部記録する
$ git add -A
$ git commit -m commitの名前
```

・変更内容をリモートに保存

```
$ git push origin 作業ブランチ名 
```

・変更内容をdevブランチにも適用する

```
#被適用ブランチに移動
$ git checkout dev
$ git merge 適用ブランチ

#リモートに適用
$ git push origin dev
```

・devの変更内容をmasterブランチにもマージする（なるべく開発責任者only）

```
#devブランチをAWS環境用に編集したうえで
$ git checkout master
$ git merge dev
$ git push origin master
```

#mergeがconflictしたとき
```
#略
```
バレンタインデーにもらったチョコが本命かどうか判定するAIを実際に作って公開した(2019)

# TL;DR

今年もバレンタインデーが近いですね！[去年のもの](https://boomin.yokohama/archives/990)より、AIもフロントエンドも刷新してリリース！です。

バレンタインでもらったチョコが、本命かどうかは、世の男性にとって、重大な問題です。
**女性心理の機微に疎い`男子中高生、理系男子学生、男性エンジニア(偏見)`** を救うべく、__[実際にもらったチョコが本命かどうか判定するAIを開発しました](https://boomin.yokohama/archives/1357)__。

![apptop-min.png](https://qiita-image-store.s3.amazonaws.com/0/109411/40b0cf87-e0de-6cf5-8532-ef839d1612bf.png)


# 1. 男性エンジニアを悩ませるバレンタイン問題
## 1.1 バレンタインデー
世界中にあるイベントの一つに、2/14のバレンタインデー(Valentine’s Day)があります。
国や地域によって、その日の過ごし方などは異なるようですが、ここ日本では、女性から男性へチョコレートを贈る日、という __お菓子会社の戦略によって定着した文化__ があります（例えば[1]参照。諸説あり）。

[[1](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%AC%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%B3%E3%83%87%E3%83%BC#%E6%97%A5%E6%9C%AC)]によれば、1970年代後半頃に本命チョコを贈る習慣が定着したようです。ここから、さらにお菓子業界の商機ととらえた全国飴菓子工業協同組合は、義理チョコとホワイトデーという文化を創り出し、1984年をホワイトデー定着の年としました。

## 1.2 バレンタインデーの悲劇
しかし、このような文化は悲劇を起こしました。それは、女性から贈られたチョコが、本命なのか義理なのかがはっきりしないケースが登場したためです。はっきり口にせず、**以心伝心や忖度を是** とする日本の文化が、**多くの迷える男性を生み出して** しまうことになりました。

このような背景から、贈られたチョコレートが、本命なのか義理なのかをはっきりさせる社会的ニーズが産まれました。図1に、この状況証拠を示します。世の中のどれだけの人が検索をすれば、Googleの検索サジェスチョンにこのような結果をもたらすのでしょうか。これは、もはや国民的課題といえるでしょう。
以降、これを **バレンタイン問題** と呼ぶことにします。

![図1](https://i0.wp.com/boomin.yokohama/wp-content/uploads/2018/03/problem.png?ssl=1)
図1：バレンタイン問題 – バレンタインのチョコレートが本命か義理かを判断する社会的ニーズ

## 1.3 バレンタインデーの救世主

一方、最近の機械学習手法の発達は目覚ましい物があります。AIすなわち、機械学習がこの バレンタイン問題 を解決する手段になりえることが示されました[[2](https://boomin.yokohama/archives/1357)]。これは画期的な観点であると思われましたが、開発したエンジニアのみが実行、評価できるものでした。これでは、__迷える男子中高生、理系男子大学生、そして男性エンジニア__を救う ことはできません（筆者の独断と偏見による）。

また、男性の立場からすると、ホワイトデーにお返しを行う義務が、暗黙のうちに発生します。ここで不適切な対応をとると、**その後の長期間にわたり、生きづらい人生を歩む**ことになりかねません。
そのため、贈られたチョコレートに対して、どのくらいのお返しを行えばよいのか、その指針を示すことができれば、悩める男性に対して有効なサービスとなり得ると思われます。図2に、悩める男性像の一例を示します。

![](https://i1.wp.com/boomin.yokohama/wp-content/uploads/2018/03/okaeshi.png?resize=640%2C230&ssl=1)
図2 バレンタインのお返しに苦悩する男性の一端

# 1.4 バレンタイン問題の解決方法
以上のことから、本記事では[[2](https://boomin.yokohama/archives/1357)]をさらに発展させ、バレンタイン問題の一助となることを目指すものです。

* 本命チョコと義理チョコを判別する学習モデルを開発する
    * 二値分類と呼ばれる、機械学習における代表的な手法を用いたアプローチをとる
    * これを本命・義理チョコ分類問題と呼ぶ
* 開発した、構築した学習モデルをサービス化して公開する
    * PC、スマホのどちらからでも使えるように、Webサービス化を行う
* 義理チョコと本命チョコを分類する際の確率を算出する
    * 定量的に判断指標を示すことで、悩める男性自身の判断を促す
    * 確率を用いることで、ホワイトデーのお返し予算の提案も併せて行う

実際のイメージを、以下に示します。

![](https://camo.qiitausercontent.com/970a0d2f36137b26a680e627cb74d2a819f2787e/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3232313133392f34653162343231322d363564652d316466302d613638632d6435393536303262613731662e706e67)


なお、筆者が人生でチョコレートを貰った回数（個数）は、年齢のおよそ25%以下である。
**チョコ欲しい**。

# 2. DNNでの学習

学習データの収集方法、学習データの前処理、学習モデル、モデルの精度などについて、[以下URL](https://boomin.yokohama/archives/1357)にて紹介しています。
https://boomin.yokohama/archives/1357

# 3. お返し予算の算出

AIで判定されたチョコ画像の本命度をもとに、お返し予算の算出方法について[以下URL](https://boomin.yokohama/archives/1413)にて紹介しています。
https://boomin.yokohama/archives/1413
Google SpreadsheetをURLダウンロードする


##使用用途
・Google formなどで集めた情報が書き込まれたスプレッドシートを取得し、
ロボに読み込ませる

#方法
Excel形式で全てのシートをダウンロードしたいとき
https://docs.google.com/spreadsheets/d/FileID/export?format=xlsx

Excel形式で特定のシートをダウンロードしたいとき
https://docs.google.com/spreadsheets/d/FileID/export?format=xlsx&gid=SHEETID

CSV形式でダウンロードしたいとき
https://docs.google.com/spreadsheets/d/FileID/export?format=csv&gid=SHEETID
※日本語だと文字化けします

#解説
###https://docs.google.com/spreadsheets/d/
固定値です。特に何も考えなくて大丈夫です。

###FileID
スプレッドシートのURLの /d/ と /edit の間の文字です。
例)/d/  *1wxPAy1hStI322aa1yp17e14467e0pn97gGnwvJ0*←ココ！　/edit#gid=12345678

###export?format=xlsx
出力形式です。
・エクセル形式にしたい　⇒ xlsx
・CSV形式にしたい　⇒CSV

###gid=SHEETID
スプレッドシートのシートIDです
例)/d/1wxPAy1hStI322aa1yp17e14467e0pn97gGnwvJ0/edit#gid= *12345678* ←ココ！

##使用方法
###① http request
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298686/3977cd2b-9d98-9a64-0b4f-26d98e6a969b.png)
uipathの場合、HTTP Requestというアクティビティがあるので、そちらを使用します。
1.EndPointにURLを入力
2.ResoucePath にファイルフルパスを入力
※1,2共に柔軟に対応できるよう、変数で渡してあげましょう
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298686/82178fc2-abe6-bde6-fba8-f537805faef5.png)

※注意する点としては
ダウンロードした場所に既にファイルがある場合、*上書き*されます

###②Open Browser
セキュリティの都合上、httpリクエストを許可されていないときなどに使用します。 

※共通する注意点
1.Googleにログイン
⇒ログインされていないときの回避処理を入れましょう

2.スプレッドシートへのアクセス権限
⇒アクセス権限がない時はエラーメールを送ってあげるなどの処理を入れましょう

3.ダウンロードするファイルは上書きされない
⇒Deleteアクティビティであらかじめ消しておくような処理を入れましょう。
  ContinueOnErrorをTrueにしていれば、ファイルが存在しなくてもエラーが出ません

####IEの場合
ダウンロードしますか？のダイアログが出現します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298686/dbaa6f3a-1b42-e3d0-a9e3-4418a19d2863.png)
↓
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298686/ee67dbc7-12b2-1e5b-3e16-24a656c11c57.png)

1.ボタン[保存]をClick
2.Find Element でダウンロードの表示が出現するまで待つ
3.close tabや　kill processでIEを終了

####chromeの場合
1.いきなりダウンロードが開始します
2.close tab やkill processでchromeを終了
![image.png](https://qiita-image-store.s3.amazonaws.com/0/298686/c1eb1950-3e1d-9271-8b1d-e9067a1ffc0f.png)
※Path Existsでダウンロードが完了したのを確認後、消すようタイミングを工夫しましょう。
※タイミングによっては上手く自動ダウンロードが働かない時があるので基本的にはIEを勧めます。

##備考
スプレッドシートのURLダウンロードは結構便利で、メールに書いたり色々出来ます。
また、http requestはGoogle spreadsheet以外でもファイルをダウンロードするときに使えます。
初めてのVulkanプログラミング step5 グラフィクスパイプラインとは、

[目次に戻る](https://qiita.com/tositada_nakada/items/db0f01c1c8c2945f786b)

ソースコードは以下の場所に置いておきます。各自のバージョンに合わせたプロパティ設定をしてから自由にご利用ください。

[GitHub](https://github.com/nakadasanda/vulkanAppaddcal2018)

##はじめに
5章では、三角形を描くグラフィックスパイプラインを作成します。
グラフィックスパイプラインとは、一言でいうと、3Dオブジェクトをディスプレイに映し出す処理のことです。
![20160508210300.png](https://qiita-image-store.s3.amazonaws.com/0/251306/8c583a6f-492d-da04-3d30-c861e9df0260.png)

詳細に中身を見ていくと以下のような、ものがあります。

![スケッチ (4).png](https://qiita-image-store.s3.amazonaws.com/0/251306/dab83ea9-3165-0025-bca1-64764e023f8e.png)
####　アセンブラ入力
3D,2Dオブジェクトから頂点データを収集し、インデックスバッファーに格納します
#### バーテックスシェーダー
インデックスバッファーから、受け取った三角形の頂点の座標をスクリーン上のどこに配置するか計算して決める。
#### テッセレーション
メッシュ品質を向上させるために、一定のルールに基づいてジオメトリを細分化します。
左のキャラクターから、右のキャラクターのように、テッセレーションを行うことによってより複雑な凹凸を作り上げることができます。
![スケッチ (5).png](https://qiita-image-store.s3.amazonaws.com/0/251306/8a51d8f9-e8e1-d878-a9a6-12a29ea03b04.png)

#### ジオメトリシェーダー
オブジェクト内の頂点の集合を加工する。ジオメトリシェーダーにより、実行時に頂点数を増減させたりすることができる
#### ラスタライズ
線や頂点の集合から、ドットの集合に変換します。
#### フラグメントシェーダ
ドットの集合にどのような色を付けるのか決定します。
#### カラーブレンディング
同じ画素に異なるマッピングが重なったときにどのように処理するか計算します。

緑色の段階は、固定パイプラインと呼び、事前に動作は定義された仕様に沿ってパラメータを変更することで微調整することができます。
オレンジ色の段階は、自分のプログラムをGPUにアップロードして、必要な操作を適用することができます。これによりフラグメントシェーダーを用いて、ライティングから、レイトレーシングまで広く追加することができます。

##終わりに
次回は、バーテックスシェーダーとフラグメントシェーダを作成します。

##連絡先
tweeter: tositada_nakada
mail: nakadasanda@outlook.com

## 寄付

paypal: [tositada_nakada](https://www.paypal.me/nakadasanda)
Amazon:[欲しいものリスト](http://amzn.asia/fGpGuJo)
JSXの基本

##はじめに
JSXとは、JavaScriptの拡張構文です。
実行時、内部的にはJavaScriptにトランスパイルされます。

**具体的には、React.createElementメソッドに変換される**

##複数の要素を列挙することができない
複数の要素を列挙することができないため、以下のコードは不可です。

```sample.js
React.DOM.render(
  <h1>Hello, World</h1>
  <p>こんにちは、世界</p>,
  document.getElementById('root')
);
```
**複数の要素全体を``<div>``などの要素で括る**

```sample.js
React.DOM.render(
  <div>
    <h1>Hello, World</h1>
    <p>こんにちは、世界</p>,
  </div>
  document.getElementById('root')
);
```
**または、``<React.Fragment>``で、複数の子要素をまとめる**

```sample.js
React.DOM.render(
  <React.Fragment>
    <h1>Hello, World</h1>
    <p>こんにちは、世界</p>,
  </React.Fragment>
  document.getElementById('root')
);
```

##空要素は<~ />で終える
JSXでは、XMLと同じように、空要素は``<~ />``で終えなければなりません。

```sample.js
//ダメなコード
const tag = <img src={logo}>;

//正しいコード
const tag = <img src={logo} />;
```
[空要素とは](https://gingdesign.com/website/words/ka/emptyelement.html)

##JavaScriptの予約語は使えない
JSXはあくまでもJavaScriptの拡張構文なので、JavaScriptの予約語である``class``, ``for``などの属性は使えない。

##JavaScriptを使う場合は{}で埋め込む
JSX内でJavaScriptを使う場合は、``{}``で埋め込むことができる。

```sample.js
const name = 'Tom';

ReactDOM.render(
  <p>Hello {name}.</p>,
docunent.getElementById('root')
);

#=> Hello Tom.
```
Windows10 HomeでDocker環境を構築

# サーバーサイドの開発をするために
Dockerでローカル環境構築を検討したのですが、
Windows10 Homeだと、Docker Toolboxになるし・・・
WSLだとdocker-composeが動かないし・・・
ほかにどういう環境がイケてるのだろうかと調べてみると、
VagrantでVirtualBox上にCoreOSインストールしてDockerを動かすのが良いらしいです。
CoreOS使う利点としては下の３つかなと思いました。

- docker-composeが動く
- Dockerインストール済
- 移植性が高い

下の３つをダウンロードして、適当にインストールします。
# Vagrant
https://www.vagrantup.com/

# Virtual Box
https://www.virtualbox.org/wiki/Downloads

#CoreOS
https://github.com/coreos/coreos-vagrant


# Vagrantのプラグインインストール
ファイル共有で使用する。
`vagrant plugin install vagrant-winnfsd`
 ※nfs形式以外で共有ディレクトリで`npm install`実行するとエラーになります。
VirtualBoxと連携する場合は必要になるみたい
`vagrant plugin install vagrant-ignition`

# Vagrantfileの編集
### Windowsのファイルを共有する設定をします。
共有ディレクトリ指定
35行目　`$shared_folders = {'Windows側' => 'CoreOS側'}`

### ポートフォワード指定
36行目 `$forwarded_ports = {CoreOS側=> Windows側}`

### 共有ディレクトリ指定
148行目 `config.vm.synced_folder host_folder.to_s, guest_folder.to_s, id: "core-share%02d" % index, nfs: true, mount_options: ['nolock,vers=3,udp']`
↓に変更
148行目 `config.vm.synced_folder host_folder.to_s, guest_folder.to_s, id: "core-share%02d" % index,  type: "nfs"`
※nfs: trueオプションについて調べてみたけど情報が全然でてこない・・・・
　[オフィシャルのマニュアル](https://www.vagrantup.com/docs/synced-folders/nfs.html)

適当な行にdocker-composeインストールコマンドを追加


````
      $get_compose = <<-'EOF'
        sudo mkdir -p /opt/bin
        sudo curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /opt/bin/docker-compose
        sudo chmod +x /opt/bin/docker-compose
      EOF
````

# 起動
CoreOSのページのReadmeに書いてあるとおりに `vagrant up`すれば起動するはず。
https://github.com/coreos/coreos-vagrant
Rubyで深いHashが書きまくれるやつが欲しくなった

Rubyの深いハッシュ、例えば地球>日本>東京>目黒区>大岡山は

```ruby
{
  earth: {
    japan: {
      tokyo: {
        meguro: {
          o_okayama: {
            # something
          }
        }
      }
    }
  }
}
```

こういう感じのHashになって、`{}`を書くことに疲れてしまいそうとおもった。
ネストしたHashを書きまくれる`N`というクラスを定義してみた

```ruby
class N < Hash
  def initialize(*args)
    return self if args.length == 0
    key = args.shift
    case args.length
    when 0
      self[key] = nil
    when 1
      self[key] = args.first
    else
      self[key] = N.new(*args)
    end
  end
end
```

```ruby
oookayama = %i(earth japan tokyo meguro o_okayama)
#=> [:earth, :japan, :tokyo, :meguro, :o_okayama]
N.new(*oookayama, 'something')
#=> {:earth=>{:japan=>{:tokyo=>{:meguro=>{:o_okayama=>"something"}}}}}
```

階層構造を変数にしてそのまま渡せるのでなんかわかりやすいかもと思ったけど、
使い所が思い浮かばなかった。

おわり。
xonshでpromptのgitstatusの表示をカスタマイズする

xonshでは、`{gitstatus}`を含んだプロンプトの書式を`$PROMPT`に格納することで、gitの状態をプロンプトに追加できる。

https://xon.sh/tutorial.html#customizing-the-prompt

この機能のマークや色などの書式変更は、`$XONSH_GITSTATUS_*`を変更することで実現できる。

https://xon.sh/envvars.html#xonsh-gitstatus

それ以上のカスタマイズは、promptで実行する関数は、`$PROMPT_FIELDS["some_command"] = lambda: xxx`と関数を定義し、`{some_command}`を書式に追加する必要がある。

ちょっとした改修であれば、元の`{gitstatus}`のコードは以下にあるため、これをコピーして（xonsh:2条項BSDライセンス）流用すると簡単である。

https://github.com/xonsh/xonsh/blob/master/xonsh/prompt/gitstatus.py

私の場合、masterの時には気づくようにしたいため、ブランチに絵文字を追加した。

```python3
def gitstatus_prompt()
    
    ~
    
    ret = ""
    if s.branch == "master":
        ret += "🌟"

    ~
```

これを、`$PROMPT_FIELDS`に追加し、書式に関数を追加すれば良い。

```python3
$PROMPT_FIELDS["git"] = gitstatus_prompt
```

やはりPythonでShellを拡張できるxonshは便利です！！
Djangoの環境構築の方法

mbフォルダに環境を構築する時のやり方

```ruby:qiita.rb
cd ~/Desktop
mkdir mb
cd mb
pipenv install django==2.1
pipenv shell
(mb) $ django-admin startproject mb_project
(mb) $ python manage.py startapp posts
```

これでrunserverを実行すれば、いつものロケットの画面が現れて
The install worked successfully! Congratulations!と表示される。
AWS Route53のホステッドゾーンが削除できない

今月の利用料金を見てみると、Route53に$0.5の請求が。。

![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/350277/adfe9ea8-899e-9a4d-87a6-d57602dd37c2.png)

あれ、何か使ったっけと思いながらコンソールから削除しようとするとエラーでできない。。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/350277/e39e5346-96a0-65ec-bc9e-c98a7b62b462.png)

ネットを色々調べた結果、ECSのサービスがRoute53を使っているのではという情報を見ました。

コンソールを確認

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/350277/cde51e5a-9ec3-c584-5854-29238a793c9e.png)

⇒サービスなし

CLIで確認

![e2.png](https://qiita-image-store.s3.amazonaws.com/0/350277/1e3a86f9-fd7e-8279-78da-ded541094bde.png)

⇒サービスあり！

なぜ、コンソールで見れないと思いながら、
サービスを削除しホステッドゾーンも削除しました。

これにより解決。

```:コマンド

'サービスの確認
aws servicediscovery list-services

'サービスの削除
aws servicediscovery delete-service --id=srv-xxxxxxxxxxxxxxxx

・ネームスペースの確認
aws servicediscovery list-namespaces

・ネームスペースの削除
aws servicediscovery delete-namespace --id=ns-xxxxxxxxxxxxxxxx
```
【Blender】UV展開とベイクをしてからUnityへ取り込む

環境メモ

⭐️Mac OS Mojave バージョン10.14
⭐️Blender v2.79.6
⭐️Unity 2018.2.15f1
⭐️Mac Book

BlenderでUV展開とベイクをしてからUnityへ取り込む

![s_001.png](https://qiita-image-store.s3.amazonaws.com/0/93155/6cd7c8a8-e5d9-4636-f0fd-7e0da51b366e.png)

Unityへ取り込み完了↓↓↓↓
![s_002.png](https://qiita-image-store.s3.amazonaws.com/0/93155/27a04bf2-9f33-570f-da00-b8a4fea4a2ab.png)


<font color="Magenta">画像が多いとQiitaの容量オーバーで画像が貼り付けられなくなるので</font>
詳細は、「はてなブログ」に記載してます↓
[かぴばらさんの覚書ブログ nonkapibara](https://nonkapibara.hatenablog.com/entry/2019/02/09/114806)

</br>
</br>
Kubernetes オートスケーリング機能の自習メモ

KubernetesのオートスケーリングSIGには、複数のサブプロジェクト[1,2]があります。その中でも、特に注目するべきものが、次の２つの活動になると思います。

* Horizontal Pod Auto scaler (HPA)
* Cluster Autoscaler (CA)

## HPAとCAの両者の必要性

HPAは、ポットのCPUの使用率を監視しながら、ポッドのレプリカ数を増減するものです。一方、CAは、リソース要求に対してノードの資源が不足している状態を解消するために、ノードを追加します。

HPAは、ポッドのCPU使用率が閾値を超えると、レプリカ数を増やして処理能力を向上させますが、既存のノード数に、新たにノードを追加してくれる訳ではありません。クラウドを利用する場合、ノード数はコストに関わりますから、処理の要求量の少ない時間帯にはノード数を減らして費用を節約して、逆に、要求量の大きな時には、ノード数を増やして要求に答えるようにしたいものです。しかし、HPAだけを利用していたのでは、このニーズに答えることができません。

そこで、CAの出番となります。CAは、ポッドのレプリカ要求数を稼働させるために必要なノード数を、クラウドプロバイダーのAPIと連携して、ノード数を必要数まで増加させます。もちろん、要求量が減れば、ノードをキャンセルして、無駄なコストが発生しないように働きます。

## クラウドベンダーのオートスケール機能と対比

クラウドプロバイダーにも、仮想サーバーのCPU稼働率に応じて、仮想サーバー数を増減するオートスケーリングのサービスがあり、Kubernetesのノードに対して、この機能を適応することで、無駄なコストを削減するように働いてくれます。 一方で、HPAとCAを組み合わせて利用することの価値は、クラウド事業者に依存しないKubernetesプロジェクトの中で開発された機能であるため、ベンダーロックインを回避して、マルチクラウドやハイブリッドを実現しやすくなることだと思います。

## IBM Cloud Kubernetes Service でのCA利用

IBM Cloud Kubernetes Service では、IaaSのCPU使用率などのメトリックスで、仮想サーバー数をスケールするのではなく、CAをベースに開発したクラスタ・オートスケーラーのベータ版 IBM Cloud Kubernetes Service cluster autoscaler (beta) の提供[3,4](2019年2月8日現在)でしたが、2019年3月11日に正式提供が開始されました[6]。

この設定は、IBM Cloud Docに詳細に解説[3]されていますから、そのとおりに、インストールすれば、利用できるようになります。



## 参考資料

[1] Autoscaling Special Interest Group, https://github.com/kubernetes/community/blob/master/sig-autoscaling/README.md
[2] Kubernetes Autoscaler, https://github.com/kubernetes/autoscaler
[3] IBM Cloud Kubernetes Service cluster autoscaler (beta), https://cloud.ibm.com/containers-kubernetes/solutions/helm-charts/ibm/ibm-iks-cluster-autoscaler
[4] Scaling clusters (preview beta), https://cloud.ibm.com/docs/containers/cs_cluster_scaling.html#ca
[5] Frequently Asked Questions, https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md
[6] Worker Node Auto-Scaling GA in IBM Cloud Kubernetes Service,https://www.ibm.com/blogs/bluemix/2019/03/worker-node-auto-scaling-ga-in-ibm-cloud-kubernetes-service/
a[:0] と append の秘密

（http://zetamatta.hatenablog.com/entry/2019/02/05/161003 より転載）

[io.Reader のプリプロセッサな io.Reader を作る](https://qiita.com/zetamatta/items/9312375f90f7b5bee85f)の中で、["tidwall/transform"](https://github.com/tidwall/transform)で使われていると紹介したテク：`a = a[:0]` は領域のサイズをリセットするが、`a = make([]T,0,cap(a))` と違って、使っていたメモリブロックを再利用するため、allocation 回数を削減できるというものだった。

だが、旧`a` の領域が他で使われていないかを気にせず、無頓着に使うと append でおかしいことになる。たとえば

```go
a := []string{ "a","b","c" }
b := a[:0]
b = append(b,"1")

fmt.Printf("%+v\n",a)
```

とすると a の内容が [1 b c] となる。これは append が領域を上書きで使用するためだ。

append 側で他所で使われているかチェックしてくれたらよさそうな話ではあるが、おそらく物理的に無理だろう。というのも参照カウンタ方式ではなく、マーク＆スイープ方式の Garbage Collector を使っている場合、参照されている場所が自分を含めて２個以上あるか、調べようがないのだ。（GCの中身のコードならばできなくもないだろうが…）

となると、常に他で使われているという前提で append を実装しないと、上のような状況は避けられないわけだ。そういう append ちょっと作ってみよう。

```go
package main

import (
	"fmt"
)

func appendStr(a []string, b string) []string {
	r := make([]string, len(a)+1)
	copy(r,a)
	r[len(a)] = b
	return r
}

func main() {
	a := []string{}
	for i := 0; i < 10; i++ {
		a = appendStr(a, fmt.Sprintf("%d", i))
	}
	fmt.Printf("%+v\n", a)
}
```

こんな実行効率わるそうなの、みんな使いたいと思うだろうか？結局、みんなオリジナル append を使うことになるだろう？（でも、スクリプト言語では効率が悪くても平気でやってそうではある）。

-----

こういった append の挙動は一見奇異なものに見え「Go言語は糞」と罵られる一因ではある。だが、C言語を知る者は append は realloc と対応する関数だから、領域拡張前の a が正常に使える保証はなく、使うべきではないと直感的に分かっている人が多い。

人によって、Go言語の評価が「サイコー」or「糞」と正反対になるのは、そういうあまり言及されない前提知識や慣れ（訓練されたC言語プログラマはエラーチェックコードが多くてもまったく気にしない等）の有無が大きいのではないだろうか。
1つの親レコードに対して複数の子レコードである画像をアップロードしたい。

5日間くらい詰まって進まなかったので、同じところで詰まる人がいないようメモ

# やりたいこと
フリマアプリのように、出品するアイテムに複数の画像をアップロードする機能を作りたい。

# 環境
Rails 5.0.7.1

# 使用するgem
- carrierwave
- mini_magick

#手順
1. gemをGemfileに記述し、bundle install
2. モデル作成
3. アップロードのためのviewを作成
4. コントローラー作成

以上で完成！
手順2から解説

# Model作成
**コンソールでモデル作成**

```コンソール
rails g model Product
rails g model Item_image
```

**マイグレーションファイルにカラムの記述を行う**
create_products.rb


```ruby
class CreateProducts < ActiveRecord::Migration[5.0]
  def change
    create_table :products do |t|
      t.string :name,         null: false, default: ""
      t.references :user,     foreign_key: true
      t.timestamps null: false, foreign_key: true
    end
  end
end
```

create_item__images.rb

```ruby
class CreateItemImages < ActiveRecord::Migration[5.0]
  def change
    create_table :item_images do |t|
      t.string :name, null: false, default: ""
      t.references :product, foreign_key: true
      t.timestamps
    end
  end
end
```

```ここに言語を入力
rake db:migrate
```

**各モデルにアソシエーションを記述**
product.rb
accepts_nested_attributes_forと記述することで、親レコードの作成と共に子レコードの作成が可能となる。

```ruby
class Product < ApplicationRecord
  has_many :item_images, :dependent => :destroy
  accepts_nested_attributes_for :item_images, allow_destroy: true
end
```

item_image.rb
uploaderをマウントするコードを記述

```ruby
class ItemImage < ApplicationRecord
  mount_uploader :name, ImageUploader
  belongs_to :product, optional: true
end
```

# View作成
view側でアップローダーを作成する。
1つのアップローダーで画像の複数選択を出来るようにするためには、multiple: trueを記述する必要がある。
multiple: trueを記述した場合、paramsには配列として渡されるので、コントローラー側で配列の中身を取り出す処理が必要になる。

```haml
= f.fields_for :item_images do |i|
  = i.file_field :name, multiple: true, type: 'file', name: "item_images[name][]"
```

# Controller作成
ストロングパラメーターの記述

```ruby
private
def product_params
  params.require(:product).permit(
    :name,
    item_images_attributes: [:name])
end
```

newアクションでインスタンス生成し、createアクションで保存の処理を行う。
この際、params[:item_images]['name']の中身は配列なので、それぞれ@item_images取り出す処理を行う。

```ruby
def new
  @product = Product.new
  @item_image = @product.item_images.build
end

def create
  @product = Product.new(product_params)
  if @product.save
    binding.pry
    params[:item_images]['name'].each do |a|
      @item_image = @product.item_images.create!(name: a)
    end
    redirect_to root_path, notice: '出品しました。'
  else
    render :new
  end
end
```

以上で完成。

参考記事
[CarrierWave Upload Multiple Images [2018 Update]](https://kolosek.com/carrierwave-upload-multiple-images/)
fish 疑似ヒアドキュメント

fishでヒアドキュメント。変数を展開したかったので、sedで書き換え
他に良い方法があれば知りたい

```
mkdir ~/workdir
string trim '
{ 
  "cidrBlock" : "0.0.0.0/0",
  "networkEntityId" : "sedstring"
}
' > ~/workdir/routetable_rule.json
sed -i "s/sedstring/$ig_ocid/g" ~/workdir/routetable_rule.json
```
amply でチームで開発するときは amplify cli の multienv 版を使おう

## はじめに

amplify で作ったリソースを Git 管理するさい、何をコミットして何をコミットしないかで悩んだことはありませんか？ また、チームの他のメンバーがコミットしたリソースを自分の環境にチェックアウトしたとき、デプロイができなくなった経験はないでしょうか？
そんなときは amplify-cli の beta版 である multienv [[1][multienv]] を試してみましょう。

## amplify-cli multienv を使うメリット

1. デプロイ環境の分離
2. amplify init 時にコミットしなくて良い資材を .gitignore に自動追加してくれる

私の場合はとりあえず 2番目の目的のためにインストールしました（何を gitignore に追加するべきなのかについて、公式ドキュメントに記載が見つけられなかったので。。こちらの [github issue][gitignore] でも multienv を使うようにガイドされています。）。デプロイ環境の分離もできるようなので、**これからリソースを作ろうとしている人は multienv 版を試してみることをおすすめします**。

## インストール

`@aws-amplify/cli` でなく `@aws-amplify/cli@multienv` をインストールします（**注1**）。

```
npm install -g @aws-amplify/cli@multienv
``` 

---
**[!] 注1**: 公式ドキュメント [[1][multienv]] にもあるとおり、 **multienv版をインストールすると、もともとあった amplicy-cli が multienv 版に置き換わります** 。既存のプロジェクトに意図しない影響を与える可能性があるので、すでに amplify-cli で環境構築してある場合は注意してください（グローバルでなく、まずはローカルにインストールしてみて試してみるなど）。

---

## サンプルプロジェクトの作成

```
mkdir amplify-multienv-example
cd amplify-multienv-example
```

```
amplify init
```

普通の amplify-cli と同様、対話的に設定の入力を求められます。
multienv を使った場合の違いとして environment について聞かれます。
ここでは開発環境として `dev` を指定します。

```
? Enter a name for the environment dev
```

すべての質問を入力し終えると、 `.gitignore` が自動的に作成され、コミットする必要のない資材のパスが追加されています。

```:.gitignore
#amplify
amplify/\#current-cloud-backend
amplify/.config/local-*
amplify/backend/amplify-meta.json
aws-exports.js
awsconfiguration.json
```

multienv で amplify init したときのもう一つ違いとして、 `team-provider-info.json` というファイルが `amplify` フォルダに作られていることがわかります。

```json:amplify/team-provider-info.json
{
    "dev": {
        "awscloudformation": {
            "AuthRoleName": "amplifymultienvexamp-20190209112419-authRole",
            "UnauthRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/amplifymultienvexamp-20190209112419-unauthRole",
            "AuthRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/amplifymultienvexamp-20190209112419-authRole",
            "Region": "ap-northeast-1",
            "DeploymentBucketName": "amplifymultienvexamp-20190209112419-deployment",
            "UnauthRoleName": "amplifymultienvexamp-20190209112419-unauthRole",
            "StackName": "amplifymultienvexamp-20190209112419",
            "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/amplifymultienvexamp-20190209112419/ce6b1060-2c11-11e9-ade2-0a29b069fc22"
        }
    }
}
```

amplify リソースを作成したときの Cloudformation stack の情報が記載されていることがわかります。このファイルをメンバーとシェアすることで、同じ CloudFormation Stack に対して push/pull することができるようになります。

**注意**: AWSアカウントIDなどが記載されているので、**リポジトリを Public に公開する場合は上記のファイルはコミットしないようにしましょう**。

## 終わりに

これで、複数のメンバーで amplify のプロジェクトを共有することが問題なくできるようになりました。
気が向いたらデプロイ環境の分離についても試してみようと思います。

## 参考


1. [Multiple environments and team workflows (beta)][multienv]
2. [amplify/.config should be in .gitignore?][gitignore]
3. [Sharing projects outside the team ][team-provider-info]

[multienv]: https://aws-amplify.github.io/docs/cli/multienv?sdk=js
[gitignore]: https://github.com/aws-amplify/amplify-cli/issues/38
[team-provider-info]: https://aws-amplify.github.io/docs/cli/multienv#sharing-projects-outside-the-team-
【便利！】pandas-profiling（Python）による簡易データ解析

# pandas-profilingとは？

pandas-profiling は、pandas の DataFrame のプロファイリング結果をまとめて出力できるライブラリです。
DataFrame の基本的な統計量や相関係数などを一度にまとめて確認でき非常に便利です。


**特徴**
・ 使いやすい（１行のコードで実行可・パラメータ設定不要）
・ 手っ取り早く多角的にデータを解析してくれる
・ グラフを出力しビジュアル面でも分かりやすい


参照元データ
Github : https://github.com/pandas-profiling/pandas-profiling
Demo : https://nbviewer.jupyter.org/github/JosPolfliet/pandas-profiling/blob/master/examples/meteorites.ipynb

# インストール〜実行

データはKaggleのTitanicのTrainデータを使用します
https://www.kaggle.com/c/titanic/data

```py
# 未インストールの場合はpipでインストール
pip install pandas-profiling
```
```py
# ライブラリをインポート
import pandas as pd
import pandas_profiling
```
```py
# データファイルを読み込む
df = pd.read_csv('titanic/train.csv')
```
```py
# 実行
pandas_profiling.ProfileReport(df)
```
4つのセクションに分かれて分析結果が出力されます。

<img width="970" alt="Screen Shot 2019-02-09 at 11.12.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/278569/13986c80-7322-1fb1-cd97-d1d068c91285.png">
**①Overview**
データ全体の情報を表示してくれます。
欠損値の割合やデータ型なども一目で確認できますし、Warningsの部分では各特徴量の注意点（欠損値が多い、0の割合が多い...等）を教えてくれます。

<img width="968" alt="Screen Shot 2019-02-09 at 11.12.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/278569/8645a511-a347-4eb4-6bd8-b960192a4366.png">
**②Variables** 
各変数に対して簡単な分析結果が得られます。
データ型に応じてグラフの形態が変わり非常に親切です。
欠損データが目立つと赤で強調されます。

<img width="956" alt="Screen Shot 2019-02-09 at 11.14.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/278569/3d0d35f1-b4f4-50a0-74aa-a801b128ffb4.png">
**③Correlations**
ヒートマップで相関関係を可視化します。
相関の強い変数のペアを視覚的に理解できます。
ピアソンとスピアマンの両方の結果を出力してくれます。

<img width="968" alt="Screen Shot 2019-02-09 at 11.17.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/278569/0eac9527-38ed-664e-6f52-8f5609af02de.png">
**④Sample**
df.head()と同じ出力を表示。
基本的にデータを扱う際、必ず.head()は使うので手間を省けます。


# 使ってみた感想

とにかくスピーディなのがいいですね。
これだけでは不十分ですが、ざっくりデータを分析する際に非常に便利です。
EDA (探索的データ解析) の第一歩として非常に有用だと感じました。
Kaggleなどのコンペでも１発目に使っていきたいです。
Terraformのassociate_public_ip_addressの差分をなくす

# はじめに
`terraform plan`とか`terraform apply`した時に出てくる`associate_public_ip_address`の差分をなくす方法
![associate_public_ip_address.png](https://qiita-image-store.s3.amazonaws.com/0/169814/a98eee9c-655d-c76b-8287-367a2f9ea28a.png)
`associate_public_ip_address`を設定している状態でインスタンスが停止してたりすると出てきます

# 結論
1. `associate_public_ip_address`の設定は削除
2. サブネットの設定に`map_public_ip_on_launch=True`を追加

これでパブリックIPアドレスを付与しつつ、Terraformでの変更がいかなる場合も出なくなります。

<details><summary>参考までに2.のサブネットの設定はコンソール画面だとこうです</summary><div>
サブネットの設定で**自動割り当てIP設定の変更**を<font color="Red">**有効**</font>にする

|![自動割り当てIP設定の変更.png](https://qiita-image-store.s3.amazonaws.com/0/169814/24b3ea03-a055-9a8e-37ff-0e3059e03e21.png)|
|:-:|

|![自動割り当てIP設定の変更2.png](https://qiita-image-store.s3.amazonaws.com/0/169814/187b1cd6-3ab1-4301-677e-ed19973db6eb.png)|
|:-:|

</div></detail>


# パブリックIPアドレスの付与
インスタンスにパブリックIPアドレスを付与する方法は大きく分けて以下の3つです。

1. 自動割り当てIPの設定が有効になっているサブネットにインスタンスを立てる
 - Terraformの`map_public_ip_on_launch`で設定
1. インスタンスの起動時のパブリック IP アドレス割り当てを有効にする
 - Terraformの`associate_public_ip_address`で設定
1. EIPをインスタンスに割り当てる

AWS公式：[IPアドレス指定](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-ip-addressing.html#vpc-public-ipv4-addresses)

## 設定の組み合わせによるパブリックIPアドレスの付与
上で説明した設定を有効にしたり、無効にしたりした時のIPアドレスの状態が以下の表です。
**インスタンスの設定が優先されます**

|No.|サブネットの設定|インスタンスの設定|パブリックIPアドレス付与される？|
|:-:|:-:|:-:|:-:|
|1|有効|有効|<font color="Red">**付与される**</font>|
|2|有効|無効|付与されない|
|3|有効|設定なし（デフォルト）|<font color="Red">**付与される**</font>|
|4|無効|有効|<font color="Red">**付与される**</font>|
|5|無効|無効|付与されない|
|6|無効|設定なし（デフォルト）|付与されない|

## なぜ差分が出るのか？
タイトルのような差分が何故出てしまうのかというと、**インスタンスを停止すると自動割り当てのパブリックIPアドレスが解放され、associate_public_ip_addressの設定状態と差分が出るからです**

|No.|サブネットの設定|インスタンスの設定|パブリックIPアドレス付与される？|インスタンス停止状態のTerraform差分|
|:-:|:-:|:-:|:-:|:-:|
|1|有効|有効|<font color="Red">**付与される**</font>|<font color="Red">**差分あり**</font>|
|2|有効|無効|付与されない|差分なし|
|3|有効|設定なし（デフォルト）|<font color="Red">**付与される**</font>|差分なし|
|4|無効|有効|<font color="Red">**付与される**</font>|<font color="Red">**差分あり**</font>|
|5|無効|無効|付与されない|差分なし|
|6|無効|設定なし（デフォルト）|付与されない|差分なし|

**パブリックIPアドレスが付与される**かつ**インスタンス停止状態でもTerraformの差分が出ない**設定の組み合わせが3.の組み合わせです。

## EIP付与状態時の差分について
`associate_public_ip_address`の設定を無効（FALSE）にするとEIPを付与した時に差分となってしまいます。

|No.|サブネットの設定|インスタンスの設定|EIP付与状態時のTerraform差分|
|:-:|:-:|:-:|:-:|
|1|有効|有効|差分なし|
|2|有効|無効|<font color="Red">**差分あり**</font>|
|3|有効|設定なし（デフォルト）|差分なし|
|4|無効|有効|差分なし|
|5|無効|無効|<font color="Red">**差分あり**</font>|
|6|無効|設定なし（デフォルト）|差分なし|

そのため結論に書いたとおり

1. インスタンスに`associate_public_ip_address`の設定はしない（デフォルト状態にする）
1. サブネットの設定は有効にする（`map_public_ip_on_launch=True`）

としておくのが一番平和です。
Visual Studio 2017 で System.Windows.Interactivity.dll が見つからない

Visual Studio Installerで「個別のコンポーネント」、「SDK、ライブラリ、およびフレームワーク」から「Blend for Visual Studio SDK for .NET」を選択すればOK。

![blend_dll01.png](https://qiita-image-store.s3.amazonaws.com/0/142879/99d7fbad-2e3b-9723-d89c-abd71bb00dc7.png)
nRF52840 の sleep を試す (Nordic SDK/Softdevice)

ble_app_uart を使ってテスト。

# ble_app_uartとは
- Nordic の サンプルプログラム
- SDK 中 examples/ble_peripheral/ble_app_uart に収録
- BLE で UART のように送受信するもの。

元々は、180秒で以下が実行される

```

static void sleep_mode_enter(void)
{
    uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    APP_ERROR_CHECK(err_code);

    // Prepare wakeup buttons.
    err_code = bsp_btn_ble_sleep_mode_prepare();
    APP_ERROR_CHECK(err_code);

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);
}
```

ちなみに、bsp_btn_ble_sleep_mode_prepare の中身はこんな感じ。bsp_btn_ble.cの中にある。

```

uint32_t bsp_btn_ble_sleep_mode_prepare(void)
{
    uint32_t err_code;

    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);

    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP_BOND_DELETE);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);

    return NRF_SUCCESS;
}
```
BTN_ID_WAKEUPは、同じく bsp_btn_ble.cの中にある。

```

#define BTN_ID_WAKEUP             0  /**< ID of button used to wake up the application. */
#define BTN_ID_SLEEP              0  /**< ID of button used to put the application into sleep mode. */
#define BTN_ID_DISCONNECT         0  /**< ID of button used to gracefully terminate a connection on long press. */
#define BTN_ID_WAKEUP_BOND_DELETE 1  /**< ID of button used to wake up the application and delete all bonding information. */
#define BTN_ID_WHITELIST_OFF      1  /**< ID of button used to turn off usage of the whitelist. */
```


ということでボタンIDは0. PCA10056 (nRF52840 DK)ではButton1~Button4、MDBT50Q DB 上では SW1~SW4として実装されているが、このうちのButton1（SW1）を押すとスリープから復帰する。


# System OFF mode

sleep_mode_enter とはなっているが、中身は sd_power_system_off();を実行するようになっていて、
「System OFF mode」に入る。

「System OFF mode」とは、データーシートによると以下のトリガで復帰することができる。

1.The DETECT signal, optionally generated by the GPIO peripheral.
2.The ANADETECT signal, optionally generated by the LPCOMP module.
3.The SENSE signal, optionally generated by the NFC module to wake-on-field.
4.Detecting a valid USB voltage on the VBUS pin (V BUS,DETECT ).
5.A reset.

しかしながら復帰時にはリセットを伴う。




# WFI (wait for interrupt)/WFE (wait for event) sleep


sd_app_evt_wait（）を使うと、WFIに入り低消費電力になります。
しかしながら


先の
static void sleep_mode_enter(void)
の

```

    err_code = bsp_btn_ble_sleep_mode_prepare();
```
を

```

    err_code = sd_app_evt_wait();
```

に変更しても、CPUは停止しませんでした。別スレッドでソフトウェアループを回していたのですがそれを止める操作を入れないといけない感じです。（調査中）

# 追記

GPIOによる System OFF mode からの復帰について書きました
https://qiita.com/nanbuwks/items/36c32989543399f3aa62