OmniAICreator/Qiita-1.07M huggingface dataset:
paizaラーニングレベルアップ問題集の「残り物の量」を色々な言語でやってみた

paiza×Qiita記事投稿キャンペーンということで、paizaラーニングレベルアップ問題集の[残り物の量](https://paiza.jp/works/mondai/c_rank_skillcheck_archive/leftover)を色々な言語でやってみました。対象は[コードモンスター大図鑑](https://paiza.jp/code_monster)で対応している9言語です。

2024/08/25
Javascriptのコードを修正いたしました。
- - -
###### 方針
答えは
```math
\begin{eqnarray}
&&m\times\left(1-\frac{p}{100}\right)\times\left(1-\frac{q}{100}\right)\\
&=&\frac{m\left(100-p\right)\left(100-q\right)}{10000}
\end{eqnarray}
```
です。
- - -
###### PHP
```php
<?php
	[$m, $p, $q] = explode(" ", fgets(STDIN));
	echo $m * (100 - $p) * (100 - $q) / 10000;
?>
```
- - -
###### Ruby
```rb
m, p, q = gets.split.map(&:to_f)
p m * (100 - p) * (100 - q) / 10000
```
- - -
###### Java	
```java
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		double m = sc.nextDouble();
		double p = sc.nextDouble();
		double q = sc.nextDouble();
		sc.close();
		System.out.println(m * (100 - p) * (100 - q) / 10000);
	}
}
```
- - -
###### Python
```py
m, p, q = map(float, input().split())
print(m * (100 - p) * (100 - q) / 10000)
```
- - -
###### C言語
```c
#include <stdio.h>

int main(void) {
	double m, p, q;
	scanf("%lf %lf %lf", &m, &p, &q);
	printf("%.4lf\n", m * (100 - p) * (100 - q) / 10000);
	return 0;
}
```
- - -
###### C#
```cs
using System;

class Program
{
	static void Main()
	{
		double[] mpq = Array.ConvertAll(Console.ReadLine().Split(), double.Parse);
		double m = mpq[0];
		double p = mpq[1];
		double q = mpq[2];
		Console.WriteLine(m * (100 - p) * (100 - q) / 10000);
	}
}
```
- - -
###### Javascript
```js
const lines = require("fs").readFileSync("/dev/stdin", "utf8").split("\n");
// 2024-08-25 parseFloatからNumberに変更
// const [m, p, q] = lines[0].split(" ").map(parseFloat);
const [m, p, q] = lines[0].split(" ").map(Number);
console.log(m * (100 - p) * (100 - q) / 10000);
```
- - -
###### C++
```cpp
#include <iostream>
#include <iomanip>
using namespace std;

int main(void) {
	double m, p, q;
	cin >> m >> p >> q;
	cout << setprecision(7) << m * (100 - p) * (100 - q) / 10000 << endl;
	return 0;
}
```
- - -
###### Kotlin
```kotlin
import java.util.*

fun main() {
	val sc = Scanner(System.`in`)
	val m = sc.nextDouble()
	val p = sc.nextDouble()
	val q = sc.nextDouble()
	sc.close()
	println(m * (100 - p) * (100 - q) / 10000)
}
```
[AWS #23] Route 53

<!--
 <font color="c00000"></font> 赤
-->
## はじめに
こんにちは
今回はクラウドテクノロジーとサービス分野である **<font color="c00000">「Route 53」</font>** について紹介したいと思います。
:upside_down: Route 53は**DNS（ドメインネームシステム）** の**フルマネージドサービス**です。Amazon Route 53で管理しているドメインを参照し、レコード（IPアドレス）に紐づくデータを取得することができます。

## DNS
はじめにで登場した「DNS」について軽く紹介いたします。
DNSとは「ドメインネームシステム」の略称です。数字を組み合わせたコンピュータの住所である「IPアドレス」を<font color="c00000">**人間が理解しやすい住所へと変換する**</font>ための仕組みです。
![AWS23_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/7abd1d7d-2a37-35ae-6207-e42c8137ab38.png)

## Route 53の特徴

Route 53には次の特徴があります

:::note info
様々な**ルーティング機能**
:::
:::note info
高可用性を実現する**ヘルスチェックとフェイルオーバー**
:::

### 様々なルーティング機能
ルーティング機能には以下のものがあります。

・**シンプルルーティング**
→　１つのリクエストに対して、一つの値を返します。

![AWS23_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/48bc18be-9200-ea1b-29bd-6cfa7b9a01f7.png)

・**レイテンシーベースのルーティング**
→　1つのドメインに対して複数のDNSレコードを用意しておき、地理的な場所を近くして複数のレイテンシー（遅延）が低くなるようにルーティングを行います。
![AWS23_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/825c993b-154f-8b61-8d3b-dd65c572ed10.png)

・**加重ルーティング**
→　1つのドメインに対して複数のDNSレコードを用意しておき、割合を決めます。その割合に応じて回答を返します。
![AWS23_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/5d408c8a-bf2d-faf3-4529-246a65224b18.png)

### 高可用性を実現するヘルスチェックとフェイルオーバー
:upside_down: Route 53ではルーティング先に対して**ヘルスチェック**をすることが可能です。
図のように「Sample.com」にプライマリとセカンダリを設定しておくとヘルスチェックでプライマリに障害発生した時は、ルーティング先を自動的にセカンダリにフェイルオーバーをすることができます。
![AWS23_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/277c77cd-ce80-a3ac-6524-a8b11a4f7742.png)

このようにヘルスチェックとフェイルオーバーを使用することで、システムの<font color="c00000">**可用性を向上させる**</font>ことができます。

## おわりに
今回のちょっとしたまとめになります。

:::note info
Route 53では、複数のレコードを設定し、用途に応じて**最適なルーティングを選択**できる
:::
:::note info
Route 53では、プライマリの障害時にセカンダリに**自動的に振り替えるフェイルオーバー**が利用できる
:::

Route 53は色々なビジネスシーンやケースによって、様々な機能を提供しているサービスということがわかりました。最後までお読みいただきありがとうございました！
>>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[Amazon Route 53](https://aws.amazon.com/jp/route53/)
>
> **「参考元」**
[【初心者向け】Amazon Route 53 とは](https://www.sunnycloud.jp/column/20210602-01/)
>
> **「Youtube」**
[Amazon Route 53](https://www.youtube.com/watch?v=_wO82D_Hojw)
Alembicのマイグレーションファイル作成時に希望するテーブルの順番でupgrade文を出力する

# 課題

alembicでテーブル定義のマイグレーションファイルを作る場合に以下の課題があった。
モデル定義ファイルをテーブルごとに分割すると、ファイル名の並び順でマイグレーションの定義が作成される。


# 要求

依存関係があるとエラーになるので、指定の順序で定義を出力したい。

# 前提

- modelsフォルダにSQLModelを利用してテーブル定義を作成する
- 「models/__ init__.py」に定義を作成した順番にimportを記載する

```sh：例
models
 └ __init__.py
 └ user_assign.py
 └ user.py
```
ファイルの並びは上記のようになりmigrationファイルの出力結果も名前の並び替え順になる。
それを、定義の順番である「user → user_assign」に変更して、出力する。

```py:__init__.py

from .user import User
from .user_assign import UserAssign

```


上記の「__ init__.py」のインポート順で定義を出力する。

alembic/env.pyでmetadataを取得しやすいように、モデルは「sqlmode.SQLModel」を継承しておく。

```user.py
from sqlmodel import SQLModel

class User(SQLModel):
    ... # 具体的な定義

```

# 定義

alembic/env.pyに以下を記載します。
デフォルトの記載は省略します。加筆する部分のみ記載します。

```py:alembic/env.py

... デフォルトの定義は省略

# metadataを取得するためにインポート
from sqlmodel import SQLModel
# 各テーブル定義をインポート
from models import *

... デフォルtの定義は省略（「target_metadata = None」を以下のように変更）

target_metadata = SQLModel.metadata


... デフォルトの定義は省略

# ★並び替えの関数を追加
def process_revision_directives(context, revision, directives):
    if directives[0].upgrade_ops.ops:
    
        # 定義順になるようにリストを作成(metadata.tablesは定義順になっている）
        table_order = list(SQLModel.metadata.tables.keys())

        # 既存の操作をソート
        sorted_ops = sorted(
            directives[0].upgrade_ops.ops,
            key=lambda op: (
                table_order.index(op.table_name)
                if hasattr(op, "table_name") and op.table_name in table_order
                else len(table_order)
            ),
        )

        # ソートされた操作で置き換え
        directives[0].upgrade_ops.ops = sorted_ops

# ★ 並び替えの関数定義ここまで

def run_migrations_offline() -> None:
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
        process_revision_directives=process_revision_directives, # ★この行を追加
    )

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online() -> None:
    connectable = engine_from_config(
        config.get_section(config.config_ini_section, {}),
        prefix="sqlalchemy.",
        poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
        context.configure(
            connection=connection,
            target_metadata=target_metadata,
            process_revision_directives=process_revision_directives, # ★この行を追加
        )

        with context.begin_transaction():
            context.run_migrations()


```

上記の定義後、以下のようにマイグレーションファイルを作成する。

```sh
 alembic revision --autogenerate -m "create-basic-tables"
```

alembic/versionsに以下のような順番の定義ファイルが作成される。

```py:バージョン定義ファイル

def upgrade() -> None:
    op.create_table('user',...)
    op.create_table('user_assign',...)    

```

# 参考

perplexityに質問して、その内容を実証してみました。

質問：alembicのprocess_revision_directivesでテーブルの順序を指定するには？

https://www.perplexity.ai/
2024/8/19主にITとかセキュリティの記事

AMD『Sinkclose』脆弱性の修正対象にRyzen 3000シリーズを追加。8月20日以降に対応へ(8/17)
https://gazlog.jp/entry/amd-sinklose-ryzen3000/

米携帯キャリアのPixelデモ機アプリにセキュリティの危険性が判明。Googleが削除へ(8/16)
https://smhn.info/202408-pixel-showcase-app

英国国家犯罪庁、米国シークレットサービス、連邦捜査局が協力し、ランサムウェア等のサイバー犯罪グループのトップ容疑者を逮捕、身柄を引き渡す (2024.08.13)(8/17)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/08/post-c1e46d.html

太陽光発電、サイバー攻撃の温床に　IoT経由で不正送金(8/17)
https://www.nikkei.com/article/DGXZQOUC254VD0V20C24A7000000/

米　ハッカー集団が最大29億人分の個人情報不正入手か(8/17)
https://news.yahoo.co.jp/articles/a278770e8d998470f4c7456cac67da1ea5990f82

Google SecOps：SIEM と SOAR ではじめるサイバーセキュリティ(8/16)
https://zenn.dev/cloud_ace/articles/google-secops-overview

RAIDとは(8/16)
https://qiita.com/ichigoohitujiza/items/bfe3c2f129069bc55f7d

中国TP-Link社製ルーターがハッキングリスク、国家安全保障を脅かす：米国議員が調査を要求(8/17)
https://www.epochtimes.jp/2024/08/246567.html

生成AIを使用すべきでないケースとは？(8/17)
https://www.gartner.co.jp/ja/articles/when-not-to-use-generative-ai

アップル社　iCloud上の児童性的虐待コンテンツ問題に対する不作為で提訴される(8/17)
https://www.epochtimes.jp/2024/08/246627.html

【SNS犯罪被害に巻き込まれる小学生が過去最多！】専門家に聞いた「SNS犯罪から身を守るために親子で知っておくべきこと」とは？(8/17)
https://news.yahoo.co.jp/articles/d04833785fab03f9717a49f53dc6378e1b6afc99
シェルスクリプト(.sh)でpythonを実行するとimportエラーが出る

# 事象
raspberry Pi や linuxを使っているときにシェルスクリプト(.sh)でpythonを実行すると
importエラー(ModuleNotFoundError)が出る

# 原因
shで実行すると個別ユーザーでpip installしたモジュールフォルダを見に行かない（パスが通ってない）ため

# 解決法
## 方法① pyファイルの実行を明示的にユーザーで実行する
一番楽

方法
```
sudo -u username pythonのパス pytonのファイル.py 
```
例
```
sudo -u pi /usr/bin/python3.9　/usr/bin/test.py
```

### 方法② sudoを使ってモジュール再インストール
全体に適用させたい場合におすすめ、あと簡単
個別ユーザーと全体に同じものが2つ入るので容量が重いmoduleだとやだ

方法
```
sudo pip xxxxx
```
のようにsudoを使って再インストール


### 方法③pythonファイル内にて明示的にpathを追加する
とりあえず自分自身の環境で実行する場合におすすめ
pythonにコードを追加する必要あり

方法
```
import sys
sys.path.append('追加したいパス')
# 例えば /home/"ユーザーネーム"/.local/lib/python3.9/site-packages
```    

補足
対象のpythonファイルに以下を追加して
実行できる環境と、そうでない環境(.shによる実行環境など)で対象のpythonファイルを実行すると
それぞれで参照している環境変数pathがわかるのでどのpathが足りていないか比較できる
→追加すべきパスがわかる

```
import sys 
print(sys.path)
```
【Javascript】DOMの概念について図解で端的に解説する

# はじめに

前々から「DOM」という言葉は知っていたのですが、あまり概念について把握してない状態で学習を進めていました。今回、Javascriptの基礎概念を網羅した動画で勉強したので、この記事にて共有できればと思います！

# DOMについて

### 概要

DOM(Document Object Model)とは、下図のように、**HTMLを描画するにあたって描画しやすいようにプログラムを整形してくれる仕組み**です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/11f6306d-ba03-9bb4-dfeb-fb8f469a2fae.png)

上図より、「test」と出力するHTMLファイルを記述して、DOMで何らかの整形をして、画面に「test」と反映できていることが確認できます。
それでは、DOMでは具体的にどういったことが行われているか？を次で解説します。

### 内部ではどういったことが行われているか？

DOMの内部では、HTMLをツリー上に整形しています。
例えば、下記のようなソースコードを考えます。

![スクリーンショット 2024-08-19 0.36.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/73580c86-70d8-d73b-9e4c-6974e8f47af1.png)

その場合、下図のようなDOMツリーの構造になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/a8c79355-6fd5-1158-1404-ec6561b61a38.png)

こちらは、開発者ツールでも確認が可能になります。

![スクリーンショット 2024-08-19 1.13.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/6842ff3f-0c3f-a269-b7e5-95c0b37eb648.png)


この手法を導入したことで、HTMLをオブジェクト的な階層構造としてみなすようになりました。また、それぞれのタグの単位を「ノード」といい、特に同じ階層にあるノードを兄弟ノード、上下にあるノードを親子ノードと呼んだりします。
では、このDOMの仕組みを導入した利点は一体なんでしょうか？

### 一体どんな利点があるのか？

DOMを導入した利点として、**動的なWebページを作れるようになった**ことです。
動的なWebページとは、リアルタイムでページの内容が変化する仕組みで、例としてXやInstagramなどがあります。例えばInstagramに例えて考えると、

* DOMなし：更新するたびに、画面で変わらない部分(スマホ画面にて見た場合、左上のInstagramの文字やボタン部分)も毎回読み込まれることで、**表示速度が遅くなる**
* DOMあり：画面で変わる部分のみ(ストーリーや投稿など)が読み込まれることで、**表示速度が速くなる**

となり、DOMがあることで、一部の情報だけを書き換えることができることから、更新時の表示速度が速くなります。

# まとめ

今回はDOMについて解説しました。まとめると、

* DOMとは：HTMLを描画するにあたって描画しやすいようにプログラムを整形してくれる仕組み

* DOM内部の処理：HTMLをオブジェクト(階層構造)としてみなす

* DOM導入の利点：動的なWebページが作れるようになったこと

となります。

次の投稿では、DOMを操作する代表的なコマンドについて解説できればと思います。
VRoid SDKを使ってUnityでVRoid Hubのアバターを出す方法

# はじめに

こんにちは。
ジョジョ好きなXRクリエイターの [もふるね](https://twitter.com/mofurune_k) です。

古銭プッシャーフレンズというゲームではVRoid Hubに登録したアバターをゲーム内に登場させれるみたいです。
好きなアバターを出せるアプリ、つくってみたいね！
VRoid Hubとアプリをどうやって連携するんだろう...?
とりあえず、やってみよう！


# 参考記事

https://qiita.com/tatsuya1970/items/a1ecd31f8b431822d217

https://vroid.notion.site/VRoid-SDK-ee0292e55d364f88b3ecef67b820c040


# 目的

Unity上でVRoid Hubに登録したアバターを出現させるまでをやります。
VRoid Hubに登録したアバターを出せるサンプルシーンがVRoid SDK for Unityの中にあるので、それを動かすことを目的とします。


# 申請

VRoid SDKを使うには申請が必要です。
[VRoid SDKのサイト](https://developer.vroid.com/sdk/?referrer=https%3A%2F%2Fwww.google.com%2F)にて、VRoid Hub API / SDK開発者登録をします。
登録にはPixivアカウントが必要です。

登録が完了すると、Unity向けVRoid SDKをダウンロードできるようになります。
ダウンロードしておきましょう。
![17d80cc9e5c2dbdc98a37956ba0eccc3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/44e688b9-e27c-0bbc-9fe2-fa8ea00deff2.png)

![8dd834165d8d44672ebdd2fa9cca0362.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/b8cc5f8a-fef1-7ce0-e241-263be44aa844.png)

[VRoid Hubのアプリケーションのサイト](https://hub.vroid.com/oauth/applications)にて、アプリの登録をします。

アプリの登録をすると、アプリケーションIDとシークレットが手に入ります。（画像ではモザイクをかけてます）
「Credentialファイル作成」ボタンを押して、credential.json.bytesをダウンロードしておきます。
後々Unityにて使います。
![tenorivrm_qiita01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/8995580c-b933-7c53-7291-9a003a4ffa3f.png)



# 環境構築

Unity 2022.3.22f1の3D(Built-In Render Pipeline)コアでプロジェクトを作成します。

Unity向けVRoid SDKをインポートします。
インポートが完了するとエラーがでました。インポートしただけだぞ...?
調べたら、Input Systemをインストールすればいいらしいです。
Package Managerタブで、Unity RegistryにてInput Syetemをインストールします。

![3dd23804b4d54c17faa4e6f4077cab52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/114cc4c9-2838-c9a9-dc8d-ad6b8c4bdbde.png)

これでエラーがでなくなりました。ふぅーーーっ。

それではサンプルシーンを触っていきます。
まずは、credential.json.bytesをAssets > Resources以下に配置します。
次に、Assets > VRoidSDK > Examples > CharacterModelExample > Scenes にある Example を開きます。
Hierarchyの VRoidHubController > Routesの Add PassWordに任意の文字列を書きます。
任意とはいえ、ひらがな、半角数字、全角スペース、記号などはダメなようです。なんか試したらエラーが出ました。半角アルファベットにしておきましょう。「password」とかね（セキュリティガバ）

これで準備は完了！Unityの再生ボタンを押して確認してみましょう！
初めはアプリの連携画面が出てくるので、連携をしておきます。
VRoid Hubに登録してある自分のアバターを選択します。（VRoid Hubにアバターを登録しておいてください）もしくは、Pickupを押して適当なアバターを選択します。

![a101d32cff94b75caa000296fe55de92.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/b5348ba1-c79b-ccde-bfdf-45a8886841ca.png)

アバターが出ました！アバターをクリックしながらマウスを動かすと回転します。
これにて完了です！

![b2971bb444e6f75a53127474498f374d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/ba7d5050-ac95-acf8-46fb-459c9aede328.png)


# 終わりに

VRoid SDKをUnityにインポートしただけでエラーが出たときには、びっくりしてVRoid SDKの開発者ディスコード鯖に参加して質問しかけた。既の所でChatGPTに質問したらいい回答をしてくれて助かった。GPTくん有能だねぇ！
初級者向けオープンソースプロジェクトに貢献する方法

オープンソースプロジェクトってかっこいいなーと思いつつ、参加する勇気が全く出ないし、難しそうだなーと思ってるんですがいつかやってみたい、、！ので今日はその第一歩としてオープンソースプロジェクトとはなに？？どうやってするの？？っていう基礎的なところをまとめてみました。

## オープソースとは
オープンソースとは、誰でも自由に使用、変更、配布できるソフトウェアを指します。ソースコードが非公開にされているソフトウェアとは異なり、オープンソースプロジェクトでは透明性、コラボレーション、コミュニティが重視されます。

なぜ貢献する必要があるのでしょうか? 以下にいくつかの理由を挙げます。

**学習**: 新しいスキルや知識を習得する。
**接続**: 志を同じくする開発者と出会い、人脈を広げる。
**構築**: 実際のプロジェクトをポートフォリオに追加する。
**恩返し**: 普段使っているツールやテクノロジーのプロジェクトに参加して恩返しをする。

## ステップ1: 適切なプロジェクトを見つける 🔍
オープンソースに貢献するための最初のステップは、ワクワクするプロジェクトを見つけることです。小さなことから始めても大丈夫です。
GitHub には多くのオープンソースプロジェクトが存在します。探索機能を使用して、興味のあるプロジェクトを見つけましょう。

## ステップ2: プロジェクトを理解する 📚

プロジェクトを見つけたら次はそのプロジェクトの理解を深めましょう。

まずは、プロジェクトの README ファイルを読み込みます。このファイルにはプロジェクトの概要、設定方法、貢献方法が記載されています。

次にコードを見てみましょう。構造、コーディング スタイル、主要なコンポーネントについて理解を深めます。

その後このプロジェクトはどのようなサポートを必要としているかを知るためにissueを確認しましょう。good first issue” や “beginner-friendly.”のラベルがついているものはとっつきやすいそうです。

## ステップ 3: 小さなことから始めて自信をつける 🛠️
タイプミスの修正、ドキュメントの改善、単純なバグの解決など、小さな問題を探してみましょう。
小さいように思えるものも実はプロジェクトにとって非常に価値があることです！

## ステップ 4: 実際にコントリビューションしてみる

貢献するための手順:

**リポジトリをフォークする** : GitHub 上のリポジトリをフォークして、プロジェクトの独自のコピーを作成します。

**リポジトリのクローン作成**: フォークしたリポジトリをローカル マシンにクローンします。
```
git clone https://github.com/YOUR-USERNAME/REPOSITORY-NAME.git
```

**ブランチを作成する**: 変更を加えたいときは新しいブランチを作成します。
```
git checkout -b your-branch-name
 ```

 **変更を加える**: ファイルを編集し、変更をコミットします。
 ```
git add .
git commit -m "Your descriptive commit message"
   ```

**プッシュしてプルリクエストを作成する**: ブランチを GitHub にプッシュし、元のリポジトリに対してプル リクエスト (PR) を開きます。
```
git push origin your-branch-name
```
これで最初の貢献が完了です! 🎉

## ステップ 5: コミュニティに参加する 🤝

オープンソースはコードだけではありません。コミュニティも重要です。
ディスカッションに参加したりミートアップやカンファレンスに参加して、他の貢献者とつながりましょう。

そしてある程度の経験を積んだら、新人を助けましょう。
自分もかつては同じ立場にいたことを忘れてはいけません。
Vue.jsって何？

## はじめに
ツール開発をするためにvue.jsを学んでいるので、自分が学習したことを備忘録として残していきたいと思います。
私の現状のスキルはhtml、css、JavaScriptは超超初心者で、実務経験もほとんどありません。
私みたいな超超初心者の方でも理解しやすいようにまとめたので、参考になれば嬉しいです。

## Vue.jsって何？
Vue.jsとは、UI開発のための**JavaScriptのフレームワーク**です。
フレームワークとは、**アプリケーション開発に必要なものをまとめたもの**です。
何もない状態からアプリケーションを開発するとなると、本来作らなければいけない機能がたくさんあるなか、フレームワークを使えばそれらをつくる必要がありません。
また、一定のルールや仕組みがすでにあるので、

- エンジニアの間でコードをの書き方を統一できて理解しやすくなる
- 開発がスムーズに進んでコスト削減につながる

というようなメリットがあります。

## Vue.jsの特徴
### リアクティブなデータバインディング
リアクティブなデータバインディングとは、**データの変更を保存すると自動で画面にも反映されること**です。
htmlやcssを書くときにはデータを変更した後に保存し、画面を更新しないと変更箇所を確認できませんでした。
しかしこれによってデータの変更をした後に保存するだけで自動で画面に反映されるため、手動で画面を更新したりすることなく、画面で変更箇所を確認することができます。

### コンポーネントベースの開発
コンポーネントとは、**再利用な可能な独立した部品のこと**です。
例えば、ボタンのコンポーネントを作成すると、そのボタンを表示させたい部分に1行コードを書くだけでボタンを表示することができるようになります。
コンポーネントをうまく利用することができれば、
- コードの量を減らすことができる
- 作成したコンポーネントを変更するだけで、そのコンポーネントを使用してる部分を一気に変更できる

というメリットがあります。

### シンプルで学習コストが低い
Vue.jsはJavaScriptの**基本的な知識と少しの追加構文を学ぶだけ**で開発が進められるため、学習コストが比較的低いと言われています。
私はJavaScriptの基本的な知識も怪しいですが、、、
Vue.jsを進めながらの理解を深めていけば良いと助言をいただいたので、Vue.jsの学習を進めながらJavaScriptの理解を深めていきたいと思います。

### 拡張機能が豊富で柔軟な開発ができる
Vue.jsはさまざまなライブラリやプラグインが利用できるので、さまざまなニーズに合わせて開発を進めることができます。

## まとめ
Vue.jsはJavaScriptのフレームワークであり、

- リアクティブなデータバインディング
- コンポーネントベースの開発
- シンプルで学習コストが低い
- 拡張機能が豊富で柔軟な開発ができる

という特徴がありました。

明日からは実際に手を動かして小規模なものを作りながら、コードの書き方やコンポーネントの使い方など、Vue.jsについて理解を深めていきたいと思います。

## 参考にした記事
[Vue.js公式](https://ja.vuejs.org/guide/introduction.html)
[アプリケーションフレームワークを徹底解説｜おすすめのフレームワーク9選も紹介](https://web-camp.io/magazine/archives/106630)
[Vue.jsとは？特徴や利用するメリットなどをわかりやすく解説
](https://ninjacode.work/magazine/programming/javascript6/#toc3)
非プログラマのDocker覚書

# 非プログラマのDocker覚書

プログラミングをしていると目に付く’Docker’という単語。調べてみたけど結局Dockerは何を解決するために存在しているのかわからない。そもそも何をどう調べたらいいかわからない。Dockerはわかったけどどう使うの？
そんな人の為に覚書を書いてみました。

目次
- なぜDockerを使わなければいけないのか？
- Dockerとは何？
- どうやってDockerを使えばいいのか？

## Q：なぜDockerを使わなければいけないのか？
A：環境を同じにするためです

「自宅のMacbookで動くけど、会社のwindowsでは動かないコード」とか「git上にあるサンプルコードはLinuxで動かすことを前提として作られていた。windowsで試しても謎のエラーが発生した。該当するエラー記事もない、オワタ＼(^o^)／」といった状況に陥らないためにもコードは同じ環境で動かしたいですね。そんなときにDockerの登場です。

## Q:Dockerとは何？
A:コンテナ型仮想環境。ゲストOSを起動せずにホストOS上の実行環境（ドッカーコンテナ）でアプリケーションを動作させる。従来型より軽い。

例えば、Windows上でLinux環境を構築しようと思ったら一つのOSの上に別のOSを構築するわけですから手順もややこしく、メモリ消費も大きいわけです。Dockerのコンテナ機能を使えば手順も画一化されているし、メモリ消費も最小に抑えられるといったメリットがあります。

## Q:どうやってDockerを使えばいいのか？
A デスクトップ上のファイルからDocker上の環境にアクセスできるようにする

今回は例としてWEB上で動くデータサイエンス環境を作って行こうと思います。以下ロードマップ。
- DockerHubの登録とDocker Desktopのインストール
- Docker　login
- Docker imageをpullする
- デスクトップ上のファイルにDockerのコンテナ内のファイルをマウントする

## DockerHubの登録とDockerDesktopのインストール
以下DockeHubリンク
https://hub.docker.com
DockerHubに登録したIDとPassは控えておきましょう

以下リンクからDockerDesktopをインストール。
https://docs.docker.jp/desktop/toc.html
Mac、Windows、Ubuntuと環境におうじて適切なパッケージを選びましょう。
## Doker login
DockerDesktopアプリの起動。または、ターミナルから
```
$ docker login
```
login時、DokerHubのIDとPassが必要

## Docker imageをpullする
以下リンクよりUbuntuにAnacondaが搭載されたJupyterNotebook用imageをpull
https://hub.docker.com/r/jupyter/datascience-notebook

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/e49dac33-05ba-dc6e-9f13-a9d83e69222e.png)
青ボタン'COPY'を押して、ターミナルに貼り付ける
```
$ docker pull jupyter/datascience-notebook
```
## デスクトップ上のファイルにDockerのコンテナ内のファイルをマウントする

```
$ mkdir desktop/jupyter_datascience-notebook
$ cd desktop/jupyter_datascience-notebook 
$ docker run -v ~/desktop/jupyter_datascience-notebook:/home/jovyan/work -p 10000:8888 --name jupyter jupyter/datascience-notebook
```
完成！！（緑で光ってるとこが新しく作成された）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/30ed5fd6-659e-bde4-9778-6774a9139603.png)
webにlocalhost:10000と入力すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/5471fd0e-5905-7b7f-7561-72c166892653.png)
※初回はtokenを求められるので、以下の記事を参考にしてください。

https://qiita.com/XTJP/items/29981dc25d80f7fed871
## でたー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/8caa6435-8e56-9fd8-c753-5653059c284c.png)

- マウントするコンテナのpathは/home/jovyan/workになっているので注意
【Rails】Rails始めて2週間でよく使ったコマンド

こんにちは！
今回はRailsを始めて2週間でよく使ったコマンドを紹介したいと思います。
最後まで読んでいただけると嬉しいです！

# コマンド紹介
 ``` php
 rails server
 ```
説明: Railsアプリケーションをローカルで実行するためのコマンドです。http://localhost:3000でアプリケーションを確認できます。
 ``` php
 rails generate scaffold [モデル名] [カラム名:型, ...]
 ```
説明: モデル、ビュー、コントローラなどの基本的なCRUD機能を一括で生成するコマンドです。開発初期によく使用します。
  ``` php
 rails db:migrate
 ```
説明: データベースのスキーマを最新の状態に更新するためのコマンドです。新しいマイグレーションファイルを適用します。
 ``` php
 rails console
 ```
説明: RailsアプリケーションのコンテキストでインタラクティブにRubyコードを実行できるコンソールです。モデルの操作やデバッグに便利です。
 ``` php
 rails routes
 ```
説明: アプリケーション内で定義されているルーティングを確認するためのコマンドです。どのURLがどのコントローラとアクションに対応しているかを一覧表示します。
 ``` php
 rails db:seed
 ```
説明: データベースに初期データを投入するためのコマンドです。db/seeds.rbファイルに定義したデータを反映します。
 ``` php
 rails test
 ```
説明: テストを実行するためのコマンドです。アプリケーションの動作が期待通りかどうかを確認するために使用します。
 ``` php
 rails db:rollback
 ```
説明: 最後に実行したマイグレーションを取り消すためのコマンドです。データベースの状態を前のバージョンに戻すことに役立ちます。
 ``` php
 bundle install
 ```
説明: Gemfileに記述されたgem（ライブラリ）をインストールするコマンドです。Railsプロジェクトで必要なライブラリを一括で導入します。

```php
bin/dev
```
説名: bin/devは、Rails 7以降で導入された新しい開発ワークフローであるforemanなどのプロセス管理ツールを利用して、複数のプロセスを一括で管理・起動するためのコマンドです。通常、ProcfileやProcfile.devに記述された複数のサービス（Railsサーバー、Webpack、Job Queueなど）を一括で起動します。

以上になります！
最後まで見ていただき、ありがとうございます！
では、次の記事で〜！
VSCodeからReact環境構築～HelloWorldまで

# 以下サイトを参考に作業
非常にわかりやすかったです。基本、こちらに沿っていけば問題なくHelloWorldできると思います。
参考：[【VSCode】Reactを環境構築してHello Worldする方法  |  いなかdeMac](https://inakademac.com/react-hello-world/)

個人的に引っかかったところだけ、参考までに残しておきます。
## npx create-react-appでエラー

```jsx
PS D:\_work\svr\react_test> npx create-react-app react-test
npm error code ENOENT
npm error syscall lstat
npm error path C:\Users\ユーザー名\AppData\Roaming\npm
npm error errno -4058
npm error enoent ENOENT: no such file or directory, lstat 'C:\Users\ユーザー名\AppData\Roaming\npm'
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm notice
npm notice New patch version of npm available! 10.8.1 -> 10.8.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.2
npm notice To update run: npm install -g npm@10.8.2
npm notice
npm error A complete log of this run can be found in: C:\Users\ユーザー名\AppData\Local\npm-cache\_logs\2024-08-15T20_52_01_113Z-debug-0.log

```

## npm updateでググって「プラグインでupdateするといいよ、今のver確認して」など出てきたのでとりあえず確認
```jsx
PS D:\_work\svr\react_test> npm list --depth=0 -g
npm error code ENOENT
npm error syscall lstat
npm error path C:\Users\ユーザー名\AppData\Roaming\npm
npm error errno -4058
npm error enoent ENOENT: no such file or directory, lstat 'C:\Users\ユーザー名\AppData\Roaming\npm'
npm error enoent This is related to npm not being able to find a file.
npm error enoent
npm error A complete log of this run can be found in: C:\Users\ユーザー名\AppData\Local\npm-cache\_logs\2024-08-15T20_56_16_332Z-debug-0.log
PS D:\_work\svr\react_test> npm list --depth=0 -g
C:\Users\ユーザー名\AppData\Roaming\npm
└── (empty)
```

## 'C:\Users\ユーザー名\AppData\Roaming\npm'ディレクトリが無いよとのことで、エクスプローラから作成
※これすみません、ターミナルからmkdirできるんですね…。
```jsx
PS D:\_work\svr\react_test> npx create-react-app react-test
Need to install the following packages:
create-react-app@5.0.1
Ok to proceed? (y) y
```

## yしてとりあえず成功
- src/App.js開いて編集後、localhostでf5押したらアクセスできず
- ググったけどようわからん
    - wslの再起動やってみたけど反応あったのかわからん
- 結局ターミナルから再度npm start叩いたらいけた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251777/befbc4d2-80e9-63ef-982b-b3011de378ce.png)

## 所感とか
- ターミナル全然慣れてないのでそこら辺で躓く
- とはいえCUI慣れればめちゃくちゃ便利な予感はしてる
- 最近のHelloWorldはデフォルトがリッチでかっこいい

## 次回予告
tailwindCSS使ってポートフォリオ的なやつ模写します。
【React】要素をサイズ変更時に再レンダリングする方法

以下のように記述すると要素のサイズが変更された際に再レンダリングされます。

```jsx
// ...

export function Sample() {
    const ref = useRef(null)
    const [height, setHeight] = useState(0)
    
    useEffect(() => {
        const element = ref.current
        const observer = new ResizeObserver(() => {
             setHeight(element.offsetHeight)
        })
    
        if (element) {
             observer.observe(element)
        }
    
        return () => {
            if (element) {
                observer.unobserve(element)
            }
        }
    }, [])
    
    return <div ref={ref} />
}

```

https://developer.mozilla.org/ja/docs/Web/API/ResizeObserver
【TypeScript】`"xxx" | "ooo" | string` の時、エディタで型推論を効かせる二つの方法

# はじめに
今回は表題の通り以下のようなコードでエディタの型推論を効かせる方法を二つ紹介します。

## コード例
以下の書き方で実現できます。

```ts
type MyProp = 'xxx' | 'ooo' | (string & {});

type MyProp = "xxx" | "ooo" | (string & Record<never, never>);
```

## おわりに
このような書き方はコンポーネントのProps定義でままあるのでとても便利だと思いました。
TSに詳しくなりたい...
AWS App Studioが将来的に使い勝手よさそうな話

ひょんなことから、ノーコードの画面開発ツールで使い勝手がいいものはないか調査することになり、AWS App Studioがちょうどよさそうだったのでその使い勝手の調査と結果報告

# AWS App Studio
ノーコードで画面開発ができ、AWSの様々なアプリと連携できる（DynamoDBのデータと連携可能）
生成AIを駆使して画面作成が可能

↓実際の起動画面はこちら↓
Cognitoの設定だったり、諸々の設定が完了すると下記の画面に遷移できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/d5b86322-c849-6f2c-a29d-c69b35a124a1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/c2c56ffe-0606-15aa-d944-3d296425337a.png)

# 感想
直感的に画面構成ができるので使いやすさや想像しているノーコード開発がここにあるといった感じです！
ただ、まだ日本語化対応されていないため、習熟には慣れが必要になってきます。
下記画像のようにWeb開発をしたことある方はある程度、アイコンからどういう機能が追加できるのか推測できるので習熟は早くなるかもです。
ノーコード開発の練習にはちょうどいいもので、お客様との打ち合わせで急ぎ画面イメージが必要な時なんかにはちょうどいいですね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/d109dbb1-81c4-0a35-9df0-1d76c1d329ee.png)
いますぐ使える即戦力！「シンプル売上管理ツール」～超初心者が作成した「LINEBot」～改良してみた

# 超初心者が作成した「LINEBot」「シンプル売上ツール」を改良してみた
とある流通業で衣料品を販売している私。ITスキルゼロなのに「LINEBot」なるものに出会い、さっそく作成してみた「シンプル売上管理ツール」。

https://qiita.com/A0Ishida2563/items/167f08456535032a3357?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share）


担当スタッフに試してもらうと、「すごい！毎日の売上予算がすぐに分かる！」「昨年実績は調べるの面倒だったから便利！」との好評価。
でも、「これ、スマホのメニューが分かりづらい」「ちょっと日付入力がめんどくさいかな」との声もいただきました。

# 「シンプル売上管ツール」改良版を作成する
それじゃあ、改良版を作ってみよう！ということで、全体のプロセスを見直してみます。

# 見直したところ
## LINE画面の「リッチメニュー」を押すと不要な返答が返ってくる。

![IMG_2430.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/1a7eacb6-c97f-f0a8-691b-792750629d96.jpeg)

### これが最大の分かりにくく使いづらい理由。

「リッチメニュー」に設定したテキストが

![スクリーンショット 2024-08-18 230119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/3aa12aa2-ecfb-6e7b-8c13-3b44406afbed.png)

makeのシナリオをスルーして＜誤入力＞と判断されてしまうのが原因。

そこで「LINEBot」全体の構成を見直して、「売上予算」「昨年実績」とも
LINEの「リッチメニュー」を押すことでスタートするように改良しました。

＊以下の数値は全てダミーです。

## 使用ツール
・LINEmessagingAPI
・LINE Official Account Manager
・Make
・Googleスプレッドシート

# できたもの
### 修正したMAKEのシナリオ
![スクリーンショット 2024-08-18 231340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/ebd3b089-84c5-43e4-3434-c65fd325a906.png)

### LINE画面
![IMG_2431.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/e57cf2d4-970d-dacc-0222-f7bde952c1cf.jpeg)

### LINE動作
https://x.com/WM0nHZAdOaoO0tY/status/1825176595507945910

## 手順
### ①LINEの「リッチメニュー」を修正。
「LINE画面が分かりづらい」との指摘にこたえるため、LINE Official Account Managerの「リッチメニュー」を修正
「リッチメニュー」の【売上予算を知りたい】【昨年実績を知りたい】の２つのいづれかのボタンを押せば
### ＜ボタンを押す＝「トリガー」＞ となって「LINEBot」をスタートさせます。
分かりやすくボタンのアイコンも変更しました。

![スクリーンショット 2024-08-18 220845.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/4427b97b-be44-f04d-42fc-c5315ab90913.png)

### ②makeで「リッチメニュー」の「トリガーテキスト」を排除。
Watch EventsとGoogle Sheetsの間に「fuliter」を設定して「リッチメニュー」の「トリガーテキスト」をブロック。その先のシナリオに進ませない。

![スクリーンショット 2024-08-18 214825.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822083/4d48748a-311e-6351-45f6-f530c3d1e88d.png)

その後は下記の通り、以前とシナリオの変更はありません。

### ③Routerモジュールで「実績」「前年」のルートで分岐
### ④それぞれのGoogleSpreadSheetを経てLINE Send a Reply Message の返信

# まとめ：ちょっとした改良で見やすく・使いやすくなりました！
今回の改良は、問題のあった作動のスタートを分かりやすく
LINE側の「リッチメニュー」から始めるために、
Watch EventsとGoogle Sheetsの間にfilterを入れて「リッチメニュー」の「トリガーテキスト」を排除しただけです。
### それでも「LINEBot」の操作性が格段に向上しました。

使う人の立場に立った、こんな小さな一歩の改良の積み重ねが
「DX業務改善」につながるんだなと実感しました。

今後は、「入力が面倒」とのお声を頂いた「昨年実績」の日付入力設定、「日付＋”昨年”」を単純な日付入力に改善したいと思います。
関数を勉強して再度改良にチャレンジしていきます！

千里の道も一歩から。次の一歩をめざして精進していきたいと思います。

### 乞うご期待！！


参考資料
https://qiita.com/tabisurujapaniz/items/a56e0df499b337806e3f
BEMの書き方ついて

BEMとは、CSSの記述方法論のこと  
`Block` `Element` `Modifier`という3つの概念に沿って設計する手段
クラス名とする`Block` `Element` `Modifier`の単語を`_`や`-`、`__`などで区切ることが特徴
これをセパレートと呼びます

# Block
- 大きい塊。Elementの親要素
- BlockとElementの区切りは、`Block__Element`のように、`__`アンダースコア2つで接続します

# Element
- Blockの子要素
- Modifierとの区切りは、`Element--Modifier`のように、`--`ハイフン2つで接続します

# Modifier
- Blockまたは、Elementに特別な修飾をする要素
- key や value の役割を持ち、BlockやElementから派生させたい場合に使います
- Modifierの命名には形容詞を使用します

# どうやって使う?
BlockとElementはアンダースコア2つで区切る
`block__element`

BlockとModifierはハイフン2つで区切る
`block--modifier`

ElementとModifierもハイフン2つで区切る
`block__element--modifier`

# 採用するメリット
##### 複数人での開発がスムーズになる
BEMはルールがしっかりしているため、複数の人が開発に関わり、長く運用されるプロジェクトに特に向いている

##### 修正対応コストを低減できる
既存ページが変化していくことを前提に考え出された手法なので内容に変更があった場合、その修正対応コストをできるだけ低減することができる

##### コードの再利用性が容易になる
Webサイトを構成するパーツを独立して設計することができるため、コードの再利用が容易になる

##### コーディングルールが明確なので、命名に悩む時間が短縮される

##### コーディングルールに沿っているので可読性が上がる

##### クラス名の重複を防ぎやすくなりる

# デメリット
##### クラス名が長くなってしまう

##### 慣れるまでが大変
??と、?が二回並んでる場合

## 初めに

疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。

## 疑問に思ったメソッド
```
def page_title(title = '')
    base_object = 'aaaa'
    title.present? ? "#{title} | #{base_object}" : base_object
end
```

## 疑問に思ったこと
present?は存在するかどうかというメソッドだが、この二つ目の?は何か。
?を二つ並べることで別の意味を持つのか？

## 調べた結果
present?と?は別の意味を持つ。二つ?が並んでるので2つで意味を持つのかと思ったが、そういうわけではない。
二つ目の?は三項演算子。

**三項演算子とは**
if文の簡略化。簡単なif文ならこちらで省略した方がよい。
条件式? 真の場合 : 偽の場合

## 結論
```
title.present? ? "#{title} | #{base_object}" : base_object
```
の部分は、titleが存在する場合、"#{title} | aaaaで、存在しない場合はaaaaそのまま出力される。
【GCP】データリネージにリストビューが追加された話

# データリネージ
> データリネージは DataPlex の機能で、システム内でのデータの移動（データの送信元、データの通過先、データに適用される変換）を追跡できます。

https://cloud.google.com/data-catalog/docs/concepts/about-data-lineage?hl=ja#lineage-list-view

データがどこから来てどこに送られているのか、GCP内なら簡単に追跡できるので、データウェアハウスの運用保守において非常に重宝します。私は主にBigQueryで利用しています
そんなデータリネージが2024年8月12日に新しくリストビューをリリースしました。
従来のグラフビューとうまく使い分ければ結構便利そうなので紹介します。

:::note warn
本記事執筆時点（2024年8月18日）ではリストビューはプレビュー機能です
:::

# グラフビュー（従来からあったやつ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/f4656c9c-b315-873c-6416-c54445050de5.png)

データリネージを使っている方ならお馴染みのグラフビューです。
長方形がソース、正方形にはプロセスが表示されます。
データの接続が視覚的にわかりやすく、データの流れを簡単に把握することができます。
しかし接続するソースが膨大な数になると見るのが辛くなります。
（あとソース名が長いとグラフが横長になって見づらいです...）

# リストビュー（新規追加されたやつ）
そんな欠点を補うのがリストビューです。

https://cloud.google.com/data-catalog/docs/concepts/about-data-lineage#lineage-list-view

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/56466e60-a37a-c8cd-7752-d2e740935226.png)

基準のソースよりも上流（アップストリーム）と下流（ダウンストリーム）どちらのリネージを見るか選択します。
ソースに接続されたターゲットを一覧で見ることができます。
掘り下げた分析は基準のソースからどれだけ離れているかを意味します。
グラフビューと見比べてみるとわかりやすいですね。

ソースへのリンクになっているのでワンクリックで詳細を見に行けて便利です。
そしてこの表を**CSVでダウンロードできる**のが嬉しいポイントです。

例えば、あるデータソースに不備が見つかり、その影響範囲を調査して表にまとめたいとしましょう。
グラフビューでは一つずつソース名をコピペするしかないです。数十個のソースにつながっていれば、結構な時間がかかります（筆者の体験談です）。
リストビューならCSVを出力すればいいのです。手動のコピペと違って漏れる心配もありません。
表のフォーマットを整えるくらいで済むでしょう。

# まとめ
- 視覚的に把握するならグラフビュー
- 接続されたソースが多ければリストビュー
- リストビューはCSV出力できる
PicoCTF2024 endianness-v2 [Forensics]

## PicoCTF2024 endianness-v2の解き方
初めてWriteUPみたいなものを書きます:fist:

# 問題
Here's a file that was recovered from a 32-bits system that organized the bytes a weird way. We're not even sure what type of file it is.
> 問題へのリンク
https://play.picoctf.org/practice/challenge/415

この問題ではchallengefileというファイルが配布されます。

# 解き方

配布されるファイルの中身をVScodeのHexEditorを使って確認します。

 
https://marketplace.visualstudio.com/items?itemName=ms-vscode.hexeditor

VScodeで対象ファイルを16進エディターで開きます。
すると以下のような表示であることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810599/92b168e1-ce18-22ca-59e9-6478ff8b3456.png)
---
### エンディアン
この問題のタイトルにも入っている「endianness」について復習します。
エンディアンとはメモリにデータを保存するときにどのように配置するかを規定するものです。
今回の問題では、32bitコンピュータについて触れているため4byteをどのように並べるかを定めています。
具体的には以下の通りです。
+ ビッグエンディアン
`0x12345678`のデータを保存する場合には下位アドレスから`12 34 56 78`のように保存されます。
+ リトルエンディアン
`0x12345678`のデータを保存する場合には下位アドレスから`78 56 34 12`として保存されます。
---
###  シグネチャ
シグネチャについて少し触れてみたいと思います。
今回のファイルの場合ファイルの先頭から
```
E0 FF D8 FF ...
```
のようになっています。
ここでいろいろなファイルの先頭がどのような構造について少しだけ書きます。
ほかのファイルについては各自調べてみるといいかもしれません。
```
zip  : 50 4B
png  : 89 50 4E 47
jpeg : FF D8 FF E0
```
---
ここで問題を振り返りましょう。
気づいた方もいるかもしれませんがこの問題で配布されたファイルの中身は先頭から
`E0 FF D8 FF`でリトルエンディアンとビックエンディアンを考えてその中身を変更すると
`FF D8 FF E0`になります。
これは、JPEGファイルのシグネチャと一致します:eyes:
そのため、この問題は4byteごとに反転してJPEGファイルを取得する問題ということがわかりました。

### 配布ファイルからJPEG画像を作る方法
今回は簡単にCyberChefというサイトを使って問題を解いていきたいと思います。

 https://gchq.github.io/CyberChef/

このサイトはBase64のでコードやエンコード、画像の詳細情報(Exif情報)の取得などができる便利サイトです。

Inputの"Open file as input"から今回配布されたchallengefileを選択します。
するとこのような画面になると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810599/c5fa1ac2-4da2-500e-8ee4-e78d45a88eb8.png)

ここからファイルのシグネチャを確認するためにTo Hexを検索し、画面中央のRecipeにドラッグします。するとOutPutがVScodeで確認したような文字が出てきます。
これを4byteずつ反転させたいので「Swap endianness」を検索、ドラッグしてData formatをHex,Word lengthを4 とすることで、4byteずつ反転しOutPut部分がJpegファイルのシグネチャと一致することがわかります。

ただ、これではフラグが何か確認することができません。このデータをJpegファイルとして保存することで確認することもできますが今回はCyberChef上で画像として表示させたいと思います。
そのために「Render Image」を検索、ドラッグします。
ただそのままだと、Invalid file typeとなってしまうのでRender ImageをRawからHexに変更することでOutPutでフラグを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810599/179f9105-3149-b26b-45cc-8b5ddd9fbdd7.png)

みなさんも実際にやってみてください。
NatGateWayをPRG風に説明してみる

## :crossed_swords: はじめに
この冒険の旅路では、AWSのリソースをRPGの世界に置き換えて解説していきます。  
クラウド技術を魔法や武器に見立て、より具体的にイメージしやすくすることで、技術的な理解を深めつつ、楽しみながら学べるように工夫しました。AWSの世界を共に冒険し、クラウドの力を手に入れましょう！
 
## :beginner: 対象購読者
- AWS初心者の方
- 技術的な概念をイメージを使って捉えるのが得意な人
- 具体的な例えを通じて理解を深めたいと考えている方
- RPGが好きな方

## :video_game: RPG風解説

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/0e4cd21f-c57f-e7ad-a62a-7f1b8e6bf4b2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/d3974b8d-c44c-c680-b092-315941fd5b34.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/fd6e013a-5d02-2a37-5759-02713841f0fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/78ab8880-146c-357e-ed20-b5dc74a8d1fe.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/7ace7e1d-4465-0ada-615a-d1234ed23707.png)

## :point_up: 参考
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2933489/bf42e128-635e-5966-9b40-213d2e261ad5.png)


## :ramen: 〆
AWSの世界をRPG風に例えて解説してきましたが、冒険はまだ始まったばかりです。
まったくわからなかったものが「わかったような…わからないような…」というレベルになっていれば幸いです。新しいスキルを手に入れ、クラウドの力を存分に発揮できるよう、次のクエストでお会いしましょう:crossed_swords:あなたの旅が成功に満ちたものになりますように:sparkles::sparkles:
Arch linuxにvivaldiをインストールする恣意的ノート


高機能の色んな面で使いやすいブラウザ、vivaldiをArchLinuxにインストールしました。
```
yay -S vivaldi
```
それと、スマホと認証アプリがあれば要らないですが、vivaldiアカウント作成時の2段階認証手続き用のパソコン用認証アプリ拡張機能Authenticator

https://chromewebstore.google.com/detail/authenticator/bhghoamapcdpbohphigoooaddinpkbai

その他の拡張機能

Super Copy (for copy and paste 必須)
Video Doenloader Plus
Story Saver
Fast Save
Fire Shot
Instagram Video Downloader
【アイディア】しかのここしたんボタン


## 概要

ボタン1を押すと「しか」と言う
ボタン2を押すと「のこ」と言う
ボタン3を押すと「こし」と言う
ボタン4を押すと「たん」と言う

以上

プログラミングの勉強、コーディングテスト、ポートフォリオ、ネタにご利用してください。

素材集めの工数抜きで3分あれば実装できるでしょう。
（組み込みなら別だが）
RailsのModelに定数を用意する

# 概要
* RailsのModelで定数を用意したかった
* そのメモ

# 結論

こうすればよい

```ruby
class MyModel < ApplicationRecord
  MY_CONSTANT = '定数の値'.freeze
end
```

# freezeについて

調べてる感じ、やった方が良さそう。下記ができちゃうので

```ruby
class MyModel < ApplicationRecord
  MY_CONSTANT = '定数の値'
end

MyModel::MY_CONSTANT << '追加の値'  # これができてしまう
puts MyModel::MY_CONSTANT  # => '定数の値追加の値'
```
オブジェクト指向プログラミングとクラスの基本 for Python

## はじめに

プログラミングの世界では、データとそれに関連する操作を効果的に扱うために、**オブジェクト指向プログラミング**（OOP: Object-Oriented Programming）　という概念があります。OOPでは、のブジェクトをモデル化してプログラムを作成することで、コードの再利用性や保守性が向上します。

OOPの代表的な概念のひとつが**クラス**です。クラスは、データ（属性）とそのデータに対する操作（メソッド）をひとまとめにした設計図のようなものです。この設計図から実体である**オブジェクト**を作成し、そのオブジェクトを操作してプログラムを進めていきます。

この記事では、Pythonにおけるクラスの基本的な使い方を説明していきます。

## クラスを作る

まずは、猫を表すクラスを作ってみましょう。このクラスには猫の名前や年齢を保存し、猫が「ニャ～」と鳴く動作を定義します。

```python
class Cat:
    def __init__(self, name, age):
        self.name = name  # 名前
        self.age = age    # 年齢
    ## my_cat = Cat("たま", 2)　←使用イメージCatクラスを呼び出し、名前と年齢を入れる
    def meow(self):
        return f"{self.name} {self.age}才はニャ～と鳴いた"  # 猫の鳴き声を定義
    ## print(my_cat.meow()) ←出力使用イメージ
```

### 用語の解説と注意点

#### `self`
- **`self`とは？**  
  `self`は、クラスの中で定義されたメソッドが、そのクラスのインスタンス（オブジェクト）自身を参照するために使われます。例えば、`self.name`は、オブジェクトの`name`属性にアクセスすることを意味します。
  
- **注意点**  
  `self`は必ずメソッドの第一引数として指定する必要があります。ただし、メソッドを呼び出すときには`self`を明示的に渡す必要はありません。Pythonが自動的に現在のオブジェクトを`self`として渡してくれます。

#### `name`と`age`
- **`name`と`age`とは？**  
  これらは、猫の名前と年齢を保存するための属性（データフィールド）です。`self.name = name`のように、`self`を使ってオブジェクトの属性に値を割り当てます。

- **注意点**  
  `name`や`age`は、クラス内で一貫して使われる属性名です。名前や年齢など、オブジェクトごとに異なる値を持つ情報を保存するために使います。これらの変数名は何でも良いですが、わかりやすく意味のある名前を使うのが良い習慣です。

## クラスの使い方

クラスを使ってオブジェクトを作成し、そのオブジェクトに対して操作を行う方法を示します。

```python
# クラスからオブジェクトを作成
my_cat = Cat("たま", 2)

# オブジェクトのメソッドを呼び出す
print(my_cat.meow())  # "たま 2才はニャ～と鳴いた" と出力される
```

この例では、`Cat`クラスから`my_cat`という名前の猫のオブジェクトを作成し、そのオブジェクトが「ニャ～」と鳴きます。出力は `"たま 2才はニャ～と鳴いた"` となり、`"たま"` の後に空白が入るようにしました。

## まとめ

Pythonのクラスは、データとそのデータに対する操作をまとめて扱うための強力なツールです。オブジェクト指向プログラミングの考え方を取り入れることで、プログラムの構造がより明確になり、再利用性が高まります。

`self`や`name`、`age`といった用語や概念は、最初は少しわかりづらいかもしれませんが、クラスを使って何度も練習することで自然に理解できるようになります。

この記事で紹介したように、クラスを使って身近なオブジェクトをモデル化することで、プログラミングの基本的な考え方を理解することができます。クラスを活用して、より複雑なプログラムにも挑戦してみてください。
PHPStanをインストールして使ってみる

## はじめに

PHPを学習して2か月が経ち、コード量が増えるにつれてエラー原因の特定に時間がかかるようになってきました。そのため、潜在的なバグやエラーを検出できる静的解析ツールを導入することにしました。

## PHPStanとは

PHPStanはPHPの静的解析ツールで、実行ファイルを実行することなくコードを解析し、バグやエラーを検出することができます。

## 導入

公式ドキュメントに従い、Composerを使ってインストールします。PHPStanの実行ファイルはデフォルトで `/vendor/bin` に配置されます。

```bash
composer require --dev phpstan/phpstan
```

## 設定ファイルの作成

PHPStanの設定ファイル (`phpstan.neon`) を作成します。`level` には0から9までの数値が設定可能で、数値が大きくなるほど解析が厳しくなります。記事を参考にすると、レベル8や9は厳しすぎると感じる人が多いようです。今回はレベル6を使用します。

`paths` には静的解析の対象となるフォルダを指定し、`excludePaths` には静的解析を除外したいフォルダを指定します。

```php:phpstan.neon
parameters:
  level: 6
  paths:
    - .
  excludePaths:
    - vendor
```

## 実行

型が一致していないコードを用意して、PHPStanを実行してみます。

```php:sample.php
<?php
function addNum(int $a, int $b): int 
{
    return $a + $b;
}

$result = addNum("10", 20); // 引数の型が不一致
```

次に、以下のコマンドでPHPStanを実行します。

```bash
./vendor/bin/phpstan analyze -c phpstan.neon
```

結果は、引数の型が一致していないというエラーが表示されます。

```
 ------ --------------------------------------------------------------- 
  Line   sample.php
 ------ --------------------------------------------------------------- 
  :7     Parameter #1 $a of function addNum expects int, string given.  
 ------ --------------------------------------------------------------- 
```

また、`composer.json` に以下を追加すると、`composer phpstan` だけで実行できるようになります。

```json
"scripts": {
    "phpstan": "./vendor/bin/phpstan analyze -c phpstan.neon"
}
```

## 参考資料

- [PHPStan公式ガイド](https://phpstan.org/user-guide/getting-started)

## 終わりに

静的解析ツールの真価は、実際に運用する中で実感するものだと思います。高品質なコードを書くために、使い続けられるようにしたいと思います。
kintone APIを使ってデータを抽出する

# kintone APIを使った理由
kintoneで扱っているデータで分析を行いたかったのですが、
UI上の絞り込みでは、`AND`と`OR`が混在するような条件での抽出ができないため、
kintone APIを使ってデータを抽出することにしました。

# コード
コードの全文は以下。

```python
import requests
import pandas as pd
import json

HOST_NAME = ''
KINTONE_APP_ID = ''
KINTONE_API_TOKEN = ''
FIELDS = []
QUERY = ''

def fetch_data():
    url = f'https://{HOST_NAME}/k/v1/records/cursor.json'
    app = KINTONE_APP_ID
    fields = FIELDS
    query = QUERY
    size = 500

    header = {
        'X-Cybozu-API-Token': KINTONE_API_TOKEN,
        'Content-Type': 'application/json'
    }

    # create cursor
    body = {
        'app': app,
        'fields': fields,
        'query': query,
        'size': size
    }

    res = requests.post(url, headers=header, data=json.dumps(body))
    print(res.text)
    message = json.loads(res.text)
    cursor_id = message['id']

    # get records
    records = []
    has_next = True
    while has_next:
        res = requests.get(url, headers=header, data=json.dumps({'id': cursor_id}))
        message = json.loads(res.text)
        records += [
            {key: item[key]['value'] for key in item}
            for item in message['records']
        ]

        has_next = message['next']

    # delete cursor
    res = requests.delete(url, headers=header, data=json.dumps({'id': cursor_id}))
    print(res.text)

    return records

def get_fields():
    fields = {}

    url = f'https://{HOST_NAME}/k/v1/app/form/fields.json'
    header = {
        'X-Cybozu-API-Token': KINTONE_API_TOKEN,
        'Content-Type': 'application/json'
    }
    body = {
      'app': KINTONE_APP_ID,
      'lang': 'ja'
    }
    res = requests.get(url, headers=header, data=json.dumps(body))
    # print(res.text)
    message = json.loads(res.text)

    for code, v in message['properties'].items():
        fields[code] = v['label']

    return fields

def save_to_csv(df, filename='data.csv'):
    df.to_csv(filename, index=False)

if __name__ == '__main__':
    fields = get_fields()
    # print(fields)
    data = fetch_data()
    df = pd.DataFrame(data)
    df = df[FIELDS] # 列ならびかえ
    df = df.rename(columns=fields) # 列を日本語に変える
    save_to_csv(df)
    print("Done")

```

## KINTONE_API_TOKEN
APIトークンの作成方法は以下のリンク先。

[APIトークンの作成](https://cybozu.dev/ja/id/5bf3cd82b7b1c8d1d063511e/#how-to-generate-api-tokens)

## QUERY
クエリの書き方は以下のリンク先。

[クエリの書き方](https://cybozu.dev/ja/id/b05ff19d869f1609a1326dc7/)

## fetch_data
`/k/v1/records.json`でもデータの抽出はできるのですが、欲しいデータは100,000件以上存在するため、カーソルを使う方法を選択しました。


[複数のレコードを取得する](https://cybozu.dev/ja/kintone/docs/rest-api/records/get-records/)
> クエリで検索した結果のレコードが100,000件以上存在するとき、絞り込みは中断されます。
その場合、レスポンスヘッダーの「X-Cybozu-Warning」に「Filter aborted because of too many search results」が追加されます。

### 参考

[（レコードの一括取得）カーソルを作成する](https://cybozu.dev/ja/kintone/docs/rest-api/records/create-cursor/)
[（レコードの一括取得）カーソルからレコードを取得する](https://cybozu.dev/ja/kintone/docs/rest-api/records/get-cursor/)
[（レコードの一括取得）カーソルを削除する](https://cybozu.dev/ja/kintone/docs/rest-api/records/delete-cursor/)
クローンアプリを作ってみたーNetflixクローン⑦

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
nextjsはまだですが、実際のアプリ開発からどう作られていくかを学んでいくためにクローンアプリを開発します。
とは言っても自分で考えることは特になくYoutubeを見てやっていきます。
その中で覚えておきたい部分を分類ごとに記載していきます。なので、その時々に知ったことを小出しにしていく形になります。

前回

https://qiita.com/mr_noppo/items/4dd10edb45d0febd2d77

# 使用したものや事前準備
・Macbook Pro
・Visual Studio Code

# 使用にさせていただいた動画

https://www.youtube.com/watch?v=mqUN4N2q4qY&t=4201s

# Next.jsの知識
### react-icons/bs
良さげなアイコンをサイトから探してクリックするとimport文も提供してくれる

![スクリーンショット 2024-07-04 15.42.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943982/9d4d8f97-441f-78fc-913e-bbf98fde53f4.png)

### onClick={() => signOut()}
関数を下記のように直接渡すと暗黙的にイベントが渡される

```tsx
onClick={signOut}
```

引数が不要な場合、明示的に書く必要がある。
例えばsignOutは引数が任意で指定が入っているため、明示的に書かないとエラーが入る・
```tsx
onClick={() => signOut()}
```

### スクロール判定
addEventListenerで関数を発火する。
アンマウントされた時にクリーンアップ関数を用意する。
```tsx
useEffext(() => {
    const handleScroll = () => {
        if (window.scrollY > TOP_OFFSET){
            setShowBackground(true)
        } else {
            setShowBackground(false)
        }
    }

    window.addEventListener("scroll", handleScroll)

    return () => {
        window.removeEventListener("scroll", handleScroll)
    }
},[])
```

### コンポーネントの非表示
propsでコンポーネントの表示非表示を切り替える
```tsx
const AccountMenu: React.FC<AccountMenuProps> = ({
    visible
}) => {
    if(!visible) return null
...
```

### asyncとawait
処理が完了するまで次の処理を行わない
```tsx
export default async function handler(req:NextApiRequest, res:NextApiResponse) {
...
const movieCount = await prismadb.movie.count()
// movieCountに値が返ってきたら
const randomIndex = Math.floor(Math.random() * movieCount)

const randomMovies = await prismadb.movie.findMany({
    take: 1, 
    skip: randomIndex
})
...
```

# Prismaの知識
### テーブル情報の変更

https://zenn.dev/thirosue/books/49a4ee418743ed/viewer/57d161

schema.prismaのカラムを修正する
thumbbnailUrl→thumbnailUrl

```js
model Movie {
  id String @id @default(auto()) @map("_id") @db.ObjectId
  title String
  description String
  videoUrl String
  thumbnailUrl String
  genre String
  duration String
}
```
保存し下記コマンドを実行

```bash
npx prisma migrate dev --name fix_thumbnail_url_spelling
```

#### mongodbの場合
Prismaの標準的なマイグレーション機能をサポートしていないので下記で実行する
※ファイル修正後
```bash
npx prisma generate
```

```bash
npx prisma db push
```

# 次
まだ
島探し (paizaランク S 相当) を妙な方法で解く

## 問題

https://qiita.com/official-events/9ab96aa95d62fe3cbdd7

昨夜投稿した際にこの企画を知って、

https://paiza.jp/works/mondai/s_rank_skillcheck_sample/search-island

これを面白そうと思ってしまったので、
まあ被らないだろうと思った方法で解いてみました。

行×列のデータ構造とか使いませんよ。


## 説明

コードにも大体説明が書いてあるので、合わせて読むなりしてくださればと思います。

###### 最初の行
行数と列数が書いてあるらしいですが使いません。**捨てます。**

###### 列挙の仕方
これは普通に、1行ずつ、左から順番に見ます。

###### データ構造
データは以下のような構造です。リンク形式のリストで、1行分の情報を繋げて持ちます。

`{ start:開始位置, end:終了位置, id:島ごとのユニーク値, next: 次の構造 } → { start: ... } ...`

###### 「0」の場合
何もしません。飛ばします。

###### 「1」の場合
とりあえず他の行のことは気にせず、左隣が「1」だったかどうかで、
- 直前の構造のendの位置を直すか
- 新たに構造を作るか
を行います。

###### 前の行と隣接している場合
1行前のリストを見て、隣接しているか判定します。
隣接していたとしても、idが同じ(＝島が同じ)場合は何もしません。

隣接していてidが異なる場合は接続処理となります。
idを若い方に合わせて置換するのですが、変更する側は、その行のすべての構造のidを確認して同時に置換します。

###### データはどこまで覚えておくか
1行前のリストは必要なので覚えておきます。
それより前の行のことは忘れてください。

###### 何をもって島の数とするか
「構造を生成した回数」と「前の行と接続した回数」の差が島の数となります。


## コード

```JavaScript:search-island.js
// Copyright © 2024 https://qiita.com/tanin_no_sorani
// Released under the CC0 1.0 Universal license.
'use strict';

let first     = true; // 先頭行を飛ばす用
let before    = null; // 前行の先頭(一番左)の陸地
let created   = 0   ; // 生成した陸地の数
let connected = 0   ; // 接続した回数
let id        = 0   ; // 島ごとに割り振る値

require('node:readline').createInterface({ input: process.stdin }).on('line', line => { // 1行ごと
	if (first) { first = false; return; } // 先頭行は破棄
	
	let current = null; // 現在の行の先頭を記憶
	let left    = null; // 現在位置の左側にある陸地
	
	line.split(' ').forEach((bit, i) => { // 1行の0,1を列挙  bit:'0'or'1' i:この行における位置
		if (bit === '0') { return; } // '0'は何もしない
		
		let land = null; // 今回の陸地
		
		if (left && (left.end === (i - 1))) {
			// 左隣と陸続きの場合
			left.end = i; // endを訂正するだけ
			land = left;
		} else {
			// 新しい陸地 (前行のことは考えずに一旦生成する)
			land = { start: i, end: i, id: id++, next: null }; created++; // 生成してカウント
			if (!current) { current = land; } // この行の最初の陸地だった場合は記憶
			if (left) { left.next = land; } // 左の陸地がある場合はnextで辿れるようにしておく
			left = land; // 次のleftとして今回の陸地を設定しておく
		}
		
		while (before && (before.end < i)) { before = before.next; } // 前行で過ぎてしまった構造は飛ばす
		
		// 前行と陸続きかどうか、それが異なるID(島)か判定
		if (before && (before.start <= i) && (i <= before.end) && (before.id !== land.id)) {
			// 接続処理
			connected++; // 接続した回数をカウント
			
			// 片方の列のIDを置換する処理
			function replace(target, old_id, new_id) {
				for (; target; target = target.next) { if (target.id === old_id) { target.id = new_id; } }
			}
			// 若い方のIDに合わせる
			if (before.id < land.id) { replace(current, land.id  , before.id); } // 前行の方がIDが若い場合
			else                     { replace(before , before.id, land.id  ); } // 現在の行の方がIDが若い場合
		}
	});
	
	before = current; // 現在の行を次の前行とする
})
.on('close', () => { console.log(created - connected); }); // 「生成回数 - 接続回数」が島の数
```

## 感想

このロジックで厄介だったのはID合わせの部分でした。
若い方に合わせる点、まだ参照される可能性のある構造も全部置換しないといけない点が気づきにくく、何度か修正しました。
もう少しスマートな区別方法があるかもしれないですね。