OmniAICreator/Qiita-1.07M huggingface dataset:
Sock Shopを複数のVMでたててみた

# Sock ShopのPodを複数VMに分散させる
今回はSock Shopを1つのVMで動かすのではなく，複数のVMで動かすのが目標です．

今回はRKE2でクラスターを構築しSock Shopをインストールしました．
RKE2クラスターはこちらを参考にしました↓

https://qiita.com/C0118272/items/a3d0e40cc92439407433

![名称未設定ファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747697/a6da99b3-3c90-9a00-7bf7-b1192388626e.png)

上図のようなクラスターを構築しました．Worker1と2にSock Shopをたてます．3には監視ソフトなどをインストールする予定です．

Worker1と2にSock ShopのPodがたてられて欲しいのですが，このままインストールしても思うようにはいきません．

なので`node`に`label`を付与し，Sock Shopのyamlファイルに追記をします．

`sock-shop`というラベルを付与しました．
~~~
kubectl label nodes <worker1> worker=sock-shop
~~~

yamlファイルには`nodeSelector:`を用いてラベルから`Pod`をたてる`node`を指定します．

~~~complete-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: carts
  labels:
    name: carts
  namespace: sock-shop
spec:
  replicas: 1
  selector:
    matchLabels:
      name: carts
  template:
    metadata:
      labels:
        name: carts
    spec:
      containers:
      - name: carts
      .
      .
      .
      volumes:
        - name: tmp-volume
          emptyDir:
            medium: Memory
      nodeSelector:
        worker: sock-shop
~~~

すべての`Deployment`に`nodeSelector:`を追記しインストールします．

~~~
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
carts-7fb7b76dc-j6mbd           1/1     Running   0          9d    10.42.3.108   worker2   <none>           <none>
carts-db-74ffbdb8c6-95jzt       1/1     Running   0          9d    10.42.3.110   worker2   <none>           <none>
catalogue-8b7bf47bd-ztr5h       1/1     Running   0          9d    10.42.3.109   worker2   <none>           <none>
catalogue-db-6d4b48d5d5-td62c   1/1     Running   0          9d    10.42.3.112   worker2   <none>           <none>
front-end-7d4c894c5c-tdp4d      1/1     Running   0          9d    10.42.1.69    worker1   <none>           <none>
orders-7786c965cc-mn4zp         1/1     Running   0          9d    10.42.3.111   worker2   <none>           <none>
orders-db-6c787d4bb8-x8lkg      1/1     Running   0          9d    10.42.1.70    worker1   <none>           <none>
payment-54f95cb795-xr4pq        1/1     Running   0          9d    10.42.3.113   worker2   <none>           <none>
queue-master-6988cd4ff6-r25p8   1/1     Running   0          9d    10.42.3.114   worker2   <none>           <none>
rabbitmq-857f4995c5-9nk4g       2/2     Running   0          9d    10.42.1.71    worker1   <none>           <none>
session-db-64746f5b79-k8nt8     1/1     Running   0          9d    10.42.3.115   worker2   <none>           <none>
shipping-7476449c85-28x8p       1/1     Running   0          9d    10.42.1.72    worker1   <none>           <none>
user-7f7454894f-2q8qn           1/1     Running   0          9d    10.42.3.116   worker2   <none>           <none>
user-db-7bf76cc8dc-2mtkc        1/1     Running   0          9d    10.42.3.117   worker2   <none>           <none>
~~~
無事Worker1と2にたてることができました！
このやり方だと`label`に対してランダムに振り分けているのでしょうか？`Pod`の分散させかたも考えて振り分けないといけなさそうですね．
空き容量の確認コード



```  
#include <stdio.h>
#include <sys/statvfs.h>

int main() {
    const char* path = "/home/user";
    struct statvfs stat;
    if (statvfs(path, &stat) == -1) {
        perror("Failed to get file system status");
        return 1;
    }
    double free_space = (double)stat.f_bsize * stat.f_bavail;
    printf("Free space: %lf bytes\n", free_space);
    return 0;
}



```
Laravel Vite で build フォルダを@viteディレクティブで読む方法

npm run build 等で、public/build配下のコンパイルしたjsおよびcssを読み込みたい場合はbuildだけ指定すればよい。
※resourcesの配下を指定する形と同じ記述で、普通にディレクトリ指定しようとすると、エラーになったので記載。
```
@vite('resources/css/app.css','build')
```
上記みたいな形で、配列に設定を足すとかでＯＫ。
【Python】パッケージの依存関係を確認

https://pypi.org/project/pipdeptree/

1. pipdeptreeをインストール
    ```
    pip install pipdeptree
    ```
1. インストール済みのライブラリすべての依存関係をJSON形式で出力
    ```
    pipdeptree --json > out.txt
    ```

PyTorchの依存関係だとこんな感じ
```json
    {
        "package": {
            "key": "torch",
            "package_name": "torch",
            "installed_version": "2.0.1+cu117"
        },
        "dependencies": [
            {
                "key": "filelock",
                "package_name": "filelock",
                "installed_version": "3.8.2",
                "required_version": null
            },
            {
                "key": "jinja2",
                "package_name": "Jinja2",
                "installed_version": "3.1.2",
                "required_version": null
            },
            {
                "key": "networkx",
                "package_name": "networkx",
                "installed_version": "3.0",
                "required_version": null
            },
            {
                "key": "sympy",
                "package_name": "sympy",
                "installed_version": "1.11.1",
                "required_version": null
            },
            {
                "key": "typing-extensions",
                "package_name": "typing-extensions",
                "installed_version": "4.4.0",
                "required_version": null
            }
        ]
    },
```

```json
    {
        "package": {
            "key": "torchaudio",
            "package_name": "torchaudio",
            "installed_version": "2.0.2+cu117"
        },
        "dependencies": [
            {
                "key": "torch",
                "package_name": "torch",
                "installed_version": "2.0.1+cu117",
                "required_version": "==2.0.1"
            }
        ]
    },
```

```json
    {
        "package": {
            "key": "torchvision",
            "package_name": "torchvision",
            "installed_version": "0.15.2+cu117"
        },
        "dependencies": [
            {
                "key": "numpy",
                "package_name": "numpy",
                "installed_version": "1.23.5",
                "required_version": null
            },
            {
                "key": "pillow",
                "package_name": "Pillow",
                "installed_version": "9.3.0",
                "required_version": ">=5.3.0,!=8.3.*"
            },
            {
                "key": "requests",
                "package_name": "requests",
                "installed_version": "2.28.1",
                "required_version": null
            },
            {
                "key": "torch",
                "package_name": "torch",
                "installed_version": "2.0.1+cu117",
                "required_version": "==2.0.1"
            }
        ]
    },
```
ファイル名の先頭に簡単に日付を入れる方法　アイコンにドラッグするだけ

ファイルをスクリプトのアイコンにドラッグしてファイル名を変換する方法

以下に、PowerShellスクリプトを変更して、ファイルをドラッグ＆ドロップで変換できるようにする手順を示します。

1. テキストエディタで以下のスクリプトを開きます。

```powershell
param (
    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
    [Alias("FullName")]
    [String[]]$Path
)

$prefix = Get-Date -Format "yyMMdd"

foreach ($file in $Path) {
    $directory = Split-Path -Path $file -Parent
    $filename = Split-Path -Path $file -Leaf
    $newName = $prefix + "_" + $filename
    $newPath = Join-Path -Path $directory -ChildPath $newName
    Rename-Item -Path $file -NewName $newName
}
```

2. スクリプトを「drag_drop_rename.ps1」という名前で保存します（拡張子が「.ps1」であることを確認）。

3. スクリプトを実行可能にするために、PowerShellを開き、次のコマンドを実行します。

```powershell
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
```

4. スクリプトをドラッグ＆ドロップで実行できるようにするため、バッチファイル（拡張子「.bat」または「.cmd」）を作成します。テキストエディタを開き、以下のコードを貼り付けます。

```batch
@echo off
PowerShell.exe -ExecutionPolicy Bypass -File "C:\path\to\drag_drop_rename.ps1" %*
pause
```

5. バッチファイルを保存し、任意の場所に配置します。

6. ファイルをスクリプトのバッチファイルにドラッグ＆ドロップすると、ファイル名が自動的に日付形式で変更されます。

上記の手順を実行すると、スクリプトのバッチファイルにファイルをドラッグ＆ドロップするだけで、ファイル名が自動的に変換されます。バッチファイルが表示されると、処理が完了するまで一時停止します。必要に応じて、`pause`コマンドを削除することもできます。

なお、スクリプトのバッチファイルのパスを適切に設定することを忘れずにしてください。また、セキュリティ上の理由から、PowerShellの実行ポリシーを変更する場合は注意してください。
ハッカソンってなにかと良いことづくめなのでは？

先日、ハッカソンイベントにスポンサーとして参加した際に
ハッカソンの魅力に気づいてしまったので記事にさせていただきました。


# ハッカソンってなんぞや？

![スクリーンショット 2023-07-10 7.11.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280001/a747a6b6-31ce-466d-4645-38871981ccd8.png)

ハッカソン（Hackathon）は、
"**Hack**"（プログラミングをする）と 
"**Marathon**"（マラソン）を組み合わせた言葉で、
決められた一定の時間内で参加者がチームを組んで
特定の課題やテーマに基づき開発し、その結果を競い合うイベントのことを指します。

#### ハッカソンの歴史を簡単に

ハッカソン発祥の地はアメリカで、
1990年代後半にオープンソースコミュニティや特定のソフトウェア開発者たちが集まり、
一緒に新しいソフトウェアを開発したり、
特定の技術的問題を解決したりするためのイベントが開催されるようになったことから始まります。

日本でハッカソン文化が広がったのは2010年代初頭からで
スマートフォンやクラウド技術の普及、スタートアップ文化の浸透に伴い、
イノベーションや創造性を重視する風潮が強まり、
その結果としてハッカソンが一般的になりました。


# 参加するメリット

#### スキルアップ

メリットとして挙がるのは
やはり「**スキルアップ**」なんじゃないかと思います。

ハッカソンでなくとも、
自分でインプットすればそれはそれでスキルアップにつながると思いますが、
技術選定からプロトタイプ作成まで限られた時間内で行う為、
強制的に頭をフル回転させないといけない環境下に置かれます。。。。
より実践的なスキルが身につくこと間違いないでしょう！!!

今回参加させていただいたハッカソンは
テーマが「**ChatGPTを活用したプロダクト**」
「**Webサービスでもモバイルアプリケーションでもなんでも良い**」という条件でしたが
参加している方々の多くは頭が爆発しそうだけど楽しいって言っていましたw

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280001/d68245b1-dc34-43da-1214-1b85ae2d1ae8.png)


#### 新しい出会い（色々なバックグラウンドを持つ人と出会える）

ハッカソンは、チームで行うことが多いので、
他の参加者と協力して開発していくになると思います。
いつも違うコミュニティに属する人と話すだけでも良い刺激になりますし、
同じ目的に対して、取り組んでいると自然と距離感が縮まっていきますし、
開発合間の休憩時間でプライベートな話までできるようになれば、
生涯の友に出会える可能性だってあります！

実際、ハッカソンで出会った人同士で、
ハッカソンが終わった後に一緒に開発したり起業しようとしていたり、
なにか青春っぽい出会いを感じました。
（個人的にそういうのめっちゃ好き。）

![279154.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280001/6cb24ad0-6f52-78f5-59bc-a38060aec355.jpeg)


#### 旅行気分で賞金、景品がもらえちゃうかも

オフラインでのハッカソンに限ってしまいますが、
開催場所によっては、観光名所を巡ったり、
その土地の名産品や名物を食べたりと
メインは開発ではありますが、旅行気分を味わえるかもしれません！
（もしかしたらそんな時間がないかもしれません！なかったらすみません！）

あとは、出来によっては賞金・景品がもらえることもメリットですよね。
旅行気分を味わいながら、賞金・景品を貰えるなんで良いことしかないですね！！

今回参加したハッカソンでは最優秀賞が10万円＋副賞でした！！！

![スクリーンショット 2023-07-10 8.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3280001/969d9df2-47e9-f7de-75d3-d03c1829fdf9.png)

# 運営やスポンサーをするメリット

#### 運営メンバーにも良い刺激

運営メンバーにとっても、
いつも違うコミュニティに属する人と話す機会は非常に良い刺激になります。
（私もめちゃめちゃ刺激をもらいました）

エンジニアや同年代の人達がどういうことに興味を持って、
何を考えているのか聞くだけでも
自分に活かせることがたくさんありました。

#### 宣伝やブランディング、採用や次なるイベントに繋がるかも！

ハッカソンを通して、企業認知度アップに繋がりますし、
興味をもってくださった学生や社会人の方からインターンに参加したいです！
どのような事業を行なっているのか詳しく聞きたいです！
と聞かれることが多々あり、採用に繋がる可能性を感じました！

また、異なる会社やコミュニティ同士であっても、
今度一緒にイベントやりませんかなんて話もちらほらあり、
次なるイベントに繋がる可能性を大いに感じました！


# まとめ

ハッカソンは色々な意味で刺激をもらえるので良いことづくめなのではと思います！
普段、何か自分でアイデアを考えていてもアウトプットする機会を作れてない方、
いつもとは違う刺激を求めている方、若干勢いでもよいと思うので、
ハッカソンに申し込んでみてください！
C#のコンストラクタは完全コンストラクタパターンを検討しよう

コンストラクタとは，インスタンスが生成されるときに
一番最初に動作する部分の事です。

例えばMeasureValueというクラスを作成し
コンストラクタを作成するとこのようになります。

```
public class MeasureValue
{
    public MeasureValue()
    {

    }
}
```

publicの後にクラス名をかかれたものは
コンストラクタになります。


外部からはこのように呼び出されます。

```
MeasureValue measureValue = new MeasureValue();
```

newを実行したときに引数無しのコンストラクタが起動し
その中に今回は何も書いていないので，特に何も起こりませんが
ブレイクポイントなどを置くとちゃんと通っていることが
確認できると思います。

ではこのコンストラクタ，いったい何のために必要なのでしょうか？

それは，インスタンスを生成するときに
クラスの変数などの初期化などが行えます。

例えばMeasureValueクラスに変数を追加します。

```
public class MeasureValue
{
    private int _value;
    public MeasureValue()
    {
        _value = 1;
    }
}
```

intの変数の_valueを追加し，コンストラクタで1を設定しました。
これでインスタンスが生成されるときに_valueに1が入ります。

「そんなのprivate int _value = 1;　って書けばいいじゃん！」

ごもっともです。
次のように書いても同じ意味になります。

```
public class MeasureValue
{
    private int _value = 1;
    public MeasureValue()
    {
        _value = 1;
    }
}
```

だた，次のようなパターンではコンストラクタが
強力な意味を持ちます。

```
public class MeasureValue
{
    private int _value;
    public MeasureValue(int value)
    {
        _value = value;
    }
}

private void button7_Click(object sender, EventArgs e)
{
    MeasureValue measureValue = new MeasureValue(2);
}
```

この例ではコンストラクタにintの引数を持ち
_valueに代入しています。

これで，呼び出し元が値を自由に設定できるようになります。

さらにprivate int _value;をreadonlyにすることで
明示的にコンストラクタでの変更しかできない
変数を作ることができます。

```
public class MeasureValue
{
    private readonly int _value;
    public MeasureValue(int value)
    {
        _value = value;
    }
}
```

こういったコンストラクタで内部変数の値がすべて決まり，
その後一切変更できない実装を「完全コンストラクタパターン」といいます。

このように実装すると，インスタンスが生成されてから
一切値が変わらないので，可読性や保守性の高い
より良いコードとなります。
ファサードとは

# Laravel Facade(ファサード)とは


## ファサード作成

### 1 ファサードに登録したい処理（クラス)を作成
ディレクトリーはどこに作成するといったルールもなく、特に指定なし。


```
<?php
namespace App\Reffects;
class MyName
{
    public function run()
    {
        return 'Myname is yuki fujimoto';
    }
}
```

### 2 サービスプロバイダーに登録
App\Providers\AppServiceProvider
```
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
         //ここ↓
        $this->app->bind('MyName', \App\Reffects\MyName::class);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

```

### ３　ファサード作成
Illuminate\Support\Facades\
ファサードを作成するコマンドはなく、自分で手動で作成して下さい。
ファサードではサービスプロバイダーに登録した名前で呼び出す=処理クラスを呼び出すだけ
```
<?php

namespace Illuminate\Support\Facades;

class Own extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'MyName';
    }
}
```

### 4 呼び出す
どこの階層でも自由に呼び出し使用することができます。
ただし、必ずuse で呼び出して下さい。
```
use Illuminate\Support\Facades\Own;
Route::get('/', function () {
    dd(Own::run());
    return view('owner.welcome');
});
```


これで自由に自作ファサードを呼び出し、作成することができるようになりました。
##### さらにuse文をなくす方法をご紹介します。

/config/app.phpのaliases配列に自作ファサードの設定を追記します。

```
 'aliases' => Facade::defaultAliases()->merge([
        //ここ↓
        'Own' => Illuminate\Support\Facades\Own::class,  //これを追加
    ])->toArray(),
```

これでuse文が必要なく、呼び出すことができるようになりました。
Rails 別のユーザーの投稿を消せてしまった件

# はじめに
- 製作したSNSサイトで、urlの直打ちをすると、他人の投稿編集画面に潜入できてしまった
- その対策をとった、学習したことの備忘録

# 修正前
```ruby:posts_controller.rb
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update]

# 省略

def edit
end

def update
    if @post.update(post_params)
      flash[:dark] = "あなたの投稿を更新しました!!"
      redirect_to post_path(@post.id)
    else
      flash[:danger] = "更新に失敗しました。"
      redirect_to edit_post_path(@post.id)
    end
end

def destroy
    @post.destroy
    flash[:dark] = "あなたの投稿を削除しました"
    redirect_to user_path(current_user.id)
end

private

def post_params
    params.require(:post).permit(:post_image, :explanation)
end

def set_post
    @post = Post.find(params[:id])
end

```
このままでは、editもupdateもdestroyも、「before_action :authenticate_user!」によって、ログイン認証されたユーザーであれば可能になってしまう。
>補足
authenticate_user!
・deviseのメソッド
・ユーザーがログインしているかどうかを確認
・ログインしていない場合はログインページにリダイレクト

# 修正後
```ruby:posts_controller.rb
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update]
# 追記
before_action :ensure_correct_user, only: [:edit, :update, :destroy]

# 省略

private

# 省略

# 追記
def ensure_correct_user
    @post = Post.find(params[:id])
    unless @post.user_id == current_user.id
      flash[:danger] = "この投稿への編集権限はありません。"
      redirect_to posts_path
    end
end
```

上記のように、privateに「ensure_correct_user」メソッドを定義。直訳すると、「正しいユーザーを確保する」なので、可読性としても申し分ないと思われる。
ここでは、
```ruby
unless @post.user_id == current_user.id
```
によって、投稿のuser_idと現在のユーザーのidが一致しなければ投稿一覧へリダイレクトするように設定。

![スクリーンショット 2023-07-09 18.36.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348867/721ca619-0874-71a7-34d2-bbc4d5c6ea89.png)

これで、仮に、悪意あるユーザーが「url直打ちで消してやる〜」なんぞ思っても大丈夫。
気づいてよかった。

# まとめ
- 脆弱性があると、urlで不正なアクセスがなされてしまう
- before_actionなどで、不正アクセス対策を忘れずに

⚠️学習4ヶ月目の初学者による投稿です。
⚠️間違いがあるかもしれません。ご容赦ください。
⚠️ご指導、ご教授いただけると幸いです。
ChromeでWeb Speechの音声設定(getVoices()のバグ)でハマったのでメモ

# 初めに
Chrome標準の`lang = 'en-US'`の音声が聞き取り辛いため音声を変更しようと`SpeechSynthesis.getVoices()`で利用可能な音声を取得しようとして取得できない不具合にハマった。

# 不具合挙動
1回目の呼び出しの時だけデフォルトの音声で再生される。

# 不具合の理由
Chromeには1回目の`SpeechSynthesis.getVoices()`の返値が空になる不具合が存在する。

https://bugs.chromium.org/p/chromium/issues/detail?id=586819

# 不具合回避方法
`SpeechSynthesis.getVoices()`を予め呼び出しておき、必要な場所での呼び出しが2回目以降となるようにする。

# 不具合に言及している参照先
https://www.codegrid.net/articles/2016-web-speech-api-1/

https://moewe-net.com/js/web-speech-api-speech

https://qiita.com/7shi/items/43452dcd34e57100fc3c
Salesforce入力規則、１つの項目に1つ作成するか？１つの項目に複数作成するか？

こんにちは
本橋孝昭です


今回はSalesforceの入力規則で1つの項目に１つ作成するか。複数作成するか　について解説します


## 前提
Salesforceでは１つの項目に複数の入力規則を作成することができます

例としてSalesforceには商談オブジェクトというものがあり、
フェーズ（StageName）と金額（Ammount）項目がありますね

この際、フェーズ（StageName）に入力規則を作成しることにより
金額が空欄の場合フェーズを
Closed Won
または
Closed Lost
に設定できない
という入力規則を作成したとします

その場合、入力規則は

AND(
ISBLANK( Amount ),
OR(
ISPICKVAL( StageName ,"Closed Won"),
ISPICKVAL(StageName ,"Closed Lost")))

のように１つの入力規則で作成することも可能です

![入力規則１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/89fab758-e8e5-8909-4db3-208af1255f18.png)



また、
AND(
ISBLANK( Amount ),
ISPICKVAL( StageName ,"Closed Won"))
と
AND(
ISBLANK( Amount ),
ISPICKVAL( StageName ,"Closed Lost"))
と二個入力規則を作成することでも対応可能です

![入力規則２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/45327c93-0ee5-786a-0755-a92324bc05ee.png)

では、入力規則を１つ作成するか複数するか迷った場合、どのように考えればいいのかまとめました


## 入力規則を１つ作成したほうがいい場合

### 1 オブジェクトごとに作成できる入力規則の数に限界がきそうな場合

オブジェクトごとに作成できる入力規則の数には限界があります

※詳細
有効な入力規則の上限数を増やす
https://help.salesforce.com/s/articleView?id=000383591&type=1

そのため、オブジェクトごとに作成できる入力規則の数が気になる方はなるべく入力規則を１つ作成（少なく作成。入力規則をまとめる）ほうがいいですね



## 入力規則を複数作成したほうがいい場合

### 1 　エラーメッセージを細かく出し分けたい場合
入力規則のエラーメッセージは１つの入力規則に設定できるのは１つの文章のみです

例えばさきほどの

金額が空欄の場合フェーズを
Closed Won
または
Closed Lost
に設定できない

の場合

・入力規則１つなら入力規則のエラーメッセージも
「	フェーズはClosed WonとClosed　Lostの場合、金額を必ず入力してください」のような文章しか作成できない

・入力規則２つなら入力規則のエラーメッセージも
「Closed Wonは必ず金額入力をしてください」と
「Closed Lostは必ず金額入力をしてください」の２つに分けて作成できる

ということが可能です

### ２ 　入力規則の数式を簡単にした。数式のメンテナンスを容易したい場合

数式の文字数は限界があります
数式項目の作成
https://help.salesforce.com/s/articleView?id=sf.customize_formulas.htm&type=5

また、１つの入力規則で頑張ろうとすえるとおのずと数式が増えてしますのでメンテナンスが難しくなります

そのため、入力規則の数式を簡単にした。数式のメンテナンスを容易したい場合　は複数の入力規則を作成することをおすすめします


いかがでしょうか

他にも
Salesforce入力規則、１つの項目に1つ作成するか？１つの項目に複数作成するか？
で「こんなとらえ方、考え方もあるよ」という話もありましたら、ぜひ教えてください。
TypeScirpt サーバーレスフレームワークのSkeetにNext.js (React) スターターを追加しました

![NewReleaseSkeetxNextjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/65a9c6ae-dea5-1498-7f84-aa32f930e962.png)


こんにちは！kishi.solです。普段はオランダのアムステルダムにて、ELSOUL LABO B.V.というソフトウェア研究所から、Skeet等のオープンソース開発をやっていたり、Epics DAOというオープンソース開発をエンパワーメントする取り組みをしていたり、Solana Labs等ブロックチェーン関係のリポジトリにコミットしていたりします。

この度は、リクエストの多かった Vercel 社の Next.js スターターを Skeet フレームワークに追加いたしました。これにより、さらに高速な Web アプリ開発環境を手に入れることができます。

## Skeet Next.js (React) スターター

![WebAppBoilerplate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/c92c95b5-547d-6dc0-841f-2801e83f44e9.png)


Skeet は Firebase 上に自動スケールするアプリを構築できる TypeScript 製のフルスタックサーバーレスフレームワークです。

Skeet は素早くアプリを立ち上げ、少ないコストで長期的にメンテナンスしていくことを可能にします。

Next.js スターターは、SSG(スタティックサイトジェネレート) という技術を採用し、強い SEO 対応と高い性能、ホスティングコストの削減を実現しています。

他にも多言語対応や PWA(アプリをダウンロードして利用可能)など、Web 開発に欠かせない設定はすでに完了しており、開発環境の準備に時間をかけず、すぐにあなたのアプリケーションコードに集中できます。

Skeet Next (GitHub): https://github.com/elsoul/skeet-next

## 新しいAIチャットアプリデモ (made by Next.js)

![CreateChatRoom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/37a9f722-0292-09aa-a3f3-23899803de12.png)


同時にこの Next.js スターターと ChatGPT API を用いて新しい AI チャットアプリのデモをリリースしました。

このデモアプリは、skeet create コマンドを実行すると、どのようなアプリが構築されるのかを説明しています。

OpenAI は 7 月 7 日(米国時間)、同社の自然言語モデル「GPT-4」の API をすべての ChatGPT Plus ユーザーが利用可能になったことを発表しましたが、このデモアプリでも「GPT-4」の利用が可能です。

AI アシスタントのキャラ設定をすることで、返答の質を向上させることも可能です。


![ChatWithCodeHighlight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/bbfc0439-5668-21d5-027b-c315cd7804dd.png)


ChatGPT は開発者にとって頼れる味方となっています。

今回のデモはプログラムコードのシンタックスハイライト(ルールに沿って色がつくため読みやすくなります)にも対応しており、トークン数等をカスタマイズすることでより精度の高い回答を得ることができます。

Skeet AI チャットアプリデモ: https://skeeter.dev/


## 新しいアプリ開発を体感してください

![EffortlessServerlessSkeet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/fb0d29ed-b679-48b6-6df7-e5f272275dec.png)


Skeet を使えば、すぐに iOS・Android・Web アプリを開発し公開できます。

チュートリアルでは、実際に あなたのオリジナル AI チャットアプリを構築し、すぐにリリースすることができます。

ぜひお試しいただけると嬉しいです。

Skeet チュートリアル (ドキュメント): https://skeet.dev/ja/doc/backend/quickstart/

Skeet チュートリアル (YouTube): https://www.youtube.com/watch?v=6em68qcSsJE
VS Code で Logic Apps Standard ワークフローを作成する

[Visual Studio Code を使って Standard ワークフローを作成する - Azure Logic Apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/logic-apps/create-single-tenant-workflows-visual-studio-code) の補足メモ。

## 必要物

[Visual Studio Code - Code Editing. Redefined](https://code.visualstudio.com/)
- 拡張
    - [C# - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp)
    - [Azure Account - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account)
    - [Azure Logic Apps (Standard) - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurelogicapps)

[Azure Functions Core Tools をダウンロード](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=windows%2Cportal%2Cv2%2Cbash&pivots=programming-language-csharp#install-the-azure-functions-core-tools)
[.NET 6.0 (Linux、macOS、Windows) をダウンロード](https://dotnet.microsoft.com/ja-jp/download/dotnet/6.0)

## デザイナーを開く

- Open Designer 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/c15d4a25-79e2-4fa2-0abc-0223932c5f88.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/cd745690-fb64-45b4-71c4-d8993c289115.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/632b56ff-7565-a5b5-eb8d-a4fad8e15946.png)


## デプロイする

- Deploy

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/906773d9-1e9d-62b5-84a1-182bec57b3a1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/c96cbfdd-38f6-b191-2b02-21ccda50667b.png)


## 参考
[Azure Logic Apps (Preview) を Visual Studio Codeで作成するための手順 - MoreBeerMorePower](https://mofumofupower.hatenablog.com/entry/2020/09/23/222908)

Happy delivering!
Leetcode 226. Invert Binary Tree

# Problem
Binary treeを左右反転させるという問題です。
> Given the root of a binary tree, invert the tree, and return its root.

InputとOutputの例は次になります。
```
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]
```
![image](https://assets.leetcode.com/uploads/2021/03/14/invert1-tree.jpg)

https://leetcode.com/problems/invert-binary-tree/description/


## Key Idea
再帰を使う方法と使わない方法の２通りを考えます。

## Approach #1 Recursive (Depth First Search)

再帰を使う方法では、深さ優先探索（DFS）が用いられます。深さ優先探索は、まず一つの経路を最深部まで探索し、それが終わったら次の経路を探索する方法です。

```python
class Solution:
    def invertTree(self, root):
        if root is None:
            return None

        
        tmp = root.left
        root.left = root.right
        root.right = tmp
        # root.left, root.right = root.right, root.left でも可

        self.invertTree(root.left)
        self.invertTree(root.right)

        return root
```

## Approach #2 Iterative (Breadth-First Search)
幅優先探索（BFS）の考え方で、Queueを使って解くこともできます。

```Python
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return None
        
        queue = collections.deque([root])
        while queue:
            current = queue.popleft()

            tmp = current.left
            current.left = current.right
            current.right = tmp
            # current.left, current.right = current.right, current.left でも可

            if current.left:
                queue.append(current.left)
            
            if current.right:
                queue.append(current.right)
        
        return root
```

## Complexity
Time complexityはO(n)です（nはノードの数）。どちらの解法とも、各ノードを一度ずつ訪れるからです。

Space complexity については、少し違いがあります。
再帰の場合は、再帰呼び出しによるスタックの深さに依存します。最悪の場合（つまり、すべてのノードが1本の線上に並んだような場合）、スタックの深さはO(n)となります。しかし、完全二分木の場合、スタックの深さはO(log n)となります。

一方、キューを使用する場合は、キューに格納されるノードの最大数に依存します。幅優先探索（BFS）では、一度に最大で全てのリーフノードがキューに格納される可能性があります。したがって、最悪の場合（つまり、最も広いレベルがリーフノードで占められている場合）、空間複雑度はO(n)となります。

したがって、平均的な場合には再帰の方が空間効率がよい可能性がありますが、最悪の場合にはスタックオーバーフローを考慮するとキューを使用した方が安全であると言えます

## Reference

https://www.youtube.com/watch?v=OnSn2XEQ4MY

https://www.youtube.com/watch?v=qFIsuQnDS_g
Leetcode 141. Linked List Cycle

# Problem
Linkedlistが与えられた時に、循環があるかを判断する問題になります。
> Given head, the head of a linked list, determine if the linked list has a cycle in it.

InputとOutputの例は次になります。
```
Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).
```

![image info](https://assets.leetcode.com/uploads/2018/12/07/circularlinkedlist.png)

https://leetcode.com/problems/linked-list-cycle/description/


## Approach #1 : Hash Table
リストが循環しているかどうかを検出するには、ノードが以前に訪れたことがあるかどうかをチェックすればよいです。自然な方法は、Hash Table (PythonではSet)を使うことで実装できます。ここで、ポイントとなるのは、Hash Tableに入れていく値はノードの参照(メモリアドレス) だということです。

```python
class Solution:
    def hasCycle(self, head):
        nodes_seen = set()
        while head is not None:
            if head in nodes_seen:
                return True
            else:
                nodes_seen.add(head)
            head = head.next
        return False

```

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。ここで、nはLinked Listの要素数です。各ノードは最大で一度だけ訪問されます。ハッシュセットの挿入と検索は平均的にO(1)時間であるため、全体の時間計算量はO(n)となります。
- Space complexity: O(n)。リストの各ノードをハッシュテーブルに保存する必要があるためです。リストにn個のノードがある場合、ハッシュテーブルは最大でn個のノードを保存します。

## Approach #2 : Floyd's cycle-finding algorithm
Space complexityをさらに効率化できる方法があります。フロイドの循環検出アルゴリズム(Floyd's cycle-finding algorithm)を利用します。
この手法は以下のように機能します：
1. リストの先頭から開始して、遅いポインタと速いポインタを設置します。遅いポインタは各ステップで1つのノードを進み、速いポインタは2つのノードを進みます。
2. もしリストにサイクルが存在しなければ、速いポインタはいずれnull（リストの終端）に達します。
3. 一方、リストにサイクルが存在する場合、速いポインタ（2つのノードを一度に進むため）は遅いポインタを追い越し、両者はいずれ同じノードで出会うことになります。

```python 
class Solution:
    def hasCycle(self, head):
        if head is None:
            return False

        slow = head  # slow pointer
        fast = head  # fast pointer

        while fast is not None and fast.next is not None:
            slow = slow.next  # move slow pointer one step
            fast = fast.next.next  # move fast pointer two steps

            # If there is a cycle, the fast and slow pointer will meet at some node
            if slow == fast:
                return True

        # If the fast pointer reached the end of the list, there is no cycle
        return False
```

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。Fast Pointerは、最悪の場合でもn回でSlow pointerに追いつきます。
- Space complexity: O(1)。2つのポインタのみが利用され、追加の空間をほとんど必要としません。


## Reference
https://note.com/rhayahi/n/n7fc11c09fec6
https://www.youtube.com/watch?v=gBTe7lFR3vc
Leetcode 206. Reverse Linked List

# Problem
Linkedlistを反転させるという問題です。
> Given the head of a singly linked list, reverse the list, and return the reversed list.


InputとOutputの例は次になります。
```
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
```
https://leetcode.com/problems/reverse-linked-list/description/

## Key Idea
Pointerを使ったIterativeな方法とRecursiveな方法があります。

## Approach #1 : Iterative (Two Pointers)

Linked List の反転は、次のノードへの参照(next_temp)を保存してから、現在のノード(curr)の次のノードへの参照を更新し、前のノード(prev)を現在のノードに、現在のノードを次に保存したノードに更新するという一連のステップを繰り返すことで行います。

```python
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev = None
        curr = head
        while curr:
            next_temp = curr.next
            curr.next = prev
            prev = curr
            curr = next_temp
            
        return prev
```
head = [1,2,3]とした場合の、挙動のイメージはこちらになります。
![IMG_9095.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99549/2a7abcc8-1800-31da-3bf9-389b6af049d1.jpeg)


この解法では、計算量は下記の様になります。

- Time complexity: O(n)。LinkedListを一回走査します。

- Space complexity: O(n)。ポインタしか使っていません。

## Approach #2 : Recursive
Follow Up Questionとして、再帰で解くよう指定されています。
head.next（headの次の要素から始まる部分リスト）を再帰的に反転させます。
ここで、newHeadというポインタを用意し、常に反転リストの最初の要素を指しています。
```python
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if not head:
            return None

        newHead = head
        if head.next:
            # head を反転させた部分リストの末尾に追加
            newHead = self.reverseList(head.next)
            head.next.next = head
        
        head.next = None

        # newHead は常に反転させた部分リストの先頭（元々のリストの末尾）を指す
        return newHead
```

![IMG_9096.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99549/5dbef7ef-985d-14df-3bdf-94599068e120.jpeg)

![IMG_9097.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99549/2bfa5621-cf55-3d04-2681-7d7a08135d00.jpeg)

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。LinkedListを一回走査します。

- Space complexity: O(n)。再帰的な解法では、リンクリストのノード数に応じたスタックフレームが生成されます。これは、再帰が深いレベルに達すると、そのレベルに応じてスタックフレームが確保され、それぞれの再帰ステップで状態が保存されるからです。

## Reference
https://www.youtube.com/watch?v=G0_I-ZF0S38&t=218s
2023/7/10主にITとかセキュリティの記事

スラッシュの有無だけでセキュリティにとんでもない大穴が空いてしまうNginxのありがちな設定ミスについて実例を踏まえて専門家が解説(7/8)
https://gigazine.net/news/20230708-nginx-alias-traversal/

太陽光発電測定システム「SolarView」の多くが脆弱な状態で運用されている(7/8)
https://news.mynavi.jp/techplus/article/20230708-2722313/
https://gunosy.com/articles/ebndE

Androidのアップデートを、Googleが2023年7月セキュリティパッチ公開(7/7)
https://gunosy.com/articles/etKKx

南海電鉄のシェアオフィス、会員の個人情報漏洩の恐れ(7/7)
https://www.nikkei.com/article/DGXZQOUF07CLA0X00C23A7000000/

南海電鉄に不正アクセス(7/7)
https://sp.m.jiji.com/article/show/2975654

名古屋港にコクヨ、エーザイ…相次ぐランサムウエア感染　被害防止には「早期発見」(7/7)
https://news.yahoo.co.jp/articles/5e4b02e10a86601da41bc82d6561331ef1073ace

名古屋港のシステム障害が復旧…コンテナ搬出入は午後にも再開へ(7/6)
https://news.infoseek.co.jp/article/20230706_yol_oyt1t50125/

Cohesity、データセキュリティに関する調査を実施 92％超が2023年にランサムウェア脅威の高まりを実感(7/8)
https://news.mynavi.jp/techplus/article/20230708-2722865/

内部関係者による海外VPNサービスを悪用した不正アクセスについてまとめてみた(7/7)
https://piyolog.hatenadiary.jp/entry/2023/07/07/015246

サポート詐欺の相談件数は2022年で過去最高に。「感染しています」と警告画面が出ても連絡しないで(7/7)
https://internet.watch.impress.co.jp/docs/column/dlis/1514382.html

【10分で確認】AWSでやりがちなセキュリティ脆弱性を生み出すアンチパターン集（随時追加・更新）(7/8)
https://qiita.com/WebEngrChild/items/7a91783c9172fadf3533

ツイッターに代わるSNS「スレッズ」に登録すると「連絡先・食べた物・行動歴・閲覧サイト・支払い・健康情報」まで筒抜けに！(7/8)
https://news.nicovideo.jp/watch/nw12941040

クロスチェーンプロトコル「Multichain」、ハッキングで約1.25億ドルの資金流出(7/8)
https://www.neweconomy.jp/posts/324559

元同僚のチャット改ざんか　不正アクセス疑い男逮捕(7/6)
https://nordot.app/1049516424129069808

ビットフィネックス（Bitfinex）が2016年のハッキングから報酬を受け取る(7/7)
https://nextmoney.jp/?p=59625

中小企業の情報システム担当者1,000名に聞いた！「『クラウドサービスのセキュリティ対策』実態調査」を発表(7/9)
https://www.jiji.com/jc/article?k=000000164.000010736&g=prt

Microsoft 365とは？特徴やサービスの詳細を解説(7/7)
https://digital-shift.jp/flash_news/s_230707_3

スマホが危ない!? SIMスワップ詐欺とは？ どんなことを注意すればいい？(7/8)
https://news.yahoo.co.jp/articles/31197c532db9a474f30f3727b2bbc75189325515

注意！見知らぬ代引き便　通販サイト介し、記者の元にも…　長崎で相談増「受け取り拒否を」(7/6)
https://nordot.app/1049494401069859823

国際決済銀行、CBDCに対するDeFiリスクへの対処を勧告(7/8)
https://coinpost.jp/?p=471693

能動的サイバー防御で法改正＝政府検討、「通信の秘密」整合性焦点(7/6)
https://www.risktaisaku.com/articles/-/80968

日本とEUの首脳協議で安保協力拡大の声明発出で調整 政府(7/8)
https://www3.nhk.or.jp/news/html/20230708/k10014122511000.html

【マイナ問題続出】検査を機に仕切り直せ（７月８日）
https://news.yahoo.co.jp/articles/0c5942d6db7ac213366dd5093d081c328a40d12d

相次ぐ“マイナトラブル”受け…デジタル庁に立ち入り検査へ(7/7)
https://news.tv-asahi.co.jp/news_economy/articles/000306430.html

マイナンバー保険証で支持率下落は不可避。焦る岸田が目論む“トカゲの尻尾切り”(7/7)
https://www.mag2.com/p/news/579872

中国テック事情：深センで実際に体験したドローン配達のリアル(7/8)
https://ascii.jp/elem/000/004/144/4144477/?rss

生成ＡＩと教育(7/8)
https://www.the-miyanichi.co.jp/shasetsu/_72206.html

「発達段階、十分考慮を」小中高校の生成AI利用、文科省が暫定指針(7/7)
https://news.mynavi.jp/techplus/article/20230707-2722616/

再エネ業務管理システムの閲覧による個人情報漏えい、資源エネルギー庁と一般送配電事業者、小売電気事業者を行政指導(7/7)
https://scan.netsecurity.ne.jp/article/2023/07/07/49643.html

北朝鮮の大学生が米IT企業開催のハッキング大会で優勝(7/8)
https://news.goo.ne.jp/article/tbs/world/tbs-6096199.html
https://news.yahoo.co.jp/articles/33f94f36d8a80b971d63f4c235390e899520b3eb
[java] Spinrg Boot JPAでクエリ文を使用する方法

# はじめに
Spring BootでJPAを用いたとき、違和感を感じるほど簡単に条件を絞ることができる。
例えば特定のidを持つdataをtableから取得するためには
クエリ文なら、`select * from table where id = 1 ` と表記するが、
JPAで、`findById(1)`
などと表記する。
しかし、こういったわかりやすい表記を用いることで、かえってより細かい条件まで絞ることに限界が生じてしまう。
よってそれを解決するために、クエリ文を用いて条件を絞ることを少しまとめる。

# Code

## Entity
```java:Entity.Account
@Entity
@Data
@Table(name = "accounts")
public class Account {
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	
	private  String name;
	
	@Column(name = "login_id")
	private String loginId;
	
	@Column(name = "login_pw")
	private String loginPw;
	
	@Column(name = "is_admin")
	private Boolean isAdmin = false;
	
}
```
## Repositry
```java:AccountRepository
public interface AccountRepository extends JpaRepository<Account, Integer>  {
	
	@Query("select a from Account a")
	List<Account> findByidQuery();
	
	@Query("select a from Account a where a.id = ?1")
	Account findByidQueryOne(Integer id);
	
	@Query("select a from Account a where a.isAdmin = false ")
	List<Account> findByidQueryNotAdmin();
}
```
注意しないといけないのは、クエリ文だからSQLと全く同じようなTable名、Column名を使用してはいけない。
SQLでのColumn名は`is_admin`であるが、JPAで利用するためにはEntityと同じ名前である`isAdmin`として表記しなければいけない。

## Controller
```java:AccountController
@Controller
@RequestMapping("/account")
public class AccountController {

	@Autowired
	AccountRepository accountRepository;

	@GetMapping("/query")
	public String queryTest() {
		
        List<Account>  accounts = accountRepository.findByidQuery();
		Account  account = accountRepository.findByidQueryOne(1);
		List<Account>  accountsNotAdmin = accountRepository.findByidQueryNotAdmin();
		// Repositoryからクエリ文によるaccountを取得した

		return "account/index";
	}
}
```


# その他
```java
public interface ReadingRecordRepository extends JpaRepository<ReadingRecord, Integer> {

    @Query("select new com.example.demo.model.Recommend(rr.itemId, count(rr.itemId)) "
            + "from ReadingRecord rr "
            + "where  rr.itemRelatedId = ?1 "
            + "group by rr.itemId order by count(rr.itemId) desc "
            + "limit 5")
    List<Recommend> findRecommends(Integer itemRelatedId);
}
```

より複雑な組み合わせであると、上のように書くことができる。
閲覧記録(ReadingRecord)から関連アイテムの記録をカウントして、上位5つのRecommendを取得するようにした。
Entityにないような型だと、modelを作成して`new ~ model.Model(id, name)`などとして型を指定しなければならない。

# おわりに
少し特殊な形、例えば`Count`、`Sum`などの集計的な内容があるとき、クエリ文を使用することがほぼ必須であると思われる。Modelを作成して型指定をすることも必要である。
個人的にはJPAをそのまま利用するよりも、クエリ文で書いたほうがよりしっくりくるのでより好んで利用すると思った。
AWS Client VPN でアクセス権を特定のアクセスグループのユーザーに許可する

# 内容

今日試してみるお題は、こちらです。
![スクリーンショット 2023-07-09 19.19.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/59ff7e0f-f3be-6889-0c5e-3187a671140a.png)
AWS Client VPN で接続した際に、送信先ネットワークによって、Active Directory の グループの SID で**アクセス権を特定のアクセスグループのユーザーに許可する** ようにすることです。

# 構成図

- group001 に属するユーザーは dev001 と dev002 にアクセスできるようにする。
- group00２ に属するユーザーは dev001 にだけアクセスできるようにする。
- 青線のプライベートIPでアクセスできるようにする。
- 緑線のパブリックIPでもアクセスできるようにする。

![名称未設定ファイル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/d9b1f40c-7065-6e94-8215-e160d8aa9966.png)

なお、プライベートIP宛にアクセスすることが通常ですが、パブリックIP宛でもアクセスできるようにしたいため検証目的でわざとNATゲートウェイ経由でアクセス可能になるようにしています。
パブリックIP宛にもアクセスできるようにNATゲートウェイ経由でアクセス可能にする方法は本記事に織り交ぜてしまうと複雑になってしまうため、下記記事を参考にしてみていただくと良いと思います。

https://www.membersedge.co.jp/blog/aws-vpc-client-vpn-building/

*※ポイントは、NATゲートウェイの EIP が送信元となるため、送信先の ALB もしくは EC2 のセキュリティグループのインバウンドルールで許可してあげる必要があるという点だけです。*

また、本来は Client VPN と　アプリケーションの VPC は分けた方がいいのですが、検証目的のため 1 つの VPC にしております。

# 設定

## Active Directory

Active Directory でユーザーを以下の通り作成し、dev001 と dev002 グループの SID を控えます。

|グループ|ユーザー|
|---|---|
|group001|user001 user002|
|group002|user001|

グループの SID の確認は次のページの手順　5 を参考にします。

https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/cvpn-working-rules.html#cvpn-working-rule-authorize

## Client VPN 

AWS Client VPN の承認ルールで次の通り制御します。
![スクリーンショット 2023-07-09 19.28.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/1628fc2a-c16d-6252-5d2a-2348d3e1a262.png)
dev001 グループは、グループID の語尾が、〜1600
dev002 グループは、グループID の語尾が、〜1603
 のネットワークにアクセスできるイメージです。


# 動作確認

group01 と group002 に所属する user001 は全てのネットワークにアクセスできます。
group001 にしか所属しない user002 は特定のネットワークしかアクセスできないように制御することができました。

||user001|user002|
|---|---|---|
|ec2_group001_private|![スクリーンショット 2023-07-09 19.01.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/c3c006da-9e40-e5b4-96e4-0453dc034414.png)|![スクリーンショット 2023-07-09 19.11.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/2134ce35-c896-5c35-6058-223a1aea6043.png)|
|ec2_group002_private|![スクリーンショット 2023-07-09 19.03.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/a2d4fc73-e30b-279f-df67-57d0909080be.png)|![スクリーンショット 2023-07-09 19.12.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/c30f07c5-0432-bccc-5d81-2c6de33afbe0.png)|
|ec2_group001_pubric|![スクリーンショット 2023-07-09 18.46.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/b20c7670-4c29-1a80-4923-915d9c5247b4.png)|![スクリーンショット 2023-07-09 19.12.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/d519eaa3-4a20-ad79-37d3-b302e7cd7b12.png)|
|ec2_group002_pubric|![スクリーンショット 2023-07-09 18.44.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/e1ac7977-f750-5462-02c5-67b6c3ac12e1.png)|![スクリーンショット 2023-07-09 19.13.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/110fee42-407e-6c50-2c58-a51a136d11ef.png)|
『サーバーレスシングルページアプリケーション』の "sspa server" でつまずいた話 

OREILLYの『サーバーレスシングルページアプリケーション』を勉強中だったのですが，`sspa server`コマンドが動かず苦戦したので共有．

# ポイント
## 1. bashではなくpowershell を使ってた．
そもそもsspaファイルはラッパースクリプトの定義ファイルです．ラッパースクリプトとは既存のbashコマンド(`ls`とか`cd`とか)を書き足したり，上書きしたりするスクリプトです．なのでpowershellではそのまま打ち込んでも起動しません．
```
bash sspa server
```
と打ち込むことでbashコマンドとして機能します．

## 2. LFではなくCRLFを使ってた．
gitHubやVScodeでは改行コードをデフォルトでCRLFを採用しています．ですが，bashではLFを採用しており，スクリプトを実行しようとするとエラーを吐きます．
因みに直接編集を行わなくてもgitHubで操作した場合でも改行コードが変わる場合があるらしいです．検証してないので真偽は分かりません．

## 3. python2ではなくpython3を使ってた
自分が普段使っているpythonはpython3だったのですが，このテキストではpython2を想定しているみたいです．コマンドもpython2からpython3で`python`から`python3`に変更されたので，sspaのファイルを`exec python -m ~`から`exec python3 -m ~`と書き換える必要があります．まだ，テキストを読み進めてないのでバージョン違いによる動作の影響は今のところ不明です．ただ，序盤は開発用のサーバーを起動してるだけなのでしばらくは問題なさそうです．
ASTERIA Warpとは


## はじめに
本記事では、ASTERIA Warpの開発ノウハウを共有することです。
初任者に役立つ情報を提供いたしますので、ぜひ参考にしてください。

## ASTERIA Warpとは
ASTERIA Warpとは、アステリア株式会社が開発・販売しているデータ連携ツールです。
ノーコード開発で様々なデータソースを簡単に連携させることができます。

## ASTERIA Warpの主な機能は
・　様々なデータソースへの接続
・　データの抽出、変換、送信
・　ジョブのスケジュール設定
・　イベントトリガーによる自動実行
・　ログの管理

Windows Server や Linux オンプレミス環境だけでなく、クラウド環境（AWS、GCP）でもインストールして利用することができます。

データの送受信や加工はもちろんのこと、データの抽出や変換、集計、分析など、さまざまな機能を利用できます。

ノーコードで簡単にデータ連携を実現できることが特徴で、多くの企業で導入されています。（2023年3月末時点で9931社）
様々な業種の企業で利用されており、データ連携のニーズに応え、業務の効率化や改善に貢献しています。

## 接続できるアダプター
アダプターとは、ASTERIA Warpと外部システムを接続するためのコンポーネントです。
※一部のアダプター有料です。
![option_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463540/88f5d1c0-52b9-3e19-667e-91e599b734e9.png)

## 料金について
https://www.asteria.com/jp/warp/lineup/
上記のURLを参考してください。（Standard、Enterprise　の製品は初期費用がかかります）
![FireShot Capture 002 - ASTERIA Warp 製品ラインナップ・価格｜データ連携ツール「ASTERIA Warp」｜EAI_ESB国内シェアNo.1｜アステリ_ - www.asteria.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463540/929a1d20-e681-95ad-09f1-9d56bcdf9437.png)

## 導入する前に機能対応表をチェック
① 機能対応表
https://support.asteria.com/hc/ja/articles/360000647541?_gl=1*6spnva*_ga*MjAxNDQ2NzA0OC4xNjg3MTgyNTEz*_ga_9DBRH3NVMS*MTY4ODgyNTEzNy41LjEuMTY4ODgyNTQ1OS42MC4wLjA.
② コンポーネント比較表
https://support.asteria.com/hc/ja/articles/360000665342

ASTERIA Warpは　Core、Core+、Standard、Enterprise　４つの製品があります。
会社側がどういうような機能が必要なのか確認し、
①機能対応表と②コンポーネント比較表をチェックしてください。
![スクリーンショット 2023-07-09 0.26.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463540/a3d4060c-ff9b-31c7-cbf0-46b0011045b0.png)

![スクリーンショット 2023-07-09 0.26.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463540/bd974260-6cde-e0d5-356a-288990b0e3ad.png)


## 検討を始めたきっかけ
勤めている会社は小売業です。
ASTERIA Warp　導入を検討したきっかけは業務効率化を図るためです。
（異なるシステム間でのデータのやり取りを自動化すること）
![スクリーンショット 2023-07-10 0.17.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463540/4c9e1169-8105-e6dc-b3be-b79c88fd376c.png)

2015年当時はCore、Core+の製品がなかったため、Standard製品にしました。

## 最後に
ASTERIA Warp　初心者のデベロッパーのために、
今まで開発して来たノウハウや役立つTipsをたくさん書きたいと思います。



---

技術情報共有コミュニティ:
https://support.asteria.com/hc/ja/articles/360003274354-ASTERIA-Developer-Network-Slack-%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%81%BE%E3%81%97%E3%81%9F-
現在のステータスと勉強記録の開設

## はじめに
こんにちは。のりべんです。
自分のスキルアップ記録とその手法を残すために記事を残します

## ステータス
取得資格一覧(2023/07/10時点)
・Iパス
・基本情報
・情セキュ
・AWS CLI
・Python基礎

取得予定資格(今年度)
・CompTIA Security+
・応用情報
・AWS SAA

## 残したいもの
・勉強記録(時間・費用)
・勉強した内容(内容をまとめたPDFなど)

## 終わりに
今使っているマシンがMacBookPro2017モデルなので
こいつの元をとれるように頑張っていければと思います。
以上
DAY13~14 インデントを知る

# DAY13
230708
入院に必用な物品の買い出しと家事してました

# DAY14
230709
html,cssを1時間打ち込んでみました
教本の通りにコーディングしていて、著作権の関係でコードや画像を載せられないですが、ちょっと進みました:relaxed:
プログラマーの友達にみてもらって、tabとshift+tabでインデントをできるということを知りました
インデントで折りたたんだりできることも知りました　便利～！
インデントのルール？みたいなのがちゃんとわかってないから後で調べたほうがいいかな？
入院の準備と入院があるので1週間ほど記事更新お休みします
入院中はプログラミングの動画とかみようかな
UserAgentの廃止について調べた

※この記事は、素人がパッとググった内容ですので、確かな情報ではありません

# 背景
- UserAgentでブラウザ判定しているシステムで不具合があった  
  - Windwos11にもかかわらずWindows10と表示される
  - Android10あたりからバージョン番号が更新されなくなっていた

# UserAgent(UA)とは
- よく見るのは、HTTPリクエストヘッダに埋め込まれ、サーバーのログに出ている
- WEBサイト側の管理者が、ユーザーがどんなブラウザやOSからアクセスしてきたのか分かる
- 参考｜Apache WEBサーバーのアクセスログ例

```
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1"
```

# UA廃止の動き
- 2020年8月ChromeブラウザがUAサポート終了を決定  
  - UserAgent文字列が複雑怪奇
  - プライバシー侵害を懸念
    - UAがフィンガープリントとして機能することでユーザーを追跡できる 
    - デバイス種別によりユーザー層を推定できる　など

- UAが無くなるわけではなく、情報を削っていき最終的に固定化凍結された（Chrome110ですでに実施済）　

## UA廃止（固定化）の具体例

### Desktop (user on Windows 8.1, for example)

- Old UA	

```
Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Safari/537.36
```

- Final Reduced UA	

```
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36
```

### Mobile (user on Samsung Galaxy, for example)

- Old UA	

```
Mozilla/5.0 (Linux; Android 9; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.1234.56 Mobile Safari/537.36
```

- Final Reduced UA	

```
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Mobile Safari/537.36
```

出典：https://www.chromium.org/updates/ua-reduction/


# UAに代わるブラウザ判定方法
- User Agent Client Hints（UA-CH）がリリースされている
  - HTTP応答ヘッダで追加要求する
  
  ```
  Accept-CH: Sec-CH-UA-Model
  ```

  - JavaScript API で情報を取得する
  
  ```
  navigator.userAgentData
  ```

詳しい実装：https://techblog.yahoo.co.jp/entry/2022121930384728/

# 今後のブラウザ判定はどう実装するのか
- Accept-CHやNavigator.userAgentDataは、Chrome/Edgeは対応しているが、FirefoxやSafariは未対応  
  https://developer.mozilla.org/ja/docs/Web/API/Navigator/userAgentData

- UA-CHを取ってみて、ダメなら従来のUAを見るという実装にする？
- そもそもプライバシーにうるさくなっているということは、ユーザーの情報を取るべきではない？

引き続き要調査
組織のアウトプットを促進させるためのTips

# はじめに
Qiitaで事業開発やマーケティング、イベント企画などを担当しています！
QiitaではQiita内外問わずエンジニアのアウトプットを促進し、ソフトウェアの進化を加速させ、業界全体を盛り上げていきたいと考えています。

記事として日々の学びを記録したり、自身のポートフォリオ、所属組織の技術広報など様々な目的でみなさんアウトプットされていると思いますが、以下など様々なハードルがありますよね。
- そもそもアウトプットをはじめるのは大変
- アウトプットを続けるのも大変

1人でアウトプットするのが大変なら、みんなでアウトプットしよう、ということで本記事では組織におけるアウトプットを促進させるためのTipsをご紹介します

:::note info
小手先に感じるTipsも散見されるかとは思いますが、なにかのちょっとしたきっかけになれば幸いです
:::

:::note warn
本記事に登場するTipsは、これまで私自身がQiitaユーザーに聴いたものや、Qiita社で取り組んでいるものなど、さまざまな組織における実践例など多岐にわたります。
該当の組織の規模やフェーズ、風土によっては合わないよ、というものもあるかも知れない点は予めご了承くださいませ！
:::

# 目次
- なんでもいいので目標を作ってみんなで達成に向かう
- イベントなど乗っかれるものには乗っかっていく
- 組織内に閉じたアウトプットをまずは最大化、習慣化する
- 組織内など身近なメンバーのアウトプットを称賛し合う文化をつくる
    - RSS等でメンバーのアウトプットにすぐに気づく仕組みをつくる
- アウトプットに対してインセンティブを付与する制度をつくる

# 組織のアウトプットを促進させるためのTips
## なんでもいいので目標を作ってみんなで達成に向かう
漠然と、
- 組織のアウトプット増やしたい
- 採用に寄与させたい
- ブランディングしたい
- etc...

というようなものを掲げてもなかなか続かないですよね...
内容自体はなんでもいいとおもうのですが、**明確な目標を掲げてみんなで取り組んだほうが続きやすかったり、モチベーションが湧きやすかったりする**はずです。

あくまで一例ですが、以下などある程度定量的に計測できるものがあったほうがみんなでアウトプットするのであれば一丸になれると思います。

- ◯投稿/週、◯投稿/月
- QiitaのOrganizationランキングにランクイン
- ✕月までに◯いいね獲得

## イベントなど乗っかれるものには乗っかっていく
Qiita社の人間のため、Qiitaに寄った内容にはなりますが、あらゆるイベントごとはお祭りのように乗っかっていくというのはいいきっかけになったりするのではないかと思います。

たとえばQiitaではイベントやランキングという観点では、以下のようなものがあります。

- Qiita Organization週間 / 月間のランキング
- Qiita表彰プログラム
    - 年間のいいね数や累計のいいね数で表彰
- Qiita Advent CalendarのOrganizationランキング
- Qiita Engineer FestaのOrganization対抗戦

こういったイベント、ランキングに乗っかるメリットは以下

- **お祭り感覚で楽しみながら参加するきっかけになる**
- **イベントごとなど普段よりもさらに注目されているタイミングのため、より多くの人に見てもらえる**

## 組織内に閉じたアウトプットをまずは最大化、習慣化する
はじめて公開するアウトプットなどは心理的なハードルとしても高くなりがちなため、コツコツと習慣づけていく方法。
社内のドキュメントツールなどで学びのメモや社内勉強会の資料、イベント参加レポートなど、なんでも積極的にアウトプットする習慣をつくる。
そして、社内のメンバー同士で、「これはパブリックにだしても大丈夫」など背中を押しあって少しずつ外部への公開を増やしていくというTips。

## 組織内など身近なメンバーのアウトプットを称賛し合う文化をつくる
明らかないいね工作などでは無い限り、メンバーかどうかを問わず、いいねなど称賛し合える文化を作るTips。
アウトプット促進に関わらず、リアクションはだれもが嬉しいしモチベーションの源泉の1つであるのは間違いないのではないでしょうか！

ここでいうリアクションは2種類あります、どちらも積極的にやっていきたいですね

- **記事に対してつけられる「いいね」のような機能として備わっているリアクション**
- **特定のだれかの行動に対して「あれ良かった」というコミュニケーションにおけるリアクション**

Qiita社では日々称賛し合うためにまずはメンバーのアウトプットに気づけるように**RSS等でメンバーのアウトプットがSlackチャンネルに流れてくる**など、気づけるための仕組みをつくるということもやっていたりするのでおすすめ

## アウトプットに対してインセンティブを付与する制度をつくる
準備するのが少し重めのTipsではありますが、こういったものがアウトプット促進に有効なケースもあります。
その条件やインセンティブの内容に最適解は無いかも知れませんが以下などは例として挙げられます。

- 記事投稿ごとに¥◯相当のギフト券プレゼント
- いいね数◯獲得で¥◯相当のギフト券プレゼント

それぞれ性善説が前提とされていたり、ハックできなくもなかったりするものではありますが、きっかけのインパクトとしてはやはりインセンティブは小さくないものがあるかなと思います。

# まとめ
ぜひ参考にできるものは参考にしていただき、みんなでアウトプット盛り上げましょう！
Qiitaも組織単位でアウトプットできるQiita Organizationという機能があるのでご興味ある方はぜひ！

https://qiita.com/organizations
Git Bash (for Windows OS)

こんにちは。
[Git for Windows](https://gitforwindows.org/) をインストールし、```Git Bash``` を使いました。

### 導入手順 ###

winget を用い、PowerShell 上にて、

```powershell
PS> winget install -e --id Microsoft.WindowsTerminal
PS> winget install -e --id Git.Git
```

次に、Windows Terminal へ Git Bash を登録・追加する[^1]。

#### 動作確認 ####
Git Bash を Windows Terminal 上で動かし、各種コマンドを動作確認する。例えば、

```console
$ which sshd.exe
/usr/bin/sshd.exe
$ echo $PATH | tr ':' '\n'
 ...
$ ps aux
 ...
```

#### Git Bash が標準提供しないコマンドを入手する ####

##### winget 利用 #####
* [wget2](https://github.com/rockdaboot/wget2)
 
##### そのほか #####
* [nkf.exe](https://www.vector.co.jp/soft/dl/win95/util/se295331.html) (Vector)

##### 未調査 #####
下記は未調査です：

* gcc.exe （「MinGW-w64のダウンロードとインストール」が必要とのこと）
* lv.exe （gcc.exe を用いてソースをコンパイルする必要があるとのこと）

[^1]: 参考：「[Windows Terminal で Git Bash を表示する](https://qiita.com/yokra9/items/bdd0882268b308cf22ca)」
Javadocで エラー: セミコロンがありません というエラーが出た

# はじめに
javadocでドキュメントを作ろうとしたときに上記のエラーに躓いた。
ちょーしょーもない原因だった。

# 内容
```:エラーログ
C:hoge\hogera.java:n: エラー: セミコロンがありません
 * msg&input
           ^
 .
 .
 .
エラー1個

```
※ディレクトリは適当に置き換えてる。
※行数はnに置き換えてる。
javadocはhtmlで記述する必要があるのにガン無視で&と書いていた。
勝手に変換してくれるものだと思ってたのかな...？＾＾；

実際には特殊文字をエスケープして以下のように書く必要がある
```java:javadoc
/**
 * msg&amp;input
 */
```

# 結論
javadocは実質htmlなので、特殊文字はエスケープする必要がある。