OmniAICreator/Qiita-1.07M huggingface dataset:
openaiでパックンマン

# はじめに

IPythonでopenaiを用いる。
ソースコードをまとめたものはこちら
https://colab.research.google.com/drive/1SgT4ms-ujUgE-udHhyYz2Q6Z4b2ZG4DD?usp=sharing

#ライブラリをインストール

```
!pip install gym pyvirtualdisplay > /dev/null 2>&1
!apt-get install -y xvfb python-opengl ffmpeg > /dev/null 2>&1
!apt-get update > /dev/null 2>&1
!apt-get install cmake > /dev/null 2>&1
!pip install --upgrade setuptools 2>&1
!pip install ez_setup > /dev/null 2>&1
!pip install gym[atari] > /dev/null 2>&1
```

# ライブラリをインポート

```
import gym
from gym import logger as gymlogger
from gym.wrappers import Monitor
gymlogger.set_level(40) #error only
import tensorflow as tf
import numpy as np
import random
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import math
import glob
import io
import base64
from IPython.display import HTML

from IPython import display as ipythondisplay
```

# 結果を表示するための準備

```
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
"""
Utility functions to enable video recording of gym environment and displaying it
To enable video, just do "env = wrap_env(env)""
"""

def show_video():
  mp4list = glob.glob('video/*.mp4')
  if len(mp4list) > 0:
    mp4 = mp4list[0]
    video = io.open(mp4, 'r+b').read()
    encoded = base64.b64encode(video)
    ipythondisplay.display(HTML(data='''<video alt="test" autoplay 
                loop controls style="height: 400px;">
                <source src="data:video/mp4;base64,{0}" type="video/mp4" />
             </video>'''.format(encoded.decode('ascii'))))
  else: 
    print("Could not find video")
    

def wrap_env(env):
  env = Monitor(env, './video', force=True)
  return env
```

# パックマンを実行

```
env = wrap_env(gym.make("MsPacman-v0"))
print(env.action_space)
observation = env.reset()

while True:
    env.render()
    #your agent goes here
    action = env.action_space.sample() 
    observation, reward, done, info = env.step(action) 
    if done: 
      break;            
env.close()
show_video()
```

# 参考
https://gist.github.com/jkuruzovich/aebc07a3b554eb1253e6ef877d3c9b4f
git pushでnpmパッケージとデモページを更新する（React&TypeScript用のboilerplate付き）

(2020.08. 12更新）
実際にこのboilerplateを使ってnpmパッケージを公開してみました。
https://qiita.com/nariakiiwatani/items/aa6189e86c2bd9b4200f

# TL; DR

[GitHub: dev-npm-package-react-typescript-boilerplate](https://github.com/nariakiiwatani/dev-npm-package-react-typescript-boilerplate)

# 概要

ReactコンポーネントやHooksを作ってnpmに公開する際、

- ソースコードのgit push
- npmパッケージのpublish
- デモページの更新

という作業が発生する。
（デモページが必要ない場合もあるかもしれないが、個人的な感覚として、デモページがあるかないかで、導入するモチベーションが5倍くらい変わるのでほんとに単純なものだけでもあった方が良いと思う。）

これらの作業は独立にも行えるが、全て同じタイミングで反映されて欲しいので、手元のコマンド一発で全部できるようにしたい。
かつバージョンの不一致が起きないように、全てのリソースを一箇所に置いておきたい。

今回やることは以下の環境づくり。

- ライブラリのソースコードをGitHubリポジトリにおく
- 同じリポジトリにデモページのソースコードを置く
- リポジトリにgit pushすると以下のGitHub Actinosが実行される
    - デモページのビルドと公開
    - ライブラリのビルドとnpmへのpublish

全部入りのリポジトリはこちら。
[GitHub: dev-npm-package-react-typescript-boilerplate](https://github.com/nariakiiwatani/dev-npm-package-react-typescript-boilerplate)

最低限必要な作業は、、、

- (GitHubに登録)
- (npmに登録)
- 自分のGitHubリポジトリの作成
- npm tokenを生成してリポジトリに登録（自動publish用）
- package.jsonの編集
    - package名
    - 制作者情報
    - gitリポジトリ情報
- git push
- GitHub Pagesの公開ディレクトリ設定

以下、Readmeとかぶるところもあるがその他情報を載せておく。


## package.jsonの編集
- package名
- 制作者情報
- gitリポジトリ情報

## ライブラリ本体の開発

- まず`yarn run setup:all`する。
- 開発は基本的に`src`フォルダ内で行う。
- ここに置いたモジュールは、ビルド時に`dist`フォルダ内にトランスパイルされる。
- モジュールの追加や削除をした際は`index.js`と`index.d.ts`も編集しておく。
    - これを忘れると、import時に各モジュールへのパスをいちいち書くことになる。
- ローカル確認用にビルドする場合は`yarn run build`
- `git commit`は通常通り行って良いが、コミットメッセージに
    - fix: => パッチバージョンアップ
    - feat: => マイナーバージョンアップ
    - perf: => メジャーバージョンアップ  
のいずれかを含まないと、pushしてもライブラリが公開されない。  
コミットメッセージの詳細は[semantic-release](https://github.com/semantic-release/semantic-release)のドキュメント（英語）を参照。  
[git-todos](https://github.com/z0al/git-todos) と一緒に使うと良さそう.

※ ライブラリ本体から別のパッケージを使用する場合、`package.json`の`dependencies`ではなく`peerDependencies`と`devDependencies`に追記するようにする。
こうしないと、このライブラリを使用する環境でたまたま同じパッケージを使用しようとした場合に重複することになり、実行時エラーが起きる可能性がある。  
    参考: [Reactコンポーネントをnpmパッケージとして開発する](https://developer.hatenastaff.com/entry/2016/04/09/180000#react%E3%81%AFpeerDependencies%E3%81%AB%E5%85%A5%E3%82%8C%E3%82%8B)

関連スクリプト

```
# ライブラリをビルド。distフォルダに出力される
yarn run build
```

## デモページの作成
普通のReactアプリを開発する感じでOK。
`demo/src/components/App.tsx`の編集から始めると良い。

関連スクリプト 

```
# デモページをビルド。demo/distフォルダに出力される
yarn run build:demo
# ライブラリをビルドして、デモページをホストするローカルサーバを起動
yarn run dev
```

## リモートリポジトリ設定
npm accountページ -> Auth Tokens で新しいトークンを作ってクリップボードにコピー
GitHubリポジトリのSettings -> Secretsで新しい変数を作成する。

- NameはNPM_TOKEN
- Valueはコピーしたトークン

## pushしてみる
`git push`-> GitHub actionsのページから進捗が確認できる


実際にこの仕組みを使って公開しているライブラリがこちらになります。
https://github.com/nariakiiwatani/react-plain-json-editor
https://www.npmjs.com/package/react-plain-json-editor
Macでdmidecodeコマンドを使う

dmidecodeコマンドはBIOS内のシステム情報を見るコマンドらしい、メモリ等の情報を見ることができる。

> [dmidecode for Apple OS X](http://cavaliercoder.com/blog/dmidecode-for-apple-osx.html)
> Dmidecode is a long standing, effective tool for reading manufacturer info from the SMBIOS tables present on most modern x86 based systems. It’s been available for many years on most Unix like operating systems and has also been ported to Windows. Until now, it had never made the leap to OS X.

ターミナルから以下によりインストール可能

```
brew install cavaliercoder/dmidecode/dmidecode
```

自分のMacにはLPDDR3が２枚刺さっていることがわかった

```
$ sudo dmidecode --type memory | grep "LPDDR"
	Type: LPDDR3
	Type: LPDDR3
```

# 参考
[dmidecode for Apple OS X](http://cavaliercoder.com/blog/dmidecode-for-apple-osx.html)
[http://www.nongnu.org/dmidecode/](http://www.nongnu.org/dmidecode/)
【Go】【Ginkgo】FizzBuzzをGinkgoでテストしてみる

## はじめに
最近Goの勉強をしてて、簡単なWebサーバーを作ってみたり、コマンドラインで動作するツールを作ったり、、、としているんですけど、そういやテスト書いたことないなあと思って今回の記事を書くことにしました！

## Ginkgoを選んだ理由
Ginkgoの書き方がなんとなくrspecに似てるからです。
昔Railsを書いていたことがあるので、簡単に書けるんじゃないかな〜っていう安易な発想です。

## テストの準備
Ginkgoをインストールします。

```
go get github.com/onsi/ginkgo/ginkgo
go get github.com/onsi/gomega/...
```

ディレクトリとテスト用ファイルを作成します。

```
mkdir fizzbuzz
cd fizzbuzz
ginkgo bootstrap
ginkgo generate fizzbuzz
```

## 実装
今回作成するテストケースは以下の通りとします。よく見るFizzBuzzですね。

- 数値が3の倍数であれば「Fizz」を返す
- 数値が5の倍数であれば「Buzz」を返す
- 数値が3の倍数かつ5の倍数であれば「FizzBuzz」を返す
- 数値が3の倍数でも5の倍数でもなければ、そのまま文字列に変換して返す


早速ですが実装は以下の通りです。
シンプルなFizzBuzzなので特に何もないですね。

```golang:fizzbuzz.go
package fizzbuzz

import (
	"strconv"
)

func Convert(i int) (string, error) {
	if i%15 == 0 {
		return "FizzBuzz", nil
	}
	if i%3 == 0 {
		return "Fizz", nil
	}
	if i%5 == 0 {
		return "Buzz", nil
	}
	return strconv.Itoa(i), nil
}

```

こちらがテストコードになります。
こういう書き方がいいのかダメなのかもわかってないですけど、それっぽく書いてみました。

```golang:fizzbuzz_test.go
package fizzbuzz

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"strconv"
)

var _ = Describe("fizzbuzz", func() {

	Describe("Convertメソッド", func() {

		Context("引数が3の倍数でも5の倍数でもない場合", func() {
			data := []int{1, 4, 8, 11, 13, 14, 17, 19, 23, 26}
			for idx := range data {
				// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
				v := data[idx]
				r, err := Convert(v)
				It("そのまま文字列変換した値を返すこと", func() {
					Expect(r).To(Equal(strconv.Itoa(v)))
				})
				It("エラーがnilであること", func() {
					Expect(err).To(BeNil())
				})
			}
		})

		Context("引数が3の倍数", func() {
			data := []int{3, 6, 9, 12, 18, 21, 24, 27, 33, 36}
			for idx := range data {
				// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
				v := data[idx]
				r, err := Convert(v)
				It("Fizzという文字列を返すこと", func() {
					Expect(r).To(Equal("Fizz"))
				})
				It("エラーがnilであること", func() {
					Expect(err).To(BeNil())
				})
			}
		})

		Context("引数が5の倍数", func() {
			data := []int{5, 10, 20, 25, 35, 40, 50, 55, 65, 70}
			for idx := range data {
				// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
				v := data[idx]
				r, err := Convert(v)
				It("Buzzという文字列を返すこと", func() {
					Expect(r).To(Equal("Buzz"))
				})
				It("エラーがnilであること", func() {
					Expect(err).To(BeNil())
				})
			}
		})

		Context("引数が3の倍数かつ5の倍数", func() {
			data := []int{15, 30, 45, 60, 75, 90, 105, 120, 135, 150}
			for idx := range data {
				// rangeの第2引数はポインタなのでそのままアサーションに使用すると正しくテストが実行されない
				v := data[idx]
				r, err := Convert(v)
				It("FizzBuzzという文字列を返すこと", func() {
					Expect(r).To(Equal("FizzBuzz"))
				})
				It("エラーがnilであること", func() {
					Expect(err).To(BeNil())
				})
			}
		})

	})

})

```

## おわりに
今回は、Goで簡単なテストを書いてみました。
標準のテストを書いたことがない状態で、いきなりGinkgoを書いていいものか悩みましたが、まあよしとしましょう。
何かの参考になれば幸いです。
【Vue.js】Vue CLIグローバルフィルタの作成

#【Vue.js】Vue CLIグローバルフィルタの作成

Vue CLIで作成したサイトでグローバルフィルタを使う方法。
グローバルでフィルタを使用するには、filter関数とfilter名の登録が必要になる。

下記ページを参考にさせていただきました。
https://teratail.com/questions/281227


##手順
1. srcフォルダ配下にfilterディレクトリとindex.jsを作成
2. vueのインポート
3. フィルタの作成
4. main.jsで作成したフィルタをインポート
5. フィルタを適用する


#1. Sorceフォルダ配下にfilterディレクトリとindex.jsを作成する

filterのライブラリとしてディレクトリを作成する。

フォルダやファイルの場所や名前は任意だが、以下では、srcディレクトリ配下に作成する例とする。

・ディレクトリとファイル
**PJ > src > filter > index.js **

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/65672823-95f0-accf-a34f-e68ad90d4f13.png)


<br>
##2. vueのインポート
フィルタ関数とIDを登録するために、まずはvue自信をインポートする。

```js:index.js
import Vue from "vue"
```


<br>
**＜import Vue from "vue"について＞**
import Vue from "vue"は下記式と同義らしい。
何をしているかは明確ではないが、グローバルで使用できるVueインスタンスを生成しているとみられる。

```js:
import Vue from "vue"
↓
const Vue = require('vue')
↓
const vue = require('./node_modules/vue/dist/vue.runtime.common.js');
↓ 
if (process.env.NODE_ENV === 'production') {
  module.exports = require('./vue.runtime.common.prod.js')
} else {
  module.exports = require('./vue.runtime.common.dev.js')
}
```



<br>
#3. フィルタの作成
Vue.filterを使い、フィルタ名と処理を定義する。
`Vue.filter('フィルタ名', function(引数){return 処理})`

1000桁区切りをするフィルタ1000separatorを作成する場合。

```js:index.js
import Vue from "vue"

Vue.filter('1000separator', function(value) {
  return value.toLocaleString();
})
```




<br>
##4. main.jsで作成したフィルタをインポートする。
srcディレクトリ配下のmain.jsファイルに移動し、filterディレクトリをインポートする。

```js:main.js
import "./filter"
```



<br>
##5. フィルタを適用する
フィルタを適用したい箇所に移動し、フィルタを呼び出す。
呼び出し方は、マスタッシュ展開を用いる方法と、v-bindを用いる方法の２種類。

(1)Mustache展開
`{{式|　フィルタ名}}`

(2)v-bind
`<要素 v-bind:属性="プロパティ名 | フィルタ名">`




<br>
マスタッシュ展開でフィルタを使用する例。

```html:マスタッシュ展開
 <em>${{number | 1000separator}}</em>
```

dataオプションのnumberプロパティに格納された数値を1000桁区切りにする。


<br>
以上。
1分で分かる Cloud Firestore 概要

### Cloud Firestore とは？

高速でサーバレスなクラウド NoSQL ドキュメントデータベースです。[Firebase Realtime Database](https://firebase.google.com/docs/database?hl=ja) と同様に[スキーマレス](https://www.idcf.jp/words/schema.html)かつリアルタイムにデータを監視することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292456/568d03f7-82e2-b1ec-98ca-b6d08889f02f.png)


**公式ドキュメント**

- https://cloud.google.com/firestore/docs?hl=jaja

### メリットは？

一番大きなメリットとしては開発コストの大幅な削減です。Firebase Realmtime Database もそうですが、
Cloud Firestore は基本的にサーバレス DB なので、自前でサーバを構築する必要がなくなり。維持コストを削減
することができます。また Cloud Firestore はスキーマレスなのでデータの構造などを柔軟に変えることができ、
開発スピードの向上も見込めます。また、ある程度サービスの規模が小さいまたはテストプロトタイプとして利用する場合は
ほぼ無料で使うことができます。具体的な料金については[こちら](https://firebase.google.com/docs/firestore/pricing?hl=ja)を参照してください。


### デメリットは？

デメリットとしては、Firebase Realtime Database もそうですが、スキーマレスであるが故に柔軟性がありますが、
その分設計や[セキュリティルール](https://firebase.google.com/docs/firestore/security/get-started?hl=ja#writing_rules)
などの設定は難しくなります。また、Cloud Firestore は Firebase Realmtime Database とドキュメントデータベース
になったことで複合クエリができたりして、検索性は大幅に向上していますが、それでも十分とは言えないので、
検索APIの,[Algolia](https://www.algolia.com/)などの使用も検討しておくと良さそうです。また、
Firebase Realmtime Database はツリー構造のデータベースなので Json による一括インポートなどが可能でした
が、Cloud Firestore はドキュメント型のデータベースなので、そのように小回りのきく操作は難しいそうです。


### まとめ

Firebase Realtime Database と迷った時は基本的には Cloud Firestore を選択して問題なさそう。ただ、DB の以降で使用したり、ノードの子コレクションに対しても明示的に変更通知を受け取りたい場合などは Firebase Realtime Database の方が良さそう。また、スキーマレスが故に設計やルールの設定などは複雑化したり、検索性が十分ではないことなどのデメリットも存在するが、Firebase 全体としてのスケーラビリティの高さだったり、他のサービスとうまく組み合わせることで開発スピードは飛躍的に向上すると考えられる。
WELD-001201: Error loading beans.xmlとなったときの対応方法

# 事象 : GlassFishを起動しようとしたら怒られた

```text:エラーダイアログのメッセージ
cannot Deploy プロジェクト名
deploy is failing=Error occurred during deployment: Exception while loading the app : WELD-001201: Error loading beans.xml jar:file:/C:/app/glassfish-4.1/glassfish4/glassfish/domains/domain1/eclipseApps/プロジェクト名/WEB-INF/lib/app-name-1.0.0.jar!/META-INF/beans.xml. Please see server.log for more details.
```

```bash:server.log
[2019-11-14T10:08:52.360+0900] [glassfish 4.1] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=43 _ThreadName=admin-listener(4)] [timeMillis: 1573693732360] [levelValue: 1000] [[
  Exception while loading the app : WELD-001201: Error loading beans.xml jar:file:/C:/app/glassfish-4.1/glassfish4/glassfish/domains/domain1/eclipseApps/プロジェクト名/WEB-INF/lib/app-name-1.0.0.jar!/META-INF/beans.xml
java.io.FileNotFoundException: JAR entry META-INF/beans.xml not found in C:\app\glassfish-4.1\glassfish4\glassfish\domains\domain1\eclipseApps\プロジェクト名\WEB-INF\lib\app-name-1.0.0.jar
    at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:140)
    at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:150)
    at java.net.URL.openStream(URL.java:1037)
    at org.jboss.weld.xml.BeansXmlParser.parse(BeansXmlParser.java:74)
    at org.jboss.weld.bootstrap.WeldBootstrap.parse(WeldBootstrap.java:131)
    at org.glassfish.weld.BeanDeploymentArchiveImpl.parseBeansXML(BeanDeploymentArchiveImpl.java:755)
...省略...
```

# 原因 : 不明
プロジェクトのクリーンなどを面倒臭がってやらないときによく発生します。

## 対応 : クリーンして再度起動する
1. [サーバ]ビュー > GlassFish配下のアプリケーションを削除 > GlassFishを選択して右クリック > [クリーン]
1. メニューの[プロジェクト] > [クリーン]
1. [プロジェクト・エクスプローラ]ビュー > 対象プロジェクトを選択して右クリック > [実行] > [サーバで実行]
高位合成の言語処理系 Karutaで便利なSRAM？を作る

# はじめに

Karutaは筆者が開発している高位合成の処理系で、FPGAの開発等に使うことを想定しています。
高位合成についてご存知ない方は[論理回路の高位合成について　https://qiita.com/nekoaddict/items/cddde13a1322e94f44b8](https://qiita.com/nekoaddict/items/cddde13a1322e94f44b8)
Karutaについては[FPGA向け論理回路設計のためのプログラミング言語処理系 Karuta の紹介　https://qiita.com/nekoaddict/items/be418e1eba7eb27264fc](https://qiita.com/nekoaddict/items/be418e1eba7eb27264fc)
もしくは[https://github.com/nlsynth/karuta](https://github.com/nlsynth/karuta)をご覧ください。

開発の大きな目標として演算回路の入ったプロセスの複雑なネットワークをわかりやすく記述し、高性能な回路を生成することを目指してますが、この記事ではちょっとした雑用をこなす機能を紹介します。

Ubuntuをお使いの方は `$ sudo snap install karuta` でインストールできるので試してみてください。(WSL2の場合はsnapを動かすための追加設定が必要です)

# SRAMの作成

FPGAでSRAMを作る時はIPマクロのジェネレーター的なツール(ASIC開発の場面ではメモリコンパイラと呼ばれることがあります)を使う方法とHDLでメモリの動作を記述して合成ツールに推定させる方法がありますが、ここでは後者の方法を前提とします。

まず、次のようなコードを書いて`a.karuta`という名前で保存します。

```
module {
  @SramIf
  ram s int[16]
}
```

Karutaコマンドの実行は次のような感じです。

```
$ karuta compile a.karuta
```

するとカレントディレクトリに`a.v`というVerilogのファイルが出力されて、色々なモジュールが含まれていますが、トップのモジュールはこんな感じです。

```
module a(
  input clk,
  input rst,
  input [3:0] s_addr,
  input s_wen,
  output [31:0] s_rdata,
  input [31:0] s_wdata);
…中略
endmodule
```

`s_addr`, `s_wen`, `s_rdata`, `s_wdata`経由で外部からアクセスすると普通にSRAMとして使えます。

# メソッドの追加

いちいちKarutaなんて変なツールを使わなくてもSRAMを推定するモジュールを書くなんて簡単だし、必要なら自分で適当なスクリプトを書いてなんとかするよって場合もあるかと思いますが、もう少し頑張ってみます。

Karutaはオブジェクト指向言語なので、次のようなメソッドを追加してみます。メソッドの中身はメモリを0クリアするというもので、`ExtEntry`というアノテーションを付けることでメソッドを外部から呼べるようにします。

```
module {
  @SramIf
  shared s int[16]

  @ExtEntry
  func clear() {
    for var i int = 0; i < 16; ++i {
      s[i] = 0
    }
  }
}
```

再びVerilogを出してみると

```
module a(
  input clk,
  input rst,
  input [3:0] s_addr,
  input s_wen,
  output [31:0] s_rdata,
  input [31:0] s_wdata,
  input clear_req_valid,
  output clear_req_ready,
  output clear_req_busy,
  output clear_res_valid,
  input clear_res_ready);
…中略
endmodule
```

SRAMアクセスのためのI/Oの他にハンドシェイクっぽい信号が追加されているのが見えます。こんな感じで0クリアの機能を持ったSRAMモジュールが簡単に作れました(内部的にはdual portのSRAMを生成して片方のportに0クリア用のステートマシンが付きます)。
req側のハンドシェイクでclear()メソッドを起動し、res側のハンドシェイクでメソッドの終了を待つという動作をします。プロトコルについては @ikwzmさんの[method-interfaceについてのドキュメント　https://gist.github.com/ikwzm/bab67c180f2f1f3291998fc7dbb5fbf0](https://gist.github.com/ikwzm/bab67c180f2f1f3291998fc7dbb5fbf0)
を参考にしてください。

必要ならメソッドには引数や返り値も追加することができるので、0クリア以外の動作を実装することも簡単だと思います。

# 最後に

Karutaを使ってちょっとした用事をこなす回路を作る方法を説明してみました。
多くの場合、高位合成は解きたい問題のコア部分を良い感じに扱えるという期待を持って導入されますが、脇役的な雑用をとりあえず解決する手段という方向性も価値があるのではないかと考えています。
ここで作れる回路の品質は必ずしもベストなものではありませんが（将来的にある程度までは改善するつもりですが…）、こういった手抜きをすることで本質的に頑張りたい重要な部分に取り組む時間が稼げるかもしれません。
ソフトウェアの開発で例えるなら、アプリの多くの部分をスクリプト言語等で書き、パフォーマンス上重要な部分をCやアセンブラで書くという選択でトータルの開発コストと性能を最適化するみたいなイメージを想定しています。

(ディープラーニングの計算を記述したらありとあらゆる最適化が適用されて……みたいな野心も無いわけではないのですが、まあ、今回のAIブームが終わった後とかになる？……)
chrome拡張機能に触れてみる

#拡張機能の種類
種類は以下の3つ

1. Browser actions
2. Page actions
3. Override Pages

##Browser actions
ブラウザのツールバーにアイコンを表示させるタイプ
##Page actions
アドレスバーの中にアイコンが表示されるタイプ
##Override Pages
chrome内部のページを代替えするタイプ

#必要なファイルを揃えていく
##manifest.json
必ず必要なファイル
以下の記事で詳しく触れている。
参考：[Chrome 拡張機能のマニフェストファイルの書き方](https://qiita.com/mdstoy/items/9866544e37987337dc79)

軽く備忘録を書いておく
###manifest_version
ここは何も考えずに`2`とすればいい

###name
拡張機能の名前

###version
拡張機能のバージョン。拡張機能の自動更新機能でバージョンがチェックされ、バージョンが上がっていないと更新できないため、しっかりと書いておく。

###browser_action
```json:manigest.json
"browser_action": {
    "default_icon": {
        "19": "icon19.png"
    },
    "default_title": "Ext title",
    "default_popup": "popup.html"
},
```
出典：[Chrome 拡張機能のマニフェストファイルの書き方](https://qiita.com/mdstoy/items/9866544e37987337dc79)
####default_popup
browser_actionの子要素でアドレスバーに表示されるアイコンをクリックしたときに表示されるポップアップの中のhtml。つまり個々に書いたhtmlがポップアップ時に表示される。

###content_scripts
開いているwebページに影響するscript
ここに設定することでページの背景を変えたりできる。開いているページに影響とはそういうこと。
###background
content_scriptsやdefault_popupとの連携

##個々のファイルの連携
連携はchrome.*APIで行われる


#作りたいもの
##youtubeの画面を明るくしたい
[けそポテト](https://www.youtube.com/channel/UCB3CTxzJoA_q56_FHTyPyrA)というyouuberのジェイソンの動画をよく見ている。非常に面白く、特に作業しているときに流して、ラジオのように聞いている。
その動画はゲーム画面が暗いということもあって見にくい。いつもディベロッパーツールでcssのfilterをいじり、brightnessで画面を明るくしているが、いちいちその作業を経由するのも面倒だから、拡張機能で楽に画面を明るくできるようにしたい。

今回はcssをいじるのでcontent_scriptsが使えそう

もう少し情報を集めてみて作っていく。




#参考
[Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)

[Chromeのオリジナル拡張機能を開発しよう（ソースコードあり）](https://liginc.co.jp/web/tool/browser/163575)
before_action と redirect_to 　        〜リダイレクトが繰り返し行われないようにするには〜


【概要】
---------------------------------
<b>1.結論</b>

<b>2.ループになるのはどういう時か</b>

<b>3.なぜループになるのか</b>

<b>4.どのように解決し、使うのか</b>

<b>5.ここから学んだこと</b>





1.結論
---------------------------------
［:except］を使う。


2.ループになるのはどういう時か
---------------------------------
I）def indexに行く前にbefore_action :goindexが行われます。
II）そうすると定義先に設定されている goindexにあるindexが行われます。
III）そうなるとredirection_toというのはroutes(ルーティング）に戻り、
  ルーティングのアクションはindexになります。
IV)そうなると、また1:が繰り返され無限ループとなります！

<img width="511" alt="スクリーンショット 2020-08-11 22.25.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686400/8c50f9bc-f2fb-2dc6-a334-cc4a977973c1.png">
<img width="295" alt="スクリーンショット 2020-08-11 22.30.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686400/41b57ea1-89b2-2cd8-9612-10e4e7a9130f.png">

無限ループすると、更新ボタンを押した際に
”リダイレクトが繰り返し行われました”とメッセージがでます。

本来無限ループはプログラミング用語なので、まさにこの状況のことですね


3.なぜループになるのか
---------------------------------
ルーティングに設定されているアクション と 　　 
redirect_toのアクションが永遠と
繰り返されるために起こります！


4.どのように解決し、使うのか
---------------------------------
before_action :goindexの
あとにexcept:[:index]とすれば解決できます！
[:index]は”省きますよ！”という意味なので、
”def index”しか行われません！


5.ここから学んだこと
---------------------------------
I)”リダイレクトが繰り返し行われました”とメッセージがでた際は
まっさきに無限ループを疑う癖がつきました！


II)そもそもルーティングからコントローラーに行く際に
おかしいことがわかるのでMVCモデルがきちんとわかっていたことも
エラー解決の時間短縮につながりました！
Next.jsで静的HTMLエクスポートしたアプリをローカルで確認する方法

## 経緯
[Next.jsの静的HTMLエクスポート機能（Static HTML Export）](https://nextjs.org/docs/advanced-features/static-html-export)を使うと、サーバーにNode.jsを必要とせずに、クライントのみで実行できる静的HTMLにアプリを出力することできます。

ただし、`create-next-app`でスキャフォールディングしたプロジェクトに用意されている`dev`コマンドで起動したアプリはサーバーサイドレンダリング（以下SSR）が有効になっており、静的HTMLのみの確認ができません。


そこでNext.jsで静的HTMLエクスポートしたアプリをローカルで確認する方法を調べました。

## 確認環境

- Node.js - 12.4.1
- Next.js - 9.5.2

## 設定方法

サンプルプロジェクトを作成します。すでに作成済みの場合は飛ばします。

```bash
$ npx create-next-app my-static-site
$ cd my-static-site
```

`serve`というパッケージをインストールします。静的ファイルをホスティングするローカルサーバーを建てることができます。
開発でのみ使用するため`-D`オプションを指定しています。

```bash
$ yarn add -D serve
```


最後に`package.json`のnpmスクリプトを修正します。
静的ファイルを出力する`export`コマンドと、ローカルサーバーを立ち上げる`serve`コマンドを定義します。

`next export`ではファイルはデフォルトで`./out`ディレクトリに出力されます。
そのため、`serve ./out`でホスティングするディレクトリを指定しています。

SSRせず、完全に静的HTMLエクスポートしかしない場合、誤認防止の為に不要なコマンド削除しても良いと思います。

```diff
  "scripts": {
-   "dev": "next dev",
-   "build": "next build",
-   "start": "next start"
+   "export": "next build && next export",
+   "serve": "yarn export && serve ./out"
  },
```

実際に下記のコマンドを打つと以下のように表示されます。

```
$ yarn serve
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195024/993c3811-1c3c-0bb4-9000-a6ee2d556335.png)
PyGMTの導入

PythonでGMTがつかえるらしいので入れてみる。
https://www.pygmt.org/dev/install.html

# 仮想環境の構築

```bash:
conda create -n pygmt python=3.8.2
conda activate pygmt
conda install pip numpy pandas xarray netcdf4 packaging gmt
conda install pygmt -c conda-forge
conda install ipython jupyter jupyterlab -c conda-forge
```

# サンプルテスト
チュートリアルにしたがってすすめる。

```bash:
conda install pytest pytest-mpl ipython
```

`python`を起動して、

```Python:
import pygmt
pygmt.show_versions()
pygmt.test()
```

返ってきたメッセージ

```python:
============================== 53 failed, 212 passed, 1 skipped, 353 warnings in 83.38s (0:01:23) ==============================
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kanon/local/anaconda3/envs/pygmt/lib/python3.8/site-packages/pygmt/__init__.py", line 187, in test
    assert status == 0, "Some tests have failed."
AssertionError: Some tests have failed.
```

けっこう失敗している気がするけど、これでいいのか？
GMT5も入れているので、チュートリアルにある通り`GMT_LIBRARY_PATH`も設定してみたが、**failed**の数は変わらなかった。

# とりあえず地図！

チュートリアル通りに、絵を描いてみた。

```python:
import pygmt

fig = pygmt.Figure()

fig.basemap(region=[-90,-70,0,20], projection="M8i", frame=True)

fig.coast(shorelines=True)

fig.show()

fig.savefig("test_pygmt.png")
```

うまくかけました！
ただし、JupyterLabがDark modeだとなにも見えない・・・oh
cmake時にエラー(Missing: Qt4)

cmake時にエラー(Missing: Qt4)

```
$ cmake ../
-- BUILD ERRORS: These must be resolved before compiling.
-- 	Missing: Qt4
-- END BUILD ERRORS
```

Qt4をインストールして解決

```
$ sudo apt install qt4-default
```

# 参考
[error-with-cmake-and-manually-compiled-qt4](https://stackoverflow.com/questions/42434566/error-with-cmake-and-manually-compiled-qt4)
Bubbleでデータをランダムで取り出す方法

ノーコードツールの Bubbleで、ゲームなどを作るときには欠かせない「データをランダムで取得する」という方法を紹介します。

## データを準備する

まずは、ランダムで取り出すデータを作ります。クイズとその答えなどを作っていきます。ここでは、小学生向けの漢字ゲームを題材にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/925da240-a4ff-7fa3-0c91-d0afe444c607.png)

## グループを作る

データと連係させるためのグループを作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/a907db22-6830-b3ba-d16e-f508c2a718c9.png)

「Type of content」に作ったデータを指定して、「Data source」で「Do a search for」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/df145c0f-2eba-14b6-e4f3-19e06cc111bb.png)

「Type」で改めて同じデータを指定して、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/21f76092-2a1a-3d7d-7549-89c338144274.png)

次のドロップダウンで「:random_item」を選びます。これで、ランダムでアイテムが取り出されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/987fdf20-c09f-bb5d-5ba4-6bc4e3279be5.png)

## データを紐付ける

後は、表示したいテキストフィールドなどを追加して、グループの中のデータを紐付ければ、ランダムで値の内容が表示されるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977/04290a18-04ba-51c3-9192-bf5f0716c4a6.png)
【Flutter】TextFieldのonSubmittedコールバックが頻繁に呼ばれる時に確認すべきこと【Android】

# TextFieldのプロパティであるonSubmitted

TextFieldのプロパティであるonSubmittedは公式ドキュメントによると
`ユーザーがフィールドのテキストの編集を完了したことを示したときに呼び出されます`
とのことだ。

# 発生した異常



ということで、実装したのだが、
**テキスト入力が完了していないのに頻繁に呼ばれてしまう現象に見舞われた（Android版のみ）**

その時のソースコードがこちら

```main.dart
TextField(
// 省略…
 onSubmitted: AddButtonTapped();
// 省略…
)
```

つまり、「テキストの入力が完了したら、AddButtonTapped()を呼んでくれ」というコードだ（と思っていた）

# 解決法

ソースコードを以下の様に書き換えた。

```main.dart
TextField(
// 省略…
 onSubmitted: (String str) {
   AddButtonTapped();
 }
// 省略…
)
```

**引数を指定してあげる感じにした。**

すると、冒頭で挙げた問題点「テキスト入力が完了していないのに頻繁に呼ばれてしまう現象」が解消した。

# 関連記事

* [参考にさせていただいたソースコード](https://kodestat.gitbook.io/flutter/flutter-using-onsubmitted-to-show-input-text-after-submit)
* [TextField class公式ドキュメント](https://api.flutter.dev/flutter/material/TextField-class.html)
iPhoneでローカル開発中のHTTPS接続必須機能を動かす方法のひとつ

# はじめに
個人的にwebサービスを作りたくフロントエンドの勉強・実践を始めました。
iPhoneのSafariで動画を撮る機能を作れるかや、どんな実装になりそうかの調査を行おうと思ったところ、localhostかhttpsでないと動かない機能のようなのでSSHポートフォワーディングという手法で実現しました。

# 前提条件
* 独自ドメイン取得済み
* Https通信ができる公開サーバ設定済み
* ホストマシーンから公開サーバにSSH通信ができる

今回はお名前ドットコムで取得したドメインをEC2にアタッチしたEIPに向けて、NginxとLet's EncryptでHttps通信ができるようにしました。例として、**proxy.hoge.example**をEIPに向けていることとします。

ローカルではAngularのdevサーバをlocalhost:4200で立ち上げていて、これをポートフォワーディングします。
以上を前提とさせていただきます。

# 設定
前提条件をクリアしたらwebサーバのNginxのプロキシ設定と、ホストマシンのdevサーバのコマンドとSSHポートフォワーディングのコマンド実行のみです。

## Nginx
今回は直接nginx.confを編集します。

```
443をlistenしているserverディレクティブ内のrootをコメントアウト
# root         /usr/share/nginx/html;

443をlistenしているserverディレクティブ内の最後に追記
location / {
    proxy_pass    http://127.0.0.1:4200;
}
```
Nginxを再起動する。

## Angular
devサーバをlocalhostでproxy.hoge.exampleを許可して起動する。

```
ng serve --host localhost --allowedHosts=proxy.hoge.example
```
デフォルトの設定で4200ポートで立ち上がると思います。別のポートだった場合、SSHのコマンドでポートを合わせる必要があります。
コマンドにhostやallowedHostsを指定しなくてもコンフィグファイルで指定することもできると思います。

## SSH
SSHポートフォワーディングを実行する

```
ssh -R 4200:localhost:4200 -i ~/.ssh/hoge.pem ec2-user@proxy.hoge.example -N
```
オプションの意味などは参考記事を参照いただければと思います。

# 動作確認
iPhoneのSafariからhttps://proxy.hoge.example にアクセスするとdevサーバの内容が閲覧できるかと思います。
目的のHttpsでないと動作しない機能についても確認できました。

注意点としては、devサーバをつないでいるせいか、余計なアクセスが頻繁に走っていそうなので、動作確認の時だけなどに限定して利用した方が良さそうです。

# 最後に
思い出しながら書いたので間違いなど多々あるかもしれないです。ご指摘いただけると幸いです。

今回の手法は自分の知っている技術を使ってなるべく最短で実現する方法を探りましたが、調べる中でCaddyというGo製のサーバなど便利そうなものをいくつか発見しました。
iPhoneのプロキシ設定やラズパイ使うなどで従量課金されない方法もできそうかもしれないので、時間のあるときにチャレンジしてみたいです。

iPhoneの挙動確認、もっと楽な方法あればぜひご教示いただきたいですm(_ _)m

# 参考記事
https://qiita.com/Ayaka14/items/449e2236af4b8c2beb81
ありがとうございました。
nfsマウント (2020.08.11)

# 計算機サーバー間のNFSマウント
* 環境：　
 * サーバー（Centos7; IP=aaa.aaa.aaa.aaa）
 * クライアント１（Centos7; IP=bbb.bbb.bbb.bbb）
 * クライアント２（ubuntsu; IP=ccc.ccc.ccc.ccc）
* 参照記事
 * [centos7の記事](https://qiita.com/rikudai/items/f9900e4865ce25a8464e)
* メモ
 * アカウントへの配慮は、user id の統一により図られる。
 
##問題設定
サーバー側にある /data02 なるディレクトリを、クライアント１＆２からマウントして利用したい。

## server側 (centos7)
yumでnfs-utilsをインストール

```bash
sudo yum -y install nfs-utils
```

共有するディレクトリが無ければ作成

```bash
sudo mkdir /data02
```


/etc/exportsを編集 (#rw権限、rootでの接続を許可しない場合の設定)

```text:/etc/exports
/data02 bbb.bbb.bbb.bbb(rw,async,root_squash) # root での接続を許可する場合は no_root_squash
/data02 ccc.ccc.ccc.ccc(rw,async,root_squash) # root での接続を許可する場合は no_root_squash
```

ファイアウォールの設定

```bash
sudo firewall-cmd --permanent --zone=public --add-service=nfs
sudo firewall-cmd --reload
```

サービスを起動＆自動起動の設定。

```bash
sudo systemctl start rpcbind
sudo systemctl enable rpcbind
sudo systemctl start nfs-server
sudo systemctl enable nfs-server
```

サービスの再起動、その２。こちらは、```/etc/exports```を読み込んでサービスを再起動する。後の方でmountしたときにpermission deniedされたらこれが問題かもしれない。

```bash
sudo exportfs -ra
```

## client1側 (centos7)
yumでnfs-utilsをインストール

```bash
sudo yum -y install nfs-utils
```

マウントするディレクトリを作成

```bash
sudo mkdir /data02
```

/etc/fstabを編集して、起動時マウントの設定 (最後の方に追記)。

```text:/etc/fstab
aaa.aaa.aaa.aaa:/data02 /data02 nfs defaults 0 0
```

マウントを実行

```bash
mount -v aaa.aaa.aaa.aaa:/data02 /data02
```

## client2側 (ubuntu)
[(参考にした記事)](https://kazuhira-r.hatenablog.com/entry/2018/10/06/004855)

```bash
sudo apt install nfs-common
```

あとは、centosと同じ作業で実行可能。
K210のメモリを測ってみた

https://qiita.com/hidenorly/items/4c3ce6afddd1eb908736
を参考にして，MAiX Bit等のプロセッサであるCanaan Inc.のKENDRYTE K210のCプログラミングSDKを使えるようになりました．感謝
　いつものふるいで素数を求めるプログラムから初めて，マニュアル「K210 Standalone SDK Programming guide」をCanaanのページ
https://www.canaan.io/developer
からみつけて，これを見ながら，いつものキャッシュ速度測定プログラムでキャッシュのサイズを測ってみました．いつもは

```C:
getrusage(RUSAGE_SELF, &ru_before);
測るコード
getrusage(RUSAGE_SELF, &ru_after);
tb = ru_before.ru_utime.tv_usec + ru_before.ru_utime.tv_sec * 1000000;
ta = ru_after.ru_utime.tv_usec + ru_after.ru_utime.tv_sec * 1000000;
printf("%d,%d \n", i, ta - tb);
```
とやって，プロセスのリソース情報を取得して測っていたのだけど**裸のプロセッサにそんなものあるわけないじゃーん**（デジモンのあのセリフのノリ）ということで，1mSのインターバルタイマーを作って，mS精度のタイマーで測ってみました．結果は以下の通り：

```
256,1427 
512,1380 
1024,1357 
2048,1345 
4096,1340 
8192,1337 
16384,1335 
32768,1367 
65536,6887 
131072,9319 
262144,10559 
524288,11113 
1048576,11396 
2097152,11543 
```

これをグラフにすると，こんな感じ．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152716/c0bf10c8-12e0-c205-212b-178c89278119.png)

どうやら32KiBのキャッシュがついているようで，メモリとの速度比は8〜9倍というところです．

以下がコードです．ヒープをランダムウオークする部分とか，K210のタイマーを使ってインターバルタイマーを作る部分とか取れるパーツは再利用してください．

```C:rhit-K210.c
/* Copyleft 2020 Gian
 */
#include <bsp.h>
#include <sysctl.h>
#include <timer.h>
#include <plic.h>
#include <stdio.h>
#include <malloc.h>

#define TD TIMER_DEVICE_0
#define TC TIMER_CHANNEL_0

volatile unsigned timer_count = 0;

timer_callback_t timer_svc() {
  timer_count++;
}

char **buff = NULL;
unsigned bsize;
unsigned bmask;
unsigned repeat;
volatile unsigned tb, ta;
int zzz = 0;
#define LOAD 0x8000000

void mkbuff(unsigned size)
{
  int i;
  int l, m;
  char **j, **k;
  unsigned mm;
  
  if (buff != NULL) free(buff);
  if ((buff = (char **)malloc(size + sizeof(char *))) == NULL) {
    fprintf(stderr, "MALLOC\n");
    exit(-1);
  }
  bsize = size / sizeof(unsigned *);
  repeat = LOAD / bsize;
  bmask = 0xffffffff - bsize;
  for (mm = 0x80000000; (mm & bsize) == 0; mm >>= 1) {
    bmask -= mm;
  }
  for (m = -1, l = bmask; l >= 0; m++) {
    l = l << 1;
  }
  for (i = 0; i < bsize - 1; i++) buff[i] = NULL;
  k = &buff[0];
  for (i = 0; i < bsize; i++) {
    do {
      j = &buff[(rand() >> m) & bmask];
    } while (*j != NULL);
    *k = j;
    k = j;
  }
  *k = &buff[0];
}

void rtest()
{
  int i, j, k;
  for (i = 0; i < repeat; i++) {
    for (j = 0; j < bsize; j++) {
    }
  }
}

int test()
{
  int i, j;
  char **k;
  int s = 0;
  k = buff[0];
  for (i = 0; i < repeat; i++) {
    for (j = 0; j < bsize; j++) {
      k = *k;
      s += (int) k;
    }
  }
  return s;
}


int main(void)
{
  unsigned i;

  sysctl_pll_set_freq(SYSCTL_PLL0, 800000000);
  plic_init();
  timer_init(TD);
  timer_set_interval(TD, TC, 1000000);
  timer_irq_register(TD, TC, 0, 5, timer_svc, NULL);
  timer_set_enable(TD, TC, 1);
  sysctl_enable_irq();
  
  
  for (i = 256; i < 0x400000; i <<= 1) {
    mkbuff(i);
    tb = timer_count;
    zzz += test();
    ta = timer_count;
    printf("%d,%d \n", i, ta - tb);
  }
  
  
  while(1) {
  }
  return 0;
}
```
【イベントレポート】TDDBC2020に参加しました

8/1(土)TDDBC2020というオンラインイベントに参加しましたので、
その参加レポートです。

イベントページは[こちら](https://peatix.com/event/1545209)
TDD(テスト駆動開発)を実際に手を動かして学ぼうというイベントです。

## 事前準備

リモートでTDDでペアプロを行うイベントですので、環境準備を2週間前の午前中に行いました。
この準備会もめっちゃもりだくさんでした・・・！！

### 準備の準備

イベントはDiscordを使って行いました。
事前にDiscordをインストールして入るなどしておきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561891/95a85ed8-2ea0-7003-81c0-0a03a9c38403.png)
(ポケモンのカブトにみえる・・・)

### 準備会当日！

運営の方からの挨拶などから始まり、
勉強会というよりお祭りのような雰囲気で始まりました。すでに楽しい。

### リモートペアプロデモ

Discordで、TAによるリモートペアプロデモ！
ペアプロってこうやるんだということと、TDDの進め方について学べました。
自分リモートでペアプロやるのははじめてだったのですが、リモートペアプロの理想形がイメージできました。

本当にこれだけでコンテンツとして成立するくらいの完成度でした。すでに満足。

### 環境作成

ここで、参加する言語ごとに分かれて自己紹介。
一緒にペアプロするペアともこんにちはしました。

ここからはペアごとに環境構築を行いました。
GitHubからリポジトリをforkしてお互いにpush/pullができる確認を行いました。

この日は解散！さて、当日が楽しみだ。

## 当日

朝10時からでしたが、9:30に起きました。
リモートだと朝早くても楽勝ですね。:ok_hand:

### twadaさんによる基調講演

[youtube](https://www.youtube.com/watch?v=Q-FJ3XmFlT8)にてアーカイブが残っています。
TODOリストの作成、整理からコードに落として、構造化する一連の流れが違和感なくスッと入ってきました。
思考の過程を全部わかりやすい言葉にしながら、ライブコーディングしているのですごい実感をもって理解できました。

TDDに少しでも興味ある方は、動画を見てください！
次はいよいよ実践だ:clap:

### ついに実践！

[閉区間のお題](https://gist.github.com/twada/75fb219c8cc180e9de166d8a58e877b0)を使用して、TDDを実践しました。

と、ここでトラブル発生！
ペアの入れ替えがうまくできず、自分がドライバー専任、ペアがナビゲーター専任で進めることになりました。

TAさん巡回のもとペアプロを進めていき、2回同じ言語で集まってレビュー会を行いました。
ペアで議論を重ね、TAさんからのFBを受け、また議論して・・・

本当に時があっという間に過ぎ、気が付けば夕方になっていました。
気づけば楽しい懇親会も終わりました・・・楽しいイベントだった、、

## 後日

実はTDDBCおかわり会をやりました。

当日ペアプロでドライバー/ナビゲーター交代ができなかったのと、
まだ課題が解き終わっていなかったので後日集合してペアプロを行いました。

TAさんも来てくださり、TDDBCおかわり会がスタートしました。

・・・って気づいたらTAさん5人くらいに見守られながらペアプロしてました。なんとも贅沢・・・
フィードバックもめちゃくちゃいただいて本当に感謝です。

当日は時間切れでできなかった部分までこだわって仕上げられたかなって思います。

## 感想

総じて、最高でした！
イベント参加する前は怖いんですけど、参加後は参加してよかったなと毎回思っている気がします。
ですが、今回のTDDBCはこれまでのイベントの中でも最も参加してよかったなと自信を持って言えます。

- 勇気を出して参加して本当によかった
 - TDDについても、ペアプロについても経験値が得られました
- 雰囲気が最高
  - 疑問に思ったことを素直に聞ける雰囲気がありました
     - 日常業務だと、聞きたくても聞けない場面あります。。
  - 知らないからってマウントとられない！
  - 自分が納得できていないことについて、嫌な態度をされない！
- 手厚いフィードバック
  - 2ペアに1人以上TAさんがいて、フィードバックがたくさんいただけました
  - おかわり会は本当に贅沢な経験させていただきました・・・
- 次回は何か少しでもいいから協力したい！
zsh: command not found: pipが何回も出てきやがる

HomebrewからPython3をインストールしました。これで「pipも同時にインストールできたよ」と記事に書いてあったので、そのままライブラリをインストールしたら `zsh: command not found: pip` が出てきた。いろんな記事を見ても全然なおらん。なんとか海外の記事で解決したのでメモ。

## 解決

原因はよくわからんけど、このコマンドでpipをインストールしたら解決した

```
$ sudo easy_install pip
```

確認

```
$ which pip               
/usr/local/bin/pip
```

参考にした海外の記事
https://www.it-swarm.dev/ja/python/mac-os-zsh%EF%BC%9A%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%EF%BC%9Apip/831181572/
命名規則についてまとめてみた



##命名規則について、名前が特徴的な物が多く由来が気になったのでまとめてみました。


#キャメルケース(ローワーキャメルケース)
![camel-1987672_1920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614274/63e1044a-0521-0fc5-05f5-e7af88cd975c.png)



##由来
大文字が「らくだのこぶ」のように見えることから由来している

##使い方
複合語の先頭を、小文字で書き始めた規則
例)vinakaCamelCase

##よく使われる言語
``Java, JavaScript Objective-C``

#パスカルケース(アッパーキャメルケース)
![camel-2565030_1920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614274/e18c1d7b-68dd-7072-5ad3-0b16093d2847.png)

##使い方
複合語の先頭を、大文字で書き始めた規則
例)VinakaPascalCase

#スネークケース
![snake-312561_1280.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614274/39643d78-fa09-87eb-ef74-2ff621e4afb7.png)

##由来
そのままですが、見た目が蛇（snake）っぽいのが由来

##使い方
アンダースコア (_) を区切記号として単語を繋げた規則
例)vinaka_snake_case

##よく使われる言語
``PHP, Python, Ruby``

#チェインケース（ケバブケース）
![chain-2027199_1280.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614274/7043f13c-38db-8a8b-5dcd-03f06e6031de.png)


##由来
チェインケースでは鎖でつながってるみたいに見えるため。
ケバブケースでは「串刺し」の状態を意味している。
##使い方
単語をハイフン（-）でつなげる記法
例)vinaka-snake-case

##よく使われる言語
``HTML, CSS, Lisp``


#由来は見た目から取ってるらしい

ラクダや蛇、串刺しのケバブと見た目から当てはまる由来になっていました。
命名規則って聞くと硬いイメージですが、由来を調べると遊び心があって面白いですね！！


以下参考にさせて頂きました。
大変参考になりました。ありがとうございます。

[コーディングの命名規則一覧](https://murashun.jp/blog/20181109-01.html)
[ケバブケース（kebab-case）について調べた](https://qiita.com/ybiquitous/items/75288bacb596a82a2805)
[【極小ネタ】キャメルケース/スネークケース/チェーンケースの覚え方【変数の命名規則】](https://qiita.com/mtanabe/items/960729a3eff1d02fce79)
[変数/クラス名の命名規則に使われる記法の分類](https://qiita.com/yimajo/items/a3fac0026c07ec538fc2#:~:text=%E8%A8%98%E6%B3%95%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AF%E3%82%A2%E3%83%83%E3%83%91%E3%83%BC%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB,%E3%81%8B%E3%82%89%E3%83%91%E3%82%B9%E3%82%AB%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9%E3%81%A8%E5%91%BC%E3%81%B0%E3%82%8C%E3%82%8B%E3%80%82)
値は引き渡されているのにDBに格納されない（エラー解決はしてる）

解決はしたけどわからない。。。。
今回のエラーはコメントの投稿が反映されませんでした。
下記コード

```top_page>show.html.haml
.main
  = form_for @comment , url:{controller: 'responses', action: 'create'}do |f|
    .main__consultation
      .main__consultation__title
        お悩み一覧
      .main__consultation__text
        = @toppage.contents
    .main__comment
      = f.text_area :comment, class: "main__comment__form"
      = hidden_field_tag :top_page_id, value: @toppage.id
      .main__comment__sent
        = f.submit "投稿する"
      .main__comment__text
        <コメント一覧>
      -if @comments
        -@comments.each do |response|
          .main__comment__main
            .main__comment__main__name
              = response.user.name
            .main__comment__main__form
              = response.comment
```

```responses_controller.rb
class ResponsesController < ApplicationController
  def create
    response = Response.create(response_params)
    redirect_to root_path
  end

  private
  def response_params
    params.require(:response).permit(:comment).merge(user_id: current_user.id, top_page_id: params[:top_page_id])
  end
end
```

responsesにcreate!に変更してエラーを吐かせてみました。
するとこんな感じ。
<img width="1414" alt="ace0635e27c1c6df1b452ecdf9a0c2b5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653208/0393e335-c2a2-145d-af1e-fe292a6b5843.png">

バリデーションのエラーってことですよね？
モデルは確認して大丈夫そうだったので
binding.pryで覗いてみました。
<img width="1285" alt="1c9114613ef1ee01671fd82269b64fe2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653208/b5d57d27-aee4-a07c-9427-377c4fd43a2e.png">
値はしっかり入ってます。
ただこの
"top_page_id"=>"{:value=>13}"
valueに妙に違和感を感じたので、試しに外したところ。。。


**投稿できました。。。。。。**

謎です。valueも値を返すのでは？
そもそもvalueをつけるときとつけない時の差って？？？

有識者の方教えて頂けるとありがたいです。。。。
Azure Cognitive Searchのスキル言語設定


## 概要

日本語のデータに対してAzure Cognitive Searchのスキルを利用したいときはまりポイントがあったので備忘録

## はまりポイントについて

Azure Portal上のデータのインポートからスキルを設定する際、Analyzerという項目がありますが、こちらを日本語でセットしても、キーフレーズ抽出などがうまくいかない場合があります。



<img width="818" alt="00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b3026194-64ac-4962-7187-5778f0ab95c2.png">

## 対処方法

スキルセットのjson定義を確認してください。  
default Langageがenとなっていますので、jaに変えてあげることで、適切なCognitiveスキルを利用してくれます。


### 画面参考

概要から対象のスキルセットを確認します。
<img width="557" alt="01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/4a040d04-bc80-1c5d-2cba-64c3959827b0.png">


json定義を確認すると、キーフレーズ抽出のスキルの定義で言語がenになっています。

<img width="495" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/bf8a5f3d-7612-9246-9d2d-da6f80f81647.png">



## 参考リンク

[組み込みのスキル](https://docs.microsoft.com/ja-jp/azure/search/cognitive-search-predefined-skills#built-in-skills)
【javascript】新しい配列メソッド

こちらの記事は以下の書籍を参考にアウトプットとして執筆しました。

[入門JavaScriptプログラミング](https://www.amazon.co.jp/dp/479815864X?tag=shoeishacom-22)

#Array.fromで配列を作成する
##argumentsオブジェクトは配列ではない
arugumentsは配列ではなく、配列風のオブジェクトである。
>配列風とは、配列のようにlengthプロパティを持っていて、展示アクセスができ、forループによる処理もできるオブジェクトのこと

以下のコードはargumentsが配列でないためにエラーになる

```javascript
function avg(){
  const sum=arguments.reduce(function(a,b){
    return a+b;
  })
  return sum/arguments.length;
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/dp/479815864X?tag=shoeishacom-22)

##reduce

```javascript:構文
arr.reduce(callback( accumulator, currentValue[, index[, array]] )[, initialValue])
```

|callback引数|説明|
|---|---|
| accumulator |callback値を蓄積する|
| currentValue |現在処理されている配列の要素|
| index |現在処理中の配列要素のインデックス。initialValueが指定されている場合は0から。そうじゃないなら1から|
|array|reduce()が呼び出された配列|

|引数|説明|
|---|---|
|initialValue|callbackの最初の呼び出しの最初の引数として使用する値|

>出典：[Array.prototype.reduce()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)

##配列風を配列に変換する
Array.fromの目的は配列風を配列に変換することで、配列風とはlengthプロパティを持つオブジェクトのこと
0からlengthまで適切なインデックス位置におかれ、文字列ではlengthプロパティに加えて、各文字のインデックスを示す数値のプロパティがある。このため文字列でArray.fromを呼び出すと文字の配列が返される。
これを使ってargumentsも配列にする。

##NodeListを配列にする
document.querySelectorAllなどのDOMノードリストを返すようなオブジェクトでも配列に変換できる。
というかlengthプロパティを持つオブジェクトであれば何でもうまくいく
#参考
[入門JavaScriptプログラミング](https://www.amazon.co.jp/dp/479815864X?tag=shoeishacom-22)
ハッシュ（hash）

#keyの取り出し方
```ruby
h = {"apple" => "red"}

h.keys #=> ["apple"]

h.keys[0] # => "apple"
```

#flatten（多次元配列の平坦化）
```ruby
a = [1, [2, [3, [4, 5]]]]

a.flatten(1) #=> [1, 2, [3, [4, 5]]]
a.flatten(2) #=> [1, 2, 3, [4, 5]]
a.flatten(3) #=> [1, 2, 3, 4, 5]
a.flatten    #=> [1, 2, 3, 4, 5]
```

#merge(ハッシュの結合)
```ruby
h1 = {"red" => "apple"}
h2 = {"red" => "tomato"}
h1.merge(h2) #=> {"red"=>"tomato"}
h2.merge(h1) #=> {"red"=>"apple"}
```
上のように、キーが同じ場合、引数のハッシュの値で上書きされてしまう。
mergeは下のようにブロックを受け取ることができ、キーが重複した時の挙動を指定することができる。

```ruby
h1 = {"red" => "apple"}
h2 = {"red" => "tomato"}
h1.merge(h2){|key,h1v,h2v| "#{h1v}" + "," + "#{h2v}"}
#=> {"red"=>"apple,tomato"}
```

#key? , has_key?(キーの存在を確かめる)

```ruby
h = {"red" => "apple"}
h.key?("red")     #=> true
h.has_key?("red") #=> true

h.key?("blue")    #=> false
h.has_key?("blue")#=> false
```
Flutterで基礎代謝計算するappを作ってみた

# appのスクショ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528657/8f52e166-0650-2646-aa75-5f7861c69cb4.png)

# ソースコード
https://github.com/takahigu322/basal_metabolism

# 学んだ事
## TextFieldで入力した文字列を、基礎代謝を計算するために整数に変換したい。
```main.dart
onPressed: () => setState(
   () {              
        _weight = double.parse(_weightController.text);
        _height = double.parse(_heightController.text);
        _age = int.parse(_ageController.text);
     }
                       
```

`型.parse()`で型変換を行った。TextFieldで値を操作するTextEddingControllerがString型なのでなんとかして整数に変換したかった。

## Textで値を出力するためにString型に変換
```main.dart
Text("あなたの基礎代謝は" +
 (((13.397 * _weight + 4.799 * _height - 5.677 * _age + 88.362) * base_number) .round() / base_number) 
.toString() + "(kcal)です"),
```
TextがString型なので`(計算式).toString()`で文字列に変換した。

# 終わりに(自分用)
dartのキャストが意外と時間がかかった印象なのでメモとして残しておく。テキストが入力されなかった場合など実装してないところがあるのでそこら辺を書いていこうと思う。
GatsbyでSCSSをMixinする方法

Gatsby.jsを使ってSCSSをMixinするときに設定したことをメモ

# やりたかったこと
Scoped Styleにmixinで定義したcssをincludeで読み込ませたかった

# mixinのファイル例
```src/assets/scss/foundation/_mixin.scss
// flexbox
@mixin flexbox($wrap: nowrap, $align: stretch, $justify: center) {
  display: flex;
  flex-wrap: $wrap;
  align-items: $align;
  justify-content: $justify;
}
```

# SASS/SCSSの設定
```
$ yarn add node-sass gatsby-plugin-sass
```

```gatsby-config.js
module.exports = {
     --- （中略） ---
plugins: [
    {
      resolve: `gatsby-plugin-sass`,
      options: {
        data: `@import "./src/assets/scss/foundation/_mixin.scss";`
      },
    }
     --- （中略） ---
```

# Scoped StyleでMixinを使うとき
以下はgatsby-starter-defaultを使ってプロジェクトを作成したものに対して、index.jsでScoped Styleを使いたい場合の例

```src/pages/index.module.scss
.hoge {
  @include flexbox(nowrap, normal, center);
}
```

```src/pages/index.js
import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

import Style from "./index.module.scss" // 追加

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <h1>Hi people</h1>
    <div className={Style.hoge}> // 追加
      <p>Welcome to your new Gatsby site.</p>
      <p>Now go build something great.</p>
    </div>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link> <br />
    <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
  </Layout>
)

export default IndexPage
```

スタイルを当てたDivが中央揃えされています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202761/717fce18-a6f2-1e14-8cc8-f7deae87d333.png)
Symfony4でAuth0の認証を利用する

ちょっと前にSymfonyでAuth0を使ってみた時、情報が見当たらなくて苦戦したのでまとめ。

# Auth0とは

認証基盤プラットフォームです。
ユーザーDB, メール認証, パスワード忘れたユーザー向け再発行, 管理者向けユーザー管理画面…みたいな「よくあるユーザー機能」を提供してくれます。

https://auth0.com

# SymfonyでAuth0を使う

## Auth0でSymfonyにログインする

Auth0のユーザー情報を使い、Symfonyのfirewallを通るセッションクッキーにログインをさせたい場合は、HWIOAuthBundleを使います。
https://github.com/hwi/HWIOAuthBundle
OAuth(OpenID)を使って実現されています。

Auth0の公式のブログ記事
https://auth0.com/blog/creating-your-first-symfony-app-and-adding-authentication/#Aside--Using-Auth0-with-Symfony
の通りに設定するだけです。

ログインしようとするとAuth0に飛び、Auth0でログインするとSymfonyで作ったアプリケーションにもログインしている状態にさせることができます。


## Auth0のトークン（JWT）を使ってSymfonyのAPIを認証する

Symfonyのfirewallを通るセッションクッキーでログインしてなくてもAuth0のJWTをAuthorizationヘッダに含めてリクエストが来たら、ログインしているとみなして処理したい場合は、Auth0JWTAuthBundleを使います。
https://github.com/auth0/jwt-auth-bundle

フロントエンドがAuth0のSDKを使った完全なシングルページアプリケーション（またはAuth0のSDKを使ったスマートフォンやタブレットのアプリ）で、SymfonyはAPIのみ担当するときにおすすめです。フロントエンドやネイティブアプリでAuth0のSDKを使ってログインしたら得られるJWTを使ってSymfonyのAPIにアクセスすると、ログインしている状態として判定させることができます。

こちらも公式のサンプル通りに設定することで一応使えるのですが、Symfony4.4だとdeprecation noticeが出てしまうので、ドキュメントに載ってないGuardの認証機構を使うのがおすすめです。

### Auth0JWTAuthBundleをGuardで使う設定方法

まず、 `config/packages/jwt_auth.yaml` と `App\Security\Auth0UserProvider` の設置は公式のサンプル通りに行います。
https://github.com/auth0-community/auth0-symfony-api-samples/blob/master/01-Authorization-RS256/app/config/services.yml#L15-L17
https://github.com/auth0-community/auth0-symfony-api-samples/blob/master/01-Authorization-RS256/src/AppBundle/Security/A0UserProvider.php

その後、 `security.yaml` にfirewallを設定するのですが、公式サンプル通りだとGuardを使うことができません。
https://github.com/auth0-community/auth0-symfony-api-samples/blob/master/01-Authorization-RS256/app/config/security.yml#L8-L12

```yaml:security.yaml

security:
  providers:
    a0:
      id:
        a0_user_provider

  firewalls:
    secured_area:
      pattern: ^/api
      stateless: true
      simple_preauth:
        authenticator: jwt_auth.jwt_authenticator

  access_control:
    - { path: ^/api/private-scoped, roles: ROLE_OAUTH_READER }
    - { path: ^/api/private, roles: ROLE_OAUTH_AUTHENTICATED }
    - { path: ^/api/public, roles: IS_AUTHENTICATED_ANONYMOUSLY }
```

Guardを使う場合の `security.yaml` 設定がこちらです。

```diff

security:
  providers:
    a0:
      id:
        a0_user_provider

  firewalls:
    secured_area:
      pattern: ^/api
      stateless: true
-      simple_preauth:
-        authenticator: jwt_auth.jwt_authenticator
+       guard:
+         authenticators:
+           - jwt_auth.security.guard.jwt_guard_authenticator

  access_control:
    - { path: ^/api/private-scoped, roles: ROLE_OAUTH_READER }
    - { path: ^/api/private, roles: ROLE_OAUTH_AUTHENTICATED }
    - { path: ^/api/public, roles: IS_AUTHENTICATED_ANONYMOUSLY }
```
[react]nextjs関連のメモ

# nextjs関連で学んだことをメモ
現在nextjsの勉強をしているので覚えておいた方が良さそうなところや、
仕組みが不明なとこなどをメモがわりに残しておく。

## ページのルーティング
nextjsをなんとなく使っていたが、どういうルールでルーティングができてるのかわからなかった。
nextjsのディレクトリは

```
pages/
  - index.js
  - sample/
    - index.js
    - show.js
```

このような構成になっているが
pages/index.jsは```localhost:3000/```,
pages/sample/index.jsは```localhost:3000/sample/```,
pages/sample/show.jsは```localhost:3000/sample/show/```
という風にpagesディレクトリに存在するファイルからエクスポートされたコンポーネントがルーティングになるらしい。

sample/index.js

```
export default function Sample() {
  return <h1>sample</h1>
}
```

localhost:3000/sample/にアクセスすると確認できた。


## プリレンダリングとは
まだ調査中。
(*詳しい方いたら補足して頂けると助かります。)

### プリレンダリングの2つの形式
#### 静的生成（Static Generation）
本番にビルドしたタイミングでhtmlを生成しておき、ユーザーのリクエストに応じて生成されたhtmlを再利用して表示する。

#### サーバサイドレンダリング（SSR）
ユーザーからのリクエスト毎にhtmlが生成される。

### ページ毎に設定
nextjsでは
このページは静的生成、このページはサーバサイドレンダリングのように
ページ毎に設定ができる。
基本は静的生成の方がいい。
ただ、SSRの方がいい場合もあるので注意。