OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinでよく調べちゃう記法のTips

#はじめに
こちらのページで作ったTipsのKotlin版を作ってみました。
https://qiita.com/osashimi_lover/items/529e97ca1c13259a921b

こちらでも、基本的なところを記録していこうと思います。:raising_hand:
ご指摘などがあれば、ぜひよろしくお願いします。
※Versionは 1.3.31-release-197 を使用しています。

#文字列操作
```kotlin
// 入力文字列を受けて分割する
val str_arr = readLine()!!.split(" ")

// 一部切り出し(最初からnum文字目まで)
val part_str = str.substring(0,num)

// 文字列を分割(空要素は削除)
val chr_arr = str.split("").filter { it != "" }

// 数値→文字列
val str = num.toString()
```

#数値操作
```kotlin
// 文字列→数値変換
val num = str.toInt()

// 絶対値を求める
 var num = Math.abs(num1)
// xのy乗(Double)
var num = Math.pow(x, y)
```

#ループ操作
```kotlin
// 単純なnum回ループはrepeatを用いるべき。
repeat(num) {
// 現在のループ回数はit(値は0~num-1)で取得可能。
~
}

// イテレータの名称をつけることも可能
// また、repeat()はKotlinの標準関数のため、breakが使用できない。
// ループにラベル'@xxx'をつけてreturn文を書くことで同等の動きが可能。
repeat(num1) { it ->
    un check_loop@ {
        repeat(num2) { it2 ->
            if(array[it2] == it) {
                return@check_loop
            }
        }
    }
}
```

#分岐操作
```kotlin
// switch_case
when(status_num) {
    0 -> return "OK"
    1 -> return "NG"
    else -> return "ERROR"
}
```

#配列操作
```kotlin
// Int配列の初期化(0埋め)
var array = IntArray(num) {0}

// 配列要素の出力
array.forEach(::print)
```

#参考文献
[Kotlin公式](https://kotlinlang.org)
NuxtからFirestoreエミュレータを使おうとしたらエラー：Function Firestore.settings() requires its first argument to be of type object, but it was: a custom Object object

# 事象

nuxt.jsで、Firebase Firestoreを扱うアプリケーションを作成している最中に、Firestoreのエミュレータを使いたいなぁと思って、Firebaseの初期設定をしているコード部分に以下のようなコードを追記しました。

なお、nuxtはUniversalモード（SSRモード）で動かしています。

```javascript:firebase.js
import firebase from 'firebase/app';
import 'firebase/firestore';

export const database = firebase.firestore();

// ***** エミュレータを使うために下記コードを追記 *****
database.settings({
  host: 'localhost:8080',
  ssl: false,
})
console.warn('Firebase Firestore is emulator!');
```

すると、次のようなエラーメッセージが出るようになってしまいました。

```
Function Firestore.settings() requires its first argument to be of type object, but it was: a custom Object object
```

![エラー画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84550/14439115-d083-6b96-d922-5749e2844c1d.png)

# 解決策

nuxt-community/firebase-moduleの、下記Issueにて、同様の事象について取り扱われていました。

[[SSR] Setting firestore.settings results in "Function Firestore.settings() requires its first argument to be of type object, but it was: a custom Object object" #116](https://github.com/nuxt-community/firebase-module/issues/116)

Universalモードの場合のみ、発生するようです。どうやら、`nuxt.config.js`に、下記を追記すると治るらしい。

```javascript:nuxt.config.js
export default {
  mode: 'universal',
  // ***** 追記部分　ここから *****
  render: {
    bundleRenderer: {
      runInNewContext: false,
    },
  },
  // ***** 追記部分　ここまで *****
};
```

`runInNewContext`がどういう設定項目なのかについては、Vue SSR ガイドに記載されています。

[Vue SSR ガイド / APIリファレンス](https://ssr.vuejs.org/ja/api/#runinnewcontext)

詳しくは、このリファレンスの説明を読んでいただければと思いますが、その中に、次のような記述があります。

> このオプションは、下位互換のためデフォルトは `true` です。しかし、可能ならば常に `runInNewContext: false` または、`runInNewContext: 'once'`を使用することが推奨されます。

ですので、通常であれば、`false`にしておいて影響はなさそうです。（これ以上は調べていません。ごめんなさい。）
【bash】edコマンドの活用（大量のファイルを同じ手順で編集したい）


# はじめに
```sed```, ```awk```, ```tr```, ```sort```, ```vi```などUNIX系OSには様々なテキスト処理系のコマンドがありますが、その中の一つ```ed```コマンドを紹介します。

# 使う場面
タイトル通りです。```sed```, ```awk```, ```tr```, ```sort``` は入力ファイルと出力ファイルが異なります。```vi```はファイル１つ１つを都度開いて編集する必要があります。

```ed``` は ```vi``` に分類されるものですが、ちょっとしたテクニックを知っているとバッチ処理で使う場面がでてきます。

# スクリプト
スペースをタブに変更します。

```bash
#!/usr/bin/bash

ed $1 <<__END__
p
s/ /    /g
p
w
q
__END__
```

- コマンドは ```sed```, ```vi``` を知っているなら分かると思います。

# 備考

grepは、「g(global)＋re(正規表現)＋p(print)」の略なんだそうです。
Matplotlibで大量に画像を出力するとメモリリークする問題をなんとかしたい

##概要
Matplotlibを利用してデータを可視化し、画像を出力することは少なくないだろう。その際savefigを使って画像を出力すると若干のメモリリークが起こってしまうようだ。
数百枚～数千枚程度であれば特に問題ないが、かなり大量のデータに対し数万枚～数十万枚の画像を夜通し出力したい場合などに問題になる。

##動作環境
Python：3.7.7
Matplotlib：3.2.2

##調査

以下のコードを使ってメモリの増加量を調べた。

```Python
import os
import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
import psutil

#計測用データ
memory_start = psutil.virtual_memory().used
time_start = dt.datetime.now()
fw = open('./計測ログ.csv','w')
fw.write('i,time_delta[s],memory[KB]\n')
 
#1万枚出力させる
for i in range(10000):
    #適当な2種類のデータを生成
    size = 10000
    x1 = np.random.randn(size)
    y1 = 0.5*x1 + 0.5**0.5*np.random.randn(size)
    x2 = np.random.randn(size)
    y2 = np.random.randn(size)

    #グラフを初期化し散布図を作成
    fig, ax = plt.subplots(figsize=(8,8))
    ax.scatter(x1, y1, alpha=0.1, color='r', label='data1')
    ax.scatter(x2, y2, alpha=0.1, color='g', label='data2')
    
    #ラベル・凡例をつける
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.legend(loc='upper right')
    
    #画像出力
    plt.savefig('./output/{:05}.png'.format(i))
    
    #グラフデータを解放する※
    #plt.clf()
    #plt.cla()
    plt.close()
    
    #開始時からのメモリ増加量と1ループの時間を計測
    memory_delta = psutil.virtual_memory().used - memory_start
    time_end = dt.datetime.now()
    time_delta = time_end - time_start
    time_start = time_end
    fw.write('{},{},{}\n'.format(i+1, time_delta.microseconds/1e6, memory_delta/1e3))

fw.close()
```

なお、グラフのメモリ解放を行う際、closeのみ行う場合とcla,clfを行ってからcloseした場合で計測した。

![graph2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259220/ba4eac43-ceed-9911-e847-f012add4876b.png)

closeのみの場合よりもcla,clfを前に行ったほうがメモリの増加量は半分程度に抑えられている。
しかし、どちらの場合でも増加してしまうことが確認できる。

##どうする？

何枚画像を出力してもメモリを増加させないためにはどうすればよいか？
いろいろ試した結果以下のようにコードを書き換えることでメモリリークを抑え、
かつきちんと画像の出力を行うことができた。

```Python
#初めに初期化を1回だけ行う
fig, ax = plt.subplots(figsize=(8,8))

for i in range(10000):
    #適当な2種類のデータを生成
    x1 = np.random.randn(size)
    y1 = 0.5*x1 + 0.5**0.5*np.random.randn(size)
    x2 = np.random.randn(size)
    y2 = np.random.randn(size)
    
    ax.scatter(x1, y1, alpha=0.1, color='r', label='data1')
    ax.scatter(x2, y2, alpha=0.1, color='g', label='data2')
    
    ax.set_xlabel('X')
    ax.set_ylabel('Y')    
    ax.legend(loc='upper right')
    
    plt.savefig('./output/{:05}.png'.format(i))

    #claのみ行う
    #clf,closeを行ってしまうとその後グラフに書き込めなくなってしまう
    #逆にclaを行わないと前の画像にどんどん重なってしまう   
    plt.cla()

```

![graph.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259220/5d857576-7837-c112-86b2-29175c4b0141.png)


画像サイズを途中で変えたい等が無ければおそらくどんなグラフでもこれで対応できるのではないかと思うがあまり確信はないので利用する際はご注意。
AWS Educateを使ってみて思ったことを綴る

# はじめに
この記事では一般的に用いられるawsアカウントではなくaws Educateのアカウントを使って一般用とは少し違う？ところ（自分が使ってみた所感）を記述していこうと思います．

# AWS Educateとは
https://aws.amazon.com/jp/education/awseducate/
このサイトには,
> AWS Educate を通じて、学生と教員は、成長分野のクラウドキャリアに対応するために開発されたコンテンツとプログラムにアクセスできます。また、AWS Educate は、クラウドスキルを採用している企業を、AWS Educate 求人掲示板で資格のある学生求職者とマッチングします。

ということができるらしいです．しかし，具体的にawsのEC2が出来るの？出来るのだとしたらどこまで？とは書かれていません（結論的にはできます）．本記事ではEC2を建てることはしませんが，一般用と学生用で与えられている権限の違いなどを実際のコンソール画面を見せながら説明していきます．

詳しい概要は以下のサイトがやくに立つと思います．
https://qiita.com/yosshi4486/items/609045ae9e7e50505772
https://qiita.com/tanaka_mizuki/items/107dd68d45e38b761622

# 目次

- コンソール画面
- 権限
- AWSサービス

# コンソール画面
<img width="724" alt="スクリーンショット 2020-07-19 17.43.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460757/e7c1d722-7bf3-1989-bafb-812c1c58de31.png">
コンソール画面は一般用とあまり変わりはないように思います．

# 権限
基本的に与えらる権限は小さいです．例えば，ヘッダーにあるアカウントの場所から「マイアカウント」「マイ組織」をクリックしてもエラーが表示されます．
<img width="724" alt="スクリーンショット 2020-07-19 17.52.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460757/d81c2996-eb2c-ccc5-602e-9dc405d3df2f.png">

awsのサービスについても同様のことが言えます．例えばIAMユーザの機能は使えません（私がやった範囲の中では）でした．IAMユーザは他のチームメンバーが参加して来た時にどれくらいの権限を付与させるのかを指定する機能です．一般的にアカウント作りたての場合はルートユーザーですが，メールアドレスの変更やクレジットの変更など以外は使用せず，IAMユーザを利用することを推奨されています．しかし，この機能はAWS Educateアカウントでは作成出来る機能が付与されていません．察するに，対したアカウント情報を登録していないからではないかと思いますが，よくわかりません．

*補足ですが，IAMユーザ自体は作成出来るのですがエラーが表示されそのアカウントでログインができません．まぁ結論的に利用できないのは同じです．以下の画像
<img width="500" alt="スクリーンショット 2020-07-19 17.58.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460757/cdb9d69c-853f-466f-7d70-05b38a7827d0.png">

# AWSサービス
AWSの各サービスが利用出来るかについて記述します．結論的には使えます．ただし，機能的には小さいものであり大容量のEC2サーバーを建てることは推奨しません（やろうと思えば多分出来る？）．というのも与えられている金額も30.00$ぐらいですしあくまでもインフラを構築するお勉強と思って頂ければいいのではないのでしょうか．
しかし，注意した方がいいのがサーバーを建てる時のリージョンについてです．例えばVPCとかでネットワークの初期設定をする時にリージョンを選択しますが，日本（東京）を指定して作成すると何故かエラーが出ます．ちなみにリージョンをバージニア北部で設定するとうまく設計できます．これはVPCだけでなくCloudWatchの機能などにも通じ，おそらく他の機能も同じようなことが起きているのではないのでしょうか？
<img width="724" alt="スクリーンショット 2020-07-19 16.28.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460757/dbf9aad2-ee24-b790-8272-4181a3b2c049.png">
上の画像のようにアベイラビリティゾーンをUS設定にしないとできないみたいです．ちなみに他のUSの場所でも適応外でありバージニア北部のみが作成出来るようです．リージョンはアメリカでも機能しますのでアメリカで作ってみた方が良さそうです（多少$は上乗せされますが）．


# まとめ
本記事ではAWS Educateの一般用とは少し違うところ，というものを紹介しました．具体的には権限やサービスで気をつけることを記述しました．学生の皆様も無料でawsが使えるので少し触ってみてはどうでしょうか？？
Mac Rails Install Error

下記エラーでRailsのインストールが出来なかった！！
To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/macintosh/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/extensions/x86_64-darwin-17/2.7.0/nokogiri-1.10.10/mkmf.log

extconf failed, exit code 1

下記の設定で解決しました。
gem install nokogiri -- --with-xml2-include=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/libxml2 --use-system-libraries
SinatraでJSONのrequestを受け取る方法

# 答え

rack-contribの `Rack::JSONBodyParser` を利用すればよい。

# 使い方

公式の記載の通り。普通のRack middlewareです。

参照元）https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/json_body_parser.rb

>  # == Examples:
  #
  # === Parse POST and GET requests only
  #   use Rack::JSONBodyParser, verbs: ['POST', 'GET']
  #
  # === Parse POST|PATCH|PUT requests whose Content-Type matches 'json'
  #   use Rack::JSONBodyParser, media: /json/
  #
  # === Parse POST requests whose Content-Type is 'application/json' or 'application/vnd+json'
  #   use Rack::JSONBodyParser, verbs: ['POST'], media: ['application/json', 'application/vnd.api+json']

# 実際に使ってみる

```ruby
require 'sinatra'
require 'rack/contrib'

use Rack::JSONBodyParser, verbs: ['POST']

get '/' do
  'Hello'
end

post '/' do
  puts params
end
```

適当にPOSTしてみます。

```bash
curl -X POST -H 'Content-Type: application/json' -d '{"greeting": "world"}' http://localhost
:4567
```

OK.

```bash
== Sinatra (v2.0.8.1) has taken the stage on 4567 for development with backup from WEBrick
[2020-07-19 18:06:29] INFO  WEBrick::HTTPServer#start: pid=4933 port=4567
{"greeting"=>"world"}
127.0.0.1 - - [19/Jul/2020:18:06:31 +0900] "POST / HTTP/1.1" 200 - 0.0095
127.0.0.1 - - [19/Jul/2020:18:06:31 JST] "POST / HTTP/1.1" 200 0
```

# 注意点

- デフォルトでは `Content-Type: application/json` でないとパースしてくれない
    - [このあたり](https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/json_body_parser.rb#L48)参照のこと
Jenkins/blueoceanをMacで実行する

#概要
Mac上でJenkinsを実行するための導入手順です。

#環境
- Mac OS Catalina バージョン10.15.6
- Open JDK
  - 14.0.2, x86_64:	"OpenJDK 14.0.2"
  - 11,     x86_64:	"OpenJDK 11"
- git version 2.24.3 (Apple Git-128)
- Docker version 19.03.8, build afacb8b
- Jenkins/blueocean on GitHub 

#インストール手順
インストールをしたもののJenkinsをblueoceanで実行する場合には、不要な気がします。OpenJDK11を導入したものの環境変数は、OpenJDK14 の状態のままです。
- OpenJDKのインストール 
    - LTS（Long Term Support）バージョンをインストール
    - 勝手な思い込みから、LTS OpenJDK14をインストールしてしまいました。後で、Jenkinsをインストールしようと調べたところ、OpenJDK version 14は現時点で未対応とのこと。Jenkinsサイトによると対応バージョンは、2020年7月18日現在、次の２バージョン。
        - OpenJDK JDK / JRE 8 - 64 bits
        - OpenJDK JDK / JRE 11 - 64 bits

[リンク]https://www.jenkins.io/doc/administration/requirements/java/
 
- Docker インストール
    - 次のサイトからDockerのインストーラーをダウンロードし、実行する。
[リンク]https://www.docker.com/get-started

    -  Dockerを起動する。
-  bluoceanをDockerHubよりプルする
    -  DockerHubのアカウントを作成し、サインインして次のサイトに行く。
    -  [リンク]https://hub.docker.com/r/jenkinsci/blueocean/
    -  画面の右にあるDocker Pull Commandのコピーを選択する。
    -  Macのターミンナルモードを起動してペーストして実行する。
-  DockerHubのblueoceanの起動手順に従いdocker runコマンドを実行する
-  ブラウザからlocalhostをアクセスして画面操作のとおりにパスワードを使ってログインする。

#終わり
実行したいことにより手順が異なるため事前の準備が必要である。
Unity 複数 いっぱい たくさん 光源 ライト 反映されない 消える 暗いまま 消失


[状況]
オブジェクトを照らすライトをたくさん置いても1つのライトしか反映されない現象に出くわした。
（UnityでOculus Quest用の開発してた）

エディタ上(シーンビューやゲームビュー)では複数のライトが反映されていたが、ビルドしてquest上で動かすとライトが1つしか反映されない。
(unityのバージョンは2018.4.0f1)

[解決策]
反映させたい光源のRender ModeをImportantにすればとりあえず解決する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540890/b3851989-555f-ef12-a0cb-7cc8b6616f89.png)

[原因]
どうやらレンダリングパスとやらがフォワードレンダリングになってて、オブジェクトにきっちり作用するライトの数が1つに制限されているらしい。（それ以外のライトは近似される）
光源のRender Modeをimportantにすることでオブジェクトにきっちり作用するライトの数を増やせる。らしい。
https://docs.unity3d.com/ja/2018.4/Manual/RenderTech-ForwardRendering.html

[おまけ]
Unity内で使える動的光源(スポットライトやポイントライト)?の最大数というのもきまってるらしく
Edit > Project Settings > Quality >RenderingのPixel Light Count
でその数を確認できる。
光源の数が多いときに反映されない場合はここもいじる必要あるかも。
（ただしあまり増やすのはよくないらしい）


最初はマテリアルの問題かな～って思ってそっちずっと調べてシェーダーとかにも手を出したのにさぁ
結局は光源の問題だったというね。
~~日曜日消えたわ！うんち！~~

この記事がお役に立ちましたらLGTMボタン押しといてください。
←左側もしくは↓このへんにあります。
Optionalを初めて使ってみて感じた、理想と現実 ~Mapを使ったキャッシュの実装編 ~

# 概要
Mapに値を保持しておいて、
既にMapに値があれば、そちらを使うように実装した時の話です。

その際、
Map#put()がputした値をそのまま返却してくれず、
理想通りに書けなかったという、つまり愚痴です :cry: 
（具体的にはソースコード参照 :pencil: ）

※もしかすると、
　スマートな解決方法はあるかもしれませんし、
　ただの勘違いかもしれません :thinking: 

## ソースコード
```java:Main.java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 理想（こう書きたい）
        String idealKey = "idealKey";
        Map<String, String> idealMap = new HashMap<String, String>();
        String idealValue = Optional.ofNullable(
	        idealMap.get(idealKey)
        ).orElseGet(
            // putはnullを返す…
            () -> idealMap.put(idealKey, "idealValue")
        );
        System.out.println("get:" + idealValue);

        // 現実（こう書くことになった）
        String realKey = "realKey";
        Map<String, String> realMap = new HashMap<String, String>();
        String realStr = Optional.ofNullable(
	        realMap.get(realKey)
        ).orElseGet(() -> {
            String value = "realValue";
	        realMap.put(realKey, value);
        	return value;
        });
        System.out.println("get:" + realStr);
    }
}
```
##実行結果
```
get:null
get:realValue
```
My用語集(this.)

###説明
this.は、クラス内で、定数を定義する際に用いる。
定義した定数は、その関数の中だけで使える。
this.の利点は、最初に定数を定義する必要が無いという点である。
this.で定義した定数を使うさいは、this.(変数名)と記述する。

>const function () {
  this.name = "###"
};
Vue.js + Flask Webアプリ フォルダ構成

# はじめに
Vue.js + Flaskで作成するWebアプリのフォルダ構成を整理します。
色々なサイトを見てみたのですが、あまり綺麗にまとまっているサイトがないなーということで、本記事を書きます。
ただ、自分で考えることは非常に不毛なので誰かいい感じの記事もしくはGitを教えてくれたらなーと思っている次第です。
さらに言えば、初心者が整理する内容なのであまり良い内容だとは思いません。


#フォルダ構成
例によって個人用まとめです。

```
izanami --- アプリケーションの名前
├ backend
│ ├ templates
│ │ └ login.html --- ログイン用のHTMLを記載、なんでここにあるかは不明
│ ├ __init__.py --- 複数のファイルが利用するものを定義(Flaskインスタンス、DB、環境変数など)
│ ├ api.py --- APIエンドポイントを書く
│ ├ config.py --- 設定情報を書いておくとこ
│ ├ models.py --- テーブル定義とそのテーブルデータのメソッドを定義
│ └ view.py --- ログイン画面のルーティングとログイン処理(init.pyが読み込む)
├ frontend
│ ├ config
│ │ └ index.js --- distフォルダの作成パス等を定義
│ ├ node_modules --- npmの便利パッケージが入っている
│ ├ src
│ │ ├ assets
│ │ │ └ logo.png --- 画像
│ │ ├ components
│ │ │ └ Home.vue --- 画面(template, script, styleを書く)
│ │ ├ router
│ │ │ └ index.js --- pathとcomponentの紐付きを書いておくとこ
│ │ ├ App.vue --- ベースとなる画面(template, script, styleを書く)
│ │ └ main.js --- Vueをnewするとこ、BootstrapVueの使用を宣言するとこ
│ └ index.html --- App.vueを呼ぶとこ
└ manage.py --- アプリ実行用スクリプト（アプリの入り口）
```

#開発するとき
画面増やしたい：componentsを追加
処理を増やしたい：api.pyもしくはview.pyのようにBlueprintで処理を増やす
テーブルを増やしたい：models.pyを編集する
undefinedとReferenceErrorって何が違うの？？

## 初めに

新卒研修でJavaScriptに触れた時、違いがよくわからなかったので、それを初Qiita記事として投稿します:muscle:

私自身もJavaScriptはまだまだ勉強中のため、
初めて触れる人がなんとなくでも理解出来ることを目的としてまとめております。
（細かい部分での違いや特徴に関しては、ひとまずおいといた解釈です）

## undefind

未定義(宣言のみで何も代入していないよ！)って教えてくれているやつ。
→ エラーというわけではない  

- undefind同士で比較することもできる
- 初期値としても利用出来る

###Q.nullとは何が違うの？？

```js
var a;
var b = null;

console.log(a);
=> undefined //aの中には何も入っていない

console.log(b); //bの中には"null"が入っている
=> null

```

null＝空っぽ。という「値」  
→bにはnullという「値」を宣言しているから、nullと出力される  
undefinedはそもそも定義がされていない状態だから、「値」が入っていない
というのを教えてくれている状態

## ReferenceError

宣言されていない変数を呼び出そうとしたときの**エラー**

## 2つの違いを表した例
```js
//hogeを宣言（代入はしない
var hoge;

//hogeにはまだ何も入っていないのでundefind
console.log(hoge); 
=> undefined

//宣言していない変数を参照しようとすると
//ReferenceErrorが発生する
console.log(fuga); 
=> Uncaught ReferenceError: fuga is not defined

//ちゃんと宣言をするとReferenceErrorは発生しなくなる
var fuga; 
console.log(fuga);
=> undefined

// fugaに何かを代入すると、undefinedを指さなくなる
fuga = "foo"; 
console.log(fuga);
=> foo
```

## 参考サイト
Mozillaのサイトにさらに詳しい例や解説があるので、さらに詳しいことを学ぶにはおすすめです！

[ReferenceError]
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)
[undefined](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/undefined)

## 最後に
私の初めてのQiitaへの投稿記事を最後まで読んでいただきましてありがとうございます:bow:

ChromeなどWebブラウザのデベロッパーツール内Consoleで、例としてあげたものを試し、結果をみてみるとさらに理解は深まると思うので是非やってみてください！

読みにくい箇所や解釈が間違っている箇所などございましたら、私自身の勉強にもなりますので、コメント等で教えていただけると幸いです。
Unity 3D入門 #3 [キャラクターの動き]

まず、unity-chanのUnityChanControlScriptWithRgidBody.csを変えます。

現在は上下キーで前進/後退で左右キーでキャラクターの回転ですが、不便なので、上下左右キーどれを押しても入力した方向に走るようにしたいです。
また、走る方向はキャラクターを軸としたものではなく、カメラを基準に上下左右とします。

```
cameraObject = GameObject.FindWithTag ("MainCamera");

// 入力デバイスから情報を受け取る
float h = Input.GetAxis ("Horizontal");				
float v = Input.GetAxis ("Vertical");	

velocity = new Vector3 (h, 0, v);	// キー入力から方向ベクトルを導出
// カメラのローカル空間での方向に変換
velocity = cameraObject.transform.TransformDirection (velocity);
velocity *= forwardSpeed;	// 移動速度を掛ける
transform.localPosition += velocity * Time.fixedDeltaTime;
```

以上のコードでキャラクターがカメラを基準に上下左右に走るようになりました。
しかし、このままではunity-chanの向きがおかしいので、走る方向を見るように設定します。

```
// キャラクターの向きを調整
this.transform.forward = velocity;
```
参考URL：https://qiita.com/broken55/items/33ac4ab55744b2e5e562

アニメーションの設定は行なっていないため、アニメーションに問題はありますが、少なくとも入力した方向にキャラクターが移動し、移動している際は移動先を向くようにできました。

追記：上記のコードをif(Mathf.Max(Mathf.Abs(v), Mathf.Abs(h)) > 0.1)でくくらないと、キャラクターの向きを変えるtransform.forwardが文句を言うかもしれません。

以下、今回の進捗GIF

![ezgif-7-a6d72f6c940c.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670403/e30d3b0d-4b67-a0f4-19e9-5620ad76efb3.gif)

見た目的な違いは前回とほとんどない
yarn で意味不明なエラーを出した話

## エラー内容

```
ryotanoMacBook:app ryota$ yarn 
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.66.dylib
  Referenced from: /usr/local/bin/node
  Reason: image not found
Abort trap: 6
```

世界初のエラー出してしまった笑

## 直し方

```
brew uninstall yarn
brew install yarn
```

これで直りました。
APIからREST-APIまで理解しよう

##APIとは
APIの正式名は「Application Programming Interface」。
API とはソフトウェアを一部公開して、他のソフトウェアと機能を共有できるようにしたもの。
ソフトウェアの一部をWEB上に公開し、誰でも利用することができる。
これを外部APIといい、特定のアプリだけに対応したものは内部APIという。

自分のソフトウェアに他のソフトウェアの機能を埋め込むことができるようになるので、
アプリケーション同士で連携することが可能になる。

API利用例：
・アプリ自身では地図情報を持たずGoogle mapマップを表示をしたい
　⇒Google mapのAPI から情報を取得する。

・他のアプリからのログインを可能にしたい
　⇒TwitterのAPI から情報を取得する。

##WebAPIとは
HTTP／HTTPSベースで送受信することで利用できるAPIをWebAPIという。

##ウェブとWebAPIの違い
両方ともhttpでリクエストを送受信するが、
通常のウェブはページごとレスポンスを行い、
WebAPIはデータだけをレスポンスする。

データはJSON やXML といった形式が一般的に使われる。
（XMLは最近見ない。JSONに比べ記述する項目が多く、推奨されない。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/2ad3f071-4dd0-a14f-0df8-cd9bd1306fe4.png)

##REST APIとは
Web APIの代表的な実装方式として、RESTとSOAPがある。
SOAP方式はXMLを使用したものでここでは割愛。
今ではWeb API＝RESTと思ってもいい。
REST方式で実装したWeb APIをREST APIという。
RESTful APIも同じ意味で使われる。

###特徴４つ
１、HTTPのメソッド（命令）でデータ操作種別（CRUD）を表す
　　POSTメソッドであれば作成（Create）、
　　GETメソッドであれば参照（Reference）、
　　PUT／PATCHメソッドであれば更新（Update）、
　　DELETEメソッドであれば削除（Delete）を表す

　　何をしようとしているか一目瞭然！

２、URIで操作対象のリソースを判別可能にする
　　RESTでは、APIを介して操作する対象を「リソース」と呼ぶ。
　　例えば「ユーザー」というリソースを表すために「users」というリソース名を付与する。
　　ユーザーIDが「1000」のユーザー情報を取得したい場合、
　　下記のようなURIフォーマットでURIを生成し、操作可能とする
　　URIフォーマット：https://example.com/users/:user_id
　　生成されたURI：https//example.com/users/1000

　　どこのデータに対して処理を行おうとしているか一目瞭然！

３、セッションなどの状態管理を行わない。
　　(やり取りされる情報はそれ自体で完結している)
　　作業の状態情報を別途保存して管理することはしません。
　　
　　APIサーバーは受信したリクエストだけを単純に処理すればいい。
　　これによってサービスの自由度が高くなり、実装も簡単になる。

　　ステートレスにすることで、スケーラビリティが向上！
　　
　　つまり、言い換えると、
　　セッション情報やCookie情報を保存して管理していないため、
　　アクセスの集中に耐えやすい構造にできる！

４、情報の内部に、別の情報や(その情報の別の)状態へのリンクを含めることができる。

##omake：twitterのAPIを叩いて自身のユーザー情報をjsonで受け取ってみよう。
[GET users/show - ユーザーを取得する：サイト](https://syncer.jp/Web/API/Twitter/REST_API/GET/users/show/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/9078ffb1-9e79-eebd-e059-0876c940224f.png)

取得するユーザーID「realDonaldTrump」

目次からデモを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/b7ce32d7-8316-cf12-80a5-c4e95c517e00.png)
デモでuser_idを省略し、screen_nameにIDを入力。
リクエストを実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/19133b2c-7f38-0fff-2239-43f456df2f33.png)
jsonデータが取得出来ました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384409/c39ada0c-f60f-cf50-988a-478b59a56b87.png)


##参考記事
API とは？
https://qiita.com/jonathanh/items/6394ffb5b5ad86ae914f
APIとは何か？　Web APIとの違い、利用者のタスクを解説
https://techtarget.itmedia.co.jp/tt/news/1806/13/news01.html
create_listを使用してRSpecでFactoryBotから複数のインスタンスをまとめて作成する

---
RSpecテストを書いているときに、複数のインスタンスをまとめて作れる便利メソッド`create_list`の書き留め。

---

例えば下記のように`note`のファクトリが定義されているとする。

```factory/notes.rb
FactoryBot.define do
  factory :note do
    title { 'sample-note' }
    description { 'sample-description' }
  end
end
```

テストで`note`インスタンスを5つ作りたいと思ったとき、下記のように1つずつ作るのは面倒。

```spec/system/xxx_spec.rb
RSpec.describe 'yyyy' do
  let(:note1) { create(:note) }
  let(:note2) { create(:note) }
  let(:note3) { create(:note) }
  let(:note4) { create(:note) }
  let(:note5) { create(:note) }
  ...
end
```

ここで`create_list`を使えば、まとめてnoteインスタンスを作成することが可能。

```spec/system/xxx_spec.rb
RSpec.describe 'yyyy' do
  notes = create_list(:note, 5)
  ...
end
```

第1引数に元になるファクトリ、第2引数に作成する数を指定。
（`notes = `の部分は無くても可）

ちなみに属性の一部を上書きして作成することも可能。

```spec/system/xxx_spec.rb
RSpec.describe 'yyyy' do
  notes = create_list(:note, 5, title: 'Hello, World')
  ...
end
```

---

以上。
Package signatures do not match the previously installed version

Package signatures do not match the previously installed version
Oculus Questの開発中にこのエラーに出くわしたので，詳しい状況と解決した方法を書き残しておく．


[状況]

普段はメインPCでQuest用アプリのビルドを行っていたが，ある日サブPCで同じバージョンのUnityでビルドを行ったらこのエラーが出た

[解決策]

署名が違うよ！って怒られてるので，いったんアプリを消して，再度ビルド．

まずコマンドプロンプトを起動
C\user\[yourname]\appdata\local\android\adk\parameter_tool\の中に入る

adb uninstall "com.xxxx.xxxx"
でアプリを消す

次にこれを実行
adb.exe "1PATHxxxxx" -s -o "/*apkのパス*/"
成功するとsuccessとかsuccessfullyとかでた気がする

これでunityのビルドしたらうまく通りました
ログイン画面作成（備忘録）　section72(続)

現在は、check.phpにindex.phpで入力した値が入っていない

渡す方法は「session」と「cookie」の２パターンあるが
今回は「session」の方法で渡すのがベスト

cookieを使ってindex.phpの入力値をブラウザにずっと保存しておく必要性はなく、
個人情報なので危険なためです。

POSTで渡す方法もありますが、今回はcheck.phpで書き直す機能も使うので、
index.phpとcheck.phpの間で情報の行き交いあるため、
POSTでいちいち渡すのは非効率になる。

簡易登録などの一時的なやりとりは「session」が最適になる。
よって、入力画面で入力したデータをsessionで保存してみる。

※セッションとは：WEBアプリにおいて、各ユーザー固有のデータを格納するための仕組み
ユーザー毎に異なるログイン情報やカートなどの機能実現のためにセッションを使用する。

---------------------------------------------------------------------

スクリプト先頭にsession_start()ファンクションを記述してセッションを開始する。

セッションに値を保存するというのは header()の直前、エラーが起こっていないことが
確認出来たら、セッションに値を入力していく。

	if(empty($error)) {
		$_SESSION['join'] === $_POST;
		header('Location: check.php');
		exit();
	}
　
`$_SESSION['']`のjoinというキーに$_POSTの値を保存する。

これでcheck.phpの方でもsessionの値が参照できる。

---------------------------------------------------------------------

次にcheck.phpのコード記述をしていく
スクリプト先頭にsession_start()ファンクションを記述してセッションを開始する。

```
if(!isset($_SESSION['join'])){
	header('Location: index.php');
    exti();
}
```
`$_SESSION['join'])`の値を検査する。
`$_SESSION['join'])`の値が入っていなければ（!isset）、index.phpファイルに画面を戻す。

---------------------------------------------------------------------
次にindex.phpで'$_SESSION['join'])'に格納されている
ニックネーム、メールアドレス、パスワード情報をそれぞれcheck.phpで取り出して、表示する。

```
<dt>ニックネーム</dt>
　<dd>
　　<?php print(htmlspecialchars($_SESSION['join']['name'],ENT_QUOTES));?>
<　/dd>
```
htmlspecialchars()は安全に画面表示させるための記述

'$_SESSION['join'])'というのは２次元配列（配列が２段回になった状態）になっている。
理由はindex.phpの方で、'$_SESSION['join'])'という配列に$_POSTをセットしているから。
$_POSTは元々配列なので取り出す記述として、'['join']['name']'といったjoin配列の中のnameを取り出すという
記述方法になる。
GitHub ActionsでfromJsonを使おうとしたらset-outputでハマった話

`GitHub Actions`でPRが動いたらExpoをpublishしてそのQRコードをPRのコメントに貼るCIを作成した時に`app.json`のslugの値を取得する際にハマったお話。

## やろうとしていたこと
`app.json`の中身を別のstepでも参照できるようにして、その値を`fromJson`でjsonのように扱ってslugの値を抜き出そうとしていた。

```yaml

#.github/workflows/expo.yaml
      ...
      - name: Get app json
        id: app-json
        run: echo "::set-output name=appJson::$(cat ./app.json)"
      ...
        ${{ fromJson(steps.app-json.outputs.appJson).expo.slug }}
      ...
```

そのCIを動かしてみると、`Error reading JObject from JsonReader.`というエラーが発生した。

## 原因
この原因は`set-output`に複数行の文字列をセットできないことだった。

## 対策
`set-output`でjsonをセットする際に改行を削除するようにした。

```
echo "::set-output name=appJson::$(cat ./app.json | tr -d '\n')"
```

## 参考文献
* [Read JSON file in Github Actions](https://stackoverflow.com/questions/61919141/read-json-file-in-github-actions)
*
* [set-output Truncates Multiline Strings](https://github.community/t/set-output-truncates-multiline-strings/16852)
Thymeleafでインクリメント・デクリメント

Thymeleafでインクリメント・デクリメントする方法です。


## コード

### インクリメント

インクリメントする場合は、`#numbers.sequence`を利用します。

```increment.html
<select id="increment" name="increment">
    <option th:each="i : ${#numbers.sequence(1, 10)}" th:value="${i}"th:text="${i}"></option>
</select>
```

### デクリメント

デクリメントする場合は、`#numbers.sequence`の第３引数に`-1`を指定します。

```decrement.html
<select id="decrement" name="decrement">
    <option th:each="i : ${#numbers.sequence(10, 1, -1)}" th:value="${i}"th:text="${i}"></option>
</select>
```

### 指定した数値で増加させる

指定した数値で増加させるインクリメントする場合は、`#numbers.sequence`の第３引数に増加させたい数値を指定します。
例えば2つずつ増加させる場合は以下になります。

```two_increment.html
<select id="two_increment" name="two_increment">
    <option th:each="i : ${#numbers.sequence(1, 10, 2)}" th:value="${i}"th:text="${i}"></option>
</select>
```

## 参考
[Thymeleaf 日本語ドキュメント](https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html)
[超初心者向け]MacのTerminalでGoogleドライブのディレクトリに移動できない原因

####MacのTerminalでGoogleドライブのディレクトリに移動できない場合、フォルダ名を””で囲んでコマンドを打ちましょう。

#####【誤】
$ cd Google ドライブ
　↓　こんなエラーが出ます。
-bash: cd: Google: No such file or directory

#####【正】
$ cd "Google ドライブ"
　↓　ちゃんと移動できます。
〜〜:Google ドライブ 〜〜〜

#####間にスペースが入っているとその部分でディレクトリ名が終了していると認識されるようです。
あまりに初歩的過ぎて、ほとんどどこにも書いていないようでしたので・・。
macでaws cliを設定する

#ハマったこと
サイトを参考に以下のコマンドでダウンロードした。
https://tomomano.gitlab.io/intro-aws/#aws_cli_install

 ```
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
```

エラーが出た。
Linux系じゃないからエラーが出たのか？

```
zsh: exec format error: aws
```

#対処
python経由でaws cliをインストールしたらうまくいった。

```
pip install awscli
```

#感想
環境構築まわりが一番むずかしい。。
tensorflow v1 のhelloworld

tensorflow1のバージョンは2.2.0   

v1の場合

```
import tensorflow as tf
tf1 = tf.compat.v1
g = tf1.Graph()
with g.as_default():
  msg = tf1.constant('Hello World')
  sess = tf1.Session()
  print(sess.run(msg))
```

v2の場合

```
import tensorflow as tf
g = tf.Graph()
with g.as_default():
  msg = tf.constant('Hello World')
  print(eval(msg))
```
Alpine Linuxでライブラリをインストール


### 動機
alpine系のDockerコンテナの中身がどうなっているのか検証したかったが、その検証をするためのライブラリが不十分だったため。（当たり前だが）

### 手順
Docker コンテナを作成して、以下のコマンドでコンテナのshを起動

```
docker exec -it <container ID> /bin/sh
```

shを起動したら、apkをアップデート。apkがAlpine Linux でのパッケージマネージャとなる。

```
apk update
```

あとは必要なパッケージをaddオプションでインストール。（以下の例はbind-toolsをインストール）

```
apk add --no-cache bind-tools
```
(--no-cacheは指定しなくてもいい。その場合は事前に`apk update`必須。)


パッケージの検索はsearchオプションで。

```
apk search bind-tools
```
【React】カウントアップ機能を実装してみた

今回はReactを利用して下図のようなカウントアップ機能を実装していきます。
React初学者の方は、このような簡単な実装でコツを掴んでいくと良いと思います。

###完成図
<a href="https://gyazo.com/9fef1815f636e49c861498728372b3a4"><img src="https://i.gyazo.com/9fef1815f636e49c861498728372b3a4.gif" alt="Image from Gyazo" width="346"/></a>

#0.雛形

完成コードです。
要所で詳細に説明していきます。

```App.js
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {count: 0};
  }

  hendleClick() {
    setState({count: this.state.count + 1});
  }

  render() {
    return(
      <div>
        <p>{this.state.count}</p>
        <button onClick={()=>{this.handleClick()}}>+</button>
      </div>
    );
  }
}
```

#1.stateを定義

stateを使って初期値の設定をしていきます。

```App.js
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props)
    // this.stateでcountプロパティの初期値を0に設定します
    this.state = {count: 0};
  }
}
```

#2.メソッドを定義

setStateを使って、countの値を変更するhandleClickメソッドを作ります。

```App.js
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {count: 0};
  }

  hendleClick() {
    // 「this.state.count + 1」 とすることでstateのcountの値に1を足すメソッドを定義する
    setState({count: this.state.count + 1});
  }
}
```

#3.イベントの呼び出し

クリックイベントでhandleClickメソッドを呼び出し、ボタンをクリックする度にカウントの表示を変更してみましょう。

```App.js
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {count: 0};
  }

  hendleClick() {
    this.setState({count: this.state.count + 1});
  }

  render() {
    return(
      <div>
        // stateを表示
        <p>{this.state.count}</p>
        // クリックイベントでhandleClickメソッドを呼び出す
        <button onClick={()=>{this.handleClick()}}>+</button>
      </div>
    );
  }
}
```

#補足(setStateについて)

setStateが実行されるタイミングはReactが勝手に決めるので、
下図のように書いてしまうと、count の値がほかの処理で書き換わってしまって、うまくカウントアップできない場合もあります。

```App.js
  hendleClick() {
    this.setState({count: this.state.count + 1});
  }
```

そこで setState では state の変更前の値を取得できるようになっていて、
その場合は prevState で…、アロー関数式で下図ように書いてあげれば、 prevState に直前の値が入ってくるので、その値を使って書き換えてあげれば OK です。

```App.js
  hendleClick() {
    this.setState(prevState => {
      return(
        //  count というキーの値を prevState.count + 1 としてあげればカウントされます
        count: prevState + 1
      );
    });
  }
```

以上
Windowsで動かすElixir on Phoenix

正直全然わかってないけどとりあえず環境構築してみたのでメモ

# Elixirのインストール
公式サイトからElixirをダウンロードする。
https://elixir-lang.jp/install.html#windows
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272827/5e451750-5217-64e5-3fa0-14d67ea32334.png)
ダウンロードしたexeファイルを実行する。
自分の環境にあわせて設定していくとインストールされる。

インストールが完了したらコマンドプロンプトに
```elixir --version
```と入力してバージョンが表示されたらインストール完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272827/5998c23d-7ffd-cc62-fb0c-3ce5163714a1.png)
Elixirをインストールすると勝手にmixもインストールされる。
mixは開発に使うパッケージとかをインストールしたりプロジェクト作るときとかに使うみたい
mix
```mix -v
```と入力するとmixのバージョンが表示されるはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272827/4ea70b8d-4d30-efca-90bd-b10b25494299.png)

Elixirの構築はここまで、お疲れさまでした。

# Phoenixのインストール
上記インストールしたmixでPhoenixをインストールしてくる。
```mix archive.install hex phx_new 1.4.0```
インストールの途中でなんか聞かれたらとりあえずyesにしとく

*createing ~~ってなったらインストール成功

# プロジェクトをつくってみる
```mix phx.new hello_world```
これもなんか聞かれたらyesにする

プロジェクトが作り終わったら
```cd hello_world```
でプロジェクトのディレクトリに進む
```iex -S mix phx.server```
でローカルサーバーとプロジェクトが起動する

http://localhost:4000/に接続して以下の画面が表示されていれば成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272827/f38d9f8a-6950-5a15-bf83-9734b5904981.png)

ローカルサーバーを止めたいときはctrl + cを二度押すと止まる。
Rails ajaxで検索一致したキーワードの取得、表示まで

# はじめに
Railsで特定のデータベースの一覧を取得から表示までの実装を行なったので、忘れないようにメモしておきたい。

jqueryは少し触れた程度だったので書き方やajax通信についての勉強になった。

サンプルとしてUserテーブルを準備

| カラム名 | データ型 |
|:--|:--|
| id | integer |
| name | string |
| created_at | datetime |
| updated_at | datetime |

```
{:id=>1, :name=>"山田"}
{:id=>2, :name=>"太郎"}
```

一覧表示する箇所

```ruby

 <%= f.text_field :name, class: 'form user-match', required: true %> 
 <p class="search-attention"></p>
```

#API作成
```ruby

def index
    keyword = params[:keyword]
    @users = User.where(['name = ?', keyword])
                     .page(params[:page] || 1).per(50)
                     .order(:id)
    render json: @user
  end
```
ここでは完全一致したものを取得するようにしている。
ルーティングでパスを指定する。
params[:keyword]に太郎という値を渡すと次のようなものが返ってくる。

```
{:id=>2, :name=>"太郎"}
``` 

山田の場合だと

```
{:id=>1, :name=>"山田"}
``` 

#ajaxの実装
`user_match.js.erb`を作成。

```ruby

api_match = function (selector, path) {
  $(selector).change(function() {
    const user_name = $(this).val();
    $.ajax({
      url: `指定したurl` + path,
      dataType: "json",      #サーバから返されるデータの型を指定
      data: {keyword: user_name}
    })
    .done(function (data) {  #値が帰ってきたとき
      $(selector).next(".search-attention").empty(); #他のclass(search-attention)と被らないように
      if ($.trim(data)){ 　#dataが空じゃない時
        $(selector).next(".search-attention").append("<p>" + data[0].name + "</p>");
      };
    });
  });
};
```

```ruby
$(window).on("load", function () {　# classにevent付与
  api_match(".user-match", 指定したpath)
});
```
ここで一つはまってしまったのが`change`メソッドを用いているがfunctionを書くことを忘れておりエラーが出ていたので気をつけたい。

これでtext_fieldに検索したいキーワードを入力をすると非同期通信での取得、表示がされる。
太陽光発電の遠隔監視システムを簡単につくってみた

太陽光発電の監視システムを簡単に作ってみたお話をまとめてみました。

Google スプレッドシートにセンサーで取得したバッテリーの電圧や電流を送って可視化するものを作っていきます。

![chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97208/5ec030ac-3372-e006-f44b-c324b9b79b93.png)

定期的に電圧が上がって充電できているのが確認できます！

充電しているときは電流がマイナス側に流れて、放電するときには電流がプラス側に流れます。

# 必要な部材

- 太陽光パネルとコントローラー（[Amazon](https://www.amazon.co.jp/dp/B075W67Q8C/ref=cm_sw_r_tw_dp_x_Ma8eFb6VZMMYX)）
- バッテリー（[Amazon](https://www.amazon.co.jp/dp/B01KO9LQJA/ref=cm_sw_r_tw_dp_x_7.7eFb59S42SR)）
- obniz（[Amazon](https://www.amazon.com/gp/product/B07DD6FK8G/ref=ox_sc_act_title_1?smid=A215VXJW7Q8EUM)）
- 電圧、電流計測モジュール（絶縁タイプじゃないと配線違う）（[ストロベリーリナックス](https://strawberry-linux.com/catalog/items?code=11226)）


# 回路

![obniz.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97208/c21bdd0b-9e46-fa33-fa63-b3b00991ef58.jpeg)


バッテリを制御する端子の+側に電圧、電流計測するためのセンサーを取り付けます。

センサーをobnizにつなげば準備は完了です！

# プログラム

全文は下記のgistにあげてありますので簡単に説明します。

下記の関数によって、センサーから電流値と電圧値がそれぞれ取得できます。

```jsx
let v = Math.round(await getData(INA226PRC_BUSV_REG)* 0.0125) / 10;
let ma = await getData(INA226PRC_SHUNTV_REG) *1.25;

async function getData(command){
    obniz.i2c0.write(0x40, [command]);
    let ret = await obniz.i2c0.readWait(0x40, 2);
    let data =new DataView(new ArrayBuffer(2));
    data.setUint16(0,(ret[0]<<8)|ret[1]);
    return data.getInt16(0);
}
```

下記のコードによってIFTTTに送信するようにしています。

IFTTTの設定項目として、``IFTTT_EVENT``と``IFTTT_KEY``がありますが、下記の記事を参考に設定してください。IFTTTからスプレッドシートに記載する方法も載っていますので、こちらの設定に沿っていただければと思います。

[https://blog.obniz.io/make/obniz-board-1y-temperature-logger/](https://blog.obniz.io/make/obniz-board-1y-temperature-logger/)

```jsx
//送信データ作成
var formData = new FormData();
formData.append("value1", v);
formData.append("value2", ma);
//IFTTTリクエスト
await fetch(
  `https://maker.ifttt.com/trigger/IFTTT_EVENT/with/key/IFTTT_KEY`,
  {
    method: "POST",
    mode: "no-cors",
    body: formData
  }
);
```

あと上記の記事を参考にobnizのサーバレスイベントを設定すればサーバを用意することなくobnizとセンサーとIFTTTを設定するだけで定期的にポコポコとセンシングしたデータをあげてくれます。めちゃくちゃ便利なので活用しましょう！

## コード全体

https://gist.github.com/wamisnet/b6d4861f7879394e8cb52dc80514fc62

# まとめ

obnizを活用することで簡単にセンシングして、その結果をスプレッドシートにまとめられます。

ほしいと思っていたデータを活用して、今後にぜひ活用してみませんか！？
Redis Sentinel構成のQuorumを理解する

# 概要
sentinel.confに書く

```sentinel.conf
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
```
の最後に付いてる2の話です。

# 結論
Sentinel構成台数は奇数にして、quorumには台数/2（切り捨て）+1を設定する。

※quorumを低くしたり、高くしたりすると、フェイルオーバーしにくくなったり、しやすくなったりするので、そのような挙動が良い場合は、下の方（[最低稼働台数≠quorumの場合はどうなる？](#%E6%9C%80%E4%BD%8E%E7%A8%BC%E5%83%8D%E5%8F%B0%E6%95%B0quorum%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AF%E3%81%A9%E3%81%86%E3%81%AA%E3%82%8B)）参照。

# なぜSentinel構成台数は奇数にするのか？

Sentinel構成台数と、最低稼働台数の関係は、下表のようになります。

| Sentinel構成台数 | 最低稼働台数 | ダウン許容台数 |
|:-:|:-:|:-:|
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 6 | 3 | 2 |
| 7 | 4 | 3 |

3台→4台、5台→6台に増やしても、ダウン許容台数が増えないので、コスパが悪いというのが理由になります。
そしてquorumには、最低稼働台数と同じ値を設定します。

# Sentinelのフェイルオーバーの判断
ドキュメントに記載されています。
（参考）
[Redis Sentinel Documentation – Redis](https://redis.io/topics/sentinel)
※パーマリンクないので補足すると、かなり下の方です。

> The previous sections showed that every master monitored by Sentinel is associated to a configured quorum. It specifies the number of Sentinel processes that need to agree about the unreachability or error condition of the master in order to trigger a failover.

> However, after the failover is triggered, in order for the failover to actually be performed, at least a majority of Sentinels must authorize the Sentinel to failover. Sentinel never performs a failover in the partition where a minority of Sentinels exist.

意訳すると、下記2つを満たすことが条件です。

1. フェイルオーバーのトリガー
    - quorum数のSentinelプロセスが、マスターの到達不能またはエラー状態について合意する
2. フェイルオーバーの実行
    - 大多数のSentinelプロセスが、フェイルオーバーを許可する

大多数ってのがあいまいなんですが、等しいのはダメなので、3台なら2台（2>1）、4台なら3台（3>1）5台なら3台（3>2）、つまり、元の台数/2（切り捨て）+1が大多数に該当します。

# 最低稼働台数≠quorumの場合はどうなる？
これもドキュメントの同じところに記載されています。

（参考）
[Redis Sentinel Documentation – Redis](https://redis.io/topics/sentinel)
> 1. If a the quorum is set to a value smaller than the majority of Sentinels we deploy, we are basically making Sentinel more sensitive to master failures, triggering a failover as soon as even just a minority of Sentinels is no longer able to talk with the master.
> 2. If a quorum is set to a value greater than the majority of Sentinels, we are making Sentinel able to failover only when there are a very large number (larger than majority) of well connected Sentinels which agree about the master being down.

つまり、

- quorum < 最低稼働台数の場合、フェイルオーバーしやすくなる
- quorum > 最低稼働台数の場合、フェイルオーバーしにくくなる

ということですね。

## 実験
5台構成のRedis Sentinel構成を組んで、quorum=3のときと、quorum=4のときを比べてみました。

### 手順
1. master1台+replica4台のRedis Sentinel構成を構築する
2. masterのサーバを停止する
    3. replicaのどれかにフェイルオーバーする
3. フェイルオーバーしたmasterのサーバをさらに停止する
    4. 残ったreplicaのどれかにフェイルオーバーする（はず）

### 結果
#### quorum=3の場合
手順2、手順3いずれもフェイルオーバーした（想定通り）

#### quorum=4の場合
手順2ではフェイルオーバーしたが、手順3ではフェイルオーバーしなかった。
フェイルオーバーのトリガーのためのSentinelプロセス数を満たさなかったためと思われる。（replica -> masterへのコネクションフェイルが延々と出続けた）

Sentinel構成を組んで、フェイルオーバーしたくないっていうのは、どういうケースか分からないので（kubernetesとかですぐ復活する場合？）、通常は、quorum=最低稼働台数とすると良いと思います。
Rails6でmigrate時に自動でER図を生成する方法

## はじめに
Rails6でER図を自動生成する方法をまとめました。
Rails6の場合、ファイルのオートロードにZeitwerkをデフォルト使用しているのですが、これの影響でうまくER図を生成できなかったので対処法も記載しました。

## 開発環境
Rails: 6.0.3
Ruby:2.7.1
Macbook Pro
Graphviz
GraphQL(これで自動生成されたファイルが原因だった。)

## ER図の設定
Gemをインストールします。

```rb:Gemfile
group :development do
  gem 'rails-erd'
end
```

必要に応じてgitignoreに設定する。

```:.gitignore
*.dot
```

下記のコマンドでER図の生することができます。

```
$ bundle exec erd --filetype=dot
```

dot形式からpng形式の変更は下記のコマンドでできます。

```
$ dot -Tpng erd.dot -o erd.png` (erd.dotはファイル名)
```

## 自動生成の設定
migrate時にER図を自動生成するにはRakefileで設定を行います。
もし自動生成が必要でなければ、ここの記載は必要ありません。

```rb:Rakefile
# migrateのタスクをフックする
Rake::Task['db:migrate'].enhance do
  if Rails.env.development?
    Rake::Task[:after_migrate].invoke
  end
end

# migrateの後のタスク
task after_migrate: :environment do
  Rake::Task[:create_erd].invoke
end

# ER図を作成
task create_erd: :environment do
  # attributes=foreign_keys,primary_keys,timestamps (属性は主キー、外部キー、タイムスタンプを表示)
  # sort=false (カラム名をアルファベット順にしない)
  # filename=hogehoge-erd (ファイル名)
  # filetype=dot (ファイル拡張子)
  sh 'bundle exec erd --attributes=foreign_keys,primary_keys,content,timestamps --sort=false --filename=hogehoge --filetype=dot'
end
```

## エラー対策
### おすすめしない対策
ファイルのオートロードを行う、zeitwerkの使用をやめてclassicに変更したら、一応自動生成はできたがRspecが通らなくなった。

```:config/application.rb
config.autoloader = :classic
```

[zeitwerkの uninitialized constant XXX (NameError)エラーについて](https://qiita.com/NariFrow/items/7c0b944cb0bbe7fa788e)
[Railsガイド 2 Zeitwerkモードを有効にする](https://railsguides.jp/autoloading_and_reloading_constants.html#zeitwerk%E3%83%A2%E3%83%BC%E3%83%89%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B)
[Railsガイド 11 Zeitwerkを使わない場合](https://railsguides.jp/autoloading_and_reloading_constants.html#zeitwerk%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88)

### 実施した対策
ER図を生成すると下記のエラーが出た。

```:ターミナル 
$ bundle exec erd
Failed: Zeitwerk::NameError: expected file /app/graphql/interface_types/base_interface.rb to define constant Types::BaseInterface, but didn't
```

どうやらmoduleの定義方法が適切ではないようである。
[Zeitwerkの壊し方](https://qiita.com/fursich/items/717a720d9f4465e4cbbb)

GraphQLで自動生成されたファイルが原因だったので下記のように変更した。

```base_interface.rb
module Types
  module BaseInterface
    include GraphQL::Schema::Interface
    field_class Types::BaseField 
  end 
end

```

対策後↓

```base_interface.rb
module Types::BaseInterface
  include GraphQL::Schema::Interface
  field_class Types::BaseField
end
```

そのほかのファイルも変更する。

```base_scalar.rb
module Types
  class BaseScalar < GraphQL::Schema::Scalar
  end
end
```

対策後↓

```base_scalar.rb
class Types::BaseScalar < GraphQL::Schema::Scalar
end
```

再度ER図を生成すると今度は下記のエラーが出た。

```:ターミナル 
$ bundle exec erd
Failed: RuntimeError: Saving diagram failed!
Verify that Graphviz is installed and in your path, or use filetype=dot.
```

fileをdotに指定する必要があるとのこと。

```:ターミナル(ファイルを指定)
$ bundle exec erd --filetype=dot
```

これで無事にER図を生成できました！

## 終わりに
Rails6 × GraphQLを使用したため、オーロロードが正しくできず、発生したエラーだった。
【Windows10版】Virtualbox × Vagrant WinSCPクライアントでFTP接続してみた。

##【開発環境】
Windows 10 HOME
VirtualBox 6.0
Vagrant 2.2.9

WinSCP 5.17

##【はじめに】
FFFTPでVagrantの仮想環境にアクセルしてみたら出来なかったので
(多分秘密鍵の設定箇所が無いから？)
それ以外にFTP接続出来るクライアントツールを探していたら、
<a href="https://winscp.net/eng/docs/lang:jp" target="_blank" >WinSCP</a>というものがあるらしいので使ってみた。

##【前提条件】
VagrantとVirtualBox をインストールして、
vagrant up で仮想環境を起動している状態。
WinSCPをインストール済。

##【vagrant ssh-configで接続情報】

PowerShellにて
SSHで仮想環境に接続するための情報を確認します。

```PowerShell:PowerShell
PS C:\path_to_dir\any_name> vagrant ssh-config
```
上記のコマンドを打つと下記の情報が表示されます。

```PowerShell:PowerShell
PS C:\path_to_dir\any_name> vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile C:/path_to_dir/any_name/.vagrant/machines/default/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL
```

##【WinSCPを起動】



![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669259/3550fbb5-0938-1970-0a00-c37662daf783.jpeg)

WinSCPを起動して
赤枠部分に「vagrant ssh-config」で出した情報を入れていきます。
そんで「設定ボタン」押下。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669259/d33b2a39-c03c-6316-1779-05b011248d02.jpeg)

**` 秘密鍵 `**には、vagrant ssh-configで出力した情報の
**` IdentityFile `**のパスを入れます。

「公開鍵を表示」ボタン　→　「OK」ボタン。


![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669259/3a23cffa-dec6-5d75-5450-fda87fc1ff68.jpeg)


新たにppkファイルが出来ている事を確認して「保存」ボタン。

![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669259/73374d55-4a0a-0c2f-63a2-67bc559db1ec.jpeg)

「OK」ボタン押下し、接続してみると、、。

![6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669259/364be94f-193a-2ede-da09-c7cdd7de64a7.jpeg)


接続完了しました。
ちゃんと　/home/vagrant/　配下にアクセス出来ています。

##【余談】

CyberduckというFTPクライアントも接続まで行ったのですが、
これまでのクライアントと違ってリモート側のみしか表示されなかったので
ちと使いづらいかなという感じです。
WireShark でパケットをキャプチャする

# はじめに
* ネットワークエンジニアの方が利用される機会が多いと思いますが、パケットキャプチャ用のオープンソースツール「WireShark」について簡単に紹介します。

# パケットキャプチャとは
* ネットワーク上の障害の原因を特定するために、ネットワーク上を流れるパケットをキャプチャして確認することです。

# WireSharkとは
* パケットキャプチャの方法の一つに、「[WireShark](https://www.wireshark.org/)」の利用が挙げられます。
* Windows, Linux, Mac OSなど、多様なプラットフォームに対応しています。

# WireSharkの使い方
今回は、Windows 環境で「ICMP」をパケットキャプチャした場合の例を挙げます。

## インストール
1. [ダウンロードページ](https://www.wireshark.org/) からインストーラ（今回は3.2.5）を取得します。
2. インストーラを実行します。
   * 基本はデフォルトのチェックのまま、進めていけば良いと思います。
   * 「Npcap」のインストール確認について、[公式ドキュメント](https://www.wireshark.org/docs/wsug_html/#ChBuildInstallWinInstall) よりパケットのキャプチャで必要ですのでインストールします。
　　　![Npcap.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/7842cdfc-c75d-39df-3fcc-a6261e1ffc45.gif)
   * USB に対する通信もキャプチャする「USBPcap」のインストール確認について、私見では利用予定がなければインストールはスキップして問題ないです。
　　　![USBPcap.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/4feaee9a-dcec-953a-af9e-34cf3d718f50.gif)

## パケットキャプチャ
### ネットワークインターフェース の選択
* 対象のネットワークインターフェースを右クリックし「キャプチャ開始」をクリックします。
    ![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/4cf9dadd-a9ca-0b91-ac61-370842b612af.jpeg)

### フィルタを利用したパケットキャプチャ
* WireShark では、プロトコルタイプ、ポート番号などを条件にキャプチャしたパケットをフィルタリングする機能があります。詳細な例は、以下の [ページ](https://wiki.wireshark.org/DisplayFilters) にも紹介されています。今回は例として「ICMP」のプロトコルをフィルタリングします。

1. フィルタに「icmp」を入力し適用します。
　![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/80e00d1b-44b8-d3d2-8643-ffc8bc817e1a.jpeg)
2. 宛先ホストへ「ping」を実行します。以下は実行例です。
  ![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/ccf2f721-b0e7-9c52-cb7d-aef3380da1af.jpeg)
3. 対比として、宛先ホストが起動していない場合に「ping」を実行した場合は以下のようになります。
  ![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/07c4e818-06f4-da8a-9796-e6589b8856a1.jpeg)
4. パケットキャプチャは、「ファイル」メニューの下の赤枠のボタンで停止でき、左隣の青枠のボタンで再開できます。
　![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672573/3b01894f-e008-c862-f7d1-87f60cadcd1b.jpeg)
5. また、「ファイル」メニューの「保存」で、拡張子が「.pcapng」のファイルにパケットキャプチャを保存できます。一旦、採取記録をバックアップし、後にWireSharkで再確認したい際に利用できます。


# 補足: netshの実行結果をWireSharkで読み込む場合
* Windows 環境では、標準の「netsh」コマンドでパケットキャプチャを採取し、拡張子が「.etl」のファイルに保存できます。

```
C:\tmp>netsh trace start capture=yes
...
C:\tmp>netsh trace stop
```
* ただ、WireSharkでは「.etl」ファイルには対応していませんので、現在は Microsoft 社が提供している「[etl2pcapng](https://github.com/microsoft/etl2pcapng)」で「.pcapng」ファイルに変換する必要があります。

# おわりに
* 「WireShark」は比較的簡単に導入できますので、プライベートで特定プロトコルの仕組みを学習する際にも役立つように思います。

# 参考資料
* [WireShark](https://www.wireshark.org/)
* [Wireshark Wiki](https://wiki.wireshark.org/FrontPage)
* [DisplayFilters](https://wiki.wireshark.org/DisplayFilters)
ラズパイとArduino（BluePill）をUARTで接続（GPIO）してJSONでやりとりする

#自分メモ


```cpp:Arduino側

#include <ArduinoJson.h>
String rs;

void setup() {
  Serial1.begin(115200);
}

void loop() {
  if (rs = receiveUart())
  {
    // 数字はJSONで確保するサイズ。あまり大きいとメモリを食うので注意
    StaticJsonDocument<1000> doc;

    // 変数 rs に配列に変換したJSONデータを代入
    DeserializationError err = deserializeJson(doc, rs);
    if (err == DeserializationError::Ok) 
    {
      // UART取得OK、msgデータを取得
      String message = doc["msg"].as<String>();

      // messageをなんやかんやする処理
      // 省略


      // 配列を追加する
      doc["result"] = true;
      String ws;
      // 配列をJSON形式に変換
      serializeJson(doc, ws);
      // JSONデータを送信
      Serial1.println(ws);
      rs = "";
    
    }
  }

  delay(100);
}

String receiveUart() {
  String rs;
  if (Serial1.available())
  {
    while (Serial1.available()) {
      delay(1);
      if (Serial1.available() > 0) {
        char c = Serial1.read();
        rs += c;
      }
    }
  }
  return rs;
}
```


```python:Raspberry&nbsp;Pi側

import serial
import traceback
import time
import json

class UART:

        def __init__(self):
                try:

                        self.uartport = serial.Serial(
                                port="/dev/ttyAMA1",
                                baudrate=115200,
                                bytesize=serial.EIGHTBITS,
                                parity=serial.PARITY_NONE,
                                stopbits=serial.STOPBITS_ONE,
                                timeout=None,
                        )
                except serial.SerialException:
                        print(traceback.format_exec())

                self.uartport.reset_input_buffer()
                self.uartport.reset_output_buffer()
                time.sleep(1)

        def send_serial(self, cmd):
                print("send data : {0}".format(cmd))
                try:
                        cmd = cmd.rstrip()

                        self.uartport.write((cmd + "\n").encode("utf-8"))
                        self.uartport.flush()

                except serial.SerialException:
                        print(traceback.format_exec())

        def receive_serial(self):
                try:
                        rcvdata = self.uartport.readline()
                        self.uartport.flushInput()

                except serial.SerialException:
                        print(traceback.format_exec())

                return rcvdata.decode("utf-8").rstrip()

if __name__ == '__main__':
    uart = UART()
    while True:
        input_data = input(input data:)

        send_data = {msg : input_data}
        json_data = json.dumps(send_data)
        uart.send_serial(json_data)
        receive_data = uart.receive_serial()
        print("receive data : {0}".format(receive_data))

```
カラー画像の単色化

```CS
Mat src = new Mat("./Parrots.bmp");

Cv2.Split(src, out Mat[] planes);

Mat Zero = Mat.Zeros(header.height, header.width, MatType.CV_8UC1);

Mat dest = new Mat();

Cv2.Merge(new []{ Zero, Zero, planes[2] }, dest);

dest.SaveImage("./red.png");
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/0037ca4e-d217-3900-dac9-71cb82c2f2a2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662099/e80ed89a-c70c-bf76-ed24-a5cbef378354.png)