OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinで書く続中央値コンポーネント

#度数分布の中央値
前回作った中央値コンポーネントのJarファイルに「度数分布の中央値」コンポーネントを追加します。
「Median of frequency distribution」というらしいです。
階級に幅が無いパターンです。

#コンポーネントの仕様

* 中央値コンポーネントとほぼ同じ作り。
* レコードのフィールドは名前と値の２つをプロパティで指定します。
* 計算した中央値と名前をreadonlyプロパティへ出力します。

#作り方
IntelliJの前回作ったプロジェクトへファイルを追加します。

* com.asteria.sample.kotlin.component.MedianComponent2.kt：コンポーネント本体
* Median2.png：アイコンファイル
* Median2.html：ヘルプファイル
* ComponentDefine.xconf：Medianで作成したファイルへ追記
![project.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180278/87cbe827-fe5b-28fb-b499-7df81549db61.png)

#コード
コードも前回作った中央値コンポーネントとほぼ同じなので、コピーします。

例によってexecuteメソッド内が処理の全てです。

* 1回レコードを回して値のフィールドから全数を取得します。
* 2回目にレコードを回して中央値を含む値を探します。
* 中央値を含むレコードの名前を取り出します。

```kotlin
    override fun execute(p0: ExecuteContext?): Boolean {
        //対象の値フィールドインデックスを取得
        val targetValueFieldIndex: Int = getFieldIndex(_propValueField)

        //レコードのフィールド情報取得
        val record = inputConnector.stream.record
            ?: throw ComponentExceptionByMessageCode(this, INPUT_STREAM_IS_EMPTY)

        //レコード全部読み
        var allValue: Double = 0.0
        do {
            val fieldValue = record.getValue(targetValueFieldIndex)
            if (fieldValue.isNumberType && !fieldValue.isNull) {
                allValue = allValue + fieldValue.doubleValue()
            }
        } while (record.next())

        //中央値をプロパティへ設定
        val center: Double = allValue / 2
        _propMedian.setValue(center.toString())

        //はじめに戻る
        record.first()
        allValue = 0.0

        do {
            val fieldValue = record.getValue(targetValueFieldIndex)
            if (fieldValue.isNumberType && !fieldValue.isNull) {
                allValue = allValue + fieldValue.doubleValue()
                if (allValue > center) {
                    //中央値名をプロパティへ設定
                    _propMedianName.setValue(record.getValue(getFieldIndex(_propNameField)).strValue())
                    break;
                }
            }
        } while (record.next())

        passStream();
        return true
    }
```

kotlin風のコードってどんなでしょう？なにやら違いそうな気もしますが・・・
全コードは[github](https://github.com/ArimitsuIshii/MedianComponent)にコミットしておきました。

#ビルド
IntelliJでプロジェクトをビルドすればJarファイルの出来上がりです。

#フローで確認
出来上がったJarファイルをサーバー、デザイナーへ追加してフローを作成します。

アイコンが前回作った中央値コンポーネントに似ていますが、こっそり「２」と書いてあります。
![flow1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180278/d94d88d3-d241-aac9-e64f-5f3bcb33ba5b.png)
入力レコードは3フィールドです。

* 通番
* 名前
* 個数

1番目、100円の商品が5個あります。といった感じです。
![flow2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180278/9bbe7a8d-036b-5f62-2c4e-766e4135e76b.png)
Mapperコンポーネントのマッピング内容
![flow3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180278/720e7d7d-a8a9-667c-7818-703720cc70b2.png)
実行結果は、30個目を含む400円が中央値ということになりました。
![flow4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180278/e4d59837-487c-99c0-63e9-47a4d033cfa4.png)

#最後に
Kotlinでコンポーネントを作るのは楽です。しかし、当然ですがKotlin風にコードを書くにはKotlinに慣れる必要があり一長一短ですね。

#参考文献
[中央値と最頻値](http://www.wwq.jp/stacalcul/median2.htm)
【Day10】積み上げ日記

＜予定＞
○Progate
- HTML＆CSS 学習コース（中級）18ページまで
- HTML＆CSS 道場コース（初級）全部

＜内容＞
○Progate
- HTML＆CSS 学習コース（中級）17,18p
　- フッターのレイアウト
　- ヘッダーの常に固定しよう
- HTML＆CSS 道場コース（初級）
　- トップ部分を作ろう

＜計画通り進んだか？＞
進んでいない。
●理由
・時間が取れていない。
・道場コースで悩んでいる時間が多く、答えが結果的にわからない
→目的は”Progateの中身をできるようになる”ではなく、”HTML＆CSSを自分で作成できるようになる”なので、わからなければちっぽけなプライドは捨てて答えをコピペする。

＜間違えた箇所＞
○文章の一部だけ色を変える
→spanタグを使って囲う。

○クラス名は自分の好きな名前ではなく、定めるべき？

＜学んだこと＞
○ヘッダーの固定：position:fixed

○表示の優先順位指定：z-index 整数値
QlabでPJLinkプロジェクターを制御する

Qlab4からPJLink対応のプロジェクターを操作する
#PJlinkとは
PJLinkはプロジェクターやディスプレイをメーカーを問わず操作・管理するための統一規格です。
>[JBMIA PJLink](https://pjlink.jbmia.or.jp/)

#PJLinkの仕様
詳細は[PJLink仕様書](https://pjlink.jbmia.or.jp/data_cl2/PJLink_5-1.pdf)を参照されたい。
<dl>
  <dt>プロトコル</dt>
  <dd>TCP</dd>
  <dt>ポート</dt>
  <dd>4352</dd>
</dl>

#Qlab4でPJLink扱う
Qlab4では直接TCPコマンドを送信できないため、いくつかの方法を考える。

- scriptキューでターミナルからTCPコマンドを送信(Apple Script)
- scriptキューでPJLinkを制御できる別のアプリをApple Scriptで操作

## ターミナルからTCPコマンドを送信する
以前のMac OSではターミナルでtelnetが標準で使えたため、それを利用して制御していました。

```applescript
set EscapeChr to ASCII character 29
set hideMe to false

tell application "Terminal"
	if (count of the windows) is less than 1 then
		tell window 1 to do script ""
		delay 1.0E-5
		set hideMe to true
	end if
	
	do script "telnet 192.168.0.102 4352" in window 1
	delay 1.0E-5
	do script "%1POWR 1" in window 1
	delay 0.4
	do script "" in window 1
	do script EscapeChr & "quit" in window 1
	
	if hideMe then tell window 1 to set miniaturized to true
	delay 1
	tell application "Terminal" to quit
end tell
```
> 参考:[Google フォーラム [QLab] Script, Terminal and PJLink](https://groups.google.com/forum/#!topic/qlab/INxta94f3NE)

High Sierraになってからtelnetが標準で使用できなくなったため、この方法はすでに使っていません。

##PJLinkを制御できる別のアプリを操作
MacにはApple Scriptという言語が標準で備わっています。
Apple Scriptを介することで、他のアプリケーションに対して直接操作することが可能です。
（詳細は他のサイトを参照されたい）

ここでは、『Projector Manager』というアプリケーションを使用します。

> SIGMASIX - [Projector Manager](http://www.sigmasix.ch/projectormanager/) ([Mac App Store](https://apps.apple.com/jp/app/projectormanager/id950244656?mt=12))

![スクリーンショット 2020-03-14 16.18.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/d348e08f-f818-97bc-a784-76a7cafb322a.png)
アプリケーション自体の使い方は、割愛します。
プロジェクターを２台設定した画面が上記の画面です。


Mac OSの「スクリプトマネージャー」というアプリを開くと、Apple Scriptに対応したアプリケーションが表示され、対応したScriptの記述が表示されます。
![スクリーンショット 2020-03-14 16.09.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/bcf1b4c1-13f6-8308-90ea-27941c24aadf.png)
この記法にそって、Qlab4上でスクリプトキューを作成します。
たとえば、電源をオンするキューは次のようになります

```applescript
tell application "ProjectorManager"
	PowerOn 1
end tell
```
`tell application`　→　アプリケーションを呼び出し
`PowerOn 1`　→　実際にする処理（スクリプトマネージャーで調べたスクリプト）
なお、PowerOn命令のあとの[1]は、Projector Manager側で設定した1台目（前の図で言うと、192.168.0.102の機器）を指します。
`end tell`　→　呼び出し終了

### 実際のQlabのキューリスト
![スクリーンショット 2020-03-14 16.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601755/b7b5c4f3-8b07-c5fa-472d-681b95a3f19c.png)


実際に現場で使うことを想定したキューリストは上のようになります。
Power onやoffはキューリストから離したほうが安全かもしれません。
私がキューを組む場合はリストには入れておいて、<em>電源の操作が必要なとき以外はArmedのチェックを外しておきます。</em>
それぞれのスクリプトは先程のスクリプトの`PowerOn`の部分を書き換えただけになります。

スクリプトの実行から実際プロジェクターの操作が完了されるまでに多少のタイムラグがあるため、
`av unmute`キューと映像のスタートキューは手動にしていますが、映像の再生終了後は自動的に`av mute`キューをgoしています。
【Day9】積み上げ日記

＜予定＞
○Progate
- HTML＆CSS 学習コース（中級）18ページまで

＜内容＞
○Progate
- HTML＆CSS 学習コース（中級）16ページまで

＜間違えた箇所＞
○position: relative → position: absolute の仕組みがわからない。
→起点を変えること！詳しくはツイッターで

○HTMLの構成がclass要素が入ることによって、複雑で混乱する。>>全体の構成図を頭の中に入れる。

＜学んだこと＞
○相対的な大きさの指定：width / height  px→％

○プロパティ指定の基準地点を指定：position: relative

○プロパティ同士を重ねて表示：position: absolute;

○inline block

○ボックスに影をつける：box-shadow

○クリックした時に変化を指定：active
Qiitaの「いいね」が「LGTM」になって思ったこと

2020年3月，Qiita の「いいね」ボタンが，突然「LGTM」(Looks Good To Me)に変わった．

- [Qiitaの「いいね」が「LGTM」に変わります - Qiita Blog](https://blog.qiita.com/like-to-lgtm/)

思ったことをメモしておく．

# 機能の名称変更における注意点

- Twitter でも Favorite ボタンが Star になったり Like になったりといった過去があるので，ボタンの意味が若干変わる程度であれば，さして問題はない．事前にテストも行っていたので，ある程度エビデンスと周囲の反応を集めた上での実装になっている．
- ただ，「LGTM」と「いいね」は（少なくとも日本語圏では）それなりに違う意味で用いられているケースが多いと思う．
文脈にもよるが，LGTM は「自分的にはOK」の意味で使うほうが一般的ではないだろうか．
- 「To Me」の部分が引っかかるのか，今回の変更にはかなり批判がある．わざわざQiita内のあらゆるLGTMをいいねに戻す拡張機能を作成する人が複数あらわれるほど．
- 機能の追加でも削除でもなく，ガワを別物にすり替えてしまったので，Twitterでたまに聞く「動物画像投稿アカウントをフォローしたはずが，広告宣伝アカウントにすり替わっていた」という事案のような気持ち悪さを（意味論的もしくは道徳観念的に）感じてしまう人もいる
- しかも，これまで蓄積してきたデータについて，歴史的後方互換性が保たれていないとも言える（項目名の違うレコードを合算することになる）


誰かがコメントしていたように
**あまり細かく分類すると破綻するので，「★」や「+1」みたいな，抽象度の高い記号が妥当かもしれない．**

# サービスが持つ文化について 継続的に啓発する必要性

- [Qiitaのランキングの最初の設計者としての「いいね」の設計と、「LGTM」は下においてほしいという話 - mizchi's blog](https://mizchi.hatenablog.com/entry/2020/03/13/015359)

> まず、Qiita には最初にストックがありました。これは「後で読む」ということを意図した機能です。なので、ストックは記事トップにありました。

- 今回の騒動をきっかけに，当時の開発者が設計の意図を書いた．
私はここで，ストック機能の本来の意味を知った．

- 私は今まで，
**・いいね：シェアしたい記事に押す**
**・ストック：いつか読む記事，何度も読む記事**
という使い分けをしてきた．

- Qiitaを使い始めた頃は，
**・いいね＝読んだときに相手に送る評価＝個人的なやりとり**
**・ストック＝保存すべきもの＝共有すべきもの**
と考えていたが，

- 「いいね」がマイページで公開されるのに対し，「ストック」は非公開であることに気付き，
**・いいね：シェア**
**・ストック：ブクマ（永続 or 一時的）**
という使い分けに落ち着いた．

- しかしそれでも，**「ストック」が公開されないことへの違和感**は残った．
また**「いいね」が，その機能（公開性）を無視して乱用されている**のも気になっていた．

- 今回の件で，「ストック」が「後で（すぐに）読む」を意図していたことが分かり，納得した．
また，「いいね→LGTM」の変更が，評価機能が適切に運用されることを意図していることにも納得した．

Webサービスがユーザーの活発化によってその在り方を変化させるものである以上，**当初想定していなかったものについても**，ある程度，意義が認められるものは，**その存在を許容する**ほうが，ハッカー的で楽しい（Qiitaは，ポエム／哲学書を許容し得るのではないか）
しかし，サービスが**本来持っていた意義を見失うことは避け**たい．であれば，そのための**使い方を定期的に伝え続けて**いかなければならない．

# まとめ

機能の一貫性に注意しつつ，文化の変容性（不易流行）を考慮して運用・カイゼンしよう
CentOS7.7 に ImageMagick-6.2.x 系をインストールする


- 結論だけ述べると zlib のバージョンが合わずに無理で、ImageMagick バージョンアップを行った。

古いアプリケーションで、 CentOS 5.11 と ImageMagick-6.2.8-8 が使用されているので、
それを CentOS 7 にバージョンアップを行う。

```bash
curl -L https://sourceforge.net/projects/imagemagick/files/old-sources/6.x/6.2/ImageMagick-6.2.8-8.tar.gz/download -o ImageMagick-6.2.8-8.tar.gz
tar zxf ImageMagick-6.2.8-8.tar.gz
cd ImageMagick-6.2.8-8

./configure --prefix=/usr/local/
make
```

下記エラーが出て、zlib バージョンを下げるかしないと無理そうだったので、諦めました。

```text
/usr/include/zlib.h:1296:21: note: expected 'gzFile' but argument is of type 'struct FILE *'
 ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
                     ^
magick/blob.c:2292:13: error: 'FILE' has no member named 'have'
           c=gzgetc(image->blob->file);
             ^
magick/blob.c:2292:13: error: 'FILE' has no member named 'have'
           c=gzgetc(image->blob->file);
             ^
magick/blob.c:2292:13: error: 'FILE' has no member named 'pos'
           c=gzgetc(image->blob->file);
             ^
magick/blob.c:2292:13: error: 'FILE' has no member named 'next'
           c=gzgetc(image->blob->file);
             ^
```

ImageMagick-6.9.9 をインストールする


```bash
curl -L https://sourceforge.net/projects/imagemagick/files/im6-src/ImageMagick-6.9.9-37.tar.gz/download -o ImageMagick-6.9.9-37.tar.gz
tar zxf ImageMagick-6.9.9-37.tar.gz
cd ImageMagick-6.9.9-37

./configure --prefix=/usr/local/
make
make install
ldconfig
```

インストール後の確認

```
[root@centos7 ~]$ identify --version
Version: ImageMagick 6.9.9-37 Q16 x86_64 2020-03-05 http://www.imagemagick.org
Copyright: © 1999-2018 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC OpenMP
Delegates (built-in): bzlib jng jpeg lzma png xml zlib
```
【Day8】積み上げ日記

＜予定＞
○Progate
- HTML＆CSS 学習コース（中級）18ページまで
- HTML＆CSS 道場コース（初級）5ページまで

＜内容＞
○Progate
- HTML＆CSS 学習コース（中級）10ページまで

＜間違えた箇所＞
○画像の挿入
img src = “url” 

○画像のクラス名をつける
img class=“...” src 

○transition: all 0.5s ; で”s”をつけ忘れた。

＜学んだこと＞
○透明度の指定（背景のみ）：rgba

○要素の浮かせ方指定：float

○アニメーションの指定：transition

○行の高さ：line-height

○文字の太さ：font-weight

○ボタンを作る：aタグをインライン要素→ブロック要素にして、displayをblockに指定する。
react入門 -JSXとstateについて-

# 始めに
モダンなフロントエンド開発において世界的に利用されているreact。
昨今、日本ではnuxtが人気を得ていますが、今後どちらを利用する上でもreactの思想はフロントエンドの知識として欠かせないものだと思います。 今回はreactを触ったことがない人を対象にreactの段階に分けて解説をしていきます。

# Reactとは
UIをレンダリングするためのJavaScriptフレームワークです。
Facebookが開発し、オープンソースで公開されています。

# どんな特徴があるのか
reactではJSXと呼ばれるHTMLとJSを組み合わせた言語拡張を用いてコードを書くことができます。

```javascript
class ShoppingList extends React.Component {
  render() {
    return (
      <div className="shopping-list">
        <h1>Shopping List for {this.props.name}</h1>
        <ul>
          <li>Instagram</li>
          <li>WhatsApp</li>
          <li>Oculus</li>
        </ul>
      </div>
    );
  }
}

// Example usage: <ShoppingList name="Mark" />
```
以下、引用:https://ja.reactjs.org/tutorial/tutorial.html

これにはいくつかのメリットがあります。

- javascriptの中でHTMLを使うことができる。
- javascriptの機能を最大限利用できるのでコードの可読性が高い。
 
JSXで気をつけなければならないのは、一つの要素しか返さないことで。
複数の要素を利用する場合、それらをネストして一つの要素としてまとめて返却する必要があります。
上のコードでも最終的にdivでネストして一つの要素としてreturnしています。

# state
UIの書き換えに必要なComponentに値を記憶させるためのデータ。
React.Componentを継承したクラスのconstructorの中で定義します。
表示は
this.state.{定義したキー}
で行うことができます。

```javascript
class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }

  render() {
    return (
      <button
        className="square" //JSでclassは予約語のため、class属性を利用するにはclassNameと書く必要がある。
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.value}
      </button>
    );
  }
}
```
値を書き換える時はstateを直接書き換えずに、setStateを呼び出して値を書き換えます。

```javascript
this.setState({value: 'X'}
```

setStateを呼び出すたびにrenderが呼ばれてUIが再描画されます。
データベースとは [初心者向け][シンプルに]

#データベースとは
データベース（略してDB）とは、大量のデータが入っている箱のようなもの。
（後からデータの追加、削除、検索をしやすい形に整理してある）

##データベースの種類(型)
データベースには
**「階層型」「ネットワーク型」「リレーショナル型」**
の3つがある。
単にデータベースと言った場合は**リレーショナル型**をさすことが多い。（圧倒的に広く使われているそう）


##リレーショナルデータベース（RDB）とは？
　→行と列からなる「表」でデータを管理するデータベース。↓
<img width="331" alt="スクリーンショット 2020-03-14 15.02.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587428/280f4bcf-8f38-8180-985c-3b091c874a9c.png">
↑こんなイメージですかね。

  - データの重複を避けられる
  - 検索能力が高い
  - [SQL](https://qiita.com/freedomdom/items/1311b07a256d7322f353)を用いたデータのアクセスが可能
 （[SQL](https://qiita.com/freedomdom/items/1311b07a256d7322f353)とはデータベースとやり取りするときに使う言葉）

 等の特徴がある。


##どんなリレーショナルデータベースがあるか
代表的な製品は、
MySQL、Oracle、MS Access、MS SQL Server、DB2、PostgreSQLなどなど
EPUBファイルからMOBIファイルに変換する (macOS)

EPUBファイルを Kindle で読むためには EPUBファイルから MOBIファイルに変換する必要があります。今までは Amazon から提供されている KindleGen というコマンドラインツールを使用することで変換できたのですが、最近 macOS Catalina (10.5) で実行したところ以下のようなエラーが出て MOBIファイルの出力に失敗しました。

```bash
$ brew cask install kindlegen
$ kindlegen example.epub
-bash: /usr/local/bin/kindlegen: Bad CPU type in executable
```

このエラーですが、どうやら macOS Catalina (10.15) が 32bit をサポートをしていないために起こるエラーのようです。何か解決する手段はないかなと調べてみたところ、同じく Amazon が提供する Kindle Previewer 内にも KindleGen が含まれており、こちらを代わりに使用することにしました。

Homebrew から Kindle Previewer をインストールして、中の `kindlegen` に対してシンボリックリンクを貼ります。もし既に KindleGen がインストールされている場合、事前に KindeGen をアンインストールする必要がありますのでご注意ください。

```bash
$ brew cask install kindle-previewer
$ ln -s /Applications/Kindle\ Previewer\ 3.app/Contents/lib/fc/bin/kindlegen /usr/local/bin/kindlegen
```

すると以下のように、`kindlegen` を使って EPUBファイルから MOBIファイルへの変換ができるようになります。

```bash
$ kindlegen example.epub

*************************************************************
 Amazon kindlegen(MAC OSX) V2.9 build 0000-kdevbld
 A command line e-book compiler
 Copyright Amazon.com and its Affiliates 2015
*************************************************************

...
```
AWS Cloud9上でPostgreSQLをソースからインストール

### 概要
　AWS Cloud9 上でpostgreqlとdeviseを使ってRailsアプリを開発をしようとした際に、
postgresqlのバージョンが古いと怒られたのでやってみたことをメモ。

- 環境
    - AWS Cloud9
        - Amazon Linux AMI release 2018.03
    - postgre
        - postgres (PostgreSQL) __9.2__.24
    

### ソースからコンパイル
下記を順に実行
一応コンパイラからインストール

```
$ sudo yum install -y gcc readline-devel zlib-devel
$ wget https://ftp.postgresql.org/pub/source/v10.4/postgresql-10.4.tar.gz
$ tar -xf postgresql-10.4.tar.gz
$ cd postgresql-10.4
$ ./configure
$ make -C src/bin
```
ここでエラーが出るので`Makefile`内を下記のように修正する。

```
$ make -C src/bin
make: Entering directory `/home/ec2-user/postgresql-10.4/src/bin'
Makefile:14: ../../src/Makefile.global: No such file or directory
make: *** No rule to make target `../../src/Makefile.global'.  Stop.
make: Leaving directory `/home/ec2-user/postgresql-10.4/src/bin'
```
`Makefile`の14行目の`'Makefile.global'`のところが間違いで
`'Makefile.global.in'`に訂正すると無事に`make`できます。そのまま続きへ、

```
$ sudo make -C src/bin install
$ make -C src/include
$ sudo make -C src/include install
$ make -C src/interfaces
$ sudo make -C src/interfaces install
$ make -C doc
$ sudo make -C doc install
```
以上でエラーが出なければインストールは完了。
今回インストールされた場所は`/usr/local/pgsql/bin/psql`なのでそこにパスを通します。

```
$ vi ~/.bash_profile
```
として最後の行に

```
export PATH="/usr/local/pgsql/bin:$PATH"
```
を追加して保存。

```
$ source ~/.bash_profile
```
これで完了。

### バージョンを確認する

```
$ psql --version
psql (PostgreSQL) 10.4
```
__10.4__になってます。

因みに、これをアンインストールするには`make`した場所で、

```
$ make uninstall
```

とすると消える。


### 参照
[How To Completely Uninstall PostgreSQL](https://kb.objectrocket.com/postgresql/how-to-completely-uninstall-postgresql-757)
[Installing PostgreSQL Client v10 on AWS Amazon Linux (EC2) AMI](https://stackoverflow.com/questions/49573258/installing-postgresql-client-v10-on-aws-amazon-linux-ec2-ami)
[make installしたソフトウェアをアンインストールする](https://leico.github.io/TechnicalNote/Linux/make-uninstall)
古いrubyがMacにインストールできなくて困っているあなたへ

# これ何

古いruby（2.4以下のバージョン）がMacにインストールできなくて困っているあなたへ送るやつです。

## なぜ古いrubyでビルドエラーが発生するのか

古いrubyではopenssl 1.1系しかない環境だとビルドエラーになる。
しかし、openssl1.0系をインストールしようとしても[ここ](https://qiita.com/kunit/items/0aef44d5e522abde1f9c)に書いてある通り、openssl 1.0系はEOLを迎えたのでhomebrewで素でインストールする事ができなくなっている。

## どうするの？

以下のコマンドで無理やりインストールする。

```
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/64555220bfbf4a25598523c2e4d3a232560eaad7/Formula/openssl.rb
```

上記のコマンドの実行で、 `/usr/local/Cellar/openssl/1.0.2t` に OpenSSL 1.0.2t を入れることはできる。

さらにこんな感じでシンボリックリンク付け替えておかないとエラーになる。

```
$ cd /usr/local/opt
$ rm openssl
$ ln -s ../Cellar/openssl/1.0.2t openssl
```

あとはrbenvでrubyをインストールする時にこれを使えるようにしておく。

```rb
RUBY_CONFIGURE_OPTS="--with-openssl-dir=/usr/local/Cellar/openssl/1.0.2t" rbenv install 2.3.8
```

大変面倒だが、bundle installする時にもopensslを参照しているので該当のリポジトリを触っている間は古いopensslを使いつづなければいけない・・・
bundle installが終わってサービスを起動したらopensslのシンボリックリンクを戻しておく。

```
$ cd /usr/local/opt
$ rm openssl
$ ln -s ../Cellar/openssl@1.1/1.1.1d openssl
```

## そもそも・・・

本来であれば、EOLを迎えている物をインストールしようと試みること自体が良くない話なのだが、止むに止まれぬ事情で必要になる人もいると思ったので記録を残しておくことにしたのであった。
【大量のGmailを一括下書き作成】スプレッドシートから管理するスクリプトを書いたので使ってほしい。

# Gmailで大量の送信先にメールを送るときにスプレッドシートで管理するスクリプトを書いたので使ってほしい。

スクショはこんな感じ。

<img width="944" alt="スクリーンショット 2020-03-14 15.29.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/f80526fc-b107-853b-81c6-9557e237bed2.png">

`下書き作成` ぼたんポチすると

<img width="1351" alt="スクリーンショット 2020-03-14 15.32.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/4ff9744d-3480-bc82-de24-05ae5d10a056.png">

Gmail側に下書きが保存されます。目で目視してから使ってくれ。

## FAQ

- BCCじゃだめなんですか？
    - Toでたくさん贈りたいときもあるよね…？？
- え、もしかして ひとつひとつの宛先ごとにメール作ってくれるの？
    - そうです！
- プログラムから実行すると、間違ったときに不安！！！
    - 大丈夫です。下書き `GmailApp.createDraft(to, subject, body)` で作ってます！
    - 自分の目で確認してから、Gmailから送信ボタンぽちぽちしてください。
- 悪いことに使っていい？
    - 絶対にやめてください。特定電子メール法に則って使ってください。

## 共有

ファイルを共有したので自分のドライブにコピーして使ってほしいです。
共有リクエストしないでくださいね〜

↓共有リクエストくるたびにメールきてます。

![スクリーンショット 2023-01-15 21.14.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/c6604099-920f-fc0a-1db0-3c520765e698.png)


https://docs.google.com/spreadsheets/d/1fPE17OVUx0-OBXCRTZAm-vkLn1msYerBis7rN1tMaRc/edit?usp=sharing

あ、もちろん実際に使われているコードがどんなのか見てから使ってほしいのと、Gmailから権限要求されるので適切に許可してあげてほしい。

## 実装

```javascript
/** *****************************************
[ [ '項目', '内容', 'To', 'Name' ],
  [ '件名', 'XXXXの件について', 'example@example.com', '開発室example さま' ],
  [ '書き出し', '', 'example+123@example.com', '総務 田中 さま' ],
  [ '本文', '', '', '' ],
  [ 'To欄の数', 2, '', '' ] ]
***************************************** */
const allData = SpreadsheetApp.getActiveSheet().getDataRange().getValues();

/** *****************************************
['XXXXの件について', '本文']
***************************************** */
const commonData = allData.filter(x => (x[0] === "件名" || x[0] === "本文")).map(x => x[1]);

/** *****************************************
[ [ 'tanaka@example.com', '開発室example さま' ],
  [ 'AAA@example.com', '総務 田中 さま' ] ]
***************************************** */
const toMailData = allData.filter(x => (x[2] !== "To" && x[2] !== "")).map(x => [x[2], x[3]])

function createDraft() {
  const subject = commonData[0];

  // GmailApp.createDraft(["hirao@openlogi.com", "hirao+2@openlogi.com"], subject, "body test");

  toMailData.forEach(async x => {
    console.log(x[0]);
    const to = x[0];
    const body = createBody(x[1]);
    await GmailApp.createDraft(to, subject, body);
  })
}

/**
 * @todo メッセージ本文入れたり署名欄とか拡張する
 */
function createBody(name) {
  return name + "\n\n" + commonData[1];
}

```




`下書き作成` ってボタンをスプレッドシート内のGASの関数 `createDraft` に紐づけています。


発火したら、今ひらいているページのデータを読み込みにいってメール送信するので、こんな感じでどんどんタブを追加していって、どの時はどの人たちにメールを送ったのか、そういう履歴もわかりますです。

<img width="426" alt="スクリーンショット 2020-03-14 15.30.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/531d3c33-1083-95fd-b81e-c74922b9af2d.png">


以上。

今日さくっと作ったやつですが、必要な方いたら使ってください。
express-generatorでアプリを作成したらする事

#モジュール読み込むモジュール
* express-session
* express-validator
* mysql
* knex
* bookshelf

#インストール方法
```bash
npm install --save モジュール
```

#app.jsの追記
```javascript
var bodyParser = require('body-parser');
var session = require('express-session');
var validator = require('express-validator');

app.use(validator());

var session_opt = {
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: false,
  cookie: {maxAge: 60 * 60 * 1000}
};
app.use(session(session_opt));
```

routesの中に新しくjsのファイルを追加する場合は、上記に追加して下記も追加する。

```javascript
var hoge = require('./routes/追加したファイル名');

app.use('/パス名', hoge);
```

※hoge、追加したファイル名、パス名は同じにすると分かりやすい

#参考
node.js超入門 p376
3分で分かる。MERNスタックを簡単に説明してみる

MERNスタックの仕組みと、参考になるチュートリアルを提供する記事です。本当に重要な部分のみを扱いました。

## MERNスタックとは

**MongoDB, Express, React, Node.js**の4つを使ったソフトウェアハンドル。Webアプリ開発に用いられる。仮に、**React.jsではなく、Angular.jsを使う場合、MEANスタック**となる。

MongoDB: ドキュメント志向のNo-SQLデータベース。データの作成、読み込み、更新、削除に使う。
Express: Node.jsのフレームワーク。例えば、Node.jsで一から別々のURLパスでユーザーからくるリクエストを個別に処理するのは面倒だが、Expressを使えばそれを簡易的に行える
React: Javascript製ライブラリ。単一ページWebアプリのUIを作成するUIコンポーネントを構築する。MVCモデルのVのみを担い、仮想DOMを実装することで素早いレンダリングが期待できる。仮想DOMについては説明すると長いので、ここでは省略。

> なぜ仮想DOMという概念が俺達の魂を震えさせるのか
https://qiita.com/mizchi/items/4d25bc26def1719d52e6

Node.js: サーバーサイドでも動くJavascriptってカッコイイし楽だよね、と覚えておこう。（ぇ
公式を参照すると、以下のように記載がある。
> Node.js はスケーラブルなネットワークアプリケーションを構築するために設計された非同期型のイベント駆動の JavaScript 環境です。

**スケーラブル** = 拡張性のこと。乱暴なたとえだが、1万人のユーザーでも100万人のユーザーでも、DBとのリクエスト・レスポンスがスムーズであったり、レンダリングの速度に影響が少なかったりといった、システム負荷などの拡大・拡張に応じて、柔軟に対応できるかといったものを指す。

**非同期型** = 具体的にはI/O処理を非同期で行っている。I/O処理とは、ファイルにデータを書き込む、ファイルのデータを読み込む処理のこと。
> **身近な例: GoogleMap**
**同期型**：目的地を検索する時、検索欄に目的地を記入→検索→ページが再リロード→目的地をUIに表示
**非同期型**：目的地の周辺を拡大・縮小したり、周辺のその先を見たい時にドラッグして動かすが、その時ページ全体が再リロードされることなく、部分的にリロードされ表示させている。

同期型は再リロードされている時に他のことは出来ないが、非同期型は再リロードされている最中もドラッグして地図を動かせる。ユーザー的には、非同期型の方が嬉しい（はず）。

**イベント駆動** = 対応しているイベントが発火したタイミングで初めて、実行される。ユーザが操作をしていないときは、常に待機状態でプログラムが待っている。


## 何が良いのか
乱暴だが、フルスタックエンジニアを名乗りたい人は、実はjavascriptが書ける時点で完結できてしまうよね。
本質的な部分で言うと、
１：保守性 = Javascriptで完結しているため、扱える人が多い=人依存にならない
２：拡張性 = データ構造の変化や、json形式が使えたり。柔軟に設計ができる
の２点。


## 実際の中身

<img width="822" alt="2020-03-14 15.10.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439329/1df7028c-e3ca-ad6d-ff51-b1e1bd8f27ce.png">


View(ユーザーが見える部分)を担っているのがReact。
Express は特定のHTTP - GET, POST, DELETEなど - と、そのURLパターンに対して、どの関数が呼び出されるか、を指定するメソッドと、どのテンプレートエンジンが使用されるか、を指定するメソッドを提供する。


例）何らかのデータを**送信**したいと思い、送信ボタンをクリックした場合：
送信ボタンクリック
→Reactで送信に関する関数が実行
→Expressがその関数に対する処理を実行。MongoDBに実行させたい処理を送る
→MongoDBがExpressから来た処理を実行
→完了
といった具合（ざっくり）。完了したことをクライアントに通知させる部分まで担うのがほとんどだけど省略。

例）データを**取得**したいと思い、ボタンをクリックした場合：
取得ボタンクリック
→Reactで取得に関する関数が実行
→Expressがその関数に対する処理を実行。MongoDBに実行させたい処理を送る
→MongoDBが欲しいデータを取得して、Expressに送る
→Expressがそのデータをキャッチして、Reactに送る
→ReactがExpressから受け取ったデータをViewに反映させる
といった具合（ざっくり）。

## MERNスタックを構築してみたい、という方へ
実際にどんなTutorialがあるか調べてみました。

Youtube
https://www.youtube.com/c/CleverProgrammer/videos
英語ですが。めちゃめちゃ動画あります。好きなものを見ると良いと思います。筆者はまだ触っていないです。

MERN Stack Front To Back: Full Stack React, Redux & Node.js
https://www.udemy.com/course/mern-stack-front-to-back/
英語です。有料のUdemyですが、こちらは実際に作ってみました。ReactもHooks使ったりとモダンに扱っていたため、筆者としてはオススメです。

## まとめ
実際に作成しようとなった場合、ドキュメントが少ない、そもそも日本語で書かれたMERNのチュートリアルが見つからないと色々と不安な点はあると感じますが、今は翻訳も発展しているのでドンドン一次情報から調べていきましょう。
Reactは、2019年にHooksが使えるようになってから注目が更にされていますし、Node.jsも成長期は終えていますがバリバリの現役です。それぞれ扱えて損は全くないと思うので、是非使ってみましょう。

## 参考にした資料
What is MERN Stack?
https://www.educative.io/edpresso/what-is-mern-stack
Node.jsのMVCフレームワーク「Express」の基礎知識とインストール (1/3)
https://www.atmarkit.co.jp/ait/articles/1503/04/news047.html#011
初心者向け！3分で理解するNode.jsとは何か?
https://eng-entrance.com/what-is-nodejs
3分でわかるgRPC-Web



## gRPCとは

gRPCの概要を簡単にまとめる。

- HTTP/2による高速な通信
- IDL(Protocol Buffers)でデータ構造とRPCを定義
- 多言語対応のソースコード自動生成
- Streamingを用いた双方向通信が可能

詳細は以下へ。

- [What is gRPC?](https://grpc.io/docs/guides/)

## gRPC-Webとは

gRPC-WebによってgRPC通信をWebでも使うことができる。以上！

といえればいいのだが、実際は、ブラウザの制限にあわせたプロトコルを定義している。

- [grpc/PROTOCOL-WEB.md at master · grpc/grpc](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md)

そのため、現時点だと、プロトコル間の微調整を行うためのプロキシが必要で、公式ではEnvoyを推奨していたりする。

### ブラウザの制限

前述したブラウザの制限とは、例えば以下のようなものだ。

- HTTP/2のフレーミングレイヤーはブラウザに露出されない
- ブラウザからのStreamingがまだ不十分 (WHATWG Streams)
- クライアントにHTTP/2の使用を強制できない
- クロスブラウザで動くbase64のようなテキストエンコーディングの必要性

上記により、以下のようなことがgRPC-Webでは不可能である。

- gRPCでサーバーとの「直接」通信 (Proxyを用意する必要がある)
- Client-side & Bi-directional streaming

少なくともBi-directional streamingがでできるようになればgRPC-Webの立場はかなり上がると思うので残念だ。

### メリット

現時点でのgRPC-Webのメリットは以下のようなものがある。

- クライアントからサーバーまで、一気通貫でgRPCの開発パイプラインに載せられる
- バックエンド・フロントエンド間でタイトな連携ができる
- クライアント向けの「gRPCライブラリ」を容易に生成できる

例えば、バックエンドのサービス群がgRPCで構築されている時、HTTPのレイヤーでBFFを用意する必要がなくなり、不要なAPI設計やコミュニケーションをへらすことができるのがメリットになりそうだ。

- [gRPC-Web is Generally Available](https://grpc.io/blog/grpc-web-ga/)

下の2つは、IDLベースなこととコードの自動生成により、RESTなどで「仕様書ベース」で合意を行うよりも、スムーズな開発ができるということだと理解した。アプローチや思想は異なるが、GraphQLとも一部ゴールを共有しそうだ。

## gRPC APIの設計

API設計のガイドラインをGoogleが用意していたりする。

- [API Design Guide | Google Cloud](https://cloud.google.com/apis/design)

## 使ってみた

実際にgRPC-Webをつかって簡単なチャットを作ってみた↓

- [gRPC-Web + React Hooks + Go でリアルタイムチャットをつくる - Qiita](https://qiita.com/okmttdhr/items/a37563047904ac98f3ed)

## 参考

- [What is gRPC?](https://grpc.io/docs/guides/)
- [初めてのgRPC - Speaker Deck](https://speakerdeck.com/line_developers/starting-grpc?slide=70)

- [gRPC-Web is Generally Available](https://grpc.io/blog/grpc-web-ga/)
- [The state of gRPC in the browser](https://grpc.io/blog/state-of-grpc-web/)
- [grpc/PROTOCOL-WEB.md at master · grpc/grpc](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-WEB.md)
- [API Design Guide | Google Cloud](https://cloud.google.com/apis/design)
- [gRPC WebがGAになったのでそろそろ理解してみる - Qiita](https://qiita.com/betchi/items/0e9040f21b1f8ecbf321)
- [gRPC-Web + Typescript + GoでHelloWorld - Qiita](https://qiita.com/otanu/items/98d553d4b685a8419952)
[Processing]ゾートロープ的なもの

#的なもの
![Zoetrope.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/a3b79e4b-7dee-884a-cd10-015a591a0e42.gif)
あまりよく見えないので、隙間からではなく上から見下ろしてます（ゾートロープじゃない気が…）

#プログラム
```Zoetrope.java
//Y軸回転
float rotateY = 0;

//画角
float fov = 3;

//回転速度
float speed = 0.01f;

//X軸回転
float rotateX = 0;

//円柱半径
float radius = 0;

//円柱高さ
float leng = 0;

//アニメーション番号
int aniNum = 0;

//貼り付ける画像
PImage tex;

void setup() {
  size(1600, 800, P3D);
  frameRate(30);

  tex = loadImage("Zoetrope.png");
}

void draw() {
  background(0);
  lights();
  perspective(PI/fov, (float)width/height, 10, 1000);

  //操作説明
  textSize(25);
  text(" A :accel\n D :decelerate\n W :Just speed\n S :Stop\n Click :Zoom", 
    0, height-250);

  translate(width/2, height/2+100, 100);

  noStroke();
  fill(255);

  rotateX(rotateX);
  rotateY(rotateY);

  Cylinder(leng, radius);

  rotateY += speed;

  //アニメーションスウィッチ
  switch(aniNum) {

  case 0:
    radius++;
    aniNum++;
    break;

  case 1:
    leng++;
    if (leng >= 250) aniNum++;
    break;

  case 2:
    radius ++;
    if (radius >= 150) aniNum++;
    break;

  case 3:
    rotateX -= PI/180;
    if (rotateX <= -PI/4) aniNum++;
    break;
  }
}

//円柱メソッド
//   Cylinder( 長さ , 半径 )
void Cylinder(float leng, float radius) {

  float x, y, z;

  pushMatrix();

  //底面
  beginShape(TRIANGLE_FAN);
  y = leng / 2;
  vertex(0, y, 0);
  for (int deg = 0; deg <= 360; deg += 2) {
    x = cos(radians(deg)) * radius;
    z = sin(radians(deg)) * radius;
    vertex(x, y, z);
  }
  endShape(); 

  //側面
  beginShape(QUAD_STRIP);
  texture(tex);
  textureMode(NORMAL);

  for (int deg = 0; deg <= 360; deg += 1) {
    x = cos(radians(deg)) * radius;
    y = -leng / 2;
    z = sin(radians(deg)) * radius;
    normal(x, 0, z);
    vertex(x, y, z, deg/360f, 0);

    x = cos(radians(deg)) * radius;
    y = leng / 2;
    z = sin(radians(deg)) * radius;
    normal(x, 0, z);
    vertex(x, y, z, deg/360f, 1);
  }
  endShape();

  popMatrix();
}

void keyPressed() {
  //a で加速　d　で減速  w でいい感じの速度　d で停止
  if (key == 'a') speed += 0.01f;
  else if (key == 'd') speed -= 0.02f;
  else if (key == 'w') speed = 0.63f;
  else if (key == 's') speed = 0;
}

void mousePressed() {
  //画角切り替え
  if (mouseButton == LEFT) {
    fov = (fov+6)%12; //fovの値を3と9交互にする式
  }
}

```
#使用画像
「Zoetrope.png」
![Zoetrope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/e1b91ceb-5507-b061-345e-6f16b99af9f8.png)
Sequelize(PostgreSQL)で月次の集計を行う

例えば、特定の会社に所属するアカウントの新規作成数を月次で集計したい場合（そんな状況があるのかどうかはさておき）

想定結果

|month|cnt|
|----|----|
|2020-03|10|

## PostgreSQL

```sql
SELECT 
TO_CHAR(created_date, 'YYYY-mm') AS month,
COUNT(user_id) AS created_cnt
FROM users
WHERE company_id = 1 
GROUP BY month
```

## Sequelize

```js
const sequelize = require('sequelize');
const userCtrl = require('../models/userCtrl')
...
const res = await userCtrl.findAll({
  attributes: [
    [sequelize.fn('to_char', sequelize.col('created_date'), 'YYYY-mm'), 'month'],
    [sequelize.fn('count', sequelize.col('user_id')), 'created_cnt']
  ],
  where: {
    company_id: 1,
  },
  group: ['month'],
});
```

`sequelize.fn`...データベース関数を指定
`sequelize.col`...対象のカラムを指定

## 蛇足

MySQLではTO_CHAR関数の代わりに`DATE_FORMAT関数`を使う
指定するフォーマットには、「%」文字をつける

```sql
SELECT
DATE_FORMAT(created_date, '%Y-%m') AS month,
COUNT(user_id) AS created_cnt
...
```

## 参考
[Sequelize公式 - sequelize.fn](https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#static-method-fn)
[MySQL5.6リファレンスマニュアル - DATE_FORMAT](https://dev.mysql.com/doc/refman/5.6/ja/date-and-time-functions.html#function_date-format)
DOMに設定したvalueをval()で取れない時の解決策

# 概要
とりあえずDOMのタグに`id`と`value`を付加して、`jQuery`の`$("#id").val()`で取得しようとしたらうまくいかなかったときのメモ。

# 環境
 - macOS Catalina(10.15.2)
 - FireFox 72.0.2
 - jquery-3.4.1.min(CDN)

# 詳細

## 経緯
「『3月14日』と表示された日付のセルを選択したとき『0314』という文字列をjavascript側に渡したい」というようなことがあった。
`jQuery`については**「とりあえず要素に`id`を指定して`value`に値を入れれば`$("#id").val()`で取得できる」**程度の理解だったので、

```html
<td id="date1" value="0314">3月14日</td>
```
と書いて、

```js
$("#date1").val()
```
で取ろうとしたら空の文字列しか取得できず「？？？」となった。

## 調査

簡単なテストファイルとスクリプトを作成して挙動を確認してみる。

```test.html
<!DOCTYPE HTML>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>test</title>
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="test.js"></script>
  <table>
    <thead></thead>
    <tbody>
      <tr id="tr" value="tr">
        <th id="th" value="th">ヘッダ</th>
        <td id="td" value="td">データ</td>
      </tr>
    </tbody>
  </table>
  <div id="div" value="div">div</div>
  <span id="span" value="span">span</span><br>
  <input type="selectbox" id="selectbox" value="selectbox"><br>
  <input type="radio" id="radio" value="radio"><br>
  <button id="button" onclick="displayValue();">value</button><br>
</body>
</html>
```

```test.js
function displayValue(){
  console.log($("#tr").val());
  console.log($("#th").val());
  console.log($("#td").val());
  console.log($("#div").val());
  console.log($("#span").val());
  console.log($("#selectbox").val());
  console.log($("#radio").val());
}
```

「value」ボタンをクリックして取得できる値を確認。
![スクリーンショット 2020-03-14 14.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601682/7602ce62-da37-4098-43b6-d13c338bbf2d.png)

……`selectbox`と`radio`しか取得できていない。

## 原因

調べてみると、そもそも`value`属性は`input`等の一部の要素でしか定義されていないようだ。
`td`やら`div`やらに`value`を付加してもそれはユーザ定義の属性になるので、`.val()`では値を取得できないらしい。

　参考：https://reference.hyper-text.org/html5/attribute/value

## 回避策

ユーザ定義の属性に対してその値を取得するには、`.val()`ではなく`.attr("value")`とすればよい。

```(rewrite)test.js
function displayValue(){
  console.log($("#tr").attr("value"));
  console.log($("#th").attr("value"));
  console.log($("#td").attr("value"));
  console.log($("#div").attr("value"));
  console.log($("#span").attr("value"));
  console.log($("#selectbox").attr("value"));
  console.log($("#radio").attr("value"));
}
```

「value」ボタンをクリック。
![スクリーンショット 2020-03-14 14.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601682/d27089ac-55ce-7556-3d3f-9113eac53949.png)

無事に取得できた。

## 後日談
HTML5には「独自データ属性」というものがあり、どうやらこれを使うのが正攻法のようだ。

```html
<td id="date1" data-value="0314">3月14日</td>
```

値の取得には`.data()`を使えばOK。

```js
$("#date1").data("value")
```

　参考：https://wp.tech-style.info/archives/102
　　　　https://qiita.com/katsukii/items/c29b61b35d4919493e06

# まとめ
 - `.val()`で取得できる`value`属性は`input`等の一部の要素にしかない
 - `td`や`div`等の要素に`value`属性を与えた場合は`.attr("value")`で取得できる
 - ちゃんとやるなら独自データ属性と`.data()`を使おう
【Rails】rails generate controllerで生成されるファイルに制限をかける【config.generatorsの設定】

##はじめに

generateコマンドっていろんなファイルを作成してくれるけど、「helperファイルの自動生成は必要ないのになー」って時などには、かえって煩わしく感じますよね。

そこで今回は、`config/application.rb`内の設定によって、generate コマンドで生成されるファイルに制限をかけます。（※スキップオプションを付ける方法もあるけど省略）


##まずはrails generation時の挙動を確認

ターミナルで`rails generation(rails gに省略可)`を行うと、色々なファイルが自動生成される。

```terminal
> rails g controller user show      
Running via Spring preloader in process 
      create  　app/controllers/user_controller.rb
       route  　get 'user/show'
      invoke  　erb
      create    app/views/user
      create    app/views/user/show.html.erb
      invoke  　rspec
      create    spec/controllers/user_controller_spec.rb
      create    spec/views/user
      create    spec/views/user/show.html.erb_spec.rb
      invoke  　helper
      create    app/helpers/user_helper.rb
      invoke    rspec
      create    spec/helpers/user_helper_spec.rb
      invoke  　assets
      invoke    js
      create    app/assets/javascripts/user.js
      invoke    scss
      create    app/assets/stylesheets/user.scss
```
便利だけど、必要ないファイルがあれば、それだけ生成されないようにする。
(この自動生成したファイル等を削除したければ、ターミナルで`rails destroy controller user show`を実行しておく)

##自動生成するファイルに制限をかける
今回は、`config/application.rb`内の設定で、
・assetsファイル
・testファイル
・ルーティング
の生成を無効にしてみる。

```ruby:config/application.rb
puts class Application < Rails::Application
        
        
        
 #以下のように、generateコマンド時に生成されるファイルに制限をかける
   config.generators do |g|
     g.assets  false
     g.test_framework    false
     g.skip_routes   true
   end
 end

```
上記の設定によって、

```terminal
> rails g controller user show      
Running via Spring preloader in process 82700
      create  app/controllers/user_controller.rb
      invoke  erb
      create    app/views/user
      create    app/views/user/show.html.erb
      invoke  helper
      create    app/helpers/user_helper.rb

```

生成ファイルに制限がかかった。

このように、プロジェクトごとに設定を変えたり、自分好みのカスタマイズができる。

##おわりに
今回が初のQiita投稿でした！

これからも新しく学んだこと等をQiitaに共有できればと思います。
ご覧いただきありがとうございました。
Python Scraping

# 目標
* サイト
    * eBay.com
* 検索ワード
    * Dragon Ball
* 検索条件
    * 売り切れ
* 取得データ
    * 商品名
    * 状態
    * 価格
    * 送料
    * 1 ページ目のみ
* 出力先
    * eBayScraping_(日付).csv
 
#ソースコード
```python

from time import sleep
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import csv
import pandas as pd
import datetime


driver = webdriver.Chrome(executable_path="/Users/name/home/work/eBay/Python/chromedriver")

url  = ('https://www.ebay.com/sch/i.html?_from=R40&_nkw=dragon+ball&_sacat=0&rt=nc&LH_Sold=1&LH_Complete=1')
driver.get(url)
driver.implicitly_wait(10)

names = []
statuses = []
prices = []
shippings=[]

items = driver.find_elements_by_class_name('s-item__info.clearfix')

for item in items:
    # get Name
    name = item.find_element_by_class_name('s-item__title').text
    name = name.replace("NEW LISTING", "")
    names.append(name)
    # get Status
    try:
        status = item.find_element_by_class_name('SECONDARY_INFO').text
        statuses.append(status)
    except:
        statuses.append(" ")
    # get Price
    price = item.find_element_by_class_name('s-item__price').text
    price = price.replace("JPY ","")
    prices.append(price)
    
    # get ShippingCost
    try:
        shipping = item.find_element_by_class_name('s-item__logisticsCost').text
        shipping = shipping.replace("+JPY ","").replace(" shipping","").replace("Free International Shipping","0")
        shippings.append(shipping)
    except:
        shippings.append(" ")
    #print(shippings)

df = pd.DataFrame()
df['name'] = names
df['status'] = statuses
df['price'] = prices
df['shippingcost'] = shippings

csv_date = datetime.datetime.today().strftime("%Y%m%d")
csv_file_name = "eBayScraping_" + csv_date + ".csv"

df.to_csv(csv_file_name, index = False)

driver.quit()
```

#出力結果
<img width="841" alt="Screen Shot 2020-03-14 at 14.49.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589212/5006be14-ff70-39d6-7d49-ab3ab102c5b3.png">



#問題点
* 以下の 2 つの項目を明確に区別できない
   * Free Shipping
   * Free International Shipping
* 以下の項目を取得する際、かなりの時間がかかる
    * 送料


#改善・発展
* 送料の 2 つの項目について、分類方法を見直す
* 複数ページのデータを取得する
* 頻出単語を抽出する
Breadcrumb NavXTでダミーのパンくずを項目間に足す

Wordpress案件で、パンくずに[Breadcrumb NavXT](https://ja.wordpress.org/plugins/breadcrumb-navxt/)使う際、
「アーカイブ（一覧）ページを持たない記事ページで、パンくず的には下層に見せたい」という場合のメモ。

## 例
- 病院のサイトで、「診療案内」の中にある「外科」というページ
  - 診療案内TOPは存在しない
  - 「外科」はカスタム投稿タイプ（service）とする

この場合、アーカイブがないので
`HOME > 外科` になるけど
`HOME > 診療案内※ > 外科` にしたい。（<sup>※</sup>診療案内はリンクなし）


「アーカイブページを作って、serviceページだったらパンくずの2番目からリンクをはずす」
というやり方も考えたけど、不要なアーカイブページは存在させたくないし、
上記のやり方でもパンくずいじる必要は出てくるので、
ダミーのパンくずを追加する方向で調べた。

参考）特定のパンくずアイテムだったらリンクを消す

> https://mtekk.us/archives/guides/remove-the-link-in-a-breadcrumb/


## 調査

「静的なパンくずを足す」を試したところ、一番左に静的な項目がたされる。
> https://mtekk.us/archives/guides/add-a-static-breadcrumb-to-the-breadcrumb-trail/

普段phpほぼ使わないので読解を要する・・

- パンくず1つ1つ（アイテム）が `bcn_breadcrumb` というクラス [Github](https://github.com/mtekk/Breadcrumb-NavXT/blob/master/class.bcn_breadcrumb.php)
- それを覆っているのが `bcn_breadcrumb_trail` というクラス [Github](https://github.com/mtekk/Breadcrumb-NavXT/blob/master/class.bcn_breadcrumb_trail.php)

ぽくて、 `bcn_breadcrumb_trail` の `add` メソッドで、
静的に追加したい `bcn_breadcrumb` オブジェクトを配列に追加している様子。
https://github.com/mtekk/Breadcrumb-NavXT/blob/master/class.bcn_breadcrumb_trail.php#L165

### GOAL
👉ということは、`bcn_breadcrumb_trail` の配列の任意の場所（今回は2番目）に、
「診療案内」という `bcn_breadcrumb` オブジェクトを足せればよい◎

## コード
```php:functions.php
/**
 * パンくず
 */
function my_static_breadcrumb_adder( $breadcrumb_trail ) {
	if ( get_post_type() === 'service' ) {
		$item = new bcn_breadcrumb( '診療案内', NULL, array('post') );
		$stuck = array_pop( $breadcrumb_trail->breadcrumbs ); // HOME 一時退避
		$breadcrumb_trail->breadcrumbs[] = $item; //診療案内 追加
		$breadcrumb_trail->breadcrumbs[] = $stuck; //HOME 戻す
	}
}
add_action('bcn_after_fill', 'my_static_breadcrumb_adder');
```

### 解説
```
if ( get_post_type() === 'service' ) {
```
投稿タイプが一致する場合に

```
$item = new bcn_breadcrumb( '診療案内', NULL, array('post') );
```
パンくずアイテムを作る。
`bcn_breadcrumb` のコンストラクタで引数確認。URLはNULLで。
https://github.com/mtekk/Breadcrumb-NavXT/blob/master/class.bcn_breadcrumb.php#L51

```
$stuck = array_pop( $breadcrumb_trail->breadcrumbs ); // HOME 一時退避
```
`$breadcrumb_trail->breadcrumbs` でパンくずの配列が取得できる。
※この配列、`HOME > アイテム1 > アイテム2` とある場合、一番右（アイテム2）が0番目。HOMEが一番最後。
[array_pop](https://www.php.net/manual/ja/function.array-pop.php)で、HOMEを一度避ける。

```
$breadcrumb_trail->breadcrumbs[] = $item; //診療案内 追加
$breadcrumb_trail->breadcrumbs[] = $stuck; //HOME 戻す
```
あとは順番に追加して、

```
add_action('bcn_after_fill', 'my_static_breadcrumb_adder');
```
アクションフックで実行
無事、こう `HOME > 診療案内 > 外科` なりました。

## おわり
phpの配列の扱いでちょっと詰まった。
配列の任意のindex（2番目）に足すんだから、[array_splice](https://www.php.net/manual/ja/function.array-splice.php)でいけそうやな、
って思ったのだけど、エラーで怒られた・・

そもそも
`$breadcrumb_trail->breadcrumbs[] = $item;`
これでおしりに追加できるっていうのが普段使わない人からするとなんかすごく不慣れだ。。笑
（1回空にして代入します！みたいに思っちゃった）

PHP、もっとちゃんと読めるようになりたいなーと思いました。🐬
UnityのWorldComposerについて。

#UnityのWorldComposerについて。

こんにちは。Unity初心者の和皆と申します。
現在、C言語とC#の勉強をしています。まだ、初心者なのでModの作り方はもちろん、プログラムもあまりできません。
ただ、この頃『WorldComposer』というAssetが気になっていまして…。一度、Gaiaを購入しようと思いましたが価格が高すぎるので代替のものを探したところWorldComposerが出てきました。
しかし、どのようなものが作成できるのかできないのかの情報があまり出てこないのがかなり痛いです。
![00000000000000337634_0000001700_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602614/b2fccd61-56d1-32ae-52a9-c81bccfdccfa.jpeg)

![images (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602614/676b7dc7-772c-7a9f-0cd7-735752467325.jpeg)

![ダウンロード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602614/e6ffb302-1925-3ff7-6c13-e8e9f5259f5b.jpeg)
![ダウンロード (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602614/b18c84f9-6300-2609-8593-db26921e92c8.jpeg)



上の画像は首都高、名古屋高速、阪神高速です。WorldComposerを使った場合、この写真のように内部まで細かく再現されるのでしょうか。
![1_l.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602614/1aa031cb-d727-336d-5b7b-b3bc929b49e6.jpeg)

こちらの写真のように、トンネル内の照明等も再現されるのでしょうか。

なるべくリアルなものを作成したいので回答お願いします。
Visual Studio が Equals、GetHashCode を自動生成できるようになっていた

Visual Studio が Equals、GetHashCode を自動生成できるようになっていたので備忘のためにメモ。
`==`、`!=` 演算子や `IEquatable<T>` も生成できる。

助かる。

## 情報源

[Generate Equals and GetHashCode method overrides in Visual Studio](https://docs.microsoft.com/en-us/visualstudio/ide/reference/generate-equals-gethashcode-methods?view=vs-2017)

Visual Studio 2017 を対象とした 2 年以上前の情報なのでこのあたりから提供されていたのか。。

[Visual Studio で Equals および GetHashCode メソッドのオーバーライドを生成する](https://docs.microsoft.com/ja-jp/visualstudio/ide/reference/generate-equals-gethashcode-methods?view=vs-2019)

日本語の情報もあるな。。が、書いてしまったんで。

## 手順

1. 対象の `クラス` にカーソルを移動して、キーボードで `Ctrl + .` を入力する。このとき、クラス名を選択 (反転) 状態にしないよう注意。
2. もしくは、クラス名の行を右クリックして `クイック アクションとリファクタリング` をクリックするでも可。
3. コンテキストメニューの `Equals および GetHashCode` もしくは `Equals(object) を生成する`をクリックする。
4. [メンバーの選択] ダイアログで、評価するメンバーを指定する。
5. 必要に応じて `IEquatable<T> を実装する`、および `演算子を実装する` をチェックする。
6. [OK] ボタンをクリックする。


## 確認した環境

- Windows 10 Home 64 bit バージョン 2004
- Microsoft Visual Studio Community Edition 2019 Version 16.4.6
【CSS3】ローダーアニメーション

#### udemyの動画内容のメモ・備忘録

```html:index.html
<div class="three-dot-spinner">
    <div class="bounce1"></div>
    <div class="bounce2"></div>
    <div class="bounce3"></div>
</div>
```

```scss:style.scss
$cBlack: black;

.three-dot-spinner {
  text-align: center;

  & div {
    display: inline-block;
    width: 18px;
    height: 18px;
    background-color: $cBlack;
    border-radius: 50%;
    animation: sk-bouncedelay 1.4s infinite;
  }

  & .bounce1 {
    animation-delay: -0.32s;
  }
  & .bounce2 {
    animation-delay: -0.16s;
  }
}

@keyframes sk-bouncedelay {
  0% {
    // opacity: 0;
    transform: scale(0);
  }

  40% {
    transform: scale(1);
  }
  80% {
    transform: scale(0);
  }
  100% {
    transform: scale(0);
  }
}
```
（未経験）インターネット用のマクロを作りたいです

chromeの上でFBの不特定多数の画像アドレスをコピーして検索するアルゴリズムを作りたいですが、マクロプログラミングについて全く経験がなくて勉強をしようとも手も足も出ずな状態です。何かおすすめなサイトや入門なものをアドバイスしてくれれば大変助かります。
【MySQL・Docker】cryptography is required for sha256_password or caching_sha2_password


DockerでMySQL8.0のイメージを使用した際、「cryptography is required for sha256_password or caching_sha2_password」エラーが発生したのでその回避策。

## 原因

>デフォルトの認証がcaching_sha2_passwordになっていたのですが、これだと暗号化がうまくいかないのか、復号の際の検証がうまくいかないのか、エラーが発生しているようです。

参考
・[アプリ制作時に悩まされたエラー集](https://blowup-bbs.com/python-app-error/)
・[MYSQL8.0におけるデフォルトの認証プラグインの変更](http://variable.jp/2018/02/23/mysql8-0%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E8%AA%8D%E8%A8%BC%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E5%A4%89%E6%9B%B4/)

## 回避策
認証方式をMySQL8.0.4以前のmysql_native_passwordに戻しましょう。CMDで変更することも可能だと思いますが、今回はmy.cnfを自作して、起動したコンテナにマウントします。

```my.cnf
[musqld]
default_authentication_plugin= mysql_native_password
```


```docker-compose.yaml
・・・略
  mysql:
    image: mysql:8.0
    volumes:
      - ./my.cnf:/etc/mysql/conf.d/my.cnf
```

my.cnfをマウントする方式にしておくことで文字コード問題（utf8,latin問題）などが発生した場合も設定を書いてあげるだけなので簡単に対応することができるようになります。
[Processing]ポリゴンで波を表現

#こんな
**69行目の「stroke(255);」の時と「noStroke();」の2種類の映像**
![Waver.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/38cb239b-516a-e10c-5e60-908a561c3a0b.gif)
線が入ると正方形が連なってるのがわかりますね
手前から奥に向かって帯が揺れています
#プログラム
```Wavers.java
PShape Ball;

class SeaSell{
  
  SeaSell prev; //位置をマネする対象
  
  float x;
  float y;
  float z;
  float siner = 0;
  
  SeaSell(float x , float Z){
    this.x = x;
    z = Z;
  }
  
  void Draw(){
    
    if(prev != null)y = prev.y;
    else y += sin(siner += 0.05f);
    
    vertex(x,y,z);
  }
  
}


SeaSell sells[][] = new SeaSell[100][100];

void setup(){
  size(1800,800,P3D);
  frameRate(30);
  
  Ball = createShape(SPHERE,100);
  Ball.setTexture(loadImage("Ball.png"));
  Ball.setStrokeWeight(0);
  
  //Sea sellの間隔
  int distribution = 15;
  //波打つ帯を横に並べてる
  for(int i=0;i<sells.length;i+=2){
    for(int j=0;j<sells[i].length;j++){
      sells[i][j] = new SeaSell(i * distribution -distribution,j * distribution); //位置登録
      sells[i+1][j] = new SeaSell(i * distribution +distribution,j * distribution); //位置登録
    }
  }
  
  for(int i=0;i<sells.length;i++){
    for(int j=0;j<sells[i].length;j++){
      if(j != sells[i].length-1){   //jが端じゃない時、同列の隣のセルをprevにいれる
        sells[i][j].prev = sells[i][j+1];
      }
      else if(i != sells.length-1){  //jが端だけどiが端じゃない時、隣の列のセルを入れる
        sells[i][j].prev = sells[i+1][j];
      }
    }
  }
}

void draw(){
  background(0);
  lights();
  perspective();
  
  pushMatrix();
    translate(5,0,-1500);
    rotateX(-PI/6f);
    fill(50,50,200);
    //stroke(255);
    noStroke();
    
    
    for(int i=0;i<sells.length;i+=2){
      beginShape(QUAD_STRIP); //帯状の波
        for(int j=0;j<sells[i].length;j++){
          sells[i][j].Draw();
          sells[i+1][j].Draw();
        }
      endShape();
    }
  
    pushMatrix();
      translate(sells[50][50].x,sells[50][50].y,sells[50][50].z);
      translate(0,-30,0); shape(Ball);
    popMatrix();
  popMatrix();
  
}
```
#簡単に解説
**SeaSell**という座標と隣のSeaSellを保持するクラスが等間隔で配置されます
動作は2通り

```解説.java
if(隣のSeaSellが登録されてる){
  隣のSeaSellの位置に向かって移動する
}
else{ //隣のSeaSellが登録されていない場合
  上下に動く //←映像の一番右下で上下してるやつ
}
```
以前投稿した「[[Processing]クリック点を保存してアート作品を描く](https://qiita.com/NekoCan/items/f628be98779451751f19)」から参考に制御してみました
#OpenCV　と　#csharp　を使って、　#TETRIS　の動画からミノの積み位置を抽出するツール

githubと改行ルールが違って二重管理になるため、ここにはgithubのREADME.mdのコピペを載せます。
(githubにあっても検索で探せないため。)
https://github.com/github895439/tetris_stacking_position_picker

```plaintext:README.md
本内容を利用した場合の一切の責任を私は負いません。

機能
テトリスの動画を解析して、ミノの積み位置を抽出します。
「 https://www.youtube.com/watch?v=kJohHun8ANI 」の左フィールドを抽出したものが https://github.com/github895439/tetris_stacking_position_picker/tree/master/log です。
(ログの「表示無し」をチェック入りの状態で40分弱かかりました。 github上で表示するとフォントの都合で崩れているが、RAWデータをダウンロードすれば崩れない。)
基本的に、画面のログとログファイル(実行ファイルの場所に出力)の内容は同じです。
ログファイルは1ファイル/クレジットです。
ログの内容は、

□:ミノ落ち前後で存在したままのブロック
■:ミノが落ちる前と比較して、増えたブロック(=落ちたミノ)
◆:ミノが落ちる前と比較して、減ったブロック

ライン消しがあった場合とその後近辺はライン消しの影響があり、判別が困難なため、間違った結果になっています。
対戦モードには対応していません。
同ミノ連続した場合も判別できないため、2ミノが一度に落ちたような結果になっています。
「f」単位は経過フレームで、タイムスタンプはそれを時間換算したものです。

バージョン
OS
OS 名: Microsoft Windows 10 Home
OS バージョン: 10.0.18362 N/A ビルド 18362
システムの種類: x64-based PC
開発
Visual Studio Community 2015(以降、VS)
OpenCVSharp4 v4.2.0.20200208(nuget)
OpenCVSharp4.runtime.win v4.2.0.20200208(nuget)
OpenCVSharp4.Windows v4.2.0.20200208(nuget)
ビルド
本ツールをダウンロード
https://github.com/github895439/tetris_stacking_position_picker

ダウンロードしたものを展開

展開したソリューションをVSでオープン

OpenCVSharpをインストール
VSのプロジェクトの右クリックメニューの「NuGetパッケージの管理」を選択する。
「opencvsharp4」を検索し、結果一覧の「OpenCVSharp4.Windows」をインストールする。
(依存関係により、バージョンに挙げた残り2つのOpenCVSharpも自動的にインストールされる。)
「インストール済み」タブにバージョンに挙げた3つのOpenCVSharpが表示される。

ソリューションのビルド

使い方
直接入力か、「動画ファイル選択」ボタンで動画ファイルを選択

下記の設定を入力(座標の特定は「?」ボタンにガイド有り)

NEXT判定座標
プレイ開始判定座標
プレイ終了判定座標
フィールド判定座標
「抽出実行」ボタン押下(※markdownのせいで番号がおかしく、手順の続き)
その他:

「動画ファイル概要」ボタン
動画ファイルの情報を表示します。

「動画ファイル変更」ボタン
情報表示や抽出を行った場合はデータを破棄する必要があるため、このボタンを押します。
このボタンを押すと、動画ファイルのパスや「動画ファイル概要」ボタンが復帰します。

「抽出中止」ボタン
抽出を途中で止めます。

「終了」ボタン
ツールを終了します。

備考
下記は設計メモです。
(「追記」以降がコーディングを始めてから追記した内容です。)
https://github.com/github895439/tetris_stacking_position_picker/blob/master/design_memo.txt
フレームの確認はaviutlを使用しています。
設定値を変えれば右のフィールドも抽出できるはず。 
動画ファイルを変えて、動画に基づいた設定値にすれば、他の動画からも抽出できるはず。
```