OmniAICreator/Qiita-1.07M huggingface dataset:
【Laravel】一つのクエリでEagerロードと行ロックを実行したい

N+1問題を解決するためにEagerロードを使用すると思います。
また、行ロックをかけるためにlockForUpdateメソッドを使用すると思います。
Eagerロードと行ロックを一つのクエリで実行できます。

## Eagerロードと行ロック

一つのクエリでEagerロードと行ロックを実行するには、クロージャでクエリインスタンスを受け取り`lockForUpdate`メソッドを使用します。

```php
$books = App\Book::with(['author' => function($query) {
    $query->lockForUpdate();
}])->get();

foreach ($books as $book) {
    $book->author;
}
```

実行されたクエリを見てみましょう。

```sql
select * from `books`

select * from authors where id in (1, 2, 3, 4, 5, ...) for update"
```

Eagerロードされています。
`for update`により、しっかり行ロックもされています。

## 遅延Eagerロードと行ロック

遅延Eagerロードでも同様に、一つのクエリでEagerロードと行ロックを実行する事ができます。

```php
$books = App\Book::all();
$books->load(['author' => function($query) {
    $query->lockForUpdate();
}]);

foreach ($books as $book) {
    $book->author;
}
```
[iOS15 Safari] Canvas2Dの文字列描画でページがクラッシュする場合がある

# クラッシュする条件
* iOS 15 で Safari などの AppleWebKit エンジンを使用しているブラウザ。
* Canvas2D で ASCII 文字以外を描画しようとしている。
* font-family に `-apple-system` が含まれている。
* フォント設定値が `20px -apple-system` のように、font-size と `-apple-system` が隣接している。

# 問題のコード
```main.js
let ctx = canvas.getContext("2d");
ctx.font = "20px -apple-system";
ctx.fillText("日本語文字列", 20, 20);
```

https://codepen.io/inonote/pen/ZEyRWqg

# 解決方法
:::note warn
**2021-09-26 追記**
以下の方法を行うと -apple-system 指定が実質されていないに等しい挙動をすることが判明したため、現状 -apple-system を外すか、Apple の対応を待つしかないと思います。
:::
`20px x -apple-system` のように、font-size と font-family の間に必ずフォント設定値と認識されない任意の文字列を挟むようにする。

# その他
html2canvas もこの問題に巻き込まれるので、この場合は CSS に対して上の解決方法を適用すると良い。
遺伝的浮動のシミュレーション：R


河田研のサイトにRで行う、遺伝的浮動のシミュレーションが載ってたのでやってみました。

https://klabosendai.wixsite.com/mysite/blank-12

###ちなみに
私は、Rstudioで動かしてます。
別にどっちでも問題ないと思いますが、個人的には楽なのでRstudioが好きです。
>なんでもかんでもAnacondaから起動させちゃうマン

##スクリプトファイルの作成

まず、シミュレーションを実行するためのスクリプトファイルを作ります。
サイトにはコピペしろって書いてありますが、コピペしてもエラーでます。

ので、以下に書き換えました。

```
drift <- function(N,iFreq,Gen,Rep){
  Frequency<-numeric(Gen+1)
  Num<-numeric(Gen+1)
  Generation<-numeric(Gen)
  par(new=F)
  
  for(j in 1:Rep){
    Frequency[1]<-iFreq
    for(i in 1:Gen){
      Generation[i]<-i
      Num[i]<-rbinom(1,N,Frequency[i]) 
      Frequency [i+1]<-Num[i]/N
      }       
     Generation[i+1]<-i+1
     plot(Generation,Frequency,ylim=c(0,1),xlim=c(1,Gen),type="l",lty=1)
     par(new=T)
     }
  }
```

スクリプトはこれでおっけーです。
Source on Save で保存します。
名前はなんでもいいですが、元サイトに則り'drift.R'とします。

##ファイルの実行

![スクリーンショット 2021-09-21 22.19.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/7cc42b36-f202-111c-c29a-10a817e09868.png)

Rstudioの作業環境です。
右上のSource→を押します。

もしくは

```
source("drift.R")

```

でファイル内のコマンドを実行します。

##シミュレーション

シミュレーションの実行です。
こうやります。

```
drift(10, 0.5,50,1) #個体数(10)遺伝子頻度(0.5)世代(50)実行回数(1)

```

上記の結果

![スクリーンショット 2021-09-21 22.47.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/64921d63-e688-63e4-ac96-6ecbe32f7b0c.png)

実行回数(100)の場合の結果

![スクリーンショット 2021-09-21 22.48.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/68585eaa-3dce-26b6-0c8d-fa1e347d4688.png)

個体数(10)遺伝子頻度(0.5)世代(100)実行回数(1000)の場合

![スクリーンショット 2021-09-21 22.51.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/7a758816-2ed1-8564-b636-8c038f408481.png)

##更新：色分け
@StrawBerryMoon様に色分けを提案していただきました！
楽しさ倍増ですね。

````
drift <- function(N,iFreq,Gen,Rep){
  Frequency<-numeric(Gen+1)
  Num<-numeric(Gen+1)
  Generation<-numeric(Gen)
  par(new=F)

  for(j in 1:Rep){
    Frequency[1]<-iFreq
    for(i in 1:Gen){
      Generation[i]<-i
      Num[i]<-rbinom(1,N,Frequency[i]) 
      Frequency [i+1]<-Num[i]/N
      }       
     Generation[i+1]<-i+1
     plot(Generation, Frequency, ylim=c(0, 1), xlim=c(1, Gen), type="l", lty=1, col=j)
     par(new=T)
     }
  }
```

```
drift(10, 0.5,50,100)
```

![スクリーンショット 2021-09-22 0.49.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/0165af9a-3ce0-50f4-4b8c-8c01ea9cd6c5.png)

```
drift(100, 0.5,1000,100)
```


![スクリーンショット 2021-09-22 0.50.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572428/08a3d489-3ee3-1f3a-027d-7ba3ef36f8f4.png)




##感想

楽しい！
条件を変えて色々試すとめちゃくちゃ楽しいです。
数が多いほどワクワクしました。

みなさんもぜひ




##宣伝

こういうのやってます。

https://flcl-browser.studio.site/page

学生のみなさん気軽に遊びに来てください。
ハイレベルな研究者（私は除く）がLTしてます。

Gatherにてアフタートークも設けているので、
他分野の研究者と交流を深めたり、研究の悩みを共有しやすいと思います。
「オンサイトの学会が激減した今こそ、オンラインで輪を広げよう」みたいな企画なので、沢山の参加者がいるとうれしいです。

たたた
Visual Studio Codeの内部ターミナルにCmderを移植する

# はじめに

* 年々VSCodeが便利になり嬉しい
    * 最近ではVSCodeのIntegrated Terminalがエディタと同レベルのタブとして扱えることに感動した
* 自分は普段WindowsのターミナルエミュレータとしてCmderを愛用，VSCodeの内部ターミナルでCmder (Bash)をそのまま使えるようにした
    * 調べたらよくヒットするinit.batやvscode_init.batと言ったバッチファイルを使ったcmd.exe (bash風)の設定でなく，bash.exeが対象
* 記事執筆時のVSCodeのバージョンはVSCode-win32-x64-1.60.1
* 本設定はStep1とStep2で完了する

# Step1: プロファイルの設定

VSCodeの設定画面で`terminal integrated profile windows`と検索すると2項目がヒットする．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/46fe1371-71aa-0b03-6d82-893f4c8bad30.png)
まずはこれについて設定する．

`Terminal >Integrated > Profiles: Windows`項目の`settings.jsonで編集`を選択し，VSCodeの設定JSONファイルを開く．
![hoge01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/632bb9d7-74e7-3986-cf4d-b600e09e00ed.png)
上図の様に設定ファイルの該当箇所，`terminal.integrated.profiles.windows`へフォーカスが移る.
Cmder用に新しく追加するオブジェクトは図中赤枠である．
オブジェクト名は判別できれば何でも良い．
キーであるpathはCmderで普段bashとして使っているbash.exeの場所を指定する．
bash.exeの場所はCmderを起動して下図のように設定を起動し，起動>タスクのbash項目を見ると分かる．
赤枠で囲っている箇所が対象のpathとなる．
![hoge02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/024f6d2c-44fb-fd41-9d42-97cdd3c91039.png)
環境変数%ConEmuDir%に関しては，Cmder Bashで`echo $ConEmuDir`をコマンド実行すればパスが分かる．

argsは起動する際の引数を指定するキー，こちらはCmderの設定画面で見たとおり`--login -i`を指定する．

以上を設定し終え，最初の図に戻り`Terminal > Integrated > Default Profile: Windows`をここで設定したプロファイルに変更することでStep1は完了となる．

# Step2: 環境変数の設定

環境変数の設定と言ってもWindowsの環境変数でなく，VSCodeが内部ターミナルで使う環境変数の設定を行う．

ここで試しにStep1で設定したターミナルプロファイルを内部ターミナルで開いてみてほしい，起動と同時に設定ファイルやらが無いと出てくるはず．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/2c35f80e-54dd-9f13-846b-28e5a31f6926.png)
Step2はこれを解決する．

方法は，3つの環境変数`$CMDER_ROOT`，`$ConEmuDir`，`$ConEmuBaseDir`をStep1同様Cmderにてechoコマンドを通して調べ，判明したpathをVSCodeで設定する．
下図のようにVSCode設定画面にて`terminal integrated env`と調べ，ヒットした項目から赤枠`Terminal > Integrated > Env: Windows`を設定する．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/30f8a5ea-193f-6875-afc6-e5e702c5f17e.png)
settings.jsonで編集を選択し，フォーカスした`terminal.integrated.env.windows`オブジェクトを設定していく．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143895/8cd62c71-62b2-f67f-91ed-f4e2c803f7e3.png)
キーは上図の様に`CMDER_ROOT`，`ConEmuDir`，`ConEmuBaseDir`とCmder側の環境変数名と合わせ，pathはCmderで調べたパスをそのまま設定することでStep2は完了する．

# おわりに

* Cmderのbash.exeをVSCodeの内部ターミナルで使用することが出来る
* コンソールを利用する開発では何かとbashの方が都合が良いときもあるため重宝する(Rustのcargoやpythonやシェル芸開発とか)
Python初心者のThousandeyesログ取得

# この記事を読む方へ
基本的には個人の備忘録です。
私自身、主業務がネットワークだったこともあり、Pythonは触ったことがありませんでしたが、ネットワークの品質測定でThousandeyesを使い始めたため、ThousandeyesのAPI経由でログ取得が必要となりました。
Thousandeyesはナレッジが充実しており、素養のある人間が調べればログの取得方法はすぐに分かるようになっていますが、Python素人にはハードルが高かったこと、Qiita等に簡単な取得方が掲載されていなかったこともあり、記事を残すことにしました。

下記コードの動作は確認していますが、ID/Token以外にもユーザ固有値が必要となることから、詳細はやはり正規リファレンスを参照頂ければと思います。
[Thousandeyes Reference](https://developer.thousandeyes.com/v6/)

# 動作環境
Google Colab

# コードの概要
`start`で指定した日時から、`end`の日（時間帯指定なし）までのweb_http testのレスポンス情報を取得
編集後処理のためにDF化

```
from urllib.parse import quote
import json
import requests
import pandas as pd

email = quote("")               #thousandeyesのログインID(メールアドレス)の"@"を"%40"に変換
authToken= quote("")　          #API Tokens

start = "2021-09-08T00:00:00"   #取得開始日時：thousandeyes指定のtime rangeで指定
end = "2021-09-19"              #取得終了日時：今回は適当な時間まで取得できればよかったので、thousandeyes指定のto=""での指定はしてません

url = "https://{}:{}@  ****  .json?from={}".format(email,authToken,start)
                                # 上記　****　は取得したいデータ毎にユーザ固有値を入力
                                # 例：api.thousandeyes.com/v6/web/http-server/2245279

page = requests.get(url)
test = page.json()

# レスポンス取得
def get_res():
  date_list = []
  response_list = []

  for i in test['web']['httpServer']:
    date_list.append(i['date'])
    try:                                      #測定エラーによりキーがない場合があるため例外処理を実施
      response_list.append(i['responseTime']) #レスポンス以外を取得したい場合はここのキーを変更、または増やせば複数取得可
    except KeyError:
      response_list.append(None)

  http_data = {"date":date_list,
               "response":response_list}
  return http_data

df = pd.DataFrame(get_res())                  #編集のためと、下で終了日確認のためDF化

# Next部分の取得 endの日付まで
# thousandeyesは一度に1000レコードまでしかはかないので、1000レコードを超える範囲は
# Nextキー内のURLにアクセスし、ループ処理で取得し続ける必要あり

while df.iloc[-1,0].split(" ")[0] != end:
  try:
    if test['pages']['next']:
      url = test['pages']['next']
      url = (url.split("//")[0]+"//{}:{}@"+url.split("//")[1]).format(email,authToken)
      page = requests.get(url)
      test = page.json()
  except KeyError:
    pass
  df = pd.concat([df, pd.DataFrame(get_res())], axis=0)

print(df)                 #indexは0-999がループしますが、df.reset_index(drop=True)等で対処ください
```
Flutterで音声読み上げライブラリ(flutter_tts)を使ってみる


flutterにもiOSのAVSpeechSynthesizerのような音声読み上げをしてくれるライブラリ、
[flutter_tts](https://pub.dev/packages/flutter_tts)があります。

基本的には、AVSpeechSynthesizerと同じで
・音声言語
・再生速度
・音声のピッチ
が選択できます。

※対応SDKが21以上なので、自身で設定しているminSdkが満たしているか留意する必要があります。
##使用可能言語
【言語コード - 国名コード】で指定します。

|言語指定で使う表記|説明|
|:--|--:|
|nl-BE|	オランダ語、ベルギー|
|hu-HU|	ハンガリー語|
|he-IL|	ヘブライ語|
|fi-FI|	フィンランド語|
|it-IT|	イタリア語|
|pt-BR|	ブラジルポルトガル語（ブラジル語）|
|en-US|	英語|
|ro-RO|	ルーマニア語|
|el-GR|	ギリシャ語|
|sk-SK|	スロバキア語|
|sv-SE|	スウェーデン語|
|th-TH|	タイ語|
|no-NO|	ノルウェー語|
|zh-CN|	中国語|
|pl-PL|	ポーランド語|
|ru-RU|	ロシア語|
|tr-TR|	トルコ語|
|zh-TW|	中国語、台湾|
|en-GB|	英語|
|en-IN|	英語、イングランド|
|cs-CZ|	チェコ語|
|es-ES|	スペイン語|
|en-AU|	英語、オーストラリア|
|pt-PT|	ポルトガル語|
|zh-HK|	中国語、香港|
|id-ID|	インドネシア語|
|ko-KR|	韓国語|
|en-IE|	英語、アイルランド|
|nl-NL|	オランダ語|
|hi-IN|	ヒンディー語|
|fr-FR|	フランス語|
|en-ZA|	英語、南アフリカ|
|ja-JP|	日本語|
|es-MX|	スペイン語、メキシコ|
|da-DK|	デンマーク語|
|de-DE|	ドイツ語|
|ar-SA|	アラビア語|
|fr-CA|	フランス語、カナダ|

##簡単な実装
今回こちらを使って、英単語の音声読み上げを行ってみました。
単語帳アプリなどで応用できそうですね。
以下はProvider: StateNotifierで作製したcontrollerクラスの中身です。

~~~Dart
final FlutterTts flutterTts = FlutterTts();

void speak() {
  await flutterTts.setLangauge("en-US");
  await flutterTts.setSpeechRate(0.4); //1.0にするとめちゃくちゃはやかった
  await flutterTts.setPich(1.0);
  await flutterTts.speak("Autumn");
}
~~~

####再生中にボタンアイコンなどを変化させたいとき
UIを少し面白くするために、音声読み上げ中は異なるアイコンを表示させようとしました。
`isSpeaking`というbool値を用いて、trueの時は読み上げ中用のアイコンを、falseの時は音声読み上げボタンを表示しています。

~~~Dart
final FlutterTts flutterTts = FlutterTts();

void speak() {
  state = state.copyWith(isSpeaking: true);
  await flutterTts.setLangauge("en-US");
  await flutterTts.setSpeechRate(0.4); 
  await flutterTts.setPich(1.0);
  await flutterTts.speak("Autumn");
  state = state.copyWith(isSpeaking: false);
}
~~~
#####注意
単語のような短いものを読み上げさせるとすぐに終わってしまうので、viewの再描画が追い付かず期待していた変化をさせることができませんでした。
解決法として、speak関数実行後に数ミリ秒Durationさせることで調整しました。
Consumer等で描画範囲を指定することでも解決できるかもしれません。

~~~Dart
void speak() {
  state = state.copyWith(isSpeaking: true);
  await flutterTts.setLangauge("en-US");
  await flutterTts.setSpeechRate(0.4); 
  await flutterTts.setPich(1.0);
  await flutterTts.speak("Autumn");
  await Future.delayed(Duration(miliseconds: 500));
  state = state.copyWith(isSpeaking: false);
}
~~~

##参考にさせていただいた記事
https://qiita.com/kazutxt/items/e730e586061efc68b7bf
【ラビットチャレンジ】深層学習day1

#Section1：入力層〜中間層
●ニューラルネットワークに何らかの入力をする部分
●入力、重みは行列で表すことができる
　総入力：u=Wx+b
　内積を使うことで入力の重要度を表現することができる
　傾きだけでは表現できないu方向のずれをバイアスで表現することができる。
●傾き、切片を学習させることがニューラルネットワークの肝

[確認テスト]
●この図式に動物分類の実例を入れてみよう。
　・体長、体重、ひげの本数、毛の平均長、耳の大きさ、眉間/目鼻距離比、足の長さ

[確認テスト]
●Wx+bをPythonで書け
　・u1 = np.dot(x, W1) + b1

[確認テスト]
●1-1のファイルから中間層の出力を定義しているソースを抜き出せ。
　・u2 = np.dot(z1, W2) + b2
　　z2 = functions.relu(u2)

#Section2：活性化関数
●非線形の関数を使うことでニューラルネットワークの処理の幅が広がる
●中間層用の活性化関数
　・ステップ関数
　　→現在は使われることのない関数
　　→線形分離可能なものしか学習できない。
　・シグモイド関数
　　→最も一番最初の方に使われた関数
　　→なだらかなので微分可能
　　→勾配焼失問題を引き起こすことがある
　・ReLU関数
　　→最も使われている関数
　　→勾配焼失問題の回避とスパース化に貢献する

[確認テスト]
●線形と非線形の違いを図に書いて簡易に説明せよ。
　・線形な関数は加法性、斉次性を満たす。
　　非線形な関数は加法性、斉次性を満たさない。

[確認テスト]
●配布されたソースコードより該当する箇所を抜き出せ。
　・z1 = functions.relu(u1)

#Section3：出力層
●出力層の役割
　・各クラスの確率を出す
　・実際にニューラルネットワークを学習させる部分
●誤差関数
　・出力と入力された訓練データを誤差関数に通すことで、
　　間違え度合いを表現することができる。
　・2乗することで、すべての値を正の値になるようにする。
　・2分の1することで、誤差関数の微分が簡単になる。
●出力層の活性化関数
　・中間層はしきい値の前後で信号の強弱を調整するが、
　　出力層は信号の大きさ(比率)はそのままに変換する。
　・分類の問題の場合、出力層の出力は0〜1の範囲に限定し、総和を1にする必要がある。
　・恒等写像
　　→回帰に利用。何もしない関数。
　・シグモイド関数
　　→二値分類に利用。
　・ソフトマックス関数
　　→多クラス分類に利用される。
　・誤差関数
　　→回帰では、二乗誤差を利用。
　　→二値分類、多クラス分類では、交差エントロピーを利用。

[確認テスト]
●①〜③の数式に該当するソースコードを示し、一行づつ処理の説明をせよ。
　・def softmax(s):
　・ミニバッチとしてデータを取り扱う
　・オーバーフロー対策
　・① = ② / ③

[確認テスト]
●①〜②の数式に該当するソースコードを示し、一行づつ処理の説明をせよ。
　・def cross_entropy_error(d, y):
　・全部並べる
　・教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
　・① = ②
　　→y：0か1が並んでいる
　　→batch_size：ミニバッチの何番目か。
　　→d：d番目は0or1か。
　　→1e-7：対数関数で0の場合、-∞となるため。

#Section4：勾配降下法
●勾配降下法
　・誤差を最小化するwを発見する
　・学習率が大きすぎた場合、最小値にいつまでも辿り着かず発散してしまう。
　　学習率が小さい場合、発散することはないが、
　　小さすぎると収束するまでに時間がかかってしまう。
　　また、途中で学習が終わってしまうことがある。
　・アルゴリズム
　　→Momentum
　　→AdaGrad
　　→Adadelta
　　→Adam ※非常によく使われる
　・誤差関数の値をより小さくする方向に重みW及びバイアスbを更新し、次の周(エポック)に反映。

●確率的勾配降下法(SGD)
　・学習するデータから一部分を使って学習する方法。
　・毎回違う学習セットを使って学習する。
　・局所極小解に収束しにくくなる。
　・オンライン学習ができる。

●ミニバッチ勾配降下法
　・ランダムに分割したデータの集合に属するサンプルの平均誤差
　・一般的によく用いられている手法
　・確率的勾配降下法のメリットを損なわず、計算機の計算資源を有効利用できる。
　　→CPUを利用したスレッド並列化やGPUを利用したSIMD並列化

●誤差勾配の計算
　・数値微分のデメリット
　　→順伝搬の計算を繰り返し行う必要があり負荷が大きい。
　　 そのため、誤差逆伝播法を利用する。

[確認テスト]
●該当するソースコードを探してみよう。
　・1_3_stochastic_gradient_descent

[確認テスト]
●オンライン学習とは何か。
　・学習データが入ってくるたびに都度パラメータを更新し、学習を進めていく方法。
　　一方、バッチ学習では一度にすべての学習データを使ってパラメータ更新を行う。

[確認テスト]
●w^(t+1) = W^(t) - ε▽Etの意味を図に書いて説明せよ。
　エポック　重み
　t　　　　w^t　　　　-ε▽Et
　t+1　　　w^(t+1)　-ε▽Et+1
　t+2　　　w^(t+2)

#Section5：誤差逆伝播法
●誤差逆伝播法
　・誤差から微分を逆算することで、
　　不要な再帰的計算を避けて微分を算出できる。

[確認テスト]
●誤差逆伝播法では不要な再帰的処理を避けることができる。
　既に行った計算結果を保持しているソースコードを抽出せよ。
　・1_3_stochastic_gradient_descent
　　58行目、67行目

[確認テスト]
●2つの空欄に該当するソースコードを探せ。
　・58行目、67行目、74行目
jQueryを用いたHTML, CSS要素の操作の基本

この記事は以下のUdemyの講座のSection58~65の内容をまとめたものです（お世話になってます、、

https://www.udemy.com/course/javascript-kouza/

#### 1. **要素内の文字の取得、書き換え**

```jsx
// 文字列はtextメソッドを用いる
$("h1").text(); //=> "Template"  // 取得
$("h1").text("aaa"); //=> <h1>aaa</h1>  // 変更
```

#### 2. **要素内の HTML の取得、書き換え**

```jsx
// HTMLはhtmlメソッドを用いる（以下ではclass="form-group"が複数個あるページを扱う
$(".form-group").eq(0).html(); //=>  '\n<label>名前</label> \n<input type="text" id="name" name="name" value="Mike" class="form-control">\n'
// 指定の要素のページ内の数を求める
$(".form-group").size();
// 要素の置き換え
$(".form-group").eq(0).html("<h2>置き換える</h2>") //=> "<h2>置き換える</h2>"
```

注意点としては、置き換えられるのは、以下のように指定したhtml要素の内側の部分のみ

```jsx
$(".form-group").eq(0).html("<h2>置き換える</h2>");
/*
<div class="form-group">
	<h2>書き換える</h2>
</div>
*/
```

#### 3. **要素の属性の取得、書き換え**

```jsx
$("input").eq(0).attr("id"); //=> btn1
$("input").eq(0).attr("id", "btnX"); //=> btnX(btn1がbtnXに変わる
```

#### 4. **要素の CSS の取得、書き換え**

```jsx
$("input").eq(0).css("backgroud"); //=> #fff
$("input").eq(0).css("backgroud", "#f00"); //=> #f00（#fffが#f00に変わる
```

#### 5. **Webページのタイトルを取得、書き換え**

```jsx
document.title; // 現状のタイトルの文字列を得る
document.title = "書き換え"; // タイトルを変更する
```

#### 6.  **jQuery で要素を作り、末尾や先頭に追加**

```jsx
const element = $("<h1>New Title</h1>");
$("body").append(element); // bodyタグ内の末尾に追加
$("body").prepend(element); // bodyタグ内の先頭に追加
// "body"部分以外にも、指定できるセレクターであれば、先頭・末尾に追加可能
```

#### 7. **要素の絞りこみ**

```jsx
$("div").filter(".form-group");
$("div.form-group") // 上記と同じ
```

#### 8. **子要素を探す**

```jsx
$("div").eq(0).children(); // 1つ目のdivタグ内の、一階層目の子要素を検出する（それ以下は検出されない
$("div").eq(0).children("button"); // 1つ目のdivタグ内の、一階層目の子要素の内buttonタグのみを検出
$("div").eq(0).find("button"); // 1つ目のdivタグ内の、子要素の内全てのbuttonタグを検出
// $("div").eq(0).find(); この返り値は空
```

#### 9. **親要素を探す**

```jsx
$("label").eq(0).parent(); // 引数を指定することも可能
$("label").eq(0).parents(); // 親要素全てを取得
$("label").eq(0).parents("body"); // 全ての親要素のうちbodyタグのみ指定
```
ABC121 C - Energy Drink Collector を解いた

https://atcoder.jp/contests/abc121/tasks/abc121_c

![abc121_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/c1f29d63-0c90-5833-36d6-4f236d7a27a7.png)
![abc121_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/7830965f-0f5f-f276-d5f6-7c05d61666cc.png)
![abc121_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/f27cf007-fa55-793c-996e-0534af940805.png)
![abc121_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/d372200c-41bf-b3e0-aced-d96bb4065b7e.png)

貪欲的な感じで Ai,Bi のリストをソートし、
最安値のモノから買い占めればよろしいのでは？以下で通った。

```EnergyDrinkCollector.py
N,M = map(int,input().split())
lis = []
for _ in range(N):
    a,b = map(int,input().split())
    lis.append([a,b])
lis = sorted(lis,key=lambda t:t[0])
score = 0
for a,b in lis:
    if M == b:
        score += a*b
        break
    elif M-b > 0:
        M -= b
        score += a*b
    else:
        score += a*M
        break
print(score)
```
Pythonをインストール

## 1. Homebrewのインストール
  ターミナルを開いて以下のコマンドを実行する  。

```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"  
```

## 2. pyenvのインストール 
以下のコマンドを実行  する。
 
```
$ brew install pyenv  
```

## 3. pyenvの設定 
以下のコマンドを実行 

```
 $ echo $SHELL  
```

・実行結果が 
/bin/bash の場合、以下４つのコマンドを実行  する。

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile  
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile  
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile  
$ source ~/.bash_profile   
```

・実行結果が /bin/zsh の場合、以下４つのコマンドを実行  する。

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc  
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc  
$ echo 'eval "$(pyenv init -)"' >> ~/.zshrc  
$ source ~/.zshrc  
```
## 4.  Pythonのインストール
以下のコマンドでPythonをインストールします。

```
 pyenv install [インストールしたいPythonのバージョン]
```

以下のコマンドでインストールできるPythonのバージョンが確認できます。

```
 pyenv install --list  
```

以下のコマンドを実行してインストールしたPythonのバージョンが表示していれば完了です。 

```
python —version 
```

## 参考文献
https://prog-8.com/docs/python-env
https://qiita.com/zaburo/items/29fe23c1ceb6056109fd
https://qiita.com/koooooo/items/b21d87ffe2b56d0c589b
【XD】このファイルは新しいバージョンの Adobe XD で保存されています… と出た時の対処方

## 「このファイルは新しいバージョンの Adobe XD で保存されています。Adobe XD をアップデートして開いてください。」というエラーが出た
デザインの元ネタを確認したい時にXDファイルを見ることが稀にあり、
久々にアプリを起動したら、見慣れないエラーが表示されてファイルを開く事が出来なかった。
![スクリーンショット 2021-09-21 12.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/4ae9b846-1bf0-81d3-0d90-49763c1b962b.png)
結論としてはアラートで出ている通り、XDをアップデートしてあげる事で改善する。
以下はその手順。前提として今回はmacでの作業となります。

1. Creative Cloud を開く
2. アプリタブを開く
3. アップデートメニューを開く

![スクリーンショット 2021-09-21 12.27.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/eed648be-d1bc-f27a-99d9-aa6a740734ee.png)

画像は更新後のものとなりますが、アップデートする内容がある時はアップデートする、みたいな表示がありますので、クリックしてXDの更新を進めてください。更新完了後に先程開けなかったXDファイルが開けるようになっていればOKです。
【備忘録】bundletool を使った Play Asset Delivery 対応の Android App Bundle の検証手順まとめ

# 略称

- PAD：Play Asset Delivery
- AAB：Android App Bundle

# ■ はじめに

CIやデプロイのツール上で走らせたかったので bundle ツールを使った検証手順を調べていましたが、情報が少なく自分が困ったので情報としてまとめておこうと思いました。

# 前提条件

PAD のシステムについては詳しく記載しません。
予めご了承ください。

# ■ 配信方法のおさらい
PAD には3種類の配信方法がある。

- install-time 配信
アプリ起動時に既にインストールされていることが保証されている配信方法。
APK の assets フォルダに該当する。

- fast-follow 配信
ストアからアプリをダウンロード後にダウンロードが開始される配信方法。
アプリ起動時にダウンロードが終わっている保証が無いため、ダウンロードが完了しているか確認する必要がある。

- on-demand 配信
アプリ起動後からダウンロードが開始される配信方法。
fast-follow 配信同様にダウンロードが完了しているか確認する必要がある。

# bundletool の使い方・各種オプション
公式ドキュメントにございますのでこちらをご確認ください。

- [bundletool - Android developers](https://developer.android.com/studio/command-line/bundletool?hl=ja)

# ■ それぞれの検証手順
## ▼ install-time 配信のみの場合
### ○ 概要
install-time 配信のみの場合はAssetPackのダウンロードが必要ありません。
build-apks のオプションに `--mode=universal` という物があり、
ファイルサイズは大きくなりますが端末汎用のAPKを生成出来ますのでそちらを使います。

### ○ 検証手順
①. aabファイルを作っておきます。

②. 下記シェルを実行し、aab ファイルから apks ファイルを生成します。

``` build-apks.sh
bundletool build-apks --overwrite \
                      --mode=universal \
                      --bundle=${aabファイルまでのパス} \
                      --output=${apkセットファイルの出力先} \
                      --ks=${キーストアファイルのパス} \
                      --ks-pass=pass:${キーストアファイルのパスワード} \
                      --ks-key-alias=${エイリアスを指定} \
                      --key-pass=pass:${エイリアスのパスワード}
```

③. ②で生成した apks ファイルを7-zipなどのアーカイブツールで開き、`univarsal.apk` というファイルを取り出します。

④. ③で取り出した `univarsal.apk` をAndroidデバイスへインストールして検証。

## ▼ fast-follow 配信か on-demand 配信の場合
### ○ 概要
こちらの2つに関しては、通常GooglePlay上からAssetPackをダウンロードしてくる必要があります。
しかし、ローカル環境で検証する場合は、ダウンロードをしないで検証を行うことが可能です。

build-apks のオプションの `--local-testing` を使います。
こちらを付けることで GooglePlayConsole に aab ファイルをアップロードしなくても動作チェックを行えるようになります。

### ○ 検証手順
①. aabファイルを作っておきます。

②. 下記シェルを実行し、aab ファイルから apks ファイルを生成します。

``` aab2apks.sh
$ bundletool build-apks --overwrite \
                        --local-testing \
                        --bundle=${aabファイルまでのパス} \
                        --output=${apkセットファイルの出力先} \
                        --ks=${キーストアファイルのパス} \
                        --ks-pass=pass:${キーストアファイルのパスワード} \
                        --ks-key-alias=${エイリアスを指定} \
                        --key-pass=pass:${エイリアスのパスワード}
```

③. ②で生成した apks ファイルを bundletool 経由でAndroidデバイスへインストールして検証。

``` apks-install.sh
$ bundletool install-apks --apks ${apkセットファイルのパス}
```

### ○ 注意点
この方法ですとダウンロード関係のチェックは行なえません。
ダウンロードも含めてのチェックを行いたい場合は、
GooglePlayConsoleの内部テスト等にaabファイルをアップしてダウンロードチェックを行ってください。

# ■ まとめ
凄くざっくりではありますが検証手順をまとめました。
もしかしたら、もっと便利な方法があるかも知れませんので分かったら改めてまとめていこうと思います。
PowerAppsでTeams投稿アプリを作成する②

#選択したメッセージへの返信機能の作成

##前置き
本記事は[PowerAppsでTeams投稿アプリを作成する①](https://qiita.com/zaki_001/items/648256d4df9f0eb892ac)の続きです。
##作成するもの
前記事で、PowerAppsの画面上で選択したチーム・チャンネルに、任意のメッセージをサブジェクト付きで投稿する機能を実装しました。今回はこれに、既に投稿されたメッセージへの返信の形で投稿する機能を追加していきます。
また、今回もひとまずポカよけとかは考えず最低限動くだけの処理を実装することにします。

アプリの操作イメージはこんな感じ↓

1. コンボボックス１にチーム一覧を表示させ、投稿したいチームを選択する
1. コンボボックス２に、↑で選択したチーム内のチャンネル一覧を表示させ、投稿したいチャンネルを選択する
1. コンボボックス３に、↑で選択したチャンネル内のメッセージ一覧を表示させ、返信したいメッセージを選択する
1. 投稿したい内容（本文）を入力する
1. 返信ボタンを押し、選択したチャンネルに投稿する

##1.コントロールの配置
前回作成したアプリに、下図の通り返信先メッセージ選択コンボボックス(` ComboBox_Message`)とTeams返信ボタン(` Button_Reply`)を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/aaf7b8d8-d69b-c14d-7892-ac0275219234.png)

##2.メッセージ一覧の取得
` ComboBox_Message`コンボボックスでメッセージ一覧を表示できるようにします。
Teamsのメッセージ一覧は[GetMessagesFromChannel](https://docs.microsoft.com/ja-jp/connectors/teams/#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E5%8F%96%E5%BE%97-(%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC))コマンドで取得できますが、引数にチームIDとチャンネルIDを指定する必要があります。

ここでは、` ComboBox_Team`コンボボックスで選択したチーム内の、` ComboBox_Channel`コンボボックスで選択したチャンネルのメッセージ一覧を表示させるため、` ComboBox_Message`の`item`プロパティを下記のように変更します。

```:ComboBox_Messageのitem
MicrosoftTeams.GetMessagesFromChannel(ComboBox_Team.Selected.id,ComboBox_Channel.Selected.id).value
```
また、` ComboBox_Team`のときと同様にプロパティのフィールド 編集をクリックし、` 主要なテキスト`と` SearchField`を両方とも` subject`に変更し、`複数選択の許可` はオフにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/4a0d40fe-c48f-af84-c33f-16b39ba781f9.png)

##3.返信ボタンの処理作成
` Button_Reply`ボタンを押すと返信メッセージが投稿されるよう、`OnSelect`プロパティを下記のように変更します。

```:Button_ReplyのOnSelect
MicrosoftTeams.PostReplyToMessageV2(
         ComboBox_Team.Selected.id,
         ComboBox_Channel.Selected.id,
         ComboBox_Message.Selected.id,
            {
                content: RichTextEditor_Message,
                contentType: "html"
            }
        )
```
これで、` ComboBox_Team` で選択したチーム内の` ComboBox_Message` で選択したメッセージへ返信する形でメッセージが投稿されます。返信メッセージの内容は` RichTextEditor_Message` に入力した内容となります。
Elixirの文字列結合はiolistとして処理した方が高速らしい

[Elixir]の[文字列結合]にはいくつかの方法あります
`iolist`として処理すると効率よく文字列結合できるそうです

- [What is an iolist? What is a string? by Nathan Long]
- [ElixirConf 2019 - High Performance String Processing Scripts in Elixir - by Johanna Larsson]
- [Elixir and IO Lists, Part 2: IO Lists in Phoenix by Nathan Long](https://bignerdranch.com/blog/elixir-and-io-lists-part-2-io-lists-in-phoenix/)

[IO.puts/2]: https://hexdocs.pm/elixir/1.12/IO.html#puts/2
[Elixir]: https://elixir-lang.org/
[文字列結合]: https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%88%97%E7%B5%90%E5%90%88
[What is an iolist? What is a string? by Nathan Long]: https://nathanmlong.com/2021/05/what-is-an-iolist/
[ElixirConf 2019 - High Performance String Processing Scripts in Elixir - by Johanna Larsson]: https://youtu.be/Y83p_VsvRFA?t=1104

## [IO.puts/2]を使った例

```elixir
a = "Hello"
b = "World"

# binary 1
IO.puts( a <> " " <> b )

# binary 2
IO.puts( "#{a} #{b}" )

# iolist 1
IO.puts( [a, " ", b] )

# iolist 2
IO.puts( :io_lib.format("~s ~s", [a, b]) )

# 結果は同じ
Hello World
:ok
```

[:io_lib.format/2](https://erlang.org/doc/man/io_lib.html#format-2)は使い方によってはコードを見やすくできる場合があるとおもいます
記号の意味は[:io.fwrite/3](https://erlang.org/doc/man/io.html#fwrite-3)のドキュメントにあります
例として[NervesMOTD](https://github.com/nerves-project/nerves_motd/blob/main/lib/nerves_motd.ex)のコードでいくつか出てきます


## EExを使った例

```elixir
a = "Hello"
b = "World"

# binary 1
EEx.compile_string("<%= a <> \" \" <> b %>") |> Code.eval_quoted(a: a, b: b)

# binary 2
EEx.compile_string("<%= \"#{a} #{b}\" %>") |> Code.eval_quoted(a: a, b: b)

# iolist 1
EEx.compile_string("<%= [a, \" \", b] %>") |> Code.eval_quoted(a: a, b: b)

# iolist 2
EEx.compile_string("<%= :io_lib.format(\"~s ~s\", [a, b]) %>") |> Code.eval_quoted(a: a, b: b)

# 結果は同じ
{"Hello World",
 [{:b, "World"}, {{:arg0, EEx.Engine}, "Hello World"}, {:a, "Hello"}]}
```
iOS15から追加されたiCloud+のプライベートリレーを試す

# プライベートリレーとは？
iOS15から提供が開始されたiCloud+の機能の一つになります。(9/21時点ではベータ版)
有効にすることで、Safariを利用したWebサイトの閲覧履歴や接続元情報(IPアドレス)が匿名化されます。

https://developer.apple.com/jp/support/prepare-your-network-for-icloud-private-relay/

- wwdc
    - https://developer.apple.com/videos/play/wwdc2021/10096/

今回はこの機能について実際に試してみようと思います。

# プライベートリレーの仕組み
## OFF
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/7fbad363-45fb-ee21-6092-c33b239f362a.png)

## ON
- Ingress ProxyとEgress Proxyが仲介役となることでServer側は端末のグローバルIPを知ることができない。
- Server Name と Client IP addressの両方を知る箇所がないため、安全が担保されている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/34757ceb-6d75-2865-ef2b-e888104a93f5.png)



# 実機のスクリーンショット
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/25ac29b8-a7ec-b71d-cd5a-d4df26c891fe.png" width="40%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/ec54e94d-0fdf-eb9e-ed58-06859cae9682.png" width="40%">

# 動作確認(モバイル通信ahamo)
1. プライベートリレーをオフにした状態でグローバルIPを取得する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/a606e2ac-7ca7-fa6f-f33f-585324097dca.png" width="40%">
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/1601679c-b939-a7b4-eece-105203161174.png)

2. 「おおよその位置情報を保持」の状態でグローバルIPを取得する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/c07aeb14-84f4-865e-f891-a7a3e83fc836.png" width="40%">
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/cfa5d801-0a80-3be3-d080-a7eab0cbcd06.png)

3. 「国と時間帯を使用の状態」でグローバルIPを取得する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/72102811-1d07-09c1-d838-41367d5e6883.png" width="40%">
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/9d2920f9-311a-0f50-758b-2c9906cfac72.png)

# 検証結果
- 「おおよその位置情報を保持」 or 「国と時間帯を使用」のどちらでもホスト名が匿名性のあるものに変わる
- セルラー(モバイル通信)だけでなく Wifi(固定回線)でも同様な結果が得られる
- モバイル通信が使用するIPアドレス自体がざっくりとした住所なのではっきりとした効果は得られなかった。
- 固定回線になるとより細かくIPアドレスによって住所が特定されるため、より効果が得られる。
- Safariだけの機能であり、Chromeなどのブラウザでは機能しない
- SFSafariViewControllerでも有効になる


# まとめ
- この機能を有効にするとWebブラウジンクにまつわる行動は利用者以外だれも追跡ができなくなる。
- GAに送信されるIPアドレスも変わるはずなので、集計されるユーザ属性が参考にならなくなる可能性がある。
- 社内のVPNなどを使ってIPアドレス変更したい場合はこの機能をOFFにした方が良いかも。(期待通りのIPアドレスにならなくなる)
    - と思ったが、プロキシやVPNを有効にしているときはプライベートリレーはOFFになるらしい。
- キャリアサービスが提供しているSNSサービスが正常に機能しなくなる可能性がある。
    - https://www.itmedia.co.jp/mobile/articles/2109/21/news105.html
- IPアドレスで位置情報特定やユーザIDを紐付けをしているサービスはこの機能により正常に動かなくなるためユーザに許諾をとって位置情報を取得したり、他の方法を使ってユーザIDとの紐付けが必要となる。

# 使用したWebサービス
- https://www.myglobalip.com/
- https://rakko.tools/tools/11/
[Javascript]アロー関数についてちょい調べる

<h2>はじめに</h2>
またも「アロー関数とは？？」という質問をもらったときに、よくわからなかったので
調べて理解を深めつつ、学んだことをアウトプットしてみる。✊

<h2>アロー関数 vs 関数　違いは?</h2>

ES6から導入された***新しい関数の書き方***。

前の関数と比べて、その特徴は....

<h4>1 functionより短く書ける</h4>

```javascript
//関数
function test(x) {
}

//アロー関数
const arrowFunc = (x) => x + 1

```

<h4>2thisの扱い方に注意</h4>
this....オブジェクト。どのオブジェクトであるかは、関数の呼ばれ方によって変わる。



<h5>普通の関数</h5>
...thisの参照先が、呼び出した関数によって変わる

```javascript
param = 'global param';

function testFunc(){
  console.log(this.param);
}

const test = {
  param: 'test param',
  func: testFunc
}
const test2 = {
  param: 'test2 param',
  func: testFunc
}

test.testFunc(); // 結果：test param
test.testFunc2(); //結果: test2 param

```

this.paramの値は、呼び出し元がtest or test2かで異なります。
関数が定義された地点では、thisが何者なのかは決まってなく、呼び出されたときに決定します。


<h5>アロー関数</h5>
同じ関数を、アロー関数で見てみます。


```javascript
param = 'global param';

function testFunc(){
  console.log(this.param);
}

const test = {
  param: 'test param',
  func: testFunc
}
const test2 = {
  param: 'test2 param',
  func: testFunc
}

test.testFunc(); // 結果：global param
test.testFunc2(); //結果: global param
```

アロー関数では***どちらもgloval param***になります。
アロー関数では宣言された関数は、宣言された地点で"this"を確定するのです。
呼び出し元がtestFuncだろうと、testFunc2だろうと関係ありません。



<h4>アロー関数では定義してからのみ呼び出せる</h4>

普通の関数だと下記が可能になってします。

```javascript
a() // 下で定義する前に呼び出しているが、エラーにならない
function a() {}

```
Go.spec.goからOpenAPI specの出力実験v2

## infoを出したい！

const OpenAPISpecに埋め込んでもらう→const OpenAPISpecの文字列をyamlにして読み込む。

```go
const OpenAPISpec = `
info:
  version: 1.0.0
  title: Swagger Petstore
  description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
`
```

## 制約を書きたい！

大方針として、StructTagを使う。

1. 普通のタグと一応混在できる。
1. 解析が簡単。
1. 短くかける。

ということを考えて、yamlがjsonも行けるってことなので、「`{a:"b"} `」が解析に失敗するので断念。
「`{a: "b"} `」と空白を書かないとダメなのね......
ということで、素直にjson5でやることにした。
が、ライブラリが更新されてない。けど、大丈夫だろう。

以下のように、記載する。(Qiitaはjsoncでのハイライトしかないね。しかもちゃんと効いてるな)

```jsonc
{minmize:5,maxmize:10}
```

もしくは、以下のように記載する。

```
scheme:"minsize:5,maxsize:10"
```

下の方式だと、patternを指定するとき、「\\\\\\\\」のように大量(4個)にエスケープする必要がある。
＃Qiitaだとさらにエスケープが入るから、8個書いてる......

minimizeとかminLengthとかいろいろ面倒なので、min・maxで指定可能として、integer・stringでいい感じにした。
VPC Reachability Analyzer とは

## 勉強前イメージ

EC2使ってたとき出てきたけど、わからん

## 調査

### VPC Reachability Analyzer とは

VPC内のリソース間の接続テストを実行できるようにする機能です。
VPC内の2つのエンドポイント間の到達性を解析することができ、セキュリティグループやルートテーブルの設定などの問題点を確認できる機能です。

### 分析をしてみる

- 環境構築

VPCを2つ作って、VPCピアリングをしました。
ただルートテーブルやセキュリティグループの設定はしていないので、相互に通信出来ない状態です。

![02021-09-21 # VPC Reachability Analyzer とは - diagra.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/e600732b-5881-27f5-e406-982076f89cdb.png)


- パスの作成を行います。

VPC > REACHABILITY > Reachability Analyzer へ進みます。

![0VPC Management Console - Google Chrome 2021-09-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/b7c77033-3978-cc09-a898-dc6647ca2cc3.png)


- 分析の設定を行う

![1VPC Management Console - Google Chrome 2021-09-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/a442bf02-bb93-fdeb-e0ad-2f2ce22ba46c.png)


- 保留中

分析中は保留中になります。
数分待つと結果が出てきます。

![2VPC Management Console - Google Chrome 2021-09-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/d5fcb7b7-7386-7a03-3f66-2b6559a34b91.png)


- 結果が出力

到達不可能とステータスが出ました。
また、接続出来るようにするためには ということで、Explanationsより下に
ルートの設定やルールの設定を行うように記載されています。
Details を開くと何を設定すればよいかの記載もあります。

![3VPC Management Console - Google Chrome 2021-09-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/65f3f054-eba0-ce0a-a517-848e0a75c7ed.png)


## 勉強後イメージ

設定できてるはずなのになーってときよくある・・・今日もなった。
そんなときにすぐ使えるのいいね。

## 参考

- [VPC の新機能 Reachability Analyzer を試してみた。](https://blog.serverworks.co.jp/reinvent2020-vpc-reachability-analyzer)
AtCoderログ：0119 - ABC 219 B

# 問題

https://atcoder.jp/contests/abc219/tasks/abc219_b

## 問題文
> 英小文字からなる $3$ つの文字列 $S_1,S_2,S_3$ と、$1$、$2$、$3$ のみからなる文字列 $T$ が与えられます。
> $T$ の各文字に対応する文字列を連結してできる文字列を出力してください。より厳密には、以下の指示にしたがって文字列を出力してください。
> ・$1 \le i \le ∣T∣$ を満たす整数 $i$ に対し、文字列 $s_i$ を次のように定める。
>   - $T$ の $i$ 文字目が $1$ のとき、$S_1$
>   - $T$ の $i$ 文字目が $2$ のとき、$S_2$
>   - $T$ の $i$ 文字目が $3$ のとき、$S_3$
> ・$s_1,s_2, \ldots ,s_{∣T∣}$ をこの順に連結してできる文字列を出力する。

## 制約
> ・$1 \le ∣S_1∣,∣S_2∣,∣S_3∣ \le 10$
> ・$1 \le ∣T∣ \le 1000$
> ・$S_1,S_2,S_3$ は英小文字からなる。
> ・$T$ は $1$、$2$、$3$ のみからなる。

# 回答
## 回答1 (AC)
いま、流行のマリトッツォです(が、問題名の由来がわかりませんでした...)。文字列 $T$ の各文字に対し、'1' ならば $S_1$ を、'2' ならば $S_2$ を、'3' ならば $S_3$ を出力していけば良いでしょう。各文字が chr 型になりますのでご注意ください。コードは以下のようになりました。

```C++:abc219b-1.cpp
#include <bits/stdc++.h>
using namespace std;

int main(){
  string s1, s2, s3, t;
  cin >> s1 >> s2 >> s3 >> t;

  for ( int i=0; i<(int)t.size(); i++ ) {
    if ( t.at(i)=='1' ) {
      cout << s1;
    } else if ( t.at(i)=='2' ) {
      cout << s2;
    } else {
      cout << s3;
    }
  }  
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc219/tasks/abc219_b/editorial) → [公式解説](https://atcoder.jp/contests/abc219/editorial/2656)
回答1と同じ方針でした。$S_1,S_2,S_#$ を配列で保持すれば、場合分け (if 文) が不要になるとのこと。なるほど。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0118 - ABC 219 A](https://qiita.com/RoadLynton/items/8ef1ff655c25720d2c75)
CCNA　IPアドレッシング

今回はIPアドレッシングについて話していきます。
まず、IPアドレッシングとはネットワーク上の機器へIPアドレスを
割り当てることを言います。
IPv4ならIPv4アドレッシングでIPv6ならIPv6アドレッシングと言います。

IPアドレスは本来32ビットで4分割して、それを10進数に直しています。
それぞれにオクテットという名前が付いていて、ネットワークを表すネットワーク部と
ホストを表すホスト部に分かれます。

分け方は2種類ありまして、サブネットマスクを使ったクラスレスと
サブネットマスクを使わないクラスフルに分かれます。

クラスAではネットワーク部は0から始まります。
クラスBでは10から始まり、クラスCでは110から始まります。
クラスDはマルチキャストアドレスで、1110から始まります。
クラスEは実験用で1111から始めます。

クラスAは1:3なので、24ビットがホストの分になります。
2の24乗でそこからネットワークアドレスとブロードキャストアドレスを引いた数になります。
全てのホスト数は2のn乗からネットワークアドレスとブロードキャストアドレスの
2つ分を引いた数になります。


**サブネットマスク**

サブネットマスクとはどこまでがネットワーク部かを表す情報のことを言います。
例えば300台のホストが必要な場合、クラスBだとホストは足りているが、
16ビット分は必要ではなく、9ビットで事が足りてしまう。
残りの7ビットを無駄にしないための方法をサブネットマスクと言います。

これはクラスレスアドレスと言います。
IPアドレスと同じように32ビットで構成されており、ネットワーク部を1で表し、
ホスト部を0で表しています。
これを更に単純に分かりやすく表したのが、プレフィックス長表記と言います。
/の後に数値を入れることで表します。

**予約済みIPアドレス**

予約済みIPアドレスはネットワークに割り振ることのできない
アドレスのことを言います。

その中でもネットワークアドレスはホスト部が全て0のアドレスを指します。
これはネットワーク自体を表すアドレスです。
次がブロードキャストアドレスです。これはホスト部が全て1のアドレスです。

後は自分自身を表す仮想的なアドレスがループバックアドレスです。
これは第1オクテットが127から始まりますので、クラスAになります。
先頭が0から始まるクラスAの最後のネットワークです。

最後はリンクローカルアドレスです。
これはDHCPが機能せず、IPアドレスが付与されなかった時に
割り当てられる非常用のアドレスです。
これは169.254から始まるので、クラスBに入ります。
先頭が10から始まります。

**グローバルIPアドレスとプライベートIPアドレス**

グローバルIPアドレスはその名前の通り、全世界で通用するアドレスです。
世界にただ一つ、インターネットの接続の際に割り振られるIPアドレスです。
これはISPによって割り振られます。

プライベートIPアドレスはネットワークの範囲内で用いられるIPアドレスです。
ネットワーク内で判断できればいいので、他でも同じアドレスが
使われている可能性もある。

プライベートIPアドレスは範囲が決まっています。
クラスAは第1オクテットが10から始まります。
クラスBは172.16~172.31の範囲です。
クラスCは192.168です。

**サブネット化**

ネットワークを更に小さく分割したものをサブネット化と言います。
これがデフォルトのサブネットマスクだとナチュラルマスクと言います。

これはホストの数がそこまで必要ではないときに使います。
ホスト部のビットから数ビットもらって、それをサブネット部とします。
これにより、更にネットワークを大きくできます。
サブネット部が全て0だとゼロサブネット、
全て１だとオールワンサブネットになります。

最多サブネット数はゼロサブネットと、オールワンサブネットが許されているかどうかで
判断されます。許されてる時は2のs乗、許されていない時は2のs乗-2になります。

ネットワークを更に分割することをサブネット化と言うのに対して、
複数のネットワークをまとめて大きなネットワークを作ることを
スーパーネット化と言います。

サブネット化は2種類に分かれます。
1つ目はFLSM(Fixed Length Subnet Musk)で、これは
ホストの数を常に一定に保つサブネット化です。
これに対して、VLSM(Variable Length Subnet Musk)は
ホストの数を柔軟に対応できるサブネット化です。
【Talend】ファイル出力【基礎】

#初めに
Talendの基礎を実践的に身に付けることが本記事の目的です。

以下の記事の続きなので、未読の方は是非お読み下さい。
[【Talend】Hello World 的な【基礎】](https://qiita.com/nagisa_O/items/76b8bd0cf2d9101adcf8)


#環境
|使用環境  |バージョン  |
|---|---|
|OS  |Windows10  |
|Talend  |7.3.1 |

#使用するコンポーネント
・tFileInputDelimited
・tFileOutputDelimited

#実践内容
ファイルの読み込みと出力は前回やったので、次はそれをファイル出力してみましょう。

#実践
今回もこのcsvファイルを使用します。
コピペして使いましょう。

```employee.csv
id,name,age
1,Ross,26
2,Rachel,24
3,Monica,24
4,Phoebe,25
5,Joey,25
6,Chandler,25
```

まずは「tFileInputDelimited」を配置して設定します。
前回と同じなので細かい説明は省きます。
![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/a8684308-430c-8fe3-8343-a16979748ad5.jpeg)

「tFileInputDelimited」をダブルクリックし基本設定を設定します。

|項目  |設定内容  |備考  |
|---|---|---|
|ファイル名  |csvファイルのパス  |入力フィールドの横の「…」からファイルのパスを指定。変数も使用可。  ​|
|フィールド区切り  |"," |今回はcsvファイルなのでコンマを指定  |
|ヘッダー  |1 |ヘッダーの行数を指定  |

次に「スキーマの編集」の横の「…」からカラムの定義をします。
![キャプチャ2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/331a9434-0e71-413c-9f0e-92c10b77ccbe.jpeg)

|項目  |設定内容  |備考  |
|---|---|---|
|カラム  |ヘッダー  |カラム名を好きに入力しましょう。  ​|
|タイプ  |型 |値の型を定義します。  |
ここからがファイル出力部分です。
「tFileOutputDelimited」を配置し、「tFileInputDelimited」と繋げます。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/d690492b-54ee-1e05-9ba5-e7de679933b9.jpeg)

最後に「tFileOutputDelimited」設定しましょう。
今回はtsvファイルで出力します。
![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/597ca420-f261-70a1-077d-26785cd924f9.jpeg)


|項目  |設定内容  |備考  |
|---|---|---|
|ファイル名  |tsvファイルのパス  |入力フィールドの横の「…」からファイルのパスを指定。変数も使用可。  ​|
|フィールド区切り  |"\t" |今回はtsvファイルなのでタブを指定。  |
|ヘッダーを含む  |☑ |ヘッダーのinputでヘッダーを指定したので、outputでも指定します。  |
|スキーマ  |同期カラム  |同期カラムを押下すると繋いだコンポーネントに定義したカラムと同期します。  ​|
※補足
追加にチェックを入れると既にファイルがある場合は追記します。
詳細設定でエンコーディング等も設定できるので必要に応じて設定しましょう。

#実行
実行タブから実行しましょう。
「tFileOutputDelimited」のファイル出力で指定したフォルダにファイルが出力されていることを確認します。
![キャプチャ2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1225075/a9ff03aa-ab21-0671-6e30-c7ec605d0691.jpeg)
値がタブで区切られていることを確認できました。
ヘッダーも出力されていますね。

#まとめ
今回はTalendの基本、ファイル出力を実践しました。
これだけでも、csvファイルをtsvファイルで出力する立派なETLツールの出来上がりです。
husky+lint-stagedでtscするときにtsconfig.jsonが無視されてしまう時の対応

## はじめに

TypeScriptを書いていて、`git commit` する前に`tsc --noEmit`を動かしてタイプチェックしたり、`tsc`でコンパイルだけしたいことがよくあると思いますが、そういうときにhuskyとlint-stagedを使うと思います。

しかし、この時にtsconfig.jsonに記載している設定が反映されない状況（outDirの設定などがわかりやすい）があったため調べたところ解決方法を見つけたので、メモとして残しておきます。

## バージョン

```json
"husky": "^7.0.0",
"lint-staged": "^11.1.2",
```

## やりたかったこと

* `git commit`をした時に`tsc`でコンパイルをして、`git add dist`でコンパイル先のフォルダもステージに乗せたい。
* tsconfig.jsonの`outDir`には`"./dist"`を設定

huskyのpre-commitに`npx lint-staged`でlint-stagedを動かして

```title:.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
```

lint-stagedでコンパイルしてgit addします。

```title:package.json
"scripts": {
  "compile": "npx tsc"
},
"lint-staged": {
  "*.{ts,tsx}": [
    "npm run compile",
    "git add dist"
  ]
}
```

しかし、これだとtsconfig.jsonを参照してくれないため、distフォルダではなくコンパイルされるtsファイルと同ディレクトリにコンパイル後のjsファイルが生成されてしまいます。

## 解決法

huskyからtscを呼び出した時にプロジェクトフォルダの構成を見つけることができないため、bashから呼び出すことで解決できます。

```title:package.json
"lint-staged": {
  "*.{ts,tsx}": [
    "bash -c 'npm run compile'",
    "git add dist"
  ]
}
```

これでtsconfig.jsonの設定を参照することができるようになります。

## サンプル

以下GitHubのリポジトリを参照してください。

https://github.com/N-Iwata/node-typescript-sample

## 参考

以下issueで議論されていました。

https://github.com/okonet/lint-staged/issues/825
セキュリティ・ツール「mod_evasive」CentOS

自分のメモとして

Apacheに対するDoS攻撃対策としてmod_evasiveをインストール
OS : centos7

###インストール
yum install epel-release
yum install mod_evasive
systemctl restart httpd

###確認
httpd -M | grep evasive

###テスト
perl /usr/share/doc/mod_evasive-1.10.1/test.pl

###設定ファイル
/etc/httpd/conf.d/mod_evasive.conf




###参考サイト
https://ex1.m-yabe.com/archives/1662

https://xtech.nikkei.com/it/article/COLUMN/20070510/270527/

https://dev.classmethod.jp/articles/mod_evasive20/
Dockerの送信専用メールサーバー（DKIMに対応しました。）

#はじめに
過去に投稿した「[Dockerの送信専用メールサーバー](https://qiita.com/takeyamajp/items/be4ccc61862de3b121bf)」を DKIM に対応しました。
これで、メール送信時に関連するセキュリティ SSL, SPF, DKIM, DMARC を一式全てサポートできるようになりました。
（SPF, DKIM, DMARC を利用する場合は、別途 DNS サーバーに TXT レコードの追加が必要です。）

**GitHubへのリンク（日本語の説明もあります。）**
https://github.com/takeyamajp/docker-postfix

##DKIMに関するオプション
+ **ENABLE_DKIM**（デフォルト：true）  
trueの場合は、送信メールのヘッダーに電子署名を追加します。  
もし DKIMの機能を使わない場合は、falseに設定してください。
+ **DKIM_KEY_LENGTH**（デフォルト：1024）  
鍵の長さ(bit数)です。使用する DNS サーバーが255文字より長い TXT レコードをサポートしている場合は、2048 に変更する事をおすすめします。
+ **DKIM_SELECTOR**（デフォルト：default）  
DKIM の鍵が複数ある場合にそれらを識別するための名前です。  
このコンテナ以外にもメールサーバーがある場合は、セレクタが重複しないように 'default' 以外に変更してください。
+ **鍵の永続化について。**  
ボリューム '/keys' をホストマシンにマウントしてください。そうしないと、このコンテナが起動するたびにDKIMの鍵が変更されてしまいます。

以上です。よいメール送信ライフを！
コールバック関数を勉強するとアロー関数がちょっとわかった

#コールバック関数とは
>引数に関数をとる場合の呼ばれる関数のことをコールバック関数という。

:arrow_up: この定義のことは知ってたけど、それがどういう意味なのか、なんで名前がついているのか理解していなかった。:baby_bottle::baby_tone2:
#この記事を書いた経緯
アロー関数についてブチ切れながら:rage::rage::rage::rage:理解を深めようとしていたら、コールバック関数を用いることで書き方が違うことに気づいた。:bulb:
この記事では、コールバック関数を第一引数にとる**mapメソッド**と**setInterval関数**について説明していくよ。

#その前に結局アロー関数ってどんな形？


これを

```js
function 関数名(){〇〇};
```
こう

```js
const 変数名 = ()=>{処理};  //変数名は関数名のことだよ
```
**`()=>〇〇`**これが一つの塊。
いくら`()`がたくさんあっても、惑わされないように。
`=>`の右と左の関係は、`(必要時右側で使う引数)=>処理`
###アロー関数ではreturnが省略できる話
アロー関数では`=>`の直後の処理が`{return 〇〇}`の場合、
`{}`と`return`を省略できるので、
`=>〇〇`とか、`=>(〇〇)`という書き方ができる。
とっても惑わされてしまう。。。:joy:
あれこれどういう関数だろうと思ったら、`return`が隠れているのではと思い出せるように:spy_tone2:

#mapメソッドって何？
配列オブジェクトに用意されているメソッドの一つ。（配列.mapで呼び出せる）
##mapメソッドは何ができるの？
配列の中身を一つ一つ取り出して、何らかの処理を加え、新しい配列を作り出すことができる。
正確には、mapメソッドで新しい配列を作り出すというより、新しい配列をreturnできる。
もともとの配列は変更されない。

```js:function.ver
配列.map(
    function(value){
        return 処理;    //←新しい項目
    }
)
```
これをアロー関数で書くと

```js:アロー関数.ver
配列.map((value)=>新しい項目)  //配列.map(引数)=>戻り値

```

このvalueの中身は配列の中身が一つずつ入る。


#setInterval関数って何？
組み込み関数（なにも定義しなくてもいきなり使える関数のこと）の一つ。
##setInterval関数って何ができるの？
一定の間隔で特定の処理を繰り返し行う。
処理される間隔はミリ秒（1秒=1000ミリ秒）で表されるので、注意。:warning:
例：1秒ごとに処理されるなら、第二引数は1000と記載する。

```js:function.ver
  setInterval(処理内容,処理される間隔);  //抽象的に
  setInterval(function(){処理内容},時間)  //もうちょっと具体的に
```

アロー関数で書くと、

```js:アロー関数.ver
setInterval(()=>{処理内容},処理間隔)

```
`setInterval`は第一引数に処理内容が入るけど、処理内容にsetIntervalから値は渡さないよ。
#コールバック関数をとるアロー関数の書き方
mapもsetIntervalもコールバック関数を第一引数にとる。
mapはコールバック関数を呼ぶときに引数が必要だけど、
setIntervalはコールバック関数に値を渡さなくても良いので書き方が違うよ。

```js
配列.map((value)=>新しい項目) //渡す値は=>の前の（ここ）=>に入るよ
setInterval(()=>{処理内容},処理間隔)//  (()=>第一引数,第二引数)
```
[ruby]約数を足し算する方法

# はじめに
本記事では、私が本日取り掛かった問題を備忘録として記述します。

# 内容
1111111111の約数で、1111以下の約数を足す。

divisor = 約数　by　Google先生

```divisors.rb
def divisors(num, limit)
  (1..limit).select{ |i| num % i == 0 }.sum
end

puts divisors(1111111111, 1111)
```

1~limitまでの約数で` (1..limit)`、
今回の数字(1111111111)がi(ある数)で割ると0になるもの達の`.select{ |i| num % i == 0 }`、
合計`.sum`を出す。

ターミナル上にて、

```
% ruby divisors.rb
775
```

`775`が答えです。
なるほど、プログラミングすごい。w


# 終わりに
このような数学の問題、解く分には好きなんですが、
如何せん実力不足の知識不足で、40,50分ぐらいかかります。

もっと経験して、解けるようにしたいと思います。
諦めないことが大事ですね。

以下参考サイトです。というかすごく勉強になりました。ありがとうございます。
[【Ruby】ある整数の約数（要素の数、和）を求める](https://qiita.com/hirakei1203/items/def4242d18862f776efc)
[Rubyで1234567890の約数の内、30000000以下の約数を足す](https://teratail.com/questions/326275)

明日も頑張ります！！
霜に備える。

#概要

この春、霜にやられた。
来年の霜に備える。
構想編。

#被害状況

収量が七割だった。
5時の時点で、マイナス４度、ヒーターを焚いたが、間に合わず。

#対応策

気温を、測定する。
霜を、予測なんてしない。
零度以下なら、警報を鳴らす。

#警報を検討

- 携帯を鳴らす。
- smsで携帯を鳴らす。
- パトライトを回す。
- しゃべらす。


以上。
Safari 15でタブバーの色を指定する

# Safari 15でタブバーの色を指定する

## やりたいこと

Safari 15からタブの仕様が変わってサイトにあった色にタブバーがアマガエルやカメレオンみたいに擬態するようになった。そのタブバーの色をサイト制作者側のこっちから指定したい。
<img src="https://user-images.githubusercontent.com/47915291/134159806-248d7592-129c-487b-8565-c83caf902d31.png">
↑この画像のここの色を指定したい

## 解決法

`<head>`内に下記のコードを追加する。

```html
<meta name="theme-color" content="#007d92">
```

`content`のところで色を指定する。閲覧側のデバイスがダークモードに設定されている場合、設定した色が白や黄色など明るすぎる色だと反映されないから要注意。
<img width="1451" alt="スクリーンショット 2021-09-21 20 10 53" src="https://user-images.githubusercontent.com/47915291/134160650-6ec6f609-1d51-41d2-a728-eb10b6c0d622.png">
↑反映された

## 参考

[Design for Safari 15](https://developer.apple.com/videos/play/wwdc2021/10029/)の2分30秒らへんから。タブバー以外にも面白い情報がたくさんあるので是非みてみてね。
【PHP】2次元連想配列の結合（array_replace_recursiveで異なるキーの値を残して結合）

## 実現したいこと
多次元配列の内側の配列にも再帰的に結合を行いたい。
下記の配列```$status```と```$orders_count```という2次元の連想配列を、```$result```という配列のように結合したい。

#### 一つ目の配列

```
$status = [
    [
    "status" => 1,
    "name" => "ステータス1",
    ],
    [
    "status" => 2,
    "name" => "ステータス2",
    ],
    [
    "status" => 3,
    "name" => "ステータス3",
    ]
];
```

#### 二つ目の配列

```
$orders_count = [
    [
    "orders_count" => 40,
    ],
    [
    "orders_count" => 30,
    ],
    [
    "orders_count" => 20,
    ]
]
```

#### 欲しい結合結果

```
$result = [
    [
    "status" => 1,
    "name" => "ステータス1",
    "orders_count" => 40,
    ],
    [
    "status" => 2,
    "name" => "ステータス2",
    "orders_count" => 30,
    ],
    [
    "status" => 3,
    "name" => "ステータス3",
    "orders_count" => 20,
    ]
]
```


## array_replace_recursiveで対応
array_replace_recursive()という関数を使って結合する。

```
$result = array_replace_recursive($status, $orders_count);
```

第一引数に指定した配列に対して、第二引数の配列が下記の条件で結合される。

-  最初の配列のキーと同じキーが2番目の配列にあれば、2番目の配列の値が最初の配列の値を上書きする
-  2番目の配列に存在するキーが最初の配列に存在しなければ、 そのキーが新たに最初の配列内に作られる
-  置き換え用の配列が複数渡された場合は渡した順に処理を行い、 後から渡した配列の値のほうが優先される

今回はキーの重複はないので、1番目の配列に2番目の配列の中身が追加される。

## 参考
PHP公式リファレンス：[array_replace_recursive](https://www.php.net/manual/ja/function.array-replace-recursive.php)
Vite使っていて moment.locale('ja') が効かないときは

おそらくここにたどり着いた人は、下記の記事で上手くいかなかった人。

https://qiita.com/elzup/items/60d7bf38f12a7531c3f6

↓ これはダメ :x:

```typescript
import 'moment/locale/ja'
```

↓ こうすればいい :ok_hand: 

```typescript
import 'moment/dist/locale/ja'
```

理由は Vite でUMDモジュールのインポートをサポートしていないためで、dist/ に入っているのはESM形式なのでimport可能だからのようです。
LeetCode389[Find the Difference]-Pythonで実現

# 問題文

問題文はそのままコピーします。

```md
You are given two strings s and t.

String t is generated by random shuffling string s and then add one more letter at a random position.

Return the letter that was added to t.

 

Example 1:

Input: s = "abcd", t = "abcde"
Output: "e"
Explanation: 'e' is the letter that was added.
Example 2:

Input: s = "", t = "y"
Output: "y"
Example 3:

Input: s = "a", t = "aa"
Output: "a"
Example 4:

Input: s = "ae", t = "aea"
Output: "a"
 

Constraints:

0 <= s.length <= 1000
t.length == s.length + 1
s and t consist of lower-case English letters.
```

Exampleのように、`s = 'ae'`, `t='aea'`の時、この`t`配列の`a`をoutputしたいのことです。

簡単だと思いますが、ある特別な方法をシェアしたいと思っています。

# 解き方

この問題に対して、最初に思いついた方法はfor文でループして、dictを2つ使ってそれぞれ配列の要素をcountするだと思います。

だが！もっと面白い解き方があります！

pythonの組み込み関数の`ord()`と`chr()`を使って、listのみで問題を解決できます！

では！コードを載ります。

```python
class Solution:
    def findTheDifference(self, s: str, t: str) -> str:
        if len(s) == 0:
            return t
        
        table = [0] * 26
        
        for i in range(len(t)):
            if i < len(s):
                table[ord(s[i]) - ord('a')] -= 1
            table[ord(t[i]) - ord('a')] += 1
        
        for i in range(26):
            if table[i] != 0:
                return chr(i + 97)
        return 'a'
```

1行目と2行目はleetcode上のコードなので、基本は無視しても大丈夫です。

最初はif文で、配列`s`がもしなにも入っていないなら、そのまま配列`t`が戻ります。

そして、if文が成り立っていない場合、26個の要素が含まれている配列を作成します。

続いて、for文はややこしいなので、図に合わせて説明します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729963/c44ab729-1f90-e00c-ba22-69d8be586289.png)

例えば、上の配列は`s`, 下は配列`t`とします。この2つの配列に対して、同時にfor文を掛けます。最初に出てきたのは配列`s`の`a`です。この時、countを-1にします。続いて、配列`t`の最初の要素は`b`で、countを+1にします。2回目に入って、配列`s`の`b`のcountを-1にし、配列`t`の`c`の countを+1にします。**ここで、2つの配列にある要素`b`のcountを思い出してください！、-1, +1で0になります！**。そのあとは同じのことを繰り返し、最後は必ずどっちかの要素が1になります。私たちはこの0ではない要素を探せばよいです。

って、`ord`と`chr`はなんやろと思うかもしれませんが、簡単です！indexを設定することです。

```python
print(ord('a'))
>>> 97
```

文字列`a`を数値に変化することです。一方、`chr`は数値を文字列に変換することです。

`ord(s[i]) - ord('a')`こうやって書く理由として、私たち先作った26個要素が含まれている配列があるではないですか。`ord`で変換すると26を超えてしまったので、ようするにindex `0,1,2,3,4...`を作るためです。

これでfor文は終了し、最後は`count != 0`の要素を探せてreturnしたら良いです。

# 参考

<https://leetcode.com/problems/find-the-difference/>
アジャイル開発ってIT独特なんか？

こんにちは！
僕前職で毎度、現場に行って倉庫内での仕分けや搬送といった物流システムの取り付け業務（主にコンベアやラック）をやってました。
アジャイル開発について調べていくうちに、この開発手法ってIT業界独特のものなの？とふと考えるようになりました。


# アジャイル開発
Agile（アジャイル）とは和訳すると敏捷、素早いといった意味になるそうです。
企画→要件定義→設計→開発→テストを重要度の高い実装から行い、何度も行う手法です。
小さく作ることから始めて、テストを繰り返すことで仕様変更があった際に対応しやすいです。
進捗がわかりにくいので、スクラムを導入することがあります。

## スクラム
ラグビーでスクラムを組むってこういうことですよね。
![photo-1480099225005-2513c8947aec.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/f00abc97-74ee-50cc-4d83-946db97bff3c.jpeg)

IT用語のスクラムは、開発を進めるチームの単位です。
チームメンバー1人1人が主体性を持って開発を進めることでプロダクト完了に向けた責任を持つことが特徴です。


# ウォーターフォール開発
初めに決めた要件をある期限までに完了する開発手法です。納期が決まっており、納期から逆算した進捗管理を行うので、急な仕様変更や作りたいものが変わった時には対応しにくいです。

# どっちがいいの？
一概にどっちがいいとは言えないです。
これは開発するモノによって変わってきます。

初めて作るアプリならアジャイル開発が向いているんだろうなあとは思います。
お客様と確認しながら変更して欲しいところがあったら対応しやすいし。

あとは最終的な要件がはっきりしていないプロダクトや、開発の優先度がコロコロ変わる可能性のあるモノが向いてるのかな？

最初から作るものが明確に決まってるものならウォーターフォール開発が適しているかと思います。
あとは大型システムのように、たくさんのエンジニアが開発に関わるプロジェクトなら役割分担と期限を設定しやすいし、いいんじゃないかと思ったけどただ仕様変更には対応しづらいからどうなんやろな。

# アジャイル開発ってIT独特なん？

記事の冒頭でも載せたけど、
僕前職で毎度、現場に行って倉庫内での仕分けや搬送といった物流システムの取り付け業務（主にコンベアやラック）をやってました。

確実に納期が決まってたし、設計図面も詳細に書かれていたので、仕様変更には対応できないんやろな〜とアジャイル開発のことについて調べているときに思いました。
でも、コンベアもラックも現場事に広さや階数も異なるので、設計図面のボリュームや納期は異なりますが、製品としては毎度同じものを取り付けにいっていたので仕様変更に対応する必要がないんです。
 IT業界以外ってほぼウォーターフォール開発やろと思いました。

それに対して、未だ作った事のないWebアプリケーションを作成する中で、お客様のレビュー確認は確実に必要だから仕様変更に強い開発手法を取るのは当たり前ですよね。