OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】psycopg2をインストールでエラーが出た

Djangoをherokuにデプロイする時,sqliteからpostgreに移行するべく
`pip install psycopg2`
をしたらエラーが出てしまった。

一部エラー内容
```
Error: pg_config executable not found.
    
pg_config is required to build psycopg2 from source.  Please add the directory
containing pg_config to the $PATH or specify the full executable path with the
option:
    
    python setup.py build_ext --pg-config /path/to/pg_config build ...
    
or with the pg_config option in 'setup.cfg'.
    
If you prefer to avoid building psycopg2 from source, please install the PyPI
'psycopg2-binary' package instead.
    
For further information please check the 'doc/src/install.rst' file (also at
<https://www.psycopg.org/docs/install.html>).
```
  
# 環境
MacOs Big Sur: 11.3.1
postgresql: 14.3
psycopg2: 2.9.3
# 手順
どうやらopenssl周りをいじるとうまくいくらしいので、以下のコマンドを実行した。
```
$ brew install openssl
$ export LDFLAGS="-L/usr/local/opt/openssl/lib"
$ export CPPFLAGS="-I/usr/local/opt/openssl/include"
$ pip install psycopg2`
```
環境によってはpg_configをインストールすると解決するらしい
モジュール周りに疎いので勉強次第追記するかも

 参考:https://dev.classmethod.jp/articles/mac-psycopg2-install/
CountdownCalendarに過去記事を投稿

CountdownCalendarに過去記事を投稿することの是非は、それぞれのCountdownCalendarの企画者が決めればいいことだと思う。

企画段階で、明記せずに、後から、ごちゃごちゃ言う企画者の企画には二度と参加しなきゃいい。

個人亭には、少なくとも、CountdownCalendar投稿期間の間に、１文字でも編集していればOKというのが私が企画する場合の方針です。

１文字でっていうとこが大事です。

例えば、アセンブラによっては、＃記号がコメントになる場合があります。

そして、この＃記号を１文字入れるだけで、過去に多くの方から感謝されたことがあります。

VZエディタ移植に当たって実施したことと成果。仮説(115)

https://qiita.com/kaizen_nagoya/items/5551be98dcbed8f41949

一文字じゃなくて、意味のあるまとまりじゃなきゃだめとか、2022年にあったことを追加しなきゃだめとか、企画される方が、条件をお書きになればいいと思います。

自分の過去記事をコピペして、Qiita上は新しい記事にすることは、本人なら、更新事項があれば、システム側から文句が出る可能性は低い気がします。

システムで自動判定するには、変えた１文字の価値が判定できるほど、機械学習を成熟させておくのも手かもしれません。
Pyspark テーブル更新時のエラー対応


# テーブル変更後の更新でエラーになる

write実行時にDelta Lake でのスキーマがチェックされ、合致しなければエラーになってしまいます。
間違い防止にすごくありがたいこの機能ですが、仕様変更で新しい列が追加されたり、データの型が変更になってしまうととたんに厄介者になってしまいます。
開発時はテーブル削除でしのげても、いったん運用になってしまうとそうはいきません。

## .option('mergeSchema','true') 
- 新しい列の追加（最も一般的なシナリオ）
- NullType からあらゆる型へのデータ型変更。もしくは、ByteType、ShortType、IntegerType へのアップキャスト

公式ページではケースとして上記が挙げられているけど NullType …正直わからない！のでここでは、新しい列追加に絞って記載します。
いままでのテーブル/parquetファイルに新しい列を追加したいなら、Sparkの .write コマンドまたは.writeStreamコマンドに、.option('mergeSchema','true') を追加しよう。

```Python 
# Add the mergeSchema option
loans.write.format("delta") \
    .option("mergeSchema", "true") \
    .mode("append") \
    .save(DELTALAKE_SILVER_PATH)
```

> このオプションを使用することで、既存の列を参照するモデルに影響を及ぼすことなく、運用中のテーブルに新しい列を追加できます。例えば、データサイエンティストやエンジニアが、新しい追跡指標や直近の売上データの列を追加したい場合などが想定されます。

これで運用中のテーブルでも新しい列を追加できる！


## .option('overwriteSchema','true') 
新しい列の追加じゃなくて、列の削除とか既存の列のデータ型変更なんだよぅ！:confounded:
という場合は、こちら。
- 列のドロップ
- 既存の列のデータ型変更
- 大文字と小文字で区別された列名の変更（例：「Foo」と「foo」）

こんなときはスキーマとデータを上書きするための .option("overwriteSchema","true") を追加しよう。
#### 列の型を変更する
```Python 
spark.read.table(...) \
  .withColumn("birthDate", col("birthDate").cast("date")) \
  .write \
  .format("delta") \
  .mode("overwrite")
  .option("overwriteSchema", "true") \
  .saveAsTable(...)
```

#### 列の名前を変更する
```Python
spark.read.table(...) \
  .withColumnRenamed("dateOfBirth", "birthDate") \
  .write \
  .format("delta") \
  .mode("overwrite") \
  .option("overwriteSchema", "true") \
  .saveAsTable(...)
```
これで仕様変更があってもバッチリ！


## この記事は以下の記事を参考に書きました。
#### Delta Lake でのスキーマ（schema）DB の適用・展開とは
> https://databricks.com/jp/blog/2019/09/24/diving-into-delta-lake-schema-enforcement-evolution.html
#### テーブルのバッチ読み取りと書き込み
> https://docs.microsoft.com/ja-jp/azure/databricks/delta/delta-batch
ソラカメを使ってみた

ALGYAN７周年イベントのプレゼントとしてソラカメをいただきました！
早速使ってみたので共有したいと思います。

![IMG_0049.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326104/9cd14ec0-613d-863d-62c0-4efe9e323d8f.jpeg)

設定手順は簡単
ATOMのアプリをインストールして、SORACOMのアカウントでログイン
あとはデバイス追加で画面の手順に従ってセットアップするのみ

これだけで動きを検知できるようになりました

![IMG_0050.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326104/a6b8e688-6502-de53-a843-69e5135a025f.jpeg)

付随していたライセンスも設定。アップデートが必要でしたが、こちらも問題なく設定完了

![IMG_0051.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326104/92535595-8390-bb78-fa9f-02b376319f6c.png)

使い道を模索していきたいと思います
【Vue3】Maximum recursive updates exceeded in component解消備忘録

## Maximum recursive updates exceeded in component
どういうエラーかというと、コンポーネントが再起呼び出しされまくってメモリがパンクしていますよというもの。
これの何が厄介かというと、npm run serveで開発しているときは警告なのに、デプロイするとエラーに化けるところ。

私はこれで３日悩みました。

![スクリーンショット 2022-06-11 16.12.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1135021/76d435e6-56cc-9117-2536-f95642cf866c.png)

## 具体例 Vue3-Carousel
今回このエラーに悩まされたのは、Vue3-CarouselというCarouselコンポーネントを使っていて、リストレンダリングをする際にどうしてもこのエラーが消えませんでした。
（どんなコンポーネントかは以下を参照）

https://qiita.com/soh_mitian/items/352078dc575311ab9ad8

### 解決法
解決方法は非常にシンプルです。

```vuejs
<carousel v-if="List.length!==0">
```
このように、コンポーネントタグに```v-if="List.length!==0"```を入れるだけ。


## 参考
https://github.com/ismail9k/vue3-carousel/issues/154
[UE5]マテリアルでメッシュをローカル座標系で回転させる

# はじめに
Tick等を使わずにマテリアルを使用して、ローカル座標系でメッシュを回転させる方法です。
![y8xex-0ms2q.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/21f453ce-9804-520e-0814-ef62355d4a91.gif)

# 動作を確認したバージョン
- UE5.0.2
- UE4.27.2

# 実装
まずは[ヒストリア様のブログ](https://historia.co.jp/archives/6261/)の通りにマテリアルを組みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/0e9d6add-2a75-ac65-0f30-907a5995494a.png)

このままだとワールド座標の軸に沿って回転するため、メッシュの向きを変えるとメッシュから見た回転方向が変わってしまいます。
![0m0fs-viada.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/3c8d46f2-0f4b-1821-5295-6438977b89f5.gif)

下記のようにTransformとNormalizeノードをRotateAxisとRotateAboutAxisの間に追加することで、冒頭の動画のようにメッシュのローカル座標系で回転ができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/6d65b5e2-af3a-8fa1-1f40-46bd1ce59d35.png)
TransformのSourceはLocal Spaceにします。
これによりRotateAxisのローカル座標系をワールド座標系に変換しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/aa48646c-35e7-5da0-c6f0-7ff46454a65e.png)
ただ、それだけではベクトルの長さが1にならないようなので、Normalizeで長さを1にしています。
（RotateAboutAxisのNormalizedRotationAxisに渡すベクトルの長さが1以外だとサイズの伸縮が発生してしまうため）

# 参考サイト

https://historia.co.jp/archives/6261/

https://kinnaji.com/2019/08/19/getanglefrommaterial/
通話の画面共有でバ美肉する

公式チュートリアルを進めて最低限動くものができたので通話でバ美肉ごっこできないかと試してみました。
結論から言うと、「カメラ共有できるメディアなら何でも行けそう」でした。

https://saraemi.com/2109live2d-animaze/

こちらのブログを参考にさせていただきましたが
現在ではFaceRigが入手自体はまだできますがサポートは終わっているようで、代わりにAnimazebyFaceRigというアプリを使うことでLive2Dのモデルを動かせました。
こちらは基本無料で、ロゴを消したければサブスクに加入する必要がありますが内輪で使う分には気にならないと思います。

Animazeで「バーチャルカメラを有効」にすることによりDiscordやMeetなどでのカメラ共有設定にAnimazeが出てくるため、一般的なカメラ共有が可能なメディアであれば何でも行けそうです。
【Unity】Textで表示した文字の外側と内側を別の色にする方法

よく忘れるので備忘録的に。
ググれば普通に出てくる話ではあるけれど。

UIでTextを作成したら、「Add Component」から「outline」で目的の事が出来る。
2022年現在、「TextMeshPro」とか言うのが今後Unityのテキストの主流になる、みたいな話もあるので、1年後にはこの手法も使われない可能性もあるけど。
Docker事始め

今更ながらにコンテナ開発を理解したいとおもい、Dockerを試してみました。
最近は単独での開発で済んでいたので、VirtualBoxで足りており、Dockerで開発環境を作る必要がありませんでした。

そろそろコンテナ開発を本気で勉強しておこうとおもい、今更ながらに試しに使ってみました。

# Dockerのメリット
今ではDockerを使うのがあたりまえみたいな感じになっていますが、そもそも使うことでどんなメリットがあるのかを自分なりにまとめてみると、

1. 同一の開発環境を複数人に簡単に提供できる
1. 開発環境、テスト環境、本番環境を揃えることができる
1. Infrastructure as Codeを実践できる
1. 開発からリリースまでを全てをコンテナ単位で管理できる

と言った感じでしょうか。

その辺の概念などはAWSなどが無料でYoutubeやe-learningを提供してくれているのですが、実際にDockerなどを使って実践しようと思うとなかなか情報を見つけるのに苦労したりというのがありました。

# Dockerの基本構成
Dockerをインストールすると、仮想OS上に様々なものがインストールが完了した状態で利用することができるようになります。
例えば、Ubuntu上にWordPressが入った状態で使えるとか、CentOS上にLaravelが入った状態で使えるとか。

仮想OSはDockerImageという形でインターネット上で様々な方が提供してくれています。
また、自分なりの初期設定を施した仮想OSを作ることもできます。
そのためにはDockerFile内にインストールコマンドなどを記載してDockeImageを生成する必要があります。

# Dockerをまずはインストールしてみる
まずは以下のページをDockerをインストールして、仮想OSとしてCentOSを動かしてみました。

https://qiita.com/gahoh/items/92217e0a887bb81e3155

結構簡単にDockerImageを手に入れたり、独自のDockerImageを作ったりできます。

# 仮想OS上でApacheを動かしてみる
仮想OS上でApacheを動かすと、ブラウザからどうやってアクセスしたらいいんだろう？という疑問があったので、Apache+phpが動くDockerImageを以下のページを参考に作ってみました。

https://pocketcode.net/docker-php7-apache-install

こちらも結構簡単に行えました。
（探せば、phpが動くapacheサーバのDockerImageはいくらでもあるでしょう。）

# まとめ
今の所、私の現状を考えるとVirtualBoxから移行する手間を考えると大きなメリットがありませんが、VirtualBoxよりも非常に軽い印象があります。
どこかのタイミングで少しずつ移行してみようかとおもいます。
Pyenvを使ってから標準入力のリダイレクトがEOF errorになったので対処法

状況が特殊で同じような人はいないと思うが備忘録

## 経緯
今まで`main.py`に`input.txt`からリダイレクトさせたいと思ったときに`python main.py < input.txt`と入力していたが、それがPyenvを入れてから`EOFError: EOF when reading a line`になった

## 対処法
コマンドの最初の`python`をなくして`main.py < input.txt`に変えた
RustでUnit Testを書く

## 概要

RustでUnit Testを書く方法を学ぶための作業手順メモです。

## 参考

https://gihyo.jp/book/2019/978-4-297-10559-4

## プロジェクトの作成

Unit Testにフォーカスするためにライブラリプロジェクトを作成し、
空の状態で `cargo test` を実行してみます。

```console
% cargo new unit_test_hello_world --lib
     Created library `unit_test_hello_world` package
% cd unit_test_hello_world

% cargo test
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests src/lib.rs (target/debug/deps/unit_test_hello_world-c10baac44515af32)

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests unit_test_hello_world

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```

`src/lib.rs` に次のようなファイルが生成されているため、
プロジェクト生成の直後の状態でもテストが1件実行されています。

```rust
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}
```


## 生成されたコードについて調べたこと

- `#[cfg(test)]` アトリビュートを付けたモジュールは `cargo test` を実行したときのみコンパイルされる。
- テストケースとなる関数には `#[test]` アトリビュートを付ける


## 簡単な関数を作り、そのテストを記載する

```rust
pub fn my_div(x: i64, y: i64) -> i64 {
    x / y
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_my_div() {
        assert_eq!(2, super::my_div(4, 2));
        assert_eq!(2, super::my_div(5, 2));
        assert_eq!(3, super::my_div(6, 2));
    }
}
```

実行結果
```console
% cargo test
   Compiling unit_test_hello_world v0.1.0 (/.../unit_test_hello_world)
    Finished test [unoptimized + debuginfo] target(s) in 0.30s
     Running unittests src/lib.rs (target/debug/deps/unit_test_hello_world-c10baac44515af32)

running 1 test
test tests::test_my_div ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests unit_test_hello_world

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

```

## エラーケースを追加

Result型の勉強も兼ねてエラーケースの追加してみます。

```rust
pub fn my_div(x: i64, y: i64) -> Result<i64, &'static str> {
    if y != 0 {
        Ok(x / y)
    } else {
        Err("divider must not 0")
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_my_div() {
        assert_eq!(Ok(2), super::my_div(4, 2));
        assert_eq!(Ok(2), super::my_div(5, 2));
        assert_eq!(Ok(3), super::my_div(6, 2));
        assert_eq!(Err("divider must not 0"), super::my_div(6, 0));
    }
}
```

実行結果は次の通り。

```console
% cargo test
   Compiling unit_test_hello_world v0.1.0 (/.../unit_test_hello_world)
    Finished test [unoptimized + debuginfo] target(s) in 0.32s
     Running unittests src/lib.rs (target/debug/deps/unit_test_hello_world-c10baac44515af32)

running 1 test
test tests::test_my_div ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests unit_test_hello_world

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
```
[Python]Arduinoのシリアルポートを自動検出して取得

DeviceNameで共有で使われているデバイス名を指定

```python
import serial
from serial.tools import list_ports

class Settings:
    DeviceName = "USB-SERIAL"

def select_port(default_name=Settings.DeviceName):
    ser = serial.Serial()
    ser.baudrate = 9600  # ArduinoのSerial.beginで指定した値
    ser.timeout = 0.1  # タイムアウトの時間

    ports = list_ports.comports()  # ポートデータを取得

    # for info in ports:
    #     print(info.description)

    devices = [info.device for info in ports if default_name in info.description]

    if len(devices) == 0:
        # シリアル通信できるデバイスが見つからなかった場合
        print("error: device not found")
        return None
    elif len(devices) == 1:
        print("only found %s" % devices[0])
        ser.port = devices[0]
    else:
        # ポートが複数見つかった場合それらを表示し選択させる
        for i in range(len(devices)):
            print("input %3d: open %s" % (i, devices[i]))
        print("input number of target port >> ", end="")
        num = int(input())
        ser.port = devices[num]

    # 開いてみる
    try:
        ser.open()
        return ser
    except:
        print("error when opening serial")
        return None
```
AWS LightsailにLAMP環境を構築する

Exmentを使っているのですが、サーバへの負荷が少々重くなってきたので練習の意味もあり、AWS Lightsailに移行してみることにしました。

今後のためにその手順を載せておきます。

1. AWS　LightsailにLAMPのインスタンスを作る
1. StaticIPを設定する
1. privateキーを取得する
1. phpmyadminが使えるようにする
1. FTP接続できるようにする
1. 旧サーバのデータベースダンプファイルを取得して、新サーバに流し込む
1. 旧サーバのファイルを圧縮してLightsailにアップロードする
1. 設定ファイルの修正(今回の場合はexmentの微調整)

# AWS LightsailにLAMPのインスタンスを作る
Lightsailコンソールにログインすれば簡単に作成できます

# StaticIPを設定する
これもLightsailコンソール上で作成できます

# privateキーを取得する
これもLightsailコンソールでダウンロードできます。この後のsshアクセス、sftpアクセスに必要なのでダウンロードしておきます。

# phpmyadminが使えるようにする
bitnamiの初期設定では、phpmyadminにリモートでアクセスはできないように設定されています。
bitnamiのドキュメントでは、パソコン側でトンネル設定をしてssh経由でphpmyadminに接続する方法が紹介されていますが、これだとパソコンを起動するたびにトンネルを作成しないといけないので、今回はサーバ上のapache/conf/bitnami/phpmyadmin.confを編集して対応しました。
```:phpmyadmin.conf
Alias /phpmyadmin "/opt/bitnami/phpmyadmin"
<Directory "/opt/bitnami/phpmyadmin">
  Options -Indexes +FollowSymLinks -MultiViews
  AllowOverride All
  # Require local
  # ErrorDocument 403 "For security reasons, this URL is only accessible using l
ocalhost (127.0.0.1) as the hostname."

  AuthType Basic
  AuthName phpmyadmin
  AuthUserFile "/opt/bitnami/apache/users"
  Require valid-user
</Directory>
```

SSHでサーバに接続してファイルを直接編集します。
設定が終わった後は、apacheサーバの再起動が必要です。

```
sudo /opt/bitnami/ctlscript.sh restart apache
```

# FTP接続できるようにする
FileZillaにprivateキーを設定して接続できるようにしました。

＜＜参考＞＞

https://lightsail.info/ftp-client-access/

# データベース移行
旧サーバのphpmyadminからデータベースのダンプファイルを取得して、Lightsailのphpmyadminで流し込みました。

# 旧サーバのファイルをLightsailにアップロードする
tar,gzipでフォルダごと圧縮をかけてFileZillaでダウンロード、Lightsailにアップロードして展開します。

# 設定ファイルの修正
~/stack/apache/conf/httpd.confを修正して、新しいフォルダへアクセスできるようにします。
config関連ファイルなどを修正してうまく動くように調整します。

以上で終了です。今後徐々に様々なものをLightsail上に移行していこうかと思っています。
【SwiftUI】Extra argument in callの対処法

# はじめに
`Extra argument in call`はSwiftUIにはあるあるで、よく発生します。

# 原因
SwiftUIはView要素を9個以上追加できないようになっています。
![スクリーンショット 2022-06-11 15.37.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4461b888-9e5f-da8e-1d48-1c9171aa986f.png)

# 解決策
Viewを`Group`でグループ化して要素をまとめます。
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Group {
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
                Text("Hello, world!")
            }

            Group {
                Text("Hello, world!")
            }

        }
    }
}
```

これでエラーは出なくなります。
Xcode Previewsのためのビルド時はBuild Phase Scriptを実行しない

⚠️ Xcode 16からこの方法は効かなくなっているようですのでご注意ください。

https://qiita.com/hohohehetoto/items/1038ee5f5300047ba953

---

XcodeのBuild PhasesスクリプトでFormatterやGeneratorを実行していると、そのコード変更によりXcode Previewsが不安定になることがあります。
Xcode Previewsのためのビルド時は環境変数`ENABLE_PREVIEWS`が`YES`に設定されているので、その時はスクリプトを実行しないようにすることでXcode Previewsの動作が安定します。

```sh:Run Script
# Xcode Preview のビルド時はスクリプトを実行しない
if [ \"$ENABLE_PREVIEWS\" == \"YES\" ]; then
  exit 0
fi

# Formatter, Generator の実行
...
```
github issueで設計する時に気をつけるポイントを自分なりにまとめてみた

# はじめに
皆さんこんにちは。
最近転職し、初めてgithubのZenHubを使いながら、issueベースでのスクラムを経験しております。
（情報量が多いですね 笑）

スクラムを進めていく中で、機能実装の案件に携わることになりました。
仕様・設計について大変勉強になったのでアウトプットしたいと思い投稿しております。

#### 全体像
まず、全体的なコーディングするまでの流れとして、
1. issueの作成（課題・今回のゴール・背景など　ビジネスサイドの情報　作成者はPO or SM）
1. 実装するに当たり影響範囲・実装イメージの確認（簡易見積り）
1. 元issueをベースに設計・仕様のissueを立てる
1. 設計・仕様issueをベースに実装issueを立てる
1. 各実装issueを順番に開発

のような5ステップがあります。
また`5. 各実装issueを順番に開発`からコーディングになるので
そこから、PRやテスト等盛りだくさんです。

このように非常に丁寧に仕事が進んでいきます。
機能追加が本番環境に反映されるまで、今回の案件に関して言うと2週間ほどかかります。
（案件により期間は前後します）

個人的な話になってしまいますが、
前職の本番反映と見比べていただくとわかりやすいかと思います。
以下が前職での本番環境反映までの流れです。
1. 要件定義（エクセルで作成されたもの）
1. コーディング
1. テスト環境で最終確認
1. 本番反映

「おそろしく早い本番反映、俺でなきゃ見逃しちゃうね。」
前職と見比べてもらうだけで、どれだけ丁寧かわかると思います。

#### 勉強になったこと
`3.元issueをベースに設計・仕様のissueを立てる`の実行中、初めて同じスクラムメンバーにレビューいただきました。（設計・仕様issueでレビューいただけるなんて嬉しいですよね）
そのレビューが大変参考になり、非常に丁寧に教えていただいたのでそれをアウトプットしようと思います。

# 仕様・設計のアウトプット

## レビュー学んだこと
#### 要件はユーザーストーリーベースで書くと分かりやすく、また漏れに気づきやすい
例えば下記のように、○○はXXできる〜というふうに書くと良い。
そしてストーリーベースで書くと、それがそのままテストケースとしても生きてくる。

> ユーザーはカレンダータイプの予約枠において、曜日ごとの休憩時間を「xx時xx分」から「xx時xx分」までという範囲で指定できる
>   - 分数はN分単位で選択できる
>ユーザーはカレンダータイプの予約枠において、曜日ごとの休憩時間を複数設定できる
>  - 休憩時間が複数設定されている場合は、好きなものを選んで削除できる
>  - 休憩時間が複数設定されている場合は、開始と終了の範囲が被らない時間を選択する必要がある
>  - 休憩時間が1つしか設定されていない場合は、削除できない
>  - 休憩時間が複数設定されている場合は、入れ替えをすることができない

#### 抽象的な表現は控え、はっきりと書く
`ユーザー`ひとつとっても、`エンドユーザー`や`アクティブユーザー`など様々表現ができてしまう。
そこから認識にズレが発生し、作業し直しになる場合もあるので、抽象的な表現はなるべく避ける。

#### フロントエンド/バックエンド両方の領域の視点を持つ
※今回のAPIを実装する機能の話の例

最初にDBの構造がどうなるかを想像してから考えるとイメージしやすい。
TBLに`☓☓_☓☓`みたいなカラムができるとすると、APIには文字列データが必要で…
　のようにFE視点で考えるのではなく、もっと広い視野で考える。
複数の実装方法がある場合もあるため、フロントエンド　バックエンドでどういう実装するかも事前に話し合う必要がある。

#### 機能追加のサイズ感によってはリリースブランチを作成する
ファイル数によってはレビュアー負荷が高くなるので、リリースブランチを作成するか、1PRにするか検討する。

#### システム要件なのかビジネス要件なのか
システム要件の場合は実装中で修正できるが、ビジネス要件の場合は実装前に確認必須。
確認しないまますすめてしまうと、余計な工数が発生する可能性大


## 最後に
以上が今回の設計・仕様issueで学んだことです。
その他にも実装issueの立て方を、作業ファイルで分けるのではなく、作業範囲で分けるなど
たった1週間（issueレビューは2日間）でしたが、非常に学ばせていただけました。

来週もいろいろ学びの多い一週間になると思うので、どんどんアウトプットしていこうと思っています。
ここまで読んでいただきありがとうございました。
jQuery を読み込まずに、$.ajax 構文だけは使えるようにするためのポリフィル

作成したコード：

```JavaScript
const $ = (() => {
    if (typeof jQuery === "undefined") {
        return {};
    }
    return jQuery;
})();

$.ajax =
    $.ajax ??
    (async (url, options) => {
        if (typeof url === "object") {
            options = url;
            url = undefined;
        }

        const controller = new AbortController();
        const timeoutId = window.setTimeout(
            controller.abort.bind(controller),
            options.timeout ?? 10000
        );

        const fetchOption = {
            method: options.type ?? "GET",
            cache: options.cache ? "default" : "no-cache",
            credentials: "same-origin",
            redirect: "follow",
            referrerPolicy: "no-referrer",
            signal: controller.signal,
        };

        if (options.type === "POST" && options.data !== undefined) {
            const postData = new FormData();

            Object.entries(options.data).forEach(([key, value]) => {
                if (value === undefined) {
                    return;
                }
                postData.set(key, value);
            });

            fetchOption.body = postData;
        }

        return window
            .fetch(url ?? options.url ?? "", fetchOption)
            .then((response) => {
                if (response.ok === false) {
                    console.error(response);
                    throw new Error(response.statusText);
                }
                window.clearTimeout(timeoutId);
                return response.json();
            })
            .catch((error) => {
                console.error(error);
                throw new Error(error);
            });
    });
```

以上のポリフィルを読み込むことで、jQuery を使わずとも、以下のような構文を利用できます。

```JavaScript
$.ajax({
    url: "https://ajax.example.org/posts",
    type: "POST",
    cache: false,
    timeout: 5000,
    data: {
        groupID: 15,
        userID: 1992,
    }
})
    .then((result) => {
        console.log(result);
    })
    .catch((err) => {
        console.error(err);
    });
```

ただし、done と fail は使えません。
どう書けば使えるようになるのか見当もつきません。

```JavaScript
// 以下は jQuery なしの場合エラーとなる。
$.ajax({
    url: "https://ajax.example.org/posts",
    type: "POST",
    cache: false,
    timeout: 5000,
    data: {
        groupID: 15,
        userID: 1992,
    }
})
    .done((result) => {
        console.log(result);
    })
    .fail((err) => {
        console.error(err);
    });
```

ie11 終了に伴い、jQuery を読み込まないことに決めたため、以上のポリフィルを作りました。モダンブラウザのみに対応させればよいということにしたため、fetchAPI や null 合体演算子（??）を利用しています。そのため古いブラウザでは動きません。

本当はもっと多くの引数・処理が存在するようですので、正直ポリフィルとは言えないと思います。自分が使う機能をやっつけ仕事で記述しました。もっと良い方法があったら教えてください。
RailsでGemを更新したら再起動しましょうという話【初学者向け】

:::note result
**gemを更新したらサーバーを再起動しないと反映されない🥲**
:::

## 解決策
### dockerなしの通常開発環境の場合
railsを再起動する
```terminal:terminal
$ rails restart　
```

### docker環境の場合
``docker compose up -d``で「web」をバックエンドで起動している状態を想定。
```terminal:terminal
$ docker compose exec web bundle install   #gemを更新。これだけじゃ足りない😭
$ docker compose restart                   #dockerの再起動、これが必要😁
```

ちなみに、、、
gem更新後にrailsを再起動すれば良いので以下でもOK。
```terminal:terminal
$ docker compose exec web bundle install   #gemを更新。これだけじゃ足りない😭
$ docker compose exec web rails restart    #dockerコンテナでrailsを再起動する😁
```

## 今回、こんな感じでハマった
**「ActiveModelSerializers」** という、Rubyでjsonを整形してくれるライブラリを導入した時に詰まりました😇
https://github.com/rails-api/active_model_serializers


### やりたかったこと
Postmanでリクエストを送り、UserモデルからUser ID のみjsonで返却させたい。
↓この記事でやってることです

https://qiita.com/onikan/items/d24ce08adf144c326812#%E5%B0%8E%E5%85%A5%E3%81%A8%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9

### 実際にやったこと

`docker compose exec web bundle install`にてgemを更新...
```:結果→失敗😇
{
    "status": 500,
    "error": "Internal Server Error",
    "exception": "#<NameError: uninitialized constant ActiveModel::Serializer\n\nclass UserSerializer < ActiveModel::Serializer\n                                  ^^^^^^^^^^^^\nDid you mean?  ActiveModel::Serializers>",
    "traces": {
        "Application Trace": [
...
```
idをjsonで返却するだけなのに500エラー！！
` uninitialized constant`と表示されているので、クラスが読み込めてないのか？と思い調べながら1時間ほど四苦八苦😥

一から環境構築してやり直してみるか〜と思って`docker compose down`。
その後、やっぱ環境構築がめんどくせーとなって、もう一度`docker compose up -d`してチャレンジしようとしたら上手く言ってた(笑)

```terminal:結果→成功😁
[
    {
        "id": 1
    }
]
```

何かうまく動いてなかったら、とりあえず再起動しようと誓ったrails初心者でしたw

## 余談
↓今回の失敗に関しての記事

https://qiita.com/gyu_outputs/items/1cc1903db802daf0fdbc

後で「gem 更新されない」で調べたらヒットしました。
ずっとライブラリ側のワードで検索して悩んでましたが、どう調べるとこの記事に早くたどり着けたのでしょうか🤔
コメントよりアドバイスくださると嬉しいです😆
Node.js(Express)で書いたJSONデータの受け渡しプログラムをHeroku上で動かしてみる

Node.js(Express)でGETリクエストに応答するだけのプログラムを作れたので、次はクライアント側からPOSTしてなんやかんやするプログラムを作ります。
JSONデータのPOSTを受け取って、そのままJSONデータを返してもらいましょう。
# 結論
どハマりするポイントもなくすんなり書けます。
JSONデータを受け取る、JSONデータを返すができればDB連携のあるプログラム作成も目前感がしてちょっとした進歩感が出てきて嬉しい。


##### 環境
Win10+VSC@1.68
Node.js@16.14.2+Express@4.18.1
##### やろうとしたこと
- Herokuサービス上でNode.js(Express)アプリケーションを動かす
- JSONデータをポストしてJSONデータを返してくれる実装

## やってみる
Herokuにアプリをデプロイするのはこっち参照

https://qiita.com/shichisan21/items/b163e33669763ca6fffc

POSTされたJSONデータを返すプログラムの作成メモはこっち

https://qiita.com/shichisan21/items/4d18ce73708cd6cd8d6e

まずGETリクエストに応答するだけのプログラムにPOSTリクエストを受け付ける部分を足していきます。

```:index.js
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.get('/', function (req, res) {
  res.send(`HELLO WORLD!! PORT NUMBER is ${PORT}`)
})

app.post('/', function (req, res) {
    console.log(req.body)
    res.json({
        msg: 'These messages are JSON',
        name: req.body.name,
        data: req.body.age
  })
})

app.listen(PORT)
console.log(`Express Server Listen START at port=${PORT}`)
```

REST Clientを使ってPOSTリクエストが返ってくることを確認します。
こちらを参考にJSONデータをPOSTリクエスト。

https://qiita.com/toshi0607/items/c4440d3fbfa72eac840c

```:.http
POST  http://localhost:3000 HTTP/1.1
content-type: application/json

{
    "name": "Anya Forger",
    "age": "6"
}
```
```:Response
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 65
Connection: close

{
  "msg": "These messages are JSON",
  "name": "Anya Forger",
  "data": "6"
}
```


最初 __REST Client__ で投げるデータでエラーを出しました。
ちょっとしたハマりどころかもしれないのですが、どうやら`content-type: application/json`の後に改行を挟まないといけないらしい。
データの中身とヘッダ部は改行で分けろ、ってことなんですね。

https://qiita.com/hiro5963/items/b55c125b6400cbaa2f5d

## Herokuにデプロイ＆実行
コミットしてローカルリポジトリにプッシュしてから`git push heroku [ブランチ名]`を実行。
そして`heroku open`
![5de901470ab8eabbca4e37acac144e3d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707014/53855b82-4972-c942-5e19-99a151dd8e74.png)
正常に動いていることを確認できました。

続いてこの`heroku open`で開いたアドレスに対して、REST ClientからJSONデータをPOSTします。
```:.http
POST https://[ほにゃらら(アプリ名)].herokuapp.com HTTP/1.1
content-type: application/json

{
    "name": "Anya Forger",
    "age": "6"
}
```
```:Response
HTTP/1.1 200 OK
Connection: close
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 65

{
  "msg": "These messages are JSON",
  "name": "Anya Forger",
  "data": "6"
}
```
__成功です！__
JSONデータをPOSTして、返ってきたデータもJSONデータになっています。
SPY FAMILYは放映終了したら一気見したい。

## まとめ
エラーが出てきたところといえばPOSTする時にREST Clientの書き方を間違えた部分くらい。
あと、本文には書きませんでしたがapp.postの中にres.sendとres.jsonを一緒に書いてres.json側が出力されなかったりといった凡ミスがありました。

次はJSONデータをDBに格納する/読み出すとかやりたいところ。
Error Code: 1248. Every derived table must have its own alias の解決方法

# 執筆理由

SQLで下記のテーブルから、同じクラスの生徒で、好きな色（favorite_color)が全員赤色のクラスIDを抽出できるようなSQL文を作成したかった。

**テーブル名：class**
| id   | class_id | name | favorite_color|
| ---- | -------- | ---- | ------------- |
| 1    | 1        | 佐藤 | 赤            |
| 2    | 1        | 田中 | 赤            |
| 3    | 1        | 近藤 | 赤            |
| 4    | 2        | 辻　 | 黄            |
| 5    | 2        | 森　 | 赤            |
| 6    | 3        | 三浦 | 赤            |

このテーブルだと、同一クラスでfacorite_colorが全員「赤」なのは、class_id = 1と3になる。

しかし、タイトルのエラーが出て解決に手間取ってしまったので、メモとして解決方法まとめることにしました。

# 今回のエラーが出たSQL文
下記のSQLを作成した。

```sql
SELECT class_id
FROM 
( SELECT class_id
    FROM class 
    GROUP BY class_id
    HAVING COUNT(*) = SUM(CASE WHEN favorite_color = '赤' THEN 1 ELSE 0 END)
)
```

すると下記のエラーが出た。

```
Error Code: 1248. Every derived table must have its own alias
```

# エラーの原因

英吾のままだと何を言っているのかよく分からないので、ひとまず翻訳。。。。
すると、「すべての派生テーブルには、独自の通称が必要です」とのこと。
今回は、FROM　の後にサブクエリ（派生テーブル）を入れたにも関わらず、名前をつけていなかったから怒られているみたい。。。

# 解決策

エラーの内容から、FROM の後の派生テーブルに名前をつければいいっぽいのでSQLを下記のように修正してみました。

```sql
FROM 
( SELECT class_id
    FROM practice_sql.class 
    GROUP BY class_id
    HAVING COUNT(*) = SUM(CASE WHEN favorite_color = '赤' THEN 1 ELSE 0 END)
) AS hoge -----派生テーブルに対してつけた名前

```

そして、SQLを実行すると無事欲しかった形のデータを抽出することができました。

| class_id | 
| -------- | 
| 1        | 
| 3        | 

# 感想

エラー文をちゃんと読んで原因を確認するのは原点にして頂点なのだと改めて痛感しました。
Next.jsのnext/imageについて引数ざっくりメモ

## Requiredな引数
| 引数名      | 説明                                  |
|:-----------|------------------------------------- |
| src        | 画像のpath<br>(例: https://...みたいな) |
| width      | 画像の幅                              |
| height     | 画像の高さ                             |

## Optionalな引数
| 引数名<br>(太文字は重要)      | 説明                              |
|:-----------|--------------------------------- |
| __layout__     | viewportが変化したときの画像のサイズを指定する |
| __loader__     | next.config.jsに設定を加えるとデフォルトのローダーが上書きされる(画像を読み込んでくれる処理という認識です) |     
| sizes         | 異なるブレイクポイントで画像がどの程度の幅になるかの情報を提供する文字列を指定(例: sizes="50vw"),sizesがないとパフォーマンス低下するので注意。 |
| quality         | 最適化される画像の質(デフォルトが75) |
| __priority__        | 画像読み込みを優先度高めてpreloadする(LPC要素と判断される) |
| __placeholder__         | 画像を読み込んでいる時に表示する画像を設定できる |

[sizesがないとパフォーマンス低下](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-sizes)
[preloadする](https://web.dev/preload-responsive-images/)
[LPC要素について](https://nextjs.org/learn/seo/web-performance/lcp)

# Next.jsの公式
### API_Reference
https://nextjs.org/docs/api-reference/next/image#loading

### Basic Feature
https://nextjs.org/docs/basic-features/image-optimization
HHKBの日記

# はじめに
在宅勤務が増えて数年、少しずつ家の仕事環境を整えてきました。その中でHHKBというキーボードを購入したので、操作方法などについて記載したいと思います。本記事の目的はHHKBの操作性に適応することです。

https://happyhackingkb.com/jp/

### 今まで使っていたキーボード
会社ではノートパソコンのキーボード、自宅では有線のコンパクトキーボード「TK-FCM103BK」を利用していました。家電量販店で2,000円ほどで購入したものです。概ね満足していたものの、毎回USBの抜き差しをするのが少しだけ手間だと感じており、無線のキーボードで良いものがないかを探し始めたのがこの記事のきっかけになります。

https://www.elecom.co.jp/products/TK-FCM103BK.html

### 購入したHHKB
Youtubeで「キーボード沼」という言葉を知り、たくさんの動画で紹介されているHHKBを使ってみたいという衝動に駆られ始めました。しかしながら現在保有するキーボードの15倍以上の価格に悩み、しばらく踏み切ることができませんでした。数か月間悩んだ末、無事ににHHKB Professional HYBRID Type-S/日本語配列/白([PD-KB820WS](https://happyhackingkb.com/jp/products/hybrid_types/))を注文することができました。

https://happyhackingkb.com/jp/products/hybrid_types/

# 日記
1. 2022年6月10日 PFU DirectよりHHKBが届く。開梱し、付属していた単三電池をセット。仕事用パソコンとのペアリングを実施して利用を開始。多くの方々が絶賛する打鍵感の第一印象は悪くないと感じるが、使い勝手の違いに戸惑うことが多発。第一にIMEの切り替えのつもりでESCキーを押してしまう問題が頻発。第二にPageUp/DownやHome/Endのキーを押すのが困難。適応できるか不安。
1. 2022年6月11日 自宅のPC及びAndroidスマホとペアリング実施。複数デバイスの切り替え方法をマニュアルにて習得。AndroidのIME切替、物理キーボードとして日本語配列で認識させることに成功。日本語配列には109A以外にS-Shoinというものがあることを発見。AQUOSに書院の名残を見るとは。
1. 2022年6月13日 一つ困ったのは会社パソコンの起動時にWindows10のbitlockerというHDDの暗号化ツールが起動してパスワードを求められるが、その時点ではOSが起動していないためHHKBでの入力ができないことが判明。その後マウスの右クリック相当のキー操作を把握。
1. 2022年6月14日 Web会議など、キーボード操作が30分無いとBluetoothの接続断が発生。DIPスイッチ#6をOFF→ONにすることにより、回避できるとのこと。
1. 2022年6月17日 上記の方法でBluetoothの接続断が無くなり快適化を実感。極端な電池の減りも現状無し。Windows上でのIME切替キーが非常に押しづらい位置に配置されている問題で、PowerToys等での解決も検討したが、通常のIME設定画面で[変換]キー等を割り当て可能なことを発見。
1. 2022年6月25日 キー操作に慣れ始めたところで、ノートパソコンのキーボードを利用する際にControlを押し間違える事象が発生。PowerToysでCapsLockキーをControlに割り当てることを試みるも、失敗。
1. 2022年7月18日 使い続けて1か月。突然きた電池0%の知らせ。そのごもしばらくは利用できる模様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/020e27e3-5917-321e-f6bc-1a9f81d48c82.png)


# 覚えたこと
便利と感じたコマンドなどを書き留めます。
## Windowsの操作
* IMEの切替方式について
    * MicrosoftのIMEは通常の設定画面から[キーとタッチのカスタマイズ]により、変換のON/OFFを[変換]キーなどに割り当てることができます。
## 特殊なキー操作
* マウスの右クリック相当
    * [Fn]+[Shift]+0
## Bluetooth関連の操作
* 複数の機器とのペアリング（4台まで可能）
    * [Fn]+Q
    * [Fn]+[Control]+[1-4]
* 接続機器の切り替え
    * [Fn]+[Control]+[1-4]
## Androidでの操作
* IMEの切替は
    * [Shift]+[Space]
* 日本語配列のキーボードを認識させるには。
    * [システム]-[言語と入力]-[物理キーボード]でHHKBを選択
    * [キーボード配列]-[日本語109A配列]を選択

# 参考文献

https://happyhackingkb.com/jp/download/
kazuo_reve さんがベストプレゼンテーション賞　を受賞されて思い立ったこと。

@kazuo_reve 新人の方によく展開している有益な情報

https://qiita.com/kazuo_reve/items/d1a3f0ee48e24bba38f1

色々なランキングにも入り、今年の行事の際は、行事の記事の参照に入っていた。きっとviewsも伸びたに違いない。

2021年は、投稿のきっかけとなった元記事と、自分が引用してもらった記事の書き直しだけして、あとは拝見して集計しただけだった。

「@kazuo_reve の Qiita記事」の分析

https://qiita.com/kaizen_nagoya/items/81e3519e3740fa766d6a

記事を参照してもらった時にしていること。 

https://qiita.com/kaizen_nagoya/items/0e4e92f45c158ef81423

2022年は、すべての記事を拝見し、自分の記事への反映を試みようとした。


# 新たな目標

@kazuo_reve さんが、

>先日、派生開発カンファレンスで、発表させていただきました。
ベストプレゼンテーション賞いただきました！

https://qiita.com/kazuo_reve/items/58076494d0bb72c0a37a

https://affordd.jp/.../affordd-conference2022-denso-create/

とのこと。

おめでとうございます　いくつかの案件で後を追いかけようとしています。自分が先に走らなきゃいけないかもしれない案件もあり、書ききれていません。ごめんなさい。

https://qiita.com/kaizen_nagoya/items/b9380888d1e5a042646b

一度は、確認記事の方の表題の見直しと、URLの不足を補う書き直しした。
だいたい100点満点で10点から30点くらいのばらつきを感じる。（３倍）
できれば、30点から60点くらいのばらつきに抑えたい。（２倍）
今年の12月末までに、確認記事と自己記事の加筆することを目標にする。

数値目標としては、当初の５月時点では現在46,000viewsを100,000viewsにすることにしていた。

今回の、@kazuo_reveさんの受賞を記念して、
関連自分の全記事のいいね(goods)とViewsのどちらかは、元記事を超えることを目標にしようと思った。

最初のviewsだけの目標よりは、ちょっと困難だ。
やってみて、価値があることがみつかるような気がする。

場合によっては、関連記事も足して、水増しさせてもらおうかなって思うんです。

p.s.
やりかけの下記記事の70点到達を優先させてください。

「@kazuo_reve, AUTOSARのClassic PlatformとAdaptive PlatformにおけるDiagnosticsの違いを整理」で慌てて

https://qiita.com/kaizen_nagoya/items/d3ff6aba9b7402e8bde8

AUTOSAR 21-11, 335文書読んだ。2022年6月初旬にFO, AP, CP全部到達。

https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR文書の読み方（文書番号と発行年）2021-11 改訂版

https://qiita.com/kaizen_nagoya/items/62f8329c67a4d95d7bcb

IEEE 802.3 Ethernet 単語帳

https://qiita.com/kaizen_nagoya/items/4c31491f1883dd5ecfae

# 参考資料

私が効果を確認した「小川メソッド」

https://qiita.com/kazuo_reve/items/a3ea1d9171deeccc04da

タグ　小川メソッド　めざせ100記事

「https://qiita.com/tags/%e5%b0%8f%e5%b7%9d%e3%83%a1%e3%82%bd%e3%83%83%e3%83%89」

https://qiita.com/tags/%e5%b0%8f%e5%b7%9d%e3%83%a1%e3%82%bd%e3%83%83%e3%83%89

p.s. 
言い訳を書かせてください。

経済学徒だったころ、３つほど懸賞論文で落ちました。
すこし、趣をかえて、データ分析を書いたら、すぐに受賞しました。

その後は、どちらかというと、審査する側で、自分のを通すのは憚れるため、賞狙いはしたことがありませんでした。

大学院の博士課程で、海外発表が要件になっておろ、投稿したところ、long paperではなく、short paperとして通りました。long paperとshort paperと合わせて、Selected Presentationという賞をいただいたことがあります。

Qiitaの一番いいね（LGTM)が多い記事に基づいて投稿したデモは、Silver賞をいただいたことがあります。

最近思うのは、聴衆に受ける話ができないと、お客様も喜んでいただくことはできない可能性があるかもっていうことです。

最後に、facebookに書いた紹介
>柏原一雄さん。ほぼ毎年のご受賞おめでとうございます。山路厚さん、竹下千晶さんの聴講者に焦点をしぼったよい発表を受け継がれているのがすごいと思います。３代受け継ぐのって難しいっていうのが経験則。 p.s. ところで私は何があっても記事にしてしまう今日この頃、皆様いかがおすごしですか。

https://qiita.com/kaizen_nagoya/items/a661a912248c05ea6712


# 参考資料

新しい記事７割、過去記事更新３割。

https://qiita.com/kaizen_nagoya/items/82138c13d957dd1300af

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
WSLの環境を別名で複数作る


WSLの環境を複数作りたい、もしくはWSLの複製を作りたい場合の方法

いちど`wsl.exe`の `export`でtarファイルに出力してから `import` します。
```powershell
# ディストリビューションの一覧を表示
PS> wsl.exe -l -o
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS

# Ubuntu-20.04をcopyしてtestUbuntuを作成
PS> wsl.exe --export Ubuntu-20.04 test.tar

PS> wsl.exe --import testUbuntu testUbuntu test.tar
PS> del test.tar
```
【React】公式のチュートリアルをやってみる～⑥プレイヤーの追加

[【React】公式のチュートリアルをやってみる～⑤関数コンポーネント](https://qiita.com/asahina820/items/19822a54cac199fa1230) の続きです。
まだ盤面にXしか表示されていません。 Oを追加して、交互にプレイできるようにしましょう。

## プレイヤーを追加する
### stateに手番を判定する変数を追加する
```diff_jsx
class Board extends React.Component {
  // コンストラクタ
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
+     xIsNext: true,
    }
  }
  (略)
}
```
- stateに`xIsNext`変数を追加して、次のプレイヤーはXかどうかを判定する
- デフォルトではtrue = 先手を“X にする

### マス目がクリックされる度に手番を変更する

```diff_jsx
class Board extends React.Component {
  (略)
  handleClick(i) {
    const squares = this.state.squares.slice();
-   squares[i] = 'X';
+   squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
+     xIsNext: !this.state.xIsNext,
    });
  }
  renderSquare(i) {
    return (
      <Square 
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
  (略)
}
```
- マス目をクリックしたときに呼ばれる`handleClick`関数内で、画面に描画する値と次のプレイヤーを判定する真偽値を設定する
    - 画面に描画する値は、プレイヤーごとに設定する
        - xIsNextがtrueだった場合（Xがプレイヤー）は、Xを設定する
        - xIsNextがfalseの場合（Oがプレイヤー）は、Oを設定する
    - 次のプレイヤーを判定する真偽値は、現在のxIsNextの値を逆にして設定する
        - xIsNextがtrueだった場合（Xがプレイヤー）は、falseに設定する（Oがプレイヤーになる）
        - xIsNextがfalseだった場合（Oがプレイヤー）は、trueに設定する（Xがプレイヤーになる）

#### 条件演算子について(JavaScript)
- 条件 (三項) 演算子とは、JavaScriptで唯一、3 つのオペランドをとる演算子
    - if文の代替としてよく用いられる
- 構文は、`condition ? exprIfTrue : exprIfFalse`
    - condition: 条件式
    - exprIfTrue: condition が真値 (trueと等しいか、trueに変換できる値) と評価された場合に評価される式
    - exprIfFalse: condition が偽値 (falseと等しいか、false に変換できる値) と評価された場合に評価される式
 

### 次のプレイヤーを表示する

```diff_jsx
class Board extends React.Component {
  (略)
  render() {
-   const status = 'Next player: X';
+   const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}
```

- 次のプレイヤーを表示する`status`変数を動的に設定する
    - xIsNextがtrueだった場合（Xがプレイヤー）は、Xを表示する
    - xIsNextがfalseだった場合（Oがプレイヤー）は、Oを表示する

![ReactApp7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/4518ce30-79ae-6d4d-9840-3d0e927b6385.png)
ついに、盤面にOが登場しました～
マス目をクリックすると、OとXが交互に表示されて、次のプレイヤーは誰かも表示されるようになりました。
完成が近づいてきました～



## 参考文献
- https://ja.reactjs.org/tutorial/tutorial.html#taking-turns
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
【初心者向け】Reactでボタンのコンポーネント 

## はじめに

React, Tailwind CSSでボタンコンポーネントを作ります。
初心者向けの記事です！
ボタンコンポーネント結構便利なので、毎回ボタンをベタ書きしている人がいたら是非作ってみてください。
ベタ書き辞めてコンポーネント化した時は、想像以上の快適さでびっくりした記憶があります。

何個もボタンあるけど、コンポーネント作ってないって方は是非作ってみてください！

※「ここが変」とかあったら教えてもらえると嬉しいです🙇‍♂️

## メリット

* ボタンを作るのも変更するのも楽
* ボタンのスタイルが微妙に違うみたいなことが起きない
* 既に作ってあるボタンから使おうと思うから統一感が出る(スタイルの違うボタンが減る) などなど

## コード
```.tsx
type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & {
  children: React.ReactNode;
  variant: keyof typeof buttonStyle;
};

const buttonStyle = {
  "green-fill": "bg-green-400 text-white",
  "red-gradation": "bg-gradient-to-r from-red-300 to-red-600 text-white, hover:from-red-600 hover:to-red-300",
  "variantのkey名3": "スタイル",
  "variantのkey名4": "スタイル",
} as const;

export const Button = ({ children, variant, className, ...props }: Props) => {
  return (
    <button
      className={`rounded-md ....(ここら辺にボタンの共通のスタイル) ${buttonStyle[variant]} ${className}`}
      {...props}
    >
      {children}
    </button>
  );
};
```

## 解説

### buttonStyle

* variantによって複数の種類のボタンを切り替えることができ、種類ごとのスタイルをbuttonStyleに書いています。
* keyとvalue(スタイル)には好きな値を入れてください。

### Button

* ボタン共通のスタイルは`rounded-md ....(ここら辺にボタンの共通のスタイル) ` の部分に書きます。
* `buttonStyle[variant]` でvariantに指定したkey名のスタイルを取得しています。
variantがgreen-fillなら、`buttonStyle[green-fill]`となり、`bg-green-400 text-white`の値になります。
* classNameのスタイル、ボタンの共通のスタイル、variantごとのスタイルを全部くっつけたのがこのボタンのスタイルになります。
* `{...props}`では、className以外のbuttonの属性をbuttonタグに渡しています！
※ onClick、onFocus、id、、などなど
これで、buttonタグを扱うようにButtonコンポーネントを扱えるようになります！

### Props

* `React.ButtonHTMLAttributes<HTMLButtonElement>`でbuttonタグが受け取れる属性をPorpsに受け取れるようになります！
※ className、onClick、name、id、、、などなど
なので、buttonタグを扱うようにButtonコンポーネントを扱えるようになります！
* `variant: keyof typeof buttonStyle;`はbuttonStyleのkey名の型になります。
green-fill、red-gradation、などのkey名の文字列のみを指定することができるようになります。
* `children: React.ReactNode;`にすることで文字列以外もボタンの中に入れることができます。例えば、アイコンと文字を入れることが可能になります。

## 使い方

variantを指定して、ボタンの種類を選びます！

```.tsx
<Button  variant="green-fill">ボタン</Button>
```

onClickやclassNameなどbuttonに渡せるものは渡せます！
```.tsx
<Button  variant="green-fill" onClick={handleClick} className="px-10">ボタン</Button>
```

アイコンなどのコンポーネントも渡せます！
```.tsx
<Button  variant="red-gradation"><Icon/>ボタン</Button>
```
Flutter: XCode error "Unable to boot the Simulator"


## 概要

任意のsimulatorを起動しようとすると次のエラーが出る

```
Flutter: XCode error "Unable to boot the Simulator"
```

## 対処法

1. 次のページを開く [このMacについて > ストレージ > 管理 > デベロッパ]
1. 全てのコンテンツを消す


以上です。

## 参考文献

https://stackoverflow.com/questions/72229589/flutter-xcode-error-unable-to-boot-the-simulator
[javascript,cssアニメーション]草からテキストが生えてくるアニメーション

テキストを入力するだけでメッセージ動画が作れるサービス[Teloppy](https://teloppy.com "Teloppy")を運営しております！
その中で用いたアニメーションのコードを一部紹介したいと思います！
![ea2c50d51c1234f4916b7cc21a0d9e0b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707318/821b3df2-4496-34cf-8c0d-f16170d71812.gif)

まずは、コードの完成形です。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="BaYGRMa" data-user="teloppy_com" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/teloppy_com/pen/BaYGRMa">
  Untitled</a> by Teloppy テロッピー | 自分だけのメッセージ動画を作ろう (<a href="https://codepen.io/teloppy_com">@teloppy_com</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

htmlのタグの

```html
<div class="catch">草からテキストが出てくる</div>
<div class="shadow">草からテキストが出てくる</div>
```

catchは背景画像と同化した文字、shdowは、影だけの文字と役割が分け、それを重ねることで実現しています。


そして重要になるcssがこの記述です。
```css
body {
 background:url(https://drive.google.com/uc?export=view&id=19JvBpXFksnKhWWLNuOE6YZYdvD2z060A);
  background-size:160px auto;
}
.catch{
   background:url(https://drive.google.com/uc?export=view&id=19JvBpXFksnKhWWLNuOE6YZYdvD2z060A);
  background-size: 160px auto;
  background-clip: text;
  -webkit-background-clip: text;
}
```

ここの、background-clip:textの部分は、文字の背景を画像にするときに用いる記述であり、bodyの背景と.catchの背景を同じにすることで同化させています。

.catchにtext-shadowつければ一番早いんですが、 **background-clip: textを用いた場合、文字に影をつけることができないので**、影用の要素である.shadowを重ねることで擬似的に影をつけているという訳です。(.catchが上に来るようにz-indexで調整が必要)

```css
.catch,.shadow{
  text-align:center;
  font-size:7vw;
  position:absolute;
  width: 100%;
  top:50%;
  transform:translateY(-50%);
  font-weight: bold;
  color:transparent;
  transition:all 0.3s;
}
```

で、あとはjsで.shadowにis-visibleをつけてやれば出来上がりです。 
```css
.shadow.is-visible{
  text-shadow: 0 5px 5px #0D3400;
}
```
 background-size:160px auto;ここの部分をカスタマイズすると草感が変わりますので試してみてください

また、こんな感じでホバーアクションにしても良さげです。
```css
.shadow:hover{
  text-shadow: 0 5px 5px #0D3400;
}
```


Teloppyではこんな感じのアニメーションを多く作ってます。[twitter](https://twitter.com/teloppy_com)のフォローもお願いします:sunny:
PSReadLineで提供される入力履歴の削除について

PowerShellのモジュールPSReadLineでは入力履歴を管理しており。

PSReadLineの設定項目にあるPredictionViewStyleで`ListView`を設定していると、この入力履歴を下記のようにいい感じに入力履歴を表示してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/4cd705ba-834f-e5d1-4193-88314f2cef53.png)

いい感じに表示してくれますが、コマンドをタイポした場合だったり、削除したい入力履歴がでてくることもあります。

その場合は、下記コマンドで入力履歴の保存場所を取得できるので、こちらに表示されたファイルから該当コマンドを削除します。

```PowerShell
Get-PSReadLineOption | Select-Object -ExpandProperty historysavepath
```

上記ファイルを変更後、PowerShellのセッションを起動すると削除した内容が入力履歴に表示されたない事を確認できます。

## PowerShellのコンソールからShift+Deleteで削除できるようカスタムキーハンドラに登録する

PSReadLineで表示される入力履歴について、何らかのキー操作で現在選択している入力履歴をキー操作で削除できれば便利そう。

例えばコンソール上で選択している入力履歴候補を取得して、一致する文字列を履歴ファイルから削除するような方法とか。

とちょっと探してみた所、下記のissueがありました。

[Question/Request: Is it possible to remove an item from the history?
](https://github.com/PowerShell/PSReadLine/issues/1778)

この中のコメントでPSReadLineのキーハンドラに`shift+delete`から現在している行の内容を入力履歴から削除する実装が紹介されていました。

[https://github.com/PowerShell/PSReadLine/issues/1778#issuecomment-1111383429](https://github.com/PowerShell/PSReadLine/issues/1778#issuecomment-1111383429)

自分はこちらの内容を起動プロファイルに入れてしばらく使ってみましたが。

たまに入力履歴を調整する際に、PowerShellコンソールから直接調整できるのは便利です。
（調整後に新しいセッションを開く必要はありますが）

## 総評

PSReadLineの入力履歴をコンソール上から削除できれば便利なのにと探したら、そのものズバリをPSReadLineのキーハンドラで設定している人がいました。　やっぱみんなこれやりたいよなという感じ。

そのまま使ってみていますが便利です。
Phoenix.HTML.Form、Phoenix.LiveView.Helpersにclassを指定する

Phoenix.HTML.Form、Phoenix.LiveView.Helpersにclassを任意の引数として指定する例をいくつか。

tailwind css、daisyUIをPhoenixアプリに追加したとき、classの指定のやり方が分からなかったので備忘録:hatched_chick:

## 結論：optsにclassを指定するとよい

Phoenix.HTML.Form.htmlやPhoenix.LiveView.Helpers.htmlで各フォームヘルパーの関数が紹介されています。

https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html

https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Helpers.html

> text_input(form, field, opts \\ [])

であれば、optにあたる引数にclassを渡してあげればよいです。

以下、いくつか例を紹介していきます。

## Phoenix.HTML.Form

### text_input(form, field, opts \\ [])

classを１つ指定する場合。

```elixir
<%= text_input f, :display_name, class: "input") %>
```

classを複数渡す場合は文字列のリストで渡します。
他のフォームヘルパーも同様です。

```elixir
<%= text_input f, :display_name, class: ~w(input input-bordered input-accent) %>
```

### textarea(form, field, opts \\ [])

```elixir
<%= textarea f, :message, class: ~w(textarea textarea-accent w-10/12) %>
```

### submit(value, opts \\ [])

```elixir
<%= submit "感想を投稿", class: ~w(btn btn-success) %>
```

## Phoenix.LiveView.Helpers

### live_patch(text, opts)

```elixir
<%= live_patch "感想を投稿する", to: Routes.message_index_path(@socket, :new), class: ~w(btn btn-success) %>
```
Github PagesでMathJaxを使おうとして失敗したときのメモ

DjangoとかJekyllとかHTMLの仕様とかよくわかってない初心者です。

# 成功した時のメモ

素直に[この記事](https://qiita.com/memakura/items/e4d2de379f98ad7be498)に従った。

1. Github PagesのSourceディレクトリに`_config.yml`を作成して`theme`を設定（リポジトリの設定からPagesを有効化してテーマを選ぶと自動で作成・設定される）。
1. Github PagesのSourceディレクトリに`_includes/mathjax-v3.html`を作成（中身は上記記事をコピペ）。
1. Github PagesのSourceディレクトリに`_layouts/default.html`を作成（1.で選んだ[テーマのリポジトリ](https://github.com/pages-themes)の`_layouts/default.html`をコピペしてくる）。
1. `_layouts/default.html`内の`</head>`の手前で`mathjax-v3.html`をインクルード。
``` html:_layouts/default.html
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
  <head>
    <meta charset="UTF-8">
    ~ 省略 ~
  {% seo %}
    {% include head-custom.html %}
    {% include mathjax-v3.html %} <!-- これを追加 -->
  </head>
  <body>
    <a id= ~
```
Githubのリポジトリにpushして「pages build and deployment」が完了したら反映される。（1～2分）

# 失敗した時のメモ

## MathJaxの有効化に失敗した

[テーマのリポジトリ](https://github.com/pages-themes)の中を見ていたら、
`_includes/`下に`head-custom.html`があり、それを`_layouts/default.html`でインクルードしているようだった。
`_includes/head-custom.html`は同じ`_includes/`下のhtmlファイルをインクルードしていた。

「じゃあ、`_includes/head-custom.html`と`_includes/mathjax-v3.html`を作って、
　`_includes/head-custom.html`の中で`mathjax-v3.html`をインクルードすればいいのでは？」
と考えたが、やってみたらダメでした。

インクルードされるタイミングの問題なのか、スコープ的な問題なのかよくわかってません。
詳しい人コメントください。

***

## 数式がテーブルになってしまった

Markdown内の数式で`|`（絶対値のカッコ）を使ったらテーブルとして認識されてしまった。（テーマによるかも）
`\vert`を使えば問題ない。

$ a | b | c $ `$ a | b | c $` 
$ d \vert e \vert f $ `$ d \vert e \vert f $`

***

## 数式内の`_`が強調表示扱いになる

Github PagesではなくGithub側に原因がある(?)
`$a^{b}_{c}$`のような表現が1行中に複数あると、`_`の後ろが斜体となり数式にならない場合がある。
[参考リンク](https://github.com/psymonmarkrine/test_mathjax_githubpages/blob/main/docs/test2.md)

次のいずれかの条件を満たすと回避できる。

* `$a_{c}^{b}$`のように下付き文字を先に書くとこの問題は発生しない。（これが一番確実）
* 必要がなければ下付き文字を`{}`で囲わない`$a^{b}_c$`
* `_`と`{}`の間にスペースを入れる`$a^{b}_ {c}$`
【Android】Robolectric 4.8でshadowOfメソッドを使用した際に出るエラーの解決法

# はじめに

皆さん、ごきげんよう！れぶです！

今回の記事では、`Robolectric 4.8`で`shadowOf`メソッドを使用した際に出るコンパイルエラーの解決法を書いていきます。同じエラーでハマってる方に特に参考になれば光栄です。

それでは、参りましょう！！

# 開発環境

* MacBook Air
* Android Studio Bumblebee | 2021.1.1 Patch 1
* Java 8
* compileSdkVersion 32
* minSdkVersion 21
* Robolectric 4.8

# エラー内容

`Robolectric 4.8`で、`Shadows.shadowOf`メソッドを使って`Shadow`インスタンスを生成する際に、以下のコンパイルエラーが発生します。

* `cannot access BackdropFrameRenderer`

* `class file for com.android.internal.policy.BackdropFrameRenderer not found`

つまり、**「com.android.internal.policy.BackdropFrameRenderer」クラスがないため、アクセスできない**よと言われています。見覚えのないクラスで最初戸惑うと思います。

# 解決方法

結論、**Robolectricのバージョンを4.8▶︎4.8.1にアップグレードする**ことでエラーが解消されます。

https://github.com/robolectric/robolectric/pull/7284

上記のページを参照すると、`Robolectric 4.8.1`では`Robolectric 4.8`で起こったバグ（`shadowOf`メソッドのコンパイルエラー）をしっかり修正してくれていることが分かりますね。

具体的には、問題となっていた「com.android.internal.policy.BackdropFrameRenderer」クラスに対して、「isInAndroidSdk」パラメーターを「false」に設定することで修正されています。この辺の内部構造に関しては、「そうなんだ」ぐらいで受け止めるのがまずは良いかと思います。

おそらく次回リリース(予定)の安定バージョン4.9でも、4.8で起こったエラーにしっかり対応してくれると思うので、期待したいですね！

# サンプルコード

とここで、自分自身がRobolectricを使ってサンプルのテストコードを書いたので、もし良かったら参考にしてみてください。

https://github.com/seiyaleb/RobolectricTrialApp

# おわりに

今回は、`Robolectric 4.8`で起こった`shadowOf`メソッドのエラーに対する対応を記述しました。

`Robolectric`でも、前のバージョンのバク修正や機能の拡張などによってバージョンが日々更新されます。**以下のリリースノートからバージョンの進捗を確認できますので、エラーが出てハマってしまった際にはご覧ください**。自分も今回のエラーに対する対応方法は、ここから発見しました。

https://github.com/robolectric/robolectric/releases

また、`Robolectric`でも`SDK`や`Java`のバージョンによってはうまく動作しないこともあるため、今一度バージョンを確かめてみてください。

以上です。この記事が少しでも役立つと嬉しいです。ありがとうございました！

# 参考サイト
* [Skip to generate shadowOf for ShadowBackdropFrameRenderer #7284](https://github.com/robolectric/robolectric/pull/7284)
* [Annotate ShadowBackdropFrameRenderer with isInAndroidSdk = false #7287](https://github.com/robolectric/robolectric/pull/7287)
* [Robolectric 4.8.1](https://github.com/robolectric/robolectric/releases/tag/robolectric-4.8.1)
* [targetSdkVersion を 29 に上げても Robolectric のテストを動くようにする](https://qiita.com/toastkidjp/items/8a301728221d88706ae1)