OmniAICreator/Qiita-1.07M huggingface dataset:
ヒープソートをC言語で作ってみた

いろいろお勉強したのでまとめます
## ヒープソートって？
ヒープソートは、ヒープ化を使って配列の最小（最大）値を求めて配列の先っぽにくっつける
その最小（最大）値を配列から無視して、もう一度ヒープ化

これを繰り返すと、ソートが完了するよねっていうソート方法

## ヒープ化って？
ヒープ化は配列を木構造に見立てて親が子よりも小さい（大きい）法則を守った木構造にすること
これによって配列の中の最小（最大）を早く求めることができる

## ソースコード
```C:heap.c

void swap(int* i1, int* i2){
    int temp = *i1;
    *i1 = *i2;
    *i2 = temp;
}

void downheap(int* array, int len ,int target){
    int right, left, min = target;
    left = (target * 2) + 1;
    right = (target * 2) + 2;
    if(len > left){
        if(array[left] < array[min]){
            min = left;
        }
    }
    if(len > right){
        if(array[right] < array[min]){
            min = right;
        }
    }
    if(min != target){
        swap(&array[min], &array[target]);
        downheap(array, len, min);
    }
}

void heap(int* array, int len){
    for(int i = (len / 2) - 1; i >= 0; i--){
        downheap(array, len, i);
    }
}

void heap_sort(int* array, int len){
    for(int length = len, i = 0; length > 0; length--, i++){
        heap(&array[i], length);
    }
}
```

ヒープソートの本体は`heap_sort()`
ヒープ化は`heap()`が担っている

## 実行してみる

```C:heap.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
void array_print(int* array, int len){
    for(int i = 0; i < len; i++){
        printf(" %d,", array[i]);
    }
    printf("\n");
}

#define ARRAY_NUM 15

int main(int argc, char const *argv[])
{
    
    int buf[ARRAY_NUM];
    srand((unsigned int)time(NULL)); 
    for(unsigned int i = 0; i < ARRAY_NUM; i++){
        buf[i] = rand() % 200;
    }
    array_print(buf, ARRAY_NUM);
    heap_sort(buf, ARRAY_NUM);
    array_print(buf, ARRAY_NUM);

    return 0;
}

```
乱数を使ってぐちゃぐちゃの配列を作って並び替えてみる

### 実行結果
```
./heap2.bin
 172, 137, 40, 128, 97, 73, 180, 155, 132, 101, 96, 87, 93, 72, 171,
 40, 72, 73, 87, 93, 96, 97, 101, 128, 132, 137, 155, 171, 172, 180,
```
ヨシ！！！！

## まとめ
とりあえずヒープ化を理解するのが難しかった
最初は配列を木構造にするとかもあんまり理解できなかったし
そこからヒープ化する動きも、最初は理解できなかった
先人たちのコードを参考にしなければ絶対に理解できなかった気がする

クイックソートがあるから実用環境じゃあんまり使えないけど
ヒープ化の参考にでもしてください
【nodejs】ハッシュ化におけるソルト

# ソルトハッシュとは
ソルトハッシュとは、パスワードなどの機密情報をハッシュ化する際にランダムな文字列を追加し、機密情報の解読をより困難にするためのデータです。ハッシュ化ソルトは、機密情報が盗まれた場合でも、攻撃者にとって正しい機密情報を推測することが難しくなります。

例えば、パスワードをハッシュ化する場合、パスワードとハッシュ化ソルトを結合した文字列をハッシュ関数に入力し、ハッシュ値を生成します。このようにすることで、同じパスワードでも異なるハッシュ値が生成されるため、パスワードを知っていても、ハッシュ値から元のパスワードを復元することは困難になります。

![スクリーンショット 2023-04-19 10.24.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/6117cb3e-75a0-8530-cbd5-9712f93d8702.png)

# nodejsによるソルトハッシュ
```js
const crypto = require('crypto');

// ランダムな16バイトのソルトを生成する
const salt = crypto.randomBytes(16).toString('hex');

// ソルト化するパスワード
const password = 'password123';

// パスワードとソルトを結合する
const saltedPassword = password + salt;

// SHA256ハッシュ関数を使用して、ソルトとパスワードを混ぜ合わせてハッシュ化する
const hashedPassword = crypto.createHash('sha256').update(saltedPassword).digest('hex');

console.log('ソルト：', salt);
console.log('ソルト化されたパスワード：', saltedPassword);
console.log('ソルト化されたパスワードのハッシュ値：', hashedPassword);

```

上記の例では、crypto.randomBytes()メソッドを使用して、ランダムな16バイトのソルトを生成します。次に、パスワードとソルトを結合し、新しい文字列を形成します。その後、SHA256ハッシュ関数を使用して、新しい文字列をハッシュ化し、最終的なソルト化されたパスワードのハッシュ値を得ます。

注意点として、パスワードの検証時に同じソルトを使用するため、生成されたソルトをデータベースなどに保存しておく必要があります。パスワードの検証時には、ユーザーが入力したパスワードと保存されたソルトを結合し、同じハッシュアルゴリズムと同じソルトを使用してハッシュ化する必要があります。

以下は、パスワードを検証する例です。
```js
// データベースから取得した保存されたパスワードのハッシュ値とソルト
const storedHashedPassword = 'c684b07e9d69ef37f1352c78b8c590b17beaa1f85b44d176fbb79c9b66fb786d';
const storedSalt = 'b25c508e97486ccf62c1d26177d4f4f3';

// ユーザーが入力したパスワード
const userPassword = 'password123';

// ユーザーが入力したパスワードとソルトを結合する
const userSaltedPassword = userPassword + storedSalt;

// SHA256ハッシュ関数を使用して、ソルトとパスワードを混ぜ合わせてハッシュ化する
const userHashedPassword = crypto.createHash('sha256').update(userSaltedPassword).digest('hex');

// ユーザーが入力したパスワードを照合する
if (userHashedPassword === storedHashedPassword) {
  console.log('一致する');
} else {
  console.log('一致しない');
}

```
JIRAでのタスク管理整理

# JIRAタスク導入のメリット

<dl>
  <dt>リージョン組織 -> 機能別組織への変換</dt>
      <dd>日本・海外問わずに、ERPシステムの統一化が図れる。GDMなどの事前整備が必要</dd>
  <dt>ロードマップ整理・タスク可視化</dt>
      <dd>半年・1年後のロードマップを作成。その目標に対して、タスクを細分化してSprintの落とし込む</dd>
</dl>

<dl>
  <dt>Conversion from Region Organization -> Functional Organization</dt>
      <dd>Unify ERP systems regardless of Japan or overseas; requires advance maintenance such as GDM.</dd>
  <dt>Roadmap organization and task visualization</dt>
      <dd>Create a roadmap for the next 6 months or 1 year. For that goal, subdivide tasks and drop them into Sprint.</dd>
</dl>
App Engineについて

# App Engineについて
## App Engineのコンポーネントについて
　①App Engineスタンドアプリケーションは、次の4つのコンポーネントから構成されている</br>
　　・アプリケーション</br>
　　⇒プロジェクトで作成された上位リソース、App Engineアプリに関連するすべてのリソースはアプリ作成された時に指定したRegion内に作成される。</br>
　　・サービス</br>
  ⇒ソースコードと定義ファイルで定義される。このような組み合わせがアプリのバージョンになります。
　　・バージョン</br>
⇒ソースコードや定義ファイルは少しでも変更すると、別のバージョンが作成される。一度複数のバージョンのアプリケーションを管理することができます。</br>
　　・インスタンス</br>
以下のイメージで

## App Engineのdeployついて
　①Cloud shellとCloud SDKを利用して、アプリをデプロイする </br>
      ・gcloudがApp Engineで動作するような構成を確認する</br>
      　```gcloud components install app-engine-python``` </br>
      上記コマンドでライブラリがインストールまたは更新される。</br>
　　　　・以下のＨｅｌｌｏＷｏｒｄ　サンプルアプリを使って、Deployの手順を説明する</br>
　　　　　・サンプルは以下。</br>
　　　　https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine/standard/hello_world　</br>
　　　　　サンプルには、以下の３ファイルが存在する</br>
　　　　　　　　　　・app.yaml</br>
　　　　　　　　　　・main.py</br>
　　　　　　　　　　・main_test.py</br>
　　　　　上記のapp.yamlは以下の内容で、アプリの構成を定義したファイルである。
　　　　　　<pre><code>
　　　　　　runtime: python27
　　　　　　api_version: 1
　　　　　　threadsafe: true
　　　　　　handlers:- url: /.*
　　　　　　script: main.app
  　　　　　</code></pre></br>
　　　　アプリ構成ファイルには、Pythonのバージョン、デプロイしているＡＰＩのバージョン、Pythonのパラメータを指定する</br>
　　　・アプリをDeployするには、以下のコマンドで</br>
      　```gcloud app deploy app.yaml``` </br>
       また、以下のパラメータも任意指定できる </br>
       　　　■--version: バージョン指定</br>
       　　　■--project: このアプリのプロジェクトIDを指定する</br>
       　　　■--no-promote: トラフィックをルーティングせずにアプリをDeployする/br>

　　　・アプリの特定バージョンを停止するには、以下のコマンドで</br>
　　　　```gcloud app version stop v1 v2``` </br>
        v1とv2を停止する </br>

## App Engineのスケーリングついて
　①App Engine負荷に基き、必要に応じて自動的にインスタンスを追加または削除することができる。負荷に基づいてインスタンスがスケーリングされる時は、動的インスタンスと呼ばれる。</br>

　②常駐または常時実行を継続できる自動的にインスタンスを追加または削除することができる。負荷に基づいてインスタンスがスケーリングされる時は、動的インスタンスと呼ばれる。</br>
　　　・インスタンスは常駐か動的か、構成によって決まる、自動スケーリングまたは基本スケーリングを構成する場合、インスタンスは動的で、手動スケーリングを構成する場合、インスタンスは常駐 </br>   
　　　・自動スケーリングの場合、app.yamlにautomatic_scalingセクションを追加して、以下の構成オプションのキーと値のベアを指定</br>   
　　　　　　　・target_cpu_utilization：ＣＰＵ使用率、追加インスタンスが起動する前の最大ＣＰＵ使用率を指定する。</br>   
　　　　　　　・target_throughput_utilization：スループット使用率、追加インスタンスが起動する前、同時リクエストの最大数を指定する。</br>  
　　　　　　　・max_concurrent_requests：スループット使用率、追加インスタンスが起動する前、同時リクエストの最大数を指定する、既定値は１０、最大８０。</br>  
　　　　　　　・max_instances、min_instances：最大及び最小インスタンス数、このアプリで実行できるインスタンス数の範囲を指定する。</br>  
　　　　　　　・max_pending_latency、min_pending_latency：最大及び最小レイテンシ、キューのリクエストの待機最大時間と最小時間を指定する。</br>
　　　・基本スケーリングの場合、idle_timeout及びmax_instancesのみです</br>   

## App Engineバージョン間でのトラフィックの分割について
　①複数のバージョンのアプリが実行される場合、バージョン間でトラフィックを分割できる</br>
　　　　　　　・IPアドレスにより分割</br>  
　　　　　　　　　　ある程度のトラフィックが固定され、IPアドレスが変わらない限り、常に同じ分割にルーティングされる。</br> 
　　　　　　　・Http　Cookieにより分割</br>  
　　　　　　　　　　ユーザを複数のバージョンに割り当る時役たち。</br> 
　　　　　　　・ランダムにより分割</br>  
　　　　　　　　　　ワークロードを均等に分散させる。</br>
yt-dlpをDEから呼び出すwrapper

yt-dlpをDE（MATEやcinnamonやxfce4やLXDE）から呼び出すwrapperです。
どうしても、ytdlp-guiが動かなかったので作りました。
DEにランチャを作り、このプログラムを「端末内で実行」するようにしておけば、GUIからyt-dlpが呼び出せます。

### yt-dlpのインストール

```
yay -S yt-dlp
```

yt-dlpは、URLさえ解れば、ウェブ上の大概の動画とFacebookの動画と、Twitterの一部の動画をダウンロードできます。

### wrapper

`chmod +x videodownloader.py`として、実行権を付けておいて下さい。

```videodownloader.py
#!/usr/bin/env python3
import subprocess

savedir="/home/user/Videos"
print("Youtube Downloader")
url=input("Input URL:")
subprocess.call(["/usr/bin/yt-dlp","-P",savedir,"--trim-filenames","32",url])
print("Done. Hit enter key")
a=input()
```
Benchmarkでパフォーマンスを確認しましょう！

## 概要

時には、アプリケーションの一部の処理速度を確認したいことはあるかと思います。 [Laravel9.32](https://github.com/laravel/framework/blob/5dd58d428c64811b70ecba57a75e77c136578410/CHANGELOG.md#v9320---2022-09-27)から便利な素早くテストができるBenchmarkのファサードが追加されました！

## 使い方

コールバックとして、速度をテストしたい機能を`Benchmark::dd()`に渡して、処理が完了するまでかかるミリ秒を測定することができます！

```php
use Illuminate\Support\Benchmark;

Benchmark::dd(
    fn () => User::orderBy('id', 'desc')->get()
);

// 1.505ms
```

### 同時に複数機能をテストする
一つの機能だけではなく、コールバクの配列を渡せば、同時にいくつかの機能を「素早く比較」もできます！

```php
use Illuminate\Support\Benchmark;

Benchmark::dd([
    fn () => User::orderBy('id', 'desc')->get(),
    fn () => User::all()->sortByDesc('id')
]);

// array:2 [ 
//  0 => "1.669ms"
//  1 => "1.810ms"
// ]
```
### 反復回数の設定で平均値をとる

処理期間でばらつきはあり得るため、一回だけで実行するのはテストにならないという意見もあるかと思います。そのため、`Benchmark::dd()`の第二引数でコールバックを呼び出す反復回数を指定することも可能です。反復回数を指定すれば、かかった**平均ミリ秒**が返されますのでより良い判断材料になるかと思います。

```php
use Illuminate\Support\Benchmark;

Benchmark::dd(
    fn () => User::orderBy('id', 'desc')->get(),
    100
);

// 100回実行した平均ms
// 1.669ms
```

## まとめ

実装中の悩み・先輩のサジェスト・デバグにネックなりそうのところのパーフォマンスをBenchmarkで確認しましょう！

## 参考

 [APIのドックス](https://laravel.com/api/9.x/Illuminate/Support/Benchmark.html)
 [公開ドックス](https://laravel.com/docs/9.x/helpers#benchmarking)
  [Laravel9.32のchangelog](https://github.com/laravel/framework/blob/5dd58d428c64811b70ecba57a75e77c136578410/CHANGELOG.md#v9320---2022-09-27)
FirebaseのrealtimeDBの書き込み・読み込みを行う方法

Firebaseのプロジェクト画面を開き、プロジェクトの管理をクリックする

![Screen Shot 2023-04-19 at 9.43.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/e28e8fd3-0619-e59d-2c1b-52d274155328.png)

サービスアカウントタブの、〇〇個のサービスアカウントタブを押す
そうするとGCPのIAMのサービスアカウントの管理画面にいく

![Screen Shot 2023-04-19 at 9.44.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/0ae56d3b-e946-cea1-41d2-90063f84e840.png)

下記の画面は、サービスアカウントが3つ、オーナーが1つ表示されている。
![Screen Shot 2023-04-19 at 9.48.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/0315cd3e-6175-1e17-ad0f-f47812f4396a.png)

サービスアカウントに適切な権限があるかを確認する(下記2つ)
- Firebase Authenticate 管理者
- Firebase Realtime Databse 管理者

次に、サービスアカウントをプログラムで管理できるようにキーを発行する
使うアカウントをクリックし、キータブを開くと、`鍵を追加` と出てくる。
![Screen Shot 2023-04-19 at 9.52.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/436863ec-ebcf-f7a1-6daa-8b5a93ee6361.png)

json型を指定してダウンロードし、鍵を大事に保管してください。
![Screen Shot 2023-04-19 at 9.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/c9877325-0ef4-c666-e3a7-9bc5e8bc9a79.png)

Railsでは、
ちなみに、Realtime databaseでルールが、以下のようにした場合
(読み込みは誰でもできる・書き込みは認証を通った人のみ)

![Screen Shot 2023-04-19 at 9.56.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/15acf94c-c554-6384-3253-dd6d3eb83567.png)



```rb
        # Firebase RealTimeDBに書き込むためのアクセストークンを取得
        CONFIDENTIAL_PATH = "config/#{ファイル名}.josn"
        def get_google_oauth2_access_token
            # 参考: https://github.com/googleapis/google-auth-library-ruby
            scopes =  [
                "https://www.googleapis.com/auth/userinfo.email",
                "https://www.googleapis.com/auth/firebase.database",
            ]
            
            authorizer = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: File.open(CONFIDENTIAL_PATH),scope: scopes)
            
            authorizer.fetch_access_token!
            
            # トークンの有効時間は1時間のみ
            authorizer.access_token
        end
    def reset_db
        access_token = get_google_oauth2_access_token
        uri = URI("#{REALTIME_DB_ENDPOINT}/schedule_list.json?access_token=#{access_token}")
        request = Net::HTTP::Put.new(uri)
        request.body = {}.to_json
        response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
            http.request(request)
        end
        puts response.body
    end
```
みたいな感じで操作できます。
Tried k8sgpt job

こんにちは。Enabling team の山本です。

今回は、[k8sgpt](https://github.com/k8sgpt-ai/k8sgpt) について書きます。

ChatGPT の登場以降、Engineer としての存在意義を考えざるをえない状況にあると思います。

今回、検証する `k8sgpt` は、次のとおり説明されています。
>Giving Kubernetes SRE superpowers to everyone

今の自分の Role の消滅さえ近づいている 😱

ひとまず、`k8sgpt` について活用方法を調べていきます。

`k8sgpt` については、いろんな方が記事を残していますので、使い方は割愛します。
今回、`Job` として、`k8sgpt` を動かすことによって、自動的に Cluster のエラーを通知する仕組みを考察します。

## TL;DR
- 分析した内容を Webhook で通知することは可能。
- 情報の漏洩を考えると、Production 環境で運用することは難しい。Staging 環境で分析し、その内容を Production 環境に反映することは可能かも。

## RBAC の準備
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gpt-ksa
  namespace: gpt
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gpt-cr
  namespace: gpt
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gpt-crb
  namespace: gpt
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gpt-cr
subjects:
- kind: ServiceAccount
  name: gpt-ksa
  namespace: gpt
```

## Job の作成
```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: gpt-job-e
  namespace: gpt
spec:
  template:
    spec:
      serviceAccountName: gpt-ksa
      containers:
      - name: gpt-job
        image: google/cloud-sdk
        command: ["bash", "-c"]
        args:
        - curl -LO https://github.com/k8sgpt-ai/k8sgpt/releases/download/v0.2.4/k8sgpt_amd64.deb && dpkg -i k8sgpt_amd64.deb && k8sgpt version && k8sgpt auth --password=************* && k8sgpt analyze --language Japanaese --explain --no-cache
      restartPolicy: Never
  backoffLimit: 4
EOF
```

## 結果
```bash
yamamoto_daisuke@cloudshell:~ (hoge-334000)$ k logs gpt-job-e-gstgv -n gpt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 16.3M  100 16.3M    0     0  10.5M      0  0:00:01  0:00:01 --:--:-- 51.0M
Selecting previously unselected package k8sgpt.
(Reading database ... 98425 files and directories currently installed.)
Preparing to unpack k8sgpt_amd64.deb ...
Unpacking k8sgpt (0.2.4) ...
Setting up k8sgpt (0.2.4) ...
k8sgpt version 0.2.4
Using openai as backend AI provider
New provider added
key added
 100% |███████████████████████████████████████████████| (1/1, 9 it/min)        

0 gpt/hoge(hoge)
- Error: Back-off pulling image "hoge"
エラーメッセージ：「バックオフイメージ「hoge」の引き出し」

このエラーメッセージは、Kubernetesが指定されたコンテナイメージを取得できなかったことを示しています。このエラーの原因は、Dockerレジストリからイメージをダウンロードするために必要な権限が不足していることがあります。

解決策：
1. イメージの名前が正しいか確認します。
2. 既存のイメージと同じ名前のイメージが存在しないか確認します。
3. Dockerレジストリにログインして、必要な権限があることを確認します。
4. インターネット接続が正常に行われているか確認します。

以上の対処法を行い、再度実行してみてください。

yamamoto_daisuke@cloudshell:~ (hoge-334000)$
```

## まとめ
`k8sgpt` について書きました。
今後は、分析だけではなく、対話しながら解決に導かれるような運用になっていくことも考えられます。
GPT とどのように付き合っていくのか、試行錯誤していきます。
【データ基盤構築/AWS】DMSとSnowpipeを使ってRDSのデータをSnowflakeにロードする時につまずいたこと

# 今回の課題
DMS(Database Migration Service)とSnowpipeを使うことで、
RDS上の変更をほぼリアルタイムでデータウェアハウスに転送することが可能だということを知ったため試してみることにした。





# 実装手順
基本的に、下記の記事の通りに進めたので、
本記事での解説は割愛して、実装中につまずいたところを中心に書いていきたいと思います。

https://zenn.dev/dataheroes/articles/2021-04-24-snowflake-dms-rds?redirected=1





実装した手順を簡潔に書くと、以下の流れになります。
1. DMSのレプリケーションインスタンスの設定。
1. データ転送元のRDSに対して、ソースエンドポイントを作成。
1. データ転送先のS3に対して、ターゲットエンドポイントを作成。
1. `データベース移行タスク`を作成。
※`データベース移行タスクの作成`では、`移行タイプ`を`既存のデータを移行して、継続的な変更をレプリケートする`または`データ変更のみをレプリケートする`を選択し、RDSの変更が継続的にS3にロードされるように設定します。
5. Snowpipeを作成。

# つまずいたポイント
RDSのデータに変更があった際に、変更を検知してS3にデータをロードしたいので、
移行タイプを`既存のデータを移行して、継続的な変更をレプリケートする`または、`データ変更のみをレプリケートする`に設定していたのだが、
そうすると、`データベース移行タスク`を実行しても、下記の画像のように失敗に終わってしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/160b6481-24fe-316b-65f1-61e7b80bc7ad.png)

色々試行錯誤してみたところ、
データ転送元のRDSに対してソースエンドポイントを作成する段階で、以下2点の設定ができていなかったことが原因だと分かった。


# できていなかった設定について
## RDSのMYSQLバイナリログ保持時間を変更
まず1つ目のできていなかった設定は、**バイナリログの保持時間の変更**。
デフォルトだと、バイナリログを保持しない状態となっている。

以下の記事のように、
バイナリログの保持時間についての値を`_NULL`(バイナリログを保持しない状態)から、`24` (24時間保持する状態)に変更する設定を行う必要があった。

このように設定することによって、レプリケーション時に参照するバイナリログがすぐに消えてしまわないように調整することができた。

https://qiita.com/kooohei/items/90a1ad7d3e83b1e941ec

**※バイナリログとは**
MYSQLサーバーインスタンスで行われたデータ変更に関する情報を含む、一連のログファイルのこと。

## RDS Parameter Groupを変更する
2つ目のできていなかった設定は、RDS Parameter Groupの変更。
RDS Parameter Groupとは、データベースの設定をテンプレートとして管理できるような機能のこと。

以下の手順で、DBパラメータグループの作成・編集して、現在利用しているRDSの設定に使用する必要があった。

#### 1)パラメータグループを新規作成する
RDSのコンソール画面から`パラメータグループの作成`を行う画面に飛ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/a9201e10-82d2-2e8f-d540-5727f9909d1a.png)

ここで、現在使用しているバージョンと同じ(今回はmysql8.0)パラメタグループを選択し、パラメータグループの新規作成を行う。



#### 2)パラメータの編集を行う
DBパラメータグループを作ったら、下記の作成したDBパラメータグループのページから、
`パラメータの編集`ページに飛ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/71ce8bd5-234c-ccb0-e55b-8c7574871e39.png)
そして、[こちらのドキュメント](https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Source.MySQL.html#CHAP_Source.MySQL.AmazonManaged)のように、`1)`で作成したDBパラメータグループの2つのパタメータを下記のように変更する。
* `binlog_format = ROW`
* `binlog_checksum = NONE`



#### 3)現在利用しているRDSのDBパラメータグループを変更する
RDSの`DBインスタンス変更`画面の、`追加設定`の`データベースの選択肢`にて、
DBパラメータグループを`2)`で作成したものに変更する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/05b342a4-e758-97a1-7f9f-959afd505641.png)
これによって、RDSの設定を変えることができた。


#### 4)RDSインスタンスを再起動する。
最後にRDSを再起動する。
これによって、`3)`で行なったRDSの設定の変更を反映させることができる。

# まとめ
以上のように進めることで、
`データベース移行タスク`が失敗に終わってしまう不具合を解決することができた！

そしてそれによって、
**RDSに変更があった時にはDMSがS3に変更データをロードし、
SnowpipeがSnowflakeのテーブルにほぼリアルタイムでデータをロードする。**
という機能を実装することができた。

MySQLは「バイナリログ」を使って、データベースの操作履歴を記録しているため、「バイナリログ」周りの設定を少し調整する必要があったようだった。



#### 参考記事

https://zenn.dev/dataheroes/articles/2021-04-24-snowflake-dms-rds?redirected=1

https://dev.classmethod.jp/articles/rdb-dms-rds/

https://docs.aws.amazon.com/ja_jp/dms/latest/userguide/CHAP_Source.MySQL.html#CHAP_Source.MySQL.AmazonManaged
MLflow 2.3のHugging Faceトランスフォーマーのサポートを試す

世の中のスピードがすごいと感じる今日この頃です。

こちらのHugging Faceトランスフォーマーのサポートを試しました。

https://qiita.com/taka_yayoi/items/431fa69430c5c6a5e741

```
%pip install mlflow==2.3
```

DollyをHugging Face HubからDollyをロードして、MLflowにロギングします。

```py:Python
import mlflow
import transformers

architecture = "databricks/dolly-v2-3b"

dolly = transformers.pipeline(model=architecture, trust_remote_code=True)

with mlflow.start_run():
    model_info = mlflow.transformers.log_model(
        transformers_model=dolly,
        artifact_path="dolly3b",
        input_example="Hello, Dolly!",
    )

loaded_dolly = mlflow.transformers.load_model(
model_info.model_uri, 
max_new_tokens=250,
)
```

記録されました！
![Screenshot 2023-04-19 at 9.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f4abb0a0-ed14-41c4-924f-60c298352e87.png)

モデルカードもばっちり。
![Screenshot 2023-04-19 at 9.29.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b8feeaca-a2d1-a670-765d-8e93eade9fc5.png)

次に、ロードしたモデルPyFuncとして活用できるようにしてみます。

```py:Python
import transformers
import mlflow

chat_pipeline = transformers.pipeline(model="microsoft/DialoGPT-medium")

with mlflow.start_run():
  model_info = mlflow.transformers.log_model(
    transformers_model=chat_pipeline,
    artifact_path="chatbot",
    input_example="Hi there!"
  )

# Load as interactive pyfunc

chatbot = mlflow.pyfunc.load_model(model_info.model_uri)
```

南極大陸に行くベストな方法は？

```py:Python
chatbot.predict("What is the best way to get to Antarctica?")
```

ボートでそこに行けると思います。

```
Out[3]: 'I think you can get there by boat.'
```

そうですか…。

次は、OpenAIのAPIのフレーバーを試してみます。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Compose実装時に気をつけたいこと

# 初めに
今回はCompose実装時に自分が気をつけていることを紹介していきます
### 本文
***Modifierの設定順序***
自分が一番気をつけていることは`Modifier`に対する設定の順番です
実は`Modifier`は設定がどんどん上書きされているので
```kotlin:例１
modifier = Modifier.padding(8.dp).clickable{}
```

```kotlin:例２
modifier = Modifier.clickable{}.padding(8.dp)
```
上記二つでは大きく違ってきてしまいます。
例１では先に`padding`を設定しているため、対象のView全体にはタップ判定が存在しません
そのため、`padding`が大きくなればなるほどタップ判定を拾ってくれる箇所が狭くなってしまいます
これはタップ処理だけでなく`background`なども同じことが言えるので自分は一番気をつけています
### 最後に
今回は自分がCompose実装時に気をつけていることを紹介しました。
ふとした時にやってしまうので自戒の意味も込めて記事にしました
atu dump support for mediatek

atu dumpの機能をRT3050などのMediatek(Ralink)のSOCでもサポートしてみました。

https://github.com/ZRouter/freebsd-src/commit/50597bd76a22c73a4fe382b535344135aee495a4

RalinkはRT3050でSwitchが入ってRT5350などは同じ仕様のようですが、Mediatekに買収されてからのMT7620以降は大きく仕様が変わっています。

ただ両方ともMDIOなどではなくBUS上にSwitchのレジスタが見えてます。

MT7620のデーターシートはMT7620 PROGRAMMING GUIDEというタイトルになっています。

SwitchのAddress Tableは一昔前は企業秘密みたいなところがあったのですが、上のドキュメントにはなんだか内部仕様みたいな情報まで載っています。買収されてやけくそになったのかな？

とりあえずデーターシートで仕様を確認してユーザーランドのetherswitccfgコマンドのregで書き込みして読み込みを試して、なんらかの値が帰ってくることを確認して、カーネルに実装しました。

Mediatekのetherswitchcfgのregは16bitで返すようになっていました。おそらくMDIOの仕様にあわせたと思われますが、etherswitch自体は32bitも扱えるので、SOCの仕様が32bitなので、32bitの方が良いように思われます。

RT3050ではportは数値なのですが、MT7620ではビットで表されています。

こういう追加機能のカーネルへの実装はその機能を使うまでは処理が行われないので、万が一があっても気が楽です。カーネルが上がんなくなると、upgradeがリモートで出来なくなるので厄介です。

RT3050の方はゴミが入っていたりします。また何故かすぐに消えます。MT7620の方は二重にエントリーが入っていたりします。

flushの機能はあまり必要性を感じないので実装してません。

MT7620の4ポートにはNTP ST1をそれぞれつないでいて、どのポートにどのサーバが接続されているか確認できます。

上のレポジトリには本家に無い機能がいろいろ入っているのでZRouter.org Forked FreeBSD(ZFF)と呼ぼうかと思っています。
VSCodeマウスのホイールで画面の拡大・縮小できる設定


# 【執筆中】VSCodeマウスのホイールで画面の拡大・縮小できる設定

setting.jsonに以下の記述を追記しておくと[Ctrl]+マウスのホイールで画面の拡大・縮小ができるようになるので便利！！

```
"editor.mouseWheelZoom": true,
```
APIGatewayをCDKで構築するコツ

## ターゲット
CDKでAPIGatewayを構築したい。
APIGatewayをOPENAPIで定義をしたい。

## OPENAPIでAPIGatewayを構築するメリット
最大のメリットはドキュメントの作成とAPIの実装を同時にできることだと思います。　
簡単に書けるのに、OPENAPI形式で構成を記述すれば、可読性も上がるし、APIGatewayに読み込ませるだけですぐにAPIが実装できます。　


しかし、CDKでAPIGatewayを構築すると、AWSの拡張機能もOPENAPIに記述しなくてはならないです。
以下のようなオブジェクトです。毎回調べる必要があるのは手間です。

```
x-amazon-apigateway-integration
```

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html

## open-apix
解決策になるのが以下のライブラリです。

https://github.com/alma-cdk/openapix

```javascript
npm i openapix 
```

で使えます。　

使い方の詳細はAPIリファレンスを参照してください。

https://github.com/alma-cdk/openapix/blob/main/API.md


## 使い方のコツ
使い方の流れは以下のようになります。
* OPENAPIを記述
* CDKの定義ファイル内でopenapixのモジュールを呼び出す
* openapixのモジュールでOPENAPIを読み込む
* OPENPAIで定義できないAPIGatewayの設定を記載する

実際にAPIGateway→Lambdaで構築したAPIのCDKを解説します。


## サンプルコード
```typescript:api_gateway_stack.ts
import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as iambda from 'aws-cdk-lib/aws-lambda';
import * as apigw from 'aws-cdk-lib/aws-apigateway';
import * as openapix from '@alma-cdk/openapix';
import * as path from 'path' 
import { Construct } from 'constructs';

export class ApiStack extends
cdk.Stack { constructor (scope: Construct, id: string, props?: cdk.StackProps)
{
  super(scope, id, props);

  const apiResourcePolicy = new iam.PolicyDocument({
    statements: [
      new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        principals: [new iam.AnyPrincipal(), 
        actions: ['execute-api: Invoke'], 
        resources: ['execute-api:/*/*/*'],
        conditions: {
          'IpAddress': {
            "aws: SourceIp": [
              "xxx.xxx.xxx.xxx/32",
              "xxx.xxx.xxx.xxx/32"
            ]
        }
      })
    ]
  })

  const api = new openapix.Api(this,'api', {
    source: path.join (dirname, '../openapi/openapi.yaml'),
    restApiProps: {
      policy: apiResourcePolicy
    }, 
    paths: {
      /api/{path}': {
        get: new openapix.LambdaIntegration(this, lambdaFunction)
      }
    }
  }
}

```

## サンプルコードの解説
* `apiResourcePolicy` : APIGatewayのリソースポリシーを定義しています。ここではIPアドレスを制限しています。
* `openapix.Api` : openapixを使ってAPIGatewayの設定を定義します。
* `source` : openapiディレクトリに配置しているOPENAPI形式のyamlファイルを読み込んでいます。
* `restApiProps` : リソースポリシーを設定しています。リソースポリシー以外にもRESTAPIの設定を加えることができます。
* `paths` : APIのパスを設定しています。
* `openapix.LambdaIntegration` : 事前に定義したLambda関数を呼び出しています。今回のサンプルコードではLambda設定部分は省略していますので、定義方法は他の記事を参照してください。

## 参考記事
https://zenn.dev/taroman_zenn/articles/91879cec40627c
VScodeを使いこなすためのショートカットキーのメモ

# 【執筆中】VScodeを使いこなすためのショートカットキーのメモ

VSCodeを使っている人が身近に多く、自分自身もこの機会にVSCode使いになろうと思って毎日今までのテキストエディタからVSCodeへの切り替えをしていこうと思い練習中なので、使いこなしていくためのショートカットキーなどのメモを残しておこうと思います（拡張機能編などは別の記事にします）。

|したい事|ショートカット|備考|
|:----|:----|:---|
|一行削除|[Ctrl]+[Shift]+[k]||
Webアプリケーションの仕組みを理解する

## 足し算をするWebアプリケーションを作る
index.html:
```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>足し算アプリ</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
    }

    input[type="number"] {
      width: 100px;
      margin: 5px;
    }

    .result {
      font-size: 24px;
      margin-top: 20px;
    }
  </style>
</head>
<body>
  <h1>足し算アプリ</h1>
  <input type="number" id="number1" placeholder="数値1">
  <span>+</span>
  <input type="number" id="number2" placeholder="数値2">
  <br>
  <button id="calculate">計算</button>
  <div class="result" id="result"></div>

  <script src="app.js"></script>
</body>
</html>
```
app.js:
```javascript
const number1 = document.getElementById("number1");
const number2 = document.getElementById("number2");
const calculateBtn = document.getElementById("calculate");
const resultElement = document.getElementById("result");

async function calculateSum() {
  const value1 = parseFloat(number1.value);
  const value2 = parseFloat(number2.value);

  if (isNaN(value1) || isNaN(value2)) {
    alert("数値を入力してください。");
    return;
  }

  try {
    const response = await fetch("calculate.php", {
      method: "POST",
      body: new URLSearchParams({
        number1: value1,
        number2: value2
      }),
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      }
    });

    if (!response.ok) {
      throw new Error("サーバーエラーが発生しました。");
    }

    const data = await response.json();
    resultElement.textContent = `合計: ${data.sum}`;
  } catch (error) {
    alert(error.message);
  }
}

calculateBtn.addEventListener("click", calculateSum);
```
calculate.php:
```php
<?php
header("Content-Type: application/json");

$number1 = isset($_POST["number1"]) ? $_POST["number1"] : null;
$number2 = isset($_POST["number2"]) ? $_POST["number2"] : null;

if ($number1 === null || $number2 === null) {
  http_response_code(400);
  echo json_encode(["error" => "数値を入力してください。"]);
  exit();
}

$sum = $number1 + $number2;
echo json_encode(["sum" => $sum]);

```



### 基本的な情報のやり取りの説明

1. **クライアント（index.html & app.js）**： ユーザーがブラウザで足し算アプリケーションを開くと、HTMLとJavaScriptが表示・実行される。ユーザーは2つの数値を入力し、「計算」ボタンをクリックする。

2. **リクエスト（app.js）**： ボタンがクリックされると、JavaScriptはサーバーにリクエストを送信する。このリクエストは、HTTP POSTメソッドを使用し、入力された数値がパラメータとして送られる。

3. **ルーティング（サーバー側）**： サーバーはリクエストを受け取り、URLに基づいて適切な処理を行うプログラム（この例では、PHPファイル：calculate.php）にリクエストを渡す。

4. **処理（calculate.php）**： PHPプログラムは、リクエストから送られた2つの数値を受け取り、足し算を実行する。

5. **レスポンス（calculate.php）**： 足し算が完了したら、サーバーは結果をJSON形式でクライアントに返す。JSONデータには、計算結果が含まれる。

6. **表示（app.js）**： クライアントは、サーバーから受け取ったJSONデータを解析し、計算結果を表示する。JavaScriptを使って、結果をHTML要素に挿入し、ユーザーに表示する。
入力規則をバイパスする方法


+ [Bypass Validation Rules in a Flow (and Process too!)](https://jenwlee.com/2021/04/05/bypass-validation-rules-in-a-flow-and-process-too/)

以下はチェックボックスを使わない方法を求めているけど、無いとおもう。

+ [Bypass validation rule](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000PeIU7)
Googleデータアナリティクス：SQLの一時テーブル

# はじめに

本記事は、Googleデータアナリティクスのプロフェッショナル認定証のプログラムより、参照させて頂いています。興味を持った方は、是非受講してみてください。

https://www.coursera.org/professional-certificates/data-analytics-japanese

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/21a12cb1-a49a-802f-d903-6f68758eca0c.png" width="800">

# 一時テーブルについて

データアナリストが SQL を使うときにも 付箋のようなものがあります。 これは一時テーブルと呼ばれるものです。 今回は、これがどんなものかを探っていきます。 一時テーブルとは、データベースサーバー上に 一時的に作成され、存在するテーブルのことです。 

標準データテーブルのデータのサブセットを 一定期間保存してくれるものです。 そして、SQL データベースでセッションを 終了すると自動的に削除されます。 一時テーブルは永久に保存されないので 計算などの分析作業を行うために 短期間だけテーブルが必要な場合に便利です。

- たとえば、同時に計算を行うテーブルが たくさんある場合などがそうです。 そのうちの 7、8 個のテーブルを 結合するクエリがある場合 行数の少ない 2、3 個のテーブルを結合し その出力を一時テーブルに 格納することができます。 そして、この一時テーブルは 他の大きなテーブルと結合できます。 
- もうひとつの例は、多くの異なる データベースにクエリを実行する場合です。 それぞれのデータベースで最初のクエリを実行し 一時テーブルを使ってすべてのクエリの結果を 収集できます。 最終的なクエリ レポートは、 この一時テーブルで実行されます。 一時テーブルがなければ、このレポート構造を 使うことはできないかもしれません。 
- また、テーブルの中に大量のレコードがあり その中のごく一部のレコードを何度も操作して 計算や分析を行う必要がある場合にも便利です。 そのため、何度もデータをフィルタリングして サブセットを返すのではなく 一度データをフィルタリングして 一時テーブルに保存できます。 そして作成したその一時テーブルを使い クエリを実行できます。 

一時テーブルを使用すれば、 データをフィルタリングすることなく このデータに対していくつかのクエリを 実行できます。 SQL で一時テーブルを作成する方法は 使用しているリレーショナル データベースの 管理システムによってさまざまです。

# クエリ 

クエリに WITH 句を当てはめてみます。 WITH 句は一時テーブルの一種で 複数回クエリを実行できます。 一時テーブルに近いものです。 基本的に一時テーブルと同じ働きで 同じものを作成します。 作業中のデータベースにテーブルを追加せず 他の人も結果を見ることができますし 皆さんの作業を確認する必要がある人は 皆さんの結果を導いたコードも見られます。

では、このクエリを書いてみましょう。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/e991f0dc-3e54-4efc-efba-74dbb437b9e0.png" width="700">

- このクエリは、WITH コマンドで始まります。一時テーブルの名前を trips_over_1_hr とします。 
- 次に、AS コマンドと開き括弧を入力します。 
- 新しい行では、SELECT FROM WHERE 構造の サブクエリを使用します。 
- 次に FROM コマンドを入力し、 取得するデータベースの名前 bigquery-public-data. new_york.citibike_trips を入力します。
- 次に、WHERE 句で、一時テーブルで必要な 自転車走行の長さが 60 分以上であることを 条件として追加します。 
- 最後に、新しい行に閉じ括弧を追加して サブクエリを終了します。 

これで、一時テーブルができあがり、 60 分以上の旅行の結果だけを返す クエリを実行できるようになりました。 早速試してみましょう。 

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/8be75538-c776-fa60-565a-270204380f38.png" width="700">

このクエリを実行すると、 データセットから 60 分以上の 自転車走行の総数が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/e66e88a4-7570-4cb9-77cf-a4813d29fb1b.png" width="300">

60 分以上の自転車走行を分析する限り この一時テーブルに対して 何度もクエリを実行できます。 またセッションを終了し、後で新しい処理を 開始する必要がある場合、ほとんどのサーバーは 一時テーブルに使用したコードを保存しています。 コードを実行してテーブルを再作成するだけです。

:::note info
一時テーブルを使用すると 作業を効率化することができます。 一時テーブルに名前を付けて使えば たくさんのデータをより合理的に処理でき 同じクエリを何度も繰り返すことなく 一時テーブルにそのコードを含めるだけで 済みます。 
さらに、一時テーブルを使うことで 他のチームメンバーの役に立つ側面もあります。 一時テーブルは コードの複雑さを軽減でき、 読みやすく、理解しやすくなり、 チームメンバーも喜ぶでしょう。
:::
Add More Options to Your Screens


+ [Screen Flows  > Add More Options to Your Screens](https://trailhead.salesforce.com/ja/content/learn/modules/screen-flows/add-more-options-to-your-screens)

+ [Even though the Checkbox component has a conform product field in its properties, it doesn't show.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PixywSAB)
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2f88debe-679e-fcc6-b432-505be63f70df.png)


+ [オブジェクト API 名を選択するときに、オブジェクト「Opportunity」を選択できません。選択できるのは、作成したレコード変数 OpVar のみです。変数を選択すると、フィールドも選択する必要があります。課題のように、オブジェクト自体だけを選択する方法はありますか?それともOpportunity.IDを選択する必要がありますか? ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007clQwY)

:::note
https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007UvhCr

ありがとう。名前を入力するだけで機能するようになりました。参考にさせていただきました、検索しても該当のスレッドが見つかりませんでした。 
:::
Trailhead Playground を再アクティブ化する方法


+ [How do I get my Trailhead Playground reactivated or create a new one?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PihNH)


Salesforce Developer Edition 組織の再有効化で問題が発生しているとのこと、申し訳ございません。組織を再アクティブ化するために実行できるいくつかの手順を次に示します。

1. 資格情報を使用して Salesforce アカウントにログインします。
2. 画面の右上隅にある疑問符アイコン (?) をクリックして、ヘルプ & トレーニング ポータルに移動します。
3. 検索バーに「ケースを開く」と入力します。
4. 「Salesforceカスタマーサポートでケースを開く」という最初の結果をクリックします。
5. [開始] ボタンをクリックして、ケースを開くプロセスを開始します。
6. 連絡先情報、問題の説明、非アクティブ化された組織の組織 ID (00D8c0000085uta) などの必須フィールドに入力します。
7. ケースを送信すると、Salesforce の担当者がすぐに連絡を取り、組織の再有効化を支援します。


それでもヘルプ & トレーニング ポータルからケースを作成できない場合は、電話や電子メールなどの他のチャネルで Salesforce カスタマー サポートに問い合わせることができます。連絡先情報は、Salesforce の Web サイトで確認できます。


I'm sorry to hear that you are having trouble reactivating your Salesforce Developer Edition org. Here are some steps you can take to reactivate your org:

1. Log in to your Salesforce account with your credentials.
2. Go to the Help & Training portal by clicking on the question mark icon (?) in the top-right corner of the screen.
3. In the search bar, type "open a case."
4. Click on the first result, which should be "Open a Case with Salesforce Customer Support."
5. Click on the "Get Started" button to initiate the process of opening a case.
6. Fill in the required fields, including your contact information, a description of your issue, and the org ID of the inactivated org (00D8c0000085uta).
7. Submit your case, and a Salesforce representative should get back to you soon to help you reactivate your org.


If you are still unable to create a case via the Help & Training portal, you can try reaching out to Salesforce Customer Support through other channels, such as phone or email. Their contact information can be found on the Salesforce website.
ターミナルがBashやZshではなくBourneシェルだよってGPTに教えられた話

# あれ、補完が効かないし意味わからん文字でるし

深く、色々な事を理解しないまま進めているとこういう事ってよくありますよね。

今回は、ターミナルが変な挙動をするのでGPTに聞いたら簡単に理解と解決が出来た、そんなお話
。


# おい！GPTさんよぉ！これなんなん！
質問した内容はこうです。

```
docker内にexecでコンテナに入った後、
ターミナルにて補完が出来ていましたが、
タブ補完やカーソルキーを押下しても、
履歴や保管が出るのではなく「[[A」のような文字が入力されます。
これはどういう状況でどのようにすれば解決できるか知りたい
```

まずまずの、国語力の無さが際立った文章です。良い感じです。

GPT返答

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081664/5f849b62-cc86-5b98-a547-ae1458ba95c2.png)

なるほど？

とりあえず、ターミナルで

```sh
echo $0

# out
/bin/sh
```

まぁ、そうよね。Dockerfileに
```dockerfile
CMD ["/bin/sh"]
```
って書いたし。
(この時点でもよくわかってないので、何も通じていない所がGoodですね。)


続きいってみよう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081664/dd056d84-035e-4172-714c-74bc3e90d989.png)


# Bourneシェル？( ﾟдﾟ)ﾅﾆｿﾚ

```sh
Bourneシェルは、タブ補完やカーソル移動などの
高度なターミナルエミュレーション機能を持っていません。
```

そういうことか！！先に言ってくれよ(誰かのせいにするあたりは、優勝ですね。)

ワイ「なんかおかしいとおもったんよね。ターミナル入力するとき、#しか映ってなかったから、違和感はあったんじゃぜ。」

おしまい。

# 結論
- 補完、効いて嬉しい。
- 困ったらそのままにしないで調べよう
- GPT便利（だけど、使用者のリテラシーによって間違えている回答に気づけず間違えた理解になるときがあるので利用時に注意。詳細は本記事コメントでの指摘を要確認）
wemosでlcdkeypad その7

# 概要
wemos d1で、lcdkeypadを使ってみた。
練習問題、やってみた。

# 練習問題
じゃんけんを実装せよ。

# サンプルコード

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(0, 2, 4, 14, 12, 13);
char janken[] = { 
	0xbc,
	0xde,
	0xac,
	0xdd,
	0xb9,
	0xdd,
	0x00
};
char aiko[] = { 
	0xb1,
	0xb2,
	0xba,
	0x00
};
char kati[] = { 
	0xb1,
	0xc5,
	0xc0,
	0xc9,
	0xb6,
	0xc1,
	0x00
};
char make[] = { 
	0xb1,
	0xc5,
	0xc0,
	0xc9,
	0xcf,
	0xb9,
	0x00
};
char gu[] = { 
	0xb8,
	0xde,
	0xb0,
	0x00
};
char choki[] = { 
	0xc1,
	0xae,
	0xb7,
	0x00
};
char par[] = { 
	0xca,
	0xdf,
	0xb0,
	0x00
};
int hantei(int a, int b) {
	if (a == b)
	{
		return 0;
	}
	switch (a)
	{
	case 0:
		return ((b == 1) ? 1 : 2);
	case 1:
		return ((b == 2) ? 1 : 2);
	case 2:
		return ((b == 0) ? 1 : 2);
	default:
		return -1;
	}
}

void setup() {
	lcd.begin(16, 2);
	lcd.setCursor(0, 0);
}
void loop() {
	int a = -1,
		b;
	int adc;
	adc = analogRead(A0);
	if (adc > 1000) 
	{
		delay(500);
		adc = analogRead(A0);
		if (adc > 1000) 
		{
			return;
		}
	}
	if (adc > 0 && adc < 30)
	{
		//lcd.printf("RIGHT");
		a = 2;
	}
	if (adc > 30 && adc < 300)
	{
		//lcd.printf("UP   ");
		a = 0;
	}
	if (adc > 400 && adc < 600)
	{
		//lcd.printf("DOWN ");
		a = 1;
	}
	if (adc > 700 && adc < 1000)
	{
		//lcd.printf("LEFT ");
		lcd.setCursor(0, 0);
		lcd.printf("                ");
		lcd.setCursor(0, 1);
		lcd.printf("                ");
		lcd.setCursor(0, 0);
		lcd.printf(janken);
	}
	if (adc > 1000) 
	{
		//lcd.printf("     ");
	}
	if (a > -1)
	{
		b = rand() % 3;
		lcd.setCursor(0, 0);
		lcd.printf("                ");
		lcd.setCursor(0, 1);
		lcd.printf("                ");
		lcd.setCursor(0, 0);
		switch (a)
		{
		case 0:
			lcd.printf(gu);
		break;
		case 1:
			lcd.printf(choki);
		break;
		case 2:
			lcd.printf(par);
		break;
		default:
		break;
		}
		lcd.setCursor(7, 0);
		switch (b)
		{
		case 0:
			lcd.printf(gu);
		break;
		case 1:
			lcd.printf(choki);
		break;
		case 2:
			lcd.printf(par);
		break;
		default:
		break;
		}
		lcd.setCursor(0, 1);
		int c = hantei(a, b);
		switch (c)
		{
		case 0:
			lcd.printf(aiko);
		break;
		case 1:
			lcd.printf(kati);
		break;
		case 2:
			lcd.printf(make);
		break;
		default:
		break;
		}
	}
	delay(1000);
}




```

以上。
paiza.ioでelixir その219

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
じゃんけんを実装せよ。

# 参考にしたページ。

https://qiita.com/RyoWakabayashi/items/584ca018d03656f92481

# サンプルコード

```

defmodule Main do
    def hand(c) do
        if c == 0 do
            IO.puts("グー")
        end
        if c == 1 do
            IO.puts("チョキ")
        end
        if c == 2 do
            IO.puts("パー")
        end
    end
    def judge(a, b) do
        if a == b do
            IO.puts("あいこ")
        end
        if a == 0 && b == 1 do
            IO.puts("あなたの勝ち")
        end
        if a == 1 && b == 2 do
            IO.puts("あなたの勝ち")
        end
        if a == 2 && b == 0 do
            IO.puts("あなたの勝ち")
        end
        if a == 0 && b == 2 do
            IO.puts("あなたの負け")
        end
        if a == 1 && b == 0 do
            IO.puts("あなたの負け")
        end
        if a == 2 && b == 1 do
            IO.puts("あなたの負け")
        end
    end
	def main do
		IO.puts("0, グー 1, チョキ  2, パー")
		{a, _} = IO.read(:line)
		    |> Integer.parse()
        hand(a)
        b = 0..2 
            |> Enum.random
        hand(b)
        judge(a, b)
	end
end
Main.main
Main.main
Main.main




```

# 実行結果

```
0, グー 1, チョキ  2, パー
グー
パー
あなたの負け
0, グー 1, チョキ  2, パー
チョキ
グー
あなたの負け
0, グー 1, チョキ  2, パー
パー
パー
あいこ

```

# 成果物

https://paiza.io/projects/nlJI6opF7aCs7clU46HNGA


以上。
システム開発の設計のつながりを自分なりに考えてみた

システム開発を20年くらいやってる人です。
要件、設計、開発、テストとそれなりにいろんな役割でやってました。
プロジェクトが変わるたびに自分なりに設計書のつながりを絵にすることが多かったので発散含めて自分なりに汎用的なやつを考えてみました。
プロジェクトごとに着眼点が違ったり自分の足りてない経験があったりで至らない点が多いかも．．．

システム設計の中で一番、重要になるのは概念モデルだと思ってます！

# システム設計のつながり
![システム設計つながり.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/e6c1d676-2d0f-977c-d4da-35886c3b4ac8.png)

# 各システム設計の概要
![システム設計概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/432dd080-6109-7040-944e-8cb944dcaab0.png)
Test-Connectionコマンドについて

# Test-Connectionとは
PowerShellのコマンドレット『Test-Connection』について解説します。
こちらはDOSコマンドの『ping』にあたり、特定のコンピュータにIPネットワーク経由で接続できるか確認することができます。

# 構文
```PowerShell
Test-Connection
    [-TargetName] <string[]>
    [-Ping]
    [-IPv4]
    [-IPv6]
    [-ResolveDestination]
    [-Source <string>]
    [-MaxHops <int>]
    [-Count <int>]
    [-Delay <int>]
    [-BufferSize <int>]
    [-DontFragment]
    [-TimeoutSeconds <int>]
    [-Quiet]
    [<CommonParameters>]
```

色々とオプションがありますが、引数にアドレスを持たせるだけでシンプルに実行してみると下記のような結果になります。

```PowerShell
PS C:\User> Test-Connection www.google.com

Source   Destination     IPV4Address      IPV6Address                              Bytes    Time(ms)
------   -----------     -----------      -----------                              -----    --------
TEST-PC   www.google.com  142.250.207.36                                            32       10
TEST-PC   www.google.com  142.250.207.36                                            32       9
TEST-PC   www.google.com  142.250.207.36                                            32       9
TEST-PC   www.google.com  142.250.207.36                                            32       11
```

DOSのpingと同じでデフォルトでは4回送信される。
オプション`-Count`で回数の指定もできる。

```PowerShell
PS C:\Users\user> test-connection -Count 10 google.com

Source    Destination     IPV4Address      IPV6Address                              Bytes    Time(ms)
------    -----------     -----------      -----------                              -----    --------
TEST-PC   google.com      142.250.207.46                                            32       1336
TEST-PC   google.com      142.250.207.46                                            32       12
TEST-PC   google.com      142.250.207.46                                            32       9
TEST-PC   google.com      142.250.207.46                                            32       13
TEST-PC   google.com      142.250.207.46                                            32       10
TEST-PC   google.com      142.250.207.46                                            32       10
TEST-PC   google.com      142.250.207.46                                            32       10
TEST-PC   google.com      142.250.207.46                                            32       9
TEST-PC   google.com      142.250.207.46                                            32       10
TEST-PC   google.com      142.250.207.46                                            32       9
```

## 参考

https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/test-connection?view=powershell-7.3
「HTML+CSS 標準入門」＃3

今日の勉強メモ

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

「疑似セレクタ」
:hover　マウスが上に乗っているとき
:active　クリックしている間
:focus　Tabキーなどでフォーカスされている時
:visited　訪れたことのあるリンクのスタイル

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

transform:translate
Y(値);→要素をY方向(縦)に値分動かす
X(値);→要素をY方向(縦)に値分動かす
                    　　　　　　　　 
　　　　　　　　　　　　　　　　　　　 

使用例：
:active {
    border-bottom: none;
    transform: translateY(4px);
}
ボタンをクリックしたときに、凹んだようにみせる。
AKS Edge EssentialsをWindows11にインストールしてみる

### 前段

Windows 11, Windows 11 IoTにKubernetesをインストールする方法の第二弾です。AKS Edge EssentialsをWindows11にインストールしてみます。
この記事は[Install Kubernetes on Windows 10 and Windows 11 with AKS Edge Essentials](https://www.thomasmaurer.ch/2023/03/install-kubernetes-on-windows-10-and-windows-11-with-aks-edge-essentials/)を参考にしました。

### 要件

4/18/2023時点だと以下のように記されています。最新情報は[Microsoftドキュメント](https://learn.microsoft.com/en-us/azure/aks/hybrid/aks-edge-system-requirements?WT.mc_id=modinfra-0000-thmaure)から確認してください

| Specs | Local cluster |
| ----- | ------------- |
| Host OS | Windows 10/11 IoT Enterprise/Enterprise/Pro and Windows Server 2019, 2022 |
| Total physical memory | 4 GB with at least 2.5 GB free
| CPU | 2 vCPUs, clock speed at least 1.8 GHz |
| Disk Space | At least 14 GB free |

### 手順

1. AKS Edge Essentialsのインストール
早速インストールを進めていきます。K8s、K3sお好みのインストーラをダウンロードします。作業しやすくするためにC:\AKSEdgeEフォルダを作成しそこで作業していきます。
```
# Create Folder 
mkdir C:\AKSEdgeE

# K8s installer
$urlK8sMSI = "https://aka.ms/aks-edge/k8s-msi"
$path = "C:\AKSEdgeE\k8s.msi"
Start-BitsTransfer -Source $urlK8sMSI -Destination $path
```
Windows Containerを扱えるようにしておくためにWindows Node Filesもダウンロードしておきます。
```
#Windows Node Files
$urlWindowsFiles = "https://aka.ms/aks-edge/windows-node-zip"
$path = "C:\AKSEdgeE\windowsNodeFiles.zip"
Start-BitsTransfer -Source $urlWindowsFiles -Destination $path
```
また、AKS Edge Essential Toolsもダウンロードしておきます。
```
# Download and expand AKS Edge Essential Tools
$urlTools = "https://github.com/Azure/AKS-Edge/archive/refs/heads/main.zip"
$path = "C:\AKSEdgeE"
Start-BitsTransfer -Source $urlTools -Destination $path
Expand-Archive -Path $path\main.zip -DestinationPath $path\main
```
インストールを実行します。Windows Node Filesはあらかじめ展開し、K8sのインストーラと同じフォルダに入れておきます。
```
msiexec.exe /i C:\AKSEdgeE\k8s.msi ADDLOCAL=CoreFeature,WindowsNodeFeature INSTALLDIR=C:\Programs\AksEdge VHDXDIR=C:\vhdx
```
AKSEdge PowerShellモジュールが使えるようことを確認します。
```
Set-ExecutionPolicy RemoteSigned
Import-Module AksEdge
Get-Command -Module AKSEdge | Format-Table Name, Version
```
2.　AKS Edge Host Featureを追加
```
Install-AksEdgeHostFeatures
```
ちなみにもし仮想環境で検証される場合は[Nested-Vierualization](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization)が必要です。

3.　AKS Edge EssentialsのKubernetes Clusterをデプロイ
構成ファイルを作成します。今回は単体マシン上にKubernetes Clusterを展開します。
```
# Create AKS Edge Config File
New-AksEdgeConfig -DeploymentType SingleMachineCluster -outFile C:\AKSEdgeE\aksedge-config.json | Out-Null
```
構成ファイルの情報を基にAKS Edge Essentialsをデプロイします。必要に応じて構成ファイルは編集してください。[参考](https://learn.microsoft.com/en-us/azure/aks/hybrid/aks-edge-deployment-config-json)。
```
New-AksEdgeDeployment -JsonConfigFilePath C:\AKSEdgeE\aksedge-config.json
```
※メモリサイズを最小にしていたら4596MB以上の空きメモリが必要だと怒られました。余裕を持って作成することが重要ですね。。。

5分くらいでデプロイが完了しました！

### まとめ

今回はAKS Edge Essentialのインストールまでをまとめました。なによりすごく手軽に導入できてしまうところが魅力ですね。次回はサンプルアプリケーションを動かしてみようと思います。
hostsファイル（Windows）について

# hostsファイルとは
※Windowsのhostsファイルについてのみ解説します。
OSの設定ファイルの一つで、IPアドレスとホスト名の対応を記述し、名前解決をするファイル。
（hostsファイルに設定した内容はDNSより優先される）

## hostsファイルの場所
hostsファイルは下記ディレクトリに存在する。
`C:\Windows\System32\drivers\etc`

## hostsファイルの編集方法
メモ帳を「管理者として実行」する。
画面下部に下記フォーマットで入力する。

`[IPアドレス]     [ホスト名]`
![hostsfile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1905379/59e316a2-9ec0-28cc-cca3-b23ea2538e10.png)

保存後、ブラウザから設定したホスト名でサイトが表示されるか確認する。
SQLServer VBAでリモート接続

```vb
Option Explicit


'Microsoft OLE DB Provider for SQL Server→ADOでSQLServerにアクセスするためのプロバイダー。
Private Const PROVIDER As String = "SQLOLEDB"

Private Const DATA_SOURCE As String = "192.168.0.1"   'サーバ名
Private Const DATABASE As String = "TEST_DB"         'データベース名

'SQL Server認証で接続する場合
Private Const USER_ID As String = "sa"        'ユーザID
Private Const PASSWORD As String = "hogehuga"       'ユーザパスワード

Sub sample()
    On Error GoTo ERR_HANDLER
    Dim strSQL As String
    Dim i As Long

    '--------------------------------
    ' データベース接続
    '--------------------------------
    Dim cn As New ADODB.Connection

'    'Windows認証で接続する場合
'    cn.connectionString = "Provider=" & PROVIDER _
'                        & ";Data Source=" & DATA_SOURCE _
'                        & ";Initial Catalog=" & DATABASE _
'                        & ";Trusted_Connection=Yes"
'    cn.Open


   'SQL Server認証で接続する場合
   cn.connectionString = "Provider=" & PROVIDER _
                       & ";Data Source=" & DATA_SOURCE _
                       & ";Initial Catalog=" & DATABASE _
                       & ";user id=" & USER_ID _
                       & ";password=" & PASSWORD
   
   Debug.Print (cn.connectionString)
   cn.Open

    '--------------------------------
    ' SQLの実行
    '--------------------------------
    Dim rs As New ADODB.Recordset
    strSQL = "SELECT * FROM dbo.test;"
    rs.Open strSQL, cn

    '取得データをセルに一括出力
    rs.MoveFirst
    ActiveSheet.Range("A1").CopyFromRecordset rs
    'データベース切断
    Call disconnectDB(cn, rs)

Exit Sub

ERR_HANDLER:

    'エラーメッセージ
    Debug.Print Err.Number & ")" & Err.Description
    'データベース切断
    Call disconnectDB(cn, rs)
    
End Sub
Sub disconnectDB(cn As ADODB.Connection, rs As ADODB.Recordset)
    'データベース切断
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then rs.Close
        Set rs = Nothing
        End If
    If Not cn Is Nothing Then
        If cn.State = adStateOpen Then cn.Close
        Set cn = Nothing
    End If

End Sub

```
【Laravel不思議エラー】ポリシーに違反していないのに403

# :warning: どういうパターン？
ユーザの権限などがあり、ルートモデルバインディングでバインドされたモデルにアクセスする権限があるかどうかを確認するポリシーが存在するとき、
ポリシーに違反していない(アクセス権限がある)はずなのに、403エラーが発生する、みたいなパターン。

## :white_check_mark: 解決方法
ルートモデルバインディングしているモデルを、例え使わないとしても受け取ってください。
```php
class StoreController extends Controller
{
    public function index(Store $store): View
    {
        return view('user.store.index');
    }
}
```

## サンプルコード

`/stores/{store}`には、ログイン中のユーザと店舗に関連が無いとアクセスできないようにポリシーを設定します。
```php
class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        Store::class => StorePolicy::class,
    ];
    
    // ...
}
```
```php
class StorePolicy
{
    use HandlesAuthorization;

    public function view(User $user, Store $store)
    {
        return $user->stores->where('id', $store->id)->isNotEmpty();
    }

    // ...
}
```
```php
Route::middleware(['can:view,store'])->group(function () {
    Route::get('/stores/{store}', StoreController::class . '@index')->name('stores.index');
}
```
このような場合に、とりあえずviewの表示だけしよう！などという考えでこのように書くと、403になってしまいます。
```php
class StoreController extends Controller
{
    public function index(): View
    {
        return view('user.store.index');
    }
}
```
勉強日記2023/4/18

統計検定2級過去問　2019年11月　18/35

【要復習】
・一致推定量と不偏推定量
・T統計量を利用した平均の差の検定
・一元配置分散分析

『現代数理統計学の基礎』

第5章　標本平均と標本分散の独立性
280blockerが原因で不意にシェアボタンが消えたときの対処法

ニッチすぎる内容だけどもハマったので備忘録として残します。

# 概要

メディアサイトのページを作成していて、SNSのシェアボタンを追加したときに、
自分のiPhoneでだけシェアボタンが表示されない現象がありました。

コンテンツブロッカーをオフにすると表示されたので自分のiPhoneに入れている280blockerが原因なのは分かったのですが、
同じページ内の別のシェアボタンは表示されてたのでどういう違いがあったのかを調べていました。

# 結論

結論から言うと、class名に`sns-list`があると非表示にするようでした。
これが不思議で、`.+sns-list.+`のように何かしら前後についているものは表示させる上に
`sns_list`や`snsList`も表示させ、`sns-list`のみが非表示の対象のようでした。
※他にも単語はあるかもですが。

また、id名に`sns-list`が入っていても非表示にはされませんでした。

# 回避方法

`sns-list`以外のclass名にすればOK。

280blockerがどういうものを弾くのかの仕様があるかを探していたんですが、
特に見つからず。
知っている方いましたら教えて下さい。