OmniAICreator/Qiita-1.07M huggingface dataset:
プロジェクト全編ほぼモブプロでやってみた

この記事は　[ZOZO #3 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) ６日目の記事になります。

コロナ渦が２年ほど続いていますね。弊社も去年４月からずっとリモートワークです。

そんななか、プロジェクトを進めていくのは本当に困難なことだと思いますが、自分のチームも今年５月から１１月にかけて新規プロダクトを実装し、リリースに漕ぎ着きました。

今回は対面できない中で工夫しながらプロジェクトを進めて来たのでうまくいったこと、いかなかったことを整理できればと思います。

## うまくいった

- ***一箇所に集まって作業するというというお約束***

ツールは色々試しましたが、どれを選択するにせよどこかに集まって作業することで、みんなで同じ作業をするにせよ、分担するにせよすぐ聞ける、すぐ解決するという環境がすごい助かりました。
対面で作業する場合は集中している人には話ずらく、席が離れていればそれも話ずらい。しかしリモートであれば全員が隣の席にいるみたいなもの、ミュートにもしていないのでとても話しやすいです。

- ***できるだけ全員で同じ作業をする（モブプロをする）***

リモートでやるならモブプロがおすすめ。すぐに聞けるというのにも繋がってきますが、全員が集中して同じ課題に取り組むことで、ほぼ悩む時間もなく、レビューもいらず、スムーズにことがすすみます。今回ほぼ全編このやり方でやりましたが、無事予定通りリリース。べロシティを計測していなかったので、効果のほどが数値化できなかったのが残念ですが、直感分担してやるのと変わらないスピードが出ていたと感じています。
品質はさらに全員が見るので分担するよりいいものができていると感じます。

- ***ツールは色々試したがDiscordが今の所ベター***

同じチームのメンバーによる４日目の[@naoya_sの投稿](https://qiita.com/naoya_s/items/b12a69df5f9a53a0682e)でも色々紹介していますが、最終的に続いたのはDiscordでの画面共有。
ブースト機能で画質も良く、画面共有はしやすかったです。チェンネルさえ作っておけばいつでも入れるので参加へのハードルがとても低い。
開発メンバー以外にもチャンネルを知らせておくことで、開発以外の関係者も気軽に色々聞ける場ができました。

また、ポイントでCode With Meを使って一斉にみんなで書きまくるなんてこともしましたが、個人的にはドライバーと他で分けるほうがいいかな。何やっているかわからなくなるので。

- 困ったときのGoogleMeet

リモートワークの難点はネットワーク環境。画面共有してて重くなったり、再起動する必要があったりすることは度々。Discordも例にもれずもうどうにもならないときは場を変えてやってみることもありました。そのとき使いやすかったのはGoogleMeet。
画面共有の画質も問題なく、Discord同様使いやすい。難点は毎度場を作る必要があること。なのでDiscordの避難先として活躍しました。

##  （まだ）あまりよくなかった

- ***Slackのハドルミーティング***

プロジェクト進行中に急にリリースされた機能。期待して使ってみましたが、画質がまだ良くなく、ソースコードを共有するにはちょっと不十分でした。これからですかね。

- ***自宅のネットワーク***

こればっかりはどうしようもない。。。特にMacを何日も立ち上げっぱなしだと次第に重くなり、急に再起動が必要になったり。。。自宅のネットワーク環境は大事。なんとかならないかなぁ。

- ***疲れ***

1日ずっとモブプロやっているととても疲れます。まじで疲れます。定期的に休憩をいれるとか、頻繁にドライバーを変えるとかルールを決めるといいですね。

## まとめ

総じてリモートでモブプロはとてもおすすめです。
続けるにはまずは試してみてメンバーによい実感をもってもらうことが何より大事です。

この記事を参考にぜひチャレンジしてみてください。

明日も自分ですね。fluent bitのタグのお話をしたいと思います。
【4日目】Python初心者が変数の基本を学ぶ

#変数宣言
Pythonでの変数宣言は下記のように行います。

```python:文字列
foo = "test"
print(foo)
```

```python:数値
var = 100
print(var)
```

文字列はシングルクォーテーションでも大丈夫です。
また、文字連結するときは同じ型同士であれば「+」で可能です。
**#**の行はコメントで出力結果イメージ

```python:文字列連結
hoge = 'hello' + ' ' + 'world'
print(hoge)
# hello world
```

文字列と数値を連結しようとするとエラーになるので、取扱には注意です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2343271/8d07cb05-c9cb-6ca6-0557-589ca0477b51.png)

#データ型チェック
~~type関数で変数のデータ型が何か判別できます。~~
【2021/12/5追記】
こちら変数に代入されたデータ型ではなくオブジェクトの型が正しいです。
ご指摘ありがとうございます。

```python
print(type(hoge))
# <class 'str'>
```


#前回の応用

datetime関数を変数に入れて、あれこれと試してみます。

現在日付を入れる。

```python:関数インポート
import datetime
```

strftime関数で曜日を出力できます。

```python:曜日を出力
time = datetime.datetime.now()
print(time.strftime('略称：%a \n' + '正式名称：%A'))
# 略称：Sat 
# 正式名称：Saturday
```

```python:曜日を出力　日本語ver
import locale
locale.setlocale(locale.LC_TIME, 'ja_JP.UTF-8')
time = datetime.datetime.now()
print(time.strftime('略称：%a \n' + '正式名称：%A'))
# 略称：土 
# 正式名称：土曜日
```

【2021/12/5追記】
また、コメントにて教えていただいた方法も共有させていただきます。
Pythonのバージョンが3.8以降ならf-stringというものが使えるそうです。
詳しくは、<a href="https://qiita.com/simonritchie/items/74f544944ee11a226613">こちら</a>の記事に分かりやすくまとめて頂いております。

```python:ver3.8以降
time = datetime.datetime.now()
print(f'{time:略称：%a \n正式名称：%A}')
# 略称：Sun 
# 正式名称：Sunday
```


関数の結果を変数に引き継げるのでうまく使えると可能性が広がりますね。
今日はここまで。

ご一読ありがとうございました。
Hinge Jointでなんとかしてみた話

#はじめに
こちらの記事は[VCI Advent Calendar 2021](https://qiita.com/advent-calendar/2021/vci)の第５日目の記事です。

今回はすぐに忘れてしまうHinge Jointの設定をメモ代わりに書いていこうと思います。
VCI作成者でHinge Jointを使おうと思ったのに、なんもわからん時に見ていただけると嬉しいです。

#VCIでオブジェクトを動かしてみたい

3Dのオブジェクトをバーチャルキャストで動かしてみたいときに、VCIにLuaを入れて動かすのが一般的です。
でも、Luaを入れなくてもそれなりに動くVCIを作ることはできます。

今回はLua無しで、UnityのHinge Jointを使って銃の的を作ったお話です。

#Hinge Jointで何ができる？

Hinge JointはJointの中にある設定でできます。
代表的な使い方は、ドアの蝶番なんかの動きになります。
VCIで有名なのは公式さんのサンドバックが有りますね。

#銃の的を考える

銃の的を作るときは、何かが当たったときにドアが開くようなイメージです。
Luaで作ろうと思うと、当たり判定、角度計算なんかで結構大変です。

UnityのHinge Jointを使うと銃の的をこんな感じで作ることができます。
・銃の弾などが当たると、的が動く
・動いた的がもとに戻る

それだけです。

#銃の的の構成

銃の的のオブジェクトです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/67176861-9605-ce07-3fb1-672cbf387b77.png)

Unityだけで作れる簡単な構成になっています。
TargetBaseがSubItemで土台と棒、Quad01-04が的になっています。

Quadの方は適当なテクスチャを貼り付けて的っぽくしておきます。

#Hinge Jointの設定

Hinge Jointは的の方（Quda01-04）に入れます。
Quad01内のHinge Hointの設定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/ab8c2989-9e90-cea3-0eaf-a1076767883a.png)

Connected Body：今回は土台となる"TargetBase"のSubItemを設定します。土台が親になります。
Anchor：Hingeの回転の根元の座標を設定します。
Axis：回転方向です。今回はY軸を中心に回します。
Auto Conifure…：ここのチェック外してConnected Anchorを設定します。
Connected Anchor：アンカーの位置です。ここは的のY軸の値を入れています。
Use Spring：的が動いた後に自動で戻すのでONにします。
Spring：今回はSpringの強さを0.5で設定しています。
Motor：VCIでは使えません
Use Limits：回転の上限下限を設定できます。
適当に飛ばして。
Mass Scale：的の重さになります（たぶんそんな感じ）、的の値は最小値に設定。
Connected Mass Scale：親側のTargetBaseの重さです。

最後の2個のMassの設定をすることで、TargetBaseをつかんでもプルプルしない設定にすることができます。

#的をもっと多機能にしたい

当たったときにポイントを入れる、当たったときにエフェクトや音を出したい。
なんて思った方は、Luaで作成してください。
的もSubItemで作っているので、判定も簡単に追加できるかもしれません。

#問題点

簡単に作れるものは何か問題があります。
この銃の的は所有権を持ってないとちゃんと動きません。
所有権を持った状態で銃を使ってください。

#おわりに

今回作成した銃の的をTSOにアップしましたのでご参考に。
[銃とかの的](https://seed.online/products/0410dab715148c8bac665b8808f9f674b4084f28497e513400f19ce774825932)
![2021120401055613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/b6182219-3feb-abcb-a343-dbc66ff9037f.jpeg)

Hinge Jointは使い方でいろいろ遊べると思いますので、いろいろやってみてください。
![2021120401072376.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545584/33754874-c091-bfd9-da1f-c7230af50dbb.jpeg)

[TSO にゃふ屋](https://seed.online/users/106600#products)

それでは、まったね～。:blush:
[Flutter] ログインページへリダイレクトさせる方法

# したいこと
Flutterでログアウトした後、ログインページへ遷移させたい。
保持されているルートも削除したい。（戻るをされるとページを戻れてしまうため）

# 実装方法

```dart
// name path の場合
Navigator.pushNamedAndRemoveUntil(
  context,
  '/login',
  (Route<dynamic> route) => false,
);

// page widget の場合
Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute<void>(builder: (context) => const SignInSelectPage()),
  (Route<dynamic> route) => false,
);
```

# 参考
https://stackoverflow.com/questions/45889341/flutter-remove-all-routes
ラズパイで子供の寝相監視をした時のログと、参考にした記事のまとめ【後編】

# はじめに

[前回](https://qiita.com/mickie895/items/dbb7571388264e575ec8)の続き。
ラズパイ上のファイルをWindows上に持ってきて、それを動画にするまで+α

# ラズパイ上にあるファイルのダウンロード方法

ラズパイ上にあるファイルの転送方法はすぐに思いつくのは2つ。

1. WindowsOSを対象とした、ファイルサーバ機能などを提供するSamba
1. とりあえず誰とでも接続できるFTPサーバ

今回はWindows以外と接続する予定がないので、とりあえずSambaを利用することにした。
Sambaのセットアップ方法は[このリンクの記事](https://www.itmedia.co.jp/news/articles/2002/09/news012.html)を参考にした。

これの設定通りコマンドを叩いて、いざ```\\raspberrypi```をエクスプローラのアドレス欄に記入…しても動かない。
WindowsからpingしてみたらIPv6のアドレスが返ってきているため、物理的にはつながっていたようだった。

下記のリンクを見る限り、おそらく正しくIPアドレスが設定されておらず、raspberrypiまで到達できないのが原因のようだ。

http://www.samba.gr.jp/doc/diag.html

ただ、teratermでraspberrypiに接続すればその接続状況がWindowsに保存されるらしく、
接続後はWindowsからファイルサーバへアクセスできた。
Sambaは必ず手動で立ち上げるように```sudo systemctl smbd disable```で自動で起動しないようにしたため、
今の時点ではteratermへの接続が必須な状態は問題なさそうだ。

今後問題が出てから改めてDHCPクライアントや固定IPについては考えることにする。

ここからはCPUをより使う作業になっているため、WindowsPC上で作業を行う。

# 画像ファイルを動画ファイルに変更する

画像ファイルの動画ファイルへの変換はサンプルがたくさんあるが、
個人的に良いサンプルだと思ったのは下記のアドレスのコード。

https://axa.biopapyrus.jp/ia/opencv/videowriter.html

自分はアンパックを生かしたfourccの作成が思いついていなかった。

今回の画像や動画には、下記のような特徴やユースケースがある

+ 暗視状態だと画像が紫色になる
    + グレースケールに変換する
+ 画像のサイズが良くわかっていない
    + 特定の写真を見てサイズを推定することにする
    + 負荷状況で画像のサイズが変わるかもしれないので念の為、3枚目あたりを利用する
+ 速度とか読み出し位置とかを変更して、寝相のわるいところだけ切り出すといったユースケースもありそう
    + 考えられる部分は変数として指定できるようにしておく

これらのことを考えて、次のコードを作って変換することにした。

```python:image_comverter.py
import cv2
from typing import Iterable
import glob
import re


def files2image(images: Iterable[str], write_path: str, sample_image: str, skip: int = 1, flame_rate: float = 30.0):
    if skip <= 0:
        raise ValueError("スキップ間隔間違えていますよ。")

    sample = cv2.imread(sample_image)
    height, width, _ = sample.shape
    writer = cv2.VideoWriter(write_path, cv2.VideoWriter_fourcc(*"mp4v"), flame_rate, (width, height), isColor=False)

    for count, filename in enumerate(images[::skip]):
        color = cv2.imread(filename)
        gray = cv2.cvtColor(color, cv2.COLOR_BGR2GRAY)
        writer.write(gray)
        print(f"\r{count} 枚処理完了", end="")

    writer.release()


if __name__ == '__main__':
    base_path = r"D:\photos"
    dir_name = "1125"
    append = "gray"
    glob_path = f"{base_path}\\{dir_name}\\*.jpg"
    result_path = f"{base_path}\\{dir_name}_{append}.mp4"
    items = glob.glob(glob_path)

    files2image(items, result_path, items[2])

```

結果を表示したいところだけど、流石に個人情報的にまずいと思ったので別の動画を作成してきた。

こんなことできま~~せん~~した

https://twitter.com/mickie_on_Paper/status/1467110240164675590

# おまけ

![スクリーンショット 2021-12-04 213746.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395414/7ae9bf12-142e-80fb-ace6-655d0688d4e8.png)

Aviutilでエンコードし直したらファイルサイズが半分程度になりました(1.5MB→610KB)。OpenCVの動画エンコードはあまり効率が良くはなさそう。
AtCoder Beginner Contest 230

##[A - AtCoder Quiz 3](https://atcoder.jp/contests/abc230/tasks/abc230_a)

O(1)

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    int N;
    cin >> N;
 
 
    if(N>=42) N++;
 
    ostringstream sout;
    sout << std::setfill('0') << std::setw(3) << N;
    cout << "AGC" + sout.str() << endl;
 
    return 0;
}
```

##[B - Triple Metre](https://atcoder.jp/contests/abc230/tasks/abc230_b)

O(N)
シミュレートしました。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    string T, S;
    cin >> S;
    rep(i, 100000){
        T+="oxx";
    }
 
    T.rfind(S) != string::npos ? cout << "Yes" << endl : cout << "No" << endl;
 
 
    return 0;
}
```

##[C - X drawing](https://atcoder.jp/contests/abc230/tasks/abc230_c)

O(N)
配列を用意して全ての要素を生成する事ができません。
必要な部分だけ処理を行います。
コンテストでは計算式通りにif文で分岐をさせました。

```C++:C++
#include <bits/stdc++.h>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define fixed_setprecision(n) fixed << setprecision((n))
#define execution_time(ti) printf("Execution Time: %.4lf sec\n", 1.0 * (clock() - ti) / CLOCKS_PER_SEC);
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll = long long;
using P = pair<int,int>;
template<class T> inline bool chmax(T& a, T b){ if(a<b){ a=b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b){ if(a>b){ a=b; return 1; } return 0; }
 
int main() {
    ll N, A, B, P, Q, R, S;
    cin >> N >> A >> B;
    cin >> P >> Q >> R >> S;
 
    for(ll y=P; y<=Q; y++){
        for(ll x=R; x<=S; x++){
            int ok=0;
            if(y-A == x-B){
                if(max(1-A, 1-B) <= y-A && y-A<=min(N-A, N-B)){
                    ok=1;
                }
            }
 
            if(y-A == -(x-B)){
                if(max(1-A, B-N) <= y-A && y-A<=min(N-A, B-1)){
                    ok=1;
                }
            }
 
            if(ok) cout << '#';
            else cout << '.';
        }
        cout << endl;
    }
 
    return 0;
}
```
Ubuntuを日本語化する

:::note info
当記事の内容はUbuntu 20.04 LTSにて動作確認済みです。
:::
## Ubuntuを日本語化しよう
AWSやLinodeなどでインスタンスを作成すると、タイムゾーンはUTCで言語は英語になっていると思います。
ログを見たりする際に時間がUTCだと不都合なので、日本語に設定しましょう

## タイムゾーンをJSTに変更(デフォルトはUTC)

```bash
#dateで現在の時刻を確認
date
Fri 03 Dec 2021 11:58:24 PM UTC

#タイムゾーンを日本時間(JST)に変更
sudo timedatectl set-timezone Asia/Tokyo

#dateで現在の時刻を確認
date

#タイムゾーンがJSTになっていたらOK
Sat 04 Dec 2021 09:00:12 AM JST
```

## Ubuntuを日本語化

```bash
#日本語パッケージをインストール
sudo apt-get install language-pack-ja-base language-pack-ja

#日本語に変更
localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"

#localectlで現在の言語設定を確認
localectl

#LANG=ja_JP.UTF-8になっていたら日本語化されています
LANG=ja_JP.UTF-8
```
## お疲れ様でした！
【Linux】cutコマンドのオプション別パフォーマンス対決

# はじめに

この記事はLinux Advent Calendar 2021の9日目の記事になります。
昨日は@kimullaaさんの記事でした。時間が許す人はぜひそちらもチェックしましょう！

# やりたいこと

通っている大学の課題で`date`コマンドの結果の一部を`cut`コマンドで抽出する機会がありました。やっていることはシンプルで`date`コマンドの結果をパイプで`cut`コマンドに渡して範囲選択して良い感じに日時なり時刻なりを取り出しているだけです。課題自体はつつがなく終わったのですがLinuxのコマンドというのはどれもオプションがめちゃんこ多いことが気にかかりました。

***もしかしたら課題で提出した以外のやり方の方が速いこともあるのでは？...と。***ということで課題として私が提出した書き方と同じ出力結果を返す別の書き方を両方計測して結果を比較してみよ〜というのがこの記事でやりたいことです。なお、この後すぐ本題に入ります。コマンドやオプションそのものの解説は記事ではしていないのでもし必要であれば以下の参考資料をお手元で開いておくことをお勧めします。

[cutコマンドの参考資料](https://atmarkit.itmedia.co.jp/ait/articles/1610/31/news026.html)
[dateコマンドの参考資料](https://www.server-memo.net/tips/command/date/date.html)

# 年月日と曜日編

## 期待する出力
![スクリーンショット 2021-12-04 19.17.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/c4af49bf-bb8e-c271-77d7-2382e366d1de.png)

## 課題で提出してしまった方(cutにd,fオプションを使う)

### ソースコード

![スクリーンショット 2021-12-04 19.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/5c3903f4-34be-9a42-0c43-333b2842b234.png)

### 計測結果

![スクリーンショット 2021-12-04 19.07.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/8f21cb58-5d07-5a61-eaad-22e516fac550.png)

## 別の書き方(cutにcオプションを使う)

### ソースコード

![スクリーンショット 2021-12-04 19.16.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/8839d44e-482b-fe66-8cdc-e8bb73721192.png)

### 計測結果

![スクリーンショット 2021-12-04 19.19.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/a9971026-b4d7-ba40-cba8-cf32f6eca9a8.png)

# 現在時刻編

## 期待する出力

当然この値は現在時刻によって変わります
![スクリーンショット 2021-12-04 19.28.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/e0010e30-f2e7-98a1-d3ac-fade44a97938.png)

## 課題で提出してしまった方(cutにd,fオプションを使う)

### ソースコード

![スクリーンショット 2021-12-04 19.11.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/360e9cfd-2907-b8b7-6a9f-16427b2880ad.png)

### 計測結果

![スクリーンショット 2021-12-04 19.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/65804b6a-b0d8-29b3-c471-bf1a0bbd4a6e.png)

## 別の書き方(cutにcオプションを使う)

### ソースコード

![スクリーンショット 2021-12-04 19.21.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/66dd359b-4eb7-b8d3-a8ce-9ad3a0823dca.png)

### 計測結果

![スクリーンショット 2021-12-04 19.23.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893208/5b3d4510-504a-ceea-5c5b-dcab12f82098.png)

# 結果・感想

はい。完全にやらかしました。計測結果のrealを見てみると「年月日と曜日」と「現在時刻」の両方とも大学に提出したソースコードよりも提出した後から思いついた書き方の方が1秒強ほど早く処理が終わっています。(つまり`c`オプションの方が今回は優秀。)

残念ながら再提出はできません。かなしみ。10000回繰り返して1秒強程度の差でも塵も積もれば山となるでなかなかばかにできせんね。

またこれは個人的な直感ですが、「なんとなく」1文字で範囲を指定する`c`オプションの方が文字の塊単位で範囲を指定する`d,f`オプションよりも計算コストがかかりそうだと思っていました。しかし結果は逆だったのでやはり気になったことは確かめてみると面白いこともあるものだなぁと思いました。

こうなる理由ははっきりしていませんが、`c`オプションに比べて`d,f`オプションが比較的遅いのはデリミタで文字列を区切る手間が入っているからなのではないかと私は推測しています。別の見方やご意見、間違いの指摘などコメントくださるととても嬉しいです。
Qt複数Widgetの切り替え

複数Widgetの切り替えの方法です。
Stacked Widgetというものを使用するとその中に複数のWidgetを持ち,外部のSignalからページの切り替えができます。

作成したGUIは以下のようになります。
今回は簡単にページ切り替えのSignalをSpin Boxから与えています。

![stacked_widget.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/1349d9c8-aa70-b090-5fda-91810e19d0cd.gif)

Qt Creatorを使うと簡単に作成できるので興味のある方はお試しください。

作成手順はYouTubeにQt Creator上げましたのでよろしければご覧ください。

https://www.youtube.com/watch?v=GgtM6dCcqiQ
【見切り発車】Generative NFT を売る①【準備編】

## はじめに
今年の NFT締めとして、ジェネレーティブ NFTを作って売るまでの過程を、３回に渡って書いていこうと思います。Adventカレンダーのクリスマス気分に浮かれた、まとまりのない記事になるかもしれませんが、どうぞお付き合いくださいませ。

で、１回目となる今回は、「準備編」として、ジェネレーティブ NFTの作り方の基本と、どの方向性で売るかを考えてみます。
じゃぁ、やってまいりますか！

## Generative NFT とは？
大量生成した画像などをもとにした NFTです。

例えば女の子のイラストを例に考えてみましょう。
髪型、服装、メガネなどの装飾品といったパーツを別々に作成しておき、それらをバラバラに組み合わせて色々なバリエーションの画像を作成します。で、大量にできた画像を NFTとして自前サイトで一次販売し、その後は OpenSeaなどのマーケットで二時流通させるのが定番の売り方です。

ジェネレーティブという名前の通り、NFTにひもづくコンテンツがなんらかのシステムで生成されるため販売数が多く、供給量は 10000点前後になるケースが多いです。

## 売るまでにどんな作業が必要なの？
基本的な作業は下記となると思います。

・コンテンツ（画像など）の大量生産
　なんらかの方法でコンテンツを大量に作り出す仕組みが必要です。
　どのようなコンテンツを、どのように作りだすのか？
　ジェネレーティブ NFTのコアとなる作業です。

・コンテンツに紐づくメタデータ
　OpenSea等でNFTの情報を正しく表示するためのデータが、コンテンツとは別に必要です。
　生成されるコンテンツ１つ１つに対応したメタデータが必要となるため、コンテンツ生成時にメタデータも同時に生成されるような実装が理想です。

・コンテンツとメタデータのアップロード
　特に理由がない限りは IPFSへアップロードするのが無難です。
　大量の素材を扱うことになるため、フォルダ単位でアップロードできる [PNATA](https://www.pinata.cloud)がお勧めです。

・NFTを供給するスマートコントラクト
　NFTを大量に売りさばくためのスマートコントラクトが必要です。
　スマートコントラクトで販売期間や値段、一度に購入(MINT)できる最大数などを調整します。
　売り方によっては、SNS等での集客へつなげるために、giveaway等の機能を組み込むことになります。

・販売サイトの作成
　NFTの一次販売を行うサイトの作成が必要です。
　ユーザーのウォレットと接続して、NFTのミントができることが最低要件となります。
　売り方によっては、ここでロードマップを掲載して NFTの提供後のスケジュールを詳細に記載することになります。

とりあえず、以上の作業が終われば「ジェネレーティブ NFTを売る」という目標は達成したことになります。とはいえせっかく売るのですから、どうやったら「売れる」かも考えてみましょう。

## ジェネレーティブ NFTの売り方
個人的な考えですが、ジェネレーティブ NFTの売り方には、大きくわけて３つのパターンがあると思います。

1. 見返りで売る = 投資家向けの売り方
2. コミュティで売る = ファン向けの売り方
3. アイデアで売る = コレクター向けの売り方

### 見返りで売る
ターゲットは「投資家」となります。

販売する NFTが将来的にどれだけの価値を生み出すかをアピールして売るパターンです。サイト上でホワイトペーパーやロードマップを公開して、NFTを中心としたプロジェクトの青写真を全面に押し出します。

例えば、
「ゲームが完成したら、この NFT所有者は超有利に遊べますよ！」
「コミュニティが盛り上がったら、この NFTの所有者には特別な役割が与えられますよ！」
「このプロジェクトがうまくいったら、この NFTの保有者には報酬が支払われますよ！」
といった感じです。

後々の転売益が購入者の目的であり、IPOや ICO的な売り方に近いイメージかと思います。シビアな投資家さんのお眼鏡にかなう計画と、説得力のある組織図等を提示できないと、売り逃げのような結果に陥るリスクをはらむ販売方だと思います。

### コミュニティで売る
ターゲットは「ファン」となります。

なんらかのプロジェクト(キャラクタや世界観)を立ち上げ、SNS等でファンを集め、コミュニティとして大きくなった頃に、関連する NFTとして売るパターンです。また、すでに十分名の知れたクリエイターさんの作品をジェネレーティブとして NFT化し、そのままファンの人たちに売るパターンも考えられます。

ファンの人たちがそのまま購入者につながるため、とても平和で納得感のある売り方だと思います。

### アイデアで売る
ターゲットは「コレクター」となります。

NFTの作りや見せ方に、今までにないアイデアを盛り込むことで売るパターンです。NFTに組み込まれたデータによって見た目が変わる等、表現を生成するという意味で、まさにジェネレーティブNFTといえる存在です。

アイデアとそれを実現にこぎつける工夫が必要な上、パッと見て「新しい！」と思わせるキャッチーさが勝負の売り方だと思います。

## どの路線で売るの？
当然「アイデア」一択です（消去法で...）。
とりあえず、メモ帳に書いてある「お風呂キャット」か「ヒエログリフ」のどちらかをこねくり回そうと思っています。

## どのチェーンで売るの？
Ethereumは[４月に爆死して](https://qiita.com/hakumai-iida/items/c5d1c47499bbfe5d2b30)懲りてますから、今回は別のチェーンにしようと思います。噂では、Solanaが良さげなので、勉強しつつチャレンジしてみたいと思います。

では、基礎編はここまでです。
[２回目](https://qiita.com/hakumai-iida/items/c9ec2f964f71d0c22e13)でお会いしましょう。
JavaでABC230(B問題まで)

ABC230に参加しました。解答できた問題に関して投稿していきます。

使用言語はJavaです。

#A問題
https://atcoder.jp/contests/abc230/tasks/abc230_a

####方針
1. 入力される値(Nとする)によって処理を分岐させる。具体的には42 ≦ Nであれば、"AGC0" + (N + 1)と出力する。N < 10であれば、"AGC00" + Nと、それ以外の場合は"AGC0" + Nと出力する。


####コード
**標準入力と出力のコードは省略しています。(以下略)**

```Main.java
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.NoSuchElementException;

public class Main {
	public static void main(String[] args) {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);

		int n = fs.nextInt();
		if(n >= 42) {
		    out.println("AGC0" + (n + 1));
		}else if(n < 10) {
			out.println("AGC00" + n);
		}
		else {
			out.println("AGC0" + n);
		}


		out.flush();
		fs.close();
	}

}

```

#B問題
https://atcoder.jp/contests/abc230/tasks/abc230_b

####方針
1. "oxx"を100回くらい繰り返した文字列を用意する。(Tとする。)
2. 与えられる文字列(Sとする)として、Tに対してSが含まれているかcontainsメソッドを使って判定する。

containsメソッドに関してはこちらを参考までに

https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/String.html#contains(java.lang.CharSequence)



####コード

```Main.java
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.NoSuchElementException;

public class Main {
	public static void main(String[] args) {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);

		String tString = "oxx";
		for(int i = 0;i < 100;i++) {
			tString = tString.concat("oxx");
		}

		String s = fs.next();

		if(tString.contains(s)) {
			out.println("Yes");
		}else {
			out.println("No");
		}


		out.flush();
		fs.close();
	}

}



```

C問題は解けなかったので、解説を参考にしながらコードを書いてみたいと思っています。

2完ですが、レーティングが上がってほっとしています。

ありがとうございました。

#参考文献
https://qiita.com/p_shiki37/items/a0f6aac33bf60f5f65e4

https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/String.html#contains(java.lang.CharSequence)
Google Cloud の コトハジメ～その②：Googleアカウント作成～

Google Cloudを使うには何よりもまず、Googleアカウントを持っていないと始まりません。
Googleアカウントと言えば、

「　@gmail.com　のアカウントだな。」

と思う人は多いでしょう。
もちろん答えは、**Yes**です。ですが、それだけではありません。

* 仕事で使うのに@gmail.comのアカウントは抵抗があるな
* そもそも会社でフリーのメールアカウント利用は禁止されている
* たくさんアカウントIDが増えるのは嫌だな
* カスタムドメイン（企業ドメイン）のメールアドレスをアカウントにしたい

と言ったお話をよくいただきいます。
そこで今回は、企業ドメインのメールアドレスでGoogleアカウントを作成する方法をご紹介します。

**注意①：もちろんGmailに企業ドメインのメールボックスができるわけではありません。**
**注意②：企業ドメインでGmailを利用している方はすでにGoogle Cloudがそのアカウントで利用できます。**

# 1. 準備
Googleアカウントを作成するために必要な情報を準備しましょう。

| 項目 | 説明 | この記事で使用する値 | 省略可 |
| :-- | :-- | :-- | :-- |
| 姓名 | これは大丈夫ですね。| 情報 太郎 | |
| メールアドレス | **メール受信可能な**メールアドレス | j-taro@company.com | |
| パスワード | 半角英数字、数字、記号を組み合わせて8文字以上 | 任意 | |
| 電話番号 | 2要素認証などが必要な場合には必要（SMS受信推奨） | 0123456789 | ◯ |
| 再設定用メールアドレス | パスワードを忘れた場合など、復旧用のGmailなどの予備アドレス | j.taro.99999@gmail.com | ◯ |


# 2. Googleアカウント作成開始
以下URLにアクセスします。
https://accounts.google.com/SignUp?hl=ja
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/185233bc-9f75-56f1-e286-f2166c6fe60c.png)

## 2.1. 姓名を入力
画面指示に従って姓名を入力しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/baf80748-2e71-1e91-3d66-b75f1bb0fdb3.png)

## 2.2. メールアドレスを入力
ここがポイントです。
（というかここだけがポイントで他は普通のアカウント登録と変わりません。。）
上の画面真ん中にある

「**代わりに現在のメールアドレスを使用**」

をクリックします。
すると@gmail.comが消えて、任意に指定できるようになりますので企業ドメインのメールアドレスを入力します。
パスワードも入力して「**次へ**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/c558b507-91fa-8de1-b9b9-6e5375ffd0b4.png)
※「**代わりにログイン**」は既存のGoogleアカウントでログインしようとするだけですので気にせず。

## 2.3. メールで送られたコードを入力
設定したメールアドレスで受信したコードを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/7f2c54e1-006b-e234-cb3b-0afbaf4f2770.png)

## 2.4. その他必要情報を入力
電話番号・再設定用のメールアドレス・生年月日・性別を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/805664b3-bcd6-5c8a-1206-9f284b8372fb.png)
※設定した電話番号が何に利用されるかは以下URLを参照してください。
https://support.google.com/accounts/answer/3463280?hl=ja&co=GENIE.Platform%3DDesktop

## 2.5. 利用規約に同意
利用規約を確認し、「同意する」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/3f83be4c-3224-81a5-2907-8ce310e0e53f.png)
※「その他設定」で必要な設定を実施する。後でも変更可能。

## 2.6. Googleアカウント登録完了
以下画面が表示されれば登録完了です。
ここまでできたらGoogle Cloudのプロジェクトを作成しましょう！それはまた今度。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340961/872b9c6a-705e-1a35-ad08-d9ebd7d3e5c1.png)
ubuntu 20.04.3 LTS でeBPFをインストール

# 環境
マシン　conohaの最小構成
OS　　　Ubuntu 20.04.3 LTS

# やり方
今回はパッケージからインストールするとバージョンが古すぎる為、ソースからコンパイルする方法を行います。

1. 依存関係を持つアプリケーションをインストール
1. BCCのインストールとコンパイル

# 依存関係を持つアプリケーションのインストール
```bash
sudo apt install -y bison build-essential cmake flex git libedit-dev   libllvm7 llvm-7-dev libclang-7-dev python zlib1g-dev libelf-dev libfl-dev python3-distutils
```
# BCCのインストールとコンパイル

## BCCのリポジトリをクローン
```bash
git clone https://github.com/iovisor/bcc.git
```
実行後はbccディレクトリが作成される

```bash
~$ ls
bcc  hello.txt
```

## bcc配下にbuild用ディレクトリを作成
```bash
..mkdir bcc/build
cd bcc/build
```

## bccのビルド,インストールを行う
```bash
cmake ..
```
実行後、makeファイルや各設定ファイルが作成される

```bash
~/bcc/build$ ls
CMakeCache.txt  cmake_install.cmake  examples       Makefile  src    tools
CMakeFiles      CTestTestfile.cmake  introspection  man       tests
```
cmakeで作成されたmakeファイルを基に、コンパイルを行う

```bash
make
```

makeでコンパイルしたアプリケーションをインストールする

```bash
make install
```

# Python3のビルド?ライブラリのビルド？
Python3を使ってeBPFのコードを変換を行いバインドを行うので、必要

何を行っているのか要検証

```bash
cmake -DPYTHON_CMD=python3 ..
```
実行後、makeファイルや各設定ファイルが作成される

```bash
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  CTestTestfile.cmake  examples  install_manifest.txt  introspection  Makefile  man  src  tests  tools
```

python用のソースコードからコンパイルとインストールを行う

```bash
pushd src/python/
make
sudo make install
popd
```

# テスト
インストールが実際にできたテストする
https://github.com/iovisor/bcc/blob/master/examples/tracing/hello_fields.py を使用する

```python
#!/usr/bin/python
#
# This is a Hello World example that formats output as fields.

from bcc import BPF
from bcc.utils import printb

# define BPF program
prog = """
int hello(void *ctx) {
    bpf_trace_printk("Hello, World!\\n");
    return 0;
}
"""

# load BPF program
b = BPF(text=prog)
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello")

# header
print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE"))

# format output
while 1:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    except ValueError:
        continue
    except KeyboardInterrupt:
        exit()
    printb(b"%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))
```
このコードは、cloneのシステムコールを検知して標準出力に表示するソースコードです。

出力結果が下記のようになれば成功です。

```bash
$ sudo -E python3 hello_field.py 
TIME(s)            COMM             PID    MESSAGE
2790412.579803000  <...>            232728 Hello, World!
2790412.584491000  <...>            293749 Hello, World!
2790412.586786000  <...>            232728 Hello, World!
2790412.590722000  <...>            293751 Hello, World!
2790412.603958000  <...>            232728 Hello, World!
2790412.607811000  <...>            293753 Hello, World!
2790412.610399000  <...>            293754 Hello, World!
2790412.615617000  <...>            293754 Hello, World!
2790412.618347000  <...>            293754 Hello, World!
2790412.620822000  <...>            293754 Hello, World!
2790412.623829000  <...>            293754 Hello, World!
```





# 参考文献
この記事は下記のサイトを参考に書いています
[eBPF入門](https://zenn.dev/masibw/articles/068bdfe5edee17)
https://github.com/iovisor/bcc/blob/master/INSTALL.md
gatsby-plugin-typegenでTypeScript化したgatsby-node.jsで呼び出したGraphQLにも型を生成するための対策

gatsby-plugin-typegen を使うことで build 時に GraphQL の型生成ができます。
しかし、 gatsby-node.js 側で呼び出した GraphQL に対しての型生成は行われません。
そのためにやったことを紹介します。

そもそも gatsby-node.js をTS化するやり方に関しては<a href="https://zenn.dev/ryo_kawamata/articles/gatsby-ts-2020">Gatsby.jsのTypeScript化 2020</a>の記事がわかりやすいです。
（gatsby-node.js側にtsファイルをimportすることによってTypeScript化しています。自分もこのやり方を採用）

## ダミーページで GraphQL を呼び出す
アナログな手法なのですが gatsby-node 側で呼ばれないのであればコンポーネントおよびpageディレクトリのファイルで呼び出します。

```dammy.tsx
import React, { VFC } from 'react';
import { graphql } from 'gatsby';

const Hoge: VFC = () => {
  return (
    <>
     // 省略されたJSX.Element
    </>
  );
};

// 実際には使わないし引数として受け取ったりしないがdammyとして記載しておく
export const query = graphql`
query HogeTable {
  allHoge {
    edges {
      node {
        data {
          createdAt
          descIconImg
          description
          publicUrl
          fullName
          refFullName
          refUnitName
        }
      }
    }
  }
}
`;

export default Hoge;
```

この状態で gatsby build に成功すれば 型 HogeTableQuery のような名前で 
 src/__generated__/gatsby-types.ts にデフォルト設定として生成されています。

## プラグインが gatsby-node.js 側での型生成に対応していない
<a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-typegen/#emit-schema-as-graphql-sdl">Gatsby公式サイト - gatsby-plugin-typegen</a>の詳細を見てもnode側の型生成に対応してないことが記載されています。

いつか誰かがコミットしてくれるかもしれないので入れ違いにならないようチェックしてみてください。

## gatsby-node.jsに関わるおまけの小ネタ
gatsby-nodeでcreatePagesを使ってページを生成するとページはできているしテンプレートも読み込まれているしTS設定周りとかも何度も確認したけれどページにテンプレートがあたっていない問題にぶち当たったんですが結果としてそれぞれのslugに小さいスペース入っていたことが原因でした。trim()で解決。

```gatsby-node/index.ts
createPage({
            path: `/hoge/${slug}`, // string型のslugデータ末尾に小さいスペースが入っていることに気がつかなかったのでページが生成されなかった（おそらく空白スペース入りのURLとしては生成されていた）
            component: testComponent,
            context: {
              post: hogedata,
           },
   });
```

エラーとして拾われないのでわからなかったけれどソースデータ側でtrimができていなかったりするとこういうこともありますという事例です。
UbuntuのUnityでカメラ入力を扱う方法

# 目標
UbuntuのUnity(デスクトップ環境じゃなくてゲームエンジンのほう)で, Webカメラからの入力をカメラに表示する.

# 環境
Ubuntu 20.04 LTS
Unity 2020.3.16f1

# カメラ入力のフォーマットの変換
私が使用しているWebカメラのフォーマット, mjpegにUnityが対応していないようで, そのままではUnityで映像入力として扱うことができませんでした. そこで, ffmpegを使ってv4l2loopbackによる仮想カメラを経由してUnityに映像を渡すことにしました.
私はどちらも導入済みでしたが, まだの方は,

* ffmpeg: `sudo apt-get install ffmpeg`
* v4l2loopback: https://qiita.com/skyfish20ch/items/b1a29dd03bf2808ea59c (追加でv4l-utilsも使うので, `sudo apt-get install v4l-utils`あたりで導入してください)

あたりで導入してください.
これで必要なものが揃いました.

では, まずは仮想デバイスを作ります.
`sudo modprobe v4l2loopback devices=1 exclusive_caps=0`で仮想デバイスを作成し, `v4l2-ctl --list-devices`で現在のデバイスの一覧を確認します. すると, 接続されているWebカメラの他に以下のようなデバイスが作成されていることが確認できると思います.

```
Dummy video device (0x0000) (platform:v4l2loopback-000):
	/dev/video4
GENERAL - UVC : GENERAL - UVC  (usb-0000:00:14.0-3):
	/dev/video0
	/dev/video1
```
環境によって`/dev/video*`の数字などが違うかと思いますが, 私の場合は上の`/dev/video4`が作成した仮想デバイス, `/dev/video0`がUSB接続のWebカメラを表しています(なぜWebカメラのデバイスが2つあるのかは謎ですが).

次に, Webカメラの映像を仮想デバイスに流します.

```
$ ffmpeg -f v4l2 -i /dev/video0 -vf format=yuyv422 -f v4l2 /dev/video4
```
このように, `-i`のあとにWebカメラ, 末尾に仮想デバイスを指定します. また, Unityが対応しているフォーマットを指定します.

# Unityで映像を流す
シーンにCanvasを追加し, その子要素にRaw Imageを追加します. さらに, 以下のようなスクリプトを作成します.

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class WebCamera : MonoBehaviour
{
    public RawImage rawImage;

    WebCamTexture webCamTexture;
    WebCamDevice[] webCamDevice;
    int selectCamera = 0;

    void Start () {
        this.webCamDevice = WebCamTexture.devices;
        for (int i = 0; i < this.webCamDevice.Length; i++){
            print(i.ToString() + ": " + this.webCamDevice[i].name.ToString());
        }
        this.webCamTexture = new WebCamTexture(webCamDevice[selectCamera].name, 1280, 720, 30);
        this.rawImage.material.mainTexture = this.webCamTexture;
        this.webCamTexture.Play();

	}
}
```
スクリプトは, Raw Imageあたりにアタッチしましょう. そして, アタッチ先のInspectorからScriptのRaw Imageにシーン内のRaw Imageをアタッチします.

さていよいよ実行…ですが, おそらくエラーが出たり, canvasに何も表示されなかったり, 正しく動作しないと思います. 一度ログを見てみましょう. for文の中でのprintの出力は, 以下のようになると思います.

```
0: GENERAL - UVC : GENERAL - UVC  (/dev/video0)
UnityEngine.MonoBehaviour:print (object)
1: GENERAL - UVC : GENERAL - UVC  (/dev/video1)
UnityEngine.MonoBehaviour:print (object)
2: Dummy video device (0x0006) (/dev/video4)
UnityEngine.MonoBehaviour:print (object)
```
この中の, `2: Dummy video device`の`2`が, Unity上での識別番号のようです. そこで, 先程のスクリプトの`int selectCamera = 0;`を`int selectCamera = 2;`に書き換えて実行してみましょう. これでcanvasに映像が出ると思います.
また, うまくやれば, この手動での書き換え操作を処理に組み込めそうですね.

# 感想
最初はOBSのv4l2-sinkで仮想カメラに接続していましたが, 煩わしさを感じたので~~重い腰を上げて~~ffmpegのことを調べてみました. なかなか苦戦しましたが, シェルスクリプトにまとめておくことでスッキリさせることができて満足です.
ffmpegすげえ.

# 参考
https://younaship.com/2019/01/16/unity%E3%81%A7%E3%82%AB%E3%83%A1%E3%83%A9pc-%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%92%E4%BD%BF%E3%81%86%E6%96%B9%E6%B3%95/

https://forum.unity.com/threads/webcamtexture-yuyv-in-videocapture.982866/

https://i-beam.org/2020/05/05/remote-web-camera/

https://trac.ffmpeg.org/wiki/Capture/Webcam

https://stackoverflow.com/questions/60808333/unknown-v4l2-pixel-format-equivalent-for-yuvj420p
プログラミングで最重要なのに誰も教えてくれないデバッグのやり方

# デバッグとは

1. ログをよく読む
2. ログをよく読む
3. ログをよく読む
4. ログをググる、調べる
5. 修正する

デバッグと調べると、デバッガのことやロガーのことばかり出てきますが、それは手法に過ぎません。
デバッグでは、とにかくログの意味を理解していないことがほとんどです。そのままでは、何が問題かわからないまま時間を浪費してしまいます。
ログは英語なので記号に見えるかもしれませんが通常は文章です。正しく読み込めば、何が(Who)いつ(When)どのように(How)何故(Why)何を(What)を起こしているのかが理解できるように作られています。
ログさえ正しく理解してしまえば、自然に調査するべき対象や分析するべき対象、どのように質問すれば良いかがわかります。


こちらの例だと
![スクリーンショット 2021-12-04 20.52.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53443/0bce5e02-cbb9-00d0-80f6-ba024141895b.png)

無理やり当てはめるとすれば
1. What NameError 
2. who indexメソッドが
3. When 2021-11-11 12:18:14に
4. Where home_contoller.rbの11行目で
5. How & Why undefined local variable or method hogehogeが理由で
という感じだと思います。


# 鉄板フロー

1. 再現する
2. ログを出力する
3. ログをよく読む
4. ログをググる、調べる
5. 修正して再現しないようにする

新人は、1→5の順で出来ていません。
大体どうしたら良いのかわかりませんと言われると、

1. 再現出来た?
2. ログは見た?
3. ログになんて書いてあった?
4. ログをググった?
5. バグっている箇所はどこ?

と聞きます。何故コードを見ていないのにわかるんですかと聞かれますが、この順に聞いているだけです。
再現させ、デバッグし、直すというのがフローになります。ログで十分デバッグできることが多いと思います。

# 調査方法
1. 通常のログをよく読んで調査(Railsなら起動画面で確認できる(実態はlog/development.log), 通常はファイルになっているので、tail -f コマンド等を使う)
2. ロガーでログを出力して調査(Railsなら logger.debug(), Cならprintf, goならlog.Print)
3. インタラクティブシェルを使って再現する(Railsならrails c, MySQLならmysqlコマンドのシェル)
4. デバッガを使う(Railsならbyebug等のgem, Cならgdb等, IDEがデバッガを備えていたりします)

これら4つと覚えておくと良いと思います。
Next.js を使い始めて、あれどうやるんだ？をまとめていく

## Sass どう使うんだ？

フロントエンドエンジニアなのでSassをまず使うよね。

https://qiita.com/blanket11/items/2c3218a7c5b7de085a77

## autoprefixer どうするねん？

Sass使える様になったけどいろんなブラウザ様に保管してくれないと、もうワイ仕事できんねん。

### モジュール追加

- postcss-flexbugs-fixes
- postcss-preset-env

を追加する

```
$ yarn add postcss-flexbugs-fixes postcss-preset-env
```

### `postcss.config.js` を追加
プロジェクトフォルダのルートに `postcss.config.js` を追加

▼ postcss.config.js

```
{
  "plugins": [
    "postcss-flexbugs-fixes",
    [
      "postcss-preset-env",
      {
        "autoprefixer": {
          "grid": true
        },
        "stage": 3,
        "features": {
          "custom-properties": false
        }
      }
    ]
  ]
}

```

### 対象ブラウザの指定は、`browserslist`を設定

`package.json`ファイル に `browserslist`を追加

▼ package.json

```
{
// （省略）
  "browserslist": [
    "last 2 version",
    "ie 11"
  ]
}
```

## 静的書き出しってどうやるんだ？

静的書き出しどうするねん。

https://qiita.com/blanket11/items/a2a6ca6e16ba987786e1
Pythonのpsycopg2でCSVファイルからNULLをインポートできない

# 問題
CSVファイルからデータをインポートするときにNULLを入れようとすると怒られる。空文字列、null、NULLでも同じ。

## 環境
Windows10
PostgreSQL14
Python 3.10.0
psycopg2 2.9.2

## テーブル作成
```sql
create table test (id varchar(10), time time);
```

## CSVインポート
ちなみにio.StringIO(文字列)で、open関数と同じようなことがでるらしい。
[公式Document:class io.StringIO](https://docs.python.org/ja/3/library/io.html#io.StringIO)

実際にCSVファイルをインポートするときはopen("/path/to/file.csv", "r")などとする。

```python:csvimport.py
import psycopg2
import io

input = "01,12:34\n02,17:55\n03,"

with psycopg2.connect("dbname=test host=localhost user=test password=test") as conn:
    with conn.cursor() as cur:
        with io.StringIO(input) as f:
            cur.copy_from(f, table="test", sep=",")
```

こんな感じで登録したい。

|id|time|
|--|----|
|01|12:34|
|02|17:55|
|03|NULL|

## エラー内容

```
> python csvimport.py
Traceback (most recent call last):
  File "C:\***\csvimport.py", line 9, in <module>
    cur.copy_from(f, table="test", sep=",")
psycopg2.errors.InvalidDatetimeFormat: time型の入力構文が不正です: ""
CONTEXT:  testのCOPY、行 3、列 time: ""
```

id=03のところのtime（空文字列部分）をNULLやnullにしても同じ。

```
psycopg2.errors.InvalidDatetimeFormat: time型の入力構文が不正です: "NULL"
CONTEXT:  testのCOPY、行 3、列 time: "NULL"
```

```
psycopg2.errors.InvalidDatetimeFormat: time型の入力構文が不正です: "null"
CONTEXT:  testのCOPY、行 3、列 time: "null"
```


# 原因
copy_from関数でnullが、デフォルトでは\\Nっていう値に設定されている。
[公式Document:The cursor class](https://www.psycopg.org/docs/cursor.html)

# 解決方法
copy_fromを呼ぶときにnull="NULL"などとして、CSVのNULLを入れたいところにNULLと書けばよい。

```python:csvimport.py
import psycopg2
import io

input = "01,12:34\n02,17:55\n03,NULL" # NULLを入れたいところにNULLと書く

with psycopg2.connect("dbname=test host=localhost user=test password=test") as conn:
    with conn.cursor() as cur:
        with io.StringIO(input) as f:
            cur.copy_from(f, table="test", sep=",", null="NULL") # 文字列"NULL"をNULLとしてコピー
```

## 結果
修正後のcsvimport.pyを実行したらNULLを含めて登録された。

```
test=> select * from test;
 id |   time
----+----------
 01 | 12:34:00
 02 | 17:55:00
 03 |
(3 行)
```

# まとめ
ドキュメントを読もう、という話ではあるんだけど、言い訳をすると、原因がどこかが分かるまではドキュメントにも行きつかないと思うんですよ。空文字とかNULLって書いたらNULLが入ると思うじゃないですか。（震え声）
環境によって何をNULLとするかは変わるっていう知見が得られた。
ISMS 認証を取得した話(1)

こんにちわ @kotetsu-sr です。

本業はサービス開発者なのですが、ここ1年半くらいはその傍ら社内システムやセキュリティ管理にも携わってきました。社員数100名未満くらいの中小企業の場合、開発者が本業の傍ら社内システムやセキュリティのお守りをすることが多いと思いますが、弊社も例に漏れずそのパターンでした。そんな中、2020年5月からISMS（情報セキュリティマネジメントシステム）認証の取得に向けてプロジェクトチームを組織し、2021年1月にISMS認証を取得しました。認証取得だけでなく社内のセキュリティレベルの向上やシステム環境の改善など、諸々メリットはあったので2年目の継続審査を前にして、これまでを振り返っておきたいと思います。

## SaaSを利用したISMS構築

社内に認証取得ノウハウがない場合、多くは専門のコンサルティング会社にお手伝いしてもらうことが多いと思います。いずれもISMSの認証を取得するための Word や Excel ベースのドキュメントのテンプレートがあり、コンサルタントのアドバイスを受けながら自社に合わせた形でそれを編集する形になるようでした。認証取得までは良いかもしれませんが「ドキュメントの保守運用が大変になりそう」というのが正直な感想でした。だからといって、Git で MarkDown 形式のドキュメントを管理して...みたいなことはエンジニア以外にはハードルが高いので、あまり現実的ではありません。そんなときにISMSについて検索していて、たまたま目にはいったのが SecureNavi という ISMS 認証の取得を支援してくれる SaaS でした。文書のバージョン管理などもこのサービスの中で完結できるので、Word / Excel での苦行を強いられるのよりは良さそうくらいの気持ちでコンタクトを取って話を聞いたところ、自社で SaaS 型でサービスを提供している我々とも相性が良さそうなので、プロジェクトメンバーで話し合って早速導入を決定しました。先日インタビュー記事が公開されたので興味のある方はどうぞ。
<a href="https://secure-navi.jp/voices/sensyn-robotics">
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58490/28f87b46-3302-86d0-906e-9627269cdc28.png)</a>

## 全社の情報セキュリティに対する主体性が向上

SecureNavi を選択したことでまずはプロジェクトメンバーが主体的にならなくては物事が進まないため半ば強制的に主体性を持って活動しました。プロジェクトメンバーが定期的に全社へ情報発信することにより、全従業員への情報セキュリティの意識付けができ、セキュリティに関する質問や相談が増えました。またセキュリティインシデントが発生しても、それを隠すことなく報告できるような空気感になってきたと思います。このように SecureNavi 上でインシデントの管理から、是正処置の管理などを元に改善活動を行っています。
![kaizen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58490/98f2e7f5-065d-d403-b6ba-039aa04851eb.png)

## 各種システムや機器の運用改善が捗るようになった

情報資産を起点にリスクアセスメントとリスク対応を計画することで、対応前後のリスクレベルが可視化することができるようになっています。これにより、これまで不安や不便を感じつつも利用していたシステムの改善も、優先度と具体的な対応計画を明確にして実行することができました。
![risk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58490/2f719662-2e87-1517-c86d-f8a418646510.png)

実際には NAS を廃止してクラウドストレージでファイルを管理を統一したり、Slack の運用ルールを定めるなどを行ってきました。利便性を極力落とさず、セキュリティを考慮した運用するにはそれなりに一筋縄ではいかない部分はあったので、それはまた別記事で紹介したいと思います。
テスト実行進捗報告について

※本記事は、[ベリサーブアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/veriserve) 4日目の記事になります。

どうも、オムそばです。
「ソフトウェアテストなどプロダクトの品質向上にかかわる内容を書いていきます！」というベリサーブアドベントカレンダーの理念に反しちゃうかもしれませんが、今回は「テスト実行進捗報告」についての記事を書きたいと思います。
一応テストに関することだから、許してほしい。(誰に)


#記事の概要

- なぜこのテーマを選んだか
- そもそもの進捗報告の目的とは何か
- テスト実行進捗報告のよくない事例を紹介
- 具体的にどの点が問題かを洗い出す
- 問題に対する解決策の例をあげる

#なぜこのテーマを選んだか

ここ数年、テスト実行進捗報告をあげる立場だったり、受ける立場だったりと、私の仕事は常にこの進捗報告という作業と共にあったといっても過言ではありません。
おかげさまで、報告を受ける側が、どういったところを気にしているか、どういったところにツッコミを入れるかなど、ある程度わかるようになってきました。
ツッコミを受ける立場からすると、せっかく一生懸命データを拾い集めてきて報告しているのに、やり直しになるし、怒られるし、嫌ですよね。
今回の記事では、**"報告を受ける側が気にするポイント"**をご紹介することで、そんな嫌な思いをするテストエンジニアを少しでも減らせればと思っています。

#進捗報告の目的とは何か

当たり前の話ですが、テスト実行に限らず、進捗報告には目的があります。
私が考える進捗報告の目的ですが、<del>"仕事(作業)の出し手に対し、仕事の状況を正しく伝達する"</del>**"仕事の出し手（スポンサー）のみならず、プロジェクト関係者全員（ステークホルダー）に進捗状況を正しく共有すること"**です。(12/6 更新)
何を当たり前のことをと思っている方が多数だと思いますが、実際の現場では、「自分が報告したいことを報告する」人が散見されます。
大切なのは、誰のための報告なのか、だと私は考えております。

#テスト実行進捗報告の例

前段でお伝えした、「自分が報告したいことを報告する」例を一つあげます。

###[前提]

- PRJ責任者に対し、総合テストのチームリーダーが日に1度のテスト実行進捗報告を行う。
- PRJ責任者は実際のテスト現場は基本的に見ておらず、本報告で1日の状況を把握する。

###[報告内容]

- 今日は総合テストを50件実施（実施率5％）しました。
- バグは2件でました。
- 進捗はちょっと遅れ気味です。

#具体的にどの点が問題かを洗い出す

さて、問題ありありの報告だったと思います。
この報告の中にどういった問題が潜んでおり、どう是正していくか、考えていただき、この後の記事を読んで答え合わせをしていただければと思います。


###[問題点]

①全体の件数のうちどれくらい実施したかが明確になっていない。**（テストの全体像が見えない）**
②OK率が報告されていない。**（テスト品質が見えない）**
③報告している件数が当日の実施なのか、累計なのかが不明**（曖昧な記述がある）**
④進捗の遅れが定量化されていない。**（定性的な報告は受け手によって認識がぶれる）**
⑤バグの全体状況が報告されていない。**（テストへの影響が見えない）**
⑥遅れに対するリカバリー計画が報告されていない。**（遅延の解消目途がわからない）**

※他にもあるかもしれませんので、周りの方とぜひディスカッションしてみてください。


#問題に対する解決策の例をあげる

現場によって、ステータスのルールや、テスト管理ルールなどあると思います。
そのため、以下の解決策は一つの例だとお考え下さい。
どうすれば誤解がでないよう、正しく情報が報告を受ける側に伝わるか、それを忘れなければ、例と違う解が出てもよいと考えます。

###[解決策]
①報告は、総件数、予定数、実績数(OK/NGなど) を報告する
②実施率の他に、OK率を報告する
③誤解を生まないよう、複数の意味を持つ言葉を除外する。
　（例：実施数⇒当日の実施数（OK + NG））
④定性的な表現や、主観的な表現は避ける。
　（ちょっとの遅れ⇒0.5人日遅延 or 30件遅延 or 進捗率（80%））
⑤バグの総数、オープン中の件数、今週の発生数。それ以外で、クリティカルなバグを合わせて報告されるとよい。
⑥リカバリー策を立てる。先週から対応している場合は、リカバリー策の状況を報告する。
　※ほかにも、ネクストアクションや、リスクが簡潔に報告されているとよい。

#最後に
どんなに良いテストができても、仕事の出し手(多くの場合はPM)にその成果をうまく報告できなければ、評価されません。
うまく報告できないと、追加で調査が必要だったり、報告の修正の手間が増えたりと、報告者の負荷はどんどん高まっていき、やがて潰れてしまいます。
そうならないよう、上記のポイントをおさえて、スマートに報告できるようにしましょう。
小学生向けのプログラミング教室

小学校でプログラミングが必修化され、中学受験でも採用され始めました。
当然、小学生のうちにコーディング技術などを身につけて将来SEになることを子どもたち全員に求める教育ではありません。

小学生がプログラミングを通して学ぶのは、順序だてて考える力・自分の力で課題を解決しようとする姿勢です。
とは言っても、小学校の先生方がプログラミングを教えられるかというと…むしろ現状でも忙しい小学校の先生たちにそこまで期待するのは酷かもしれません。
その中で、受験目的や将来を見据えてプログラミングをきちんと学んでおこうと考えるのなら、小学生向けのプログラミング教室を検討するのも良いと思います。

もちろん、「プログラミングスクール」というものに賛否があることは知っています。
まして小学生にそれをさせなくても…と考える方も多いでしょう。

でも、小学生の習い事って、ほとんどが将来の仕事や人生に大きな役割を担うことはないような気がしませんか。
その習い事で得たスキルそのものより、その経験や考え方が大事というか…。

それであれば、少なくとも大学受験まで必要になることが決まっていて、将来今以上にIT化が進んだ世の中を生きる小学生の習い事としてプログラミングを選ぶことを私はおすすめします。

自分が習ったことのないプログラミング、どうやって教室を選んだらいいのかわからず困ってしまう保護者が多いと思います。
そんな方の一助になればと思い、小学生向けのプログラミング教室を紹介する教室を運営しています。
https://programmingo-kids.com/

当サイトが誰かの助けになれば幸いです。
LaravelでCAS認証

# 目的

Laravelのcas認証ライブラリの一つ, [subfission/cas](https://github.com/subfission/cas)を使う機械があったのですが, 日本語での解説が見つからなかったので自分用の覚書も兼ねて使い方を書いておきます. とりあえず, casでの認証が動くようになることをこの記事のゴールにします. まだよくわかっていない部分もあるので, まだまだ試行錯誤の部分もあったりしますがご容赦を.

# 実行環境
Laravel 8.47.0
[cas認証ライブラリ subfission/cas](https://github.com/subfission/cas)

# 導入
[GitHubのwiki](https://github.com/subfission/cas/wiki/Installation)の通りに`php artisan vendor:publish`まで進める.

# configの編集
config/cas.phpを必要に応じて編集する. 多分この2つだけやっておけばとりあえず動くはず. 他の項目については, コメントアウトで書いてある説明を読むのを頑張りましょう…

```php:config/cas.php
'cas_hostname' => env('CAS_HOSTNAME', 'your.cas.address'),
'cas_real_hosts' => env('CAS_REAL_HOSTS', 'your.cas.address'),
```

# ログイン&ログアウトのAPIエンドポイントを作る
僕はroutes/api.phpに作ることにしました. 以下を追記します.

```php:routes/api.php
Route::get('auth/login', function(){
    cas()->authenticate();
});
Route::get('auth/logout', function(){
    cas()->logout();
});
```

# ページを作る
とりあえず最低限動くページを作ってみましょう. 下記のように色々追記したり, ファイルを作成したりします.

```php:routes/web.php
Route::get('cas_test', 'App\Http\Controllers\CasTestController');
Route::get('main_containts', 'App\Http\Controllers\MainContaintsController');
```

```php:app/Http/Controllers/CasTestController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;


class CasTestController extends Controller
{
    public function __invoke()
    {
        return view('cas_test');
    }
}
```

```php:cas_test.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    @if(! cas()->checkAuthentication())
    <a href="api/auth/login">
        ログイン
    </a>
        not logged in
    @else
        {{ cas()->user() }} でログインしています
        <a href="api/auth/logout">
            ログアウト
        </a>
    @endif
</html>
```


```php:app/Http/Controllers/MainContaintsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;


class MainContaintsController extends Controller
{
    public function __invoke()
    {
        if (cas()->checkAuthentication()){
            $user_name = cas()->user();
            return view('main_containts', conpact('usetname'));
        } else {
            /* ログインしていない場合の処理を適当に */
        }
    }
}
```

最初は `if (cas()->checkAuthentication())`無しで実装しようとしたのですが, これを呼ばずに`cas()->user()`を実行するとエラーになるような気がしました(もしかしたら別の原因かもしれませんが). もしこれが正しい推測ならば, ライブラリ側で一種のセーフガードが機能しているということでしょう.

```php:main_containts.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    welcome {{ username }}!!
</html>
```

# 結果
ログイン/ログアウト時のリダイレクトなどができていませんが, ブラウザで/cas_testにアクセスしてログインした後に/main_containtsにアクセスすると, CASでのユーザー名が表示されると思います.

# 参考
[stackoverflow Trying to set up CAS with my Laravel project](https://stackoverflow.com/questions/55809116/trying-to-set-up-cas-with-my-laravel-project)
[subfission/cas GitHub wiki](https://github.com/subfission/cas/wiki/Installation)
next.js で コンポーネントだけのSCSSを使いたい時

コンポーネントファイル　Hoge.jsで、 CSS Modules を使用して、やりたいと思い。

## まずsassをインストール

```
$ yarn add sass
```

## SCSSファイル作成と読み込み

▼ styles/Hoge.scss

```scss
.hoge {
  background: red;
}
```

▼ components/Hoge.js

```javascript
import test from "../styles/Hoge.scss";
const Hoge = () => {
  return (
    <div className={style.hoge}>
      <h1>こんにちは</h1>
    </div>
  );
};

export default Hoge;

```

## 下記の様なエラーが表示された。

```
Global CSS cannot be imported from files other than your Custom <App>. Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://nextjs.org/docs/messages/css-global
Location: components/Hoge.js
```

グローバルでCSSを読み込みたいときは、_app.js でしか読み込めないよって言ってるっぽい。


## 【結論】コンポーネントで、CSS Modulesときは...

ファイル名が悪かった、
`Hoge.scss` にしてたのを `Hoge.module.scss` にする。

`XXX.module.css` や `XXX.modile.scss` の形にしないとグローバルCSSとして扱われて、 _app.js で読み込めないらしい。

### 結果下記の様になる

▼ styles/Hoge.module.scss

```scss
.hoge {
  background: red;
}
```

▼ components/Hoge.js

```javascript
import test from "../styles/Hoge.module.scss";
const Hoge = () => {
  return (
    <div className={style.hoge}>
      <h1>こんにちは</h1>
    </div>
  );
};

export default Hoge;

```

おわり。
Netlifyでのデプロイに失敗し続けパソコンを投げそうになった話

Netrifyでwebアプリをデプロイしようとしたところ以下のエラーが出現

```
Command failed with exit code 1: yarn build
```
![errorcontent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/6289e111-27b4-c154-bde7-2acecb40f236.png)

しかし、よく見ると
![log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/1e6f625c-b3bc-82ab-021d-59ae33a57e4c.png)


原因は.envファイルで以下の記述をしていることが原因でした。

```
SKIP_PREFLIGHT_CHECK=true
```

ここで、Netrifyでbuildコマンドを以下のように書き換えました。

```
CI=npm run build
```

すると…
![deployed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/5f991594-c738-3ba7-1d4b-228f070b42ec.png)

やったぜ！！！！！！！！！！！！！！

泣いた。
【オブジェクト指向】ポリモーフィズム

##ポリモーフィズムとは
意味：多相性、多態性

プログラミング言語の持つ性質の一つで、ある関数やメソッドなどが、引数や返り値の数やデータ型などの異なる複数の実装を持ち、呼び出し時に使い分けるようにできること。
**多態性の概念がない言語では、同名のプログラムが二重に定義されていますとエラーが出てくる。**

https://e-words.jp/w/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0.html


- dogもcatも同じcryメソッドを呼び出しているが、呼び出し先に応じて適切なメソッドを実行している。


```ruby
class Animal
  attr_accessor :name

  def cry(voice='')
    "#{self.name}: #{voice}"
  end
end

class Dog < Animal
  def cry(voice='わんわん')
    super
  end
end

class Cat < Animal 
  def cry (voice='にゃー')
    super
  end
end

dog = Dog.new
dog.name = 'チョコ'

cat = Cat.new
cat.name = 'ミケ'

dog.cry     
#=>チョコ: わんわん
cat.cry     
#=>ミケ:　　　にゃーにゃー
```
rdmdはimport先を自動解決してくれるのでスクリプト管理が楽になる

# はじめに

D言語はスクリプト用途にめっちゃ便利という記事が思ったより好評だったので、他にもこんなところが便利という続編です。要はポエムに軸足置いたゆえに書き損じてたところの補足です。

__元記事__

https://qiita.com/lempiji/items/0730a6441f4f23a57119

# 複数ファイル分割

rdmd はソースを複数ファイルに分割できます。D言語ならそりゃそうでしょ、と思うかもしれませんが、何が良いかと言えば__「実行のために参照先ファイルを指示する必要がない」__ということです。

たとえば

```
sandbox
  start.d
  build.d
  common.d
```

というファイル構成に対し、`start.d -> common.d`, `build.d -> common.d` といった参照があっても `rdmd start` や `rdmd build` とするだけで実行できるということです。

もう少し具体的に書くと以下のような感じですね。

```d:common.d
module common;

enum url = "https://github.com";
```

```d:start.d
import std;
import common; // 同フォルダのcommon.dをimport
void main() {
    writeln("start: " ~ url);
}
```

```d:build.d
import std;
import common; // 同フォルダのcommon.dをimport
void main() {
    writeln("build: " ~ url);
}
```

静的コンパイルなのになんだか動的ロードみたいにも見えます。

とまぁこれで複数のコマンドがあっても共通変数などを1か所で管理できるようになり、保守性が大幅に改善されます。
いつものD言語っぽくて良い感じですね。

# コンパイラの `run` スイッチとの違い

前記事への反響として、「`rdmd` を使わなくても大体 `dmd run start.d` で済ませちゃう」といった話があり、確かにそれで良い気がする、とその時納得していました。

公開翌日に別件でふとスクリプトをメンテしていたところ、そういえばrdmdはファイル分割できるな、と思って試したらやっぱり動くぞ！ということで本記事を書くに至った次第です。

ここでコンパイラを使う場合、 `dmd -run start.d common.d` と両方指定してやれば良い気がしますが、試してみるとエラーでした。
エラーの理由は `-run` の場合はファイルが1つだけという縛りがあるため、2つ目のファイル指定が実行時の引数と解釈されてシンボルが見つからずリンカエラーになるためです。（そういうもの？）

結果、 `dmd start.d common.d` からの `./start.exe` みたいなことになり、これが `rdmd start` で1コマンドでOK、ということでちょっと楽になります。

なんというか、色々わかってる人が作った感があって良きかな良きかな、という感想です。
何よりコンパイラに同梱されてるのがありがたいんですけどね。
GitHubからSSHでローカルにクローンする

### 事前準備
- GitHubに登録済みであること
※後日リンク追加
- パーソナルアクセストークンあるいはSSH認証が済んでいること
[GitHubでパーソナルアクセストークンを設定する](https://qiita.com/mz_mz_mz/items/f0d3ce1edc513627947a)
[GitHubでSSHキーを設定する](https://qiita.com/mz_mz_mz/items/1c9a73031870b082675c)

### GitHubからURLを取得

1. [GitHub](https://github.com/)から対象のリポジトリを開く

2. `<> Code`タブをクリック

3. `Code▼`ボタンをクリック

4. `SSH`をクリック

5. 表示されているURLをコピー 
ex) git@github.com:hello-world-app.git

### ローカルにクローン

```ruby:sh
cd hello-world-app # プロジェクトのディレクトリ
git clone git@github.com:hello-world-app.git
```

## 関連

https://qiita.com/mz_mz_mz/items/f0d3ce1edc513627947a

https://qiita.com/mz_mz_mz/items/1c9a73031870b082675c