OmniAICreator/Qiita-1.07M huggingface dataset:
NULLについて考えてみる。

突然ですが、
`　　SELECT *
　　 FROM テーブル名
　　 WHERE 1＝1；
`
とSQLを実行するとどうなると思いますか？

1 = 1 が検索条件に指定されていますが、1 = 1 はtrueなので全件検索(早い話が条件がないのと一緒)全レコードが抽出されます。

では、以下はどうでしょうか？
`SELECT *
FROM  テーブル名
WHERE　NULL＝ NULL；
`
一見、NULL＝NULLはあってそうなので、データは抽出されそうですが、リレーショナルデータベースの世界では抽出されません。

NULLを検索条件にするには IS　NULLが必要になります。
なぜこんな仕様なんでしょうか？

それはリレーショナルデータベースの世界に導入された3値論理が影響(悪さ？)しています。

3値論理というのは、trueとfalseの組み合わせからなる2値論理に、unknownを加えたものです。

ひとまず、2値論理の真理値表からおさらいしてみましょう。

###2値論理

| AND | TRUE| FALSE |
|:-----|:---------:|:----------:|
| **TRUE** | true     | false      |
| **FALSE** | false    | false      |

ANDは、どちらもtrueの場合にのみ、trueになるパターンですね。

| OR | TRUE | FALSE |
|:------|:--------:|:---------:|
| **TRUE**  | true     | true      |
| **FALSE** | true     | false     |

ORはどちらかがTRUEの場合、trueになります。

では3値論理の真理値表はどうでしょうか？

###3値論理


|  AND |TRUE|FALSE|UNKNOWN|
|:---:|:---:|:---:|:------:|
|**TRUE**| true |false|unknown|
|**FALSE**|false|false|false|
|**UNKNOWN**|unknown|false|unknown|

|  OR |TRUE|FALSE|UNKNOWN|
|:---:|:---:|:---:|:------:|
|**TRUE**| true |true|unknown|
|**FALSE**|true|false|unknown|
|**UNKNOWN**|true|unknown|unknown|

マトリックスでtrueになっている組み合わせしかデータは抽出されません。
一見、分かるような、よく分からないような。
少し話が脱線したので、IS NULLと書かないといけない理由に話を戻してと。
プログラミング言語が=null というような書き方を許容しているのが多くあるのに、SQLはIS NULLなんて書かないといけないのでしょうか？

**それはSQL標準規格 で定められているから** なのですが、その理由を少し想像してみたいと思います。
（※ここから先は、はっきりと書かれている文献等を見たわけではないので、私の想像が入っています。あくまで参考程度にしてください）

リレーショナルデータベースを提唱したコッドさんは、3値論理を飛び越えて、4値論理を提唱していたそうです。
え！？4値？もう一個はなに？
というと、NULLには2種類あると考えていたそうです。

**4値論理の2種類のNULL**
*・値がわからない NULL*

例えば、従業員マスタに性別 という列があると仮定しましょう。

従業員マスタ

| 従業員コード | 名前 | 性別 |
|-----------:|:---:|:--------:|
|1|テスト1|男性|
|2|テスト2|NULL|

テスト2さんの性別がNULLの場合は、男性か女性か分からないという状態ですね。
*こういう意味のNULLは値がわからない* を表しています。

*・ありえない状態のNULL*
入学テーブル

| 受験者コード | 不合格日 | 
|-----------:|:---:|
|1|NULL|
|2|NULL|

テーブル設計ミスだろ！とは思うのですが、この状態のNULLのいい例が思いつかなかったのです。
入学した人に不合格 はありえませんね（特殊なパターンはあるかもしれませんが）
ありえない状態のNULL とは、意味的に存在しない状態を指しています。

コッドさんは、RDBの世界にも4値論理を入れて、NULLも2種類で表現したかったそうなのですが、大変になりそうってことで実装されなかった・・・
IS NULLも間違えやすいのに、そのNULLが2種類になんてしまったら、、、末恐ろしい。

**こんな風にNULLには2種類の意味が込められた単純な値ではない**
ということを表すために、IS NULL が導入されたのでしょう・・・たぶん、知らんけど。

とにかく、NULLというのはバグの原因になったり、なんで数が合わないんだー！とか色々悪さをしてくれます。
（理論で考えたら納得できるのですが、バグを生んだり悩んだりするときって疲れてて正常な判断できないんですよね～。）

そういうわけで、これから私がデータベースからなぜNULLを排除すべきと考えているか？
非正規化すべきではないと考えているのか、もう一度自分の中でほりさげる意味で
理由を書いていきたいと思います。
Nuxt.jsで外部サイト（URL）へ遷移する方法

Nuxt.js（Vue）で外部サイト（URL）へ遷移する方法です。

## aタグで遷移

```vue
<template>
  <div>
    <a href="https://www.yahoo.co.jp/">リンク</a>
  </div>
</template>
```

内部へのリンクでしたら`<nuxt-link to=""></nuxt-link>`が使えますが、外部リンクでは使用できません。

## scriptで遷移

イベント後に外部サイトへリンクしたい場合などは、scriptで記述します。

```vue
<template>
  <div>
    <button @click="externalLink">ボタン</button>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  methods: {
    externalLink() {
      const url = 'https://www.yahoo.co.jp/'
      window.location.href = url
    }
  }
})
</script>

```

上記の例では、clickイベント後に`window.location.href`で外部URLに遷移させています。
別タブで外部サイトを開きたい場合は、`window.open()`を使用します。

```vue
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  methods: {
    externalLink() {
      const url = 'https://www.yahoo.co.jp/'
      window.open(url, '_blank')
    }
  }
})
</script>
```

何か処理をしたあとで、ページ遷移させたい時などに有効です。
ubuntu-18.04.4-server-amd64.isoでインストーラの言語が日本語だと途中でループする

以下と同件

> [amd64向け18.04のNetbootインストーラの言語が日本語だと途中でループします](https://forums.ubuntulinux.jp/viewtopic.php?pid=119684)

言語を英語にして回避

# 参考
[amd64向け18.04のNetbootインストーラの言語が日本語だと途中でループします](https://forums.ubuntulinux.jp/viewtopic.php?pid=119684)
[Ubuntu 18.04 LTS (Bionic Beaver)](http://old-releases.ubuntu.com/releases/18.04.2/)
備忘録　PythonでのwebAPIの叩き方

40の手習いでプログラミングをとPythonを学び始める
環境　MBA2018
Python3

PythonでWebAPIを叩きたい。
ライブラリはurllib3とRequestsっつ-のがあるらしい。
どっちがいいんだべか？よくわからんけどどうもrequestsのほうが簡単って書いてあるのを見かけるので
そちらにしてみよう。

import requests
 r = requests.get("https://news.yahoo.co.jp/")
 print(r.text)

<!DOCTYPE html><style data-styled="gpQmdr jhlPYu" data-styled-version="4.4.1" data-styled-streamed="true">
/* sc-component-id: sc-jAaTju */
.gpQmdr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:hidden;position:relative;background-color:#efefef;height:80px;width:80px;} .gpQmdr::after{content:'';display:block;position:absolute;top:0;left:0;box-sizing:border-box;width:100%;height:100%;border:solid 1px rgba(0,0,0,0.06);}
/* sc-component-id: sc-jDwBTQ */
.jhlPYu{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;max-height:80px;max-width:80px;}</style><html lang="ja"><head><title>Yahoo!ニュース</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta name="viewport" content="width=970"/><meta http-equiv="Content-Style-Type" content="text/css"/><meta http-equiv="Content-Script-Type" content="text/javascript"/><meta name="description" content="Yahoo!ニュースは、新聞・通信社が配信するニュースのほか、映像、雑誌や個人の書き手が執筆する記事など多種多様なニュースを掲載しています

とりあえずGETできた模様。
明日はこれを使ってAPIを叩いてみよう。
RaspberryPiを使ってDNSサーバーを構築し、広告をブロックする方法

#前置き
今回は280blockerさんのリストを使用したいので、[AdGuardHome](https://github.com/AdguardTeam/AdGuardHome)というアプリケーションを使用します

使うもの
iPadPro 12.9(3世代)
・iPadOS 13.4

RaspberryPi3 ModelB
・RaspberryPi OS(32bit)
#準備
事前に作業環境のアップデートとIPの固定をします

```
sudo apt update
sudo apt upgrade
```
今回は`192.168.11.100`に固定します
![68825B1B-1D23-45AF-998D-C829F19B9C40.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/9738579a-2d68-48ef-1c09-60934c1ee03c.jpeg)
![F9E1E1F7-2C2F-4ED7-869B-91E4CE7DA3F8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/828c9344-8511-458d-e74b-44f649c5bd75.png)
適用ができたら再起動をします

```
reboot
```
#インストール
準備が終わったら、AdGuardHomeをインストールします

```
wget https://static.adguard.com/adguardhome/release/AdGuardHome_linux_arm.tar.gz
tar xvf AdGuardHome_linux_arm.tar.gz
cd AdGuardHome 
sudo ./AdGuardHome -s install
```
AdGuardHomeのインストールできたら起動します

```
AdGuardHome -s start
```
上記の作業を行うシェルスクリプトを用意したのでよかったら使ってください

```
wget https://raw.githubusercontent.com/Ringo-dev/file/master/install.sh
sudo sh install.sh
```
#設定
**※ここからは同じルーター内の端末であればラズパイでなくとも作業することができます**
起動後、`http://192.168.11.100:3000`をブラウザーに入力します
![DEB8EE03-3E82-47E5-81B9-1B21C4F1AAC5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/29ff4077-3ae7-15e6-7e07-5899d6e0305c.png)

今回は全てeth0のIPのみにします
![9776BC82-A65E-47A0-8C2C-916566887DBC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/36c517ea-ff58-311f-8274-e0f2e59c0b5e.png)

ログインが完了し、この画面が表示されたらブロックリストを追加していきます
![1660F6EE-A12A-491B-BBAF-1746490793B6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/dff9c488-d229-9130-59d0-bc17e2b07b2e.png)

フィルタ
　DNSブロックリスト
![48CC3850-298F-4646-87ED-9A77E4AC9DA3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/0155984c-4577-db7c-0db5-9700935878cc.png)
から下にある
ブロックリストに追加を押し、[こちら](https://280blocker.net/download/)からリスト方式のURLをコピぺして、保存します
保存ができたら、DNSの設定に固定したIPを入力することで広告ブロックが可能になります

DNS設定前
※著作権の理由から画像は黒塗りにしています
![9C82F8EB-AD78-406E-B67A-019710B78B05.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/83e5fbf6-d60f-3dca-b80e-b6b0503bc1de.jpeg)
DNS設定後
![A53D0B4E-6D74-4B13-B9EC-BBD6ED0C937A.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492340/70618602-6aab-9ea3-fff5-dfd1aec698b8.jpeg)

また、YouTubeアプリやTwitterアプリでは消えませんでした
**※気付いていないだけで、多少は消えてるのかもしれません**
ゲームアプリで試したところ動画広告や広告バーなどは消えることを確認しました

#感想
私自身、広告ブロックができなくてChromeからSafariに移行したので、iPhoneやiPadでSafari以外のブラウザーを使用していて広告が邪魔だなと思っている方には、怪しいVPNを使わずにブロックする事ができるのでおすすめです

**ここまで読んでいただいてありがとうございました。**
Arduinoで各種コントローラを制御する。②ハードウェア

※自分用のメモも兼ねてます。随時更新予定。

Arduinoで各種コントローラを制御する。①検討 は <a href="https://qiita.com/mako0314tama/items/1653b117b95afd54638f">こちら</a>
Arduinoで各種コントローラを制御する。②ハードウェア は <a href="https://qiita.com/mako0314tama/items/6679d89658f91b758712">こちら</a>
Arduinoで各種コントローラを制御する。③ソフトウェア は <a href="https://qiita.com/mako0314tama/items/0bf414f0bf0d81d5966d">こちら</a>

#コントローラ分解
|  MCU付近 | ボタン付近 | 回路検証 |
|:-:|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/07375526-72bf-1ed6-5843-74db67063254.jpeg">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/d5ff1480-5056-e8d0-af14-86af51bc1827.jpeg">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/63403327-62d5-0472-1f4b-66d97b9da51c.jpeg">テストパターンを利用して、抵抗値や電圧を測定。|

中華の~~怪しい~~やつは分解も簡単で初心者むけ。



#ArduinoPINの対応関係

| テストパターン | DUALSHOCKのボタン | 制御方式 | ArduinoPIN NO. |
|:-:|:-:|:-:|:-:|
| X | □ | ① | 0 |
| A | x | ① | 1 |
| B | ○ | ① | 2 |
| Y | △ | ① | 2 |
| KL1 | L1 | ① | 4 |
| KR1 | R1 | ① | 5 |
| KL2 | L2 | ② | ~~6~~->35 |
| KR2 | R2 | ② | ~~7~~->36 |
| SH  | SHAREボタン | ① | 8 |
| OP  | Optionボタン | ① | 9 |
| KL3 | L3 | ① | 16 |
| KR3 | R3 | ① | 17 |
| PS  | PSボタン | ① | 18 |
| TO | TouchPad| ① | 19 |
| AU | 上ボタン| ① | 20 |
| AR | 右ボタン| ① | 21 |
| AD | 下ボタン| ① | 22 |
| AL | 左ボタン| ① | 23 |

制御方式①：HIGHで待機。ボタンを押したときLowになる。
　　　　　　電流制御用の抵抗4MΩがあるため、そのまま制御信号でショート。
制御方式②：ボタンを押すとテストパターンの電圧が0V~2.8Vくらいまで変化。
　　　　　　GND-パターン間の抵抗3.3kΩとスイッチ部の可変抵抗の分圧電圧を読み取っている。
　　　　　　~~Analog入出力をすることで制御可能？~~ -> 入力のみ確認
　　　　　　出力はPWM出力のため、コンデンサなどを利用する必要がある。
　　　　　　出力用にコンデンサをつけると入力時に遅延が起きるため見送り(2020/7/19追記)

#回路図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/5dccc0f3-7c6a-c00a-ff54-4a97b524a331.png)



#コントローラ基板改造&Teensy用基板作成
| コントローラ基板改造 | Teensy用基板作成① | Teensy用基板作成② | Teensy用基板完成 |
|:-:|:-:|:-:|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/016e9720-edf8-4be3-dbb5-40cd404b89ff.jpeg">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/3e6a1799-ebe4-d467-ea25-19cea39fa83f.jpeg">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/2b5df6b3-ffb2-ac69-dec5-07bf103a169c.jpeg">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/1b2d6ec2-a5fc-fb87-c941-5ce0825818bc.png">|

#完成
![全体像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659663/a7f534a9-c60d-d180-144b-4f8f14994d45.jpeg)

#Future work
・L2R2への対応
・アナログスティック入力への対応





#参考サイト
「[デュアルショック4乗っ取り] - 松蔵さん家の物置場(仮)」 2020/06/21アクセス
https://rezius2.jimdofree.com/%E5%B7%A5%E4%BD%9C%E3%81%AE%E6%A3%9A/%E3%83%87%E3%83%A5%E3%82%A2%E3%83%AB%E3%82%B7%E3%83%A7%E3%83%83%E3%82%AF4%E4%B9%97%E3%81%A3%E5%8F%96%E3%82%8A/

「DualShock 4-PS4開発者Wiki」2020/06/21アクセス
https://www.psdevwiki.com/ps4/DualShock_4

「デュアルショック4のアナログスティックを乗っ取る(1)：分解〜回路図〜試験 | ファミコンと心中するの？」2020/06/21アクセス
https://ameblo.jp/bit287/entry-12426938822.html
45秒でMVCのイメージをつかむ

# まず
他のMVCに関する記事を見て、「難しい・・・」となったときに見ていただくのがオススメです。

# MVCって難しい？


まだIT業界に夢見ていた頃、MVCに書かれている本やサイトを見るたびに「難しいなぁ・・・」と頭かきむしっていましたが、ある程度業界に染まった後に振り返ってみると、別に大したことを言っていないな、と思います。

以下の図をイメージしながら他の記事を見ると、何を言っているのかがよくわかると思います。
![IMG_5562 2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562211/a1faec79-85dc-7362-1327-eb68eaa5fa80.jpeg)

View：テレビ
Controller：ビデオデッキ
Model：ビデオテープ

MVCの依存関係について、「ViewはModelのことを知らない」「ModelはViewのことを知らない」はまさにこれで、テレビにビデオテープがささるのはおかしい訳です。
![IMG_5563.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562211/3c79e419-5a6d-29d3-f478-d33d40fe7000.jpeg)

MVCを意識せず一緒くたにしても動きはしますが、それは**「劇場版ドラえもんを内部に埋め込んだテレビデオ、ポケモンが観たい時はテレビをドライバーで分解しないといけない」**ようなもので拡張性最悪なので、きちんと責務を分割して、ドライバー無しでもポケモンを観れるようにしましょう。
1 コンストラクタの代わりにstaticファクトリメソッド

#そもそもstaticファクトリメソッドとは

```
クラスのインスタンスを返す単なるメソッド
```
だそうですで

サンプルのコードには

```
public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}
```

と書かれている。

##三項演算子？？
まず、いきなりつまずいた。
三項演算子を理解していない。
条件式 ? 値1 : 値2;
これは条件式に一致すれば、値１を返し、一致しなければ値２を返すという意味なので

本の例だと　`return b ? Boolean.TRUE : Boolean.FALSE;`
パラメータのbがtrueならBoolean.TRUEを返し、以外はBoolean.FALSEを返す
ということになるがこれに何の意味があるのか理解するにはボクシングされた
基本データを理解していおく必要がある。

##基本データ型 と ボクシングされた基本データ
ここでまたまた初歩的学習
基本データ型（プリミティブ型）と
ボクシングされた基本データクラスの違い（ラッパークラス）の違いを確認すると

| 基本データ型 | ボクシングされた基本データクラス |
|:-----------|:------------|
| boolean | Boolean |
| char | Character |
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |

基本データ型は値で
ボクシングされた基本データクラスはその名の通りクラス（オブジェクト）。
つまりサンプルはboolean基本データ値をBooleanオブジェクト参照に変換するということだ。

#staticファクトリメソッドのメリデメ
コンストラクタの代わり、あるいは加えてstaticファクトリメソッドを提供することによる
長所と短所についてはこう書いてある。

```
メリット１
```
名前に意味を持たせることで可読性がよくなる。
コンストラクタと違い名前を変えることができるためシグネチャの縛りを考えなくてよい。

`脱線：シグネチャ[シグニチャ]とはメソッド名、引数の数、引数の型を組み合わせもの`

```
メリット2
```
コンストラクタと違い呼び出しごとに新たなオブジェクトを作成する必要がない。（オブジェクトの作成をコントロール可能）
pandasのfillnaを使ったときの「TypeError: No matching signature found」エラーへの対処法

## こんな人におすすめ

- pythonのdf.fillna(method = "ffill")を使ったときに「TypeError: No matching signature found」がでて困っている人

## 対処法
``` python:
df.fillna(method="ffill")
``` 
で「TypeError: No matching signature found」のエラーが発生した場合、下記のように修正すれば良い。

``` python:
df.astype("object").fillna(method="ffill")
``` 

一度object形式に変換してからfillnaを適用する。
上記のエラーは型が異なるときに発生するエラーらしい。
fillnaのあとはintなりfloatなりに再度astypeするのを忘れずに。
floatにする場合は下記。

``` python:
df.astype("object").fillna(method="ffill").astype("float")
```
Postgresで発生したエラー「PG::ConnectionBad: 〜"/tmp/.s.PGSQL.5432"?」に対処した

## 発生内容

昨日まで問題なく稼働していた、ローカルのrailsアプリを今日も起動して確認しようと思い、rails server起動後に、画面アクセスしたところ、以下のエラーが発生

```ruby
PG::ConnectionBad (could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
):
...以下略
```

こんなエラー見たことない（汗）

## 環境

- macOS Catalina 10.15.5
- postgres (PostgreSQL) 12.2
- rails 6.0.3.1

## 問題の特定と対処

とりあえず、postgreのログを確認してみる。

```bash

$ postgres -D /usr/local/var/postgres
2020-06-25 09:38:18.176 JST [3469] FATAL:  lock file "postmaster.pid" already exists
2020-06-25 09:38:18.176 JST [3469] HINT:  Is another postmaster (PID 405) running in data directory "/usr/local/var/postgres"?
```

起動時に作成されるロックファイルがすでに存在していて、エラーになっている模様。
つまり二重起動？おそらく前回起動したpostgresプロセスが正常に停止していないと想像。
（そいえば、昨日の夜macのバッテリーが少ない状態でスリープかけて朝起きたら勝手にシャットダウンしてたのと関係するかも）

[こちらの記事]([https://stackoverflow.com/questions/19828385/pgconnectionbad-could-not-connect-to-server-connection-refused](https://stackoverflow.com/questions/19828385/pgconnectionbad-could-not-connect-to-server-connection-refused))を参考にして、`postmaster.pid`を削除＆postgresの再起動をかける

```bash
$ rm /usr/local/var/postgres/postmaster.pid
$ brew services restart postgresql
```

結果、無事に起動できました。

# 参考記事

[PG::ConnectionBad - could not connect to server: Connection refused](https://stackoverflow.com/questions/19828385/pgconnectionbad-could-not-connect-to-server-connection-refused)
僕が考えた最強の React 技術スタック

# 開発

## フレームワーク

- [Next.js](https://nextjs.org/)
    - `$ npx create-next-app`
    - `with-typescript-eslint-jest` を選択すると、いい感じに色々入る

## ルーター

- [React Router DOM](https://reactrouter.com/web/guides/quick-start)

※ Next.js を使わない場合

## 状態管理

- [Redux](https://redux.js.org/)
- [React Redux](https://react-redux.js.org/)
- [Redux Toolkit](https://redux-toolkit.js.org/)
- [redux-logger](https://github.com/LogRocket/redux-logger)

## フォーム

- [React Hook Form](https://react-hook-form.com/jp/)

## コンポーネントフレームワーク

- [MATERIAL-UI](https://material-ui.com/)

## HTTP クライアント

- [axios](https://github.com/axios/axios)

## Firebase

- [with-firebase](https://github.com/vercel/next.js/tree/canary/examples/with-firebase)

## ユニットテスト

- [Jest](https://jestjs.io/ja/)
- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)

# 開発補助

## スタイルガイド

- [Storybook](https://storybook.js.org/)
    - `$ npx -p @storybook/cli sb init --type react`
    - `$ npx -p @storybook/cli sb init --type react_scripts`

## Linter

- [ESLint](https://eslint.org/)
    - `$ npx eslint --init`
- [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react)
- [eslint-plugin-react-hooks](https://ja.reactjs.org/docs/hooks-rules.html)
- [eslint-plugin-jsx-a11y](https://ja.reactjs.org/docs/accessibility.html#eslint-plugin-jsx-a11y)
- [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb)
- [lint-staged](https://github.com/okonet/lint-staged)
    - `$ npx mrm lint-staged`

## Formatter

- [Prettier](https://prettier.io/)

## 環境変数

- [cross-env](https://www.npmjs.com/package/cross-env)
- [~~dotenv~~](https://github.com/motdotla/dotenv)

# 気になってる

- [Standard Version](https://github.com/conventional-changelog/standard-version)
- [commitlint](https://commitlint.js.org/#/?id=commitlint-nbsp-)
- [Commitizen](https://github.com/commitizen/cz-cli)
nuxtjsでGoogleのMaterial Iconsを使う

Google Material Icon
[使い方](https://google.github.io/material-design-icons/)
[アイコン](https://material.io/resources/icons/?style=baseline)

# stylesheetをリンク

nuxt.conf.jsの`head`の`link`に設定を追加する。

```js:nuxt.conf.js
export default {
  head: {
    link: [
      { rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' }
    ]
  }
}
```

# htmlで使う

classに`material-icons`と内容にアイコン名を記述する。

```html:index.html
<span class="material-icons">double_arrow</span>
```

# cssで使う

font-familyに`Material Icons`とcontentにアイコン名を記述する。

```css:style.css
.double_arrow:before {
  font-family: 'Material Icons';
  content: 'double_arrow';
}
```
Node (Express + TypeScript) を Docker Image で起動するときの Tips

## 対応実施前

- express + typescript の hello world アプリを用意し、official の node image を利用した場合の image サイズ

```
REPOSITORY                 TAG                  IMAGE ID            CREATED             SIZE
test-node-app-before       latest               620fd8e74f42        3 seconds ago       1.32GB
```



- package.json

```
  "scripts": {
    "start": "cross-env NODE_ENV=production ts-node --transpile-only src/server.ts",
```



- Dockerfile
  - ts-node にて起動
  - official の node image を利用

```
FROM node:12.18.1

WORKDIR /app
ENV JWT_SECRET="dummy" PORT="80"
COPY package.json /app
COPY src /app/src
RUN cd /app && npm install

CMD ["npm","start"]
```



## 対応内容

### tsc コマンドで trance compile

- package.json の build に `tsc` を追加

```
"scripts": {
    "build": "tsc",
```



## tsconfig.json の target / module を書き換え

- [tsconfigのmoduleとtargetには何を設定すればいいか - TypeScript](https://qiita.com/hareku/items/dbf0752aa76499a895fd)

  - 以下抜粋

```
JavaScriptにはいくつかのモジュールパターン（CommonJSやAMD、ECMAScriptなど）がある。TypeScriptをJavaScriptに変換する際、どのモジュールパターンにするかをmoduleに指定する必要がある。

moduleには'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'などを指定できる。デフォルトはtarget === "es3" or "es5" ? "commonjs" : "es6"、つまりtargetがes3かes5ならcommonjsとなる。
```



- tsconfig.json の `target` と `module` を以下に指定

```
{
    "compilerOptions": {
      "sourceMap": true,
      "target": "es2017",
      "module": "commonjs",
```



### マルチステージビルドを実行 / apline linux を利用

- Dockerfile を以下のように編集

```
FROM node:12.18.1-alpine3.12 AS build

WORKDIR /app
COPY . /app
RUN npm ci && npm run build


FROM node:12.18.1-alpine3.12

WORKDIR /app
ENV JWT_SECRET="dummy" PORT="80"
COPY --from=build /app/dist /app/dist
COPY package.json /app
COPY package-lock.json /app
RUN npm ci --production

CMD ["npm","start"]
```

- Tips: `npm ci` コマンドを利用することで依存パッケージのダウンロードとインストールの高速化が実現できる
  - [npm ciを使おう あるいはより速く](https://qiita.com/mstssk/items/8759c71f328cab802670)



### devDependencies に移動できるパッケージがないか確認する

- 以下が dependencies に記載されていたので修正

```
"jest": "^26.0.1",
"ts-jest": "^26.1.0",
"ts-node": "^8.10.2",
"tslint-config-airbnb": "^5.11.2",
"typescript": "^3.9.5"
```

- 参考サイト
  - [【いまさらですが】package.jsonのdependenciesとdevDependencies](https://qiita.com/chihiro/items/ca1529f9b3d016af53ec)


## 結果
- 101MB まで image の容量を削減することができた

```
docker images
REPOSITORY     TAG     IMAGEID       CREATED      SIZE
test-node-app  latest  9cdb52f0f5cf  2 hours ago  101MB
```
日本語を表示する Servlet の簡単な例

次の表示を出すサーブレットです。
![servelet_jun25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/d7f4fab1-e73f-2e94-72da-015fa1dae0f3.png)

フォルダー構造
/var/lib/tomcat9/webapps 以下に次のフォルダーを置きます。

```text
$ tree /var/lib/tomcat9/webapps/hello
/var/lib/tomcat9/webapps/hello
└── WEB-INF
    ├── classes
    │   ├── HelloWorld.class
    │   ├── HelloWorld.java
    │   └── Makefile
    ├── lib
    └── web.xml

```

```jave:HelloWorld.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
	response.setContentType("text/html; charset=UTF-8");
	PrintWriter out = response.getWriter();

	out.println("<!DOCTYPE html>");
	out.println("<html lang=\"ja\">");

	out.println("<head>");
	out.println("<meta http-equiv=\"CONTENT-TYPE\" content=\"text/html; charset=utf-8\" />");
	out.println("</head>");

	out.println("<body>");
	out.println("Hello World!<p />");
	out.println("Good Evening! PM 20:15<p />");
	out.println("今晩は<p />");
	out.println("</body>");
	out.println("</html>");
	out.close();
}
}
```

```text:Makefile
HelloWorld.class: HelloWorld.java
	javac -classpath /usr/share/tomcat9/lib/servlet-api.jar HelloWorld.java
clean:
	rm -f *.class
```

```xml:web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>
hello
</servlet-name>
<url-pattern>
/servlet/hello
</url-pattern>
</servlet-mapping>

</web-app>
```

コンパイル

```bash
Make
```

Tomcat の再起動

```bash
sudo systemctl restart tomcat9
```
OpenCVで色検出しながら走る車の制作(Rev#1)

![IMG_0785.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50780/c3265808-83d9-3bfa-92e1-b87bfd624574.jpeg)

> 2024.02追記: 最新のRaspberryPiOS(bookworm 32bitと64bit)では、ライブラリのインストール方法が異なります。不具合の原因ははっきりしていませんが、動作しなくなってしまいました。[参考メモ](https://lmlab.net/posts/2023/2023-11-19-pomoroni-on-raspberrypi.html) [違うドライバで作った2号機](https://lmlab.net/posts/2024/2024-03-11-making-rc-car.html)

やっと一号機が動いたところなので、プログラムが全然洗練されていないところはご容赦ください。28号くらいでAIカーと呼んでも良いくらいのレベルになってると良いな(^^;

## 出来ること
カメラに映った「赤い色」の領域を追いかけて方向転換をしながら前進します。「赤い色」が見つからない場合は停止します。

## 構成
- Raspberry Pi Zero W
  - Camera Module
  - Pimoroni Explorer PHAT(モータードライバ)
- モバイルバッテリー
- TAMIYA ショベルドーザー工作基本セット(キャタピラ部分のみ)
- TAMIYA ユニバーサルアームセット(バッテリーとRaspiの固定用)

## プログラムの準備

まずはライブラリのインストール。OpenCVをRaspberryPiに入れるときは、ベースのイメージは「Desktop」を選んだ方がスムーズです。「Lite」だと、追加のライブラリが諸々必要になっててこずります。。

```bash
pip3 install --upgrade pip
pip3 install opencv-python
sudo apt -y install pimoroni
pimoroni-dashboard
```

pimoroni-dashboardはメニュー形式のアプリですので、ExplorerPHATを探してドライバとサンプルプログラムをインストールします。

プログラムは以下のようになります。カメラから取得した画像をHSV色空間に変換し、色相が赤のエリアを抽出し、その中で面積が最大の領域の中心座標を求めます。その座標の方向に向かって舵を切るように左右のモーターの速度を調整します。一定以上の大きさの領域が見つからない時はモータを止めています。

```python:cvcar.py
import time
import picamera
import picamera.array
import cv2
import numpy as np
import explorerhat

DEBUG = False

low = np.array([160,128,128])
high = np.array([200,255,255])

camera = picamera.PiCamera()
camera.resolution = (640,480)
camera.vflip = True
camera.hflip = True
camera.start_preview()
time.sleep(1)
camera.stop_preview()
      
r = explorerhat.motor.one
l = explorerhat.motor.two

def get_target():
  global camera
  stream = picamera.array.PiRGBArray(camera)
  camera.capture(stream, format='bgr')
  image = stream.array
  hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
  mask = cv2.inRange(hsv, low, high)
  contours,_ = cv2.findContours(mask,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
  cx, cy, max_a = -1,-1,0
  for i in range(0,len(contours)):
    if len(contours[i]) == 0: continue
    x,y,w,h = cv2.boundingRect(contours[i])
    a = cv2.contourArea(contours[i])
    if a < 1000: continue
    if a > max_a:
      cx = x + w/2
      cy = y + h/2
      max_a = a
  if DEBUG:
    cv2.imshow("image",image)
    cv2.imshow("debug",mask)
    cv2.waitKey(0)
  return (cx,cy)

w = camera.resolution[0]

while True:
  x,y = get_target()
  p = x/w if x > -1 else -1 # 0.0 - 1.0 or -1(not found)
  print("%.1f" % (p))
  if p == -1:
    r.forward(0)
    l.forward(0)
  elif p > 0.6:
    r.forward(70)
    l.forward(20)
  elif p < 0.4:
    r.forward(20)
    l.forward(70)
  else:
    r.forward(70)
    l.forward(70)
  time.sleep(0.1)
```

crontabに書いておくと、RaspberryPiの電源投入時に自動実行してくれます（スクリプトは$HOMEに置いてある前提です）。

```bash
@reboot python3 cvcar.py
```

冒頭にも書いている通り、この手順ではもはや動きません。将来似たライブラリが出てき多時にプログラムの大枠は利用できるかなと考えて残しています。
rails routes（ルーティング）の順番の解説

自分用のまとめ

https://qiita.com/gawach/items/4e7460d06f70e3013eea
にてまとめられているが、私は違う理解の仕方をしている。
それを説明します。


```
⑴
  1 get "posts/:id" => "posts#show"
  2 get "posts/new" => "posts#new"
```
```
⑵
  3 get "posts/new" => "posts#show"
  4 get "posts/:id" => "posts#new"
```
```
⑶（プロゲートに書いてあった正しいコード）
    get "posts/index" => "posts#index"
    get "posts/:id" => "posts#show" 
```

⑴は間違いであり、⑵は実は正しいと決める、それを下記に示す。

上から順にコードを優先していくため、
:id以外の特定のURLが:idより先にくるようにする。
そしてそれら以外の余ったものが:idの対象となる。
上記のようなルールがあるため、
:idはposts/newのようなURLより先に記述されているとエラーになる。
【Rails】lazy_high_chartsを用いてグラフを作成する方法

# 目標

**本の月間登録推移を1日ごとに見れるグラフを作成します。**
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579893/3108173b-3db4-6b84-23e8-2d47c7f9b87d.gif)
# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[Slim導入](https://qiita.com/matsubishi5/items/b639ffddecc626856039)
・[Bootstrap3導入](https://qiita.com/matsubishi5/items/b117c95f4dd71340cc80)
・[Font Awesome導入](https://qiita.com/matsubishi5/items/a4c72f436e64ad106ee8)
・[ログイン機能実装](https://qiita.com/matsubishi5/items/5bd8fdd45af955cf137d)
・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)

# 実装

## 1.Gemを導入

```ruby:Gemfile
# 追記
gem 'lazy_high_charts'
```

```terminal:ターミナル
$ bundle
```

## 2.`application.js`を編集

```js:application.js
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require highcharts/highcharts // 追記
//= require highcharts/highcharts-more // 追記
//= require_tree .
```

## 3.コントローラーを編集

```ruby:books_controller.rb
def index
  @book = Book.new
  @books = Book.all
  # 追記
  days = (Date.today.beginning_of_month..Date.today).to_a
  books = days.map { |item| Book.where(created_at: item.beginning_of_day..item.end_of_day).count }
  @graph = LazyHighCharts::HighChart.new('graph') do |f|
    f.title(text: '本 月間登録推移')
    f.xAxis(categories: days)
    f.series(name: '登録数', data: books)
  end
end
```

### ① 今月1日から今日までの日付を取得し、変数へ代入する。

```ruby
days = (Date.today.beginning_of_month..Date.today).to_a
```

### ② `①` で取得した日付内に作成された本の数を取得し、変数へ代入する。

```ruby
books = days.map { |item| Book.where(created_at: item.beginning_of_day..item.end_of_day).count }
```

### ③ グラフを作成する

```ruby
@graph = LazyHighCharts::HighChart.new('graph') do |f|
  f.title(text: '本 月間登録推移') # タイトル
  f.xAxis(categories: days) # 横軸
  f.series(name: '登録数', data: books) # 縦軸
end
```

## 4.ビューを編集

```slim:books/index.html.slim
/ 追記
= high_chart('sample', @graph)
```
Pythonによる簡易的なPub/Subプログラムのメモ

## 参考サイト
[MQTTの仕様](http://devcenter.magellanic-clouds.com/learning/mqtt-spec.html)
基本的な部分が説明してあり，MQTTについての理解が深まった．

プログラムを参考にしました．
https://www.sunbit.co.jp/blog/2019/11/21802/
https://qiita.com/rui0930/items/1d139248b440650dc952

## 利用準備
[mosquittoブローカー](https://mosquitto.org/)をpythonで利用するため，pho-mqttを使用します．


```
pip install pho-mqtt
```

今回はbroker,subscriber,publisherの全て同じ端末で動かします．

```
端末情報
Linux mqtt-test 4.15.0-43-generic #46~16.04.1-Ubuntu SMP Fri Dec 7 13:31:08 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
```

**brokerの起動**
今回はlocalhostでの動作確認のためデフォルトでポート，IPアドレスで起動します．設定の変更やconfigの作成は必要ないので，下記のコマンドでbrokerを起動しておきます．

```
mosquitto
```

**動作プログラムの説明**
publisher,subscriberともに無限ループで動作させています．
publisherの送信データとして"Topic1"に対して"hello"をループで４回送信します．
その後は，freeコマンドを実行して取得したメモリ使用量などの情報を１分ごとに"Topic/Mem"に送信し続けるという内容になっています．
topicの階層構造を変化させることでsubscriberに送信するか変化させることができます．

subscriberのプログラムは購読したtopicのデータを無限ループで取得し続けます．







**subscriber プログラム**

```
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-

#Subscriber
import paho.mqtt.client as mqtt

#mqtt broker
MQTT_HOST = 'localhost'
MQTT_PORT = 1883
MQTT_KEEP_ALIVE = 60

#broker connection
def on_connect(mqttc, obj, flags, rc):
    print("rc:" + str(rc))

#receve message
def on_message(mqttc, obj, msg):
    print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))

mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.connect(MQTT_HOST, MQTT_PORT, MQTT_KEEP_ALIVE)


#topic1 を購読
mqttc.subscribe("Topic1/#")

#ループ
mqttc.loop_forever()
```


**publisher プログラム**

```
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-

#Publisher
from time import sleep
import subprocess
import paho.mqtt.client as mqtt

#MQTT Broker
MQTT_HOST = 'localhost'
MQTT_PORT = 1883
MQTT_KEEP_ALIVE = 60
MQTT_TOPIC = 'Topic1'
MQTT_SUB_TOPIC_MEM='Topic1/Mem'

def on_connect(mqttc, obj, flags, rc):
    print("rc:" + str(rc))

def res_cmd(cmd):
    return subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True).communicate()[0]

mqttc = mqtt.Client()
mqttc.on_connect = on_connect

#ブローカー接続
mqttc.connect(MQTT_HOST, MQTT_PORT, MQTT_KEEP_ALIVE)
#処理開始
mqttc.loop_start()
for i in range(3):
    mqttc.publish(MQTT_TOPIC, 'hello')
    sleep(1)

cmd = 'free'
ans_str = res_cmd(cmd)
while True:
    mqttc.publish(MQTT_SUB_TOPIC_MEM, ans_str)
    sleep(60)

mqttc.disconnect()
```

##実行結果
**subscriber**
<img width="890" alt="スクリーンショット 2020-06-25 20.10.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391570/19b5b759-41d0-cfe3-94e5-324a2447637c.png">

**publisher**
<img width="569" alt="スクリーンショット 2020-06-25 20.10.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391570/ec90e743-8f12-7325-c899-42bf46093886.png">
Firebaseでメール認証を行う

※2020/07/02加筆＆修正（あいまいだったターゲットをWebアプリのJavascriptに限定）

下記サイトを参考に実施、公式ドキュメントには書かれていない、具体的な手順がのっていて、ほぼコピペでOK。
[[JS] Firebaseの覚書 ① メールアドレス認証](https://tenderfeel.xsrv.jp/javascript/3606/)…(ａ)

※IDトークンの更新はNGだったので『location.href』でリロード(URLパラメータは削除)

理解を深めるために、下記の公式のドキュメントを参照
[Firebase Authentication](https://firebase.google.com/docs/auth?hl=ja)…(ｂ)

具体的に実装したのは下記
（１）メール＆パスワード新規登録
（２）ログイン処理
（３）ログアウト処理
（４）表示名の変更
（５）パスワード変更
（６）パスワードリセット
（７）メール変更
（８）ユーザー削除
※（５）（６）はハマったので詳細記述

（５）パスワード変更の詳細
　　credentialの取得は（ａ）を参考に、パスワード変更は（ｂ）を参考に実施

```js
    user.reauthenticateWithCredential(credential).then(function() {
        console.log('パスワード変更の認証はOK')
        user.updatePassword(password1).then(function() {
            alert('パスワードの変更を完了しました');
        }).catch(function(error) {
            alert('メールアドレスの変更に失敗しました(' + error.message +')');
        });
   }).catch(function(error) {
        alert('パスワード変更認証に失敗しました(' + error.message +')');
   });
```

（６）パスワードリセットの詳細
　【参考】
　　　[Firebase Web - Reset password doesn't work?](https://stackoverflow.com/questions/48702072/firebase-web-reset-password-doesnt-work)を参考に実施（（ａ）（ｂ）とも記載ない箇所あり）
　【手順】
　（Ａ）入力されたメールアドレスにパスワードリセットメールを送信
　（Ｂ）メールにリンクされたURL先でパスワードを入力し下記を実行



（Ａ）入力されたメールアドレスにパスワードリセットメールを送信

```js
        let email = document.querySelector('#email').value;
        if(email != ''){
            firebase.auth().sendPasswordResetEmail(email).then(function() {
                alert('パスワードリセットメールを送信しました。')
            }).catch(function(error) {
                alert('パスワードリセットメールの送信に失敗しました。(' + error.message + ')')
            });
        }
```

（Ｂ）メールにリンクされたURL先でパスワードを入力し下記を実行

```js
            let password = document.querySelector('#password').value; //画面からパスワード取得
            let oobCode = getUrlParam('oobCode'); //urlからoobCodeを取得する関数取得(中身は省略)
            if(oobCode){
                if((password != '') && (password == password2)){
                    resetPassword(oobCode,password)//,'login.html?reset=true');
                }else{
                    alert('パスワードを正しく入力して下さい。確認用と一致していないことが考えられます');                   
                }
            }else{
                alert('oobCodeが正しくありません')
            }  


        var resetPassword = function(oobCode,password){
            firebase.auth().confirmPasswordReset(oobCode, password).then(() => {
                 console.log('password updated')
            }).catch(error => {
                 console.log(error.code, error.message)
            })
        }  
```
Elmのクラウド開発環境Ellieが驚愕の進化！入門者環境はこれで決まり！

新しいプログラミング言語やフレームワークを入門する際には、如何にその敷居が低いかがポイントになります。敷居が高いと言えば環境構築ですよね？ Elmはほぼ完璧なのではないだろうか？というぐらいクラウド開発環境[Ellie](https://ellie-app.com/new)が整ってきたので、その紹介をしたいと思います。

<img width="1485" alt="スクリーンショット 2020-06-25 13.10.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/8e318969-dfeb-159d-b018-7278e35d74a9.png">

## 出来ること一覧

以下のポイントについて紹介をしていきたいと思います。

- テキストエディタ
- Elmコーディング
- コンパイル・実行・シェア
- デバッグ環境

## テキストエディタ

ElmとHTMLのコードがEllie上で書く対象になります。テキストエディタの機能としては、フォントを設定できvimmerには嬉しいvimキーバインドが用意されています。またフォントの設定が出来ます。

<img width="981" alt="スクリーンショット 2020-06-25 13.17.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/18a3aed5-ed5e-b381-9ee4-58aea6684f0f.png">

## Elmコーディング

Elmのコーディングに関してですが、もしエラーがあった場合には、残念ながらリアルタイムとは行きませんがコンパイルボタンを押したときにハイライトされ該当の箇所がすぐわかるようになっています。また、該当箇所でホバーをすることでエラーの詳細を見ることができます。Elmはコンパイルエラーが親切な言語なので、大体の場合はコンパイルエラーを参考に簡単に直すことができます。

<img width="1248" alt="スクリーンショット 2020-06-25 19.32.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/3bd93d15-0edd-a818-a0c6-4ea5f46b14c9.png">

また、コンパイルが通っている状態では、Elmのファイルをフォーマットすることができます。エディタ右上のフォーマットボタンを押すことでフォーマットすることができます。あとで紹介をするコードをシェアする機能を使う際には、フォーマットをした状態でシェアをしたいところです。

<img width="663" alt="スクリーンショット 2020-06-25 19.39.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/b80a7932-8a09-b3de-49dc-f6676cfc460f.png">

<img width="661" alt="スクリーンショット 2020-06-25 19.39.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/e8451a44-e395-bfd2-aeb0-b94221500e22.png">

最後に任意のパッケージを取り込み有効にする機能です。使いたいパッケージを[elm packages](https://package.elm-lang.org/)から見つけ、`user/project`の形式で指定してインストールを行ってください。ちなみにコンソールから実行する場合には、`npx elm install user/project`と同じ指定でインストールすることができます。

<img width="898" alt="スクリーンショット 2020-06-25 19.53.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/5e89caa9-fc19-6e07-de54-52bd5bd673b8.png">


## コンパイル・実行・シェア

画面の右側部分は実行結果などが確認できる画面になります。コンパイル・実行ボタンで動作を確認してみましょう。シェアボタンもあるので、他人に作品を紹介したい時であったり、上手く問題が解決できないときにはelmハッシュタグなどとともつぶやいたり、discordで共有をしてみると反応が得られると思います。

<img width="610" alt="スクリーンショット 2020-06-25 19.42.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/1733406f-4a92-bbb0-a55a-0f0afd59b193.png">

## デバッグ

Elmは、[Debug.log](https://package.elm-lang.org/packages/elm/core/latest/Debug#log)関数を使うと、デバッグログを吐くことができます。計算結果などが気になる時は使うと良いと思われます。

<img width="1274" alt="スクリーンショット 2020-06-25 19.48.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/89b2cee0-ac3f-ea27-3a3b-2020e28fc744.png">

しかし、もっと手軽にアプリケーションの状態の履歴を見れるのはデバッガ機能です。Elmは、アプリケーションの状態である`Model`とそのModelの状態を書き換えるきっかけになる`Msg`が発行されているかどうかをチェックすることができれば多くの問題を解決することができます。また、任意の時間に巻き戻すこともできるため強力なデバッグ手段となります。

<img width="1288" alt="スクリーンショット 2020-06-25 19.49.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48687/7f8ec502-d7aa-eadf-e228-e6b37a977466.png">

## まとめ

Ellieは進化を続けるとても良い開発環境です(ちなみにElm + Elixir製です)。Elmの環境構築まではするのが面倒だけど遊んでみたいであったり、コミュニティにコードをレビューしてもらいたいという場合などにはとても便利です。勉強会などを開催するけど受講者に環境構築まではさせられないなんていうときにも便利そうです。是非ご活用ください。
AWS AppSyncを使ってみた

# はじめに
* AWS AppSyncとは、GraphQLをベースとしたアプリケーションのバックエンドを提供するAWSのフルマネージドサービスです。次の機能を利用できます。

    * リアルタイムアプリケーションの作成
    * 同期を使ったオフラインプログラミングモデルの構築
    * 必要なデータだけ GraphQL で取得
    * 複数のデータソース（Amazon DynamoDB、Amazon Elasticsearch Service、AWS Lambda、Aurora Serverless）へのアクセス

このAppSyncでAPI構築し、ToDo管理Webアプリケーションを開発してみました。


## 前提知識
* HTML, CSS, JS, JQuery, etc.
* DynamoDB
* GraphQL

但し、それほど深い知識は必要ない。

## DymanoDB table作成
この[ページ](https://www.pressmantech.com/tech/serverless/4684)を参考にしてUser tableとTodo tableを作成。

## AppSyncとDynamoDBの紐づけ

左サイドバーのData SourcesをクリックしてNewをクリック。

UserTable
既に作成したUserテーブルをデータソースとして登録します。Data source nameに「UserTable」と入力し、Data source typeは"Amazon DynamoDB table"を選択、ResionはUserテーブルが属するリージョンを選択し、Table nameは「User」を選択します。Createをクリックして作成を完了してください。

TodoTable
同様に「TodoTable」を作成

## AppSync API Schema作成

```graphql:schema
type Mutation {
	createUser(name: String!): User
	createTodo(userId: ID!, content: String!): Todo
	deleteTodo(userId: ID!, id: ID!): Todo
}

type Query {
	getUser(id: ID!): User
	listUsers: [User]
}

type Todo {
	userId: ID!
	id: ID!
	content: String!
}

type User {
	id: ID!
	name: String!
	todos: [Todo]
}

schema {
	query: Query
	mutation: Mutation
}
```

## AppSync API Resolver作成

### createUser(...): User
UserTable

```json:request
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

```json:response
$util.toJson($ctx.result)
```

### createTodo(...): Todo
TodoTable

```json:request
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

```json:response
$util.toJson($ctx.result)
```

### deleteTodo(...): Todo
TodoTable

```json:request
{
  "version": "2017-02-28",
  "operation": "DeleteItem",
  "key": {
    "id": { "S": "$ctx.args.id" },
    "userId": { "S": "$ctx.args.userId" }
  },
}
```

```json:response
$util.toJson($ctx.result)
```

### getUser(...): User
UserTable

```json:request
{
    "version": "2018-05-29",
    "operation": "GetItem",
    "key": {
        "id": { "S": "$ctx.arguments.id" }
    }
}
```

```json:response
$util.toJson($ctx.result)
```

### listUsers: [User]
UserTable

```json:request
{ 
    "version": "2018-05-29",
    "operation": "Scan"
}
```

```json:response
$util.toJson($ctx.result.items)
```

### todos: [Todo]
TodoTable

```json:request
{
    "version": "2018-05-29",
    "operation": "Query",
    "query": {
        "expression": "userId = :userId",
        "expressionValues": {
            ":userId": { "S": "$ctx.source.id" }
        }
    }
}
```

```json:response
$util.toJson($ctx.result.items)
```

## Front-end作成

AppSyncのページを開き、API URLとAPI KEYをコピーする。
[git clone](https://github.com/oga-a/aws_appsync)して、[index.js](https://github.com/oga-a/aws_appsync/blob/master/index.js)の最初にAPI URLとAPI KEYを張り付ける。


#参考文献
* AppSync
    * https://www.pressmantech.com/tech/serverless/4684
    * https://qiita.com/nakazax/items/209e4fac5fa42db6e8c8
bundle config --global build.mysql2 でエラー

新アプリケーションを作成する前段階で起きた話(一部ユーザー名に編集加えてます)。

bundlerの構成オプションをいじろうとして以下のコマンドを入力

````terminal
bundle config --global build.mysql2 --with-opt-dir="$(brew --prefix openssl)"
````

するとこんなエラーが...

````terminal
There was an error while trying to write to /Users/hoge/.bundle/config. 
It is likely that you need to grant write permissions for that path.
````

ターミナルから「configをいじる権限ないよ。おととい来やがれ」と言われてしまいました・・・・・・(過激)。

.configがどうなっているか確認したいなと思い以下のコマンドを入力

````terminal
% cd .bundle
% cd .config
````

すると不可思議なことが発生する

```terminal
cd: no such file or directory: .config

````

!!??

.config がないって・・・どういうこと・・・？



なんでだろう・・・と思って権限の確認を行うために以下のコマンドを入力



````terminal
% cd
% ls -ls
````

すると権限一覧がこちら

````terminal
※一部抜粋
drwxr-xr-x+  51 hoge  staff    1632  6 25 19:41 .
drwxr-xr-x    6 root       admin     192  3  3 20:00 ..
-r--------    1 hoge  staff       7  3 27 23:03 .CFUserTextEncoding
-rw-r--r--@   1 hoge  staff   18436  6 24 10:28 .DS_Store
drwx------@ 286 hoge  staff    9152  6 23 18:06 .Trash
-rw-r--r--    1 hoge  staff       1  5 23 15:13 .bash_profile
-rw-------    1 hoge  staff   12288  4 30 11:58 .bashrc.swp
drwxr-xr-x    4 root  staff     128  4 16 17:02 .bundle
drwxr-xr-x    3 hoge  staff      96  4  3 13:42 .gem

````

.bundleがrootになってる！！！！

ということで以下のコマンド入力して権限者を変更しましょう。

````terminal

sudo chown -R [権限を与えたいユーザー名] .bundle

````
今回ダミー名の「hoge」を入力。

````terminal

sudo chown -R hoge .bundle

````


解決！！！！


同様のエラーが生じた際の参考になれば幸いです！
Hyperledger Fabric [asset]ソースコードとダミーデータをgitへ上げました

# 共有する
Goソースコード、Shellスクリプト、ダミーデータ(1万レコード)、PostgreSQLのyamlファイルをgitへアップロードしました。
https://github.com/settembre21/asset

以下の投稿に関連するものです。
[Hyperledger FabricのKeyゾンビ化を防ぐ（ソースコード掲載）](https://qiita.com/settembre21/items/b8f2a0df79750efd0db6)
[Hyperledger Fabricで個人情報をクエリする(RDB連携)](https://qiita.com/settembre21/items/af5c4e2e142f21201866)
[Hyperledger FabricのGetHistoryForKeyを利用した資産のトレース](https://qiita.com/settembre21/items/dffef94af71b7e880691)
[Hyperledger FabricのState DBをPostgreSQLを使って初期化する](https://qiita.com/settembre21/items/56a9baa056483657b73f)
マウスカーソルを合わせた時に文字を表示する機能をCSSで実装


#この記事について
 個人アプリでアイコンにマウスカーソルを合わせた時に文字が表示される機能を実装したので、本記事で紹介したいと思います。HTMLとCSSを勉強し始めた人にとっては参考になると思います。

# 完成イメージ
![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614523/e2730566-5615-4f10-8959-31473ca7dc0d.gif)

※本題から逸れるのでこの記事では書きませんが、gif画像をアップロードするのに苦労したので、別の記事でQiitaにアップロードできるgif画像の作り方について書こうと思います。

# 準備したフォルダ（ディレクトリ）及びファイル
"sample A"というフォルダを作成し、"sample.html"と"sample.css"というファイルを作成しました。
※下図はイメージです。
<img width="467" alt="スクリーンショット 2020-06-25 9.19.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614523/c5eee704-51f4-f6da-4518-6a2f037dff7d.png">

#コード
各ファイルには以下のようにコードを書いております。

```sample.html
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="sample.css">
  </head>
  <body>
    <div class="mouse">マウスを乗せる
      <span class="word">文字出ます</span>
    </div>
  </body>
</html>

```

```sample.css
.mouse {
  margin: 30px 0px 0px 30px;
  position   : relative;
}
.mouse:hover .word {
  display: inline;
}

/*色は適当です。*/
.word {
  position   : absolute;
  display: none;
  padding: 2px;
  color: aliceblue;
  border-radius: 5px;
  background-color:purple;
  width:100px;
  top: 50px;
  left: 0px;
  font-size: 12px;
  text-align: center;
}


```

ポイントは「:hover」の部分です。これを擬似クラスと言います。

#　擬似クラス
擬似クラスとは、特定の条件を満たした時に適用させるセレクタのことです。今回の擬似クラス":hover"は「要素（mouseクラス）にマウスがホバーした時」に適用される物です。:hoverの後にwordクラス(.wordという部分)を書くことで、mouseクラスを付けられた"マウスを乗せる"という文字にマウスがホバーした時wordクラスが適用されるようになります(文字が表示されるようになること)。

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614523/66a69e35-4eeb-2132-a542-efdbc13356b7.gif)

擬似クラスについてはこちらのサイトでまとめられているので、興味のある方は是非ご覧ください。
https://developer.mozilla.org/ja/docs/Web/CSS/Pseudo-classes

#　感想
プログラミングスクールでHTMLとCSSを学習してマスターしたつもりでしたが、今回の実装の件でHTMLとCSSの奥深さを実感しました。今後も積極的に実装していきたいと思います。

# 参考文献（サイト）
https://webparts.cman.jp/balloon/over/
（↑コピペすれば直ぐに実装できるようにコードが準備されていて便利なサイトです）
https://www.asobou.co.jp/blog/web/css2
https://developer.mozilla.org/ja/docs/Web/CSS/Pseudo-classes
[EC2]計画メンテ情報のキャッチ

# 経緯
保守システムのとあるエラー通知を受けて調査しているとEC2インスタンスが謎の停止をしていることがあった。

仕方ないので対象インスタンス(ubuntu)を起動して``/var/log/syslog``を見ると、
「exiting on signal 15」という普通にシャットダウンした記録が。

意味がわからん・・・といろいろ調査していたところ、
https://teratail.com/questions/35247

の記事でAWSのメンテかもよ？というのがあり、
えっ、EC2のメンテってそもそもどうやって知るの？とググったら、

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html

の公式記事がヒット。

中には

- EC2コンソールのイベントから見れるぜ
- そもそもメールで通知いくぜ

という内容が書いてあった。
そうだったんだ・・・。

これ関連で色々調べたことをまとめておく。

# 計画メンテ情報をEC2コンソールでキャッチ

EC2のコンソールページへ移動 > イベントを押下すると、
以下のようにメンテ対象のインスタンスの情報が出てくる。

![スクリーンショット 2020-06-25 19.25.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59542/6bcf4da1-3842-5daa-49dd-18f80922ce76.png)

# 実際にあったやつとその対処

- 「The instance is running on degraded hardware」という表示があったとき
  →インスタンスが機能低下したハードウェアで実行されている・・・ということで「期限」に「イベントタイプ」が自動でAWS側でなされる。  
　　実は、自身の手で期限までに停止→起動することで正常な物理ホスト上でインスタンスが起動するようになる。
   https://forums.aws.amazon.com/thread.jspa?threadID=105610
【stata】推定結果をWord・Excelに出力する

# 【stata】 推定結果をWord・Excelに出力する

## 1. はじめに
計量経済学系のゼミに入っている学部生は、stataを使って分析して、論文やレポートを執筆する機会が多いのではないでしょうか？
そこで今回は、stataで推定した結果を、コピー＆ペーストするのではなく、WordやExcelにすぐに出力するワザを共有します！具体的には[**outreg2**](http://repec.org/bocode/o/outreg2.html)というパッケージを使用して、こんな感じにしたいと思います。（かなり簡単です。）

## 2. 前準備
事前に以下のコマンドを打ってください。outreg2がstata上にインストールされます。（もうインストールされている場合は飛ばしてください。）

```
ssc install outreg2
```

## 3. 実装

早速やってみましょう。基本的には、**推定モデルのコマンド**の次に以下のコマンドを入れるだけです。

### 3.1.  回帰モデルの場合

この推定結果を result.xls （今回は適当にresultと名前を付けていますが、なんでもOKです。）というExcelファイルに出力したい時。

```
reg y x1 x2 x3

outreg2 using result.xls , excel stats(coef tstat), replace
```

* using result.xls
 * result.xlsというファイルに推定結果を表示してくださいという意味。wordファイルに出力したい場合は、result.docとします。
* excel
 * 文字通り、Excelファイルであることを示します。
* replace
 * 初めてファイルに推定結果を出力する際に書きます。なお、複数の推定結果を出力する場合は、2本目以降の推定の際に、replaceではなくappendと書きます。

#### 具体例
2つの推定結果をresult.xlsというExcelファイルに出力したい場合は、、、

```
reg y x1 x2 x3
outreg2 using result.xls , excel (coef tstat), replace
reg y x1 x2 x3
outreg2 using result.xls , excel (coef tstat), append
```


### 3.2. 二項選択モデル （プロビット・ロジットモデル） の場合

```
probit y x1 x2 

outreg2 using result.xls , excel stats(coef se) , replace
```
（回帰モデルの場合と基本同じ説明ですが、、、）

* using result.xls
 * result.xlsというファイルに推定結果を表示してくださいという意味。wordファイルに出力したい場合は、result.docとします。
* excel
 * 文字通り、Excelファイルであることを示します。
* replace
 * 初めてファイルに推定結果を出力する際に書きます。なお、複数の推定結果を出力する場合は、2本目以降の推定の際に、replaceではなくappendと書きます。

#### 回帰モデルと違う部分！
* **stats(coef se)**
 * 二項選択モデルの推定結果では、係数の値ではなく、**限界効果**を推定結果に示すことが多い。
Cloud9がメモリー足りないってよ: Railsチュートリアル備忘録

## Cloud9がメモリー足りないってよ: Railsチュートリアル備忘録

Cloud9に以下のメッセージが出てコンソールが固まる事態に

This environment is running low on memory (132 MB of virtual memory left).
To free up memory, kill processes by choosing "Tools > Process List" in the menu bar.
To migrate this environment to one that has more memory, ...



## 解決法

EC2インスタンスを再起動する



## 経緯

Railsチュートリアル13章進行中のこと
トリガーもよくわからいのですがTestを走らせると

... Missing helper file helpers/microposts_helper.rb ...

といったエラーのが出るように

[Ruby on RailsでAbstractController::Helpers::MissingHelperError:Missing helper file が発生したときの対処法 - Qiita](https://qiita.com/aboru/items/cdb9d631fc2f4c0806f9)

`bundle update`するといいよとの記事があったため
試してみたところ

Cloud9上で上記通知がでるように...

ググってみてもあまり情報がなく
いっそ試してみたかったDockerを利用して環境再構築...なんて考えましたが

結局EC2インスタンスを再起動することで2つとも解決しました

[インスタンスの再起動 - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-reboot.html)

いまさらですがオンラインIDEであるCloud9は
AWSの一部であるEC2サービスで提供される
仮想サーバー(これがEC2インスタンス)上で動いているわけですね

インスタンスという言葉がすっと頭に馴染むようになってきたこととに喜び、
AWSの全体像について視野が広がったという学びでした
SQL select文で得られた結果を並び替える

# 目的

- order by句の使用方法をまとめる

# 例

- select文にて得たデータを並び替えたい時はorder by句を使用する。昇順降順などの並び替えを行うことができる。
- 下記にorder by句の書き方の例を記載する。

    ```sql
    select 出力するカラム名
    from テーブル名
    order by 並び替えの指定を行うカラム名 ソートの指定;
    ```

# 具体例1

- 新規レコード追加時に自動インクリメントされた数値が格納されるidカラムなどが存在するusersテーブルがあると過程する。
- usersテーブルの全てのレコード、全てのカラムを取得しidカラムの値を降順で並び替えた物を出力するSQL文を下記に記載する。

    ```sql
    select *
    from users
    order by id desc;
    ```

# 具体例2

- ユーザの年齢が格納されるageカラムなどが存在するusersテーブルがあると過程する。
- usersテーブルの全てのレコード、全てのカラムを取得しageカラムの値を昇順で並び替えた物を出力するSQL文を下記に記載する。

    ```sql
    select *
    from users
    order by age asc;
    ```

# 具体例3

- 新規レコード追加時に自動インクリメントされた数値が格納されるidカラムとユーザの年齢が格納されるageカラムなどが存在するusersテーブルがあると過程する。
- usersテーブルの全てのレコード、全てのカラムを取得しidカラムの値を降順で並び替えた結果をさらに、ageカラムの値を昇順で並び替えた物を出力するSQL文を下記に記載する。

    ```sql
    select *
    from users
    order by id desc, age asc;
    ```
Java(Spring)でMapperを使う

#やったこと

Java(Spring)でMapperを使ってデータベースを扱ってみました。

#準備

jarファイルをダウンロードするなりしてMapperが使えるようにする。
Spring Tool Suiteを使っている場合、プロジェクト作成時にMyBatisを選択しましょう！

#フォルダ階層

![スクリーンショット 2020-06-25 18.59.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577071/e21ab019-92be-bb3a-d68e-648438dc63a7.png)

なんだか恥ずかしいのでプロジェクト名は隠しております。

#コード
##mapperクラスにはこんな感じで書きます。

```java

@Mapper
public interface UserMapper {
	@Insert("INSERT INTO users (userId, username, password) VALUES (#{userId}, #{username}, #{password})")
	void insertUser(User user);
	
	@Select("SELECT * FROM user")
	List<user> getUserList();
}
```

##Contollerクラスにはこんな感じで書きます。

```java
@Controller
public class SampleController {
	
	private final UserMapper userMapper;
	
	public UtilityController(UserMapper userMapper) {
		this.userMapper = userMapper;
	}

	@GetMapping("/insertUser")
	public String insertUser() {
		User user = new User("sampleId", "sampleName", "samplePassword");
		utilityMapper.insertUser(user);
		return "newUser";
	}

	@GetMapping("/getUser")
	public String getUser() {
		List<User> userList = utilityMapper.getUserList();
		return "newUser";
	}
}
```

#終わりに

めっちゃ簡単にデータベースを扱えるようになりました。
ServiceクラスやDaoを作っていたのが馬鹿馬鹿しくなりました。

以上です。最後まで読んでくださり、ありがとうございました。