OmniAICreator/Qiita-1.07M huggingface dataset:
cancancanのコード読む(load_and_authorize_resouce)

プロジェクトでcancancanを使っていますが、たまに挙動がわからないことや、期待通りに動いてくれないことがありました。
そもそも、gemの内部的な動きを知らなかったということもあり、この機会に読んでみました。

* 今回は、load_and_authorize_resourceの挙動のみ確認する
* rubymineでdebugモードで起動して、posts#indexにリクエストとばしてひたすらデバッグしていきます。
* 重要なコード以外はむちゃ省略してます。
https://github.com/CanCanCommunity/cancancan

引数もどんな感じで処理されるのか知りたかったので、下記のように設定しました。
```ruby
class PostsController < ApplicationController
  load_and_authorize_resource :account, only: :index

  def index
  end
end

```
load_and_authorize_resource自体の定義は2つあるんですが、最初に呼ばれるのは下記でした。
```ruby
module CanCan
  module ControllerAdditions
    module ClassMethods
      def load_and_authorize_resource(*args)
        cancan_resource_class.add_before_action(self, :load_and_authorize_resource, *args)
      end
    end
   end
end
```
```ruby
def cancan_resource_class
  ControllerResource # Cancan::ControllerResourceクラスのこと
end
```
```ruby
module CanCan
  class ControllerResource
    include ControllerResourceLoader

    def self.add_before_action(controller_class, method, *args)
      # controller_class => PostsController
      # method => :load_and_authorize_resource
      # args => [:account, {:only=>:index}]
      options = args.extract_options! # => {only: :index}
      resource_name = args.first # => :account
      before_action_method = before_callback_name(options) # => :before_action
      controller_class.send(before_action_method, options.slice(:only, :except, :if, :unless)) do |controller|
        controller.class.cancan_resource_class
                  .new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method)
      # ブロック引数のcontrollerはPostsControllerのインスタンス
      # 下記がPostsControllerに動的にはえてくる
      # before_action only: :index do
      #  CanCan::ControllerResource.new(controller, :account, {}).load_and_authorize_resource
      # end
    end
  end
end
```
あんまりみなれない書き方なんですが、before_actionにブロック渡すときはこういう書き方になるらしいです（？）


```ruby
module CanCan
  class ControllerResource
    def initialize(controller, *args)
      # controller => # <PostsController:0x0000000000a438>
      # args => [:account, {}]
      @controller = controller 
      @params = controller.params # <ActionController::Parameters {"controller"=>"posts", "action"=>"index"} permitted: false>
      @options = args.extract_options! # {}
      @name = args.first # => :args
    end

    def load_and_authorize_resource
      load_resource
      authorize_resource
    end
  end
end
```

:::note info
Tips
HogeControllerがロードされるとputs 1が評価される
次にbefore_action内のputs 2が評価される。
本番環境とかだと、サーバー起動時にファイルを読み込むのでそのときputs 1が評価されるが
dev環境だと、遅延評価らしく、実際にindexとかにリクエストとばしたタイミングでputs 1が評価されるので挙動違う
つまり本来であれば、サーバー起動時とかにload_and_authorize_resourceが評価されて、before_actionが動的に生えてくる。
あとはリクエスト毎にbefore_actionが呼ばれる。
```ruby
class HogeController
  puts 1

  before_action do
    puts 2
  end

  def index
  end
end
```
:::

# まとめ
* load_and_authorize_resourceのデバッグを行った。
* 結果的にbefore_action do ~ endブロックをロード時に生成している
* do ~ endの中身はload_resourceとauthorize_resource
* CanCan::ControllerResourceがinitializeされるときの引数でload_resourceとauthorize_resourceの挙動が決まると思いますが、これはまた次に書く。
* メタプロとか全然なれていないので、実はすごく時間がかかったがとても良い機会だった
プログラミング言語化テスト

# 大問1

以下のプログラムはPHPにて記載されたプログラムの一部である。
記載の内容を日本語に翻訳せよ

## 第1問
```php5
$a=2;
```

## 第2問
```php5
$a=["a"=>3];
```

## 第3問
```php5
$a = ad(1,2)
```

## 第4問
```php5
$a = new A();
```

## 第5問
```php5
a();
```

## 第6問
```php5
A::v();
```


## 第7問
```php5
$b->get()
```

## 第8問
```php5
a(a(1))
```

## 第9問
```php5
$a = c();
a(b(1), new A($a))
```

## 第10問
```php5
$users = User::all();
```

# 大問2

以下のプログラムはPHPにて記載されたプログラムのである。
echoされる結果を回答せよ

## 第1問
```php5
$a = 1;
$b = 2;
$c = compact("a", "b");
echo $c["a"].$c["b"];
```


## 第2問
```php5
$a = "a";
$b = "b";
$c = "c";

$x = function($a, $b) use ($c) {
    return $a.$b.$c;
};

echo $x($b, $a);
```

## 第3問
```php5
class MyClass {
    public static function sayHello($name) {
        echo "Hello, " . $name . "!";
    }
}
MyClass::sayHello("John");
```


## 第4問
```php
class MyClass {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public static function sayHello() {
        echo "Hello, " . $this->name . "!";
    }
}

$myObject = new MyClass("John");
$myObject->sayHello();
```


## 第5問
```php
class MyClass {
    private static $count = 0;

    public static function getCount() {
        return self::$count;
    }

    public static function incrementCount($cnt = 1) {
        self::$count += $cnt;
    }
}

MyClass::incrementCount();
MyClass::incrementCount(3);
MyClass::incrementCount(MyClass::getCount()+1);
echo "カウント: " . MyClass::getCount();
```


## 第6問
```php
function createMultiplier($factor) {
    return function($number) use ($factor) {
        return $number * $factor;
    };
}

echo createMultiplier(2)(10);
```

## 第7問
```php
function processNumbers($numbers, $callback) {
    foreach ($numbers as $number) {
        $result = $callback($number);
        echo $result . ",";
    }
}

$numbers = [1, 2, 3, 4, 5];

$x = function($number) {
    return $number * 2;
};

processNumbers($numbers, $x);
```

## 第8問
```php
function c($factor) {
    return function($number) use ($factor) {
        return $number * $factor;
    };
}

$x = c(2);
$a = $x(10);
echo $a * 2;
```

## 第9問
```php5
class Animal {
    protected $name;
    
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function eat() {
        echo $this->name . " is eating.\n";
    }
}

class Dog extends Animal {
    public function bark() {
        echo $this->name . " is barking.\n";
    }
}

$animal = new Animal("Generic Animal");
$animal->eat();

$dog = new Dog("Fido");
$dog->eat();
$dog->bark();
```
FastAPIをデプロイ環境で起動させる時には「--host」オプションをつけることを忘れずに

## 通常のスタートアップコマンド
```
uvicorn main:app --reload
```
「--reload」を付けることで、ソースコードを変更すると自動でローカル環境に反映してくれます。
ただ、これをそのままデプロイ環境で使っても上手く起動しません。

## デプロイ環境でのスタートアップコマンド
```
uvicorn main:app --host=0.0.0.0
```
FastAPIはデフォルトでは「**127.0.0.1**」にアクセスするため、
「--host」をすることで、ホストアドレスを「**0.0.0.0**」にして他のコンピュータからアクセスできるようにします。

## 必要とあらばPortも指定しよう
```
uvicorn main:app --host=0.0.0.0 --port=80
```
【JavaScript】Weather App開発でAPIを使ってみた話

# はじめに
　今回は、天気アプリの作成中OpenWeatherのAPIを利用してみた際に、**async\/await**の他に**fetch**の知識が必要でしたので、復習がてらに使い方を確認していきたいと思います。

# JavaScript~async\/await、fetch編~
- とりあえずコードを見てみましょう。
```javascript:WeatherApp
//一部抜粋
const apiKey = "My OpenWeather API Key";
const apiUrl = "https://api.openweather.org/data/2.5/weather?units=metric&q=japan"; 

async function openWeather(){
  const response = await fetch(apiUrl + `&appid=${apiKey}`);
  const data = await response.json();
};
//~~~~
```
- ここでキーとなるのが、非同期処理の**async\/await**と、APIを呼び出すための**fetch**になります。使い方を簡単に説明していきたいと思います。

## fetch
- **fetch**関数は、JavaScriptが外部からデータを取得するために用意した関数になっています。今回は、APIからデータを取得したいので以下のように記述します。
```JavaScript:fetch確認用
fetch("data.json")
.then((data) => data.json())
.then((response) => console.log(response));

//fetch動作確認用のコンソール
console.log("test");
```
- fetch()は引数に取得するデータのパスやURLを指定してあげます。上記の`data.json()`は、data(引数で指定しているdata.json)を`json`形式で取得するように指定しています。`.then()`は一回目のthenの中身を実行した後に、二回目のthenが動作するようになっています。
:::note info
**then**とは？
・ここのthenメソッドは、前の処理を待つことが目的です。あるコードの後に実行したい場合に使用します。
:::
- fetch確認用のコードを実行すると、fetch動作確認用のコンソール`test`が先に表示されます。先ほど説明したように、thenを使うと前の処理を待って実行していますので、動作確認用のコンソールよりも`fetch(...).then(...)`の処理のほうが時間がかかってしまい、確認用のコンソールのほうが先に実行された、と言いうような流れになります。

## async\/await
- asyncとawaitはほぼセットになります。まずはコードを見てみましょう。
```javascript:async,await確認用
async function fetchJson(){
  const data = await fetch("data.json");
  const response = await data.json();

  console.log(response);
}
fetchJson();
```
- 上記は、fetch()の処理を待った後に、データが取得できると、data.json()で取得したデータをjson形式に直しています。その後、コンソールにresponseに格納された結果を表示している流れになります。
　これは、.then()を使った書き方と同じ処理になります。以下比較してみます。
```javascript:比較してみた
//thenを使った記述
fetch("data.json")
.then((data) => data.json())
.then((response) => console.log(response));

//async,awaitを使った記述
async function fetchJson(){
  const data = await fetch("data.json");
  const response = await data.json();

  console.log(response);
}
fetchJson();
```
- 上記を見てみると、thenの役割を担っているのが、awaitになっています。

簡単に出したが、WeatherAppを作成している時に必要だったモノを紹介しました。

# 参考
1. [JavaScriptのfetch()の基本的な使い方を分かりやすく解説](https://lorem-co-ltd.com/fetch-basic/)
2. [How To Make Weather App Using JavaScript Step By Step Explained](https://www.youtube.com/watch?v=MIYQR-Ybrn4)
dataclasses-json：`DataClassJsonMixin`を継承してデータクラスを定義すれば、mypyに怒られない

# 環境
* Python 3.11.2
* [dataclasses-json](https://github.com/lidatong/dataclasses-json) 0.5.7
* [mypy](https://github.com/python/mypy) 1.3.0

# 本題
`@dataclass_json`でデータクラスを定義して、`dataclass_json`が用意した`from_dict`関数などを呼び出すと、「そんな属性はない」とmypyに怒られます。

```python
from dataclasses_json import dataclass_json, DataClassJsonMixin
from dataclasses import dataclass


@dataclass_json
@dataclass
class Task:
    value: int


Task.from_dict({"value": 1})
```


```
$ mypy sample.py 
sample.py:11: error: "Type[Task]" has no attribute "from_dict"  [attr-defined]
```

mypyなどのlinterを使う場合は、`DataClassJsonMixin`を継承してデータクラスを定義しましょう。

```python
@dataclass
class Task(DataClassJsonMixin):
    value: int


Task.from_dict({"value": 1})
```

```
$ mypy sample.py 
Success: no issues found in 1 source file
```

>Pick whichever approach suits your taste. Note that there is better support for the mixin approach when using static analysis tools (e.g. linting, typing), but the differences in implementation will be invisible in runtime usage. [^1]


[^1]: https://github.com/lidatong/dataclasses-json#approach-2-inherit-from-a-mixin
dataclasses-json：`DataClassJsonMixin`を継承しているデータクラスで`undefined`や`letter_case`を設定する場合は、`dataclass_json_config`クラス変数を設定する

# 環境
* Python 3.11.2
* [dataclasses-json](https://github.com/lidatong/dataclasses-json) 0.5.7



# やりたいこと
`@dataclass_json`には`letter_case`や`undefined`引数で、設定を変えることができます。

```python
from dataclasses import dataclass
from dataclasses_json import dataclass_json, Undefined, Undefined

@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.RAISE)
@dataclass
class Task:
    task_name: str
    value: int = 10

```

`@dataclass_json`デコレータで定義するとmypyなどのlinterに怒られる場合があるので、`DataClassJsonMixin`を継承してデータクラスを宣言したいです。

```python
from dataclasses_json import DataClassJsonMixin

class Task(DataClassJsonMixin):
    task_name: int
```

その場合、`letter_case`や`undefined`はどこで設定すればよいのでしょうか？


# 解決方法

以下のコードのように、`dataclass_json_config`クラス変数を用意すればよいです。

```python
from dataclasses_json import config

@dataclass
class Task(DataClassJsonMixin):
    dataclass_json_config = config(
        letter_case=LetterCase.CAMEL,
        undefined=Undefined.EXCLUDE
    )["dataclasses_json"]

    task_name: str
    value: int = 10
```

以下のissueにコードが記載されていました。

https://github.com/lidatong/dataclasses-json/issues/247

なお`dataclass_json_config`には型ヒントを指定してはいけません。型ヒントを指定すると、データクラスのフィールドみなされてしまい、エラーが発生します。

```python
@dataclass
class Task(DataClassJsonMixin):
    dataclass_json_config: Any = config(
        letter_case=LetterCase.CAMEL,
        undefined=Undefined.EXCLUDE
    )["dataclasses_json"]

    task_name: str
    value: int = 10
```

```
$ python sample.py
...
ValueError: mutable default <class 'dict'> for field dataclass_json_config is not allowed: use default_factory
```
smbclientコマンド

●smbclientコマンドでWindowsネットワーク上の共有リソースにアクセスすることが出来る。

smbclientの書式とオプション

smbclient [オプション] //ホスト名/共有名
smbclient //ホスト名/共有名 [オプション]

オプション
・-L　ホスト名|--list=ホスト名　指定したホストで利用可能な共有リソースを一覧表示
・-N　認証を行わない
・-U ユーザ名|--user=ユーザ名　接続するユーザを指定
MacBook の Boot Camp の Ubuntu 22.04 LTS で Wifi 接続

参考ウェブサイト：https://iori.dev/archives/2394/

## 状況

MacBook の Boot Camp にインストールした Ubuntu 22.04 LTS をいろいろアップデートしていたら（or クリーンインストールしたら）、Wi-Fi 接続ができなくなった。Ethernet による有線 LAN 接続は機能している。 

## 対処

```sh
sudo apt purge bcmwl-kernel-source
sudo apt update
sudo update-pciids
sudo apt install firmware-b43-installer
sudo reboot
```

具体的な環境にもよるのだろうけど。今回はとりあえずこれだけで大丈夫だった。
本当なら `lspci` コマンドでネットワークアダプタを調べるなりすべきかも。
悩めるエンジニアとABC理論のお話

# 1.はじめに
どうも、ARIの名古屋支社に勤務している愛知県民こと、
新藏（にいくら）と申します♪
(/・ω・)/

実は自分は教育学部の出身なので、大学で多少心理学の勉強もしていました。
ふと、ABC理論という理論があるのを思い出し、エンジニアに応用ができそうと感じました。

**そこで今回はABC理論について記事にしたいと思います！**
若手の方や、悩みがある人、心理学に興味がある人の参考になれば幸いです
(*^^)v

# 2.ABC理論の前に・・・
## 2.1.「今、何をしていますか？」
では早速ABC理論、の前に1つお話をさせてください。

あなたは就活サイトの改修を行うプロジェクトリーダです。

先月から新卒のXさん、Yさん、Zさんがプロジェクトに参画し、
3人で1つの画面を作成する作業をお願いしました。

今日、あなたが出社すると新卒の3人も出社していたので、あなたは以下の質問しました。
「今、何をしていますか？」
すると以下の回答が返ってきました。

**Xさん「言われた通り、私はプログラミングをしています。」**
**Yさん「私は就活サイトのGUIを作っています。大変ですが、評価してもらいたいので頑張ります。」**
**Zさん「私は就活生も採用担当者も幸せになるシステムを作っています。完成するのが楽しみです。」**

ではここで質問です。
5年後、あなたは別プロジェクトのリーダを推薦することになりました。
Xさん、Yさん、Zさんの誰を推薦しますか？

## 2.2.Xさん、Yさん、Zさんの違い

・・・いかがだったでしょうか。
先ほどの質問はほとんどの方がZさんを選ぶと思います。

では、3人の違いを考えていきます。

Xさんは純粋に実施している作業を答えました。
Yさんは実施している作業で何が作れるかと、評価して欲しいことを答えました。
Zさんは実施している作業が最終的にもたらす結果を答えました。

3人の動機については以下となります。

Xさんは「特になし（言われたからやっている）」です。
Yさんは「評価してもらいたいから」です。
Zさんは「就活生と採用担当者を幸せにしたいから」です。

最後に、3人の5年後の姿を想像してみます。

**Xさんは引き続き1メンバとして仕事をしています。
Yさんはプログラミングのスペシャリストとして仕事をしています。
Zさんはプロジェクトリーダとして仕事をしています。**

さて、上記のまとめから、何が分かるのでしょうか？

# 3.ABC理論
いよいよ、本題のABC理論です！
## 3.1.ABC理論とは

ABC理論とは、結果がどのようにして起こるのかを
**A：出来事、B：とらえ方　C：結果**
の3段階に分けて考える理論のことです。

**同じAという出来事が発生した時に、
B1、B2という2つのとらえ方をした場合、
B1からはC1　B2からはC2　という違う結果が生じる**
というのがABC理論のポイントとなります。

実は2章のお話がABC理論の具体例となっているので、次節でまとめます。

:::note info
ABC理論の「ABC」は以下の言葉の頭文字からとられています。
A　→　Activating event
B　→　Belief
C　→　Consequence
:::

参考：https://swingroot.com/abc-theory/

## 3.2.前章のお話とABC理論
では、2章のお話とABC理論の関係性をまとめていきます。

**A（出来事）としては「プログラミングをしている」が該当します。**

**B（とらえ方）としては動機が該当するため、以下となります。**
Xさんは「特になし（言われたからやっている）」です。
Yさんは「評価してもらいたいから」です。
Zさんは「就活生と採用担当者を幸せにしたいから」です。

**C（結果）としては5年後の姿が該当するため、以下となります。**
Xさんは引き続き1メンバとして仕事をしています。
Yさんはプログラミングのスペシャリストとして仕事をしています。
Zさんはプロジェクトリーダとして仕事をしています。

**プログラミングをしているという同じ出来事でも、
それぞれとらえ方（動機）は異なり、それにより結果（5年後の姿）も変わります。**

# 4.伝えたいこと
ここまで長々と書いてきましたが、
最後に自分から伝えたいことを記載して結びとしたいと思います！

新人の頃や、悩んでいる時は
「怒られて辛い」とか「この作業は自分にとって意味があるのか」とか「全然できなくてどうしよう」
と考えることがあると思います。

そんな時にABC理論、特に**B（とらえ方）によってC（結果）が変わる**ということを思い出し、
広い視野で考える、少し視点を変える、他の人に相談する等で別のとらえ方を探してみてください。

その後、とらえ方に対する結果も考え、自分で納得できる答えを見つけられると、
エンジニアライフや人生がより良くなると思います！

**この記事が読者の方の助けになれば幸いです♪**

# 5.おわりに
ここまで読んで下さり、ありがとうございます！！！
(^^)

実は今年、自分はOJTの担当者になったので、自戒の意味も込めて執筆しました。
OJT関連のこともどこかで記事にしたいと思うので、何卒よろしくお願いします♪
(:3_ヽ)_

:::note info
一部の方はお気づきと思いますが、以下の「三人のレンガ職人」を参考にお話を作成しました。
https://tokyo.real-cocoon.com/16657-2/
:::
Windows11×Rails7×ポスグレSQL 環境構築

## はじめに
近いうちにRails7とWindowsで(ローカル)開発することになりまして、今回メモとして残していこうと思います。
メモ代わりとしてなので、少し説明雑なところもあるかもしれません。。
もし誰かの参考になりましたら、幸いです。


## 環境構築手順

- [Rubyのインストール](https://rubyinstaller.org/downloads/)
※基本的に1番上の推奨されているやつをインストールすれば大丈夫です
 `Ruby+Devkit 3.~ (x64)`
コマンドプロンプトで`ruby --version`でバージョンが表示されたら無事完了

- SQLiteのインストール(ぽすぐれ使うなら不要)

- Ruby on Rails の Install
コマンドプロンプトで`gem install rails`
`rails --version`でバージョンが表示されたら無事完了

- rails new プロジェクト名
ポスグレの場合　`rails new プロジェクト名 -d postgresql`

- rails s
`localhost:3000`で開けたら完成
ポスグレの場合は`rails s`して画面開いたらエラーになっているので、下記でセットアップ

## ポスグレSQLのインストール
https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
好きなバージョンをインストール
インストール中に聞いてくるマスターパスワードは任意

pgAdmin4にチェックを入れてインストール
![aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124434/67ab26ca-9729-98d6-08ff-cb86376709a6.png)

#### pgAdmin4の日本語化
pgAdminを起動し、上部のメニューからFile⇒Preferences⇒Miscellaneous⇒User languageからJapanese

#### pgAdmin4とDB接続
pgAdminを起動して、ファイル⇒設定⇒パス⇒バイナリパスを選択
![ps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124434/6644731b-a4d3-7d39-ee26-76989a6617c4.png)

#### DBの作成
DBを右クリックして作成
DBの名前はアプリ名_developmentにしましょう
ユーザーはとりあえずpostgresを使いましょう

ここまで出来たら後はRailsとの接続だけです




## Railsとポスグレを接続
`database.yml`に設定を記載
開発ではdevelopmentの設定でRailsを動かすので、development:と書かれている中の設定を変えます

- database:(接続先PostgreSQLのどのDBにつなぐか)
  `database` アプリ名_development

- username:（PostgreSQLのどのユーザとして接続するか）
  `username: postgres`

- password:（ユーザのパスワード）
  最初にポスグレSQL入れた時に設定したパスワード

- host（どのコンピュータ上で動くPostgreSQLに接続するか）
localhost

### 接続確認
`rails s`をしたときにエラー出ず画面が表示されたら接続完了![スクリーンショット 2023-05-31 225849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2124434/458778d8-ecda-f8db-fa05-9fc46a1a1d4a.png)



## 注意点
※ポスグレを使う場合はSQLiteのインストールは不要
※Rails７を使うにはRuby 2.7.0以降が必須
※ポスグレSQLをインストールした際に設定したパスワードはRailsのdatabase.ymlで使用

### その他
Rails 7: Ruby 2.7.0以降が必須
Rails 6: Ruby 2.5.0以降が必須
Rails 5: Ruby 2.2.2以降が必須


### 参考
こちらの記事を参考にさせていただきました。
有難うございます
[WindowsでRails環境構築](https://qiita.com/good_engineer00/items/711a022c6234fc495724)

### エラー対応

`rails new`した際に下記のエラーが出る
```
 run  git init from "."
C:/Ruby32-x64/lib/ruby/gems/3.2.0/gems/railties-7.0.5/lib/rails/generators/rails/app/app_generator.rb:258:in ``': No such file or directory - git config init.defaultbranch (Errno::ENOENT)
```
Gitがないため表示されるのでGitのインストールをする
[参考](https://prog-8.com/docs/git-env-win)
C#で、JavaScriptのmap関数っぽく2次元配列を作る

否応なく触れる機会が増すJavaScript
---
自分がJavaScriptを書くなどとは思ってもみなかった。
Html+CSS+JavaScriptは、今更言うまでもなくWebページ作成の為の重要な構成要素だ。
その中でもJavaScriptは、kintoneやらGoogleスプレッドシートやらの様々なクラウドサービスでExcelのVBAが如くその機能をユーザーがカスタマイズできるように利用されている。
クラウド全盛の昨今、JavaScriptの知識があればクラウドを身近に活用できるようになるだろう。

JavaScriptで2次元配列を作る
---
そんなことを感じていた折、いざJavaScriptで配列を操作しようとするとどうやっていいか分からない。しかし、今の世の中、ChatGPTという何でも相談できる心強い先生がいる。
単に配列を作るのではなく、空の2次元配列が必要となり、早速作り方を尋ねると以下の回答を得た。

```js:JS
let cells = Array(5).fill(null).map(() => Array(5).fill(null));
```
これは、5行5列の2次元配列を作らせた時の回答である。
ここで注目すべきは、`map`関数だ。これは一体何をやっているのだろう?
分かりづらいことは、好きな言語で書き換えると理解が深まる。
以下は`map`と`fill`の中身をC#で書いてみた。(書かせてみた:sweat_smile:）
```C#:C#
public static class ArrayExtensions
{
    public static TOutput[] Map<TInput, TOutput>(this TInput[] source, Func<TInput, TOutput> selector)
    {
        TOutput[] result = new TOutput[source.Length];
        for (int i = 0; i < source.Length; i++)
        {
            result[i] = selector(source[i]);
        }
        return result;
    }

    public static T[] Fill<T>(this T[] source, T value)
    {
        for (int i = 0; i < source.Length; i++)
        {
            source[i] = value;
        }
        return source;
    }
}

```
（参考まで:point_right:[『【C#】期せずして知識の詰まったメソッドを生んだ』](https://qiita.com/nekohei/items/b424ba3171b7a0630c44)）

ここで混乱するのは、`Map`拡張メソッドの第2引数の`Func<TInput, TOutput> selector` だろう。

`Map`の中では`selector`の実装が書かれていない。これはどういうことか?

`selector`の実装は`Map`メソッドを使用するユーザーが書く。`Map`メソッド使用時に引数として実装を渡すのだ。ユーザーが元の配列を使って新たな配列に作り変えることができるが、どう作り変えるかをここでユーザー自身が実装する訳だ。だから第2引数はデリゲートのシグネチャのみで構わない。

これを使ってみる。

```C#:C#

var cells = (new string[5]).Fill(null).Map(x => (new string[5]).Fill(null));

Console.WriteLine($"[\n {string.Join(",\n ", cells.Select(x => $" [{string.Join(", ", x.Select(y => y is null ? "null" : $"{y}"))}]"))}\n]");

```
JavaScriptの`console.log`風に出力されるようにしてみた。

```:出力
[
  [null, null, null, null, null],
  [null, null, null, null, null],
  [null, null, null, null, null],
  [null, null, null, null, null],
  [null, null, null, null, null]
]
```
配列の各要素に配列を格納しているので2次元配列となる。

気持ち悪いJavaScript
---
C#では実のところ`Fill`メソッドは不要だ。これがJavaScriptだとどうか?
後ろの`fill`を消してみた。

```js:JS
let cells = Array(5).fill(null).map(() => Array(5));
console.log(cells);
```

```:出力
[
  [ <5 empty items> ],
  [ <5 empty items> ],
  [ <5 empty items> ],
  [ <5 empty items> ],
  [ <5 empty items> ]
]
```
前のを消すと、、、
```js:JS
let cells = Array(5).map(() => Array(5).fill(null));
console.log(cells);
```
```:出力
[ <5 empty items> ]
```
両方消すと、前のを消したのと同じ結果となった。

これが空配列か。JavaScript気持ち悪い、、、:confounded:

https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.map
自社におけるデイリースクラムに関する取り組み

## 自社のアジャイルに関する取り組み
**昨年度の夏からチームメンバー（６名）にてアジャイル開発に取り組み**をおこなっています。
デイリースクラム（デイリーミーティング）はアジャイル開発を取り組み始めてから、**今までずっと継続して取り組めていること**の１つになります。

自社のデイリースクラムの内容
* 毎朝15分 チームメンバーで集合
* リモート勤務の方もWeb会議で参加
* 「昨日やったこと」「今日やること」「困っていること」の３つをチームメンバーに共有
* デイリースクラム内では困っていることの解決に向けての議論はおこなわない。（必要であれば、デイリースクラム終了後に話し合う）

## 当初のデイリースクラム
取り組み当初のデイリースクラムでは、以下のような取り組みをしていました。

* 「昨日やったこと」「今日やること」「困っていること」を**チームメンバー全員が報告**
* チームメンバーの報告後に、**全体への連絡事項と司会者のショートスピーチ（1分程度）を実施**
* 最後にサイコロを振り、**翌日の司会者を決定**

実はアジャイル開発を開始した時にチームも結成しており、メンバー間のことをよく知らなかったり、チーム全体として固さがあったりしました。
そのような状況を改善するため、サイコロで司会を決めるというゲーム要素を取り入れて、**デイリースクラムが盛り上がる要素**を入れてみました。（意外と成功だったと思っている）

## 当初から経過後の課題

しばらくデイリースクラムを継続していく中で、以下のような改善事項が出てきました。

* サイコロの目が偏る
    * 同じ人の司会が続いたり、しばらく当たらなかったり
* デイリースクラムの中でショートスピーチもおこなうため、続くと大変
* メンバーの報告も同じような内容が続く
    * ６名を２チームにロールを分けて開発をしているため、同じチームであれば、同じような報告になってしまう

## 課題への対処

* メンバー間のことも、よく分かるようになり、当初の目的は達成したため、サイコロでの司会決めは廃止して、当番制で回していくこととしました
* チームメンバー全員の報告は廃止して、各ロールチームからの報告のみにしました

２つめの内容については、本来であれば全員がすべきですが、**アジャイルチームとして柔軟に対応しても改善するので良いかな**と思ってます。

## 次の課題
![スクリーンショット 2023-05-31 235015.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100890/c9b53bc2-7546-b768-08b1-ac72f8de6023.jpeg)

分かりにくい絵ですが、１つの円が１人になります。
重なっているところが、チーム開発で取り組んでいる案件になりますが、
**実は各メンバーごとに違う案件にも取り組んでいたりします。**（そもそも良いのか論はありますが、、、）
今のデイリースクラムの対象はチーム開発の案件のみを範囲としています。
一方で自身のチームのマネージメントとしては、チーム開発の案件以外の部分にまで届くことができておらず、やり方含めて検討すべき事項と認識しています。
チームメンバーの自律的な活動を支援しながらも、早めにアラートなどに気づいていくためには、どうするべきかは引き続き考えたいと思っています。

# 余談）ショートスピーチの話

余談ですが、、ショートスピーチから派生する雑談などが意外と面白いです。
業務には直結しませんが、日ごろからもこのようなコミュニケーションって大事だなと思ってます。

* おいしいクレープ屋さんがある。（移動販売車のため、期間限定！）
* 初めてリアルサバイバルゲームを経験してみた
* 甥っ子がかわいい
* 〇〇って本を読んでみた
などなど。
AWS RDS データベースのバックアップと復元方法をまとめ

# 背景
* リリース前にサービス品質監査を行う予定
* 回復性特性の中に、データベース問題がある時にデータを回復する
* AWS RDSの機能とmysql機能より、データ復元方法を調査する

# 概要
### 復元方法と対応ケースを考える

| 番号 | 復元方法 | 対応ケース |
|:-----------:|:------------:|:------------|
| 1       | バックトラック        | 突然データを削除してしまって、早めに復元したい         |
|2|特定時点へ復元|クラスターが存在しているが、特定時点(3分前)に戻れる|
|3|スナップショット復元|クラスターも削除してしまう場合の復元|
|4|mysqldump|リリース時に、db migrationミスの対応|

* 上記のテーブル分類より一つ一つ説明する

# 内容
### バックトラック 
* [Aurora DB クラスターのバックトラックとは](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Backtrack.html)
    * 指定した時間まで DB クラスターを「巻き戻し」ます。
* 前提条件
    * 操作ミスに本番DBへアクセスしてデータを削除してしまう
    * すぐミスを発見できる
* 復旧手順
    * https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.Backtrack.html#AuroraMySQL.Managing.Backtrack.Performing
* 復旧時間
    * 10min
* メリット
    * 簡単にエラーを取り消すことができます。
    * DB クラスターのバックトラックは迅速に実行できます。
* デメリット
    * バックトトラックウィンドウの上限は 72 時間
    * バックトトラック機能有効の場合は、別の料金がかかる
        * 時間あたりの料金: 0.014USD/変更レコード 100 万件 

### スナップショット復元
* [スナップショットからの復元とは](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_RestoreFromSnapshot.html)
* 前提条件
    * クラスターが削除されてしまうが、スナップショットが保留される
* 復旧手順
    * https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_RestoreFromSnapshot.html
* 復旧時間
    * 40min
* デメリット
    * スナップショットの自動バックアップが１日1回
    * 新しいクラスターが作成されて、復元後にエンドポイントのことを考えないといけない


### 特定時点へ復元
* [特定時点へ復元とは](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_PIT.html)
* 前提条件
    * バックトラック復元できない場合
* 復旧手順
    * https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_PIT.html
* 復旧時間
    * 40min
* デメリット
    * 新しいクラスターが作成されて、復元後にエンドポイントのことを考えないといけない

### mysqldump
* 前提条件
    * リリース時にdb migrationのために事前バックアップする
* 復旧手順
```
$ mysql -h hostname -u username -pパスワード < dump.sql
```
* 復旧時間
    * 10min(データの量によって)
* メリット
    * バックトラックも復元できるが、料金かからない
* デメリット
    * データの量が多い場合は、バックアップの時間がかかる
FlutterでDIを理解する

# DIとは?
DIとはDependency Injectionの略で、日本語にすると**依存性の注入**です。
この言葉を聞いても「なるほど依存性の注入か!」と(僕だったら)なるわけがないのでググってみました。
[記事](https://www.sophia-it.com/content/DI#:~:text=DI%E3%81%A8%E3%81%AF%E3%80%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B,%E6%A6%82%E5%BF%B5%E3%81%AE%E3%81%93%E3%81%A8%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82)の中には以下のことが書いてありました。
>DIとは、プログラミングにおけるデザインパターン（設計思想）の一種で、オブジェクトを成立させるために必要となるコードを実行時に注入（Inject）してゆくという概念のことである。

う〜ん、、いまいちピンとこないですよね。。。
端的に言うならば、**依存関係を切って実行時に外部からオブジェクトを入れるようにすることです。**

# 依存関係って何?
いきなりですが、下のコードを見てください。

```car.dart
class EngineA {
  void start() {
    print("車が走ります。");
  }

  void stop() {
    print("車が止まります。");
  }
}

class Car {
  late EngineA _engine;

  Car() {
    _engine = EngineA();
  }

  void engineOn() {
    return _engine.start();
  }

  void engineOff() {
    return _engine.stop();
  }
}

```

一見何の問題もなさそうですが、問題があります。
CarクラスのEngineAが故障したとしたらこのCarクラスは使い物にならなくなってしまいます。
そして、Carクラスの内部を編集してEngineAをEngineBに変更しないといけません。
そして、またEngineBクラスが故障したら、EngineCに、、、、って大変ですよね！
てか、そんなことやりたくないですよね？(少なくても俺はやりたくない。。。)
このめんどくさい関係が`依存関係であり、CarクラスはEngineAクラスに依存しています`

例えば、このめんどくさい依存関係が人間関係だったらどうしますか？
すぐに依存関係を切り離しますよね？(中にはずっと依存するような人もいるかもしれないが、、、、)

それが**DI**です。
(テストがしやすいとか、オブジェクトを差し替えて注入するだけで良いとかメリットはいっぱいあるけど、
それよりも、まず**依存してるの嫌じゃない？？**)

# DIしようぜ!!
まずは、Engineという抽象クラスが必要です。(Engineという概念を定義しよう。)
抽象クラスを定義する際はabstractキーワードを指定します。
インターフェースを作成しておく感じです。

```engine.dart
abstract class Engine {
  void start();
  void stop();
}
```
そして、Carクラスの引数は抽象クラスであるEngineに変更しよう。
```car.dart
class Car {
  late Engine _engine;
  Car(this._engine);
  
  void engineOn() {
    return _engine.start();
  }

  void engineOff() {
    return _engine.stop();
  }
}
```

engine.dartで実装したインターフェースの実際の処理はEngineAに移譲します。
```engineA.dart
class EngineA implements Engine{
  @override
  void start() {
    print("エンジンAの車が走ります。");
  }

  @override
  void stop() {
    print("エンジンAの車が止まります。");
  }
class EngineB implements Engine{
  @override
  void start() {
    print("エンジンBの車が走ります。");
  }

  @override
  void stop() {
    print("エンジンBの車が止まります。");
  }
}
```
エンジンAの車の時はEngineAインスタンスをポイってしてあげて、エンジンBの時はEngineBのインスタンスをポイってしてあげるだけでOKです。
```main.dart
void main() {
  final car = Car(EngineA());
  car.engineOff();//エンジンAの車が止まります。
}
```
**これで綺麗に依存関係を切り離すことができました。**

# さいごに
お腹減った。。。。
では、次の記事でお会いしましょう。
【Mac】コマンドでリマインダーを追加する方法

## reminders-cliを使用する

reminders-cliを使用することでコマンドでリマインダーを追加できます。

Homebrewでインストールするには以下のコマンドを実行します。

```terminal
brew install keith/formulae/reminders-cli
```

リマインダーを追加するには次のように実行します。

```terminal
$ reminders add リマインダー reminders-cliで追加 --due-date "today 3pm"
Added 'reminders-cliで追加' to 'リマインダー'
```

上記の場合には「リマインダー」というリストに「reminders-cliで追加」というタイトルの当日の午後3時が期限のリマインダーが作成されます。

リマインダーの追加以外にも編集や削除などもできます。
詳細は以下をご参照ください。

https://github.com/keith/reminders-cli


## AppleScriptを使用する

以下のコマンドを実行することでリマインダーを追加できます。

```terminal
osascript -e 'tell application "Reminders" to make new reminder with properties {name:"AppleScriptで追加", allday due date:current date} at list "リマインダー"'
```

上記を実行すると「リマインダー」というリストに「AppleScriptで追加」という名前の当日終日が期限のリマインダーが追加されます。

リマインダーのプロパティ一覧は以下のとおりです。

| プロパティ | 説明 |
|:-|:-|
| name (text)  |リマインダーの名前 |
| id (text, r/o)  |  リマインダーの一意な識別子 |
| container (list or reminder, r/o)  |  リマインダーのコンテナ |
| creation date (date, r/o)  | リマインダーの作成日  |
| modification date (date, r/o)  |  リマインダーの変更日 |
| body (text)  |  リマインダーのメモ |
| completed (boolean)  |  リマインダーが完了したかどうか |
|  completion date (date) | リマインダーの完了日  |
| due date (date)   | リマインダーの期限。日付と時間の両方を設定する  |
| allday due date (date)  |  リマインダーの期限。日付のみ設定する |
| remind me date (date) | リマインダーの期日を指定する |
| priority (integer)  | リマインダーの優先順位。<br>0：優先順位なし、1〜4：高、5：中、6〜9：低 |
| flagged (boolean) |リマインダーにフラグを立てるかどうか |
よく使用するGitコマンドまとめ

- 案件で頻繁に使用するGitコマンドをまとめました。
    - 最低限作業する上で必要なコマンドのみを記述しております。
    - 基本的なコマンドでも、あまり使わないコマンドは記述していません。
- 自分用に使用するケースによって分けて記述しています。
    - コマンドの種類やオプションごとにはあまり整理されていないです。

## 目次

[1. リポジトリの初期化・クローン](##リポジトリの初期化・クローン)
[2. ブランチの操作](##ブランチの操作)
[3. 変更の確認〜リモートリポジトリにプッシュ](##変更の確認〜リモートリポジトリにプッシュ)
[4. ミスった時](##ミスった時)

## 1. 最初にやること（リポジトリの初期化・クローン）

```
// 現在のディレクトリに新しいGitリポジトリとして初期化
$ git init
// リモートリポジトリの特定のブランチをクローンする場合
$ git clone -b [branch] [url]
```

## 2. ブランチの操作＋その際よく使うコマンド（プル・マージ・スタッシュ）

```
// 現在のリポジトリのブランチ一覧表示
$ git branch
// リモートのリポジトリのブランチも表示
$ git branch --all

// ブランチの切り替え
$ git checkout [branch-name]
// ブランチの作成＋切り替え
$ git checkout -b [branch-name]

// リモートリポジトリからすべての情報を取得
$ git fetch --all

// リモートリポジトリの最新の変更を取得し、現在のブランチに結合（git fetch＋git merge）
$ git pull [remote-name] [branch-name] 

// 指定ブランチの変更を現在のブランチに結合
$ git merge [branch-name]

// 変更を退避
$ git stash -u
// 退避した作業の一覧
$ git stash list
// 退避した分を戻す
$  git stash apply stash@{0}
```

## 3. 変更の確認〜リモートリポジトリにプッシュ

```
// ワーキングディレクトリの現在の状態を表示
$ git status
// 変更の確認
$ git diff [file-name]
// ステージングエリアと最新のコミットとの差分確認
$ git diff --staged
// 変更したファイルをステージングエリアに追加
$ git add [file/directory]
// 全て追加する場合
$ git add .
// ステージングエリアの変更をリポジトリにコミット
$ git commit -m "[message]"
// 複数のコミットを一つにまとめる場合
$ git commit --squash
// ローカルの変更をリモートリポジトリにプッシュ
$ git push [remote-name] [branch-name]
```

## 4. ミスった時

```
// Gitの操作履歴を表示
$ git reflog
// 最後のコミットを修正
git commit --amend -m "[message]"
// 指定したコミットまで戻す（履歴が消える、他の人が操作したブランチでは基本NG）
$ git reset --hard [commit-hash]
// 指定したコミットまで戻す（履歴は残る）
$ git revert [commit-hash]
```
モダンアクティビティで全シート名を取得する

全てのシート名をリストで取得したい時があります。

↓シート名を入れるリスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636507/f23f7b73-0d4f-555b-0184-8bfc2c4ba263.png)

クラシックアクティビティであれば「ブックの全シートを取得」アクティビティで取得できましたが、モダンアクティビティでは同じ物はありません（UiPath.Excel.Activities V2.20.2時点）。

↓「ブックの全シートを取得」アクティビティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636507/f5bd2c62-8d31-68e9-ba42-3cc67939038c.png)

これをモダンアクティビティだけでやるときは「繰り返し（Excelの各シート）」「リストに項目を追加」アクティビティを使うと同じことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636507/e890a119-b75c-3187-97be-aef97bdbcfac.png)

ちょっと長くなってしまいますが、これで全シート名を取得することが可能です。
「DNSサーバ」という呼称は誤解を招く説

## きっかけ
DNS関連の話をするときに「DNSサーバ」という言葉がよく出る。
人によってイメージするものが違うようである。

## RFC
[RCF1034](https://datatracker.ietf.org/doc/html/rfc1034)を参照する。
> NAME SERVERS are server programs which hold information about
> the domain tree's structure and set information

「name server」が情報を持つ、とある。
> RESOLVERS are programs that extract information from name
> servers in response to client requests.

「resolver」がname serverから情報を引き出す、とある。
登場人物は(クライアントを除けば)この2者である。
ちなみに、以下の用語は**登場しない**。
「DNS server」「Cache server」「Content server」「Full-service resolver」
木構造とか権威とか委任とか難しそうな用語が出てくるが登場人物は意外とシンプルである。

## どうしてこうなった？
OSのせいな気がする。
Linux系のresolv.confにはresolverを設定するところに「nameserver」という用語が使われているし、
Windowsでは、同じく「IPv4 DNSサーバー」という用語が使われている
クライアント目線では直接やりとりするresolverのみを気にすればいいので問題ないといえばないのだが。
経緯をご存じの方がいればコメントください。

## まとめ
「今話をしているのはname serverだろうか、それともresolverだろうか」は常に意識しておきたい。
（最近は減ってきたが）一つのホスト上にまとまってしまっている場合もあるし・・。
gitのコミットの消し方～git revert～

何番煎じか分かりませんが、`git revert`を解説します。

gitでコミットを重ねていくうちに「前のコミットに戻したい」という場面はあると思います。そのとき、`git revert`というコマンドが便利です。これはコミットを打ち消すコミットを出します。分かりにくい言い方ですが、これは、行を追加したならばそれを削除し、行を削除したならば元の行を追加するコミットということです。

`git revert`の良いところは、いくつかあるコミットを取り消す方法の中で最も簡単で安全だということです。もし間違ってrevertしても、revertを再度revertすれば元の内容に戻すことができます。

それでは実際の動作を見ていきましょう。

```Shell Session
git init
echo x > a.txt
git add .
git commit -m "x"
```

これで"x"と書かれたa.txtがコミットされました。
次に以下を実行します。

```Shell Session
echo y > a.txt
git add .
git commit -m "y"
```

これで"y"と書かれたa.txtがコミットされました。
この"y"と書かれたコミットを取り消して"x"に戻したいとします。
そのため、以下のコードを実行します。

```Shell Session
git revert 33ffe
```

"33ffe"は、`git log`で見ることができる"y"のコミットのコミットIDです。全てを入力しなくとも、他と重複しないのであれば先頭の一部のみで大丈夫です。`git revert`するとvimが立ち上がり、コミットメッセージの入力を促されます。表示されている内容で問題なければ":wq"をタイプしてEnterを押して下さい。

これでa.txtを見ると内容が確かに"x"となっています。revert成功です。
とりあえず入れとくと便利なVSCodeの拡張機能

# はじめに
個人的にVSCodeに入れていて便利な拡張機能の中で**開発言語や分野に関わらずどのユーザーでも共通して使えそうな拡張機能**をピックアップして解説してみましたのでぜひ読んでいってください。

# Excel Viewer
![スクリーンショット 2023-05-30 23.33.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/1c213cdb-26b6-cbd2-9dbd-7c635ff41d65.png)
VSCodeでExcelファイルを開こうとすると`サポートされていないテキストエンコードを使用しているため、テキストエディターに表示されません`と表示されVSCode上でExcelファイル開くことが困難です。
Excel Viewerを導入すればそんな問題も解決することができます。
さらに、**Excel以外にもCSVファイルをExcelのようにテーブル形式で表示できます。**
csvファイルをテーブル形式で表示した例↓
![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/cfb013ed-1449-a6f7-fd7e-15cd9446fd4f.gif)
ExcelやCSVが文字化けする場合は設定から`Auto Guess Encoding`で検索してチェックを入れた後に再度開くと直ります。

# vscode-pdf
![スクリーンショット 2023-05-30 23.34.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/27fbb822-e7ef-8a91-bac2-9e29c0703d03.png)
PDFもExcelと同じようにVSCode上で開くことができないため、この拡張機能を入れると見れるようになります。
### PDFプレビュー画面↓
![スクリーンショット 2023-05-31 23.16.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/f7623767-d8ac-a6d7-c1aa-a5ce86fec076.png)

# Error Lens
![スクリーンショット 2023-05-31 23.20.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/5f00b8a1-66c4-85f7-d653-05073e39aa2e.png)
コード内のエラーや警告を視覚的に強調表示するツールです。エラーメッセージや警告メッセージが直接コード上に表示されるため、エラーの特定や修正が容易になります。

### 導入前↓
![スクリーンショット 2023-05-30 23.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/7c77d2c8-bda6-435e-94a3-c83f8ea3ca4c.png)
### 導入後↓
![スクリーンショット 2023-05-30 23.32.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/ab29337e-e9a6-58d5-cea7-764d7e08321f.png)

パッとみただけでエラー内容がわかるのが素晴らしいです。

# Material Icon Theme
![スクリーンショット 2023-05-30 23.33.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/897981fb-a234-3bb0-d3da-f36a94f2e9e8.png)
この拡張機能は、GoogleのMaterial Designアイコンセットに基づいており、ファイルやフォルダ、拡張子、ラベルなど、さまざまな要素に対してアイコンを提供し、ファイルやフォルダの種類を視覚的に識別しやすくなります。たとえば、フォルダはフォルダのアイコンで表示され、ファイルの種類に応じて異なるアイコンが表示されます（例: .htmlファイル、.cssファイル、.jsファイルなど）。

### 導入前↓
![スクリーンショット 2023-05-30 23.48.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/2c395bff-2058-996b-fef6-1069eb1d97e2.png)

### 導入後↓
![スクリーンショット 2023-05-30 23.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314085/ad813060-031e-71f7-b480-9663da3a35bf.png)
他の拡張機能でも同様にアイコンを変更できるものがありますが、個人的にこれが一番好きです。


## 最後に
ご拝読いただきありがとうございました。
より良い開発体験になると思うのでぜひダウンロードして使ってみてください！
他にもVSCodeにはたくさん便利な拡張機能があるため、開発環境が快適になるよう今後も模索していこうと思います。

サンプルで使用したデータセット
https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00200521&tstat=000001011777&cycle=0&tclass1=000001094741&tclass2val=0
[java] 配列から順列を求める方法

# 序論
Javaを用いたアルゴリズムの勉強をしているが、Javaは順列を求めるような便利なコードは用意されてないので、自分でそのコードを用意する必要性があった。よってそれを調べたのでメモ。


# Code 
```java:Permutation
public class Permutation {

	static void permutation(int[] arr, int[] output, boolean[] visited, int depth, int n, int r) {
		if (depth == r) {
			print(output, r);
			return;
		}

		for (int i = 0; i < n; i++) {
			if (visited[i] != true) {
				visited[i] = true;
				output[depth] = arr[i];
				permutation(arr, output, visited, depth + 1, n, r);
				visited[i] = false;
			}
		}
	}

	static void swap(int[] arr, int depth, int i) {
		int temp = arr[depth];
		arr[depth] = arr[i];
		arr[i] = temp;
	}

	static void print(int[] arr, int r) {
		for (int i = 0; i < r; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}
}

```

```java
public class PermutationUse {
	public static void main(String[] args) {
		int n = 3;
		int[] arr = { 1, 2, 3 };
		int[] output = new int[n];
		boolean[] visited = new boolean[n];

		Permutation.permutation(arr, output, visited, 0, n, n);
	}
}

```

```terminal:Terminal
1 2 3 
1 3 2 
2 1 3 
2 3 1 
3 1 2 
3 2 1 

```

最初に並べた通りの順列を求めることができる。
`sort`をしておくと、辞書的な順番の結果を得ることができると思う。


# 出典

https://bcp0109.tistory.com/14
HTTPサーバーの構築

# 概要
WEBサーバとして、「Apache」をインストールします。
構築する環境は、前回構築したVMware

# 目次
[インストール手順](#インストール手順)
[ホストマシンからWEBページを閲覧する](#ホストマシンからwebページを閲覧する)

# インストール手順
#### Apacheのインストール
```htlm:実行コマンド
# yum install httpd
```

#### Apacheの起動
```html:実行コマンド
# systemctl start httpd
```

#### 起動確認
Activeがrunningになっていることを確認する
```html:実行コマンド
# systemctl status httpd
```
#### 仮想マシン上の確認
WEBブラウザでURLにlocalhostと入力する
下記画面が表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459413/ab720635-f2da-f23e-31b1-c7d6e75e408f.png)

# ホストマシンからWEBページを閲覧する

#### 仮想マシンのIPアドレスを確認
```html:実行コマンド
# ifconfig
```
#### FWの設定確認
WEBブラウザのURLに仮想マシンのIPアドレスを入力し検索します。
下記のようになった場合はFWの設定不足です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459413/3e7b1b7e-30a4-00e8-331e-33f94ac93488.png)
仮想マシンで下記コマンドを実行し、FW設定でhttp通信が解放されていないことを確認します。
```html:実行コマンド
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens33
  sources: 
  services: dhcpv6-client ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
# 
```
#### FWの設定変更
http通信が行えるようにFWの設定を変更します。
実行コマンドは上から、httpの設定追加、リロード、一覧表示
```html:実行コマンド
# firewall-cmd --add-service=http --permanent

# firewall-cmd --reload

# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens33
  sources: 
  services: dhcpv6-client http ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
#
```
サービスにhttpが追加されました。
もし、上記設定でも駄目だった場合はポートの許可設定も行います。
実行コマンドは上から、80/tcpの設定追加、リロード、一覧表示
```html:実行コマンド
# firewall-cmd --add-port=80/tcp --permanent

# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens33
  sources: 
  services: dhcpv6-client http ssh
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules:
```
ホストマシンのWEBブラウザからも仮想マシンと同じような画面が表示されればOKです。
![http.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3459413/ec66e20c-7776-75e0-f50e-420b92b0b6df.png)
)
【Paiza問題集】文字列処理メニュー/1問～10問

# Paiza問題集
Pythonで回答

## 文字列処理メニュー/1問～10問

### 1問目 文字列の出力
```Python
"""
文字列の出力
https://paiza.jp/works/mondai/string_primer/basic_step1

問題
文字列 paiza を出力してください
"""

print('paiza')
```

### 2問目 文字列の受け取り
```Python
"""
文字列の受け取り
https://paiza.jp/works/mondai/string_primer/basic_step2

問題
1行で文字列Sが与えられるので、その文字列をそのまま出力してください
"""

print(input())
```

### 3問目 i文字目の出力
```Python
"""
i文字目の出力
https://paiza.jp/works/mondai/string_primer/basic_step3

問題
文字列Sと整数iが与えられるので、Sのi文字目を出力してください
"""

S = input()
i = int(input())

print(S[i-1])
```

### 4問目 文字列の条件判定
```Python
"""
文字列の条件判定
https://paiza.jp/works/mondai/string_primer/basic_step4

問題
1行で文字列Sが与えられるので、Sが "paiza" である時は "YES", そうでない時は "NO" を出力してください
"""

print('YES' if input() == 'paiza' else 'NO')
```

### 5問目 文字列の文字数
```Python
"""
文字列の文字数
https://paiza.jp/works/mondai/string_primer/basic_step5

問題
1行で文字列Sが与えられるので、Sの文字数を出力してください
"""

print(len(input()))
```

### 6問目 文字の検索
```Python
"""
文字の検索
https://paiza.jp/works/mondai/string_primer/basic_step6

問題
文字列Sと文字cが与えられるので、cはSの何文字目に現れるかを調べてください
"""

S = input()
C = input()


for i, str in enumerate(S):
    if str == C:
        print(i + 1)
```

### 7問目 文字列の連携
```Python
"""
文字列の連携
https://paiza.jp/works/mondai/string_primer/basic_step7

問題
与えられる文字列の数Nと、N個の文字列が与えられるので、それらを順に末尾に連結した文字列を出力してください
"""

N = int(input())
S = ""

for i in range(N):
    S += input()
print(S)
```

### 8問目 部分文字列
```Python
"""
部分文字列
https://paiza.jp/works/mondai/string_primer/normal_step1

問題
文字列Sと整数i,jが与えられるので、Sのi文字目からj文字目までの部分文字列を出力してください
"""

S = input()
i, j = map(int, input().split())

print(S[i-1:j])
```

### 9問目 文字列の挿入
```Python
"""
文字列の挿入
https://paiza.jp/works/mondai/string_primer/normal_step2

問題
文字列S,Tと、整数Nが与えられるので、SのN文字目の後ろにTを挿入した文字列を出力してください
"""

S = input()
T = input()
N = int(input())

print(S[:N] + T + S[N:])
```

### 10問目 文字列の書き換え
```Python
"""
文字列の書き換え
https://paiza.jp/works/mondai/string_primer/normal_step3

問題
文字列Sと整数iと文字cが与えられるので、Sのi文字目をcに書き換えたものを出力してください
"""

S = input()
i, c = input().split()
i = int(i)

print(S[:i-1] + c + S[i:])
```
Sphinxの書き方（リスト関連まとめ）

Sphinxの書き方をまとめたのですが、今回はリストの書き方をまとめてみます。

箇条書き
--------------

- 一つ目
- 二つ目

書き方
```
- 一つ目
- 二つ目
```

番号付きの箇条書き
-------------------------------------

1. 一つ目
2. 二つ目

書き方
```
1. 一つ目
#. 二つ目
```

初期値を設定した場合、設定した数値からの箇条書きを行うことができます。

リストのネスト
-----------------------

書き方
```
-親リスト

 - 子リストの1つ目
 - 子リストの2つ目

-親リスト
```

番号付きリストのネスト
-----------------------
書き方

```
#. 番号付き親リストの1つ目

  #. 番号付き子リストの1つ目
  #. 番号付き子リストの2つ目

#. 番号付き親リストの2つ目
```

英小文字を使用したリスト
---------------------------
書き方

```
a. 英小文字リスト1つ目
#. 2つ目
   サブリスト
```

英大文字を使用したリスト
-----------------------------
書き方

```
A. 英大文字を使用したリストの1つ目
#. 2つ目
#. 3つ目
   サブリスト
```


以上になります。
まだSphinxについて学び始めのため、誤りや補足等があればご指摘いただけるとありがたいです。
見ていただきありがとうございました。
[VSCode] venvで作成した仮想環境がkernel一覧に表示されないときの対処法

# 1. はじめに
VSCode で .ipynb ファイルを実行するには、カーネルを選択する必要がある。
セルを実行したり、右上の方にある "Select Kernel" ボタンを押したりすると、下のようなポップアップが出てきて、カーネル一覧が表示される。
![Screenshot 2023-05-31 at 23.02.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/d9f04b09-4148-5f48-661d-d5963d7ba7e9.png)
本来はこの写真のように venv で作成した仮想環境がカーネル一覧に表示されるはずなのだが、実行環境によっては何故か表示されないことがあった。
表示されない原因の究明はできていないが、下記の方法で解決することができた。
# 2. 対処法
## 2.1. 手順
仮想環境を activate した上で、仮想環境内で
``` 
$ ipython kernel install --user --name=test_venv --display-name=test_venv
 ```
を実行してカーネルを追加し、VSCode を再起動すると、Jupyter Kernel の中に
![Screenshot 2023-05-31 at 23.04.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/8ff9c3e6-6cb4-7204-f922-ae4c6c90061f.png)
![Screenshot 2023-05-31 at 23.04.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/36718664-18a4-0e06-565f-10e9cf8ca15d.png)
`ipython kernel install` で追加したカーネルが表示されるようになる。
## 2.2 コマンドのオプションなど
| オプション | 意味 |
| --- | --- |
| --user | 現在のユーザーのローカル環境に追加する |
| --name | Jupyter 内部におけるカーネル名。重複すると上書きされる |
| --display-name | 選択画面などで表示されるカーネル名 |

意図しない上書きを防ぐためには `--name` で指定するカーネル名には気をつけた方が良さそう。
# 3. 参考
* [Installing the IPython kernel — IPython 8.13.2 documentation](https://ipython.readthedocs.io/en/stable/install/kernel_install.html)
* [VSCodeのipynbファイルの「Select a Kernel」に、venvの環境が表示されないときの対処法 - ベスパリブ](https://takeg.hatenadiary.jp/entry/2021/05/22/165935)
* [Jupyterで複数カーネルを簡単に選択するための設定 - Qiita](https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e)
学内でAttack and diffence Pre大会を開いた話

## 筆者について
オンプレよりのインフラエンジニア。現在はコンテナ技術に興味がありK8sを触ったりしています。

## セキュリティの勉強は何からするべき？
情報セキュリティについての勉強はどこから始めるべきか少々戸惑う。しかし、よく考えてみれば自分が技術を学ぶ時にはやはり手を動かしながら理解を進めた。そのため、今回はCTFの中でも上級者向けであるAttack and difference形式の競技を開催する事とした。

## Attack and diffenceってどうやって準備すんの!??
実は筆者自体もAttack and difference 形式はおろか、CTFに参加した事がほとんどない。Jeopardy形式を何回か興味本位でやった事があるくらいである。。。。

そこで一番最初にぶち当たった問題は「Attack and Diffence」の環境ってどうやって準備するの？だった。
実際にAttack and Diffenceっ形式の大会に出るのが手っ取り早いが近場でやってるものも無かった。
ということで、今回は自分のイメージで開催する事とした。
また、弊学の頭文字がTということで、TAaD(T〇〇 Attack and Diffence)という名前で、コンセプトは「初心者用Attack and Diffence」で開催する事とした。



## TAaDについて
### 各チームの環境
| VM | 用途 | 個数 |
| -------- | -------- | -------- |
| kali     | 競技者用VM    | チーム人数分     |
| web    | 運用サーバー    | 1台    |


各チームに、競技用VM（環境内で実際に攻撃を行うVM）チームの人数分、webサーバー(これが脆弱性を持っている)を配布した。webサーバーは稼働している時間に応じてポイントが加算される。
ここで、なぜタイトルにPre大会とついたのかが分かる。今回はお試しで一回開催してみたかったので、運用するサーバーはwebのみとなっている。


### 競技の流れ
1. 各チームには上記の環境が配布される。
2. サーバーを運用している間はポイントが入り続ける。
3. 競技者は相手のチームのwebサーバーへの攻撃をして、運用を止める事と、自分のサーバーに存在するwebサーバーの脆弱性を潰す事を目標とする

#### TaaD特別ルール
セキュリティをばりばりにやっている人からすると反感を食らう様なルールを設けた。
こういった競技では、サーバーへの侵入を醍醐味としているのが一般的であると思うが今回は最初から各チームはお互いのサーバーへバックドアを持っている構成となっている。そのため、競技前にバックドアを仕込む事前準備を行った。

##### 事前準備
チーム１のwebサーバーには、チーム２、３のKaliのAuthorized_keyを登録

また、そのAuthorized_keysをそれぞれ好きな場所に好きな名前で配置

また、裏で好きな場所に置いたAuthorized_keysは、リネームして、.ssh/にリネームされて配置されるsystemdが動いている。

これによって、自分のwebに登録されているauthorized_keysを削除するまではバックドアが仕込まれている。

つまり、TAaDではゲーム開始時に相手のサーバーに侵入出来るようになっている。



### トポロジー
![taad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/dc8e76fb-4e00-7f79-f213-1789cff38afe.png)


### 開催結果
今回、本校の情報系研究室I研究室、K研究室、S研究室の3研究室からそれぞれ3人の合計9人で行った。

競技としては、K研究室がポイントを最も取った。しかし、最初からrootを取っている状態だと思った以上に攻撃の勢力が強い。せめて一般ユーザーにすべきだった。また、webの脆弱性自体ももう少し作り込むべきだったと課題が見えた。
Visual Studio 2022でGitHub Copilot chatを使う方法

「GitHub Copilot chat」が使えるようになったので、Visual Studio 2022で使ってみました。
その手順の説明です。

# 0. Copilot Chatの承認
[GitHub previews](https://github.com/features/preview)からCopilot chatの[Join the waitlist]をクリックしてウェイトリストに並びます。
許可されると以下のようなメールが来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/aa6aa044-0712-35d8-3911-c31d7afa73e6.png)


# 1. 拡張機能のインストール

機能を有効化するため[拡張機能] - [拡張機能の管理]でメニューを開いて、「Visual Studio Extension for GitHub Copilot Preview」をインストールします。(右上の検索で「Copilot」と検索すると楽)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/69bde73e-1c93-c760-c555-47da35148f0b.png)

# 2. Visual Studioにサインイン

Visual Studioの右上のボタンからサインインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/c8ce317a-18ab-4a4a-3fc9-ee03cc48d047.png)

# 3. GitHubへのサインイン

さらに、GitHubへもサインインが必要です。
右上のボタンから「アカウントの設定...」でダイアログを表示した後、GitHubの「資格情報を再入力する」からサインインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/45c14460-b6c2-5275-8804-41b0c37b724f.png)

# 4. GitHub Copilotの確認

これで準備は完了です。
表示に「GitHub Copilotチャット」が表示されたり、エディタ上で右クリックした際のメニューに「Copilotに質問する」が表示されていれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/4eae73f0-60e5-8026-e299-217a56ea32c3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/40627468-308f-40ed-b109-58c7b4b5b582.png)

# 5. トラブルシューティング

もし何か問題が発生した場合は、「出力」ウィンドウの「GitHub Copilot chat」を選択して、ログを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178867/5bf14ad2-339e-b09d-2b92-407b029d0187.png)

---------------------------------------

以上、Visual Studio 2022でGitHub Copilot chatを設定して使う方法についての解説でした。
GitHub Copilotは、コーディング作業を大いに助けてくれる優れたツールです。
ぜひこの記事を参考に、設定してみてください。
S4におけるインボイス対応

SAPの公式サイトには記載があるが、改めて備忘のために記載しておく。

# 消費税の端数計算

特にインボイス対応で計算方法を変更せずに今までどおりのロジックとなります。
その対応で、SAP社としては問題ないと考えているそうです。

具体的には、たとえば、今まで通りに以下となります。

消費税の端数処理は、FI 会計伝票単位で、税コード毎に行われます。


# 会社コードの消費税登録番号

会社コードの法人番号を保存する特定の項目が存在します。
そのため、その項目を利用します。


# 仕入先の消費税登録番号
仕入先マスタに項目が存在するため、その項目を利用します。

法人番号：仕入先マスタの項目の税番号 3 
消費税登録番号：仕入先マスタの項目の税番号 4
リスト内包表記について簡単にまとめてみた

### forループでリスト作るのめんどくさいぞ

2の累乗のリストを作るとする
forループを使うと
```python
a = []
for i in range(1,11):
  a.append(i*2)
print(a)
```
まあまあめんどくさい
これをリスト内包表記で書くと
```python
a = [i*2 for i in range(1,11)]
print(a)
```
となる
一行で書けてしまう圧倒的スマートさ
かっこいい。

慣れるまで少し時間がかかるかもしれないが、使いこなせればめちゃ便利

### リスト内包表記の書き方を学ぼう
文法としては

[式 &nbsp;&nbsp;&nbsp;for &nbsp;&nbsp;&nbsp;iなどの任意の変数&nbsp;&nbsp;&nbsp;  in &nbsp;&nbsp;&nbsp; range()などの範囲指定]

となる

いくつかの使用例を下記にまとめる

```python
b = [1 for i in range(10)]
print(b)
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

c = ["5" for i in range(10)]
print(c)
# ['5', '5', '5', '5', '5', '5', '5', '5', '5', '5']

d = [int(i) for i in c]
print(d)
# [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
```
（実際これらは指摘していただいた通り、他のやり方で十分かのうではある
pythonを触っていて内包表記でやると便利だった、と思ったことをこれからもここに追加していくとする）

最初に書く式というのは数式でもいいし文字でもいいし関数でもいい
リストcで'5'を十個格納したリストを作った、これをdでは全てをint型に直している
この時、range()を使わなくとも、cと書けばリストcの要素分forを回してくれる
Sphinxの文法まとめ

Sphinxを使用して仕事をする予定があるので簡単に文法をまとめてみました。
表などは次回に分けて記載していきます。

改行
---------
**強調** したい文字を**で囲む


```
**強調**
```




コードサンプル
------------------
````で囲むと```` コードサンプル変わる

```
````囲む````
```




フィールドリスト
---------------------
:フィールドリストは:  :で囲む

```
:フィールドリスト:
```

リテラルコードブロック
--------------------------

文章の後に ::をつける
```
次の行からリテラルコードブロックです。 ::

  ここからリテラルコードブロックです。
  リテラルコードブロック部分の改行は、
  ソースコードの内容がそのまま反映されます。

  - 改行もそのまま反映されます。

  リテラルコードブロック終了
```



見出しの書き方
------------------
見出し一覧 
--------------------------

```
  ########################
  h1
  ########################

  *********************
  h2
  *********************

  h3
  ==================

  h4
  --------------------

  h5
  ^^^^^^^^^^^^^^^^^^^

  h6
  """"""""""""""""""
```

今回は以上になります。
少しでも参考になれば嬉しいです。
v6プラスとPPPoEを同時に扱う

# 目的
一般のご家庭にある光回線で普段使い(ゲームなどの大容量高速通信）のためにv6プラス、サーバ用にPPPoEを使い分けられる環境を作ったよという話です。
値段と速いとの売り文句でv6プラスの光コラボを選んだ後でv6プラスの制約を知り、試行錯誤した結果であり、もっといい方法があればコメントいただければ幸いです。

# 環境
コラボ光: GMO光アクセス　ファミリー接続サービス
別途用意したプロパイダー: インターリンク ZOOT NEXT

# v6プラスは速いが制約がある
まずv6プラスでは固定IPが利用できないものが多いです。
DDNSを用意したとしても解放できるポートが決まっており、80や443などを開放することはできないようです。それ以外にもVPNやポートの決まっているゲームなどでも困ることがあるかと思います。(回線契約後に気づいて辛かったです。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522264/77ee0d57-86f2-0037-6fa9-97f3fd36dea2.png)
また対応機器を用意する必要があります。v6プラスを提供するプロパイダーからレンタルされたルータは当然対応していますが、別途用意する場合はIPv4overIPv6の規格(MAP-EやDS-Lite)に注意して用意する必要があります。これらの規格は日本のガラパゴス規格のため自作ルータでpfsenseやOPNsenseを使う場合は相当面倒な設定が必要になってきます。

しかし、逆に言えば固定IPやポート解放を使用しない、スマホや一般的なゲーミング用途の回線としてはv6プラスは非常に有用なものと言えます。

# PPPoEは遅い
PPPoEは遅いです。プロパイダーにもよるところが大きいのですが、今回GMO光のままPPPoEに変えてもらったところ普段使いには論外な速度(fast.comで数Mbps~数十Mbps程度)になってしまったため、人間向けにはIPoE、サーバ向けにはPPPoEという今回の環境を構築するに至りました。

# マルチセッションとは
一つの回線契約に複数のプロパイダーに同時接続するものです。
**ONU直下にハブを置き、分岐させて二つ以上のルータを使うことができます。** ~~知らなかった~~
参考
https://www.interlink.or.jp/service/flets/multisession.html
イメージとしてはこんな感じ
![Group 8 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522264/405d8201-6dd2-cfa4-80d7-a1ddb6e73b37.png)



標準で2セッションまで扱うことができます。IPoEであればセッション数は消費しないため理論上もう一つプロバイダーを用意することも可能でしょう。ひかり電話は起動時のみ1セッション消費するようです。

v6プラスはNTTから回線に割り当てられるIDに紐づくためv6プラスをこの方法で複数扱うことはできず、複数扱うには光ファイバーをもう一本引き込むことになるようです。

# 副産物
グローバルIPが二系統あるので、Webサーバが外から見た時どう振る舞うかの確認が簡単になりました。(これまではテザリングで確認していました)
また片方(PPPoEを想定)をサーバ専用にすれば、もう片方（v6プラスを想定）を友人に多少軽率に貸し出してもセキュリティが保てます。~~こうなってくると自作ルータで仕切る意味がもうないんよな...~~
プロパイダーの冗長性向上が見込めますがこれに関しては物理回線が死んだら両プロパイダー両方死ぬのであんまり意味ないかもです。

# デメリット
宅内のサーバでもグローバルIPを用いてアクセスするので、LAN内だからいいやーと雑に設定してあったNASをどうしようか迷っています。~~サーバ増やして外向きのサーバと宅内用サーバに分けようかな...~~
あと体感できるレベルではないですが一度外の回線を通ってサーバへアクセスするため多少ラグくなるとは思います。