OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Black Belt Online Seminarで学んだAWS Configをまとめる

会社でAWS Configについて理解が浅いため、一度動画を見て学び自分用にまとめることとした。
視聴した動画は[こちら](https://www.youtube.com/watch?v=vnqX0gMj6jw)

## AWS Configとは
構成管理にまつわる課題として、実設定とドキュメントとの整合性の乖離や管理コスト、コンプライアンス準拠への負担が挙げられる。これらの課題をクリアして構成管理を楽にしましょうという機能がAWS Config。

概要は次の通り。
* AWSリソースのインベントリ管理、構成変更のためのフルマネージド型サービス
* AWSリソース構成変更をロギング（保存期間はデフォルト7年間）
* 履歴も保存
  * 構成情報を定期的にスナップショットしてS3に保存
  * SNSを用いた通知も可能
* 構成変更の追跡、セキュリティ分析、トラブルシューティング、コンプライアンス準拠を容易にできる

## AWS Configの各機能の役割
保管する3つの処理として、次のものがある。
* ストリーム
  * リソースが作成/変更/削除されるたびに作成
  * 構成ストリームに追加される
  * SNSトピックに連携可能 
* ヒストリー
  * 任意の機関における各リソースタイプの構成要素の集合(あるEC2に対してどんな設定が過去に変更されたかなど)。 
  * リソースの設定履歴を指定したS3バケットに保存
* スナップショット
  * ある時点でのコンフィグレーションアイテムの集合
  * 自動で定期的、あるいは変更トリガーで作成され、指定したS3バケットに保存

## 対応しているリソース
動画の中では24のサービスでリソース数は60以上対応していると紹介されている。（きっと今はもっと多そう）
公式ページの対応リソース一覧は[こちら](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/resource-config-reference.html)

## AWS Configによる構成管理のメリット
* 構成管理/記録の保存
* 過去の構成状況
* 依存関係の確認
* コンプライアンス準拠


## AWS Configで管理する構成情報をへ評価する
* AWS Config Rulesを用いるとルールに用いて変更をして良いかの判断を自動でできる（例：すべてのEBCボリュームが暗号化されているか）。それによって次の恩恵を受けれる。
  * 準拠状況のチェック
  * 構成修復の実行
  * SNSによる通知 
* ルールの策定には2種類ある
  * マネージドルール
    * AWSによって定義・提供される
    * 汎用性の高いベーシックルール
  * カスタムルール
    * 自分でAWS Lambdaをもとにルールを策定可能
    * 管理自体は作成者で実施 
* ルール評価実行のトリガータイミング
  * 設定変更
  　　*　関連リソースが作成、変更された際 
  * 定期的
  　　* 任意の定期的なタイミング（1h毎〜24h毎）
  　　* AWS Configがスナップショットを撮る際

## 修復アクション
コンプライアンス違反のリソースに対して、ルールに関連づけられた修正アクションを実行できる。
* 事前入力されたリストから修正アクションを選択
* AWS Systems Manager Automationドキュメントを使用したカスタムの修正アクションを設定。

※ Cloud Watch EventsからLambdaをトリガーしてより細かい修正アクションも実行できる

## マネージドルールのユースケース1
実際にどんなユースケースがあってルール設定されているかも動画で紹介があった。
下記の他にもコミュニティベースで融資で作成されている[リポジトリ](https://github.com/awslabs/aws-config-rules)というものもある。
* approved-amis-by-id
  * 実行中のインスタンスで使用されているAMIが指定したもの（承認済みのもの）かを確認
* required-tags
  * リソースに指定したタグがあるか確認 
* encrypted-volumes
  * アタッチ済みのEBSボリュームが暗号化されているかを確認 
* ec2-instance-managed-by-ss
  * ec2インスタンスがAWS Systems Managerで管理されているか確認
* vpc-flow-logs-enabled
  * VPCのパケット取得（Flow Logs）が有効になっているか確認
 
## マネージドルールのユースケース2
* s3-bucket-public-read-prohibited
  * S3バケットでパブリック読み取りアクセスが許可されていないことを確認 
* s3-bucket-public-write-prohibited
  * S3バケットでパブリック書き込みアクセスが許可されていないことを確認 
* rds-snapshots-public-prohibited
  * RDSスナップショットが公開禁止されていることを確認 
* s3-bucket-server-side-encryption-enabled
  * S3でバケットのデフォルト暗号化が有効化されているか確認 
* access-keys-rotated
  * 有効なアクセスキーが指定日数内にローテションされているか確認 

他にもAWS Config単独ではないが
不正ソフトウェア導入に対する自動アクションを設定みたいなこともできるらしい。


## ベストプラクティス
量が多いため、動画ではいくつかピックアップされている

### 記録対象について
#1. すべてのアカウントとリージョンでAWS Configを有効に
→ すべての操作を記録する
→ ミスがあったら気づける仕組みを整えておく
#2. 全てのリソースタイプについて設定変更を記録する 
→ 新しく追加されたリソースタイプも自動で記録対象になる
#3. グローバルリソースは1リージョンで記録を有効にする
→ 重複して記録されるのを防ぐ

### 保存先について
＃５. 安全なS3バケットにヒストリーとスナップショットを保存する
  → 特定の人しかアクセスできず、改竄ができない場所へ保存

S3バケットの公開設定をチェックするAWS Managed Ruleも活用

### マルチアカウント環境での利用について
#19. Data aggregation機能を使って、管理アカウントから集中管理する
#20. Organizationベースのaggregatorを使う

## 料金について
### AWS Config
リソースに対して記録された設定項目 1記録あたり：0.003USD

### AWS Config Rules
記録されたAWS Configルールの評価数（リージョン毎）
最初の10万ルールの評価につき：0.001USD
次の40万ルールの評価につき:0.0008USD
次の500,001以上のルールの評価につき：0.005USD

### 追加料金
S3,SNS,Lambda,SSM Automation
UbuntuでSMB共有をしてみた

Ubuntuでたまにファイル共有したくなるのですが、毎回忘れるのでメモを残します。

# SMBサーバを立てる場合

まずは下のコマンドでSMBのサーバ用プログラムをインストールを行います。

```bash:
sudo apt install samba
```

次に、共有するフォルダを作成します。一般的には`/home`配下で作成するみたいです。

```bash:
sudo mkdir /home/test
```

設定ファイル`/etc/samba/smb.conf`に下の設定を追記します。最初の`[test]`の部分は既に登録されている`[global]`や`[home]`、`[printer]`でなければ何でもいいみたいです。ちなみに、読み書きを許可し、誰でも入れる設定にしてあります。

```
[test]
path = /home/test
read only = no
guest ok = yes
```

SMBを起動します。

```bash:
sudo service smbd start
```

# クライアント側でSMBを使う場合

まず、下のコマンドでSMBクライアント用プログラムをインストールします。

```bash:
sudo apt install cifs-utils
```

マウントするためのフォルダを作成します。今回は`/mnt/test`にします。

```bash:
sudo mkdir /mnt/test
```

下のコマンドでマウントを行います。なお、`//サーバのIPアドレス/`の後には、設定ファイル`/etc/samba/smb.conf`で書いた`[test]`の名前を書きます。（ディレクトリ名ではありません）

```bash:
sudo mount -t cifs //サーバのIPアドレス/test /mnt/test
```

# おわりに

今回も個人での使用を前提にしているため、セキュリティ設定とか行っていません。今後勉強したら追記します。
Codebuild での Docker build 時 に ssh キーを使う方法

# はじめに
ハマったので備忘録として。

# 手順
## 1. Systems Manager の Parameter Store で設定する

こんな感じで。
Type は String でもよいけど、セキュアなデータなので個人的にには SecureString がおすすめ。
![Screen Shot 2022-07-11 at 20.18.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44959/0e35f205-37f1-1be1-b9b4-58cc0783b050.png)

## 2. buildspec.yml で使うように記述する

```yaml
version: 0.2

env:
    parameter-store:
        SECRETS_GITHUB: github-deploy-key
    variables:
        DOCKER_BUILDKIT: "1"

phases:
    pre_build:
        commands:
            - echo Logging in to Amazon ECR...
            - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}
            - IMAGE_TAG=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | head -c 7)
    build:
        commands:
            - echo "$SECRETS_GITHUB" > deploy_key.txt
            - chmod 600 deploy_key.txt
            - docker build --secret id=ssh,src=deploy_key.txt -t ${IMAGE_REPO_NAME}:${IMAGE_TAG} .
    post_build:
        commands:
            - aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
            - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${REPOSITORY_URI}:${IMAGE_TAG}
            - docker tag ${IMAGE_REPO_NAME}:${IMAGE_TAG} ${REPOSITORY_URI}:latest
            - docker push ${REPOSITORY_URI}:${IMAGE_TAG}
```

`--secrets` で渡すのは色んな記事で見かけるけど意外と `chmod` しているのは見かけなかった。
が、ここが大事で、しなかった場合に Docker build 時にエラーになる。
通常の ssh キーと同じ挙動なので、 `--secrets` で渡すファイルは中身だけじゃなく権限も一緒に渡している模様.

あと、どこかの記事で「改行文字があるとダメだから置換しないといけない」って記述を見かけたけど、
それは全然必要なかったので無視してよい。

## 3. Dockerfile 内で使う

```Dockerfile
FROM python:3.8.13-slim-bullseye
〜〜〜〜〜〜
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa poetry install
〜〜〜〜〜〜
```

ポイントは、ssh キーを使う処理と `--mount` を一緒に記述すること。
```Dockerfile
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa
RUN poetry install
```
のようにやると、 `/root/.ssh/id_rsa` が存在せず、エラーになってしまう。
ssh キーを使う処理が複数存在する場合は、以下のように複数行書く必要がある。
```Dockerfile
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa poetry install
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa poetry run pip install -r requirements.txt
```

## 4. Role に権限をつける
Systems Manager にアクセスするので Codebuild を実行する Role に `ssm:Get*` の権限をつける

## 5. 実行
あとは、Codepipeline から呼び出すなり、 Codebuild 単体で実行するなりで実行したらOK。
[Ruby]配列演算子[]等をあえて通常ののインスタンスメソッドのように使う

Rubyで個人的に面白い気づきがあったので記事にします。

## []を通常のインスタンスメソッドとして使っている例を発見
先日、担当しているプロジェクトで以下のようなコードを見ました。

```ruby:ruby
array.[](0)
```

恥ずかしながら、一瞬、これは何をしているんだ？と戸惑ってしまいました。
[]は配列演算子として配列や文字列にドットなしでつけるのしか見たことがなかったからです。

[Array#[]](https://docs.ruby-lang.org/ja/latest/method/Array/i/=5b=5d.html)はインスタンスメソッドとして用意されているので、以下は同じ結果になります。

```ruby:ruby
array = [1, 2, 3]

array[1] #=> 2
array.[](1) #=> 2　（[]メソッドの引数を()で指定している）
array[] 1 #=> 2 （()を省略）
```


## どんなときに使うのか

これをどんな時に使うのか、という話ですが、例えば以下のようなかたちで`&.`を使って、[]が使えないものがレシーバに来たときにNoMethodErrorの代わりにnilを返すことができます。

```ruby:ruby
REGEX = /ab|ba/.freeze #=> 正規表現 abもしくはbaにマッチ
sample = ['a', 'b', 'c'].shuffle.join #=> abcをランダムに入れ替えて文字列にする

sample.match(REGEX)&.[](0) #=> matchするデータがあれば最初にマッチした部分を返す、matchするデータがない場合はnilを返してくれる
```

マッチしない時でもNoMethodErrorではなくnilを返して処理を続行したいときなどは便利になると思います。

### 追記

[コメント](https://qiita.com/m-ito27/items/df838d293d0397aeabb7#comment-230f6614e6fd170218cd)でブロックを渡す方法も教えていただきました！

```ruby:ruby
sample.match(REGEX) { |e| e[0] } #=> matchするデータがあれば最初にマッチした部分を返す、matchするデータがない場合はnilを返してくれる
```

## さいごに

こんなの当たり前じゃんと言われるかもしれないですが、このように使う方法が頭に無かったので、大変勉強になりました。

今回は[]に遭遇したのですが、他の演算子でも同じようなことができる（`<<` を `.<<(...)`にできるなど）ということなので、自分の引き出しが増えた気がします。
基本情報（入力装置）

入力装置は「処理に必要となるデータ」をコンピュータに入力してあげるのが入力装置の役割です。
代表的なところでは文字を入力するキーボードと、位置情報を伝えるマウスなどたくさんありますが下記に一例を出します。

## キーボードとポインティングデバイス


|   |説明  |
|---|---|
|キーボード  |パソコンにほぼ標準装備。文字や数字を入力するための装置。  |
|マウス  |マウス自身を動かすことで、その移動情報を入力して画面内の位置を指し示す装置。  |
|トラックパッド　 | パッド上で指を動かすことで、その移動情報を入力して画面内の位置を指し示す装置。ノートパソコンでマウスの代わりに搭載されていることが多い。
|タッチパネル | 画面を直接触れることで、画面内の位置を指し示す装置。銀行のATMや駅の券売機等で使われていることが多い。|
|タブレット   | パネル上で専用のペン等を動かすことにより、位置情報を入力する装置。絵を描く用途に使われることが多い。大型のものはディジタイザと呼ばれ、画面作成用途に用いられる。|
 |ジョイスティック  | スティックを前後左右に傾けることで位置情報を入力する装置。  |

ポインティングデバイスは画面内の特定の位置を指し示すために使う機器のことです。マウスやトラックパッドの他、銀行のATMや駅の券売機にあるようなタッチパネルもそうです。

## 読み取り位置とバーコード
入力装置は「指示を与える」ばかりではありません。「処理対象となるデータそのものを入力する」ことも入力装置の大事な役割です。

|  |説明  |
|---|---|
|イメージスキャナ  |絵や写真を画像データとして読み取るための装置。単にスキャナと呼ばれる。  |
|OCR(Optical Character Reader)   |字された文字、もしくは手書き文字などを解析して文字データとして読み取る装置。ハガキの郵便番号欄などはこれで読み取っている。   |
| OMR(Optical Mark Reader) | マークシートの塗り潰し位置を読み取る装置。試験の答案や、アンケートの集計などで使われている。 |
|  キャプチャカード| ビデオデッキなどの映像機器から、映像をディジタルデータとして取り込むための装置。 |
| ディジタルカメラ | カメラ。フィルムの代わりに、CCD(Charge Coupled Device:電荷結合素子)などを使って、画像をディジタルデータとして記録する装置。 |
|バーコードリーダ  |バーコードを読み取るための装置。コンビニエンスストアで読み取らせているのをよく見る。  |

バーコードには下記の2種類があります。

JANコード
![jan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542637/e0e5a606-7abd-9c43-a7d1-433b3485945d.png)
商品コードを表すバーコード。白黒の帯によって13桁か8桁の数字を表現する。
QRコード
![220px-QR_code_desktop_Japanese_Wikipedia.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542637/f5eaff9e-adf1-fabd-c304-3b7ed3b08ba4.png)
縦横を使うことでより多くの情報が持てるようになった２次元バーコード。3個の検出用シンボルによって、回転角度と読取り方法が認識できる。

## まとめ
入力装置といっても種類は様々ですね。
【Laravel】サービスコンテナ

# サービスコンテナ
なんか書き方が豊富で混乱してきたので、整理したい

## サービスコンテナとは

- フレームワークは多くのクラスによって構成されている
  - コントローラやモデルもクラス
- クラスのインスタンスを管理するのが、**サービスコンテナ**

### サービスコンテナの実体

Illuminate\Foundation\Applicationクラス

## インスタンスの生成
まずはPHPでの書き方をおさらい
```php
$hoge = new \App\Services\HogeService();
```

## インスタンスの取得

```php
// app関数から取得する
$app = app();

// Application::getInstanceメソッドから取得
$app = \Illuminate\Foundation\Application::getInstance();

// Appファサードから取得
$app = \App::getInstance();
```

## インスタンスの取得＆生成

### makeメソッド

```php
app()->bind(Number::class,function(){
	return new Number();
});

// app関数から取得する
$number1 = app()->make(Number::class);

// Application::getInstanceメソッドから取得
$number2 =  \Illuminate\Foundation\Application::getInstance()->make(Number::class);

// Appファサードから取得
$number3 = \App::getInstance()->make(Number::class);
```

### app ヘルパ関数

```php
app()->bind(Number::class,function(){
	return new Number();
});

$number4 = app(Number::class);
```







## 引用

https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF-Laravel-Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B38-x%E5%AF%BE%E5%BF%9C-%E7%AB%B9%E6%BE%A4/dp/4802613008

## 参考

https://qiita.com/kd9951/items/951ab700f28d1d49c9c9
【PHP初級㉙】for文応用1

[問題]　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksPrimary.html)
整数値を5回入力させ、それらの値の合計を表示するプログラムを繰り返しを使って作成しなさい。

# コード
```php
for($m = 1; $m <= 5; $m++){
    $a = intval(fgets(STDIN));
    $i[] = $a; 
}
echo array_sum($i);
```

↓
5
2
3
9
10　　と入力

# 結果
```
29
```
Arduino UNOと温度センサーS-8120Cで温度をシリアル出力(map文)

目的
安価に温度を測る。

v = -8.2 * t + 1705

式の変形

t = (v - 1705.0) / -8.2;


```

  //  207.92 = (0    - 1705.0) / -8.2;
  // -401.82 = (5000 - 1705.0) / -8.2;
  int t = map(s,0,1024,2079,-4018);


```


![o_con569.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/eeabdf74-9018-0d1f-0013-5933057d4e44.jpeg)



![o_con573.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/01837f99-0b63-d248-97e6-caef90b320f2.jpeg)



プログラム


```c++


//SER_S-8120C_map_UNO_1

#include <Arduino.h>

//初期化処理
void setup()
{

  //シリアルの初期化
  Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  //センサーの値を読み込む
  int s = analogRead(A0);   // センサーの読み取り値

  //センサーのADC値を温度に変換 温度の10倍を出力 ex 20.1 => 201
  // v = -8.2 * t + 1705  =>  t = (v - 1705.0) / -8.2;
  //  207.92 = (0    - 1705.0) / -8.2;
  // -401.82 = (5000 - 1705.0) / -8.2;
  int t = map(s,0,1024,2079,-4018);

  //温度の表示
  Serial.print(t / 10);
  Serial.print('.');
  Serial.print(t % 10);
  Serial.println();

  //1秒の待ち
  delay(1000);

} //loop




```


https://paiza.io/ja/projects/new?language=c



テストプログラム


```c++


long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


#include <stdio.h>
int main(void){
    
    int s;
    float v;
    float t;
    
    for(int ii=0;ii<=1024;ii++){
        printf("[%d]= ",ii);
        
        s = ii;
        
        v = s * (5000.0 / 1024);
        
        printf("V[%f]= ",v);
        
        t = (v - 1705.0) / -8.2;
        
        printf("T[%f]= ", t );
        
        printf("T[%d]= ", map(ii,0,1024,2079,-4018) );
        
        printf("\r\n");
    }
    
}



```
テスト72

```vb

Sub Reg_Proccess()

'正規表現
Dim reg As Object
Dim matches As Variant
Dim tmp_str As String

Set reg = CreateObject("VBScript.RegExp")

'正規表現の指定
With reg
'    文字列の中で(○○)を抽出...〆(･ω･` )ﾒﾓﾒﾓ
    .Pattern = "\(.*?\)"   'パターンを指定(最も短い範囲にあるカッコを全て取り出す)
    .IgnoreCase = True       '大文字と小文字を区別する(False)、しない(True)
    .Global = True           '文字列全体を検索する(True)、しない(False)
    
End With


With ThisWorkbook.Sheets("表1")
    '半角で取得
    Set matches = reg.Execute(StrConv(.Range("A10").Value, vbNarrow))
    
    '文字列内に1つ以上(○○)があった場合
    If matches.Count > 0 Then
        '文字列の最後の(○○)を取得
        tmp_str = matches.Item(matches.Count - 1)
        
        '左右のカッコを削除
        tmp_str = Replace(tmp_str, "(", "")
        tmp_str = Replace(tmp_str, ")", "")
        Debug.Print tmp_str
        
    End If
    
End With

Set reg = Nothing


End Sub
vimのバッファをいい加減に覚える

毎回ファイルを開いてその場しのぎをしているのはイケナイ


## バッファ
- `:ls`で今のvimプロセス内で読み込まれているファイルリストを表示

```vim
:ls
  1  h   "~/.config/coc-settings.json"  line 1
  3  h   "~/.config/gnome-initial-setup-done" line 1
  4 #h   "~/.config/ibus-mozc-gnome-initial-setup-done" line 1
  5 %a   "~/.config/kglobalshortcutsrc" line 1
Press ENTER or type command to continue
```

## 操作
### 移動
- `bn(bnext)`で次のバッファ
- `bp(bprevious)`で前のバッファ
- `b <数字>`で、指定番号のバッファへ移動
- `b <ファイル名>`で、指定ファイル名のバッファへ移動

### 削除
- `bd <数字>`で、指定番号のバッファを削除

### キーマップ例

好きなキーを割り当てる
jとkあたりだとさらに早くなるという人もいる

```vim
nmap <C-n> :bn<CR>
nmap <C-p> :bp<CR>
```
【DNS】サブドメインのないドメインのAレコードは真っ先に書かないといけない

インシデントの話なのでせっかくだから[私が体験した1番ゾッとするインシデントの話](https://qiita.com/official-events/5d9db98800d6f7763fed)に参加してみたのですが、正直なところ`1番`ではないですね。
やっぱ一番は[コレ](https://qiita.com/rana_kualu/items/2f3c40642836c11f5ddc)ですよ。

というわけで先日起こした事故の紹介です。
まあタイトルどおりなのですが。

# どういうこと？

```bash:zoneファイル
; OK

     IN  A  192.168.0.1
www  IN  A  192.168.0.2
```

```bash:zoneファイル
; 死！！！！！

www  IN  A  192.168.0.2
     IN  A  192.168.0.1
```


# なにをやった？

弊社サービスの一部について、ドメインを[Doレジ](https://www.do-reg.jp/)で提供しているわけです。
ここzoneファイルをそのままアップできて自由度が高いので便利です。

ということでこんなかんじの運用をしていました。

```bash
example.jp.

; DNS
        IN    NS       NS1.DO-REG.JP.
        IN    NS       NS2.DO-REG.JP.

; 本番環境
        IN    A     10.0.0.1

; 開発環境
dev     IN    A     10.0.0.2
```

`example.jp`が本番環境で、`dev.example.jp`が開発環境という、まあよくある構成です。

`NSx.DO-REG.JP`は変更するなとDoレジから言われているところなので常に固定です。
実際はこれ以外にも色々レコードが書かれているのですがそのあたりは省略しています。

ある日、開発環境のIPアドレスが`10.0.0.2`から`10.0.0.3`に変更になったので書き替えました。
ついでにちょっと他のところも色々と整理しました。

ここで嫌な予感のした人は鋭いですね。

最終的なzoneファイルはこのようになりました。

```bash
example.jp.

; DNS
        IN    NS       NS1.DO-REG.JP.
        IN    NS       NS2.DO-REG.JP.

; 開発環境
dev     IN    A     10.0.0.3

; 本番環境
        IN    A     10.0.0.1
```


意気揚々と設定変更した数分後、口々にクレームが上がり始める。

「「「本番環境に繋がらなくなった！！」」」

実際ブラウザから見てみると`example.jp`ドメインが見つかりません。
えーなんで本番環境のAレコードなんて変えてないよ？開発環境しか変えてないよ？？どうして？？？

意味がわからねーと毒付きながらも慌ててzoneファイルを切り戻したところ、しばらくして再びアクセス可能になりました。

結果として、数十分本番サーバに接続できない状態になってしまいましたとさ。
幸いDNS変更時の作法に従って数日前からTTLを短くしていたのでまだよかったものの、うっかり86400とかのままだったら大惨事になっていたところでした。


# 対策

サブドメインのないドメインのAレコードは真っ先に書きましょう。

決して順番を入れ替えてはいけません。


# 本当の原因

嘘です。

本当の原因は、一番上に書かなかったことではありません。

サブドメイン部分を省略した場合は、前行の設定が引き継がれるという仕様のためです。

即ち、上で順番を並び替えたDNSレコードは、実際にはこう解釈されます。

```bash
example.jp.

; DNS
        IN    NS       NS1.DO-REG.JP.
        IN    NS       NS2.DO-REG.JP.

; 開発環境
dev     IN    A     10.0.0.3

; 本番環境
dev     IN    A     10.0.0.1
```

`example.jp`のAレコードなくなったやん。

どうしてこんな恐ろしい仕様なんですか。


そんなわけで、省略せずに常にフルパスで書いておけばどんな順番であろうが問題ありません。

```
example.jp.

; DNS
        IN    NS       NS1.DO-REG.JP.
        IN    NS       NS2.DO-REG.JP.

; 開発環境
dev.example.jp. IN    A     10.0.0.3

; 本番環境
example.jp.     IN    A     10.0.0.1
```

こっちのほうが面倒だけど安全ですね。
面倒だけど。


# @使えよ

これでいいらしい。OMG

```
www  IN  A  192.168.0.2
@    IN  A  192.168.0.1
```
vimのキーマップ覚書


すぐ忘れちゃうので

- `map` ノーマルモード、ビジュアルモード
- `nmap` ノーマルモード用
- `vmap` ビジュアルモード用
- `imap` インサートモード用
- `cmap` コマンドモード用



例えば、cocのリファレンスにあるキーマップ
- `<silent>`はコマンドラインに表示しない
- `<Plug>()`はvimプラグインの中のコマンドを呼び出す

```vim
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
```
論文解説1（眼球運動）

読んだ論文を記録のためにアウトプットしていきます。
解釈が違う場合があったらガンガン質問ください！！
落合フォーマットでまとめていきます。
# Eyes Move, Drones Move Explore the Feasibility of Various Eye Movement Control Intelligent Drones

https://ieeexplore.ieee.org/document/9650336


Y. Zhou, "Eyes Move, Drones Move Explore the Feasibility of Various Eye Movement Control Intelligent Drones," 2021 IEEE International Conference on Data Science and Computer Application (ICDSCA), 2021, pp. 508-513, doi: 10.1109/ICDSCA53499.2021.9650336.
___

# どんなもの？
アイトラッカーと画像処理を利用してドローンを制御する方法紹介している。

# 先行研究と比べてどこがすごい？
ドローンは長年、ジョイスティックを使用して操作することが基本だったが眼球運動で操作するところ。


# 技術や手法のキモはどこ？
畳み込みネットワークカスケードを目の検出に使用していました。Dlibキーポイント検出アルゴリズムは、アイソケットの6つのポイントを後退させて、目を閉じる動きとまばたきの動きを識別しています。
Gaze Trace機能をオンにし、目がどこを向いているかを識別して画面上の８つの位置のどこにいるかを確認する。


# どうやって有効だと検証した？
視覚位置と実際の位置の誤差
ドローンを飛ばし命令道理に動いているか確認する。


# 議論はある？

ドローンを自由に飛ばすにはコマンド数が少ない。
Tobiiの制御盤を使っている。
C++17 std::variant の簡略版がほしいメモ

`std::variant`(variant-lite 含む) コンパイル遅い...
visit とかやるとより激遅...

型セーフで union っぽいのが実現できるだけでよいので, 簡単な variant ほしい...

https://gist.github.com/tibordp/6909880

https://gist.github.com/calebh/fd00632d9c616d4b0c14e7c2865f3085

ありがとうございます!

calebh 版は RTTI も hash も使わずいい感じです!
`variant<bool, std::string> a` みたいな値なし?での初期化ができませんのでご注意ください.

オリジナルの tibordp は `std::swap` と `std::aligned_storage` での undefined behavior が起きる可能性があるのでご注意ください.

https://cpprefjp.github.io/reference/type_traits/aligned_storage.html
(設計等がよくないため, aligned_storage は非推奨になりつつあります)

いろいろ機能追加したのを tiny-variant で作りました.
型の id を自前で用意して与えて上げる必要があります
(つまり任意の型を使えはしないが, 特定の型だけに限定するのが可能となる)

https://github.com/syoyo/tinyusdz/blob/dev/src/tiny-variant.hh
python csvの中身を外部ライブラリなしで取り出す -openpyxl無し,csv無し-

<H1>csvの中身を簡単に取り出す</H1>

```python
f = open("商品データ.csv", "r", encoding="utf-8-sig") #CSVを開く
r = f.readlines() #中身を変数に代入
f.close() #CSVを閉じる
dat = []
for i in r:
    s = i.replace("\n", "") #ウィンドウズは¥n　改行を置換で削除
    dat.append(s.split(","))
print(dat)
```
![スクリーンショット 2022-07-11 19.05.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/2d343b14-4b3e-a2d2-ff46-ae65abdfa1de.png)
![スクリーンショット 2022-07-11 19.04.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/5b0c9e7f-4415-5f61-b940-cef853873c38.png)
Pythonでランダムに生成した整数を足し合わせて特定の数にするときの備忘録

# 概要
- あるテストをするのにレコード数１０００のCSVを作りたい
- ただし、ランダムに生成した整数を（1000レコード分）足し合わせたときに特定の数（今回は`32767`）にしなければならない

# 実装１
```python
import random

def gen_int():

    comb = []
    for i in range(1,1001):
        next_max_value = 32766-sum(comb)
        if next_max_value == 0:
            comb.append(0)
        else:
            comb.append(random.randint(0,next_max_value))

```
こういう風に書けば、1000レコード分足し合わせたときに32767になるのだが、、、中身を確認してみると途中から全部`０`になっていてデータとして使い物にならなそう。

```csvs:csv
27560
3412
1513
100
169
6
3
2
0
0
0
1
0
0
0
・
・
・
・
0
```
# 実装２
```python
import random
import numpy as np

def gen_int():

    value = []
    np.random.seed(32)
    value.append(np.random.uniform(0,65,998))

    int_list = []
    for i in value[0]:
        if sum(int_list) >= 32766:
            break
        else:
            int_list.append(int(i))
    
    int_list.append(352)
```
しょうがないので書き直したが、`uniform`の引数のチューニングに無駄に時間がかかってしまった上に、最後に足りない数（今回は352）をappendするという格好悪いやり方になってしまった。が、一応中身は期待するように出来上がった。

```csvs:csv
・
・
・
・
29
32
16
47
36
50
34
0
8
60
25
6
5
37
352
```

# まとめ
気の利いたやり方を考える時間が無いので今回はこんな感じで終わり。一応やりたいことはできたのだが格好悪い出来上がりになってしまったので、他に良いやり方があれば是非教えて下さい・・・。
postgreSQLのコマンドを外部から実行


## やりたい事
postgreSQLのパラメータをテキストファイルに出力するため
コマンドライン(外部)からpostgreSQLにコマンドを実行したい...

## やってみる

##### 1.SQLの実行ファイルをvimで作成

コマンドライン上でvimなどのエディタを使用し、SQL実行ファイルを作成します
今回のケースではpostgreSQLのパラメータを呼び出します。ファイル名は`parameter.sql`とします。
```
# parameter.sql
select name, setting, unit from pg_settings;
```

##### 2. parameter.sqlを実行し、テキストファイルに出力

```
psql -f parameter.sql -U ユーザ名 -d データベース名 -h ホスト > postgresql-config.txt
```

コマンドライン上から一時的にpostgreSQLにログインし、パラメータをpostgresql-config.txtに出力する
という処理が完了しました。

このように` -f sqlファイル`と指定することでファイルからコマンドを読み込んで実行する事ができます。
「HTTP/1.0」についてのメモ

#### 「HTTP/1.0」とは
- 1996年に[RFC1945](https://www.ietf.org/rfc/rfc1945.txt)としてまとめられた。
- リクエスト時にHTTPのバージョン情報が追加された。（例: `echo -e "GET / HTTP/1.0\r\n" |nc localhost 80`）
- リクエスト時のメソッドが「HTTP/0.9」の「GETのみ」から拡張された。
    - GET、HEAD、POST
        - POSTメソッドにより、クライアント側からサーバー側へのデータ送信が可能になった。([RFC1867](https://www.ietf.org/rfc/rfc1867.txt))
    - PUT、DELETE（ブラウザでは未サポート）
    - LINK、UNLINK（HTTP/1.1で廃止）
- リクエスト、応答時の両方でHTTPヘッダーが追加された。（ `Host` 、 `User-Agent` など）
    - HTTPヘッダーの例
        - コンテントネゴシエーションというファイルの種類や表示言語を決定する仕組みで、以下のようなHTTPヘッダーを利用する。
            - Accept
            - Accept-Charset
            - Accept-Encoding
            - Accept-Language
            - Content-Type
            - Content-Language
            - Content-Encoding
        - 応答時に `Content-Type` ヘッダーを送信することで、HTML形式（テキストファイル）以外のコンテンツが利用可能になった。
        - リファラー( `Referer` )
            - ウェブサイトの到達経路をサーバー側が把握するためにクライアント側から送信する。
        - ユーザーエージェント( `User-Agent` )
            - クライアントがサーバーにリクエストを行う際のアプリケーション名。
    - 「HTTP/0.9」のレスポンスはHTMLファイルそのものだったが、「HTTP/1.0」ではレスポンスにヘッダーが追加されたため、ヘッダーとボディの間に空行を挟んで、その空行以降をすべてボディとする形式となった。（電子メールと同じ構造）
- 応答時に3桁のステータスコードを送信するようになったことで、ステータスコード毎の処理分けが可能になった。（例: `HTTP/1.0 200 OK`）
    - 100番台（情報レスポンス）
    - 200番台（成功レスポンス）
    - 300番台（リダイレクトメッセージ）
    - 400番台（クライアントエラーレスポンス）
    - 500番台（サーバーエラーレスポンス）
- クッキー
- 認証
    - Basic認証
    - Digest認証
- セッション
- プロキシ
    - HTTP通信を中継する仕組み。
- キャッシュ
    - ダウンロード済みのコンテンツに変化がなければ、ダウンロードを抑制しパフォーマンスを向上させるメカニズム。

---

#### 参考URL
- [Hypertext Transfer Protocol -- HTTP/1.0](https://www.ietf.org/rfc/rfc1945.txt)
- [HTTP 1.0](https://www.f5.com/ja_jp/services/resources/glossary/http-1-0)
- [HTTP/1.0~3をちゃんと学んでみた。](https://qiita.com/rai_wtnb/items/87f8bc6c3e8f2c36a4ad)
- [Real World HTTP 技術メモ](https://qiita.com/aruitech/items/45944ac8dd63ccbdf9c6)
- [HTTPの歴史と技術の変遷](https://qiita.com/shiei_kawa/items/1c10311225eeef17fa01)
「HTTP/0.9」についてのメモ

#### 「HTTP/0.9」とは
- [Tim Berners-Lee](https://www.w3.org/People/Berners-Lee/)によって提案され、1991年にリリースされたHTTPのプロトタイプ。（1990年としている記事も多いですが、w3cの記事に「[The Original HTTP as defined in 1991](https://www.w3.org/Protocols/HTTP/AsImplemented.html)」と記載されているため、ここでは1991年としました）
- バージョン番号がなく「HTTP」と呼ばれていたが以降のバージョンと区別するため「HTTP/0.9」として位置づけられるようになった。
- サポートされているリクエストメソッドはGETのみ。
- リクエストメソッドはASCII文字列 + CRLFで構成される。（例: `echo -e "GET /\r\n" |nc localhost 80`）
- [isindexタグ](https://www.w3.org/wiki/HTML/jp/Elements/isindex)による検索が利用可能。（HTML 4.01で非推奨、HTML5で廃止）（例: `<isindex prompt="検索" action="search.cgi">`）
- サポートされている応答メッセージはHTMLのみ。
- 応答メッセージはASCII文字のストリームで構成される。
- HTTPヘッダーは定義されていない。
- ステータスコード、エラーコードは定義されていない。
- 応答メッセージの転送が完了するとTCP/IP接続が切断される。

---

#### 参考URL
- [The Original HTTP as defined in 1991](https://www.w3.org/Protocols/HTTP/AsImplemented.html)
- [HTTP 0.9: The One-Line Protocol](https://hpbn.co/brief-history-of-http/#http-09-the-one-line-protocol)
- [HTTP/0.9 – ワンラインプロトコル](https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP#http0.9_%E2%80%93_the_one-line_protocol)
- [Evolution of HTTP — HTTP/0.9, HTTP/1.0, HTTP/1.1, Keep-Alive, Upgrade, and HTTPS](https://medium.com/platform-engineer/evolution-of-http-69cfe6531ba0)
- [Summary of HTTP 0.9](https://www.w3.org/DesignIssues/HTTP0.9Summary.html)
- [HTTP/2とは？HTTP/2対応のレンタルサーバーでサイトを高速化させよう](https://knowledge.cpi.ad.jp/basic-knowledge/http2-help/)
- [What is HTTP/0.9 request?](https://superuser.com/questions/1504500/what-is-http-0-9-request)
- [第1回　HTTPプロトコルとは](https://atmarkit.itmedia.co.jp/ait/articles/1703/29/news045.html)
- [HTTP のはなし](http://www.silex.jp/blog/wireless/2016/02/http.html)
- [HTTPの歴史と技術の変遷](https://qiita.com/shiei_kawa/items/1c10311225eeef17fa01)
- [HTTPのバージョンによるリクエストの形式比較](https://qiita.com/shinobear01/items/3d152c611a81954c49f4)
- [HTTP/0.9は今でも使われている?](https://qiita.com/hakatashi/items/7bdbcab2067406003866)
- [HTTPのバージョンについてまとめ](https://qiita.com/hirooka0527/items/13767855358f83db5e02)
- [Webの世界-HTTP基礎編-](https://qiita.com/haseesah/items/6d9cb952bef8551d5eb9)
iOSでデュアルSIM情報を取得する

SIMの情報を取得しようと今まではこんな感じで、キャリアの名前とか取れてたんですが、

```
CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netinfo subscriberCellularProvider];
self.carrierLabel.text = carrier.carrierName;
```

iOS12以降ではデュアルSIMを想定したコードにする必要があります。

```objc
NSDictionary<NSString *, CTCarrier *> *dicCarrier =  [[CTTelephonyNetworkInfo new] serviceSubscriberCellularProviders];
for (id key in dicCarrier) {
  NSString *carrierName = [[dicCarrier objectForKey:key] carrierName];
  if ( carrierName ) {
    // 配列に追加
  }
}
```
【JavaScript】要素のドラッグ＆ドロップ

このように投稿した要素のドラッグ＆ドロップができるよう実装します。
![メモドラッグ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/f6f066e9-2f53-f517-4cc2-4e04a93dcdbf.gif)
# 投稿した要素のドラッグ＆ドロップ
```php
<?php
foreach ($memos as $memo) :
?>
<div class="memo">
 <div class="memo_text"><?= $memo['text'] ?></div>
</div>
<?php endforeach ?>
```
投稿をブラウザに表示します。
次に、JavaScriptでドラッグ＆ドロップを実装します。

```javascript
$(document).on('dblclick', '.memo', function(event) {
    let memo = document.querySelector('.memo');
    let currentDroppable = null;
    let currentDroppable_memogroup = null;
    let currentDroppable_memogroup_create = null;
    let shiftX = event.clientX - ball.getBoundingClientRect().left;
    let shiftY = event.clientY - ball.getBoundingClientRect().top;

    //絶対位置で一番上になるように
    memo.style.position = 'absolute';
    memo.style.zIndex = 5;

    //対象オブジェクトをbody要素に追加
    document.body.append(memo);

    moveAt(event.pageX, event.pageY);

    function moveAt(pageX, pageY) {
        memo.style.left = pageX - shiftX + 'px';
        memo.style.top = pageY - shiftY + 'px';
    }

    function onMouseMove(event) {
        moveAt(event.pageX, event.pageY);

        memo.hidden = true;
        let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
        memo.hidden = false;
    }
    document.addEventListener('mousemove', onMouseMove);

    memo.onmouseup = function() {
        document.removeEventListener('mousemove', onMouseMove);
        memo.onmouseup = null;
    };
});
```
対象の要素をダブルクリックしたときに、関数`moveAt`と`onMouseMove`を呼び出しています。
`mousemove`でleft/topを変更しています。

# ドラッグ中の要素を別要素にドラッグ
ドラッグ中の要素が別要素に重なるまたは離れた場合、処理が走るようにします。
```js
:
    document.addEventListener('mousemove', onMouseMove);

        let droppableBelow = elemBelow.closest('.memo');

        if (currentDroppable != droppableBelow) {
　　　　　　 // ドラッグ中の要素が別の要素から離れた場合
            if (currentDroppable) { 
　　　　　　 　alert('離れました');
            }

　　　　　　 // ドラッグ中の要素が別の要素に重なった場合
            currentDroppable = droppableBelow;
            if (currentDroppable) { 
　　　　　　 　alert('重なりました');
            }
        }
```
このように別要素に重なったかどうか、判定できるようになります。
![メモドラッグ2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/4a80001e-5c53-8563-f8c9-be132b3c3fa3.gif)

# 参考URL
https://ja.javascript.info/mouse-drag-and-drop
python 自動で拡張子を指定したファイルのみ新規フォルダにコピー　-shutil-

<H1>拡張子を指定したファイルのみ新規フォルダにコピー</H1>

```python
import os
import shutil

FOLDER = "コピーした文章" #作成するフォルダ名
if not os.path.exists(FOLDER): #フォルダがない場合作成
    os.mkdir(FOLDER)

for i in os.listdir(): #拡張子を指定して検索、コピー
    if i.endswith(".doc") or i.endswith(".docx"):
        shutil.copy(i, FOLDER+"/"+i)

```

![スクリーンショット 2022-07-11 18.37.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/a92ccbba-94cb-66f9-6dc4-02fed4c023ec.png)
![スクリーンショット 2022-07-11 18.38.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/af2b997f-a7ba-4c1d-a479-bc3ab3eb54a4.png)
![スクリーンショット 2022-07-11 18.39.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614609/90549530-a324-98ad-e531-c5ce8c29368c.png)
【Swift】Alamofireのパラメータエンコーディングについて

# はじめに
私は通信には必ずAlamofireを使用します。
URLSessionより簡潔にかけて便利だからです。
しかし、パラメータを設定しなければいけない時にエンコーディング形式を設定しないと動作しなかったので備忘録として残しておきます。

# パラメータエンコーディングの種類
## JSONEncoding.default
```swift
let headers: HTTPHeaders? = [
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
]

let parameters: [String: Any] = ["id": "123456789"]

AF.request("https://example.com/api", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseData { response in
    guard let data = response.data else { return }
    print(String.init(data: data, encoding: .utf8) ?? "")
}
```

## JSONEncoding.prettyPrinted
```swift
let headers: HTTPHeaders? = [
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
]

let parameters: [String: Any] = ["id": "123456789"]

AF.request("https://example.com/api", method: .post, parameters: parameters, encoding: JSONEncoding.prettyPrinted, headers: headers).responseData { response in
    guard let data = response.data else { return }
    print(String.init(data: data, encoding: .utf8) ?? "")
}
```
## URLEncoding.default
```swift
let headers: HTTPHeaders? = [
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
]

let parameters: [String: Any] = ["id": "123456789"]

AF.request("https://example.com/api", method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseData { response in
    guard let data = response.data else { return }
    print(String.init(data: data, encoding: .utf8) ?? "")
}
```

## URLEncoding.httpBody
```swift
let headers: HTTPHeaders? = [
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
]

let parameters: [String: Any] = ["id": "123456789"]

AF.request("https://example.com/api", method: .post, parameters: parameters, encoding: URLEncoding.httpBody, headers: headers).responseData { response in
    guard let data = response.data else { return }
    print(String.init(data: data, encoding: .utf8) ?? "")
}
```

## URLEncoding.queryString
```swift
let headers: HTTPHeaders? = [
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"
]

let parameters: [String: Any] = ["id": "123456789"]

AF.request("https://example.com/api", method: .post, parameters: parameters, encoding: URLEncoding.queryString, headers: headers).responseData { response in
    guard let data = response.data else { return }
    print(String.init(data: data, encoding: .utf8) ?? "")
}
```

# おわり
ちょこっと調べてみましたがパラメータのエンコーディングに関しての情報が少ないように思いました。
そもそも`encoding`という表記が分かりにくいような気がします。
何のエンコーディングなのかわからなので`parameterEncoding`このようにした方がようのかなと思いました。
Flutter オリジナルアプリアイコン を設置

# アプリにアイコン画像を設置する
アプリアイコンを初期のFlutterアイコンから任意の画像に変更する方法を記述します。
![](https://storage.googleapis.com/zenn-user-upload/4f4329fa39c5-20220709.png)

## flutter_launcher_iconsのインストール
アイコン画像を設定する為のパッケージを、ターミナルで下記コマンドを実行してインストール
```
dart pub add flutter_launcher_icons
```
https://pub.dev/packages/flutter_launcher_icons/install

## アプリに利用するアイコン画像を用意する
プロジェクト内にassetsファイル(ファイル名は任意)作成し、その中に画像を用意する
![](https://storage.googleapis.com/zenn-user-upload/182626b92bb0-20220709.png)

## pubspec.yamlにアイコン設置の記述
①``pubspec.yaml``内の``dev_dependencies:``以下に``flutter_launcher_icons: ^0.9.3``を記述
```
dev_dependencies:
  flutter_launcher_icons: ^0.9.3
```
②``pubspec.yaml``に下記を記述
``image_path: 'ここ'``と``adaptive_icon_foreground: 'ここ'``の部分にアイコンにしたい画像のPathを記述する。
```
flutter_icons:
  android: true
  ios: true
  image_path: 'assets/appicon.png'
  adaptive_icon_background: '#ffffff'
  adaptive_icon_foreground: 'assets/appicon.png'
```
インデントが見やすいよう、①②通しのコード
```
dev_dependencies:
  flutter_launcher_icons: ^0.9.3
  flutter_test:
    sdk: flutter

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^2.0.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
flutter_icons:
  android: true
  ios: true
  image_path: 'assets/appicon.png'
  adaptive_icon_background: '#ffffff'
  adaptive_icon_foreground: 'assets/appicon.png'
```
``flutter pub get``を実行して再ビルドをするとアイコン画像が表示されいるはずです!!

# 終わりに
Twitterでも情報発信しておりますので、ぜひフォローお願い致します!
https://mobile.twitter.com/tatsuki_kt
Flutter アプリ名の変更

# アプリ名の変更
下記画像の丸で囲まれている部分のアプリ名の変更方法を記述します
![](https://storage.googleapis.com/zenn-user-upload/c7a53b0aa4b9-20220708.jpg)

# ios
``ios/Runner/Info.plist``ファイルを編集する
![](https://storage.googleapis.com/zenn-user-upload/f943db9d3f56-20220708.png)
``<key>CFBundleDisplayName</key>``の下の<string>ここ</string>に変更したいアプリ名を入れる。
```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>希望のアプリ名</string>
```
これで再ビルドをすると変更されています!
# Android
``android/app/src/main/AndroidManifest.xml``ファイルを編集する
![](https://storage.googleapis.com/zenn-user-upload/1ad290f45b5a-20220708.png)

``android:label="ここ"``に変更したいアプリ名を入れる。
```
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.firebase_flutter_test">
   <application
        android:label="希望のアプリ名"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
```
こちらも再ビルドをして完了。

# 終わりに
Twitterでも情報発信しておりますので、ぜひフォローお願い致します!
https://mobile.twitter.com/tatsuki_kt
VOICEVOXのAPIからリップシンク用のlabファイルを生成


GUIには機能があるが、API経由での機能が見つからなかったので。

```python
def get_labdata(jsondata):
    labdata=""
    now_length=0
    timescale = 10000000/float(jsondata["speedScale"])
    for i in jsondata["accent_phrases"]:
      for j in i["moras"]:
        if j["consonant_length"] is not None:
          labdata += str(int(now_length*timescale)) + " "
          now_length += j["consonant_length"]
          labdata += str(int(now_length*timescale)) + " " + j["consonant"] + "\n"
        labdata += str(int(now_length*timescale)) + " "
        now_length += j["vowel_length"]
        labdata += str(int(now_length*timescale)) + " " + j["vowel"] + "\n"
      if i["pause_mora"] is not None:
        labdata += str(int(now_length*timescale)) + " "
        now_length += i["pause_mora"]["vowel_length"]
        labdata += str(int(now_length*timescale)) + " " + "pau\n"
    return labdata

request = requests.post('http://voicevoxサーバ/audio_query_from_preset?preset_id=プリセットID&text=読み上げメッセージ').json()

request["pitchScale"]=XXX
request["speedScale"]=XXX
request["intonationScale"]=XXX

labdata = get_labdata(request)
wavdata = requests.post('http://voicevoxサーバ/synthesis?speaker=スタイルID', data=json.dumps(request,ensure_ascii=False).encode("utf-8"))
wavf = open('static/tmp/'+ファイル名+'.wav', 'wb')
try: wavf.write(wavdata.content)
finally: wavf.close()
labf = open('static/tmp/'+ファイル名+'.lab', 'wb')
try: labf.write(labdata.encode('utf-8'))
finally: labf.close()
```

/audio_query_from_presetでクエリ作成した時点でconsonant_lengthやvowel_lengthの情報は出力されるが、その後にspeedScaleを変更すると、当然タイミングがずれる。
しかし/synthesisの後に改めてonsonant_lengthやvowel_lengthの情報を取得する方法が見つからなかったので、単純にspeedScale倍の速度で口を動かしてもらう。
これで一応は、それっぽく動いてくれた。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">VOICEVOXのAPIからlabファイル生成、/audio_query_from_preset時の出力から無理やり変換したが、もっとスマートな方法は無いのかな？<a href="https://t.co/jbn1rf0PyU">https://t.co/jbn1rf0PyU</a> <a href="https://t.co/DlSlUzmrXg">pic.twitter.com/DlSlUzmrXg</a></p>&mdash; lw05006 (@lw050061) <a href="https://twitter.com/lw050061/status/1546426691001917440?ref_src=twsrc%5Etfw">July 11, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

（多分、厳密にはずれる。speedScaleが変わる時は、それ用のプリセットを毎回作るのが本来のやり方かな？」）
CookieとSessionについてざっくりまとめた

Railsについての話なので、別言語別フレームワークの場合少し話が違うかもです。

# Sessionについて
sessionはサーバにデータを保存し、ブラウザのcookieという領域に（データと紐付けられた）セッションIDを保存する。そして次回リクエスト時にセッションIDをサーバに渡して、サーバがチェックしてOKだったらデータをブラウザに返すもの。データそのものをcookieに保存するのではないため改ざんされにくい。

# Cookieについて
cookieはブラウザのcookieという領域にデータをそのまま保存するから、署名しないと改ざんされる可能性がある。

# セッションCookieについて
Cookieにはいくつか種類がある。具体的には下記4つ。
・セッションCookie
・持続的Cookie
・署名付きCookie
・暗号化Cookie

セッションCookieは名前が紛らわしいですが、ブラウザを閉じると消えるCookieのことです。

# SessionとCookieの使い分け（ざっくり）
改ざんを考慮するほどでもないならcookieを使う
【PHP】UUID生成

# はじめに
昔にUUIDを生成するプログラムを作成したが、最近ふとプログラムを見直した時にUUIDを生成していないことに気付いた。
今一度UUIDの生成方法を見直したのでその記録として残そうと思う。
ちなみに記述しているUUIDは全て**version4**である。
※UUIDもどきは**version4**のつもりで作成したが**version4**になっていなかった…

# UUIDの生成
## パターン1
下記の方の記事を参考にしました。
[JavaScriptでUUID4を実現させる](https://qiita.com/jack-low/items/98b760e98895ead4bad6)
```php
$pattern = "xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx";
$character_array = str_split($pattern);
$uuid = "";

foreach($character_array as $character) {
    switch($character) {
        case "x":
            $uuid .= dechex(random_int(0, 15));
            break;

        case "y":
            $uuid .= dechex(random_int(8, 11));
            break;

        default:
            $uuid .= $character;
    }
}

var_dump($uuid); // e706a4ef_2a15_4145_a6a2_8a5cfc1cfe20
```
## パターン2
●追記　2022年7月16日
こちらのコードですが、コメント欄で@prc990さんに教えて頂きました。
```php
echo preg_replace_callback(
  '/x|y/',
  function($m) {
    return dechex($m[0] === 'x' ? random_int(0, 15) : random_int(8, 11));
  },
  'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'
);

// c66a8d6c_f74f_4267_91c3_0c36a5bfb017
```

# UUIDもどきの生成
```php
// 下記を変換してますがUUIDのバージョン4になっていない...
// xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx　→　%04x%04x-%04x-%04x-%04x-%04x%04x%04x
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
var_dump($uuid); // ac87b6c7-b014-1454-f6e7-4660ca57f395
```
ちなみに、%0(桁数)は桁数指定をしています。
例えば、%0(桁数)xの場合、10進数の「1000」を16進数変換すると「3e8」ですが0が入り「03e8」になります。.
0埋めで桁数を揃えたい場合にも使用できます。

# おまけ
Laravelだと下記のように記述することができます。
```php
use Illuminate\Support\Str;
 
return (string) Str::uuid();
```

# 参考文献
[rfc4122](https://datatracker.ietf.org/doc/html/rfc4122)
[UUID（Wikipedia）](https://ja.wikipedia.org/wiki/UUID)
[Laravel:helpers#method-str-uuid](https://laravel.com/docs/master/helpers#method-str-uuid)
[JavaScriptでUUID4を実現させる](https://qiita.com/jack-low/items/98b760e98895ead4bad6)
Flutter 自分のiPhoneにアプリをインストール

# 初めに
Flutterで作成したアプリを自分のiPhoneにインストールする方法について記述します。
インストールをすることで、**PCからビルドを行わず作成したアプリを自分のiPhone上で動かすことができます。**
今回はVScodeで行いますが、AndroidStudioでも同じ手順になります。

下記の記事での実機でビルドする為の設定が済んでいることが前提になりますので、済んでない方はそちらを行ってから今回の記事を見てください。
【Flutter iPhone実機 ビルド記事】
https://qiita.com/tatsukikane/items/000d20a234d144218923

# インストールの手順

## 自分のiPhoneが認識されていることの確認
ここに自分のiPhoneの名前が表示されていればOKです。
![](https://storage.googleapis.com/zenn-user-upload/c84e0e5d65af-20220711.png)

## ターミナルの起動
ターミナルを使ってインストールを行う為、VScode上にターミナルが表示されていない場合は、
``Command ＋　Shift ＋ P``を押すと下記の画面が表示されるので、「新しいターミナルを作成する」を選択してターミナルを起動。
![](https://storage.googleapis.com/zenn-user-upload/5e636e80e696-20220711.png)
## インストールする為のコマンドを実行
下記のコマンドを順番に実行してください。
### ①
```
flutter clean
```
### ②
```
flutter build ios
```
### ③
```
flutter install
```
以上で自分のiPhoneに作成したアプリをインストールは完了になります!!

# 終わりに😁
Twitterでも情報発信しておりますので、ぜひフォローお願い致します!
https://mobile.twitter.com/tatsuki_kt
Flutter iPhone実機 ビルド

# iPhone実機でビルド
今回はVScodeでiPhoneの実機を使ったビルド方法を記述します。

## XcodeでTeamの設定
実機でビルドをする為に、XcodeでTeamの設定を行います。
Xcodeを開いて、Open a project or file をクリック
![](https://storage.googleapis.com/zenn-user-upload/dd22bd5e1c0e-20220709.png)

対象のプロジェクトを選択して、iosを選択、その中のRunner.xcodeprojを開く
![](https://storage.googleapis.com/zenn-user-upload/ba7038f3c553-20220709.png)

Runnerをクリック、Signing&Capabilitiesの中の、Teamのタブを選択
![](https://storage.googleapis.com/zenn-user-upload/f51a0762abaa-20220709.png)

初めての場合はAdd an Account
![](https://storage.googleapis.com/zenn-user-upload/228eaf6b9f26-20220709.png)

AppleIDとPasswordを入力し、ログインをする。
![](https://storage.googleapis.com/zenn-user-upload/48204b73f74c-20220709.png)

## iPhone上での設定
iPhoneの **「設定」→「一般」**
![](https://storage.googleapis.com/zenn-user-upload/d2ae150e4ced-20220711.jpg)

**「VPNとデバイス管理」**
![](https://storage.googleapis.com/zenn-user-upload/1ab4e589d198-20220711.jpg)

**「デベロッパAPP」を許可**
※ここで何も選択できない場合は、次の手順の「Xcodeからビルド」を実行した後に、再度確認してみてください。
![](https://storage.googleapis.com/zenn-user-upload/9356da0fb340-20220711.jpg)



## Xcodeから一度ビルドする
VScodeからビルドする為に、Xcodeから一度ビルドをしておきます。
PCとiPhoneをケーブルで接続しておく。
自分のiPhoneの名前が表示されている状態で左上の再生マークを押してビルドです。
![](https://storage.googleapis.com/zenn-user-upload/292cf2fcf120-20220711.png)

## VScodeからビルドする

PCとiPhoneをケーブルで接続しておく。
VScodeの右下のNoDeviceをクリック
![](https://storage.googleapis.com/zenn-user-upload/4eae630d8c64-20220709.png)

実機のiPhoneを選択する
![](https://storage.googleapis.com/zenn-user-upload/7500ff4321a4-20220709.png)
その後いつも通りにビルドをしてOKです!

# 終わりに
Twitterでも情報発信しておりますので、ぜひフォローお願い致します!
https://mobile.twitter.com/tatsuki_kt
carrierwaveとcocoonを使った複数枚画像投稿

# 執筆中

## 概要
carrierwaveとcocoonを使った複数枚画像投稿機能。
結論から言うと、本体とは別に画像テーブルを作成し、formをcocoonで複製しないと、ハッシュ化した複数投稿はできない。(と、思う。)
いろいろな記事があるが、画像の名前をハッシュ化していなかったりとピンとくる記事がなかったのでそれらを補ったものを投稿する。

## 開発環境
・Ruby: 3.1.2
・Rails: 7.0.2
・OS: macOS Monterey

## 準備
### テーブル構成
本が1に対して、画像が多のテーブル構造。
[carrierwaveの公式サイト](https://github.com/carrierwaveuploader/carrierwave)では複数画像の時は、json形式のカラムを作り(本記事だとbook)、そこに配列形式で格納する方法が紹介されているが、この方法で実装するとファイル名のハッシュ化で詰む。(後の、画像テーブルは別で用意するにて詳述する)

```
# images
lass CreateNoticeImages < ActiveRecord::Migration[7.0]
  def change
    create_table :images,  comment: '投稿画像' do |t|
      t.references :book,       comment: '本',  null: false, foreign_key: true
      t.text :content,            comment: 'コンテント'

      t.timestamps
    end
  end
end
```

```
# book
class CreateBooks < ActiveRecord::Migration[7.0]
  def change
    create_table :books,  comment: '本' do |t|
      t.string :title,      comment: 'タイトル',    null: false
      t.text :body,         comment: '本文'

      t.timestamps
    end
  end
end
```

### gem追加
```
gem 'carrierwave'
gem 'cocoon'
gem 'mini_magick'
```

### uploaderクラスの追加
```
rails g uploader image
```

### CarrierWave編集
ApplicationUploaderクラス
```
# frozen_string_literal: true

class ApplicationUploader < CarrierWave::Uploader::Base
  storage Settings.use_gcs ? :fog : :file

  # see CarrierWave::Uploader::Configuration#add_config
  def self.fog_public
    true
  end

  def extension_allowlist
    %w[jpg jpeg gif png pdf]
  end

  def content_type_allowlist
    %w[image/jpeg image/gif image/png application/pdf]
  end

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # このメソッドで画像名をハッシュ化してる。ここ大事。
  def filename
    "#{secure_token}.#{file.extension}" if file
  end

  def fog_directory
    if fog_public
      super
    else
      Settings.fog_directory_private
    end
  end

  protected

    def secure_token
      var = :"@#{mounted_as}_secure_token"
      model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
    end
end

```

ImageUploaderクラス
```
# frozen_string_literal: true

class ImageUploader < ApplicationUploader
  include CarrierWave::MiniMagick

  # override allowlist in ApplicationUploader
  def extension_allowlist
    %w[jpg jpeg gif png]
  end

  def content_type_allowlist
    %w[image/jpeg image/gif image/png]
  end

　# ここでサムネイル画像のサイズ指定してる。
　# image_tagで使いたかったら、.thumb.url　のように指定する。
  version :thumb do
    process resize_to_fit: [300, 200]
  end

  class << self
    def accept_mimetypes
      new.content_type_allowlist.join(',')
    end
  end
end
```

## 注意点
### 画像テーブルは別で用意する
[参考記事[1]](https://github.com/carrierwaveuploader/carrierwave/issues/1716)
[参考記事[2]](https://qiita.com/sakiyamaK/items/15a95df5bf7781d1352b)
Postmanがすごそう

# 初めに

名前だけは聞いていたPostmanを使ってみた記事です。Postmanの達人ではなく、Postmanって何？という方に向けた記事になります。

# Postmanって何？

API developer用の開発ツールです。リクエストパラメータや認証情報などを任意に設定してAPIの呼び出すことができます。curlのIDEみたいな感じですね。

https://www.postman.com/

# Postmanの何がすごそうなの？

## APIリクエストのパラメータ等を管理できる

こんな感じで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/952563d9-583a-05b9-5957-269956014e91.png)


それぞれはこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/640f2c58-319e-9e7c-9643-e8ff02455cda.png)


開発するAPIの仕様に合わせて、Authorizationも設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/569bf7cf-a6e0-1652-7e9b-782e3e6f0ebb.png)

例えば`x-api-key`を設定する必要があるとか、Bearer Tokenが必要ですとか、お手元の要件に合わせて設定しましょう。

接続先などを環境変数として設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/b668f854-883e-e648-9d72-78ffa63d1d83.png)

### 詳しくは

https://learning.postman.com/docs/sending-requests/managing-environments/


なので、ベースのリクエストパターンを用意して、例えばローカル用、例えばSTG用といった形で接続先だけ分けるといったことが可能です。

## リクエスト結果をテストするScriptを書ける

こんな感じで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/a15130fb-d606-0841-ada7-23a073c4bc33.png)


これはresponseのステータスと返却内容のobjectが正しいかを確認しています。

pre-request scriptもあるので前処理もできるはず（例えば認証しないと使えないAPIのために認証をするとかできるはず）

## 諸々設定した値をjsonファイルに書き出せる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619165/f7b1327d-3a6b-9797-3ea9-9b9018cae9ab.png)

### ということは

git管理できる

### consoleから呼ぶライブラリもあります。

https://www.npmjs.com/package/newman

#### お試ししてみたい

お試し用サーバとnewman用のjsonファイルを格納したレポジトリを作りました。
READMEに書きましたが、各種コマンドを打つことでサーバを立てたり、newmanでリクエストしてみたりできます。

https://github.com/pbuchihori/postman-sample
三重のfor文でオブジェクトを沢山出す

![スクリーンショット 2022-07-11 171056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2134624/1e1dbc35-2a34-6791-4a5c-e418b59705e0.png)
まずcubeをヒエラルキーに出しassetsの中にドラッグアンドドロップしてプレハブ化したら以下のコードを書きます。
```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Boxs : MonoBehaviour
{
    public GameObject Box;
    Vector3 BoxPos;
    void Start()
    {
        for (float x = 0.0f; x < 50.0f; x += 2.0f)
        {
            for (float y = 0.0f; y < 50.0f; y += 2.0f)
            {
                for (float z = 0.0f; z < 50.0f; z += 2.0f)
                {
                    BoxPos = new Vector3(x, y, z);
                    Instantiate(Box, BoxPos, Quaternion.identity);
                }
            }
        }
    }
}
```
ヒエラルキーに空のオブジェクトを出してBoxs.csをアタッチして、プレハブ化したcubeをボックスにドラッグアンドドロップしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2134624/8b2ac5f6-4f76-f869-5fbf-a3277709f163.png)
あとは実行ボタンを押してcubeが沢山出ていることを確認しましょう。
有線LANアダプターでMacをインターネットに接続

BUFFALOのLUA4-U3-CGTE-WHを購入した。
差し込みだけで、インターネットに接続できなかった。
調べると、ドライバーが必要です。

「[対応OSツール](https://www.buffalo.jp/product/taiou/search/?item_code=LUA4-U3-AGTE-WH&lv1=2000___Mac&type=600)」により、macOS Big Sur　バージョン　11は対応されないそうです。

[plugable](https://ja.plugable.com/blogs/news/new-asix-driver-fixes-macos-11-big-sur-ethernet)のページを参考して、対応のドライバーをダウンロードできる。

今回、 **「ASIX macOS 11 Big Sur 用 DEXT 1.3.0(2021年8月18日)のダウンロード」** を使用しました。
マニュアルが入っていないため、下記のPKGを一緒にダウンロードし、中のマニュアルを使用した。
「macOS 12.x Monterey対応、DEXT2.0.0(2021年10月29日版)のダウンロード」