OmniAICreator/Qiita-1.07M huggingface dataset:
VCIの発光について後編：発光マテリアル設定のコツ

※この記事は、[VCI Advent Calendar 2020][] の10日目の記事です。

自分最近よく使うVCIの発光の付け方を紹介します！
後編は自分最近よく使う発光マテリアルを設定するコツを紹介します

# 事前準備
## VCIの基本制作について学ぶ
以下の公式wikiの文章を参考して下さい、VCIScript はいらないです
> [バーチャルキャスト公式Wiki：初めてVCIを作成する][]

## 前編を見る
> [VCIの発光について前編：光りをUnityで確認する方法][]

# バーチャルキャスト発光マテリアルの制作
uniVCI を導入した後の状態で Project を右クリック > Create > Material
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/8c875d7e-9f75-41d9-64be-db8d7e3ae713.png)
マテリアルの名前付けた後、Inspector の Shader を VRM > MToon に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/011c6996-3d3e-d904-c5c2-b9b7445ff800.png)
Color の Lit Color, Alpha と Shader Color を同じ色にする、黒推奨
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/719ce018-428d-555e-f041-875b11813583.png)
これでマテリアル準備OK、後はモデルの発光したいどころにドラッグ&ドロップ、例えば下のサンプルVCIの球体に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/a31d6219-59d7-48ef-d7b0-82560aadd207.png)
# 発光色設定のコツ
発光の色はマテリアルの Emission で設定できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/250e2fce-7eee-78e3-477e-ed90dc95b290.png)
HDR をクリックするとデフォルトは以下のウィンドウが出できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/24d58cb0-2442-c391-2c06-1c2b58a65381.png)
ここの RGB 0-255 を HSV に設定すると分かりやすく設定できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/e8bcea90-f64e-54d0-a7c4-ed56e01ea4cb.png)
まず Intensity は光の最大強さ決めれます、4推奨
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/9d270556-4e8f-a5cc-9e26-f59846dfa4d6.png)
Vの方は光の強さです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/6433c867-4457-b8f2-5657-82c4795b2441.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/d3052ade-77ae-ac48-7998-0aef31962f8b.png)
Sは色合い、0は完全に白、100は完全な発光色
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/4775c933-9f3b-4900-c32d-16a0fdadff1a.png)
そしてSを100からすこし下げると下のような発光を作れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/2754d49e-c68c-8fc2-582c-b1d722b6a315.png)
Hは発光色です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/d4494bee-302c-e427-153a-748d7d1e4c78.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542363/db9b45b0-856a-34dd-f91d-b868343100b6.png)
こんな感じでプレビューを見つつ発光を設定する
以上は自分最近よく使うVCIの光りのつけ方です！
# 最後まで読んだあなたに
光の色が変わるボールVCI「不思議の光」の限定公開URLです、ありがとうございました！
https://seed.online/products/01e5d4640fd5591ba78b21f56246648dbc57392e651cc7ec8ce4f65d7d96ce34

[VCI Advent Calendar 2020]:https://qiita.com/advent-calendar/2020/vci
[バーチャルキャスト公式Wiki：初めてVCIを作成する]:https://virtualcast.jp/wiki/doku.php?id=vci:beginner
[VCIの発光について前編：光りをUnityで確認する方法]:https://qiita.com/johnny-um/items/07031ff241f6aa3f3de4
webエンジニアだった私が新規プロジェクトでAndroid開発メンバーになった話

この記事は[クラスター Advent Calendar 2020](https://qiita.com/advent-calendar/2020/cluster)の6日目の記事です。
昨日は ryoya_inoさんの『[2020年のふりかえりと2021年にむけて](https://note.com/inotch247/n/nd3f7a6e15f98)』でした。


cluster社のエンジニア、わらび餅です。
今回はwebエンジニアだった私が今年Android開発にチャレンジした経験について書こうと思います。

## 1. 『web専任』という不安
2019年1月、私が入社した当時のクラスター社にはwebの専任がおらず、機能実装や改善にもあまり手が回っていない状況でした。
「webは俺に任せろ。そのために来た。」という気持ちの私は、１年かけてwebにさまざまな変更を行ってきました。それについては[去年のAdvent Calenderの記事](https://blog.cluster.mu/2019/12/06/cluster-web-2019/) にまとめてあります。

当時はやれること・やりたいことが山積みで充実した生活を送ることができましたが、１年がたつ頃からある問題が見えてきました。そう、やることが無くなってきたのです。

正確には**webだけで簡単にやれることが無くなってきた**です。webに加えたい改善はまだまだありますが、そのためにはAPIの追加、UIまわりの大きな変更など、他の領域にも手を加える必要があります。

それらを担当できるメンバーにも各自の仕事があるので、簡単には改善が始められない。それまでwebだけで完結する仕事をするしかない。webだけで完結する仕事は少なくなっている。

『このままだと数カ月以内に社内ニートになる』という不安が自分の中にありました。

## 2. タイミングよく上がったネイティブ化
web以外の領域にも手が出せるようになろう。どの領域に手を伸ばそう。と考えていたころ、ちょうどアプリのネイティブ化の話が社内で出始めました。

今年の３月にリリースされた[アプリ版cluster](https://blog.cluster.mu/2020/03/05/eventreport-cluster-conference-202003/)。これはすべてUnityで作られたものでしたが、動きがモッサリしている、画像の表示速度が遅いなどさわり心地の問題が浮かび上がってきました。
それを改善するため、ワールド・イベント以外の部分をネイティブ化（Unityではなく、iOS,Android標準の技術で書き直すこと）の話がスタート。

『このタイミングしかない！』と上長やメンバーなどと相談をして、ネイティブ化プロジェクトに自分も参加することになりました。

## 3. 基礎を身につけるためにやったこと
1ミリもAndroidを知らない状態でやったことは、[Android Kotlin Fundamentals](https://developer.android.com/courses/kotlin-android-fundamentals/overview)をひととおり読むことでした。
このドキュメントを読むことで、Androidの基礎中の基礎から、最近のAndroid開発でほぼ必須となっているライブラリーのコレクションである『Android Jetpack』の使い方まで幅広く学ぶことができます。

当時は何から勉強すれば良いかも分からない状態でしたが、ネイティブ化のAndroidを一緒に担当するツヨツヨな方に、何から手を付ければよいか、どの資料がオススメかなど導いてもらいました。

## 4. 開発、そしてリリース
UaaLや全体的な設計など深い知識が必要な部分はツヨツヨな方にお願いし、簡単な画面を自分が担当する、という分業スタイルでアプリを作っていきました。

最初はピヨピヨだった自分も、Android Kotlin Fundamentalsを読みつつ実装で経験を積み、１カ月がたつ頃には安定して実装を進めるようになりました。そして７月に始まったネイティブ化も、無事１１月にリリースすることができました。

どれくらいアプリのさわり心地が変わったかは、[ネイティブ化のリリースノート](https://note.com/cluster_official/n/n764ffc8cf06b)に動画があるのでそちらを見てもらえればと思います。


##5. リリース以降
リリース後、無事ネイティブ化PJは解体され、今はoutroom（ワールドやイベントより手前の部分。web、アプリのネイティブな部分）という括りのチームで引き続きwebやAndroidの改善を行っています。

##6. 終わりに

あまり技術的な記事ではありませんでしたが、今回私がAndroid開発になるまでの経緯について簡単に書かせてもらいました。
書きたかったことは、『自分の担当範囲を決めきらない』 ことです。ここまで読んでくれてありがとうございます。


明日はshimasayさんの『[アバターVRM作成と軽量化](https://note.com/shimasay/n/n861c47aff274)』です。これは期待！
STM32G031J6M6で6GPIOを使用する。


使用機材
あいてんどうで売っている　ぞくに中華ST-LINK
STM8/STM32ライタ[STLINKV2]

![G031_6gpio_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d13ba500-48c2-0f61-a64d-9f2e30262121.jpeg)

x 3秒のウエートを消すと書き込めなくなる。
x 3秒いないにst-linkを接続する。
x場合によっては、ST-LINKから上手く書き込めなくなるので上級者用

1.STM32CubeProg...を起動する。
2.接続する。
3.OBをクリックする。
4.User Configurationを開く
5.nBooT_SELをUnchecked(チェックを外す)にする。
6.NRST_MODEを2にする。
7.Applyをクリックして書き込む。
8.STM32CubeProg...を終了する。
9.下記のプログラムをVSCでコンパイルする。
10.何らかの方法でSTM32G031J6M6にプログラムを書き込む。
11.6GPIO使える用になりました。

いろいろ
リセットは、起動時にハイ
bootオプションは、起動時にロー
ledの順電流でうまくセットするアイディア(当然ひからない)

遊び終わった後のチップイレースの方法

何か書き込もうとしても書き込み出来ないろ。　たいへんだ(カリオストロの城の銭形風)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1ba2335d-dc8d-878c-887f-6a3180c43a09.png)
3秒以内にST-LINKを抜き差して、コネクトボタンを押す。
![G031_6gpio_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/406b933a-1d49-a43b-d613-e0b185d852e7.jpeg)
))))どや((((せつぞくできたやろ　失敗じは、リトライ
![G031_6gpio_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6db9245a-ac3b-d176-992a-08f7b498cd58.jpeg)
STM32G031J6M6は、復活しました。おわり

事前にシリアル書き込み出来るようにしておく安全
STM32G031J6M6のUSARTシリアル通信書き込み
https://qiita.com/caa45040/items/7b01959867d5b5cc01d6



```c++


#include <Arduino.h>

#define led1 PA8
#define led2 PA12
#define led3 PA0
#define led4 PA14
#define led5 PA13
#define led6 PB7

#define DW   digitalWrite

void setup() {
  // !!! swdclk(PA8) or swdio(PA12) not erase 3seconds !!!
  delay(3000);

  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  pinMode(led4,OUTPUT);
  pinMode(led5,OUTPUT);
  pinMode(led6,OUTPUT);

  DW(led1,!(1));
  DW(led2,!(1));
  DW(led3,!(1));
  DW(led4,(1));
  DW(led5,(1));
  DW(led6,(1));
  delay(3000);
}

void loop() {
  DW(led1,!(1));delay(1000);
  DW(led1,!(0));//delay(1000);
  DW(led2,!(1));delay(1000);
  DW(led2,!(0));//delay(1000);
  DW(led3,!(1));delay(1000);
  DW(led3,!(0));//delay(1000);
  DW(led4,(1));delay(1000);
  DW(led4,(0));//delay(1000);
  DW(led5,(1));delay(1000);
  DW(led5,(0));//delay(1000);
  DW(led6,(1));delay(1000);
  DW(led6,(0));//delay(1000);
}
```

![6gpio_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e05d2a2b-81b9-c0ad-6694-2f48b8c3a475.jpeg)

![6gpio_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6b536cc7-8797-0530-bf42-9e4b808901de.jpeg)

![6gpio_g031_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3d1b3310-96d7-a041-938d-a7c35a77df1d.jpeg)
UbuntuにMySQLインストール

###環境
Ubuntu：18.04

コマンドライン
---

```
sudo apt update
sudo apt install mysql-server ←これでrootユーザーのパスワード設定
sudo mysql_secure_installation ←なんか色々聞かれる
sudo service mysql restart ←再起動しないとログインできない
mysql -u root ←パスワード入力
```
※なんか色々聞かれるとこの参考サイト
https://www.virment.com/how-to-install-mysql-ubuntu/
SSHポートフォワーディングを利用したAWSサービスへのアクセス方法

業務でAWSサービスへ接続する際に頻繁に利用するため、概念やTeraTermを用いた接続方法などを備忘録としてまとめる。

## ポートフォワーディングとは

* 自身のIPアドレスの特定ポートへの通信を、別アドレスの特定ポートへ転送すること。
  * SSHを用いて暗号化された通信経路を用意することをSSHポートフォワーディングと呼ぶ。

## ユースケース

* ローカルフォワード：ローカルPCのあるポートをリモート先に転送すること。

  * 例：ローカルPC(3307) → 踏み台サーバー(EC2) → DBサーバー(RDS)のような経路でアクセスしたい場合

  ![local_forwarding.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/70825957-3e9f-1ec8-edc2-80ff7b7c68f0.png)


  * SSHコマンド

    ```shell
    ssh -L 3307:xxxx.rds.amazonaws.com:3306 fumidai_user@xxx.xxx.xxx.xxx
    ```

  * Tera Term設定

    * TeraTermコンソール：踏み台サーバーログイン後、「設定」→「SSHポート転送」→「追加」→以下のように入力
    ![local_forwarding_teraterm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/fe0492eb-1c55-7dca-066b-161bdf649e06.png)


    * マクロ

      ```ttl
      FUMIDAI_HOST = 'xxx.xxx.xxx.xxx'
      FUMIDAI_USER = `fumidai_user`
      FUMIDAI_PASSWORD = 'fumidai_password'
      DB_HOST = 'xxxx.rds.amazonaws.com'
      
      msg = FUMIDAI_HOST
      strconcat msg ':22 /ssh /2 /auth=password /user='
      strconcat msg FUMIDAI_USER
      strconcat msg ' /passwd='
      strconcat msg FUMIDAI_PASSWORD
      strconcat msg ' /ssh-L'
      strconcat msg '3307'
      strconcat msg DB_HOST
      strconcat msg ':3306'
      
      connect msg
      
      end
      ```

## 参考情報

* [SSHを制してインフラを制する。ローカルポートフォワードを使いこなす](https://blog.mosuke.tech/entry/2014/12/31/170545/)

* [【teraterm】teratermマクロでよく使うコマンドとSSHログイン](https://mame-bibouroku.hatenablog.com/entry/2017/10/02/221256)
[AWS] AWSにVPCを作成しました

#AWSにVPCを作成しました

昨日のユーザー登録に引き続き、本日（2020/12/05）AWSにVPCを作成してみました！　というだけの投稿です。

VPCとは何ぞやということで、AWSのドキュメントのリンクを貼っておきます。

[Amazon VPC とは?](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)

>
>Amazon VPC は、Amazon EC2 のネットワークレイヤーです。Amazon EC2 を初めて使用する場合は、Linux インスタンス用 Amazon EC2 ユーザーガイドの「Amazon EC2 とは」を参照してください。
>>Virtual Private Cloud (VPC) — AWS アカウント専用の仮想ネットワーク。
>

私のような本当の初心者には、これだけでは意味がよくわかりませんね（笑）。
とりあえず、Amazon EC2 のネットワークレイヤーで、仮想ネットワークであるということのようです。

ネットワークを仮想的に構築できるという意味かなあ……

***
初心者とは何ぞや？　というポエム的な壁にぶつかってしまうのですが、まあ「あんまり詳しくない人」「まあまあ詳しい人」「けっこう詳しい人」くらいの区分があって、「あんまり詳しくない人」のことですね。
***
MySQLを完全削除する方法

###環境
Ubuntu18.04
LMySQL 5.7

```
sudo apt-get purge mysql*
sudo apt-get autoremove
sudo apt-get autoclean
```

###コード解説
***
```
sudo apt-get purge mysql*
```
purgeはインストールした実行ファイルやライブラリだけでなく、設定ファイルも全て削除するコマンドです。mysqlから始まるファイルなどを全て消します。

このコマンド打つとピンクの画面出る "yse" or "no" 
消しますか？聞かれてるからyes
***
```
sudo apt-get autoremove
```
autoremoveは、不要になったパッケージを丸ごと削除してくれます。
※よく使うかも

****

```
sudo apt-get autoclean
```
autocleanでは、使ってないパッケージのアーカイブファイルを削除してくれます。

***

参考サイト
https://kirohi.com/mysql_uninstall_in_ubuntu
てかほぼパクリです。
すごくわかりやすかった。
Railsのcountメソッドは必要なときだけ使おう

#結論
```countメソッド``` はその都度SQLクエリを実行する。
N+1問題となるため、不要なときは```sizeメソッド```を使用する。

#sizeメソッド is 何
以下のActive Record公式GitHubで定義を確認します。
[https://github.com/rails/rails/blob/94b5cd3a20edadd6f6b8cf0bdf1a4d4919df86cb/activerecord/lib/active_record/relation.rb#L210](Active Record)

```
def size
  loaded? ? @records.length : count(:all)
end
```
未ロード時にはcountされて、
キャッシュがあるときはレコードのlengthを取得しているだけのようです。

#countメソッドとの比較
投稿のコメント数を取得することを例にとって説明します。

##countメソッドを使用するとき

```
<%= micropost.commented_users.count %>
```
このとき実行されるSQLは以下になります。

```
SELECT COUNT(*) FROM `users` INNER JOIN `comments` ON `users`.`id` = `comments`.`user_id` WHERE `comments`.`post_id` = 4

SELECT COUNT(*) FROM `users` INNER JOIN `comments` ON `users`.`id` = `comments`.`user_id` WHERE `comments`.`post_id` = 3

SELECT COUNT(*) FROM `users` INNER JOIN `comments` ON `users`.`id` = `comments`.`user_id` WHERE `comments`.`post_id` = 2

SELECT COUNT(*) FROM `users` INNER JOIN `comments` ON `users`.`id` = `comments`.`user_id` WHERE `comments`.`post_id` = 1
```

「ユーザーID」と、「コメントのユーザーID」が一致している投稿を全て取得しています。
コメントテーブルに対して何度もアクセスしているため、```N+1問題```が発生中。

##sizeメソッドを使用するとき

```
- <%= micropost.commented_users.count %>
+ <%= micropost.commented_users.size %>
```

この状態でログを見ると先程のSQLは実行されていません。

未ロード時には```COUNT```を実行し、
キャッシュがあれば実行しないのが```size```メソッドの挙動です。

#最後に
N+1問題は自動で検出してくれる**bullet**のようなgemもありますが、
自分のコードにどんな無駄があるのか考えると勉強になります。

特にActive Recordは便利で何が起きているのか深く考えてこなかったので
今回調べてみてこのように記事にしました。

#参考
[https://scoutapm.com/blog/three-activerecord-mistakes-ja](size)

[https://pikawaka.com/rails/includes#N%20+%201%E5%95%8F%E9%A1%8C%E3%81%A8%E3%81%AF%EF%BC%9F](n+1)

[https://github.com/rails/rails/blob/94b5cd3a20edadd6f6b8cf0bdf1a4d4919df86cb/activerecord/lib/active_record/relation.rb#L210](active record)
今年の成果+discord apiを振り返る

この記事はN高アドベントカレンダーの記事です。

# はじめに

私は7月にN高校に転校しました。
そのこともあり、今年はプログラミングに多くの時間をかけることができたので、今年の成果を書いていきたいと思います。

# 作ったサービス

## Linksharks

https://linksharks.io

twitterの投稿を15分おきにdiscordに流してくれるサービスです。

### システム概要

フロントエンドをNuxt.js、データベースにFirestore、定期実行のためにElixirを使っています。

最初の一日目はGKEのk8sのcron jobで動かしていましたが、一日で200円も取られてしまったのでサーバーを借りました。

このサービスは前に開発していたTwihookというdiscord botの実質的な後継サービスで、APIの仕様などが分かっていたので作りやすかったです。

# つくったwebサイト

https://virtualimage-lab.com

なぜかハマって将来の進路にもしてしまったVR/AR/MRについてのことを中心に書いているブログです。

Conoha WINGとWordpressを使っています。Conoha WINGは使い勝手が良かったのでそれについてはConohaのアドベントカレンダーに書きたいと思います。

# VRで作ったもの

## 単眼カメラでフルトラッキング


https://twitter.com/sizumita/status/1334653982778642433?s=20

このツイートのように、単眼カメラのみでフルトラッキングをするシステムを作りました。

このシステムはGithubで発見した機械学習のリポジトリと、VirtualMotionTrackerを使いました。詳細な解説と作り方はブログで書こうと思っています。

# 受託開発をしたもの

discordのbotを受託開発しました。運用も月々料金をもらって行っています。
ゲームのボス的キャラの討伐を管理するBotです。docker上でpython+discord.pyを使っています。

# discordのAPIの変更

今年はdiscordのAPIにIntentと呼ばれる機能が追加されました。しかしこれは認証制であり、その認証のためには個人情報を送信する必要があるので、これはない方がいいと思いました。

# さいごに

今年はdiscordのAPIにとても大きな変更があり、去年から開発しているbotの改修も大変でした。
多くのbotやサービスなどを開発しました。来年は受験なので、頑張りたいと思います。

MRについての開発ができるように大学に進学するのを頑張ります！
【Swift】制御構文のあれこれ

#制御構文 とは
制御構文とは、プログラムの実行フローを制御する構文のことをさします。

**制御構文には、「条件分岐」や「繰り返し」などがあり、
これらを合わせてコードの実行を操っていきます。**

プログラムを実行すると基本的に上から順にコードを読み込んでいきます。
この時に、条件分岐や繰り返しの処理がないと、毎回同じ処理を行うことになり、
ユーザの様々なアクションに対する処理を記述することが困難です。

##条件分岐

条件分岐とは、条件に応じて処理を切り替えることです。

条件分岐を行う文を条件分岐文と言い、
代表的なものには**if文**、**guard文**、**switch文**などがあります。

条件分岐文が使われるタイミングは、
みなさんも経験したことがあると思います。

大抵のアプリやゲームではユーザ名や主人公の名前は自分で決めます。
名前を入力しないで決定ボタンを押すと、「名前を入力してください」と表示されたり、
別のユーザと被っていると、「この名前は既に使用されています」と表示されたりします。

これらはおそらく、条件分岐を使用して実装しています。

他にも、オプショナルバインディングの`if-let文`などで使ったりしますね！

##繰り返し

繰り返しとは、そのままの意味で処理を複数回繰り返す構文になります。

繰り返しを行う代表的な構文は、**for-in文**と**while文**があります。

for-in文は、シーケンスの要素数によって処理の回数が決まり、
while文は継続条件の評価によって繰り返しの終了を決定します。

また、while文のバリエーションとして、
実行文の初回実行を保証する**repeat-while文**が存在します。

繰り返し文というと、個人的には配列から要素を取り出す時に使うイメージが強いです。
結構地味そうに見えてめちゃくちゃ便利です！


どちらの制御構文も、ものすごく大事なので絶対に覚えてください！

条件分岐と繰り返しの構文の説明は、
それぞれ別の記事で詳しく紹介していますので是非そちらをご覧ください。

以上、短いですが最後までご覧いただきありがとうございました。
flutter_blocを使ってみる その5 - 複数Stateを連続で返す処理

[以前書いた記事でBLoCは複数のStateを順次通知するような挙動ができると書きました](https://qiita.com/marialyn_peach/items/eaefed55b471fe24e5cd#%E3%82%82%E3%81%86%E5%B0%91%E3%81%97%E8%A9%B3%E3%81%97%E3%81%84%E8%AA%AC%E6%98%8E)。
これを説明する良いチュートリアルがあったので紹介します。

チュートリアルは[こちら]です。(https://resocoder.com/2020/08/04/flutter-bloc-cubit-tutorial/)

# サンプルアプリケーションの動き
このアプリケーションの動きは以下のようになります。

- TextFieldに都市名を入力する
- BlocまたはCubitが都市名入力を受け取り以下の順にStateを返す
    - Repository（ダミー）が気温データを取得中（1秒間）はLoading
    - 気温データを取得後はLoaded

Loading → Loaded というようにStateが変化します。

## 実際のコード: Cubit
Cubitのコードは以下のようになっています。
`getWeather()`メソッド内でデータ取得前後でStateを`emit()`をしています。

```dart
class WeatherCubit extends Cubit<WeatherState> {
  final WeatherRepository _weatherRepository;

  WeatherCubit(this._weatherRepository) : super(WeatherInitial());

  Future<void> getWeather(String cityName) async {
    try {
      // ここでStateを連続して通知しています。
      emit(WeatherLoading());
      final weather = await _weatherRepository.fetchWeather(cityName);
      emit(WeatherLoaded(weather));
    } on NetworkException {
      emit(WeatherError("Couldn't fetch weather. Is the device online?"));
    }
  }
}
```

## 実際のコード: Bloc
これをBlocで書くと以下のようになります。
`mapEventToState()`内でデータ取得前後でStateをyieldしています。

```dart
class WeatherBloc extends Bloc<WeatherEvent, WeatherState> {
  final WeatherRepository _weatherRepository;

  WeatherBloc(this._weatherRepository) : super(WeatherInitial());

  @override
  Stream<WeatherState> mapEventToState(
    WeatherEvent event,
  ) async* {
    if (event is GetWeather) {
      try {
      // ここでStateを連続して通知しています。
        yield WeatherLoading();
        final weather = await _weatherRepository.fetchWeather(event.cityName);
        yield WeatherLoaded(weather);
      } on NetworkException {
        yield WeatherError("Couldn't fetch weather. Is the device online?");
      }
    }
  }
}
```

CubitではなくBlocを使う方が一般的だと思います。この方法はBlocパターンではよく使うので把握しておくとよいと思います。


## View側のコード
BlocBuilder(listenerを併用する場合はBlocConsumer)にて表示するWidgetを切り替えています。
ローディング中は`CircularProgressIndicator()`を表示しています。


## その他の補足ポイント
### == と hashCodeをオーバーライドしている
このサンプルではStateとEventに`Equatable`を用いていません。
なので[こちらの記事](https://qiita.com/marialyn_peach/items/fe6075026fcd04eaba5a#equatable%E3%81%AE%E8%AA%AC%E6%98%8E)で説明したように `==` と `hashCode` をオーバーライドしています。


以上です。わかりやすいサンプルなのでぜひ参考にしてみてください。
Josh Skeen, David Greenhalgh著　『Kotlinプログラミング』　章末問題に挑戦(第２章)

　Josh Skeen, David Greenhalgh著『Kotlinプログラミング』には章末問題がある。残念なことに解答がないので、本を読み進めながら答案を記述する。
　もし回答に間違いや意見があれば、ぜひご指摘いただきたい。

　~~それにしても、この本は少し難しそうだ。~~ 参考までに、私がこの本を読む前に読み終えた教科書は次のとおり。
　　<<わかりやすいJava オブジェクト指向徹底解説>>　川場隆著
　　<<やさしいKotlin入門>>  野崎英一著
　　　　　　　　　　　　　　　　他

　また第２章まで読み終えて気付いたことは、IntelliJ IDEAを使って、JVMを動かすためのJava バイトコードを表示させたり、バイトコードから逆コンパイルしてJavaコードを生成する方法が記述されていることだ。今後読み進めていき、これらの使い方がより詳細に記述されていることを期待する。

#章末問題 回答案
##2.9 チャレンジ！　hasSteed
馬を手に入れたかどうかを管理するために、hasSteedという変数を定義

```kotlin
    var hasSteed  = false   // 馬を持っているか
```

##2.10　チャレンジ！　ユニコーンの角
「ユニコーンの角」というパブのシーンに必要な変数を追加
酒のメニューの表現の仕方は、第10章リスト(List)を参照した

```kotlin
fun main(args: Array<String>){
    var hasSteed  = false   // 馬を持っているか
    var needStable = false   // 馬小屋が必要かどうか
    var drink = ""      // 注文した飲み物
    var gole = 50       // 所持している金
    val publicanName = ""   // マスターの名前
    val playerName = "Estragon" // 主人公の名前
    val drinks = listOf("mead", "wine", "LaCroix")  // 店にある酒のメニュー
}
```

##2.11 チャレンジ！　魔法の鏡
主人公の名前を反転する魔法の鏡

```kotlin
fun main(args: Array<String>){
    val playerName = "Estragon" // 主人公の名前
    println(playerName.reversed())
}
```
＜以上、2020/12/05時点＞
[第２章チャレンジ！答案](https://qiita.com/guijiu/items/dd3313f2a73401e29bc4)
[第３章チャレンジ！答案](https://qiita.com/guijiu/items/672b8daf014d4e6bb346)
[第４章チャレンジ！答案](https://qiita.com/guijiu/items/08dfa397b989b7ecdb3a)
[第７章チャレンジ！答案](https://qiita.com/guijiu/items/452cfa51bee6c4a4af9d)
[第８章チャレンジ！答案](https://qiita.com/guijiu/items/9a7871b1e41bdabd85e7)
【R】固定長データ（.txt）の連続読み込みとStataデータ（.dta）への出力


+ 以下のようなファイル名を持つ固定長データがあるとする：data_H22.txt, data_H23.txt, ...,data_H30.txt, data_R01.txt
+ 各変数の長さ（width）と変数名は別のCSVファイル（varname_H22.csv, ...）で定義されている
+ 例えば 固定長データの1行目が「xxxyyzzzz...」となっているとすると、最初の4文字が変数x、次の2文字が変数y、次の4文字が変数zといった具合。この場合、varname_*.csvは以下のような中身。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/816633/a465c585-00a9-77b1-b9dc-a658fb0a8f78.png)

+ 以下のRコードは、これらの固定長データを連続で読み込み、Stataデータ形式で出力するものである。


```R:txt2data.R
# install.packages("haven", dependencies = TRUE) # install package if necessary
#install.packages("tidyverse")
library(tidyverse)
library(haven)

setwd("C:/Users/CurrentDirectory") 

primes_list <- list("H22", "H23", "H24", "H25", "H26", "H27", "H28", "H29", "H30", "R01")

for (y in primes_list) {
  datafilename.input <- paste("data_", y, ".txt", sep = "") # filename: data_*.txt 
  varfilename <- paste("varname_", y, ".csv", sep = "") # filename: varname_*.txt

  d.varname <- read.csv(varfilename) # import varname file
  width <- d.varname$column  # vector of width
  varname <- d.varname$varname # vector of variable name

  data <- read.fwf(datafilename.input, width = width, col.names = varname) # import data

  # readrパッケージを使う場合
  # d <- read_fwf(datafilename.input, fwf_widths(width, col_names = varname)) # import data
 
  datafilename.output <- paste("data_", p, ".dta", sep = "")  # filename: data_*.dta
  write_dta(data, datafilename.output) # export as .dta file
}

```
最近流行りのフレームワークライブラリ(Vue.js, Angular.js, React)を比較してみた。

**注意** この記事は初学者である筆者がネットの記事など読んで筆者なりにまとめたものです。

フロントエンドエンジニアってなんなんだろう？と思い調べていますが、流行りのフレームワークの特徴を書きました。

## Vue.js
米国在住中国人Evan Youによって作られたフレームワーク。
日本語のドキュメントもすぐに作られたので日本での利用者数も多い。
特徴的なのはSFC(シングルファイルコンポーネント)というHTML, JavaScript, CSSをまとめて１つのファイル(.vue)に記述できるコンポーネント化ができる。
視覚と機能の面でコンポーネントが果たす責務を捉えられる。
Vue.jsのコミュニティが支えるライブラリが数多くある。Vuex, Vue Router, Nuxt.js...

## Angular
Googleが開発しているフレームワーク。
他の２つと比べると機能が充実していて開発における機能が一通り揃っている。
Typescriptでのコーディングが前提。
Vueとは違ってHTML, JavaScript, CSSを分離している。
ただこちらもコンポーネント化してmain.ts(Vueはmain.js)にてコンポーネント群が集約されていく。
機能充実している反面学習コストが高い。

## React
Facebookが開発しているJavaScript ライブラリ。UI構築に主眼を置いている。
そのため公式でもAPI連携について詳しく明言していない。Angularと比較すると機能もかなりミニマム。
JavaScriptを拡張したJSX構文(HTMLにあたる)とJavaScript での記述のみ。ここが上記２つとの最大の違い。

## ポイント
3つとも共通するのはコンポーネント指向である。ではなぜコンポーネント指向にしたいのか

## コンポーネント指向が実現できること
疎結合で依存性が低いのですぐに代替可能。
これが必要な理由はフロントエンド開発の技術の波がとても早いため。ECMAscriptが年次で更新されているのが良い例。
コンポーネントならばこのような環境の変化にすぐ対応できる。

## 所感
なんとなく特徴は掴めたが結局やってみないと分からない。
とりあえず今はVue.jsを勉強中です。
PostgreSQL 9.6とpgAdmin IIIは相性が良くない件

当たり前のことですが、PostgreSQL 9.6はpgAdmin4を推奨しているらしいので、
pgAdmin IIIでバックアップを取るときにdb_dumpのserverバージョン9.5と相性が良くないので、バックアップが取れないみたいです。

解決策：PostgreSQL 9.5をインストールしdbを作り直す。

今のところ、これしか知らないのですが、何か良い方法があれば教えてください。

以上です。
よろしくお願いいたします。
::before擬似要素で間違いやすいポイント3選

`::before` `::after`擬似要素に関して誤って覚えがちなポイントを3つまとめました。

# 1. 擬似要素はどこに挿入されるか
`::after`擬似要素について調べると、
* 「タグの直後に挿入される」
* 「要素の直後に挿入される」
と解説している記事がたまにあります。

が、これは**誤り**です。

正しくは、
* 「要素の**最後の子要素**として挿入される」
* 「要素の**内容の直後**に挿入される」
といった言い方になります。

つまり例えば`span::after`の内容は、

```html:正
<!-- 内容の直後に挿入される -->
<span>spanの内容 ::after</span>
```

という位置に挿入されるのであって、

```html:誤
<!-- こうはならない -->
<span>spanの内容</span>::after
```

という位置に入るわけではありません（`::before`に関しても同様です）。

この違いは様々な場面で重要になります。例えば対象要素がフレックスレイアウトで`border`も付いている場合、以下のように要素内と要素外では大きな差が出てきます。
![スクリーンショット 2020-12-06 16.53.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/17b2752d-422e-e42f-3c4b-100c4f554c14.png)

#### 参考文献

- [Selectors Level 3 | W3C Candidate Recommendation](https://drafts.csswg.org/selectors-3/#gen-content)

# 2. &lt;img&gt; に ::after が効かないのはなぜ？

`<img>`を`::after`で装飾したいと思う場面があるかもしれませんが、通常は指定しても擬似要素は挿入されません。

これは[HTML5の仕様](https://html.spec.whatwg.org/#the-img-element)で`<img>`は子要素もテキストも持てないと定められているからです（正確に言うと、どのような子を持ちうるかを定める「コンテンツモデル」が`nothing`となっています）。

前節で解説した通り`::after`は要素内部に差し込まれるため、子要素を持てない要素には意味がないのも当然の話です。

その他`<video>`や`<canvas>`といった[埋め込みコンテンツ](https://www.w3.org/TR/2011/WD-html5-20110113/content-models.html#embedded-content)にも効かないようです（これは要素の中身自体が置換されるためと思われます）。

# 3. ::after と :after はどちらが正しい？

コロン2つの`::after`が正しいです。
これはCSS3以降では、コロンの数は擬似要素で2つ、擬似クラスで1つに統一されているためです。
（CSS2までは擬似要素も擬似クラスもコロン1つで、`:after`という書き方しかできませんでした）

ただし後方互換性のため before や after 等については、コロン1つの記法も使えるように仕様で定められています。

とは言ってもCSS4の草案には「コロン1つはもう非推奨なので2つで書くべき」とあるので、やはりこれからはコロン2つの記法を使っていく方が良さそうです。

##### 参考文献

- [Selectors Level 3 | W3C Recommendation](https://www.w3.org/TR/selectors-3/#pseudo-elements)
- [Selectors Level 4 | W3C Working Draft](https://www.w3.org/TR/selectors-4/#pseudo-element-syntax)
GitHubでのファイル消去の手順

＊何か追記すべき点や間違っている点がございましたら、ご指摘をいただけると嬉しいです。

**①現状分析**

1.昨日A_appを作成し、プルリクエスト後に放置し、本日作業再開した結果、マージができず…

2.原因はブランチをマスターに切り替え忘れたこと

3.今回は同じAブランチからAブランチにプルリクエストを出してしまうこと事態になるなど様々なエラーが起こった

4.Desktop（ローカルリポジトリ）のA_appのみ消去ができたがブラウザ上（リモートリポジトリ）には残り続けている


**②仮説**

1.最初からやり直したくなったためGitHubのサイトからターミナルを使って消去を試みることにする
https://docs.github.com/en/free-pro-team@latest/github/using-git/removing-a-remote

2.白紙からやり直すにはDesktopとブラウザの両面とSequel proのテーブルも消す必要がある


**③結果**

1.Desktopの消去手順

```
Current repository
↓
A_appを右クリック
↓
Remove
```

2.ブラウザはターミナルを使って消去

```
$ git remote -v
↓
$ git remote rm 消したいファイル名
↓
$ git remote -v
↓
$ exit
```

3.ブラウザはターミナルで消去処理をしても残ったままになってしまうので、

```
消したいファイル名をクリック
↓
setting（設定）
↓
下へスクロールしてDanger Zoneの"delete this repository"をクリック
↓
"Gitユーザー名/消したいファイル名"を入力
```

4.ターミナルでSequel proのテーブルを削除

```
$ mysql -u root
↓
$ mysql> drop database 削除したいデータベース名;
↓
ハイフンのついているファイル名はエラーが出るので、`（バッククォート）でファイル名を囲う
$ mysql> drop database`消したいファイル名`;
↓
消去できたか確認する
$ mysql> show databases;
↓
$ exit
```

**④検証**

1.作業後にコミット→プッシュ→プルリクエストで終わりではなく、必ずブランチをマスターに切り替え→Fetch origin→Pull originを忘れない

2.GitHubは、必ずローカル、リモートの両リポジトリを並行して作業することが念頭にある

3.次回は消去ではなくファイルを継続させたまま直す方法を学ぶ
slackワークフロー→ClickUp→GithubでCSとエンジニアの垣根を自動化

アトラエアドベントカレンダー5日目は新卒2年目エンジニアの櫻井がお送りします！!

今回は、業務効率化のために作成したものについてご紹介します。

僕は、現在転職サイトのGreenの問い合わせ・不具合対応をチームの中で担っています。

お問い合わせ対応や不具合対応(以下、依頼対応と称します)は問題の大小様々なものがあります。
その中で適切にissueを見つけ、進捗状況を管理し、ユーザーの期待を超えるような動きをするために日夜あれこれ改善できるとこはないかと考えています。

その中で今日は土台となる部分のツールについてお話しようと思います。

## 全然管理できてない。。

僕が依頼対応の役割を担うようになるまでは、以下のようなフローで進行していました。


・CSチームがユーザーからヒアリング
↓
・Slackにてエンジニアチームに調査・バグ修正の依頼
↓
・実装が必要な場合、CSがGithubにissueを記載。
↓
エンジニアが対応


上記のフローにおいて、大きく2点が問題となっていました。

・slackでは、情報が流れていき、依頼の管理に向いていない。
・Githubでは、進捗状況がわからない。

適切に運用し、ユーザーにより良い体験を届けるためには、現状の状態をしっかりと把握し、必要な時間・人を見積もる必要があったため、この役割を始めた当初はてんてこまいの日々でした。

そこで、依頼対応のフローを変更しようと考えました。

## 進捗状況可視化したいけど、めんどくさい。。

・依頼の一覧を確認できること
・それぞれの依頼の進捗状況が確認できること

この2点ができれば、状況が把握できるため、適切な対策を行うことができます。
管理するために一覧を作成したり、進捗状況をアップデートするのはエンジニアにとっては中々面倒なものです。できれば、全て自動化して欲しい。。そして、あわよくばそのままCSチームにも報告できれば言うことなし!

これらの条件を満たすために辿り着いたのがタイトルにあるフローです。

## 依頼は変わらずslackのままが楽

まず、CSからエンジニアチームへの依頼内容の伝達は必須です。こちらでは必要な情報を最小限の形で伝達できることが望まれます。

他のツールを使うこともなく、弊社で一般的に利用されているslackを利用することが望ましいと考えました。

しかしながら、slackでは情報は流れていきます。そこで、slackで伝達しながら情報を保存できれば良いと考えました。

slackの機能の一つである。ワークフローを利用することでこの問題は解決されました

ワークフローを起動すると必要な情報のみ記入できるようになっています。

![スクリーンショット 2020-12-05 19.06.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243735/096a2b3a-2a09-b733-b834-ef1fbb2830c2.png)

この内容に沿って入力することで必要な情報が抜け漏れなく届きます。


## 自動化その① slackのフロー情報をストックへ

このワークフローに必要な情報を入力すれば、フォーマットのある情報になるので、これを次に保管・管理するためのツールを用意することにしました。

タスク管理ツールはたくさんプロダクトがありますが、今回は無料で多機能・ユーザーが何人でも利用できるClickupを採用しました。

ワークフローに入力された情報をclickupに送信しました。

(slack apiの利用方法はこちらの記事を参考に作成しました。)
https://www.bravesoft.co.jp/blog/archives/7427

## 自動化その② 開発してたら進捗状況アップデート!?

clickupを採用した理由でもあるのですが、githubとの連携がとても優秀です。

### ステータスを変更するとissueを作れる。
clickupにはautomation機能があり、特定のアクションをすると、それに応じた別のネクストアクションを自動で行ってくれるというワークフローが備わっています。

そちらを利用することによって、「issue」ステータスにすると、自動でclickupに記載された内容をもとにgithubにissueが作られます。

![スクリーンショット 2020-12-05 19.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243735/001d73cb-8712-2d1d-f4fb-c6d88fc523c1.png)


### ブランチとclickupのタスクが紐づく！

clickupのタスクにはIDが振り分けられていて、そのIDを開発のブランチ名に記載しておくと、taskとブランチが紐づきます！(めっちゃ便利)

clickupからコミットの確認やプルリクの作成までできてしまいます。(ちょっと便利すぎる。。)

![スクリーンショット 2020-12-05 19.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243735/32415dd6-7754-94a3-861d-3eddc98e4a69.png)


ここに先ほどのautomation機能も利用することによって
コミットする→開発中のステータスに変更
プルリクを作成する→レビュー中のステータスに変更
masterにマージされる→本番反映まちのステータスに変更

といったようなことが可能となり、開発に集中しながら進捗状況をアップデートするといったようなことが可能となりました。

結果的には、CSチームとエンジニアチームの動き自体は大きく変わらないもののタスクの進捗状況や管理は圧倒的に容易になりました。
自動化ツールの強みを最大限、活かした業務効率化になったかなと思います。

slack apiとclickupを連携したソースコードはいずれ公開しようと思っています。興味がある人はご連絡いただければと思います。
HEADを使ってGitのコマンドを楽に打つ

## push するとき

定番ですね。
add,commitしたあとに

```shell
git push origin {現在いるブランチ名}
```
とするところ、

```shell

git push origin HEAD
```
とする。commitした直後ならそのブランチにいるのでこれでOKです。

## squash するとき

スカッシュしたいな・・・。しかし、そんな昔ではないし、厳密にコミットを遡ってみたくはない。しかも、スカッシュするときは一旦適当にコミットのハッシュを指定しても良い・・・。

本来、

```shell
git rebase -i {ハッシュ値}
```
とするところ、適当に何個前か（以下の例だと５）考えて

```shell
git rebase -i HEAD~5
```
とかすれば良いですね。

## show するとき

自分はある連続したコミット同士の違いを見る時にgit diffを使っていたのですが、いくつか前のコミットの内容を見る時は

```shell
git show HEAD~4
```
とすれば、その時のコミットの中身を見ることができます。
prhでの文章校正環境をVSCodeで作る

# この記事について
技術書典の季節ですね。
サークル出展するという方々は新刊の準備で忙しい頃ではないでしょうか。

環境についてはRe:VIEWを、テンプレは[TechBooster](https://github.com/TechBooster/ReVIEW-Template)さんのものを使っている方が多いかと思います。そしてこのテンプレにはprhという表記揺れ校正ツールを使用するための設定ファイルも含まれています。
今回はVSCodeで執筆しているという方向けに、prh校正環境構築のやり方を紹介します。

## 使用する環境・バージョン
- OS: macOS Catalina 10.15.7
- npm: 6.13.4
- prh: 5.4.4
- prh - ProofReadingHelper(VSCode拡張機能): v1.0.3

## 想定読者層
- 技術書をTechBoosterさんのテンプレを使って書いている人
- prhをまだ使ったことがない人

# prhのインストール
まずはツールをインストールしましょう。[prh](https://github.com/prh/prh)と[prh-languageserver](https://github.com/prh/prh-languageserver)を`npm`で入れます。

```bash
$ npm install -g prh
$ npm install -g prh-languageserver
```
補足: このコマンドではグローバルインストールしていますが、それが嫌な人はプロジェクトごとにローカルインストールでも大丈夫です。

`which`コマンドでインストールができているか確認します。それぞれパスが表示されればOKです。

```bash
$ which prh
/path/to/command/prh

$ which prhls
/path/to/command/prhls
```

# VSCodeの設定
## 拡張機能のインストール
VSCodeでprh校正を利用するための拡張機能をvvakameさんが開発されています。
![スクリーンショット 2020-12-05 19.24.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520877/9c7970f2-5953-f61e-5252-a107039ed29c.png)
[リンク: prh - ProofReadingHelper](https://marketplace.visualstudio.com/items?itemName=vvakame.vscode-prh-extention)

まずはこれをMarketplaceからインストールしましょう。

## workspaceでの設定
次に、原稿を書いているworkspaceでprh校正ができるように設定を書き加えます。

Command+Pでコマンドパレットを開き、そこに`open workspace settings`と打ち込みましょう。
![スクリーンショット 2020-12-05 15.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520877/894bc7a4-e4b4-6519-e8c0-97620eddd1ba.png)
すると、「ワークスペース設定を開く」という選択肢が表示されるので、それをクリックします。

すると、workspace配下`.vscode/settings.json`というファイルが作成されます。ここにworkspaceで使いたい設定情報を書きこみます。
TechBoosterのRe:VIEWテンプレを使っている場合は、以下のように記述すればOKです。

```settings.json
{
    // prhによるチェックを行うか行わないか
    "prh.enable": true,

    // prhlsコマンドの場所を明示的に指定する
    // 先ほどwhichコマンドで確認したパスを書き込む
    "prh.prhlsPath": "/path/to/command/prhls",

    // 校正ルールファイルの場所 prhコマンドで--rulesでの指定と同等
    "prh.configFiles": [
        "./articles/prh.yml"
    ],

    // prhlsからのログ出力レベル
    "prh.trace.server": "off",
}
```

# 結果
![スクリーンショット 2020-12-05 15.36.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520877/865da912-bec0-17de-d87a-73814ad35fd8.png)
このように、VSCodeのパネルタブにprhでの校正結果が表示されるようになりました。
悪い...やっぱCDKつれぇわ...そりゃ(黒魔術は)つれぇでしょ...

####くそなんだよ..全然(CDKの情報)出てこねーな
####俺な、覚悟してCDK選んだんだよ
####けど、なんかこうして運用してたらさ...
####わりぃ、やっぱつれぇわ


# なぜCDKを選択するのか

現状、AWSでIaCを運用する場合第一選択肢となるツールは

- terraform
- Cloudformation (以下CFn)
- AWS CDK

あたりが挙げられるでしょう。

このうち、CFn, terraform, CDK の順にコードが宣言的なものになります。
またterraformはAWSではなくHashicorpのツールとなるので、クラウドベンダに依存しないのが特徴です。  

なのでツール選定の際に

> クラウドベンダ純正のツールだからCFnを使いたい。
しかしyamlを宣言的に記述するのは大変だ。
最近CDKが流行ってるらしいからこれにしよう。

的なノリでCDKが採用されることがあるようです。
特にアプリのコードも書いてインフラも書くようなフルスタック気味のエンジニアが提唱するケースが多い印象。  
Terraformを使わない理由も
> 非純正ツールは対応が遅い可能性が高い。
CFnやCDKなら純正ツールだからサービスの対応速度も早いはず

という言及を見かけるのですよね。  

## 純正ツールだからサービスとのシナジーが良いという幻想
**CFn、およびCDKがAWS純正ツールだから、シナジーが良いというのは幻想**です。(きっぱり)
CDKもCFnのラッパーなので、CFnの制限をもろに受けます。 
それに加えてCDK特有の問題やバグと格闘する羽目になります。

##### 例（CFnの制限）
最近ではDynamoDBのGSIを複数登録しようとしていたのですが、
DynamoDBテーブル一度の更新につき、GSIは一つしか登録できません。
なので**CFn、CDKもこれのせいで一つ登録してはデプロイし、もう一つ登録してはデプロイし...**
とせざるを得ません。

[How to delete more than one Global Secondary Index from the CloudFormation at once?
]
(https://stackoverflow.com/questions/47920665/how-to-delete-more-than-one-global-secondary-index-from-the-cloudformation-at-on)

ちなみにTerraformは**この制限を受けない**そうです。
多分複数回テーブルを更新してゴリ押ししてるんじゃないですかね。

他にもCodeDeploy + ECSのデプロイとなるとサポートされていない部分があったりと
純正ツールにしてはサービス間の連携が実装できなかったりしてつれぇです。


[AWS CDKを(途中まで)使用してAmazon ECSの Blue/Greenデプロイ環境を構築する](ttps://www.seeds-std.co.jp/blog/creators/2020-05-27-153425/)

##### 例（クロスリージョン）
CDKはリージョンを跨いで情報を渡すことができません。
なので要件次第では完全自動化からは遠のきます。
例えばWAFv2のCloudfront向けルールは米国リージョンでしか作成できません。
すると**割当てるCloudfrontも米国名義で作ることになり、S3も米国名義で作ることになります。**
東京リージョンにしたい場合はCloudfrontとの連携を手作業で行います。

コード一発での作成から遠のきますね。

##### 例 バージョンアップが激しい
CDKは体感値で2週間に一度（もっと多いかも）ぐらいの頻度でバージョンアップが行われます。 
中には破壊的変更もあって、これの動作確認をすることになります。
CDKでの構築中にバグに遭遇し、回避策を考えている間にバージョンアップでフィックスされることもままあります。

##### 情報が少ない
AWS純正ツールの割に、情報が圧倒的に少ないです。
IaCはterraformが覇権を握っているようで、CDKはまだまだアーリーアダプタな感じですね。 
terraformでは複数環境構築の際はworkspace派かmodule派かで分かれていますが、
CDKではそんな流派さえまだ存在しないようです。結果的に自分で分岐させることになるので属人性の高いコードになりがちです。

ベストプラクティスも見当たらない中、上記の問題に遭遇するのは
#####そりゃ...つれぇでしょ...

# プログラマブルなのは恩恵か、負債か
CDKのメリットは**既存言語で分岐・繰り返しを駆使してインフラを書ける**だと思います。
これのおかげで、
> 開発環境はwebサーバは一台で
DBは最小スペック
ステージング環境はwebサーバ2台・DBもプライマリ・セカンダリ構成

みたいな動的に変わるインフラに対応しやすいです。 
その代わり**条件が増えるほど、コードの複雑度も上がります。**
とりわけ開発中は特に、インフラの構成に細かい注文が追加でされることも少なくないです。 
冗長性を排除しすぎるとそういった注文に対応するのに時間を食われるようになるでしょう。
なのでわざと冗長に記述して変更に強くするという判断も必要になります。  
結局その**判断基準が属人性を持つ**ようになります。

> そういった属人性を排除するためにコードを皆が書ける言語でレビュー合うべきだ

という理想が実行できるかも現実的には微妙なところでして、
CDKをレビューするためには

- 対応言語がある程度読めること
- AWSインフラの知識がある程度持っていること
- CDKの知識があること
- IaCの冗長性と宣言性のバランスが理解できること
- これらに対応する時間が割けること

上記条件が整わないと難しいかなぁという印象です。
インフラ担当エンジニアがいたとして、他のエンジニアはフロントなりバックエンドなりの作業で一杯の場合インフラ担当同士でレビューし合うしかない状況にもなり得ます。

条件が整わない場合、CDKの黒魔術に進みかねないので... 
#####そりゃつれぇでしょ...


# それでも書き心地はトップクラス
そういったもろもろの問題はありますが、CFｎやterraformと比べて圧倒的に書き心地が良いのも事実です。
得にTypeScriptを使用していれば、型定義の恩恵を十分に発揮し保守性と可読性を保つことができるでしょう。コード量自体、CDKが最も少ないので実装速度も早いと思います。  

AWSの純正ツールということに過信しすぎなければ、使うメリットは十分あります。
昨今のIaCツールはどれも何かしらの辛みを持っているわけで、技術選定時にはその比較をしておくべきというだけの話ですね。 



#####ちゃんとメリットも言えたじゃねぇか
#####聞けてよかった...
Matplotlibで画像を表示するimshowの初歩

この記事は古川研究室 <a href=https://qiita.com/advent-calendar/2020/flab>古川研究室 Advent_calender</a>6日目の記事です。
本記事は古川研究室の学生が学習の一環として書いたものです。内容が曖昧であったり表現が多少異なったりする場合があります。

# はじめに
imshowは簡単に言うとデータを画像として表示してくれるツールです。画像を表示するときや、データを画像として可視化をする際に役に立ちます。
imshowの第一引数にはRGBAの画像データまたは、2次元のスカラーデータです。cmapを指定することで元の画像をグレースケールなどに変換することができます。

今回は画像を表示する場合と、データを可視化する場合の2つの場合でやってみます。

imshowの詳細は[公式リファレンス](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.imshow.html)参照してください。

## まずは画像を普通に表示
PIL(Python Image Library)はPythonの画像処理ライブラリです。その他に、OpenCVという画像処理ライブラリもあるみたいです。
PILのインストールは下の通り。

```
$ pip install pillow
```
最初におまじないです。

```python
from PIL import Image
import matplotlib.pyplot as plt
```
まず画像を読み込みます。今回は同じディレクトリに画像ファイルとプログラムを置いています。

```python
#画像の読み込み
im = Image.open("1729971_s.jpg")
```
imを表示するとこんな感じです。Jpeg画像のRGBのデータが入っていることが分かります。

`<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=640x427 at 0x2877E085148>`

ここでimshowの登場です。引数には、画像データのimのみを渡しています。

```
plt.imshow(im)
plt.show()
```
![480.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854611/48b7b506-0191-a797-8c12-2589d0338a91.jpeg)
これだけで簡単に画像が表示できちゃいます。
(今回使ったフリー画像のダウンロードのサイトは[こちら](https://www.photo-ac.com/)です。)
##2Dのスカラーデータを画像として表示

まずは、おまじないです。

```python

from PIL import Image
import matplotlib.pyplot as plt
#データ生成用にnumpyをインポート
import numpy as np
```
データの生成と描画

```python
#データの生成、0~1までの25点を生成、2Dにするためにreshape
data = np.linspace(0,1,25).reshape(5,5)
im = plt.imshow(data)
#カラーバーの表示
plt.colorbar(im)
plt.show()
```
![data imshow.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854611/4122514c-4f66-f75d-09d0-61e500b347e2.jpeg)


1つのデータ点が1ピクセルに対応していることが分かります。データ点が多いほど画素数が増え、滑らかな画像になります。ここのカラーマップは、デフォルトでは入力データ点の最大値と最小値(ここでは1.0と0.0)に応じて、色付けされています。カラーマップの最大値と最小値を指定したい場合は、`vmin,vmax`を引数にもってきます。ここでは、`vmin=-1,vmax=1`にしています。

```python
im = plt.imshow(data,vmin=-1,vmax=1)
```
左側にデフォルトの場合、`vmin=-1,vmax=1`に指定した場合を示しています。色付けが変化したことが分かります。
![data imshow grey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854611/f267db08-2b94-9e0f-1a80-9eae81e42d77.png)

## カラーマップを変更するとき
imshowの引数`cmap`を指定することで、カラーマップを変更することができます。ここでは、グレースケールで表示するために、`cmap='Greys'`としています。デフォルト値は`cmap='viridis'`です。カラーマップの選択の際には[Choosing Colormaps in Matplotlib](https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html)を参照してください。

```
im = plt.imshow(data, cmap='Greys')
```

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854611/0371c892-7dc7-706c-1483-8969acc2a24d.png)

## 上下を入れ替えて描画するとき
デフォルトは左上から順にデータを並べていますがimshowの引数を`origin='lower'`にすると、左下からデータを並べてくれます。これにより、上下を入れ替えて描画することができます。デフォルトは`origin='upper'`です。
詳しくはMatplotlibのtutorial、[origin and extent in imshow](https://matplotlib.org/tutorials/intermediate/imshow_extent.html)に詳しく記載されています。

```
im = plt.imshow(data, origin='lower')
```
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/854611/88655063-6ed2-37c4-1c19-4147cd7a85d0.png)

#おわりに
本当に簡単にですが、Matplotlibのimshowについてまとめました。
この記事が誰かの役に立つと幸いです。
#参考文献
[1]Matplotlibで画像を表示
https://qiita.com/zaburo/items/5637b424c655b136527a
JSでいろいろな文字入力制御に対応してみた

## 背景
自社サービスにて、細かい入力制御をする必要がありました。
特に銀行口座の名義人カナ入力にて、半角カナ入力時に、小文字(ｧなど)は大文字(ｱなど)に直す必要があったり、ｰ(長音)は-(ハイフン)に直す必要があったりしたので、
そのあたりも含めいろいろ対応してみました。

## 動作例
### ひらがなのみに変換
ひらがな以外を入力しようとしてもできないようになっています。少し分かりにくいのですが、最後の「エンジニア」はカタカナに変換して確定後、ひらがなに変換されています。
![画面収録 2020-12-05 18.30.17.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867400/88e01258-1658-0882-06a9-f8ce08413cf2.gif)

### 半角カナ大文字(+ハイフン)のみに変換
以下のように「フットボール」と入力した場合、「ﾌﾂﾄﾎﾞ-ﾙ」に変換されます。
![画面収録 2020-12-05 18.44.55.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867400/a71a5d58-7a41-629e-ae56-fddee21a9a62.gif)


https://github.com/koda-h/input-validate-js
こちらをdocker-composeで動かすことによって、以下の入力制限の動作デモが可能です。

- ひらがなのみに変換(スペース含む)
- 半角カナのみに変換(スペース含む)
- 口座振替で許容する半角カナのみに変換(スペース含む)
- 全角カナのみに変換(スペース含む)
- 全角のみに変換(スペース含む)
- 全角のみに変換(スペース含む・記号は許可しない)
- 半角カナ大文字のみに変換(スペース含む)
- 半角カナ大文字のみに変換(長音はハイフンマイナスに変換)(スペース含む)
- 半角カナ大文字英数のみに変換(長音はハイフンマイナスに変換)(スペース含む)
- 半角英数に変換(スペース除去)
- 半角英数記号に変換(スペース除去)
- 半角英数に変換(スペース含む)
- 半角数字に変換(スペース除去)
- 半角数字に変換(スペース含む)
- 半角数字(0以上の整数)に変換(スペース除去)
- 半角数字(0以上の整数)に変換(スペース除去) ピリオドあり
- 電話番号文字列(半角数字+ハイフンマイナス)に変換(スペース除去)
- 電話番号にハイフンを付与


## 利用方法
### 必要なもの
- <a href="https://github.com/niwaringo/moji" target="_blink">moji.js</a>
- https://raw.githubusercontent.com/koda-h/input-validate-js/master/public/input-validate.js

### コード記述例

```html
<input name="hiragana" type="text" value="">
```
```js
<script>
    var isComposing = false;
    // ひらがなのみに変換(スペース含む)
    $('[name="hiragana"]').on('keyup blur compositionstart compositionend', function (event) {
        // 3番目の引数で最大入力文字数を制御
        convert_hiragana(this, event.type, 30);
    });
</script>
```

https://github.com/koda-h/input-validate-js/blob/master/public/index.html
こちらにも記述例があるのでご参照ください。

## 解説
`compositionstart`, `compositionend` はIMEによるテキスト編集監視に用いるイベントです。
global に `var isComposing;` を定義し、
`compositionstart` (IME入力中)のタイミングでは `isComposing = true;`とします。
この状態で `keyup`, `blur` イベントを検出した場合は、変換を行います(※1)。
そして、 `compositionend` (IME入力後Enter押下)のタイミングで `isComposing = false;`とし、この状態では変換しないようにします(※1)。
(※1) <a href="https://github.com/koda-h/input-validate-js/blob/master/public/input-validate.js#L190" target="_blink">ここ</a>の部分

## 参考
- https://qiita.com/darai0512/items/fac4f166c23bf2075deb
PyTorch でも TensorBoard in Google Colab

deep learning のフレームワークは、最近は TensorFlow か PyTorch を使用することが多いと思います(他にも色々ありますが)。

TensolFlow には TensolBoard という、loss, accracy などの学習の進行やモデルを可視化する便利なツールがついています。
TensorBoard は現在では Google Colaboratory のノートブック内で使用できるようになっており、またフレームワークの垣根を越えて PyTorch からも使用できるようになっています。

そこで PyTorch から簡単に使ってみたいと思います(実は初 PyTorch)。


### 使用する環境

Google Colaboratory を使用します。

### ソースコード

最初のマジックコマンドは TensolFlow 利用時と同様です。

参考: [簡単 3分 TensorBoard in Google Colab](https://qiita.com/go50/items/06131870299922e3d9b1)

```python
from __future__ import absolute_import, division, print_function, unicode_literals

try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass
```

```python
# Load the TensorBoard notebook extension
%load_ext tensorboard
```

PyTorch のドキュメントに例がありますので、こちらを実行してみます。
https://pytorch.org/docs/stable/tensorboard.html

ResNet という画像判別モデルで、MNIST という入門用数字画像のデータセットを学習します。
SummaryWriter を使用して、画像やモデルを出力します。

```python
import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms

# Writer will output to ./runs/ directory by default
writer = SummaryWriter()

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
trainset = datasets.MNIST('mnist_train', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64, shuffle=True)
model = torchvision.models.resnet50(False)
# Have ResNet model take in grayscale rather than RGB
model.conv1 = torch.nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
images, labels = next(iter(trainloader))

grid = torchvision.utils.make_grid(images)
writer.add_image('images', grid, 0)
writer.add_graph(model, images)
writer.close()
```

TensorBoard の実行です。
SummaryWritter はデフォルトで `./runs/ directory` に出力するとありましたので、runs を logdir として指定します。

```python
%tensorboard --logdir=runs
```

### 実行結果

ノートブックのセル内に TensolBoard が表示されます。

##### 学習時の Accuracy と loss のグラフ

loss の落ち具合などを確認します(落ちていませんが Expected result とだいたい同じ)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323666/84d3064f-0ce0-cb1c-550d-9c9f7845b436.png)

##### ネットワークの構成

ニューラルネットの構成がわかります。個人的にはこれが便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323666/1bd3f530-cd09-6197-b775-ccbe5bb88cd0.png)

### おわりに

PyTorch でも TensorBoard が使えるのは、かなり便利ではないでしょうか。
Google Colaboratory で PyTorch されている方、ぜひ使ってみてください!
[小話]Googleアナリティクスと広告ブロッカー

[本記事は、自分サイトのこの記事と同一内容です。](https://hagiayato.github.io/my-site/jekyll/update/2020/12/05/AnalyticsBlock.html)
## 発端  
先日私は、自分のサイトをGitHub Pagesで作成しました。
[自分のサイト](https://hagiayato.github.io/my-site/)
そして、そのサイトのアクセス数の集計・解析のためGoogleアナリティクスを導入したのですが、
自分でサイトにアクセスしても、それをGoogleアナリティクス側が拾ってくれませんでした。
![2020-12-05 182619.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/11b30565-1b27-3e90-375c-ffc62ee7f908.jpeg)
## 分析
真っ先に導入方法が間違えていないかを確認したのですが、どうも間違えてはいないようでした。
その方法は以下の記事の通りです。
[GitHub Pages で Google Analytics を使うシンプルな設定](https://qiita.com/memakura/items/2cfc8133e07fdc72c45f)
その後他の原因を疑っても結果は変わらず…

しばらくすると、あるものに目が行きました。
**広告ブロッカーが動作しているという表示**
※どのブロッカーかは伏せます。

試しに広告ブロッカーを自分のサイトで無効にし、再度自分のサイトにアクセスすると…
![2020-12-05 184845.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/7c213e48-6427-d05b-cd58-daa66a186562.jpeg)
今度はちゃんと、アクセスをGoogleアナリティクス側が拾ってくれました!
## 結論
**GitHub PagesにおけるGoogleアナリティクスは広告ブロッカーでブロックされ、ブロッカーが作動する環境からのアクセスを集計しない**
今まではwebページを軽量で見たいということで、基本的にPCブラウザに広告ブロッカーを入れていました。ただ今回の件を考えると、広告ブロッカーはwebページの運営に支障をきたすということになるわけでして…　
少し複雑な気持ちになります。
### 補足
- QiitaにおいてもGoogleアナリティクスを導入していますが、自分のサイトと結果は変わりませんでした。
- 広告ブロッカーを無効にしなくても、ホワイトリストでGoogleアナリティクス関係のブロックを解除する方法もあるようです。ただし方法を調べ切れていないため今回は触れません。
- GitHub Pages側での広告ブロック対策は今後調査します。
サーバ群のサーバ証明書の失効期限を自動でチェック+メールする

# はじめに

　インターネットにサーバを公開している人には、切っても切れないサーバ証明書ですが、契約期間が1年毎になったり、Let's encryptだと3か月毎とか、有効期限が短くなり管理の手間が増えて困ります。今はまだ、有償のサーバ証明書も2年または3年の有効期間の箇所のサーバもあったりしますので、更新の申請漏れに関しては注意しないといけません。

# ここに記録する記事の内容について

　管理対象の複数のサーバの有効期限を自動で確認して、残りが2週間と1週間を切ったら毎日メールを管理者に通知するShellを記載します。
　Let's encryptなどは、サーバ証明書の自動更新をShellで実施していますが、時々失敗することもあるので、更新日の把握は大切です。

# ドメイン一覧ファイルの書式

管理対象のドメインをdomain.lstに記載します。

下記はサンプルです。先頭行に#はコメント行となります。

```shell:domain.lst
#commment.com　
www.kantei.go.jp
www.mod.go.jp
```

# 検査用のShellの中身

```shell:check_ssl.sh
#! /bin/bash
# -checkend  期限切れまでの秒数
#  [2592000](=30日×24時間×60分×60秒)
#  [1209600](=14日×24時間×60分×60秒)
#  [604800](= 7日×24時間×60分×60秒)

# 期限切れの時にメールを送信する宛先
MAIL_TO=HegeHege@gmail.com
# 検査対象のドメイン名一覧ファイル
LIST_FILE=/root/LIST/domain.lst

touch /tmp/crept_date.txt

for DOMAIN in `cat  ${LIST_FILE}| grep -v "^#"`
do
  Val=`openssl s_client -connect $DOMAIN:443  -servername $DOMAIN < /dev/null 2> /dev/null | openssl x509 -checkend 604800 | grep "not" | wc -l`
  if [ "$Val" = "0" ];
  then
        echo "$DOMAINのサーバ証明書は約1週間後に無効となります。" >> /tmp/crept_date.txt
  else
     Val=`openssl s_client -connect $DOMAIN:443  -servername $DOMAIN < /dev/null 2> /dev/null | openssl x509  -checkend 1209600 | grep "not" | wc -l`
     if [ "$Val" = "0" ];
     then
        echo "$DOMAINのサーバ証明書は約2週間後に無効となります。" >> /tmp/crept_date.txt
     fi
  fi
done

Val=`cat /tmp/crept_date.txt | wc -l`
if [ "$Val" != "0" ];
then
 mailx -s "サーバ証明書期限切れ情報" ${MAIL_TO}  < /tmp/crept_date.txt
fi
\rm -f /tmp/crept_date.txt
```

# cronにShellを追加

月曜、水曜、金曜の朝8時にサーバ証明書期限切れを調べる。
下記をcrontab -e コマンドで追加する。

```
00 08 * * 1,3,5 sh /root/bin/check_ssl.sh
```
Rspecよくあるエラー問題集

##事前準備

ターミナル上で下記コマンドを実行してcloneする。

```
git clone https://github.com/Shu-Hos/chat-app_error.git
cd chat-app_error
bundle install
yarn install
rails db:create
rails db:migrate
```

###問題１
ターミナルで下記コマンドを実行してください。

```
bundle exec rspec spec/models/user_spec.rb
```

すると`NameError:　uninitialized constant Faker`
のエラーが発生したかと思います。
まずはこちらがErrorではなくfailuresになる段階まで改善してください。
※こちらはヒントなしで解決しましょう。


###問題2
上記のエラーが改善されて再度こちらのコマンドを実行してください

```
bundle exec rspec spec/models/user_spec.rb
```

しかしテストの結果は、重複したemailが存在する場合登録できないこと `(FAILED - 1)`が残ってしまっているかと思います。
こちらを修正してuserのモデル単体テストを成功させてください。

<details><summary>ヒント</summary><div>
こちらのテストの流れはユーザー１登録　=>　`ユーザー２登録時にユーザー１のemailで登録しようとする`ことです。

ユーザー１の中身を`binding.pry`を使用して確認してみましょう。
</div></details>

###問題3
問題2まで解き終えたら次はメッセージの単体テストです。
以下のコマンドを実行してください。

```
bundle exec rspec spec/models/message_spec.rb
```

すると`RuntimeError`が発生したかと思います。
こちらの状態からmessage_spec.rbでもテストがパスするように修正してください。

※エラーの原因は２つあるので、両方修正ができて始めてmessageの単体テストもパスします。

<details><summary>ヒント</summary><div>
①エラー文を読むとどうやら画像の部分が怪しそうです。
 binding.pryで処理を止めて@message.image.blobで画像データの中身を確認してみましょう。

②@message.userや@message.roomの中身も必要であれば確認してみましょう。

</div></details>

###問題4
ここからは結合テストのエラー問題です。
以下のコマンドを実行してください。

```
bundle exec rspec spec/system/message_spec.rb
```

すると、ログインができずにテストが通らないかと思います。
まずは結合テスト内でログインがされている段階を目標にコードの修正をしてください。

<details><summary>ヒント</summary><div>
tmpディレクトリ配下のscreenshotsディレクトリの中には結合テストを実行した時の画面がスクリーンショットとして自動保存されます。
そちらの動きから原因を特定しましょう。
</div></details>


###問題5
ここまで来ましたが、ログインしても投稿が出来ずにテストがまだ
通らないかと思います。
最後にこちらの問題を解決してmessage_spec.rbの結合テストを成功させてください

```
bundle exec rspec spec/system/message_spec.rb
```
<details><summary>ヒント</summary><div>
rails s でサーバーを起動させてから検証ツールで要素の中身を確認してみましょう。
</div></details>

お疲れさまです！！
何かご不明点とかあれば、今後ぜひ教えてください！
Macで青空文庫を Kindle に入れる方法

軽くてバッテリーライフが長いので、kindle paperwhiteを愛用していますが、青空文庫はiPhoneの読書アプリを使っていました。
ふと、思い立って青空文庫の作品を Kindle で読む方法を探してみたら、結構簡単にできることがわかったので、ここにメモしておきます。

### 必要な手順
* 青空文庫のファイルを ePub 形式に変換する
* ePub形式のファイルをKindle形式（mobi）に変換する
* Kindle に送る

### 必要なアプリ
#### 1. 青空文庫のファイルを ePub 形式に変換するアプリ
AozoraEpub3
~~以下のサイトから zip ファイルをダウンロードして展開する。~~ 
　~~http://www18.atwiki.jp/hmdev/pages/21.html~~ 
 上記サイトは残っていますが、ダウンロードリンク先が無くなっているようなので、以下の girhub からダウンロードして展開します。
 https://github.com/kyukyunyorituryo/AozoraEpub3
（動作させるには Java（JDK） が必要なので、無ければそれもインストールしておく）

#### 2. ePub 形式のファイルを mobi 形式に変換するアプリ
Kindle Previewer
（多機能アプリなのだが、今回は mobi形式に変換して Kindle に転送する機能を使う）
以下のサイトからダウンロードしてインストールする
　https://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765261

### 実際の操作例
#### 青空文庫（ https://www.aozora.gr.jp ）から読みたい本のデータをダウンロードする。
　例えば、夏目漱石の「こころ」
　　https://www.aozora.gr.jp/cards/000148/card773.html
　のページから「ファイルのダウンロード」をクリックして表示されるページから「テキストファイル」をダウンロードする（ebkは変換できない）
#### AozoraEpub3 の操作
・AozoraEpub3を展開したフォルダー中にある AozoraEpub3.jar をダブルクリックして起動
　（縦書き・横書きが選べるので選択する）
・AozoraEpub3のウインドウに変換したいテキストファイルをドラッグ＆ドロップ
・変換前確認のウインドウが開くので、問題なければ「✔︎変換」をクリック
　（AmazonEpub3 のウインドウに変換後のファイル名とパスが表示される）
#### Kindle Previewer の操作
・Kindle Previewer を起動して ePub ファイルを開く
　（変換が始まる）
・端末の種類を「Kindle端末」にする
・ファイルメニューのエクスポートを選択
・エクスポート先を選択して保存
　Kindle をUSBドライブモードで接続している場合は直接（Documents フォルダに）そうでなければ適当なフォルダにエクスポートし、後でKindleをマウントしてコピー

### おまけ
AozoraEpub3 で直接 mobi ファイルにする方法もあります
AmazonEpub3 で端末設定を「Kindle PW」にすると kindlegen が必要だと言われますが、このツールは Kindle Previewer アプリの中にあるので、それをコピーしてきて AozoraEpub3 を展開したフォルダに入れます
　（アプリの中身を開くと、Contents –> lib –> fc –> bin の中にあります）
そうするとAmazonEpub3で直接 mobi ファイルに変換ができるようになります

### 追記(2023/03)
AozoraEpub3がアップデートされていました。
「AozoraEpub3-1.1.1b9Qをリリースしました。」
　→ https://99nyorituryo.hatenablog.com/entry/2021/05/06/222829

また、AppleシリコンのMacではJavaがエラーになるので、ここの記事を参考に zulu-11.jdk をダウンロードして所定の場所にコピーします。（念のため元々あった Openjdk はどこかに移しておきましょう）
「M1 Macの開発環境」
　→ https://qiita.com/shibukawa/items/797b7cbb7e530842e6f7

 ### 追記（2024/05)
本家の Send to Kindle サービスを使うと、EPUB 形式のファイルを Kindle ライブラリーに直接送ることができるようになっています。
さらに、最近は青空文庫の作品が、Kindleのストアに無料で登録されていて、そのまま購入（0円）できるので、変換・登録の手間が無くなりました。（まずは、Kindle ストアで探して、まだ登録されていなかったときに自炊（変換・登録）すれば良いと思います。
EPUB形式だと macOS, iOS, iPadOSの「ブック」アプリで縦書きで読めます。
Vue.jsとは

#はじめに
本記事では数多くあるJavaScriptのフレームワークの中の**``Vue.js``**に焦点を当て、その特徴と他のフレームワークについて書きます。

#Vue.jsとは？

Vue.jsとは、UI(ユーザーインターフェース)を構築するためのJavaScriptフレームワークです。
フレームワークとは開発をする時に必要な機能などをまとめて提供してくれるソフトウェアのことで、使用することで開発の効率を上げることができます。

Vue.jsでコードを書く時は、冗長な記述を少なくすることができます。Vue.js独自の規格やルールも少ないため、他のフレームワークよりも自分の好きなやり方でアプリ開発を行うことも可能です。

#Vue.jsの特徴

###■気軽に使える
Vue.js はjQueryと同様に、scriptタグを1行書くだけで使い始めることができます。

```vuejs
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
```

###■双方向データバインディング
双方向データバインディングとは、データの変更があればUIの表示を更新し、UIの変更があればデータの更新を自動的に行う機能を指します。
Vue.jsはこの双方向データバインディングをシンプルに行うことに重点を置いています。

###■MVVM
MVVMとは、「Model(M)-View(V)-ViewModel(VM)」という設計手法を表す用語です。
「Model（データ）」「View（画面）」「ViewModel（メイン処理）」とのように分けて開発を行うこと可能です。
これにより、各プログラムを役割を分けて開発ができるので、可読性が高まります。

大規模なアプリなどでも保守、運用が行い安くなるのがMVVMの特徴です。
###■コンポーネント
コンポーネントとは、各プログラムを部品化して再利用ができる仕組みです。
1つのHTMLファイルを使いわましたり、同じ処理をまとめて外部から利用するといったことが可能です。
これにより、書くプログラム量が減るため、再利用性が高くなり、開発の生産性を上げることができます。

###■ディレクティブ
ディレクティブを利用することでDOM操作をすることができ、HTML要素の表示・非表示などを柔軟に変化させることができます。
これにより、直接DOMを操作するコードの記述量を減らすことができるため、開発スピードを早めることができます。

#参照
[Vue.js](https://v3.vuejs.org/)