OmniAICreator/Qiita-1.07M huggingface dataset:
【Vue.js】トランジションについて

#はじめに
こんにちは。
今回はVue.jsのトランジションについてアウトプットしていきます！

##Vue.jsのトランジションとは
>Vue.js は自動的に、適切な時に、あなたのために CSS トランジションまたはアニメーションをトリガするため、CSS クラスを追加または削除し、そしてトランジションの間は、カスタム DOM の操作をするために、JavaScript フック関数を提供することができます。

> 参照：https://v1-jp.vuejs.org/guide/transitions.html


```html:HTML
<div id="app">
  <button v-on:click="show=!show">
    Change
  </button>
  <transition>
    <p v-show="show">
      Hello!
    </p>
  </transition>
</div>
```

```css:CSS
.v-enter-active,
.v-leave-active{
  transition: opacity 5s;
}

.v-enter,
.v-leave-to{
  opacity: 0;
}
```

```javascript:Vue.js
var app = new Vue({
  el: '#app',
  data: {
    show: false
  }
})
```
`transition`タグを用いてクラスの追加・削除の動作を確認する。
![vue210.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/3177bae7-73e2-638d-32f1-ff6a495d09cd.gif)

始めは`show`の初期設定をfalseにしているのでボタン以外何も表示されない。
クリックイベント発生で`show`がturuになることで`Hello!`が表示される際、`transition`タグで囲った`p`タグにクラス（.v-enter-active）が追加されて、CSSが適用されてアニメーションが発火。

表示しきったタイミングでクラスが外れ、もう一度クリックイベントが発生する際に別のクラス（.v-leave-active）が追加される。


<br>


#最後に
ここまでVue.jsのトランジションについてまとめました。
今後もアウトプットしながら学習を進めていきます！
【Laravel8】JetStream 認証のリダイレクト先

jetStreamを使ってみて、認証関連のリダイレクト先で戸惑ったのでメモします。

##新規登録、ログイン
「RouteServiceProvider」の定数「HOME」を参照しているようです。
また、初期値には'/dashboard' が指定されていました。

```php:app/Providers/RouteServiceProvider.php
/* 略 */
class RouteServiceProvider extends ServiceProvider
{
    /* 略 */
    public const HOME = '/dashboard';
    /* 略 */
}
```
##ログアウト
ログアウト処理のリダイレクト処理は、デフォルトでは以下クラスのメソッドを使用しているようです。

```php:vendor/laravel/fortify/src/Http/Responses/LogoutResponse.php
/* 略 */
class LogoutResponse implements LogoutResponseContract
{
    /* 略 */
    public function toResponse($request)
    {
        return $request->wantsJson()
                    ? new JsonResponse('', 204)
                    : redirect(Fortify::redirects('logout', '/'));
    }
}
```
これをオーバーライドすれば、リダイレクト先を変更可能とのこと。

今回は、参考にさせていただいたサイトのとおり、「app\Http\Responses\LogoutResponse.php」ファイルを作成します。
※Responsesディレクトリも、デフォルトでは無かったので作成します。

```php:app\Http\Responses\LogoutResponse.php
<?php

namespace App\Http\Responses;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Laravel\Fortify\Contracts\LogoutResponse as LogoutResponseContract;
use Laravel\Fortify\Fortify;

class LogoutResponse implements LogoutResponseContract
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        return $request->wantsJson()
                    ? new JsonResponse('', 204)
                    : redirect('/');
    }
}
```
また、作成したクラスを「app\Providers\FortifyServiceProvider.php」の「boot」メソッドに記述することで、デフォルトの処理をオーバーライドできるようです。

```php:app\Providers\FortifyServiceProvider.php
public function boot()
{
    /* 略 */
    $this->app->singleton(
        \Laravel\Fortify\Contracts\LogoutResponse::class,
        \App\Http\Responses\LogoutResponse::class
    );
}
```

・参考にさせていただいたサイト
https://stackoverflow.com/questions/65822861/laravel-fortify-logout-redirect
【新人SE】サーブレットの基本

#サーブレットの基本

##サーブレットクラスのルール
+ doGet()メソッドをオーバーライドする
    + doGetメソッドは、サーブレットクラスがリクエストされると実行されるメソッドです。
    + オーバーライドとは、メソッドの上書き。
+ サーブレット関係のクラスをインポート
    + javax.servletと javax.servlet.html
    
##HttpServletRequestとHttpServletResponse
ブラウザからのリクエストが来ると、APサーバはdoGet（）を呼び出す。
このとき引数として渡されるHttpServletRequestはブラウザからの「リクエスト」、HttpServletResponseは送り出す「レスポンス」に関する情報を持つインスタンス。

##HTMLの出力
doGet()メソッドには、リクエストで実行する処理を記述するが、常に必要なのが**HTMLを出力する処理**

##サーブレットクラスのコンパイルトインスタンス化
サーブレットクラスを実行する際は、通常のクラスと同様に子パイルとインスタンスが必要だが、eclipseを使えば自動的に行われる。

#サーブレットの実行方法
##サーブレットクラスのURL
HTMLの時は以下のように「ファイル名」が必要だった。

```http
http://<サーバ名>/<アプリケーション名（プロジェクト名）>/<ルートからのパス>
```

サーブレットの場合は、最後が**URLパターン**というサーブレットクラスのあだ名をつける。

```http
http://<サーバ名>/<アプリケーション名（プロジェクト名）>/<URLパターン>
```

##URLパターンの設定
URLパターンは**@WebServlet("/URLパターン")**で設定する。
Eclpseでサーブレットクラスを作った場合、URLパターンは自動的にクラス名と同じものが設定される。

また、アノテーションではなく、web.xmlという設定ファイルを使用することもある。

##リクエストメソッドと実行メソッド
サーブレットクラスが実行するメソッドは、次の通りで決定される
+ GETリクエスト→doGet()メソッド
+ POSTリクエスト→doPost()メソッド


#サーブレットの注意事項
ソースコードを変更しても実行結果に反映されない場合は以下の対処法を実行する。

1. サーバを再起動する
2. しばらく待つ
→コンソールに「コンテキストの再ロードが完了しました」と表示されればＯＫ
ChromeBookから外付けSSDでフロント系の開発を行う方法（暫定案）

# はじめに
* この方法は正直嬉しくない方法なので別途解決策を検討中。（理由は後述）

# やりたいこと
* ChromeBookの容量が少ないので外付けSSDを購入して来たのでそちらに資材を移して開発がしたい。

# 当初の問題点
* 外付けフォルダ内でnpm installをするとsymlink系のエラーが多発する。
* npm install --no-bin-linksを試してみたがエラーとなる。(Nuxt.jsの環境作成で失敗する。）


# 解決方法

## mountコマンドを使用する
* 調べた限りでは、「Virtualboxの共有フォルダではシンボリックリンクが作成できない」事象が当てはまる様子。
* node_modulesの内部で容量節約のためにシンボリックリンクを使っているらしい。
* mountコマンドを使えばシンボリックリンクを作成できるフォルダに差し替えることができる。
* よってnode_modulesフォルダだけどうにかすれば解消する可能性がある。

## 手順
1 . ChromeBook側のディスクにnode_modulesを作成する。
（例：/home/user1/project-name/node_modules)
2 . 外付けSSDに資材を格納する※package.jsonが用意できれば良いのでgithubなどからcloneでも可。 
(例：/mnt/chromeos/removable/SSD-XXXX/projects/node/project-name)
3 . 外付けSSD側のnode_modulesを作成する
(例：/mnt/chromeos/removable/SSD-XXXX/projects/node/project-name/node_modules)
4 . mountコマンドを実行※--bindオプションがrootユーザ必須らしいのでsudoで実行。

```bash
sudo mount --bind [Chromebook側のフォルダ] [SSD側のフォルダ]
```

5 . npm installを行いエラーにならなければOK。
試しにNuxt.jsをnpm run devを実行したら起動できた。
(yarnでもやってみたが最終的にはうまくいく。）

# 現在の問題点
* これで一応動かせるようにはなったが、容量を減らしたい目的なのに中途半端な結果になってしまっている。
* 特にnode_modulesが一番重いのでそちらをどうにかしたかった。
* もう少し良い案がないかは検討だが、手間をそこまでかけたくないので一旦これで様子を見る。
* ChromeBookのデベロッパーモードを使ってどうにかできるのか不明だがSSDにシンボリックリンクの作成権限が付与できれば行けそう。
herokuのclearDBのグレードアップで死んだ話

## first trouble
Herokuのcleardbをpunch（月9$)のプランを使用していたのですが、
もう少し大きい容量のものを使用しないといけないなと思い、Standard 25($54のプラン)に変更しようとしてました。

`you have not establish payment history `だからStandard 25プランには変更できませんよ、
と怒られてしまいました。


### 解決方法
![スクリーンショット 2021-09-27 17.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/f1742d20-460e-61bf-e2ba-3507336f334c.png)

hobbyのプランから, Standard 1Xのプランに変更し、引き落としが2ヶ月経ってからDBのプランを変更することができました！！

## second trouble
Heroku cleardbを変更したことにより Mysqlのhostnameが変更され、デプロイしていたアプリが`Mysql connection error` を起こして使えなくなったこと。

### 解決方法
hostnameが変わったことを知らなかったので、Herokuに登録しているメールアドレス宛に

```
新しいhostnameは hogehoge_new.cleardb.com
だよ、
userとpasswordは今までと同じものだよ
```

とメールが来るので、
herokuのconfigの設定をし直してデプロイし、解決
直さないといけないconfigは、新しいHOST_NAMEの部分です。

```
heroku config set CLEARDB_DATABASE_URL="mysql://今までのusername:今までのpassword@新しいHOST_NAME/今までのDB_NAME?reconnect=true"
heroku config set DATABASE_URL="mysql://今までのusername:今までのpassword@新しいHOST_NAME/今までのDB_NAME?reconnect=true"
heroku config set DB_HOSTNAME=新しいHOST_NAME
```
`DB_HOSTNAME`とかは各自のdatabase.ymlで指定している環境変数に沿ってやってください
DockerとRails環境でのGemの永続化

#環境
Docker version 20.10.8
Rails 5.2.6

#事象
ログイン機能を実装するためにbcryptをGemfileに追加し、その後`bundle install`して`docker-comose up`すると、「そんなgemはないよ！」というエラーが出ました。

```ruby:
web_1  | Bundler::GemNotFound: Could not find bcrypt-3.1.16 in any of the sources
・・・（略）
web_1 exited with code 1
```
あれ？bundle installしたのになんで。。

#解決策
先に解決策からです。
gemの永続化を行いました。

```Docker:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/book_app
      - gem-data:/usr/local/bundle　#ここを追加
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  gem-data: #ここを追加
```
上記を追加した後、bundle installを行いコンテナを再起動すると解決しました！！

```docker:
$ docker-compose run web bundle install
$ docker-compose down
$ docker-compose up
```

#原因
原因はgemの永続化ができていなかったからです。
gemの永続化を行わないとコンテナ上でbundle installを実行してもDockerイメージにはgemの保存がされないので、今回のエラーが発生したみたいです。
こちらの[サイト](https://nishinatoshiharu.com/datavolume-for-gem/#Docker")が分かりやすく、助かりました！


#参考
https://nishinatoshiharu.com/datavolume-for-gem/#Docker
起動しないPCの初期化方法について 

##前置き

起動しなくなったPCを業者に引き取ってもらう場合や買い取ってもらう場合に
自分で初期化してから引き取ってもらわないとPCから個人情報が漏れてしまったりする可能性があります。

もちろん、業者側で初期化し、データ削除証明書などを発行してくださる業者さんもいらっしゃいますが、
個人的には不安なのでご自身で初期化してから業者に依頼することをお勧めします。
ましてや個人ではなく、会社で使用しているPCでしたら尚更です。

手順としては初期化したいPCのHDDをSATAからUSBの変換ケーブルで別のPCに接続し、diskpartコマンドで初期化します。


##準備するもの

・ドライバー(PCを解体しHDDを取り出すため)
・初期化するPC
・コマンドを打つためのPC
・SATAからUSBの変換ケーブル

SATAからUSBの変換ケーブルは今回は下記のものを使用しました。
![編集済みPXL_20210903_013914732.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/48e6bc88-19b9-ef4f-1ea5-e801c77535f1.jpeg)


他にもたくさん種類があるので、自分のPCに合うものをご用意ください。


##手順

今回はDELLのデスクトップパソコン Vostroシリーズを初期化します。
早速ドライバーを使ってカバーを開けて、中を確認します。
HDDは丸印のものになります。
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/94063c0b-ed05-e46c-e3ee-e6615611195d.jpeg)
HDDをPCから取り外し、SATAケーブルとPCを接続します。

HDDを取り外すとこんな感じです。
![編集済みPXL_20210903_012621031.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/a5e58694-7b0b-45c0-7d9b-09bf3211cd54.jpeg)


丸印で囲った部分がSATAの端子になります。
![編集済みPXL_20210903_012720023.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/48dcfc2a-a96e-1380-f1c0-2e15b78349ec.jpeg)

そこにSATAケーブルを差します。
![編集済みPXL_20210903_012912831.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/618ffd91-cc8d-14fe-bb8f-88ad673e34b7.jpeg)

こんな感じで接続します。
![編集済みPXL_20210903_012803155.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/6bfca922-8da4-29ee-40ba-01b3115682a9.jpeg)


USB側をPCに接続し、HDDを認識したらコマンドプロンプトを管理者として実行します。
下記のコマンドを入力し、初期化を行います。

```
C:\WINDOWS\system32>diskpart

DISKPART> list disk
-- 接続されているディスクがすべて表示されるので、初期化したいディスクを確認します

DISKPART> select disk1
-- disk1を初期化する場合は上記のように入力します

DISKPART> clean all
-- 初期化を行います
```

容量にもよりますが、clean all が完了するまでに平均3～4時間程度かかります。
『Disk Port はディスクを正常にクリーンな状態にしました。』と表示されたら初期化完了です。

これで起動しなくなったPCでもHDDを外すことが出来れば初期化することが出来ます。
【3Dプリンタ】データを作成してPRUSA i3 MK3Sで印刷するまで

#はじめに
　先週初めて3Dプリンタに触れ，データの作成からプリントまで備忘録として残す．

　使用したプリンタ：ORIGINAL PRUSA i3 MK3S (KIT)↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/75819b76-d047-b1ab-031f-2e1ebad9eed3.png)
　間違え等ございましたら，お手数ですがコメントいただけると幸いです．


#1. 3Dモデルの作成
　3Dモデルを作成する方法は主に3種類ある．基本的にはSTLやOBJファイルで保存する．STLファイルは，3D CADソフト用のファイルフォーマットの1つで，3Dプリンタを使用するときによく使われるファイルの形．OBJファイルも3Dモデルデータフォーマットの1つ．


##既存のモデルを使用
　ネット等の既存のモデルを使用する場合は2番のG-codeを作成手順は省く．

##3Dスキャナからデータを作成
　3Dスキャナにも様々な種類があるが，3Dスキャナは立体のものを様々な方法でスキャンして，3Dデータとして取り込む機械．

##自分で3Dモデルを作成
　BlenderやFusion360,SketchUPなど様々なソフトが存在するが，私はBlenderとFusion360を使用した．それぞれのソフトの使い方は省く．（いつか記事にしたいと思う）


#2.STLファイルからG-codeの生成
　STLファイルやOBJファイルから直接3Dプリンタにデータを送ることができないので，3Dプリンタで使えるG-codeファイルに変換する必要がある．そのために，<b>スライサー</b>を使う．スライサーにも種類があり，Slic3r，Kisslicer，Curaなどある．

　PRUSAの3Dプリンタでは，Slic3r Prusa Editionを使うのがいいみたいなので，私はPrusaSlicerを使用した．[公式サイト](https://www.prusa3d.com/prusaslicer/)からインストールする．インストール後に使用する3Dプリンタの基本情報を設定する．

 G-codeを生成したら，SDカードに保存する．

#3. 3Dプリンタのキャリブレーション
　プリント前に毎回行う必要はないが，綺麗にプリントできないときはキャリブレーションを行う．

　ヒートベッドは平らに見えていても，実際は少し歪んでいる．`LED Menu → Calibration → First Layer Calibration`でキャリブレーションを行う．この際，ヒートベッドが汚れている場合は綺麗にしてからキャリブレーションを行う．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/b06c89f3-d602-ffac-98be-1865673ad78c.png)


　ノズルの高さを手動で調整する．写真のように溶けたフィラメントが押しつぶされて，ヒートベッドにくっついている状態にする．コントロールノブを反時計回りに回すとノズルがヒートベッドに近づく．このとき，設定値は表示されるが設定値ではなく目視で毎回確認する．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/da4fa184-dc2f-7544-d188-4ca3725b9cab.png)

#4. SDカードから印刷する
　フィラメントの先端をとがらせて，挿入する．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/7a25d4a8-8584-05df-fa33-3ee1572a4b9b.png)

　`Print from SD`からプリントしたいファイルを選択するとプリントが開始される．


#参考文献
[STLデータとは](https://www.keyence.co.jp/ss/products/3d-printers/agilista/knowledge/stl_about.jsp)
[PRUSA公式サイト](https://www.prusa3d.jp/)
[備忘録]v-modelに配列要素を指定すると画面更新されない件

v-modelに配列要素を指定した場合、JS側で対象の要素を変更してもDOMに反映されないという現象がありました。

↓イメージ

```test.vue
<template>
  ・・・
  <div v-for="(value, index) of arry" :key="index">
    <input v-model="arry[index]" @change="changevalue($event, index)"/>
  </div>
  ・・・
</template>
<style lang="ts">
  ・・・
  arry: number[] = [1,2,3];
  ・・・
  /** 入力値の制御 */
  changeValue(value: number, index) {
    // ここで設定した値が画面に反映されない！
    if (value < 0) {
      arry[index] = 0;
    } else if (value > 99) {
      arry[index] = 99;
    } else {
      arry[index] = value;
    }
  }
</style>
```

# `$set`を使う

`this.$set()`で対象要素を更新してやる

```test.vue
<template>
  ・・・
  <div v-for="(value, index) of arry" :key="index">
    <input v-model="arry[index]" @change="changevalue($event, index)"/>
  </div>
</template>
<style lang="ts">
  ・・・
  arry: number[] = [1,2,3];
  ・・・
  /** 入力値の制御 */
  changeValue(value: number, index) {
    let v = value;
  
    if (value < 0) v = 0;
    if (value > 99) v = 99;

    this.$set(this.arry, index, v);
  }
```

※Nuxtでなく、プレーンなVue.jsを使っている場合はVue.setを使用します


# 参考

https://cloudpack.media/41984
https://jp.vuejs.org/v2/guide/reactivity.html#%E9%85%8D%E5%88%97%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6
ABC201 C - Secret Number から学んだ

https://atcoder.jp/contests/abc201/tasks/abc201_c

![abc201_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/91815453-3d2c-b134-40d8-98013ddc0c67.png)
![abc201_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/8d12e357-5c3d-4229-0d7f-55f1cff493f4.png)
![abc201_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/af65c8cb-b573-e1b6-831c-5a2b12005073.png)

うーん、if 文で条件を分けようとしたが、
途中でとん挫。。!? production で行けるかも。

うん、行けた。

```SecretNumber.py
from itertools import product
S = input()
cnt = 0
Ccnt = S.count("o")
for i0,i1,i2,i3 in product(range(10),repeat=4):
    #print(i0,i1,i2,i3)
    key = [S[i0],S[i1],S[i2],S[i3]]
    if "x" in key:
        continue
    #print(i0,i1,i2,i3,key)
    nums = []
    if S[i0] == "o":
        nums.append(i0)
    if S[i1] == "o":
        nums.append(i1)
    if S[i2] == "o":
        nums.append(i2)
    if S[i3] == "o":
        nums.append(i3)

    if len(set(nums)) != Ccnt:
        continue
    #print(len(nums), Ccnt)
    #print(i0,i1,i2,i3,key)
    cnt += 1

print(cnt)
```

C 問題、diff 茶色最弱問題に四苦八苦したが
自力で解けた。うれし---!!

***

サッパリ忘れて解き直し。

```abc201c.py
S = list(input())
ans = 0
cntC = S.count("o")
from itertools import product
for nums in product(range(10),repeat=4):
    nums_ = list(set(list(nums)))
    check = ""
    for i in range(len(nums_)):
        check += S[nums_[i]]
    if check.count("o") == cntC and check.count("x") == 0:
        ans += 1
print(ans)
```
Vue.jsの設計方針

# 概要
自分自身のナレッジのため、Vue.jsの設計方針をまとめました。

# 環境
```
Vue.js 2系
TypeScript
Vuex
Vue Router
```

# ディレクトリ構成
Atomic Designからtemplateを省いて、崩しています。
他ディレクトリもできるだけシンプルな責任分担にしています。

いろいろな用途に汎用性を持たせるのと、
コーディングのルール付けくらいになるレベルまでの定義を意識しました。
（ガチガチに固めるとそれはそれで実装効率を下げると考えました）

```
src
|--assets
|--components
|  |--atoms
|  |--molecules
|  |--organisms
|  |--pages
|--constants
|--models
|--router
|--service
|--store
|  |--modules
|--utils
|--views
```

# 各ディレクトリの役割

ディレクトリごとに責務を分離し、

- 何がどこにあるか
- 改修時どこを編集すればいいのか
- 機能追加時どこに何を追加すればいいのか

が分かりやすいよう定義することを意識しました。

| ディレクトリ名 | 役割 |
| -- | -- |
| assets | 静的ファイル・汎用CSS |
| components/atoms | これ以上分解できない最小単位の汎用コンポーネント |
| components/molecules | 一つの汎用的な部品を構成するコンポーネント |
| components/organisms | 一つの機能を構成するコンポーネント |
| components/pages | viewsから呼び出され、organismsを用いてページを構成するコンポーネント |
| constants | 定数定義 |
| models | データの型定義 |
| router | Vue Routerの定義 |
| service | APIの呼び出しやLocalStorageの使用 |
| store/modules | Vuexストアの定義 |
| utils | 汎用的なメソッド |
| views | ページ遷移のために使用する、ページ単位のコンポーネント |

# リポジトリ
上記を定義した個人学習用リポジトリです。
改修の余地はissueに纏めています。
https://github.com/RinyuDrvo/language_app
FlutterアプリとFirebaseを連携させるときに困ったあれこれ

FlutterをFirebaseと連携させようと色々弄ってたらこんなエラーに遭遇したのでメモ

```
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':firebase_core:compileDebugJavaWithJavac'.
> Could not find tools.jar. Please check that /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home contains a valid JDK installation.
```
<h1>筆者の環境</h1>
MacBook Air (M1, 2020)　zsh

Flutter doctorの結果

```
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.3.1 20E241 darwin-arm, locale
    ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] Connected device (2 available)

! Doctor found issues in 1 category.
```

pubspec.yamlはこちら

```dart:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  provider: ^5.0.0
  transparent_image: ^2.0.0
  firebase_core: ^1.5.0
  cloud_firestore: ^2.5.0
  flutter_slidable: ^0.6.0
  firebase_auth: ^3.1.0
  firebase_storage: ^10.0.3
  image_picker: ^0.8.4
  direct_select: ^2.0.0
```

<h1>実装の手順</h1>
1.https://www.oracle.com/java/technologies/downloads/#jdk17-mac
からjavaのjdkをインストール（この過程でOracleアカウントを作成する必要あり）

2./usr/libexec/java_home -V | grep jdk コマンドでjdkがインストールされているか確認

3.android ディレクトリ内のgradle.propertiesファイルにorg.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Homeを追加

```dart:gradle.properties
org.gradle.jvmargs=-Xmx1536M
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Home //これを追加する
android.useAndroidX=true
android.enableJetifier=true
```

4.appディレクトリ内のbuild.gradleファイルにあるdefaultConfigの中のminSdkVersionを16から21に書き換える

```dart:build.gradle
 defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.testapp"
        minSdkVersion 21 //ここがデフォルトでは16になってるからこれを21に変更する
        targetSdkVersion 30
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
```

5.アプリをリビルドする

以上の手順で自分の場合はエラーは解消されました。
それでは良いFlutterライフを！
OpenapiのYamlをCodeCommitにPushしたら自動的にHTMLに変換してS3にホストして公開する

## 要約
Openapi仕様で書かれたYamlファイルは、ツールを使って静的なHTMLに変換することができる。ここでは、それらのツールのひとつである[redoc](https://github.com/Redocly/redoc)で、YamlをHTMLに変換する。通常は、手元でredocを使い、HTMLに変換したのち、関係者に共有したり、[S3の静的ホスティング機能](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html)を使って共有したりする。本稿では、手元で変換する手間を惜しむため、CodeCommitにコミットしたら、自動的にHTMLに変換し、S3にホストする仕組みを紹介する。

## 構成
![arch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/0a93793d-73e1-13bf-a0a4-1a0d2b74f435.jpeg)

## 手順
１． CodeCommitのリポジトリを準備する 

下記のように、buildspec.ymlとopenapi.yamlを用意する。buildspecには、codebuildで実行する処理を記述する。
openapiはAPI仕様である。
![codecommit.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/b14916d4-045a-998c-6774-29b50840e82c.jpeg)


２．buildspec.ymlを用意する 

以下のようなbuildspec.ymlを用意する。
nodejsのバージョン14のコンテナを使用している。まずredocツールを導入し、そのあと、openapi.yamlをHTMLに変換し、変換後のHTMLファイルをリネームしている。

```yaml
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 14
    commands:
      - npm install -g redoc-cli
  pre_build:
    commands:
      - echo Nothing to do in the pre_build phase...
  build:
    commands:
      - echo Build started on `date`
      - redoc-cli bundle openapi.yaml
      - mv redoc-static.html openapi.html
  post_build:
    commands:
      - echo Build completed on `date`
artifacts:
  files:
    - openapi.html
```

３． HTMLをホストするS3を用意する

静的ホスティングを有効にしたS3を用意する。

４．CodeBuildプロジェクトを作成する

ソースプロバイダにCodeCommitを指定、１で作成したリポジトリを指定。

![codebuild2m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/2a387882-ab68-0761-18a6-f648bd753095.jpeg)


環境はマネージドイメージを使用し、Buildspecは、buildspecファイルを使用するを選択（これにより、リポジトリのbuildspec.ymlが自動的に使用される）。
このとき、OSにAmazonLinuxを選択すると、SRC_DIRのダウンロードに失敗したというエラーが発生したため、それを回避すべく、Ubuntuを選択した（Ubuntuだとなぜうまくいくのかは不明・・・）。

![codebuild6m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/f3e18d0f-5ea5-9a37-5433-c546acdee345.jpeg)


アーティファクトをS3（３で作成したもの）に設定。アーティファクトの暗号化を削除を選択しておくこと（選択しない場合、ファイルを正常に閲覧できない）。

![codebuild5m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/01240867-61e6-8550-1c15-6455fad60d6a.jpeg)


５． CodePipelineを構築する

![codepipeline1m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/e72b7462-a291-c1dd-1d7d-30144090bdcf.jpeg)

sourceにCodeCommitの１で作ったリポジトリを指定する。
![codepipeline2m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/f5978322-37be-0a01-65bf-f7d4fd3dca04.jpeg)


ビルドステージを追加する、で４で作成したCodeBuildプロジェクトを指定する。

![codepipeline3m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/906910f8-c704-ddd7-f1f1-e9bcf82441cf.jpeg)


デプロイステージを追加する、で３で作成したS3バケットを指定する。デプロイする前にファイルを抽出するにチェックを入れる。
![codepipeline4m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/57852a80-5347-0cd0-269d-d8040673a628.jpeg)


## まとめ
本稿では、Codeシリーズを活用し、CodeCommitにファイルをコミットするだけでHTMLに変換、S3で公開するまでを自動化する方法を紹介した。S3のURLを共有しておくことで、開発者は常に最新のドキュメントを参照することができる。都度HTMLファイルを配布する必要がないため、開発にかかる負担を減らすことができる。
PCの画面をオフにするショートカットつくってみた

# はじめに

PCを**スリープにはせず**画面だけオフにするショートカットをつくりました。

これの何がうれしいかというと、モニタを電源を切らずに画面をオフにでき、マウスやキーボードの操作だけで復帰することできます。
（ちなみにノートPCであれば画面を閉じたときの動作で画面だけオフが選べるはずです）

用途としてはPCで動画を再生しながら寝たいときや、大きめのファイルのダウンロードやインストール作業を寝てる裏で実行するみたいな状況を想定しています。

# 注意事項

- Windows専用
  - Macの場合はホットコーナー機能に「ディスプレイをスリープさせる」を割り当てるのが一番簡単かなと思います（[参考](https://keikenchi.com/how-to-make-the-mac-display-sleep-only)）
- PowerShellスクリプトの実行ポリシーがRemoteSignedかこれよりも緩い設定になっていること
  - 実行ポリシーについては[こちらを参照](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.1)
- 企業や学校等の組織によってPCの状態を細かく監視されているとアラートが上がる可能性がある
  - コマンドラインからPowerShellを実行しているショートカットである点や、オブジェクトの参照値を渡しているところでメモリアクセスが発生している点などから、もしかするとPCのセキュリティチェックに引っかかるかもしれません（1敗）
  - 危険なコマンドではないので、もし引っかかった場合はきちんと説明して今後使用しないことを伝えれば問題ないと思います。

# 作り方

デスクトップやエクスプローラ上で右クリック > 新規作成 > ショートカットと進んで、項目の場所を入力するときに以下のコードを貼り付ければ完成です。

```powershell
powershell -Command &{sleep 2;sal o New-Object;$f='System.Windows.Forms';Add-Type -AssemblyName $f;$m=(o \"$f.Message\")::Create((o \"$f.Form\").Handle,274,61808,2);(o \"$f.NativeWindow\").DefWndProc([ref]$m);}
```

あとはこのショートカットを実行するだけで画面をOFFにできます。

# 解説

## 基本処理

処理内容は[この記事](http://scripting.cocolog-nifty.com/blog/2009/05/powershell-e690.html)などを参考にしています。ただ文字数削減のために`New-Object`コマンドに1文字エイリアスを設定したり、型名を変数にいれて使いまわしたりしています。

最初の`sleep 2`は画面をオフにするまでの猶予時間で、ショートカットをクリックした後のちょっとしたマウスの動きですぐに画面オフが解除されてしまうことへの対策として入れています。使い方によってはこの処理はなくても問題ないです。

## パス文字列の長さ制限

Windowsはデフォルトだとパス文字列の長さが260文字に制限されています。これはショートカットも同じで、ショートカットのリンク先パス文字列も260文字以内である必要があります。

上記のコードではPowerShellの呼び出しを省略形の`powershell`にしていますが、ショートカットとしての正式なパスは`C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`となります。（PowerShellのバージョンによってはパスが異なると思います）
なのでこのフルパスの分だけスクリプトに使える文字数が減るという制限があり、そのためにわかりにくい1文字エイリアスを設定しているという次第です。

ちなみにパス文字列の長さ制限はレジストリ値を変更することで解除することができます。（[参考](https://bizlog.tech/windows-maxpath-change/)）

## コマンド引数

powershell.exeは引数でコマンド文を直接渡すことができます。

```powershell
powershell.exe -Command "Write-Host 'Hello, World!'"
powershell.exe -Command &{Write-Host 'Hello, World!'}
```

コマンド文は文字列として渡すかスクリプトブロックとして渡すことができます。

ここで、勘のいい方は「ダブルクォートで変数展開したいときはエスケープが必要そうだな」などと思うでしょう。もちろん？自分もそう思ったのですがエスケープの方法が特殊で解決するのに時間がかかってしまいました。

結論から言うと以下のようにエスケープする必要がありました。

```powershell
powershell.exe -Command "$msg = 'Hello'; Write-Host `\"$msg`\""
powershell.exe -Command &{$msg = 'Hello'; Write-Host \"$msg\"}
```

詳しいことは[こちらの記事](https://blog.shibata.tech/entry/2016/03/30/195726)に書いてありますが、-Commandで渡された文字列はまずコマンドプロンプトの処理系を通ることになり、そこではバックスラッシュでのエスケープが必要になるそうです。
なのでコマンド引数でダブルクォートを含むコマンド文字列を渡す場合は、まずバックスラッシュでエスケープして、それに加えてバッククォートでエスケープする必要があるわけです。

# おわりに

モニターだけオフにするという処理にどれだけ需要があるのかわからないですが、たとえニッチな需要だとしても、この記事が何かの助けになるのであれば幸いです。
AtCoder ABC220にチャレンジしてみた

Qiitaに登録したものの何を投稿すればいいのやら...となっていたところ, AtCoderの解説記事を見かけた. 成長記録にもなるしこれだ！ということでAtCoder ABC220のできたところを垂れ流していく.
AtCoder三回目のコンテスト参加結果：ABC(1)

A : Find Multiple
![code0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773193/dbe85173-f1e5-b7a8-b118-5024c29438f9.png)

B : Base K
![code1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773193/a59efffd-7f98-ce39-9c8c-07ae3f875526.png)

C : Long Sequence
まずは愚直にそのまま計算するやり方. 案の定TLE(実行時間制限超過)を喰らった.
![code2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773193/10e20589-8c3c-f50b-362a-ebe4ab7c7ba9.png)
次に商を求めてXを超える所を項を求めるやり方. 最初からこれをやればよかったのだが, 上のでいけるかどうか試したくなったので欲求には抗えない.
![code3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773193/f8c3932a-5cbb-94c3-adf0-5fe7d4fd2b52.png)

D : FG operation
求めたい値を出せるようになってるはずだが, TLEを喰らう.
![code4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1773193/24e94fae-31ec-f111-0974-ddea8aded374.png)

パット見 $O(n^2)$ になってるからそりゃそうだよな.
毎回D問題で詰まる...そろそろ何かしらの書籍でアルゴリズムを学びたい.
英語で知ったIT用語

海外でITの仕事をしていると、当然英語ベースで仕事をすることが多くなると思います。仕事上必要な新しいITの専門用語も英語で知る必要があります。
それでも仕事で検索などをする場合に、Qiitaの記事など日本語で書かれている記事のほうが事細かに書かれていて参考になる場合が多く、英語の記事以外でも日本語の記事をよく参考にしています。その場合は日本のIT業界でその用語がどの様に表記されているか知る必要があります。また自分で記事を書く場合とかも、日本語訳を調べる必要があったものもあるので、それらをまとめてみました。

---
### Authentication, Authorization
Authentication　認証、Authorization　認可。英語も日本語も似たような言葉ですが、意味はかなり明確に違います。同僚同士でもよく説明で使う分は**You are authenticated but not authorized to use**　訳は**あなたが誰だか確認できましたが、使用の認可はできません** と言った感じです。

### MFA,TFA
多要素認証と二要素認証/二段階認証。Qiitaでは二段階認証と言っていますね。

### CDN
コンテンツデリバリネットワーク。CDNに関する記事を書くときに調べました。

https://qiita.com/dg4101/items/6a61a27616ede8ca4435#cdn

### DR
ディザスタリカバリ。クラウドにしても一つのリジョンだけで運用すると、災害の多い地域だったりするとDR対策をしっかりしていないと大変なことになりますね。

### Retention period
バックアップの保持期間。DR対策もありますが、何かあった時に訴訟とかで必要になったりもするのでRetention periodは担当者だけで決めれない場合もあります。

### HA (High Availability)
高可用性。こちらもシステム運用の記事を書く際に調べました。

https://qiita.com/dg4101/items/0aeae61a16b979f00f80

### Self-healing
自動復旧。先ほどの記事にも登場しています。

### GDPR (General Data Protection Regulation) 
EU一般データ保護規則。ヨーロッパでITの仕事をしていると避けては通れません。

### Daylight saving time
夏時間、サマータイム。日本語で夏時間と言われますが、英語ではDaylight saving time。ただSummer timeとも表記されるみたいです。ITと関係ないようですが、タイムゾーンが関係するようなシステムだとこれを考慮しないと1時間の時差が出てしまいます。

### Machine Learning
機械学習。AIは結構そのまま英語で使われているようですが、機械学習は日本語訳で使われていることのほうが多いようです。

### Certificate
証明書。SSL、TLSなどで使われるますが、単純にcertificateと言うと何を指しているのかわからないのでTLS certificateなどいう必要があります。

### Public key, Private key
公開鍵と秘密鍵。

### CA (Certificate Authority),Root certificate
認証局とルート証明書。CAだけだとRootかIntermediateかわからなのでRoot CAと言ったりします。

### Intermediate certificate
中間証明書。先ほどのRootに対してIntermediateは中間証明書で、たまにこれをちゃんと設定していないサイトとか見かけます。

### SSL/TLS termination
SSL/TLS 終端。暗号化された通信をどこで終わらせるか。

### SSL/TLS offloading, End to end encryption
SSLオフロードとエンドツーエンド暗号化。以前はロードバランサーで暗号化をオフロードしてと言うこともありましたが、最近はセキュリティーの観点からエンドツーエンド暗号化が主流なのか思っています。

### OTP
ワンタイムパスワード。One Time Passwordの略です。

### No-code
ノーコード。英語の場合はハイフンがついていることが多いみたいです。

---
今後も出てくると思うので随時追加していきたいと思います。
M5Stack Grayのアバターにおしゃべりさせてみた ～Arduino IDEでAquesTalk ESP32の利用～

#本記事の内容
- M5Stack Grayのアバターにおしゃべりさせてみました！しゃべるだけでかわいい～

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5Stackのアバターにおしゃべりさせてみた <a href="https://t.co/EFwjfI1ykT">pic.twitter.com/EFwjfI1ykT</a></p>&mdash; kaname kun (@kanamekunkun) <a href="https://twitter.com/kanamekunkun/status/1441368803569328135?ref_src=twsrc%5Etfw">September 24, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#実施環境
- Windows 10
- Arduino 1.8.16
- M5Stack Gray

#手順の流れ 
1. ESP32向けの音声合成ライブラリのダウンロード
2. Arudino IDEでのライブラリの取り込み
3. ライブラリーの初期設定
4. サンプルプログラム(hello_aquestalk)の実行

## 1. ESP32向けの音声合成ライブラリのダウンロード

評価版のライブラリーを公開してくださっている[こちらのページ](https://www.a-quest.com/download.html#a-etc)にアクセスし、
AquesTalk ESP32ライブラリーのzipファイルをダウンロードする。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/728a40e1-0e0b-40cf-73d3-901c62b7e67e.png)


## 2. Arudino IDEでのライブラリの取り込み

Arduinoツールを起動し、`スケッチ > ライブラリーをインクルード > .zip形式のライブラリーをインストール ...`のメニューを開く。

![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/e190048b-321f-2ba3-f06f-e2e3867d3b57.png)

ダウンロードしたAquesTalk ESP32のライブラリーのzipファイルを指定する。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/bdb51a49-d583-5a93-632b-e6f3c40d8dde.png)

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/bde8ab1f-5cb7-c07a-8414-5395e9495850.png)

ライブラリー追加完了のメッセージが画面の下部に表示された。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/70970297-5b6d-a8ab-e247-83bab936c14f.png)

## 3. ライブラリーの初期設定

ライブラリーをコンパイラーに認識させるために設定ファイルを作成します。
"Arduinoのホーム"\packages\esp32\hardware\esp32\1.0.6\に"platform.txt"が存在しています。
同じディレクトリに`platform.local.txt`を作成します。
ファイルの中身は以下です。

	compiler.libraries.ldflags=
	recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} {compiler.libraries.ldflags} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"

※"Arduinoのホーム"について
現在(2021/09/27)のArduino IDEをデフォルトインストールすると、C:\Users\{PCのユーザ}\AppData\Local\Arduino15が"Arduinoのホーム"になるようです。

## 4. サンプルプログラム(hello_aquestalk)の実行

メニューから`ファイル > スケッチ例 > カスタムライブラリーのスケッチ例 > AquesTalk ESP32 > hello_aquestalk`をクリック。

以下のアイコンをクリックし実行した。

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/2ed7998a-17a4-acfc-3aef-02f5966486b7.png)

エラーなく実行できボードへの書き込みが完了したメッセージが出力され、M5Stackが喋ることができた。
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/dfe77069-cd9f-2a23-880d-f1776379c050.png)

ここまでで、AquesTalk ESP32を利用する環境が整った。
最後にhello_aquestalk_m5stackのサンプルコードやM5Stack_Avatarのサンプルコードを参考にして、ページ先頭の動画のようにアバターをかわいく喋らせることができました。

手順は以上。

# 参考文献
本記事の作成に当たり、以下の情報を参考にさせて頂きました。
- [「AquesTalk-ESP32 Ver.2.0」を使う](http://blog-yama.a-quest.com/?eid=970195)
- [ESP32 for arduino のライブラリの更新と、AquesTalk-ESP、、、　[ESP32]](https://hamayan.blog.ss-blog.jp/2018-06-13-1)
TestFlightからdSYMファイルがダウンロードできない場合

## 困った経緯
[こちら](https://qiita.com/d2cdot-mmori/items/c700a44425b89ace2643)の記事で投稿した通り、TestFlightからdSYMファイルがダウンロードを実施しております。
[dSYMファイルアップロード方法](https://qiita.com/d2cdot-mmori/items/c700a44425b89ace2643)

そんな中、chromeで「dSYMをダウンロード」をタップしてもダウンロードが始まらない事象が発生しました。
![スクリーンショット 2021-09-27 15.53.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/38f00c8a-2b98-ef2b-7b1d-eb52a6ca4676.png)
押してもダウンロードできない・・・！

## 解決策
「dSYMをダウンロード」のリンク先をコピーして、アドレスバーで実行する！

こんな簡単な方法で解決できました。
【1分で】SplatnetをPCで見る方法

## tl;dr

iksm_sessionをオンライン上で取得できるWEBサービスをつくりました。
これを利用することで公式ではスマホアプリでのみ閲覧可能なSplatnet（イカリング2）にPCからアクセスできるなど、スプラトゥーンに関する様々なAPIを叩くことができるようになります。

https://iksm.vercel.app/

<div>

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/fe830c18-f940-946f-6676-6a0080b91a62.png" alt="iksm.vercel.app_(Pixel 2).png" />

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/10d54f2b-e467-318e-9c31-908aa70a157a.png" alt="app.splatoon2.nintendo.net_results(Pixel 2).png" />

</div>

## Splatnetとは

任天堂のSwitchOnlineから閲覧可能なスプラトゥーン２の公式のアプリです。
直近の戦績や、ステージ情報など多くの情報を確認することができます。

これは実際にはWEBページを表示するwebviewのスマホアプリなのですが、実際にアクセスすると、forbitten（閲覧禁止）になっています。

https://app.splatoon2.nintendo.net/

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/fc4d8552-ecdc-ffc7-398c-43f027d5202e.png" alt="app.splatoon2.nintendo.net_home(Pixel 2).png" />

これを許可させるために必要になるのが`iksm_session`です。

## iksm_sessionの取得方法

現在ネット上に出まわっている情報だと、取得するにはアプリの導入など複雑な手順が多いのでシンプルなアプリにしてみました。

「イカスミちゃん」↓

https://iksm.vercel.app/

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/fe830c18-f940-946f-6676-6a0080b91a62.png" alt="iksm.vercel.app_(Pixel 2).png" />

紫のボタンをクリックすると任天堂のサイトからログインが求められ、ログインしてみると
確認画面が出てきます。

![Screenshot from 2021-09-27 15-44-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/0ef7999a-46d1-e4ff-fc52-2589dbcc4345.png)

「この人にする」のボタンのリングをコピーして、「イカスミちゃん」上のフォームにはりつけると準備完了です。
ピンクのボタンをクリックして生成してみましょう！

![Screenshot from 2021-09-27 15-48-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/ed1cd2a2-a5a0-f47f-c77a-d58cf4f0c84b.png)

## Splatnet（イカリング２）にアクセス

無事`iksm_session`を取得できれば、今後しばらくは同じ端末ではすぐに`iksm_session`を取得することが可能です。
「イカスミちゃん」の`how to use`からSplatnetにアクセスしてみましょう。


<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/fc4d8552-ecdc-ffc7-398c-43f027d5202e.png" alt="app.splatoon2.nintendo.net_home(Pixel 2).png" />

ここで`F12(fn + F12)`などで`開発者ツール→Application→Storage→Cookies→iksm_session`の欄に移動して、
取得したiksm_sessionに上書きしましょう。

![Screenshot from 2021-09-27 15-52-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/e30d11cf-e48d-8862-8ac3-a59d2516184e.png)

リロードするとSplatnet（イカリング２）に入ることができます！

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273096/10d54f2b-e467-318e-9c31-908aa70a157a.png" alt="app.splatoon2.nintendo.net_results(Pixel 2).png" />

## 技術的なお話

今回の実装には以下のドキュメントを参考にして実装しました。
ツール等を作成した方々には頭が上がりません。

https://github.com/ZekeSnider/NintendoSwitchRESTAPI

https://github.com/frozenpandaman/splatnet2statink/wiki/api-docs

Next.jsをフレームワークとして開発しており、今回のコードは以下から見ることができます。
vercelによるSSRとサーバレスAPIを用いて、APiを作成しました。

https://github.com/HikaruEgashira/iksm-app

また、スプラトゥーンの開発を後押しするためにAPIも公開しています

https://iksm.vercel.app/api-docs

swaggerでのドキュメント作成を行っていますがコードの自動生成などは行っていないのでもしかしたら型が間違っているかもしれません。
質問などあれば答えますのでコメントにどうぞ。
kintoneで小さい順に並べる

今回は標準機能（計算フィールド）でバブルソートというアルゴリズムを用いて、
昇順ソート（小さい順に並べる）してみたいと思います。
kintoneに入力した数値を小さい順に並べ替えます。


↓出来上がりイメージ
<iframe width="480" height="400" src="https://www.youtube.com/embed/8iAxcI6Q8dg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# バブルソートとは？

バブルソートについては、先人たちがたくさんの記事を書いておられますので、
そちらをご参照ください。

本記事は、kintoneでバブルソートで「小さい順に並べる」を作ってみただけの内容となります。

↓バブルソート参考記事

https://www.codereading.com/algo_and_ds/algo/bubble_sort.html

https://wa3.i-3-i.info/word14886.html

# アプリの準備

フィールドがたくさんあって大変です。

## 入力と結果の部分

| フィールド種類| フィールドコード |備考（計算式） |
|:-:|:-:|:-:|
|数値| a  |   |   
|数値| b  |   |   
|数値|  c |   |   
|数値| d  |   |   
|数値|e   |   |   
|計算| A  | IF(a5<=b6, a5, b6)  |   
|計算|  B |  IF(a5>=b6, a5, b6) |   
|計算|   C|  IF(b5>=c4, b5, c4) |   
|計算|   D|  IF(c3>=d2, c3, d2) |   
|計算|   E|  IF(d1>=e, d1, e) |   

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/d9f6278d-52f2-18ad-2ddc-0fe1fa3f5bfb.png)

## グループ内1回目

グループでは途中計算をしています。

a,bの比較からd,eの比較までしています。

aとbを比べて小さい方がa1に、大きいほうがb1に入り、
b1とcを比べて小さい方がb2に、大きいほうがc1に入り、・・・
といったように順番に隣り合う値を比較して、

小さい値をアルファベットの小さい方に入れる
大きい値をアルファベットの大きい方に入れる

という感じで計算式を作っています。

1回目でEの値が決まりますが、グループ内の途中計算の方には表示せず、結果の方だけに「E」を表示しています。

| フィールド種類| フィールドコード |備考（計算式） |
|:-:|:-:|:-:|  
|計算| a1  | IF(a<=b, a, b)|   
|計算|  b1 | IF(a>=b, a, b)|   
|計算|   b2| IF(b1<=c, b1, c) |   
|計算|   c1| IF(b1>=c, b1, c)|   
|計算|   c2|  IF(c1<=d, c1, d)| 
|計算|   d1| IF(c1>=d, c1, d)|   
|計算|   d2|  IF(d1<=e, d1, e)| 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/242419dc-05f5-4ae8-2944-3f05c6a0332a.png)

## グループ内2回目と3回目

1回目と同様、
a1,b2を比べて小さい方がa3に、大きい方がb3に入り、
b3,c2を比べて小さい方がb4に、大きいほうがc3に入り、・・・
といった比較をしています。

| フィールド種類| フィールドコード |備考（計算式） |
|:-:|:-:|:-:|  
|計算| a3  |IF(a1<=b2, a1, b2)|   
|計算|  b3| IF(a1>=b2, a1, b2)|   
|計算|   b4| IF(b3<=c2, b3, c2) |   
|計算|   c3|IF(b3>=c2, b3, c2)|   
|計算|   c4|  IF(c3<=d2, c3, d2)| 
|計算|   a5|IF(a3<=b4, a3, b4)|   
|計算|   b5| IF(a3>=b4, a3, b4)| 
|計算|   b6|IF(b5<=c4, b5, c4)| 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/455a85b0-4689-0d2f-db65-01279b7c43c5.png)


# まとめ

なにか使えるポイントはないかなと考えましたが、
たとえば、工夫次第では・・・ルックアップで取ってきたデータを並び替えるという事もできます👀✨✨

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/c0c83d75-7fa3-c842-7096-0da2e90099ee.png)
DockerでMailHogを使ってPHPのメール送信確認をする

Dockerでメール送信確認をする時に、sendmailの設定をしないといけなかったり、うまく外に出ていかなかったり面倒な場合がありますが、[MailHog](https://github.com/mailhog/MailHog)を使うと簡単にできます。
また、メールは実際には送信されないので、テストのつもりが間違ってメールを送ってしまった！という心配もないので安心です。
(PHPのアプリケーションでメール送信する場合について書きます。)

# 設定
## MailHogを導入

MailHogを`docker-compose.yml`のサービスに追加します。

```yml:docker-compose.yml
services:
    mailhog:
        image: mailhog/mailhog
        ports:
            - 8025:8025
```

## アプリケーションの設定
### 1. PHPのmailをMailHogに変更する場合

フレームワークの設定(後述)で設定してもいいですが、ローカルと本番で設定を変えたくない等の場合や、素のPHPを使用する場合は、phpのメール送信コマンドを`sendmail`から`mhsendmail`に置き換えます。

まず、PHPアプリケーションのDockerfileで`mhsendmail`のインストールを追加します。

```Dockerfile:Dockerfile
RUN curl -sSL https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 -o mhsendmail \
    && chmod +x mhsendmail \
    && mv mhsendmail /usr/local/bin/mhsendmail
```

phpの設定ファイルで、`sendmail_path`を`mhsendmail`にします。
`php.ini` に直接書いてもいいですが、`mail.ini`というファイルを作って`/etc/php.d/mail.ini`へ設置することにします。

```ini:mail.ini
[mail function]
sendmail_path = "/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"
```

```yaml:docker-compose.yml
services:
    php:
        volumes:
            - ./mail.ini:/etc/php.d/mail.ini:ro
```
(その他の必要な設定は適宜記述してください。)

### 2. フレームワークの設定で設定する場合

`mhsendmail`を使用せずに、フレームワークの設定でMailHogを使います。

#### Laravelの場合

`.env`にMailHogの設定を書きます。

```:.env
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_FROM_ADDRESS=test@example.com
```

#### CakePHPの場合

`app/Config/email.php.default`をコピーして、 `app/Config/email.php`にMailHogの設定を書きます。

```php:app/Config/email.php
public $default = array(
	'transport' => 'Smtp',
	'from' => 'test@example.com',
	'host' => 'mailhog',
	'port' => 1025,
	'timeout' => 30,
);
```
※ローカルと本番等で切り替える必要がある場合は、適宜書き分けてください。

# メールの確認

ブラウザで http://localhost:8025/ を開くと、送信されたメールが確認できます。
Dockerを停止すると消えてしまうので、残しておく必要がある場合は、volumeを設定するといいようです。

# 参考

* [`mhsendmail`を使用する](https://qiita.com/ktaidot/items/11337ad8e44e5561010d)
* [Laravelで使用する](https://qiita.com/ucan-lab/items/49e7f4986564f68e95c4)
* [CakePHPで使用する](https://qiita.com/nagimaruxxx/items/0f0a918ef107069fcf15)
* [Volumeを設定して使用する](https://qiita.com/matsunao722/items/047b42a9d2007edc4e86)
virtualhostの種類を見てみる

## 勉強前イメージ

virtualhostに種類ってあったっけ？

## 調査

### そもそもvirtualhostとは？

本来なら単一サーバで単一ドメインのwebサイトの運用が通常でしたが
単一サーバで複数のドメイン名のwebサイトを運用する機能です。

### virtualhostの種類

virtualhostの種類に以下の2つあります。

- NAMEベース : 1つのIPアドレスで複数のwebサイトの運用を行う
- IPベース : 複数のIPアドレスでwebサイトの運用を行う

#### NAMEベース

1つのIPアドレスで複数のwebサイトの運用を行う方法で
ホスト名を元に応答するホストを決める方式です。
ただし、一部の古いwebブラウザやプロキシなどのクライアントがNAMEベースのvirtualhostに対応していない可能性があるので
注意しないといけません。

![nameベース.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/b90dbdb6-86d0-6821-feda-082ecd393625.png)


#### IPベース

複数のIPアドレスでwebサイトの運用を行い、
IPアドレスでホストを区別するのが、IPベースのvirtualhostになります。
IPアドレスは複数用意出来るが、サーバが何個も用意できないときに使える手段になります。

![IPベース.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/8b0d0fef-819e-43ff-5dd9-b3348113c63b.png)


## 勉強後イメージ

あんまり考えて作ってなかったけど、たしかに種類あるよね。
どっちも作ったことあるけど、個人的によく使うのはNAMEベースかな。。

## 参考

- [バーチャルホストによる複数サイトの同時運用](https://atmarkit.itmedia.co.jp/ait/articles/0108/28/news001.html)
- [2.5 バーチャルホスト](https://software.fujitsu.com/jp/manual/manualfiles/M050000/B1WN4991/03/ihs02/ihs00012.htm)
【Git】git diffで差分を確認しよう（初心者向け）

#はじめに
今回は、`git diff`で変更差分を確認していきましょう。
`diff`とは`different`の略です。
ファイルを変更して、エリア間で差がある場合にのみ結果が表示されるので、ファイルを変更する前や`git commit`した後に`git diff`を実行しても、その状態ではファイルに差がないので、何も表示されません。

#git diff
`git diff`は、ワークツリーとステージ（インデックス）の間の差分を確認することができます。
つまり、`git add`する前に差分を確認するためのコマンドです。
特定のファイルの差分を確認したい場合は、`git diff`の後に確認したいファイル名を記述します。

```git:ターミナル
git diff
git diff <ファイル名>
```

#git diff --staged
`git diff --staged`とすると、ステージとローカルリポジトリの間の差分を確認することができます。
つまり、`git add`した後、`git commit`する前に差分を確認するためのコマンドです。
`git diff --cached`を使っても同じ結果になります。

```git:ターミナル
git diff --staged
git diff --cached
```

#おわりに
`git diff`を実行した結果は見ればどういう意味かはすぐ分かると思いますが、「-」が先頭に付いている行が削除された行で、「+」が付いている行が追加された行という意味になります。
前回投稿した`git status`と同様、`git add`や`git commit`を行う前に、ファイルにどのような変更を加えたのか確認する癖を付けておきましょう。
SQLServerのSQLメモ

# 取得したテーブル一覧に対して処理

## ポイント

- テーブル名の取得
- ループ
- 動的SQLの作成と実行

```sql
-- 対象DB設定
USE d_test;
GO

/*
=========================================
  条件値設定
=========================================
*/

-- 抽出対象更新日時
DECLARE @cond_datetime nvarchar(30) = '2021-09-20 00:00:00';

/*
=========================================
  テーブルと列名のMAP
========================================= 
*/
DECLARE @table_col_map TABLE(
    TABLE_NAME NVARCHAR(100)
    , COL_NAME NVARCHAR(100)
);

-- テーブルと調べる更新日時列名の対応関係を設定
INSERT INTO @table_col_map VALUES
  ('crews', 'update_at'),
  ('clients', 'update_at');

/*
=========================================
変数定義
=========================================
*/

DECLARE @table_name nvarchar(100);
DECLARE @sql nvarchar(2000);
DECLARE @updated_count int = 0;
DECLARE @updatetime_col_name nvarchar(100);
/*
=========================================
データ取得と結果表示
=========================================
*/

-- データ取得カーソル定義
DECLARE cur_table CURSOR FOR SELECT name FROM sys.tables 

-- ヘッダ表示
print 'テーブル, 更新件数' 
-- データ取得開始
OPEN cur_table;

FETCH NEXT FROM cur_table INTO @table_name 
WHILE @@FETCH_STATUS = 0 BEGIN 
  -- print '=== target_table:' + @table_name

  -- 更新日時の列名取得
  SET @updatetime_col_name = (SELECT COL_NAME FROM @table_col_map WHERE TABLE_NAME = @table_name);

  -- sql作成
  SET @sql = N'SELECT @updated_count = count(*) FROM #table WHERE #updatetime_col > ''#cond_datetime'' ';
  SET @sql = replace(@sql, '#table', @table_name);
  SET @sql = replace(@sql, '#updatetime_col', @updatetime_col_name);
  SET @sql = replace(@sql, '#cond_datetime',@cond_datetime);

  --print @sql
  -- 指定更新日より後の件数を取得
  EXECUTE sp_executesql 
    @sql,
    N'@updated_count int OUTPUT',
    @updated_count OUTPUT;

  -- 指定更新日時以降に更新があったテーブル名と件数を表示
  IF @updated_count > 0 
    print @table_name + ',' + CAST(@updated_count AS nvarchar(10)) 
  
  -- 次の行を取得
  FETCH NEXT FROM cur_table INTO @table_name

END 

-- カーソルの解放
CLOSE cur_table; 
DEALLOCATE cur_table;


```

# テーブルと列の名前とコメント取得

```sql
use d_test;
go

-- テーブルの名前とコメント取得
SELECT
  t.name    as TABLE_NAME
  ,ep.value  as COMMENT
FROM
  sys.tables t 
  LEFT JOIN sys.extended_properties ep ON t.object_id = ep.major_id

-- 列名と列コメント取得

SELECT
  t.name    as TABLE_NAME
  ,c.name    as COLUMN_NAME
  ,ep.value  as COMMENT
FROM
  sys.tables t 
  LEFT JOIN sys.columns c ON t.object_id = c.object_id
  LEFT JOIN sys.extended_properties ep ON c.object_id = ep.major_id AND c.column_id = ep.minor_id


-- テーブルコメントと件数

use d_test;
go

SELECT
    t.name    as TABLE_NAME
  , ep.value  as COMMENT
  , ind.rows  as ROW_COUNT
  , ep.minor_id
FROM
  sys.tables t 
  LEFT JOIN sys.extended_properties ep ON t.object_id = ep.major_id
  LEFT JOIN sys.sysindexes ind ON t.object_id = ind.id AND ind.indid < 2
WHERE
  ep.minor_id = 0 OR ep.minor_id is null
```
【Flutter】androidアプリをリリースしたときに躓いた

#背景
Flutterで作成したandroidアプリを始めてリリースする際、アップロード用アプリをビルドするところで躓きました。


#エラー文
terminalでアプリをビルドするコマンドを打ったらエラーが出ました。

```
$ flutter build apk
```

```
C:\Users\＜フォルダ名＞\＜アプリ名＞>flutter build appbundle

Building without sound null safety
For more information see [https://dart.dev/null-safety/unsound-null-safety](https://dart.dev/null-safety/unsound-null-safety)

FAILURE: Build failed with an exception.

- What went wrong:
Execution failed for task ':app:validateSigningRelease'.

> Keystore file 'C:\Users\＜フォルダ名＞\＜アプリ名＞\android\app\key.jks' not found for signing config 'relea
se'.

- Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to g
et full insights.
- Get more help at [https://help.gradle.org](https://help.gradle.org/)

BUILD FAILED in 22s
Running Gradle task 'bundleRelease'...                             24.2s
Gradle task bundleRelease failed with exit code 1""
```


#解決方法
keyの設置場所が間違っていて、android/key.propertiesのstoreFileを以下の値に修正したらエラーがなくなりビルドに成功しました。

```flutter:android/key.properties
storePassword=＜自分のパスワード＞
keyPassword=＜自分のパスワード＞
keyAlias=key
storeFile= ./key.jks
```
[Docker] unknown mysql server host 'db' (-2) と表示されるときの対処法

## 環境

Docker 19.03.5
Rails 5.2.4
Ruby 2.5.3
MySQL 5.7

## イントロダクション

docker-compose内でRails環境を動かそうと

```
docker-compose run web rails db:create
```
 
した際に以下のようなエラーが発生。

<br>

```
rails aborted! Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
```

はて、どうしたものか、、
まずは、調べて出てきたものをそのままやってみよう。


## まず試してみるべきこと

### 「database.yml」ファイルの編集


```yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```

最後の行の「host: db」が「host: localhost」になっている場合は動かない。


### 「docker-compose.yml」ファイルの編集

```yml
volumes:
  - ./tmp/db:/var/lib/mysql/data
```

「docker-compose.yml」ファイルのdb部分にvolumesを追加してみる。

db部分は以下のような構造になる。

```yml
db:
  image: mysql:5.7
  environment:
    MYSQL_ROOT_PASSWORD: password
    MYSQL_DATABASE: root
  ports:
    - "3306:3306"
  volumes:
    - ./tmp/db:/var/lib/mysql/data
```

## それでも動かない場合（最終手段）

```
docker rmi $(docker images -q)
```
 

docker image を一旦全削除する。
kotlin×seluniumでスクレイピング

### 環境

- Windows 10 Home
- kotlin 1.5.30
- Google Chrome 94.0

### webdriverダウンロード

まずPCのGoogle Chromeのバージョンを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966654/63c00e88-dbfb-799c-615a-994dedfe01e2.png)
ここでは94.0.4606.61となっています。

webdriverをダウンロードします。
https://chromedriver.chromium.org/downloads
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966654/47661677-324e-fde6-6522-0b77bd0b41ab.png)
ここではメジャーバージョンがPCのChromeと一致している「ChromeDriver 94.0.4606.41」を選択してダウンロードします。

ダウンロードしたzipファイルを展開してできたファイルを任意のフォルダに配置します。

### gradle設定
```build.gradle.kts

dependencies {
    implementation("org.seleniumhq.selenium:selenium-java:3.141.59")
    implementation("org.seleniumhq.selenium:selenium-support:3.141.59")
}
```

### コード
```Scraping.kt
import org.openqa.selenium.By
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions

fun main(args: Array<String>) {
    // 環境変数にchromedriverのパスを設定（自身の環境に合わせて設定してください）
    System.setProperty("webdriver.chrome.driver", "C:\\tool\\chromedriver_win32\\chromedriver.exe")

    val options = ChromeOptions().apply {
        // headlessモードにする場合はここで指定
        addArguments("--headless")
    }

    val driver: WebDriver = ChromeDriver(options)
    // Webページにアクセス
    driver.get("https://ja.wikipedia.org/wiki/ウェブスクレイピング")
    // pタグの最初の要素を取得
    val p = driver.findElements(By.tagName("p"))[0]
    // コンソールにテキストを出力
    println(p.text)

    // ブラウザを閉じる
    driver.close()
}
```

### 結果
```
Starting ChromeDriver 94.0.4606.41 (333e85df3c9b656b518b5f1add5ff246365b6c24-refs/branch-heads/4606@{#845}) on port 6418
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
9 27, 2021 2:37:43 午後 org.openqa.selenium.remote.ProtocolHandshake createSession
情報: Detected dialect: W3C
ウェブスクレイピング（英: Web scraping）とは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。通常このようなソフトウェアプログラムは低レベルのHTTPを実装することで、もしくはウェブブラウザを埋め込むことによって、WWWのコンテンツを取得する。ウェブスクレイピングはユーザーが手動で行なうこともできるが、一般的にはボットやクローラ(英: Web crawler)を利用した自動化プロセスを指す。

プロセスは終了コード 0 で終了しました
```
【React】マウス位置だけ画像が見える背景を実装する（particles.js）

<!-- =========================================================== -->
# 概要
<!-- =========================================================== -->
**マウス位置だけ粒子が結合して、背面の画像が見える背景**を実装します。

![output(video-cutter-js.com) (8).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/add2e659-8290-e2c7-eb3c-1361a3d24fc9.gif)

:::note info
本記事は、以下の動画を<strong>React</strong>で実装したものです。
:::

https://www.youtube.com/watch?v=j87gaYoBmso

:::note info
スタイリングには、<strong>emotion/css</strong>（CSS in JS）を使用しています。
:::

https://emotion.sh/docs/@emotion/css

https://qiita.com/nemutas/items/dac73aa645f27cde92cd

:::note info
<strong>particles.js</strong>の使い方は、以下を参照してください。
:::

https://qiita.com/nemutas/items/d9dd251e397d4e335731

<!-- =========================================================== -->
# 実装
<!-- =========================================================== -->
```.tsx
import React, { VFC } from 'react';
import Particles from 'react-particles-js';
import { IOptions, RecursivePartial } from 'tsparticles';
import { css } from '@emotion/css';
import ParticlesParams from '../../assets/particlesjs-black-bubble.json';

export const AnimatedParticles: VFC = () => {
	return (
		<div className={styles.container}>
			<img className={styles.img} src="/assets/bg2.jpg" alt="" />
			<Particles
				className={styles.particles}
				params={ParticlesParams as RecursivePartial<IOptions>}
			/>
		</div>
	)
}

const styles = {
	container: css`
		position: relative;
		width: 100vw;
		height: 100vh;
	`,
	img: css`
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
	`,
	particles: css`
		position: relative;
		height: 100%;
		background-color: #fff;
		mix-blend-mode: screen;
	`
}
```
* **mix-blend-mode**で、背景画像と前面のParticlesを重ねています。**screen**を使用することで、白は不透明、黒（漂う粒子の色）は透明になります。

https://developer.mozilla.org/ja/docs/Web/CSS/mix-blend-mode