OmniAICreator/Qiita-1.07M huggingface dataset:
Scala + libGDXで、Androidアプリをリリースしてみた

AndroidもScalaで書きたい！という衝動に身を任せ、パズルゲームを作ってみました。
公開中のゲームは[こちら](https://play.google.com/store/apps/details?id=com.yuiwai.tetrics)です。

4方向にフィールドのあるパズルゲームです。ブロックを積んで消していく風のやつですね。
コア部分のコードは[こちら](https://github.com/yuiwai/tetrics)です。

これまで、ブラウザで動くscala-js版や、ターミナル上で動くscala-native版を作っていたのですが、満を持してAndroid版に挑戦した次第です。

今回は、とりあえずリリースまで出来たということで、セットアップやScalaで書く上での実装方針など、軽く触れたいと思います。

## モチベーション

- Scalaの資産を活用してAndroidアプリを作りたい
- Androidアプリをリリースして、知見を得たり、実験をしたい

前者は完全な趣味の領域です。Scalaでなんでも書きたい欲を満たしたいだけです。
後者は、お仕事でAndroidを触る中で、色々と試してみたいことがあるけれど、さすがにお仕事のプロジェクトで実験するわけにもいかず、ならば自分でアプリをリリースしてまえ、というノリです。
今回、初めて自分のアプリをリリースしましたが、イチから自分でやってみるとやはり違いますね。今まで曖昧だった知識がスッと理解できたりします。

## libGDXについて

[libGDX](https://libgdx.badlogicgames.com/)は、オープンソースのクロスプラットフォームのゲーム開発フレームワークです。Javaで書かれているので、JVM言語でJavaとの相互運用が可能あれば、任意の言語で書くことができます。
デスクトップ/Android/iOS/HTML5に対応していますが、HTML5で動かすには[GWT](https://ja.wikipedia.org/wiki/Google_Web_Toolkit)経由となり、Javaで書く必要があります。また、iOS向けには[MOS](https://doc.multi-os-engine.org/)を使うらしいのですが、試したことがないので詳細は分かりません...。

> ※2019.10.22追記 - iOS向けには[RoboVMの選択肢もある](https://medium.com/@bschulte19e/deploying-your-libgdx-game-to-ios-in-2019-8d3796410d82)ということをコメントで教えていただきました。

非公式ですが、[ドキュメントの翻訳](http://westplain.sakuraweb.com/translate/libGDX/Introduction.cgi)も公開されています。

## セットアップ

libGDXでは、専用のセットアップツールが用意されていて、簡単にプロジェクトの雛形を作ってくれます。

詳細は[公式のドキュメント](https://libgdx.badlogicgames.com/documentation/gettingstarted/Creating%20Projects.html)を見ていただければと思います。

`Sub Projects`では生成するプロジェクトを選択できます。今回はAndroid版を作りたかったのと、検証用にデスクトップ版を生成しました。

ビルドツールはgradleです。
ここに[Scala用のプラグイン](http://gradle.monochromeroad.com/docs/userguide/scala_plugin.html)を入れることでScalaのビルドに対応しました。

また、使用するScalaのバージョンは2.11にしています。2.12でビルドすると、実行時に互換がなく落ちてしまいました。Scala 2.12はJava8を要求しますが、Android側の互換がないということかと思います。
詳しくは[ドキュメント](https://github.com/libgdx/libgdx/wiki/Using-libgdx-with-Scala)も参照してみてください。
sbt経由のアプローチもあるにはありますが、プラグインがメンテナンスされていないようで不安があり、採用しませんでした。

## コーディングについて

コードはScalaで書けますが、もちろんJavaや、その他のJVM言語でも書けます。

Scalaは2.11なので、ちょこちょこと不便なところが出て来ますが、今回のベースとなったコードが元々2.11向けだった(scala-nativeサポートのため) ので、その点は楽でした。

libGDXでは、マルチプラットフォーム間で共有するcoreプロジェクトと、それぞれのプラットフォーム向けのプロジェクトがあります。
基本となるアプリケーションコードはほぼcoreに書けますが、プラットフォーム固有の処理はそれぞれのプロジェクト側に書きます。
Android固有の特殊なことがしたい場合はココをいじることになります。

## libGDXは何をしているのか？

libGDXの主たる責務は、プラットフォーム間の差異を抽象化して共通のインターフェースを開発者に提供しすることです。
描画、イベントハンドリング、オーディオ、ネットワークアクセスなどをカバーしています。

描画に関しては、OpenGLをベースとしています。開発者は基本的にはテクスチャを座標指定で描画し、それをlibGDXがOpenGLを介してレンダリングします。

Androidにおいては、これをAndroidGraphicsクラス経由で行っています。このクラスはViewを提供するので、このViewをレイアウトすることで、Androidアプリとしての描画が実現されています。
[このドキュメント] (http://westplain.sakuraweb.com/translate/libGDX/Third%2520Party%2520Services/Admob%2520in%2520libgdx.cgi) は広告を埋め込む話ですが、この辺りに触れています。

つまるところ、ただのViewなので、ActivityやFragmentと組み合わせて使うことができます。
逆に、libGDXだけで完結する場合、ActivityやFragmentを意識することはほぼありません。

よしなにハイブリットにすることで、互いの弱点を補ったアプリを作ることも簡単です。

## あとがき

Scalaで書いたAndroidアプリのリリースまで漕ぎ着けたので、簡単にご紹介しました。

Scalaで書ける、というのはやはり強みです。
願わくば2.11の縛りを突破したいですが･･･。

アプリとしては、まだまだ不完全ですが、今後、色々と実験がてら拡張していこうと思います。
recyclerview-animatorsを使ってみて

## はじめに

現在開発しているAndroidアプリでRecyclerViewを使用しており、
そこにアニメーションをつけるときに発見しました。

## recyclerview-animatorsとは

[recyclerview-animators](https://github.com/wasabeef/recyclerview-animators)は、RecyclerViewのitemにアニメーションをつけるものです。
これを使うことにより、RecyclerViewにitemを追加や削除したときに、様々なアニメーションをつけることができます。

## 使用方法

1.[build.gradleにrecyclerview-animatorsのimplementationを追加](#1-buildgradle%E3%81%ABrecyclerview-animators%E3%81%AEimplementation%E3%82%92%E8%BF%BD%E5%8A%A0)
2.[使用したいアニメーションをRecyclerViewにセット](#2-%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F%E3%81%84%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92recyclerview%E3%81%AB%E3%82%BB%E3%83%83%E3%83%88)
3.[RecyclerViewにitem追加と削除の処理を書く](#3-recyclerview%E3%81%ABitem%E8%BF%BD%E5%8A%A0%E3%81%A8%E5%89%8A%E9%99%A4%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E6%9B%B8%E3%81%8F)

の3ステップで使用できます。

#### 1. build.gradleにrecyclerview-animatorsのimplementationを追加

まず、build.gradleに

``` build.gradle
dependencies {
    implementation 'jp.wasabeef:recyclerview-animators:3.0.0'
}
```

を追加します。

#### 2. 使用したいアニメーションをRecyclerViewにセット

build.gradleに追加が終わったら、RecyclerViewのitemAnimatorに動作させたいアニメーションを記述します。

``` MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    recyclerView.itemAnimator = SlideInLeftAnimator() // 左からスライドAnimationが実行される
}
```

#### 3. RecyclerViewにitem追加と削除の処理を書く

最後に、RecyclerViewにitemを追加と削除するときの処理を記述します。
今回はGroupieを使用しているため、以下のように書きました。

``` MainActivity.kt
    private val groupAdapter = GroupAdapter<ViewHolder>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        recyclerView.apply {
            adapter = groupAdapter
            itemAnimator = SlideInLeftAnimator(DecelerateInterpolator(0.1f))
            layoutManager = LinearLayoutManager(context)
        }
        create.setOnClickListener {
            groupAdapter.add(Item(groupAdapter.itemCount.toString()))
            groupAdapter.notifyItemChanged(groupAdapter.itemCount)
        }

        delete.setOnClickListener {
            if (groupAdapter.itemCount < 1) {
                return@setOnClickListener
            }
            groupAdapter.removeGroup(groupAdapter.itemCount - 1)
            groupAdapter.notifyItemChanged(groupAdapter.itemCount - 1)
        }
    }
```

このように書くことでアニメーションが動作します！

| スライドイン | スライドアウト |
|:-----------:|:------------:|
|<img width="640" alt="SlideInLeftAnimator.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501749/184316c3-71f7-b2ca-0b2b-52582449882f.gif">|<img width="640" alt="SlideOutLeftAnimator.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501749/4036eb91-8cdc-d5ba-cf81-016fa4ecb6bf.gif">|

他にもフェードイン・アウトアニメーションやフリップアニメーション、
また動作方向やアニメーション変化を変更することができるみたいです。

## まとめ

アニメーションをつけることは本来難しいのですが、とても簡単に実装できるため、
これから使っていこうと思いました。
JAVASCRIPTの勉強（１）

JAVASCRIPTを速習しようとしている。

お題としては、HTMLの表に、編集機能を足すところ

これまで本を色々見てきたが、やっぱり自分の必要な機能を
どうやって再現するのかと言う、事例を習得することが一番いい。

ソースの入手は、とりあえずGITHUBで調べまくった。
とりあえず、ワンライナーで実施しているようなライブラリ、
もしくは、自分と近いアマチュアプログラマなどを
見つけて行くのが大事だと思われる。

そうこうしている、うちにソースを発見する。
# HTMLのTABLEをJSで操作する
https://github.com/karldoenitz/html_table_immediate_edit/tree/f7fc41a9b3983bbf6b682439e1b18d23270f49b8

さて、さっそくコードを読んでいくことにする。

```javascript

$(document).ready(function(){
    var tdNods = $("td.edit");
    tdNods.click(tdClick);
});
```
おっと、いきなり$から始まっているやん。。。
この＄がついているところで、はあ？
って、つまずく以前の自分。

今となっては、＄自身がjQueryの省略形で、
このソースはjQuery.documentという風に
HTML本体を指すところは、さらっと分かるようになった。
（しかし、初めて見たら、何やこれで躓くと思う）

次のところは、関数が関数を引数とするところ・・・
これは、入れ子構造というやつで、
例えていうなら、ロシア人形のマトリョーシカみたいに
蓋を開けたら、中にもう一個蓋が入っていて、
実は最後は、もの凄い小さい人形だったりする。

プログラミングで言えば、それは変数や定数の
単一のオブジェクトになるのであるが。

JAVASCRIPTはC系の言語のため、この入れ子構造は
｛｝と（）の繰り返しオンパレードということになる。
もちろん、行の最後は；で判断する。

最近になってＰＹＴＨＯＮがもてはやされるようになったのは、
インデントで分かりやすく構造をとらえられるためであり、
やはりプログラムの解読においては、
いち早くその構造を把握することが重要である。

つまり、最初に上げたプログラム部分の構造を理解するには、
次のように書き換えてしまえば分かりやすい
（本当は脳内変換が望まれるが、最初はそこまでできないので）

```javascript
jQuery.document.ready(関数);
function　関数()
{
    var tdNods = $("td.edit");
    tdNods.click(tdClick);
}
```

つまり文書が読めたら、関数を実行しなさい
関数の中身は、｛｝に書いてありますよ・・・
ということになる。

その次の中にも、＄が出てくるので、いちいち変換してられないので、
とりあえず＄の必要性は理解できた。

ここからは$()　→　jQuerry.()の部分で、
どのオブジェクトを選択しますか？ということだが
この（）の中を、セレクターと呼ぶ。

もともとJavascript自体が、HTML文書をDOMという
文書構造のオブジェクトで解釈しているので、
.を繋いでいくと、HTML上のどこかの場所を指すことになる。

””で囲んだ場合は、これは要素セレクタと言って、
htmlで言えば<>で囲まれる部分になる。

今回の場合は"td.edit"なので、これは＜td＞という
表の中の行を表すタグであって、
つまりは、HTMLの文書の中で、＜td＞を指す。

その後の.editというのは、.で始まる場合は、
CLASSを指すので、どこかに＜class="edit"＞というのが
あるのだろう・・・

つまりeditというクラスが設定された要素全部が、変数に入ることになる。
つまり変数は複数形の名称になっている

var tdNods = jQuery.td.edit;


その後のclickというのが、メソッドであって、このオブジェクトの上で
クリックがされたらということになる。
（）に入っているのは、引数であって

    tdNods.click(tdClick);

次の行に書かれた関数を実行しなさい、ということになる。

```javascript

function tdClick(){
    var td = $(this);
    var tdText = td.text();
    td.empty();
・・・
}
```

さてさて、こんな感じで読んでいくと、だいぶん分かりやすくなってきた。

お次は、$(this)というところだが、先ほど呼び出した関数は、
editクラス全部に反応するため、どの場所から呼ばれたのか？
を特定することはできない。

そこでthisを書くことで、呼び出し元の＜TD＞が一意に決まることになる。
td.text()は、＜TD＞要素からテキストを持ってくるメソッド
td.empty()は、＜TD＞要素を空にするメソッドである。

こんな感じで、プログラム読み取り作業は、第二部に続く。。。
Bitrise APIを使ってみよう！

## やりたいこと
iOS/Androidのアプリを全てBitriseでCI/CDしているが、アプリケーションの数が30を超え管理するのが面倒になってきた。
この手のサービスはだいたいAPIがあるので、それを使って解決しちゃおうぜ！

## Bitrise API
APIの概要については以下のページで確認できる。
https://devcenter.bitrise.io/jp/api/api-index/

で、APIの一覧はここにある。
https://api-docs.bitrise.io/

パッとみた感じだと、一通りの機能が揃っていて使い勝手良さそう。
ドキュメントがSwaggerで作られていることも、個人的にポイント高め！

## 認証
当然だけど認証しないとAPIは使用できない。
リクエストヘッダーの`Authorization`に、アクセストークンを設定すれば良い。

アクセストークンはアカウント設定画面のSecurityから作成できる。
![スクリーンショット 2019-10-11 11.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144029/adf5aeee-6d1d-186a-52f1-7a92d6687a50.png)

適当にアクセストークンの名前と期限を設定する。(画像では無期限にしている)
![スクリーンショット 2019-10-11 11.40.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144029/60e0597c-4424-a6c1-f008-8ed959543464.png)

こんな感じでアクセストークンが生成される。
アクセストークンは再表示ができないため、メモし忘れると作り直しになるので注意が必要！
![スクリーンショット 2019-10-11 11.43.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144029/1df45ece-8766-b4bc-4647-da4a6fac02b3.png)

## 実際に使ってみる
使用する準備ができたので、実際に使ってみる。
一番オーソドックスなアプリケーションの一覧を取得するAPIを使用してみる。

インターフェースはこんな感じ。
<img width="1409" alt="スクリーンショット 2019-10-11 11.54.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144029/a03eae15-71be-1607-fa45-1e8c42e3bf55.png">

Base URLは`https://api.bitrise.io/v0.1/`と記載が上の方にあったので、`https://api.bitrise.io/v0.1/apps`にクエリパラメーターつけてGET送信すれば良さそう。

作成日順に取ってみたかったので、curlだとこんな感じ。

```
$ curl -X GET "https://api.bitrise.io/v0.1/apps?sort_by=created_at" -H "accept: application/json" -H "Authorization: {アクセストークン}"
```

Json形式でアプリの一覧を取得することができた！

```
{
	"data": [
		{
			"slug": "xxxx",
			"title": "バイトル iOS (開発)",
			"project_type": "ios",
			"provider": "custom",
			"repo_owner": "dip",
			"repo_url": "git@xxx",
			"repo_slug": "baitoru_app_ios",
			"is_disabled": false,
			"status": 1,
			"is_public": false,
			"owner": {
				"account_type": "organization",
				"name": "DIP",
				"slug": "xxxx"
			},
			"avatar_url": "https://concrete-userfiles-production.s3.us-west-2.amazonaws.com/repositories/xxxx/avatar/avatar.png"
		},
		{
			"slug": "xxxx",
			"title": "バイトル Android (開発)",
			"project_type": "android",
			"provider": "custom",
			"repo_owner": "dip",
			"repo_url": "git@xxx",
			"repo_slug": "baitoru_app_androidstudio",
			"is_disabled": false,
			"status": 1,
			"is_public": false,
			"owner": {
				"account_type": "organization",
				"name": "DIP",
				"slug": "xxxx"
			},
			"avatar_url": "https://concrete-userfiles-production.s3.us-west-2.amazonaws.com/repositories/xxxx/avatar/avatar.png"
		},

        {省略}

	],
	"paging": {
		"total_item_count": 33,
		"page_item_limit": 50
	}
}
```

ここまでやればあとはBitrise APIでやりたい放題できる！
Bitrise最高！
Rubyビルド時の OpenSSL の PATH指定方法

Ruby ビルド時の OpenSSLのPATH指定方法について
なかなかたどり着かなかったためメモ。

`--with-opt-dir` を指定すると良い。


```sh:1.8.7
#  ruby 1.8.7
./configure --prefix=/opt/ruby \
 --enable-pthread \
 --with-opt-dir=/opt/openssl-1.0.2t
#--with-opt-dir=/opt/openssl-0.9.8zh
```

> configure: WARNING: unrecognized options: --with-openssl

というエラーが出るが認識している様子。
npx create-nuxt-app でpython2 command exists

## 自分の環境
mac mojave 10.14.6

```sh
$ node -v
v12.4.0

$ npm -v
6.9.0

$ pyenv versions
  system
  2.7.9
* 3.7.2

$ ndenv
ndenv 0.4.0
```

## 現象
久々にNuxt.jsでサイトを作ろうとして `npx create-nuxt-app` を実行したらエラー

エラーメッセージ

```sh
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /Users/ユーザー名/.pyenv/shims/python2 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /Users/ユーザー名/.pyenv/shims/python2 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack pyenv: python2: command not found
gyp ERR! stack
gyp ERR! stack The `python2' command exists in these Python versions:
gyp ERR! stack   2.7.9
gyp ERR! stack
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:290:12)
gyp ERR! stack     at ChildProcess.emit (events.js:200:13)
.
.
.
npm ERR! Failed at the fibers@4.0.1 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
```

なんだこれは、、、初めてみたエラーだ

fibers.node というモジュールがインストール失敗している？

## 原因
エラー内容を見ると、python2が必要らしい？

しかし、自分のデフォルトpythonは`3.7.2`のpython3を設定している。

このプロジェクト内でpython2を指定したらいいだけ？

## 解決方法

この方法で無事にインストールできた。

まずプロジェクト内に移動し、pyenv localでpython2を指定する。

```sh
$ cd nuxtjs-project
$ pyenv local 2.7.9

$ pyenv versions
  system
* 2.7.9
  3.7.2
```

そして再度インストールを実行

```sh
$ npm install
```

ズラズラとログが流れ

```

Installed in `/Users/ユーザー名/dev/nuxtjs-projet/node_modules/fibers/bin/darwin-x64-72/fibers.node`
```

お、fibers.nodeがインストール＆ビルド成功したらしい

この後、`$ npm run dev`で無事にサイトがローカル表示できた。
spheroを動かしてみる①

#目的
spheroに慣れるために簡単な動作させてみる
プログラム初心者にプログラムがどうやって動くのか体験してみる

# 使用機材
Sphero BOLT
PC(Sphero Eduアプリ使用)


#今回の要件
地面を正方形を描くように移動させる

机上での設計として、直進→90度右折→直進を繰り返すことで、
正方形を描くように移動させることができるのではないかと考えました。


#実際に組んだプログラムの解説
1:AIMをリセット:向いてる方向を0としてセット
2:Sphero上部のLEDパネルでアニメーションを表示させる(遊びで組み込み)
3:現在向いている方向に速度45で2秒間進む
4:回転の前準備として停止をさせる(停止を入れない場合は慣性で進んでしまうため)
5:水平方向に90度回転させる
6:1～5をループさせる

動作のコツとして、「AIMリセット」ブロックを使用して、進行方向を0に初期化する点です。
このブロックを挿入せずに、「ロール0°～」を実行すると、
現実の北の方角(初期値)に向きを変えて直進してしまいます。
1回目の直進時は問題ないのですが、2回目以降はせっかく5行目で向きを変えたのに、
「ロール0°～」によって向きが強制的に元の方向に戻ってしまうため、
結果的にただ直進するだけの動きになってしまいます。

# 実施に作成したプログラム
![sphero1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469881/724eb4d2-0888-470a-63b1-e12fbf534b79.jpeg)
【Automation Anywhere】初回レコーディングでのみ作成できるコマンドのまとめ

Automation Anywhereでアクションリストを作成していくにはいくつかの方法が用意されています。大まかに言って、「**レコーダー (記録) から始める**」のか、「**ワークベンチから始める**」のかの2種類があります。いったん、レコーダーを終了すると、ワークベンチの画面になり、ワークベンチではコマンドを追加するか、部分的なレコーディング (Smart Recorder) を行うことが可能です。また、コマンドの中には部分的なレコーディング (Smart Recorder or Web Recorder) を実施するものがあります。つまり以下のようになります。

**パターン1:**

* **初回レコーディング (Web Recorder or Smart Recorder or Screen Recorder)の実施によるコマンド群の生成**
* ワークベンチでのコマンドの追加 or 部分的なレコーディング (Smart Recorder)
    * Object Cloning コマンドやWeb Recorderコマンドでレコーディングのやり直し

**パターン2:**

* ワークベンチでのコマンドの追加 or 部分的なレコーディング (Smart Recorder)
    * Object Cloning コマンドやWeb Recorderコマンドでレコーディングのやり直し

ここで「パターン1」でも「パターン2」でも全く同じアクションリストを作成できそうですが、Automation Anywhereではこの部分に癖があり、実はパターン1の初回レコーディングでしか生成できないコマンドがあります。このコマンドを生成したいと思ったら、一度TaskBotをレコーディングにより最初から新規作成して該当するコマンドを生成し、それを元のアクションリストにコピー＆ペーストする処置が必要になります。

**対象**

* Automation Anywhere Enterprise 11.3.2
* Automation Anywhere Community Edition

# レコーディングにより生成されるコマンド群とは？
Automation Anywhere ではレコーディングの方式は3通りあります。3種類あるのは歴史的経緯や背景となる技術の違いがあるようですが、Bot作成者は何を記録したいかによって最適な方式を自分で選んで記録することになります。

|レコーダーの種類|生成されるコマンド|
|:--|:--|
|Smart Recorder|Object Cloningコマンド|
|Web Recorder|Web Recorderコマンド系 (Go Backコマンド、Open Browserコマンド、Extract Tableコマンド、Extract Dataコマンド、**Extract Multiple Dataコマンド**、Manage Web Controlsコマンド)、Loop While Web Control Existsコマンド|
|Screen Recorder|Insert Keystrokesコマンド、Insert Mouse Clickコマンド、Insert Mouse Moveコマンド、Insert Mouse Scrollコマンド|


# 初回レコーディングでしか生成されないコマンド
**Extract Multiple Dataコマンド**は、初回のWeb Recorderでしか生成されません。Webスクレイピングでデータパターンを抜き出すような場合は、新規のTaskBotを作成することになります。
GETとかPOSTとかPATCHとかあれなんだ。

## この記事の目的

一言言いたい。
入門書とかWebの解説書によく出てくるGETとかPOSTとかPATCHとかDELETEってなんだよ。
調べてみると、これらは、HTTPメソッドと呼ばれているらしい。
もちろん、雰囲気は知ってたし一通り説明も見たけどふんわりしか分かってない(多分分かってない)ので、まとめます。

この言葉を知りたい、最初はこのHTTPメソッドって単語がそもそも出なかったりする。
そんな人たちに辿り着いて欲しい記事を作りたくて投稿します。

## HTTPメソッドとは

SafariとかGoogleChromeなどいわゆるブラウザが、行いたい処理をサーバーに伝える8種類の処理のことである。(※誤OPTION→正OPTIONS)

![名称未設定ファイル (22).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/4ae89f6f-9f1d-d4fc-5559-fb094e21a718.jpeg)

おそらく、HTTPメソッドについて調べている方ならインターネットの仕組みとブラウザとサーバーの仕組みについても説明改めて理解して頂いた方がいいので、下記に記します。

## インターネットの仕組みついて

![名称未設定ファイル (27).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/297b9f1c-fe2b-f119-83b7-28b869e66642.jpeg)

Webの世界というのは、裏と表の「二面性の世界」で動いている。
HTTPメソッドとは、その裏面の典型的なものではないだろうか。

この記事をスマホやPCで見ている際に、おそらくブラウザ(SafariやChromeもしくはブラウザと呼ばれるアプリ)で閲覧していると思う。

![インターネットとは.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/00ad224f-77b6-ef68-efd4-8589d122f545.jpeg)


そして、このアプリを使うときにあなたには目的があるはずだ。
例えば、「猫の動画を見たい」とか「東京の美味しいラーメン屋を知りたい」とか。もしくはQiitaやNeverまとめみたいな情報サイトにとりあえずアクセスして、面白い記事を見たいとか。

そんな時、大抵各サービス会社(YouTubeとか食べログとか)のサイトが検索結果にヒットして、アクセスすると思う。

この時、サービス会社(YouTubeならGoogle)のサーバーと呼ばれるところに、あなたのPCのブラウザは「HTTPリクエスト」と呼ばれる送られる。

これは、あなたの動作に応じて発行されるものである。単に動画を見たいだけなのか、動画を投稿したいのか、投稿した動画を削除したいだけなのか、などである。

要は、「HTTPリクエスト」とはあなたのブラウザの動詞を表しているのだ。

## HTTPメソッドは何の役割を担っている？

適切にあなたの要望を伝えるために、少し面倒なことがある。それは、あなたがコミュニケーションを取っているのは人ではなく、コンピューターであるということだ。
![名称未設定ファイル (33).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/36b06e92-eebc-c318-68a2-b21cb6fc775a.jpeg)

だからこそ、対話するためにHTTPリクエストと呼ばれるものは8個もの種類を擁している。

## GETについて
![名称未設定ファイル (34).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/65ed04cf-c9db-487a-b658-eb33558f4dc9.jpeg)

## POSTについて
![名称未設定ファイル (35).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/b898a00c-fd92-d3dd-c6e8-f0a043304094.jpeg)

##　PUTについて
![名称未設定ファイル (36).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/03e15ba7-d0f4-3ead-1e04-6abc6af4199e.jpeg)

##　DELETEについて
![名称未設定ファイル (37).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/d5f9dec7-2269-f700-c5df-d2779d99c6ea.jpeg)

URIってなんだよ。

##　HEADについて
![名称未設定ファイル (38).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/b53cb1c5-6eea-bb5d-f0c9-09a3442a2957.jpeg)


HTTPヘッダってなんだよ。

##　OPTIONSについて
![名称未設定ファイル (42).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/56547f27-9f45-2aa8-446f-786e395a9b2b.jpeg)

##　TRACEについて
![名称未設定ファイル (44).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/30310c71-9054-57c0-37f9-007eb675b797.jpeg)

##CONNECTについて
![名称未設定ファイル (45).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453260/55668d7d-045c-8b58-139a-4cdf42a16f81.jpeg)


## 参考記事
【エラー対処】error command 'clang' failed with exit status 1が発生する


# はじめに

pythonでreppyというライブラリをpipインストールしたとき、


```bash
error command 'clang' failed with exit status 1
```

が発生しました。

本当はもっと上にエラーコードがありましたが、ログを取り忘れてしまいました。
申し訳ありません。

環境はMacでPythonのpip時のエラーになります。

# 対処法

```bash
CFLAGS=-stdlib=libc++ pip install reppy
```

```fish
env CFLAGS=-stdlib=libc++ pip install reppy
```

bashを使っている人は上の方を
fishを使っている人は下の方を実行します。

fishではイコールで変数に代入を行わないためです。
しかし、envコマンドを使えば環境変数を設定しながら、別のコマンドを実行できます。

reppyでは、C++のMakefileを使用しているため、CFLAGSの環境変数が間違っているとどうやらエラーが出るようです。
そのため、以上のように指定することで、きちんとコンパイルしてくれます。
StringUtils.isBlank作ってみた

##つくってみました
```StringUtils.java
package practice;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Utils
 * 
 * @author me
 *
 */
public class Practice {

	/** String list */
	private static final List<String> INTEGER_LIST = Arrays.asList(null, "", " ", "0", "1", "2");

	/**
	 * main
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			run(INTEGER_LIST);
		} catch (NumberFormatException e) {
			echo.accept("・ω・ｖ");
		}
	}

	/**
	 * run
	 * 
	 * @param list <E> The element type of this list.
	 * @throws NumberFormatException if conversion to numeric number is impossible.
	 */
	private static void run(List<String> list) throws NumberFormatException {
		echo.accept(list.stream().filter(notBlank).map(Integer::parseInt)
				.collect(Collectors.summingInt(Integer::intValue)));
	}

	/** not null */
	static Predicate<String> notNull = v -> Optional.ofNullable(v).isPresent();
	/** not space */
	static Predicate<String> notSpace = v -> !v.equals(" ");
	/** StringUtils.isBlank */
	static Predicate<String> notBlank = v -> notNull.test(v) && !v.isEmpty()
			&& Arrays.asList(v.split("")).stream().anyMatch(notSpace);
	/** out */
	static Consumer<Object> echo = v -> System.out.println(v);

}

```

##結果
`3`

##結論
なんだかんだ自作できてもライブラリ追加した方が早くね問題
けど数行で終わるならいちいち使わなくてもいいですよね
ぶっちゃけもうjava既存のでなんでも解決できそうな気分になってます
最近apache.common.lang全然見ない...
【Typescript】Promiseとして帰ってくる値をReturnTypeっぽく取得したい


## 前提知識

```typescript
const f = () => ({
  fieldA: "hello",
  fieldB: 12,
  fieldC: null,
});
type FReturn = ReturnType<typeof f>;
```
この時`FReturn`は次と同じになります。

```typescript
type FReturn = {
    fieldA: string
    fieldB: number
    fieldC: null
}
```

## 本題

次の場合にも同じように`FReturn`と型を取得したい時は?

```typescript
const f = async () => ({
  fieldA: "hello",
  fieldB: 12,
  fieldC: null,
});
type FReturn = /* 何かしらの型 */;
```

## 答え&解説

```typescript
type FReturn = ReturnType<typeof f> extends Promise<infer T> ? T : never;
```


* `ReturnType<typeof f>`は前提の節で説明したようにfの返り値の型となります。つまり、`async`を利用しているので`Promise<FReturn>`の型になります。
* [Type inference in conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types)を利用します。
  *  Conditional typesでは三項子演算のように`T extends U ? X : Y`の形式で書きます。これは「TがUの型をextendしているならばX、そうでないならばY」という型を示します。
  *  `T extends U ? X : Y`のUの部分に`infer X`を利用することで、`T extend U`が真となるような`X`の型を推論してくれるようになります。つまり上の例は、「`ReturnType<typeof f>`が`Promise<◯◯>`を実装するような◯◯が存在するならば、◯◯が型となり、それが存在しないなら`never`」という型になります。`ReturnType<typeof f>`は`Promise<FReturn>`を実装しているので、上のコードが示す型は`FReturn`となります。


## あるある言いたい
ReturnTypeで実装するべきか、明示的に型定義するべきかめっちゃ悩む
bundlerで sqlite3がinstallできない

## はじめに
sinatraでactiverecordを使ってなんやかんやのアプリケーションを作ろうとしているが、Bundlerでsqlite3をインストールしようとすると下記のエラーが出て処理が終わる。

````
An error occurred while installing sqlite3 (1.4.1), and Bundler
cannot continue.
Make sure that `gem install sqlite3 -v '1.4.1' --source
'https://rubygems.org/'` succeeds before bundling.
````

## 試したこと
調べてみるとbundle install時にsqlite周りが原因でエラーが出る人が中々に多かった。

### ヴァージョン指定してみた
始めはエラーコードをろくに読んでなかった（読め）ので、ヴァージョン指定とかの話かと思って試してみたが、ダメだった。
具体的には[この記事](https://qiita.com/flowerhill/items/bb1e99bd87b151c0129b)とかを参考に、gemfileを以下のように書き換えてみた。

````
gem 'sqlite3'  
⇒　gem 'sqlite3', '~> 1.3.6'
````
結局うまくいかないので次の手を試すことに。

### yumコマンドでsqlite3の依存パッケージをインストールする
ずっとここで止まっててようやくエラーコードを読んでないことを思い出したのでログを少しさかのぼってみた。

```
 Try 'brew install sqlite3',
'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
and check your shared library search path (the
location where your sqlite3 shared library is located).
```
あった。 

とりあえず `yum install sqlite-devel` を実行するが、yumコマンドがインストールされていない。

````
sudo apt install yum
````

yumインストール後に再度

````
sudo yum install sqlite-devel
````

を実行するが、segmentaition違反だとかで断念。
これについては解決方法ほんとにわからなかったので助けてほしい。
分からんこと調べてるときに分からんこと出てくると訳の分からないことになって訳が分からない...

### ついに解決
で、疲れたのでコーヒーブレイクしていたが、そういえばもう一つ選択肢なかった？ってことで

````
sudo apt install libsqlite3-dev
````
してみたところ、なんだかいい感じ。

改めて

````
bundle install --path vendor/bundle
````

・
・
・
・
・


できた。

## おわりに
なんだか凄い遠回りをして時間を無駄にした気がするが、エラーコードはちゃんと読めってことですね。
これでようやく先へ進める。
PythonでAdobe illustratorで編集できるfigureを作成する

Jupyter notebookでの作図を論文のFigureに使用したい場合，最終的にはIllustratorでの加工が必要になるときがあります。

そのときのために，Illustratorでの編集が可能なPDFファイルの作成の方法です。
[リンク1](https://tabeta-log.blogspot.com/2018/02/matplotlibpdf.html), [リンク2](http://jonathansoma.com/lede/data-studio/matplotlib/exporting-from-matplotlib-to-open-in-adobe-illustrator/)

```Python:illustrator-editable-figure.py
import matplotlib
matplotlib.rcParams['pdf.fonttype'] = 42
matplotlib.rcParams['ps.fonttype'] = 42

#複数ページをPDF保存する際に必要なmodule
from matplotlib.backends.backend_pdf import PdfPages

.............
.............
.............

# 保存の際に下記。見切りが発生する場合は，さらにplt.savefigの引数に bbox_inches='tight' をつけるとよい。
plt.savefig("output-scatter.pdf", transparent=True)
```

2021年3月27日 Seabornで作成したFigureのPDFでの保存方法も追記。下記のリンクを参考にした。
[リンク3](https://stackoverflow.com/questions/35490203/how-to-save-multiple-seaborn-plots-to-the-same-pdf-png-file)
Seaborn moduleは作成したfigの指定を，別個に行ってこれをPDFpagesで保存する必要がある。

例として

```Python:illustrator-editable-seaborn-figure.py
import matplotlib
matplotlib.rcParams['pdf.fonttype'] = 42
matplotlib.rcParams['ps.fonttype'] = 42

import seaborn as sns
from matplotlib.backends.backend_pdf import PdfPages
.............
.............
pp = PdfPages("Seaborn_Edittedfigure.pdf")

g = sns.catplot(x="Type", y="SNV", kind="violin", data=df)
pp.savefig(g.fig)
h = sns.catplot(x="Group", y="INDEL", kind="swarm", data=df)
pp.savefig(h.fig)
i = sns.catplot(x="Type", y="MNV", kind="box", data=df)
pp.savefig(i.fig)
pp.close()
```
の用に行うと，１つのPDFファイルの別々のベージにseabornで作成したFigureがイラストとして保存されていく。
最後にpp.close()を行わないと，作成したPDFが開けなくなるので注意する。
CircleCI でテストを並列に分割する

# はじめに

テストを追加していくとテストの実行時間がボトルネックになりがちです。
そこで CircleCI ではテストを分割し、`parallelism` というキーを指定して並列実行ができるようになっています。
ここでは Node.js のプロジェクトで Jest を使用したものを例に話を進めます。

# 環境

CircleCI 2.1

# CircleCI の設定

## ジョブの並列レベルの設定

通常 CircleCI のジョブは config.yml に設定した処理を 1 つの Executor 上でジョブが動作します。
複数のジョブを並列に動作させたい場合は、`parallelism` というキーに並列数を 1 以上で設定します。
ここでは 2 を指定しているので並列数 2 で動作します。

```yaml:.circleci/config.yml
version: 2.1
jobs:
  test:
    docker:
      - image: circleci/node:12
    parallelism: 2
```

## ジョブの並列レベルの設定

並列数を増やしただけでは並列にジョブが動作するだけで、テスト時に同じテストファイルが実行されてしまいます。
次の設定を追加してテストファイルを分割することで分割されたテストファイルが並列に実行されます。
まず `circleci tests glob` コマンドにテストファイルのパスを渡します。
`glob` に使えるパターンは[ドキュメント](https://circleci.com/docs/2.0/parallelism-faster-jobs/#globbing-test-files)を参照してください。
ここでは JavaScript と TypeScript が同居するプロジェクトを想定し、`js` と `ts` を指定しています。
取得したファイルを分割するにはパイプで `circleci tests split` コマンドに渡します。
`--split-by` オプションには `filesize` と `timings` を指定できます。
今回は `timings` を指定します。
`timings` は、別途 `store_test_results` キーを使用することで適切なタイミングデータが生成されます。
`store_test_results` キーを使用した記事については[こちら](https://qiita.com/takasp/items/5864d0601c41a769a2a0)を参照してください。
`split` コマンドで実行した結果を環境変数に保存してからテストコマンドに渡すことで、テストが並列に分割された状態で実行されます。
DB などに依存するテストの場合でも並列に実行されるためデータが競合することはありません。

```yaml:.circleci/config.yml
version: 2.1
jobs:
  test:
    docker:
      - image: circleci/node:12
    parallelism: 2
    steps:
      - run:
          command: |
            TESTFILES=$(circleci tests glob "__test__/**/*.spec.{js,ts}" | circleci tests split --split-by=timings)
            npm test $TESTFILES
```

# さいごに

簡単ですが、CircleCI の並列分割テストについて取り上げました。
`parallelism` と CircleCI が用意した分割コマンドを実行することで簡単に並列実行できるのは便利だと感じます。

# 参考

[Running Tests in Parallel - CircleCI](https://circleci.com/docs/2.0/parallelism-faster-jobs/)
基本情報技術者の試験勉強計画

# 基本情報技術者の試験勉強計画
##はじめに
本記事は、IT系企業に内定した非IT系大学生が2020年4月の基本情報技術者試験(IPAより)に合格するための計画および結果を記載する記事です。
 同様に基本情報の取得を目指している人にとっても参考になれば幸いです。

また、間違っている点があれば、暖かい訂正コメントをいただけると嬉しいです。

##目標
2019年12月 or 2020年1月に午前免除試験に合格することと
2020年4月に基本情報技術者試験に合格することを目標とします。


###2019年12月
午前免除試験に合格する。(落ちたら1月に受験。)
### 2020年4月
2020年春期の基本情報技術者試験に合格する。
未受験(結果でたら追記します。）


## 計画概要

### 10~11月
参考書をベースに午前問題の範囲を一通り勉強。
 主に解説を読み、演習問題を解く。
 分野はテクノロジ系13項目、マネジメント系3項目、ストラテジ系7項目の計23項目。
6週間で23項目なので、平均すると1週間に4項目くらいのペース。
### 12月
午前問題の範囲の過去問を、1週間に1回分解く。
 後半2回分は模擬形式で（時間は問わない）。
午前免除試験の合格基準である６割を目指す。


###1月
午前問題の範囲の過去問を、1週間に1回分解く。
80問を150分以内に解けるように、時間計測をしながら模擬形式で過去問を解く。
8割正解を目指す。
1/26に午前免除試験を受験する。


###2月
参考書をベースに午後問題の範囲を一通り勉強。
 主に解説を読み、演習問題を解く。
 選択問題のうち、得意な分野を見つける。

###3月
午後問題の範囲の過去問を、1週間に1回分解く。
 後半2回分は150分以内に解けるように、時間計測をしながら模擬形式で過去問を解く。

###4月
午後問題の範囲の過去問を、1週間に1回分解く。
8割正解を目指す。
4/19ごろに基本情報技術者試験を受験する。



## 月次計画

### [10月](https://qiita.com/poohsan/items/e48a4103d06425b28a4a)

### [11月](https://qiita.com/poohsan/items/c4ce069e1e403468835a)

### [12月](https://qiita.com/poohsan/items/8dd9b07758beedbb76d0)

### [1月](https://qiita.com/poohsan/items/3bb4bc1721f14b55116d)

### [2月](https://qiita.com/poohsan/items/1c7197dc3a8e9f77e3b8)

## [3月](https://qiita.com/poohsan/items/58fcb133a14872c31709)

## おわり
基本情報技術者試験の勉強を始めて約半年間、午前が受かってはいませんが、最初のころと比べると明らかに自分が成長したと感じることができた。勉強の仕方や時間の取り方、生活においてもこれからコミットで働くために、社会人になるための前準備が多少はできてきたのではないかと思った。IT知識はまだまだなところもあるが、これからたくさんの知識を習得したいと考える。10月から３月までの築地報告を見て目標を達成していない月も半分はあったが、遅れた分を取り戻すようにまた目標を書き直してとやっていたので、PDCAサイクルはこの半年で習得できたと思う。報連相については、相談があまりできていなかったと思う。１人ではなかなか理解ができない、また解決できないところがあったら相談してみる、という所を少し意識していきたい。これからは新しいことをたくさん覚えていくので大変だと思うが、先輩や同期と一緒に楽しく働いていきたいと思う。
超初心者がLineBot×Obnizでスピーカから音を出してみた。

##はじめに
先週、人生で初めてLineBotを作った超初心者です。
勢いにのって、Obnizに初挑戦。
パソコンとObnizが繋がって画面に表示されただけでも、かなりワクワクです。
出来ることは限定的ですが、これからObnizでトライする方々の超初心者と指導者の方々の情報のために初歩的なことを記載しておきます。
##作った目的
Obnizはパソコンから操作するだけでもIOTぽさがあり楽しいですが
LineBotと連動すれば更に世界が広がるかも・・・。
ということで練習がてら実践してみました。
裏でLEDやらマイクロサーボなどちょっと触りましたが
今回はLineBotとのやり取りが一番簡単にできたスピーカーで出来たことを書いてます。

##仕様
・「音を教えて」と入力すると「ヘルツで入れてください」と答えてくれる。
・数字を入れるとhzで音を出力する。
・ずっと鳴っているとうるさいので
##使った環境
・Node.js v10.16.3
・Windows 10 pro
・Visual Studio Code v1.39.1
・[Obniz ボード](https://obniz.myshopify.com/collections/devices/products/obniz-board-hobby-license-90-day-trial)
・[圧電スピーカー（圧電サウンダ）（１３ｍｍ）ＰＫＭ１３ＥＰＹＨ４０００－Ａ０](http://akizukidenshi.com/catalog/g/gP-04118/)
・USB2.0ケーブル(A-microBタイプ)50cm
##作成方法
こちらは[老眼と加齢性難聴のチェックができるLINEbotとIotの作成](https://qiita.com/doikatsuyuki/items/fb14483b69a3d3202bed)を参考に作りました。
そちらの記事のコードBの部分だけ、非常にシンプルなものにしたので記載します。

```js
''use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: 'Lineのチャンネルシークレット',
    channelAccessToken: 'Lineのアクセストークン'
};

　// Obnizの準備
var Obniz = require("obniz");
var obniz = new Obniz("Obniz ID");  // Obniz ID を入力
var speaker; // 全体で使えるようにするスコープ
obniz.onconnect = async function () {
    speaker = obniz.wired("Speaker", {signal:0, gnd:1});
}

const app = express();

app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
 //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。
    if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
        res.send('Hello LINE BOT!(POST)');
        console.log('疎通確認用');
        return; 
    }

    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
      return Promise.resolve(null);
    }
　　//ここからがコードB
    var hz = Number(event.message.text);
    speaker.play(hz);
    obniz.wait(1000);
    speaker.stop();
    let replyText = '';
    if(event.message.text === '音を教えて'){
      replyText = 'ヘルツを言ってください';
    }else{
      replyText = hz;
    }
    return client.replyMessage(event.replyToken, {
      type: 'text',
      text: replyText
    });
  }
  app.listen(PORT);
  console.log(`Server running at ${PORT}`);
```
##動作確認
いちおう単純な返答と音は確認。音が出る瞬間、個人的な達成感はあるも家族から見たら地味・・。
![Screenshot_20191021-023825.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508834/b557371c-f678-ba4c-7686-3398cb44a5a5.png)
##疑問
もっと色々な応答を試したかったが、let replyText以下を少し変えるだけでうまく作動しなくなってしまった。前回実施したじゃんけんBOTとの組み合わせもトライしたが「じゃんけん」か「音の出力」どちらかになってしまいました。どうして組み合わせができないかもう少しお勉強してみたいと思います。
##感想
素直にLineBotもIOTも楽しい！！
ですが二つを組み合わせると初心者には不明なドツボにはまる危険性も高まる気がしました（笑）
ObnizはスピーカーのほかにLED（個人的には豊富な色もだせてはまる予感）やモーターなどツールにバラエティがあるので少しづつお勉強しつつ、幅を広げていきたいです。
初心者がC#でグーグルスピーカーを動かす（備忘録：挫折編、Javescriptで書く）


これは挫折したところまで書いた話です。
google homeでは下記の通りにデータの受け渡しがされてます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443250/d2533078-3a5a-ebec-62d0-ef9c1c412543.png)

引用：https://qiita.com/kenz_firespeed/items/0979ceb05e4e3299f313
Dialogfrowではbotの作成とかも出来て非常に面白そうなので
時期をみてやりたいなと思ってます。

ただ、今回はC#で書きたいので
もっと簡単にコード書いて、グーグルホームにお話させたいな
と思いました。

そこで見つけたのが、Node.jsで書く方法
ざっくり言うと、google-home-notifierというNode.jsのライブラリがあって
それをポチッとするとJavascriptで書くことが出来ます。

google-home-notifierでJavascriptを書く方法を残しておきます。

まず、Node.jsを有効にする。
https://nodejs.org/ja/でもいいけど
https://qiita.com/taketakekaho/items/dd08cf01b4fe86b2e218
この記事が非常に参考になりました。
ただ、初心者には、bashの使い方に要注意。

次にNode.jsの環境が整ったら、
npmを入れて、いざgoogle-home-notifierを導入へ
https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066
上記を参考にしました。


$ # package.jsonを作ります
$ npm init

$ # google-home-notifierを入れます
$ npm install google-home-notifier

$ # yarn の方は下記のようにします。
$ yarn add google-home-notifier

このようにgoogle-home-notifier導入

その後、
Javascriptでファイルを作ります。
xxxx.js
とかのNode.jsのファイルを作って

とりあえず、サンプルコードを作ります。
jconst googlehome = require('google-home-notifier')
const language = 'ja';

googlehome.device('Google-Home', language); 

googlehome.notify('こんにちは。私はグーグルホームです。', function(res) {
  console.log(res);
});

こんな感じ。

さて、コンソールでこのファイルを動かして見ると、
喋るーーーーーーー

と言うことで、Jacascriptでかけました。

C＃ではどうするんだ？
と言うことで、次回は、C#の中にJavascriptを食い込ませたやり方を
考えたいと思います。

まだまだ初心者なので、
配列を改めて勉強してるレベル。。。

精進します。

参考にしたサイト
https://smarthacks.jp/mag/37615
https://qiita.com/kenz_firespeed/items/0979ceb05e4e3299f313
https://blog.okazuki.jp/entry/2018/06/28/141410
https://azure.microsoft.com/ja-jp/services/functions/

最近学んだ言葉。
サーバーレス・コンピューティング
何かをWeb上で運用するとき、本来ならサーバーの管理が必要だが
サーバーを管理しなくていいものが作れる


オーケストレーション
オーケストラのように指揮者がいて、楽器を演奏する人がいる
指揮者を管理、開発者に例えて、サーバーなり、コードなり諸々を指揮すること


イベント ドリブン型
イベントの発生をきっかけとして処理を始めること


デプロイ
ビルドしてできた実行ファイルを、実行する環境に合わせて、実際に実行できるようにする


トリガー
きっかけになる出来事が起こったら自動的に特定の処理を起動するソフトウェアの仕組み


バインド
何らかの要素やデータ、ファイルなどが相互に結び付けられること

functions
複雑なオーケストレーションの問題も解決できる、イベント ドリブン型のサーバーレス コンピューティング プラットフォームである Functions を使用して開発を効率化しましょう。追加のセットアップを必要としないローカルでのビルドとデバッグ、クラウドでの大規模なデプロイと運用、トリガーとバインドを使用したサービスの統合が可能です
要するに、サーバーレスで、簡単にものが作れまっせってこと。
楽チンにサービス作れますよってこと

Json
配列の（）の中のものがkey
配列の箱の中にはなんでも（データ型は決まってるが）入るから
keyに対応させた表を作ること
簡単に言うと配列を表にしちゃえ！もっといえば、それをまとめたものJsonってのを作っておけば、引っ張ってくるとき楽やねん
オプショナル使い方集[Swift]

#### クラスで絞る

```swift
//一番親のViewがSCNViewだったら
let scnView = self.view as! SCNView
//そいつの背景青にする
scnView.backgroundColor = UIColor.blue
```

https://qiita.com/hachinobu/items/2ecfc5999327fff20837

#### if letとか

```swift
if let HugaViewController = hogehuga as! HogeViewController {
            //hogehoge
}
```
`!`ではなく**`?`にしてオプショナルにしなさいよ**(`nil`を許容しなさいよ)ということらしい

```
Initializer for conditional binding must have Optional type, not 'HogeViewController'
//条件付きバインディングのイニシャライザには、「HogeViewController」ではなく「Optional」型が必要です
```

```swift
if let HugaViewController = hogehuga as? HogeViewController {
            //hogehoge
}
```

あとで追記
Sierがテスト会社に転職して学んだこと

新卒でSier企業に入社し、ちょうど3年半で転職しました。
そして、テスト会社に入社しちょうど1年が経ちました。

そこで今回は、Sierで経験したこと、転職に至った経緯、テスト会社に転職してみてどうだったか、まとめてみました！

## そもそもなぜ転職したのか
新卒で入社したSI企業で、見事に配属部内のほとんどの上司、先輩にに好かれませんでしたｗ

入社一年目の時、一緒に働いていた先輩からは
⇒「他の人より仕事が遅いから残業するのなら残業は付けないで」と言われ

さらにその上の先輩からは
⇒「お前が辞めるって言っても俺は守らないけど、○○（上の一緒に働いていた先輩）は守る」と言われ

そのくせ、簡単な誰でもできるような仕事は命令してくるんですよねｗ

最悪なスタートでした。
しかも、東京で大卒で初任給270万以下ｗ

さらに、昇給はしたものの昇給額が1か月あたり500円ｗ
バイトかよｗｗｗ


そして決めたのが『できるようになったら辞めてやる！』ということｗ

## 転職するために

そこから、転職するためにWeb言語を勉強し、フレームワークによる開発を学び、デザインを学び、アクセス解析を学び、お金を稼ぐにはどうしたら良いのか、営業も学び、3年目が過ぎたとき転職活動を始めました。


そして転職活動をする中でテスト会社に採用され、新卒からちょうど3年半で入社しました。


## テスト会社で学んだこと

前職でのテストでは、UTやITでの経験はありましたが、仕様書通りに動いていることの確認だけでした。

テスト仕様書を作るようになると先輩からは「これでもう障害はないの？」という疑問を投げかけられる。
私は、「障害を全部発見はできないし、やれというなら時間が足りない」といってもやれと言われる。

### バグゼロの落とし穴
しかし、転職して学んだことは『障害はゼロにはならない』ということ。

これは本当に心に響きました。

だって、前職では「障害があると思うなら全て確認して障害としてあげろ」と言われていたことが、「障害が残っていても良い」という安心感が持てるんです！

障害がゼロにならないことは、ソフトウェアテストの7原則で記されています。

### 開発者は仕様を誤って開発する
開発の依頼側は仕様をまとめ仕様書を作ります。
そして開発者は仕様書を読み取り、仕様が遂行できるように開発します。

しかし、人の認識というものは怖いもので、このような有名なプログラマージョークがあります。
> 妻が夫に「買い物にいって牛乳を1つ買ってきて。卵があったら6つお願い」と言ったら、夫は牛乳を6パック買ってきた。

#### 妻は
夫に「買い物で牛乳を1つ、卵があったら卵を6つ買ってきて」という意味だと思います。

#### しかし夫は
「買い物で卵があったら牛乳6つ、なければ牛乳1つ」という意味だと認識してしまいました。

#### 認識が異なる
このように開発を依頼する側と実際に開発をする側で仕様の認識が異なってしまうことが良くあります。

実際に私が前職で開発をしていた時だってありました。

それらを開発とは異なる目線で、仕様を満たすためのテストをする目線で、テスト会社としてテストするため、曖昧な仕様は常に確認し、明確にすることが大切であることを学びました。

そして、開発と並行する形で仕様を明確にすることで、システム開発あるあるの「最終段階で仕様変更が入る」ということが減らせるのだと実感しています。

## 転職って素晴らしい
転職する前、「転職して良かったと思えるのだろうか」などという不安が常にありました。

だって、古代言語での業務経験しかなく、初めての転職、それ以上に悪くなったらもう生きていけなくなりそうですｗ

### しかしいざ転職が実現すると
#### 年収UP
まず、生きるために必要なお金、年収は100万円以上上がりました！

これ、めちゃくちゃ重要ですよね！

しかも、転職後の評価でも年収100万以上UP！


#### 仕事が楽しくなった
もちろん、大変なことも多くありますし、嫌なことも多くあります。

しかし、第三者としてのテスト会社の一員として、より上流に近い形で要求定義から加わり、テストもSTやUATといった、単純な仕様書通り動くかの確認以上のことを行い、個人的にはとても楽しくやれています。

さらに、上司からも現在は嫌われておらず（←ここ重要ｗ）、評価もしっかり受けられています！


## 最後に
Sierがダメというわけではありませんし、現在もテスト会社としてSierと同様の働き方をしています。

どのような職業でもいえることですが、今の職場が辛い、続けられそうにないのであれば、そんな仕事一生続けるなんてできませんし、その前に人が壊れてしまうでしょう。

さらに、給料が安い場合も同様で、上がる見込みがないのであれば、上がる会社に転職すれば、実は簡単に給料が上がる可能性もあります。

もちろん、給料は労働の対価であり、安い単価の仕事しかできないのであれば安いままかもしれません、成長できる業務、評価してくれる会社があれば、頑張れば給与が上がるものだと今は思っています！

テスト会社に入社してもよいのか悩んでいる方、転職をしようか悩んでいる方の参考になれば幸いです。
mac mini 2018 をmacOS Catalinaにアップグレードしたら画面が映らなくなった件

## 1. はじめに
macOS Catalinaがリリースされました。iPadは持っていませんが、Sidecarに興味があり、思わず上げてしまった。。。らです。画面が映らない。。。

今回はそんな時の対処法を書きます。

## 2. 目次
```:目次
1. はじめに
2. 目次
3. macOS Catalinaにアップグレード
4. 再起動後に画面が映らない
5. SMCリセットにて復活
6. さいごに
7. 参考サイト
```

## 3. macOS Catalinaにアップグレード
現在、Mac mini 2018にて色々なサービスをセットアップしているところです。 もともとMac mini Server (Mid 2011）を使用していて、そちらからのサービスの移行になります。
サービスは元々High SierraまでmacOS Serverの中にいたのですが、OSSサービスの見直しによってそれらのサービスはmacOS Serverの中に含まれなくなりました。

今回のアップグレードは、サービスをセットアップしてからOSのアップグレードをしたらサービスがおかしくなることを恐れ、あらかじめアップグレードしてしまおうと思ったからです。

特に変なことはしておりません。
MojaveからOSのバージョンアップ、更新はApp Storeではなく、環境設定から行うようになりました。そちらから、アップグレードを実施しました。


## 4. 再起動後に画面が映らない

一度ダウンロードしてから、セットアップが開始され、最終的には再起動されたのち。。。知らない間に画面に映ってこない。ハングアップしたのかと思い、キーボードでキーを叩くと音がする。。。

最初、何が起こっているのか全くわかりませんでした。

今のMacは起動音がならなくなっているのでなおさらです。

仕方がないので、起動しているかどうかの切り分けを行うために、macbook pro からVNCで画面共有すると。。。起動画面が見えます。
そう、ちゃんと起動しているのです。画面が映らない。

しかしながらこれだけだと、Catalinaがモニタ（当方モニタはLG UltraHD 24インチを使用しております。）が悪いのか、それともHDMIへの出力ができていないのかがわかりませんでした。

とはいうものの、HDMIを入力できる機器が他に用意できなかったため、似たような症状を探すことにしたんです。


## 5. SMCリセットにて復活

調べてみると、確かにある。。。Mac mini限定のようですが、HDMIの出力ができないと書かれていました。
そして、SMCリセットで復活する人もいたとか。。。

藁をもすがる思いで、SMCリセットを実施しました。
以下のページを参考にしました。

[Mac の SMC (システム管理コントローラ) をリセットする方法 - Apple](https://support.apple.com/ja-jp/HT201295)

私が実施したのは以下の通りです。

* Apple メニュー >「システム終了」の順に選択し、Mac がシステム終了するまで、そのまま待ちます。
* 電源コードを外します。
* 15 秒間待ちます。
* 電源コードを元通りにつなぎます。
* 5秒待ちます。
* 電源ボタンを 10 秒間長押しします。
* 電源ボタンを放し、数秒待ちます。
* 電源ボタンをもう一度押して、Mac の電源を入れます。
* 問題が解決しない場合は、以下の手順を実行してください。

これで再起動したら、無事画面が表示されました。

さて、SMCとはなんなのでしょうか。
ここで軽くそれに触れます。

**SMC の役割**
SMC は、Intel 搭載の Mac で以下を含むローレベルの機能を制御します。
* 電源ボタンを押したときの反応
* Mac ノートブックのディスプレイの蓋を開いたり閉じたりしたときの反応
* バッテリー管理
* 熱管理
* SMS (緊急モーションセンサー)
* 環境光センサー機能
* キーボードのバックライト機能
* ステータスランプ (SIL) 管理
* バッテリー残量のインジケータランプ
* 特定の iMac のディスプレイに対して (内蔵ではなく) 外部のビデオソースを選択

## 6. さいごに
うちの場合はなんとかSMCリセットで復活しましたが、それで復活しない場合は、どうやらApple Storeに持ち込むしかなさそうです。。。

そうならないためにも、Catalinaへのアップグレードは、10.15.2くらいまで待つことをお勧めします。。。

## 7. 参考サイト
* [macOS 10.15 CatalinaへアップグレードしたMac miniで、HDMI信号が出力されない不具合が報告される。 | AAPL Ch.](https://applech2.com/archives/20191010-no-hdmi-signal-after-catalina-upgrade.html)
* [Mac の SMC (システム管理コントローラ) をリセットする方法 - Apple](https://support.apple.com/ja-jp/HT201295)
*
SMTP25番ポートと587番ポートの違い

#送信ポート（SMTP）設定時に必要なポート番号の使い分け
SMTPを使用する際のポート番号は25番ポートですが、587番ポートを使うケースもあります。
なぜ25番と587番に分かれているのか調べてみました。
##ポート番号25とは？
古くから使用されている送信ポートであり、利用者の認証や送信元のドメインチェックなどといったセキュリティ面で必要不可欠な機能が欠落している。
25番ポートにはユーザー認証機能がないため、誰でも簡単にメールが送れてしまう。
つまり、外出先からメールを送る際に契約しているプロバイダではない回線からでも自分のアドレスからメールを送ることができるのでサーバー認証が不要で悪用が可能となる。
##OP25B（Outbound Port25 Blocking）
>プロバイダに接続しているネット利用者が、25番ポートを使用してメールを送信すると、その通信を遮断するプロバイダ側のブロック機能です。サーバーの25番ポートに接続しようとすると、「プロバイダ」によってその通信がストップさせられてしまうんですね。
OP25Bはスパムメール対策として、非常に効果がありました。しかし一方で、正しく利用しているユーザーにとっては弊害でしかありません。25番ポートへの接続を禁止するイコール、プロバイダのメールサーバーを使用してのメール送信ができないわけですから。つまり、いままでできていた外出先での契約プロバイダのアドレスを使ったメール送信も、エラーになってしまうのです。

(参照)[ウェブラボ（株）スタッフブログ](https://www.weblab.co.jp/staff/other/4515.html)

##そこで登場！587番ポート
OP25Bを導入すると、悪用は防げてもユーザーにも弊害があるためとても悩みどころだ。
そこで登場するのが587番ポートだ。（サブミッションポート）
587番ポートでは、SMTP-AUTHという認証が必要になり、その際にユーザーIDとパスワードを要求する。
このユーザーIDとパスワードを知っている人にしかプロバイダに接続した状態でのメール送信はできなくなった。
587番ポートのおかげで迷惑メール業者が減った。
##SMTP-AUTH（Authentication）とは
>「SMTP AUTH」とはメール送信時にSMTP(送信)サーバーに対して認証を取る方式です。
「POP before SMTP」認証と比べ、受信（POP認証）と送信（SMTP認証）の認証を別々にする事で
SPAMの踏み台になりにくく、セキュリティ向上が見込まれます。

(参照)[Bizメール＆ウェブ ビジネス](https://support.ntt.com/mw-business/faq/detail/pid2300000h3n)

##サブミッションポートとは
>サブミッションポートとは、メールソフトからメールサーバへメールを投稿（submission）する際に用いる、専用のTCPのポート番号。サーバの運用者が個別に指定するが、一般的に587番が用いられる。
従来は、一般にSMTPが利用する25番ポートを用いて処理されていたが、迷惑メール対策の一環として、利用者からのメール送信の受付はサブミッションポートに分離し、25番はサーバ間のメールの転送にのみ用いる事業者が増えている。このとき、外部からの不正利用を防止するため、サブミッションポートでのメール送信にはSMTP AUTHなどによるユーザ認証が求められることが多い。

(参照)[IT用語辞典 e-Word](http://e-words.jp/w/%E3%82%B5%E3%83%96%E3%83%9F%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88.html)


##まとめ
- 25番ポートはユーザー認証が不要なため、セキュリティ面で大きな問題がある
- OP25Bは迷惑メール送信の防止をおするために生まれた
- OP25Bを導入しても、自宅からであれば25番ポートを宛先にしても届くが、外出先からは587番ポートへの宛先じゃないとメールが届かない
ESP32-DevKitC-32D（ESP-WROOM-32D開発ボード）をGroveセンサーに直結する

ESP32-DevKitC-32D（ESP-WROOM-32D開発ボード）を、シールドを介さず、直接Groveセンサーとつなぎます。

# 材料
今回使用したものです。

- ESP32-DevKitC-32D（ESP-WROOM-32D開発ボード）
- GROVE - LED 青
- ブレッドボード
- ケーブル

# サンプルプログラム
Arduino IDEのスケッチ例にある「Blink」をベースに作成しました。
LEDは4番につなぐことにしました。

```c
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);              // wait for a 500ms
  digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
  delay(500);              // wait for a 500ms
}
```

# 接続
別に、ESP32-DevKitC-32DとGroveセンサーを直結してもよいのですが、他のピントの接触や、書き込み問題（※後述）でBoot/ENボタンを押さなくてはいけないため、安定させるためにブレッドボードを使用しました。

ただ、ブレッドボードが小さいとケーブルが刺さらないため、今回は半分だけ刺しました（苦笑）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/79998ce1-cd66-aa16-63eb-fa388aa884cd.png)

そのため、刺さっていない側で使用するピン（今回は5V）には、先が以下のようになっているケーブルを直結しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/051fef73-65d3-e8c8-dab2-b91eebc7033f.png)

## ESP32-DevKitC-32D側の使用ピン
ESP32-DevKitC-32D側で使用するピンは、以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/a492a3f9-270d-3a8b-f008-1f23194370f3.png)
※参考：https://ht-deko.com/arduino/esp-wroom-32.html

- 5V：電源
- GND：アース
- IO4：信号

※今回使用する電圧は5Vになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/716ece52-2393-b789-5561-2107765076b0.png)
※参考：http://wiki.seeedstudio.com/Grove-LED_Socket_Kit/

## Grove側
Grove LED側が使用するピンは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/e5a94870-d380-2ed9-c49e-48578e847cd5.png)

- 1.SIG：信号
- 2.NC：（使用しない）
- 3.VCC：電源
- 4.GND：アース

## 接続
それぞれ対応するピンをケーブルで接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/700c1998-9b2c-7863-1bee-fba6e6f6e17e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/77b53b88-49f4-097b-4624-a674ce143d67.png)

# 実行
接続したら、サンプルプログラムをコンパイル＆書き込み、実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/33535ef1-ce16-dfd2-1901-cb4dd1bde530.png)

無事、0.5秒ごとに点滅できました。

# まとめ
ESP32-DevKitC-32DとGroveセンサーは簡単につなぐことができますが、複数のセンサーをつなぐときのことなどを考えると、やはり大きいブレッドボードがあったほうがよいです。

# 【おまけ】書き込み問題

コンパイルし書き込もうとすると．．．エラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/952b0de5-d05e-14cc-56a8-efd25b277def.png)

```text
esptool.py v2.6
Serial port COM4
Connecting........_____....._____....._____....._____....._____....._____....._____

A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
```

調べてみたところ、解決方法は今のところ以下しかない模様。

1. ボードの「Boot」ボタンを押しっぱなしにする<br/>この状態を4.まで、ずっと続ける
2. 「Boot」ボタンを押しっぱなし状態で、ボードの「EN」ボタンを一度押す
3. 「Boot」ボタンを押しっぱなし状態で、Arduino IDEの書き込みボタンをクリック
4. Arduino IDEのコマンドラインに、「Connecting...」と表示されたら「Boot」ボタンから手を放す
5. 書き込みが完了（結構時間がかかる）したら、「EN」ボタンを一度押す
Raspberry Pi でPWM信号を使って5Vファンを制御する

# Raspberry Pi でPWM信号を使って5Vファンを制御する
※ 自作PCで使うような4pinファンを動かすのではなく、2pin(VDDとGND) ファンを制御するという内容です。

[Raspberry Pi でPWM信号使ってLEDの明るさを変更する](https://qiita.com/sh_o/items/9d8a617ea3e799d5fc79) でPWM信号を使ってLEDを点灯させた。
Raspberry Pi のPWM出力電圧(3.3V) では5Vファンの入力電圧(5V) には届かないため、GPIOの5V電源をトランジスタで制御し、PWM信号として使用した。

# 部品類
- 5V DC-FAN (D02X-05TS1 02)
- トランジスタ (2SC1815GR)
- 抵抗 (1kΩ)

# 回路図と配線

![pi_GPIO_PWM_t.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515629/c03b6ae4-a5d2-992c-9654-f4755b0472cf.png)
![FAN_PWM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515629/1f6b8f1e-6f55-e238-4027-5b96793095d7.png)

# PWMを出力するコードを書く
ほとんど[LEDの時](https://qiita.com/sh_o/items/9d8a617ea3e799d5fc79)と同じ
差分としては、LEDの時は10%の出力と100%を繰り返した ( `for i in [10, 100, 10, 100]:` ) が、
今回使用したファンは10%の出力では始動電力に届かなかったようで動き始めなかったため、20%に変更した ( `for i in [20, 100, 20, 100]:` ) 。

```python
import RPi.GPIO as GPIO
import time


def main():

    frequency = 200
    repeat_count = 600
    gpio_pin = 18

    GPIO.setmode(GPIO.BCM)
    GPIO.setup(gpio_pin, GPIO.OUT)

    for i in [20, 100, 20, 100]:
        
        if 0 == i:
            on_time = 0
            off_time = (1 / frequency)
        else:
            on_time = (1 / frequency) * (i / 100)
            off_time = (1 / frequency) * (1 - (i / 100))

        for rc in range(repeat_count):
            GPIO.output(gpio_pin, True)
            time.sleep(on_time)
            GPIO.output(gpio_pin, False)
            time.sleep(off_time)
            
    GPIO.cleanup()


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

Raspberry Pi では "vcgencmd" というコマンドでCPU温度などの情報を取得することが可能なようなので、
○○°Cを超えたらファンの出力を××%に などできそう。

# 参考記事
>
[RaspberryPiのCPU情報をPythonで取得する](https://qiita.com/Fendo181/items/a1fde032377337af3264)
pythonistaにstashを入れてモジュールをインポートできるようにする

### 概要
みなさんこんばんは
pythonistaはデフォルトで色んなツールがインストールされていますが開発を進めていく上でどうしてもサードパーティのモジュールをインポートしたい時があるかと思います。
今回はpythonista3にstashを入れてpipなどのコマンドを使えるようにします。

### 参考にしたサイト

- https://qiita.com/maboy/items/cef5dee13d5b2e9ac843
  - このサイトでもpythonistaへのstashへの導入を　実践していました。
- https://mahimahironron.hateblo.jp/entry/2019/10/06/
  - このサイトも参考にしました。

### 実施内容
以下のコマンドをpythonistaのコンソールで実行します。その後、pythonistaのアプリを再起動します。

```
import requests as r; exec(r.get('http://bit.ly/get-stash').text)
```

すると「this ipad」の中に「launch_stash.py」というスクリプトが出来ているので実行します。
するとコマンド用のコンソールが立ち上がります。cdやlsなどの簡単なコマンドなら使えるようです。helpと打つことでどんなコマンドが使用可能か見ることができます。

### Numpyが入らない。。
Pythonistaの制約かわかりませんが、Nunpyを新しくインポートする事ができないようです。
デフォルトでは1.8がプリインストールされているけれどずいぶん古いです。どうすればいいのやら。。
Rubyローカル環境構築：Homebrew、rbenv、ruby-buildを使った構築方法

# 概要
ここではHomebrewのインストールについて記載する。
作業で必要になったので、メモを兼ねて記載。

## 環境
Mac OS Catalina 10.15

## 前提
・Xcodeのインストール
・Command Line Toolsのインストール(xcode-select --install)

# インストール
## 1.Homebrewをコマンドラインでインストールする

ターミナルで以下を記載して実行する

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew

Press RETURN to continue or any other key to abort
==> Downloading and installing Homebrew...
HEAD is now at 8a5e32ccc Merge pull request #7663 from MikeMcQuaid/external-man
Updated 1 tap (homebrew/core).
==> Updated Formulae
imagemagick ✔    atlantis         gatsby-cli       imagemagick@6    node-sass        onnxruntime      picard-tools
acpica           evince           hlint            mu               nss              pandoc-crossref  stellar-core
==> Installation successful!

==> Homebrew has enabled anonymous aggregate formulae and cask analytics.
Read the analytics documentation (and how to opt-out) here:
  https://docs.brew.sh/Analytics
No analytics data has been sent yet (or will be during this `install` run).

==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations

==> Next steps:
- Run `brew help` to get started
- Further documentation:
    https://docs.brew.sh
```

Installation successfulと表示され、インストールが成功する


## 2.Homebrewを最新にする

```
$ brew upgrade
```

## 3.rbenvのインストール

```
$ brew install rbenv
$ echo 'eval "$(rbenv init -)"' >> ~/.zshrc
$ source ~/.zshrc
```

## 4.Rubyのインストールと利用設定

```
$ ]$ rbenv install 2.6.6
Downloading openssl-1.1.1g.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
Installing openssl-1.1.1g...
Installed openssl-1.1.1g to /Users/mem/.rbenv/versions/2.6.6

Downloading ruby-2.6.6.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.6.tar.bz2
Installing ruby-2.6.6...
ruby-build: using readline from homebrew
Installed ruby-2.6.6 to /Users/mem/.rbenv/versions/2.6.6
```

インストール後、標準で利用するRubyのバージョンを2.6.6にする。

```
$ rbenv global 2.6.6
```

ターミナルでRubyのバージョンを確認する。

```
$ ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin19]
```


## 変更履歴
|日付|内容|
|:--:|:--|
|2020/05/31|マシン環境の変更(zshに対応)とRubyバージョン更新により、方法の一部変更|