OmniAICreator/Qiita-1.07M huggingface dataset:
Railsで秘密情報を管理するためのcredentials.ymlの登録と運用についてまとめる

実務でcredentials.ymlを扱って、秘密情報を管理するときに理解が曖昧な部分があったので、「秘密情報をうまい具合に管理できるやつでしょ」という過去の自分に向けて記事を書きます。


この記事では以下のことを中心に書いてます。

:::note info
**記事で書くこと**
- credentials.ymlとは簡単な説明
- 編集方法
- 環境変数として使用するには
- 運用方法
:::


# credentials.ymlとは
- 機密情報（APIキー、パスワード、認証情報など）を安全に管理するための仕組み

以下のイラストにcredentials.ymlの全体像をまとめてみました

![段落テキスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1584967/e9918993-c8e9-afe6-c1f3-0a94026309b5.png)

▼主に登場する2つのファイルについての説明
- 秘密情報を一括管理しているcredentials.yml.enc
- credentials.yml.encを復号化（暗号を解除）するために必要なconfig/master.key
  - **注意**:リモートリポジトリにプッシュしては絶対にダメ 


# 編集方法
```復号化される前のcredentials.yml.enc
x\350\0239F\301\037!\334\037\330p\3119A\346M!\"\260\344c\347\275\031\266m\2455\263\027\217?\306
u\241\270L.\033=\254h\212|\275T?\342Y\2053\230\344\365.\313\264\211\233a\220\272\234\2269

```
上記の`credentials.yml.enc`は直接編集できません。
編集するために必要なことをこの章で解説していきます

手順① ローカル環境に`config/master.key`がある状況で下記コマンドを実行

```
$ EDITOR="vi" bin/rails credentials:edit
```
以下のようにvimで表示されます

```yaml:復号化されたcredentials.yml
# APIキー（外部サービスと連携するための情報）
some_api_key:
  api_id: your_api_id
  api_secret: your_api_secret
```
手順②  `i`を押してインサートモードに入ることで、テキストを編集
手順③  Vimで編集した後は、`Esc`キーを押して通常モードに戻り、`:wq`と入力して保存・終了







# 環境変数として使用するには
使用場面として、アプリケーション上で環境変数の情報を取得したい時について解説していきます。

例えば、`credentials.yml.enc`ファイルに下記のように情報が保存されているとします。




```yaml:credentials.yml.enc
some_api_key:
  api_id: YOUR_API_ID
  api_secret: YOUR_API_SECRET

```
この場合、`api_id`にアクセスするには次のように記述します。

```ruby
api_id = Rails.application.credentials.some_api_key[:api_id]
```
同様に、`api_secret` にアクセスする場合は以下のようになります。

```ruby
api_secret = Rails.application.credentials.some_api_key[:api_secret]
```

なので、
下記が例として、外部APIを呼び出すときに、認証情報で`credentials`の情報を利用するときのコードです。

```ruby:credentialの認証情報を使用して、外部APIを叩くとき
require 'net/http'

class ApiClient
  def initialize
    @api_id = Rails.application.credentials.some_api_key[:api_id]
    @api_secret = Rails.application.credentials.some_api_key[:api_secret]
  end
  
  def get_data
    uri = URI('https://example.com/data')
    req = Net::HTTP::Get.new(uri)
    req['Authorization'] = "Bearer #{@api_secret}"
  end
end
```

# 運用方法
チームで運用する際に、credentials.yml.encをうまく活用するためのポイントの
**「master.keyを外部に漏らさない仕組み・master.keyの共有方法」**
について紹介します。

:::note
**master.keyの管理**
-  `.gitignore`を用いて、config/master.keyはGitのリモートリポジトリで管理しないように設定すること。絶対にプッシュしない仕組みを作る！

```:.gitinnore
# Ignore master key for Rails credentials
/config/master.key
```



とはいえ`config/master.key`がないと、`credentials.yml.enc`に情報を登録したりすることができないので、チームに共有する必要があります。

なので、チームに共有する手段の1つとして、以下があると思います。
- 1Passwordのような社内のパスワードマネージャーを使う

:::



# 参考

https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39


https://railsguides.jp/security.html#%E7%8B%AC%E8%87%AA%E3%81%AEcredential

https://qiita.com/gyu_outputs/items/92c4a2a2f96edb10e298
ElastiCacheのElastiCacheとRedisについて

AWSを利用してアプリケーションを構築する際、キャッシュはパフォーマンス向上に欠かせない要素です。Amazon ElastiCacheは、MemcachedとRedisという2つのキャッシュエンジンを提供してます。ElastiCacheでMemcachedとRedisの違いや選び方についてまとめました。

### ElastiCacheとは？
mazon ElastiCacheは、AWSが提供するフルマネージドなキャッシュサービスです。
キャッシュとは、データの一時的な保存場所で、アプリケーションのレスポンス速度を向上させるために使用されます。
ElastiCacheを使うことで、手間をかけずに高速なキャッシュ環境を構築・管理できます。

### Memcachedの特徴
Memcachedは、シンプルで高速なキャッシュエンジンです。以下のような特徴があります。

- シンンプルな構造
    キーと値のペアをメモリ上に保存します。非常に高速で、大量のリクエストをさばくことができます。
- 水平スケーリングが容易
     ノード（サーバー）を追加することで、キャッシュ容量を簡単に拡張できます。
 
 - 軽量
     オーバーヘッドが少なく、リソースを効率的に利用できます。
- 用途
     ウェブサイトのセッションストア、一時的なデータのキャッシュ
- 注意点(資格試験でよく出る)
    Memcached クラスターをスケールアップ/ダウンするときは、新しいクラスターを作成する必要があります。
    
### Redisの特徴
Redisは、より多機能なキャッシュエンジンです。以下の特徴があります。

- 豊富なデータ構造:
    文字列、リスト、セット、ハッシュ、ソート済みセットなど、多様なデータ型をサポートします。

- 永続化機能
    メモリ内のデータをディスクに保存でき、再起動後もデータを保持します。

- 高可用性
    レプリケーションや自動フェイルオーバー機能があり、信頼性が高いです。

- 高度な機能
    	トランザクション,Pub/Sub（メッセージング）,Luaスクリプト

- 用途
    リアルタイムのデータ分析,メッセージキュー,キャッシュとデータストアの両方として利用

- 注意点(資格試験でよく出る)
    ElastiCacheクラスタのインスタンスタイプを変更できます。

### まとめ
- Memcachedは、シンプルで高速なキャッシュが必要な場合に最適です。
- Redisは、豊富な機能とデータ構造を活用したい場合や、データの永続化が必要な場合に適しています。
Github Packagesのインストールで詰まったところ

# はじめに
コンポーネントライブラリを、GitHub Packagesのnpm レジストリに公開して、GitHub Organization 内でのみ利用可能な状態にしました。
以下のサイトを参考にライブラリの公開まで行うことができましたが、公開したライプラリをインストールする際に詰まったところがあったので、その解消方法をメモとして残しておきます。

- [GitHub Packages の npm レジストリを使って、社内 org 用のプライベートパッケージを公開する手順とインストールする手順](https://zenn.dev/moneyforward/articles/20230620-github-packages)
- [GitHub Packagesを使ってプライベートパッケージをnpmインストールできるようにする](https://alpacat.com/posts/how-to-publish-private-npm-package)

# GitHubアカウントごとのインストール手順の違い
GitHub Organization に属している GitHub アカウントの種類（Member/Outside Collaborator）で、手順が異なります。
以下説明する作業の場面としては、上記参考サイトで掲載されているPersongt Access Tokenを発行して`.npmrc`ファイルの設定をした後からです。

## member

Persongt Access Token発行後、`npm install`を試してみると以下のエラーが発生しました。

```bash
npm ERR! code E401
npm ERR! 401 Unauthorized - GET［リポジトリURL】- unauthenticated: User cannot be authenticated with the token provided.

```

こちらに関しては、OrgnizationでSSO認証がかけられていたため、発行したトークンに対してSSO設定を行う必要がありました。以下に載っている手順で解決することができました。

[SAMLシングルサインオンで利用するために個人アクセストークンを認可する](https://docs.github.com/ja/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on)

## Outside Collaborator

アクセストークン発行後、`npm install`を試してみると以下のエラーが発生しました。

```bash

npm ERR! code E403

npm ERR! 403 403 Forbidden - GET [リポジトリURL] - Permission permission_denied: read_package
npm ERR! 403 In most cases, you or one of your dependencies are requesting
npm ERR! 403 a package version that is forbidden by your security policy, or
npm ERR! 403 on a server you do not have access to.

```

Outside Collaboratorの場合、Orgnization内のリポジトリの中でも招待されたリポジトリに対してしかアクセスすることができません。（GitHubの担当者に問い合わせました。）
ちなみに、memberの手順で行ったSSO設定の操作も行うことができません。

そのため、Github Packagesで公開したリポジトリに招待する必要があります。このときの権限はread権限で問題ありません。  
ただし、Outside Collaboratorをリポジトリに招待できるのは、OrganizationのOwnerのみです。そのため、Ownerにリポジトリ招待をしてもらう必要があります。

Ownerにリポジトリへ招待してもらった後、`npm install`を試すと、問題なくインストールすることができました。

# 参考文献

- [GitHub Packages の npm レジストリを使って、社内 org 用のプライベートパッケージを公開する手順とインストールする手順](https://zenn.dev/moneyforward/articles/20230620-github-packages)
- [GitHub Packagesを使ってプライベートパッケージをnpmインストールできるようにする](https://alpacat.com/posts/how-to-publish-private-npm-package)
- [SAMLシングルサインオンで利用するために個人アクセストークンを認可する](https://docs.github.com/ja/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on)
SPSS Modeler Serverのプロセスとユーザー

SPSS Modeler Serverのプロセスとユーザーについて解説します。

Windows版のSPSS Modeler ServerはWindowsのサービスとして起動します。
Modeler Clientはこのサービスに対して接続を要求します。
要求が成功すると別のmodelerserverプロセスが、接続したユーザーの権限で起動します。そのため、操作は接続したユーザーの権限でファイルアクセスなどが行われます。


![{16A2B1D4-4567-4891-8078-881531C09AA6}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/e332a11b-c2f3-a5df-a858-8e131cccacbd.png)


# 1. サービスとしてのmodelerserver
Windows版のSPSS Modeler ServerはWindowsのサービスとして起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/b1cb3f4c-bda6-424a-6142-b9890f53d004.png)


このmodelerserverのプロセスのユーザーはLocalSystemとして起動しています。
powerd\shellのGet-Processで確認すると以下のようになります。
```powershell
PS C:\Windows\system32> Get-Process -IncludeUserName -ProcessName modelerserver| Format-Table -autosize

Handles WS(K) CPU(s)   Id UserName            ProcessName
------- ----- ------   -- --------            -----------
    229 22160   3.16 4108 NT AUTHORITY\SYSTEM modelerserver
```

# 2. Modelerクライアントの実行プロセスとしてのmodelerserver
Modelerクライアントから接続をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/17a6c9a9-f616-da8d-8e29-495938f43853.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8b6d8017-8a58-5d59-4e4e-eddee86ae661.png)



powerd\shellのGet-Processで確認するとサービスとしてのmodelerserverのほかにdsuser1のmodelerserverが起動されているのがわかります。これがModelerクライアントの実行プロセスとしてのmodelerserverです。

```powershell
PS C:\Windows\system32> Get-Process -IncludeUserName -ProcessName modelerserver| Format-Table -autosize

Handles WS(K) CPU(s)   Id UserName                ProcessName
------- ----- ------   -- --------                -----------
    237 22204   4.14 4108 NT AUTHORITY\SYSTEM     modelerserver
    236 21856   0.64 7964 WIN-36L4N1I4M60\dsuser1 modelerserver
```


* テスト環境
    * Modeler 18.5
    * Windows 11 64bit
    * Modeler Server 18.5
    * Windows Server 2022 64bit

#### 参考:Modeler ServerでModeler Server上のファイルの読み書きする #SPSS_Modeler - Qiita 

https://qiita.com/spssfun2017/items/07bb710df8bf01a86357
recursive query

## はしがき

友達と話し合いしながら、db の recursive query に対して話題がありました。
recursive の意味はしっていますが、db からはどうやって実行されているか。わからないので、投稿します。

## recursive とは？

https://en.wikipedia.org/wiki/Recursion_(computer_science)

コードの中から、自信を繰り返して呼び出して、大きい問題を小さい問題で分け、解決することです。
有名な factorial の例を javascript で書きます。

```javascript
// javascript
const factorialRecursive = (n) => {
    if (n < 1) return -1
    if (n === 1) return 1
    return n * factorialRecursive(n - 1)
}
factorialRecursive(-1) // -1
factorialRecursive(1) // 1
factorialRecursive(3) // 6
factorialRecursive(5) // 120
```

繰り返して、自分自身を呼び出すことです。

## recursive query とは？

https://medium.com/@ugorjicalebchijindu/explaining-recursive-query-in-sql-38c043fcc740

SQL(mysql を前提で書きます)の recursive query は上の recursive と同じように、結果を出すために、繰り返して自分を呼び出すことです。

recursive query にたいして、以下のことの理解が必要そうです。

1. Common Table Expression (CTE): sql から記述された臨時の結果で、main query から呼び出すことができます。WITH で始まります。複雑な query を単純に、もしくは、ロジックを小さくなるためのことです。
1. Recursive Part: cte の recursive part は cte を参考します。なので、参考する基本的な部分と、recursive する部分があります。

```SQL
WITH RECURSIVE cte AS (
  -- 基本的な部分
  UNION ALL
  -- recursive part
)

SELECT ...
FROM cte;
```

recursive query は以下のような挙動します。

1. 基本的な部分から始まり、テーブルを呼び出します。
1. cte がテーブルのように使い、基本的な部分をもとして、recursive part の部分を実行
1. 終了の条件にあたるまで上の２番目を実行

## 例

これがどんな状況から使われるか考えました。
たぶん、hierarchical data structure の場合使われると思います。
たとえば、breadcrumbs、menu のように、hierarchical なデータがあるテーブルです。

今回は breadcrumbs で説明します。

テーブルを作ります。

### breadcrumbs

|Name|Type|nullable|
|-|-|-|
|id|INT|FALSE|
|title|VARCHAR|FALSE|
|parent_id|INT|TRUE|

```SQL
CREATE TABLE breadcrumbs (
  id INT AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  parent_id INT
);
```

テスト用のデータを作ります。

|id|title|parent id|
|-|-|-|
|1|Home|NULL|
|2|Category|1|
|3|SubCategory|2|
|4|Item 1|3|
|5|Item 2|3|
|6|Another Category|1|
|7|Another SubCategory|6|

```SQL
INSERT INTO breadcrumbs (title, parent_id) VALUES
  ('Home', NULL),
  ('Category', 1),
  ('Subcategory', 2),
  ('Item 1', 3),
  ('Item 2', 3),
  ('Another Category', 1),
  ('Another Subcategory', 6);
```

### recursive query 作成

breadcrumbs の level(どのぐらいの parent を持っているか)と root（Home） から、child までの title 全部を一気に見たいです。
結果は以下と予想します。

|id|path|level|
|-|-|-|
|1|Home|0|
|6|Home > Another Category|1|
|7|Home > Another Category > Another Subcategory|2|
|2|Home > Category|1|
|3|Home > Category > Subcategory|2|
|4|Home > Category > Subcategory > Item 1 |3|
|5|Home > Category > Subcategory > Item 2|3|

```SQL
WITH RECURSIVE breadcrumb_path AS (
  SELECT 
    id,
    title AS path,
    0 AS level
  FROM breadcrumbs
  WHERE parent_id IS NULL

  UNION ALL

  SELECT 
    b.id,
    CONCAT(bp.path, ' > ', b.title) AS path,
    bp.level + 1
  FROM breadcrumbs AS b
  INNER JOIN breadcrumb_path AS bp
    ON b.parent_id = bp.id
)
SELECT * FROM breadcrumb_path ORDER BY path, level;
```

### 参考したサイト

https://www.mysqltutorial.org/mysql-basics/mysql-recursive-cte/
https://medium.com/@ugorjicalebchijindu/explaining-recursive-query-in-sql-38c043fcc740
https://medium.com/learning-sql/understanding-recursive-sql-for-hierarchical-data-structures-76e3ac29c693
https://qiita.com/Shoyu_N/items/f1786f99545fa5053b75
cookieの用途とは

# cookieにはどういう用途があるのか？
>`httpをステートフルにする代表格はCookieを使ったセッション管理`です。RESTの視点から見ると、`Cookieを使ったセッション管理は間違ったhttpの拡張`です。ただ、REST的に間違っているからといって、`Cookieを使ったフォーム認証をやめるわけにはいかない`ことも事実です。Cookieは、ステートレスサーバの利点をあえて捨てることを理解したうえで、`必要最低限に利用`しましょう。

https://gihyo.jp/book/2010/978-4-7741-4204-3

まだまだステートレス・ステートフルの利点をまだ理解していない。理解が必要だ。
# Cookie の用途
>通常、サーバーは HTTP Cookie のコンテンツを 使用して、`さまざまなリクエストが同じブラウザー/ユーザーから送られたものかどうかを判断し、その後、必要に応じて個人設定または一般的なレスポンスを発行`します。以下では、非常にシンプルなログインシステムについて説明します。
>
>1.ユーザーは、例えばフォーム送信により、ログイン資格情報をサーバーに送信します。
>
>2.資格情報が正しい場合、サーバーはユーザーがログインしたことを示すように UI を更新し、`ブラウザー上のログイン状態を記録するセッション ID`を含むクッキーを返します。
>
>3.後日、ユーザーは同じサイトの別のページに移動します。ブラウザーは、ユーザーがまだサインインしていると認識していることを示すために、セッション ID を含むクッキーを、対応するリクエストとともに送信します。
>
>4.サーバーはセッション ID をチェックし、有効であれば、ユーザーに新しいページの個人設定版を送信します。無効であれば、セッション ID は削除され、ユーザーにはページの一般版が表示されます（あるいは、「アクセスが拒否されました」というメッセージが表示され、再度サインインするよう求められる場合もあります）。
>
>* セッション管理: ユーザーの`ログイン状態`、ショッピングカート、ゲームのスコア、またはその他のユーザーセッションに関するサーバーが覚えておくべきその他のもの。
>* パーソナライズ: 表示言語や UI テーマのようなユーザー設定。
>* トラッキング: ユーザーの行動の記録および分析。

https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies#:~:text=%E3%81%A6%E3%81%84%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,Cookie%20%E3%81%AE%E7%94%A8%E9%80%94,%E3%83%88%E3%83%A9%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0%3A%20%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%AE%E8%A1%8C%E5%8B%95%E3%81%AE%E8%A8%98%E9%8C%B2%E3%81%8A%E3%82%88%E3%81%B3%E5%88%86%E6%9E%90%E3%80%82,-%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8

# ステートレスの利点とは？
https://qiita.com/masatom86650860/items/982ed8a14455f8c050eb
# cookieの利点とは
多分ステートフルな通信ができるからステートレスの欠点が補えることができそうだ。

# なぜ必要最低限なのか？
多分ステートフルな通信が多いと対応するサーバをスケールアウトしにくくなるから最低限にしなけれなばならないと思う。
【パブリッシャー】プロンプトの値をスプレッドシートに反映させる方法について

# はじめに #
プロンプトの値をスプレッドシートに反映する方法を見ていきます。
これは、Excelの名前付き範囲とクエリ内のフィルター名を使用することで実現できます。
さあ、見てみましょう。

# Excelワークシートの名前付き範囲 #
セルD10に**Date**という名前を付けて、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f17d854c-6ffd-ba24-085a-1767388cb5ac.png)
セルE10に**Date2**という名前を付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2ce9b059-4ce9-9cd1-0832-79ebbe846929.png)

# スプレッドシート（公開レポート） #
公開レポートにインポートし、スプレッドシートとして使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/0c061811-89b3-0a49-103c-b4bc9efa0ec3.png)
次に、公開レポートのクエリにフィルターを定義します。  
公開レポートにはクエリが必要です。

私は日付フィルターを追加し、それに**Date**という名前を付けます。この名前は、セルに付けた名前付き範囲と同じでなければなりません。  
`FROM`フィルターの名前は**Date**として参照され、`TO`フィルターの名前は**Date2**として参照されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/288f8b4d-7815-7bb7-32b6-641adb46f9a9.png)

# 検証 #
公開レポートを保存し、ブラウザで表示します。  
定義した日付フィルターは、このようにプロンプトとして表示されます。  
`From`と`To`の日付を選択し、`Submit`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/541d91b4-ddc9-4027-dd05-24113efd821f.png)

入力したフィルターの値は、フィルターと同じ名前の名前付き範囲に転送されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/3d6c6609-a981-17f9-8d48-7c24d356abf5.png)

# おわりに #
この記事では、どのようにプロンプト値がスプレッドシート内に渡されるのかを見るだけだったので、私のやったこと自体には特に意味はありません。しかし、このアイデアからビジネスに役立つ方法を見つけることができるでしょう。
GPTScriptのサンプルの概要の翻訳

以下にあるGPTScriptの概要を翻訳しました。
https://github.com/gptscript-ai/gptscript/tree/main/examples

# README

このREADMEには、examplesディレクトリにある各サンプル.gptファイルの概要がまとめられています。

## 概要

[add-go-mod-dep.gpt] (add-go-mod-dep.gpt) :go.modファイル (具体的にはk8s.io/apiバージョンv 0.30.0) への依存関係の追加を自動化します。
[bob-as-shell.gpt] (bob-as-shell.gpt) :"Bob"という名前のツールと対話して、彼の健康状態を報告します。
[bob.gpt] (bob.gpt) : Bobという名前の仮想アシスタントとの簡単な対話を定義し、彼の状態を尋ねます。
[car-notifier/car-notifier.gpt] (car-notifier/car-notifier.gpt) : Craigslistの新しい4Runnerリストについて、データベースチェックと電子メール通知を含めてユーザーに通知します。
[count-lines-of-code.gpt] (count-lines-of-code.gpt) : Goファイル内のコード行をカウントし、結果を合計します。
[describe-code.gpt] (describe-code.gpt) :コード行数が最も多い上位10個のGoファイルを特定して要約します。
[echo.gpt] (echo.gpt) :任意の入力文字列をエコーバックする単純なスクリプト。
[fac.gpt] (fac.gpt) :減算ツールと乗算ツールを使用した再帰階乗関数を示します。
[gcp-assistant.gpt] (gcp-assistant.gpt) :ユーザーがGoogle Cloud Platformと対話するのを支援するGCPアシスタントエージェント。
[git-commit.gpt] (git-commit.gpt) :ステージングファイルに基づいて、整形式のgitコミットメッセージを作成します。
[gptreview-ghaction/codereview.gpt] (gptreview-ghaction/codereview.gpt) : GitHub CLIを使用して、開いているプル要求のコードレビューを自動化します。
[gptreview-jenkins/codereview.gpt] (gptreview-jenkins/codereview.gpt) :前のファイルと同様に、GitHub PRでコードレビューを実行するのに役立ちます。
[gptreview.gpt] (gptreview.gpt) : GitHub CLIコマンドの学習など、GitHub PRでコードレビューを実行するためのツール。
[hacker-news-headlines.gpt] (hacker-news-headlines.gpt) : Flaskを使用してHacker Newsのトップ10ヘッドラインの収集と表示を自動化します。
[hamlet-summarizer/hamlet-summarizer.gpt] (hamlet-summarizer/hamlet-summarizer.gpt) :テキストの一部を取得して要約することで、演劇「ハムレット」を要約します。
[helloworld.gpt] (helloworld.gpt) :"helloworld"と言う簡単なコマンドです。
[recipegenerator/recipegenerator.gpt] (recipegenerator/recipegenerator.gpt) :画像から識別された材料に基づいてレシピを生成します。
[samples-readme.gpt] (samples-readme.gpt) :他の.gptファイルを要約したToday I Learned for programmersファイルを生成する手順が含まれています。
[search.gpt] (search.gpt) :フロリダ州の休暇スポットをウェブで検索し、関連情報を取得します。
[sentiments.gpt] (sentiments.gpt) : AIオートメーションを使用してツイートのセンチメントを分析します。
[sqlite-download.gpt] (sqlite-download.gpt) : ZIPファイルをダウンロードし、SQLiteデータベースを検査して、クエリを実行します。
[syntax-from-code.gpt] (syntax-from-code.gpt) : BNF構文を使用してGoコードを分析し、特定のファイル形式を記述します。
[testkube.gpt] (testkube.gpt) : KubernetesクラスターでアプリケーションをテストするためのTestkubeを支援します。
[time.gpt] (time.gpt) :異なるタイムゾーンでの現在時刻を取得します。
[travel-agent.gpt] (travel-agent.gpt) :フランスでの休暇を計画し、詳細な旅程を作成します。
[treasure-hunt/treasure-hunt.gpt] (treasure-hunt/treasure-hunt.gpt) :参加者の手がかりとヒントを含む宝探しゲームを作成します。 
このREADMEは、.gptファイルで説明されているさまざまな自動化およびスクリプト作成手法のガイドとして機能します。

---
驚いたことにこのreadme.md自体がサンプルに含まれている以下の「samples-readme.gpt」で自動生成されます。
つまり拡張子「*.gpt」のファイルを探し、内容を読み、概要をまとめて出力するわけです。
```
tools: sys.find, sys.read, sys.write, summary
Model Name:gpt-4o-mini
Generate a readme at examples/README.md that gives a consolidated summary of each sample *.gpt file in examples/
Each entry should be a include a link to the referenced file.
---
name: summary
description: Summarize a gpt file
args: file: filename to summarize
tools: sys.read
temperature: 0.7

Read ${file} which is a sample GPTScript file. GPT script is an AI automation scripting language.
Briefly describe the contents of the GPTScript file and what technique the file is trying to demonstrate.

```
atomWithStorageでMap型を扱う方法

# 概要
[atomWithStorage](https://jotai.org/docs/utilities/storage)でMap型を扱う際に躓いたため実装方法をメモついでに記事にしました。

下記の実装ではローカルストレージへの書き込みやローカルストレージからのロードでエラーが出たり、うまく動作しませんでした。
```tsx
const sampleAtom = atomWithStorage<SampleMap>(
  'sample_map',
  new Map(),
)
```

ローカルストレージはstringのみ扱えるためMap型の値をJSON形式の文字列としてローカルストレージに書き込み、ローカルストレージからのロードする際は文字列型からJSONに変換し、それをMap型に変換する必要がある。

# 正しい実装方法
[atomWithStorage](https://jotai.org/docs/utilities/storage)のstorageパラメータにカスタム関数を渡すことで解決する。


>storage (optional): an object with the following methods:
>
>getItem(key, initialValue) (required): Reads an item from storage, or falls back to ?the intialValue
>setItem(key, value) (required): Saves an item to storage
>removeItem(key) (required): Deletes the item from storage
>subscribe(key, callback, initialValue) (optional): A method which subscribes to >external storage updates.


```tsx
type SampleMapItem = {
  value1: string
  value2: number
}
type SampleMap = Map<string, SampleMapItem>


// Mapのシリアライズ・デシリアライズ
const serializeMap = (map: Map<string, SampleMapItem>) =>
  JSON.stringify(Array.from(map.entries()))
const deserializeMap = (str: string) => new Map(JSON.parse(str))

// localStorageにMapを保存するための関数
const localStorageWithMap = {
  getItem: (key: string, initialValue: SampleMap) => {
    const item = localStorage.getItem(key)
    return item ? deserializeMap(item) : new Map()
  },
  setItem: (key: string, newValue: SampleMap) => {
    localStorage.setItem(key, serializeMap(newValue))
  },
  removeItem: (key: string) => {
    localStorage.removeItem(key)
  },
}

// atomの定義
const sampleAtom = atomWithStorage<SampleMap>(
  'sample_map',
  new Map(),
  localStorageWithMap
)
```

# 最後に
jotaiはあまり詳しくないですが、おそらくこれがベストプラクティスだと思っています。
もし他の良い方法があれば教えていただければ幸いです。
【C#】Containsの計算量

## きっかけ
競プロでTLEして、BFSで探索済みのインデックスを保持していたListのContainsが原因っぽいので
そんなの常識だろって人は笑って見逃してください

## 使用したコード
```program.cs
var rnd = new Random();

int dataCount = 5000000;
var list = new System.Collections.Generic.List<int>();
for (int i = 0; i < dataCount; i++)
{
    list.Add(rnd.Next(dataCount));
}
var hashSet = new System.Collections.Generic.HashSet<int>(list);

int testcaseCount = 100000;
var testcases = new int[testcaseCount];
for (int i = 0; i < testcaseCount; i++)
{
    testcases[i] = rnd.Next(dataCount);
}

// Stopwatchクラス生成
var sw = new System.Diagnostics.Stopwatch();

//-----------------
// 計測開始
sw.Start();

// ★処理A
for (int i = 0; i < testcaseCount; i++)
{
    list.Contains(testcases[i]);
}

// 計測停止
sw.Stop();

// 結果表示
Console.WriteLine("■処理Aにかかった時間");
TimeSpan ts = sw.Elapsed;
Console.WriteLine($"　{ts}");
Console.WriteLine($"　{ts.Hours}時間 {ts.Minutes}分 {ts.Seconds}秒 {ts.Milliseconds}ミリ秒");
Console.WriteLine($"　{sw.ElapsedMilliseconds}ミリ秒");

//-----------------
// 経過時間をリセットしてから計測開始
sw.Restart();

// ★処理B
for (int i = 0; i < testcaseCount; i++)
{
    hashSet.Contains(testcases[i]);
}

// 計測停止
sw.Stop();

// 結果表示
Console.WriteLine("■処理Bにかかった時間");
ts = sw.Elapsed;
Console.WriteLine($"　{ts}");
Console.WriteLine($"　{ts.Hours}時間 {ts.Minutes}分 {ts.Seconds}秒 {ts.Milliseconds}ミリ秒");
Console.WriteLine($"　{sw.ElapsedMilliseconds}ミリ秒");
```

## 結果

|データ数  |テストケース数  |Listの実行時間[ms]  |HashSetの実行時間[ms] |
|---|---|---|---|
|100  |100000  |2  |1|
|1000  |100000  |13  |1|
|10000  |100000  |115  |1|
|100000  |100000  |554  |1|
|1000000  |100000  |5459  |6|
|10000000  |100000  |156770  |7|

　`List<T>.Contains()`は多分計算量がO(N)なので多くのデータがある状態で使うと相当重い処理になるようです。BFSやDFSで探索済みのインデックスを保持する用途ではHashSet<T>が適切かと思います

## 参考
C#メモ　処理時間計測
https://qiita.com/Kosen-amai/items/81efaf815b48ab9ffbb6
paiza.ioでc# その9

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

# 練習問題
interfaceを2つ使え。

# サンプルコード

```

using System;

interface IQiitaPost {
    int LGTMCount { 
        get; 
    }
    int StockCount { 
        get; 
    }
}
interface IAuthorQiitaPost: IQiitaPost {
    void Delete();
}
interface IReaderQiitaPost: IQiitaPost {
    string Title { 
        get; 
    }
    string Text { 
        get; 
    }
    void LGTM();
    void Stock();
}
class QiitaPost: IAuthorQiitaPost, IReaderQiitaPost {
    private string m_title;
    private string m_text;
    public QiitaPost(string title, string text) {
        this.m_title = title;
        this.m_text = text;
    }
    public Uri PostURL { 
        get; 
    }
    public string Title => m_title;
    public string Text => m_text;
    public int LGTMCount { 
        get; 
        private set; 
    }
    public int StockCount { 
        get; 
        private set; 
    }
    public void LGTM() {
        ++LGTMCount;
    }
    public void Stock() {
        ++StockCount;
    }
    public void Delete() {
        m_title = string.Empty;
        m_text = string.Empty;
    }
    static void Main() {
        QiitaPost p = new QiitaPost("タイトル", "本文");
        Console.WriteLine("ok");
    }
}


```


# 成果物

https://paiza.io/projects/G8UPBZTqM-mDmiDZDbKKPw


以上
AGC068 A - Circular Distance

## 挨拶
にゃ～ん

## 概要
公式解説とは別の視点で解く解法。結局同じような式が立つのだけれどこっちの方がだいぶ考えやすかった。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">AGC068<br>A: 選んだ人がいるところに白、その正反対に黒を置くと、白と黒がある距離以下になってはいけない → 色は後で決めることにする　L の偶奇で場合分けなど<br>B: 最初 0*N, 1*N を置いておく　2 つのキューがあり、0 0 で 1 つのキューを回転させながら 0 1 で同時に取り出す問題になる</p>&mdash; SSRS (@SSRS_cp) <a href="https://twitter.com/SSRS_cp/status/1840407423145988290?ref_src=twsrc%5Etfw">September 29, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

丁寧に書こうと思ってます。AGC-A だからupsolveしたいけど難しいよ～って人の助けになれば幸い。

## 問題の言い換え
①人 $0$ は必ず選ぶとしてよいです。求める場合の数のうちの $\frac{N}{L}$ が人 $0$ を選んでおり、残りは人 $0$ を選んでいません。人 $0$ を必ず選ぶと思い込んで計算して最後に $\frac{L}{N}$ 倍すればいいです。
②まず人数が偶数人のときを考えます。奇数人のときは少しだけ複雑になります。

人 $i$ を選ぶことを赤く塗ることで表すことにします。それと同時にその反対の位置にある人を青く塗ります。
すると
$$
(コスト) = (赤同士の距離の最大値) = L/2 - (赤と青の距離の最小値)
$$
となります。
だいぶ見通しが立ちやすくなります。円環上の距離の最大値を求めようとすると全点対を考える羽目になり厳しいですが、最小値を求めるのであれば隣同士だけ注目すればよいです。すごい……
隣り合う赤と青の距離がどれも $D$ 以上となるような場合の数 $F(D)$ を求めにいきます。
$$
Ans = \sum_{D = 0}^{L/2} \left(\frac{L}{2} - D\right)(F(D) - F(D + 1))
$$
などとすれば答えが出ます。

## L: 偶数のとき
 $N$ 人を赤色に塗り、それらと対称の位置にいる $N$ 人を青色に塗ることを考えると、どのように塗っても必ず人 $0$ から人 $\frac{L}{2} - 1$ のうち丁度 $N$ 人が色を塗られていることに気づきます。
この範囲の人たちの色を適切に決めてあげれば、対称性により人 $\frac{L}{2}$ から人 $L - 1$ もその塗り方に従います。
さて色を塗られた人たちを $p_0 = 0, p_1, p_2, \cdots, p_N = \frac{L}{2} - 1, \cdots, p_{2N - 1}$ としましょう。

(i) 人 $p_i$ と人 $p_{i + 1}$ が同じ色で塗られる場合、間の距離は $1,2,3,\cdots$ が許されます。FPSで表すと $\frac{x}{1-x}$です。
(ii) 人 $p_i$ と人 $p_{i + 1}$ が異なる色で塗られる場合、間の距離は $D,D+1,D+2,\cdots$ が許されます。FPSで表すと $\frac{x^D}{1-x}$です。

ここで人 $p_0$ と人 $p_N$ は異なる色である必要があります。つまり人 $p_0$ から人 $p_N$ の間に(ii)は奇数回発生する必要があります。
(i)が選ばれる回数を $N-M$ 回、(ii)が選ばれる回数を $M$ 回とすると
$$
f(D)\xleftarrow{+}\binom{N}{M}\left[x^{\frac{L}{2}}\right]\left(\frac{x}{1-x}\right)^{N-M}\left(\frac{x^D}{1-x}\right)^{M}
$$
$$
=\binom{N}{M}\left[x^{\frac{L}{2}-DM -(N-M)}\right]\left(\frac{1}{1-x}\right)^{N}
$$
$$
=\binom{N}{M}\binom{(N-1) + (\frac{L}{2}-DM -(N-M))}{(\frac{L}{2}-DM -(N-M))}
$$
となります。なんと二項係数の積を計算するだけの問題になります。
これを $D=1,2,\cdots$ と$M=1,3,5,\cdots$ にかけてループを回しますが $-DM$ という項を見ればわかる通り調和級数のあれで $O(L\log L)$ です。

Q. $D = 0$ のとき、つまり赤い人の対称な位置に青い人と赤い人が共存できる場合について。(ii)のFPSは異なる色同士の距離が $0,1,2,\cdots$ となるので一見よさそうですが正しくない結果を得ます。なぜでしょう。理由はいろいろあります。

## L: 奇数のとき
 $L$ が偶数のときの議論が腑に落ちていれば大したことはありません。人同士の間に新たに人を挟んでしまいましょう。 $2L$ 人から $2N$ 人に色を塗ります。
この際に赤く塗る $N$ 人は偶数番目の人から選ぶ必要があり、青く塗る $N$ 人は奇数番目の人から選ぶ必要があることに注意します。
赤と青の距離は必ず奇数です。同じ色同士の距離は必ず偶数です。
赤と青の距離がいずれも $D$ 以上である場合の数 $G(D)$ を求めまれば

$$
Ans = \sum_{D = 1,3,\cdots, L} \left(\frac{L}{2} - \frac{D}{2} \right)(G(D) - G(D + 2))
$$

となります。

(i) 人 $p_i$ と人 $p_{i + 1}$ が同じ色で塗られる場合、間の距離は $2,4,6,\cdots$ が許されます。FPSで表すと $\frac{x^2}{1-x^2}$です。
(ii) 人 $p_i$ と人 $p_{i + 1}$ が異なる色で塗られる場合、間の距離は $D,D+2,D+4,\cdots$ が許されます。FPSで表すと $\frac{x^D}{1-x^2}$です。
として同様です。

## 終わり
解けるか～～！！(# ﾟДﾟ)

https://atcoder.jp/contests/agc068/submissions/58281551
サクラエディタの個人的に便利だと思った機能（矩形選択）


こんにちは！エンジニアの篠原です:penguin:
今回は、Windowsで開発しているエンジニアなら
誰しも使ったことがあるもしくは知っているのではないでしょうか。
「**サクラエディタ**」について、個人的に便利だと思った機能を紹介しようと思います。


## 目次
1.サクラエディタとは
2.インストール方法
3.便利機能(矩形選択)
4.まとめ



## サクラエディタとは 

Windows用テキストエディタです。
もっと簡単に言うと「メモ帳」です！

ですが、複数の文字コードに対応していたり、
マクロが使用できたりととっても便利。

また、オープンソースソフトウェアとして配布されているため
無料で使用することができます。





## インストール方法
https://sakura-editor.github.io/


公式サイトの最新版ダウンロードからインストーラーをダウンロードします。
<br>
公式サイト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/0dac0a0d-afe6-29e8-bf40-976cde574d09.png)





<br>

現在の最新版(Ver.2.4.2)はこちら↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/ed88f173-e197-5705-d417-1c68f584e3d7.png)



ダウンロードしてきたzipファイルを解凍後、
インストーラーを実行すればインストール完了です:white_check_mark:


## 便利機能(矩形選択)

まず一つ目に紹介したい便利機能は、「**矩形選択**」です。
<br>

どういう機能かと言うと↓のようなテキストがあって
アルファベットの列のみ切り出したいとき

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/6d727566-3165-02b5-ca75-820c19371a2a.png)


<br>

切り取りたい先頭の文字にカーソルを置いて
altボタンを押しながらカーソルキーを押すと範囲選択することができます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/82087aaf-0453-0413-12f0-b6d5ae9ba9c3.png)

<br>
そのままコピー＆ペーストすると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/caaa368e-af24-686a-c4f2-0d08206d0f2c.png)

切り出し成功！！
これが「**矩形選択**」です。
文字数が多いテキストデータの中から一部のみ切り出したいときって
結構あるのでとても便利:o:


## まとめ
今回は矩形選択の紹介をしましたが
サクラエディタにはまだまだ便利機能が沢山あるので
今後も紹介していこうと思います！
以上、篠原でした:penguin:
多数派要素の取得　Python

## はじめに
LeetCodeで出題された内容から、調べたことを自分用の備忘録として残しています。

## 多数派要素とは
全体の要素の半数以上（つまり、全体の要素数の半分を超える）登場する要素

### 具体例：
**リスト: [3, 2, 3]**
このリストには3つの要素があり、それぞれの登場回数は次の通りです。

- 3 が2回登場
- 2 が1回登場
この場合、リストに含まれる要素の数が3つなので、その半数は **3 ÷ 2 = 1.5** です。これを切り上げた数の 2回以上登場する要素が多数派要素です。この場合、3 が2回登場しているため、3 が多数派要素になります。

## 多数派要素の取得アルゴリズム
今回は、以下の３つの方法について、ご紹介します。

### 1. ボイヤー・ムーアの多数決アルゴリズムを使う方法
私が最初に実装したのが、この方法です。
ネット検索でヒットしたものから引用しましたが、よくできたアルゴリズムだなぁと思います。

```python
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        candidate = None
        count = 0

        for num in nums:
            if count == 0:
                candidate = num
            if num == candidate:
                count += 1
            else:
                count -=1
        return candidate
```

**時間計算量：O(n)**
配列を1回だけ走査するため。

#### 追記： 多数派要素が存在しない場合を考慮した実装

上記のコードは、多数派要素が存在しない場合が考慮されていないので、以下の処理を追記しました。
ご指摘ありがとうございました。

- 候補が本当に多数派要素かどうかを確認する処理

```python
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        candidate = None
        count = 0

        # 1. ボイヤー・ムーア多数決アルゴリズムで多数派候補を見つける
        for num in nums:
            if count == 0:
                candidate = num
            if num == candidate:
                count += 1
            else:
                count -= 1

        # 2. 候補が本当に多数派要素かを確認する
        count = 0
        for num in nums:
            if num == candidate:
                count += 1

        # リストの半数を超えているか確認
        if count > len(nums) // 2:
            return candidate
        else:
            # 多数派要素が存在しない場合、その旨のメッセージを返す
            return "多数派要素は見つかりませんでした"

```
**時間計算量: O(n)** 
配列を2回走査するため。


### 2. Pythonのcollections.Counterクラスを使った方法
collections.Counterクラスと組み込み関数maxを使うとより簡潔なコードが書けます。
時間計算量は、多数決アルゴリズムと変わりません。

```python
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        a=Counter(nums)
        return max(a, key=a.get)
```
**時間計算量：O(n)**
collections.Counterの計算量、maxの計算量ともにO(n)のため。

**参考サイト**：
https://qiita.com/ell/items/259388b511e24625c0d7
https://qiita.com/Hironsan/items/68161ee16b1c9d7b25fb

**ドキュメント**：
https://docs.python.org/ja/3/library/collections.html#collections.Counter
https://docs.python.org/ja/3/library/functions.html#max

### 3. 昇順にソートして中央値の要素を返す
簡潔なコードで書ける上に、先の２つの方法と比較して~~速く処理ができます~~
処理速度は遅くなります。（実行環境等により異なる場合があります）
それでも、スマートな方法と感動しました！

```python
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        nums.sort()
        return nums[len(nums) // 2]
```

**時間計算量：O(n log n)（n はリストの要素数）**
- nums.sort() の計算量:
sort() は内部的に「Timsort」というアルゴリズムを使用しており、平均・最悪の場合でも O(n log n) です。ここで、n は nums の要素数です。
- nums[len(nums) // 2] の計算量:
リストの中央の要素にアクセスする操作は定数時間（O(1)）で行えます。

最後まで読んでくださって、ありがとうございます。誤り等あれば、ご指摘くださるとありがたいです。

※ 時間計算量の比較について、記載誤りがありました。ご指摘ありがとうございました！
また、今回紹介した方法の２と３も、多数決アルゴリズムと同様、多数派要素が存在することを前提とした効率的な実装方法として記載しております。
ステートレスとは

httpはステートレスであるらしいがステートレスの意味を理解していない

# ステートレスとは
>「サーバがクライアントのアプリケーション状態を保存しない」制約のことです。

# アプリケーション状態とは
>ステートレスなやり取りではクライアント（客）は`毎回同じ注文内容を繰り返さなければならなかった`のに対し、ステートフルなやりとりでは`注文の差分だけを追加で説明すれば良かった`からです。
　ステートフルなやりとりは、サーバ（店員）がクライアントのそれまでの`注文を、やりとりの間ずっと覚えていることを前提`にしています。
...
この`「ハンバーガーセットをポテトで注文している」という情報のことを、クライアントのアプリケーション状態`と呼びます。
　アプケーション状態は`別名「セッション状態」`とも言います。システムにログインしてからログアウトするまでの一連の操作をまとめて「セッション」と呼ぶのですが、この`一連の操作の間の状態はアプリケーション状態`のことですので、アプリケーション状態とセッション状態はほぼ同じ意味になります。

ログインしてからログアウトするまでの操作の情報を記憶しておいてくれるのがステートフルなのか。そしてその情報をアプリケーション状態というのか。
ステートフルの方が便利そうだな。

# ステートフルの欠点
>サーバがクライアントのアプリケーション状態を覚えることは、`クライアントの数が増えるにしたがって難しく`なっていきます。
...
複数のサーバ間でアプリケーション状態を`同期して、どのサーバでも同じアプリケーション状態を扱えるようにしなければなりません`。
...
データを同期するオーバヘッドが無視できなくなります。
　このようにステートフルなアーキテクチャでは、クライアントの数が増えた場合に`スケールアウトさせにくくなります`。

複数のサーバあると同期しなければならずスケールアウトもしにくいのか。

# ステートレスの利点
>`クライアントがリクエストメッセージに必要な情報を全て含めます`。
...
リクエストの処理に必要な情報をすべて含まれているメッセージのことを「`自己記述的メッセージ`」と言います。ステートレスなアーキテクチャでは、サーバがクライアントのアプリケーション状態を覚える代わりに、`クライアントが自らのアプリケーション状態を覚え、すべてのリクエストを自己記述的メッセージで送信`します。
...
サーバはそれまでのことは`全て忘れて、新しく来るリクエストの処理に集中すれば良い`のです。この性質を利用すると、`ステートレスなシステムをスケールさせることは簡単`になります。

クライアント自身が必要な情報を送ることでサーバに負担がかからないからスケールアウトしやすいのか。

# ステートレスの欠点
### 送信するとデータ量が多くなる
>ステートレスでは全ての情報を送りなおす必要があります。これは、`データ量によってネットワークの帯域を消費`することを意味します。
### 認証など、サーバに負担がかかる処理を繰り返す
>データベースへのアクセスは重い処理ですので、これを`毎回繰り返すとパフォーマンスが落ちます`。

毎回送らないといけないからサーバに負担がかかるのか。
どちらにしてもサーバに負担がかかるのか。どっちを取るかなのか。

https://gihyo.jp/book/2010/978-4-7741-4204-3

# 感想
ステートレスは良い面もあれば悪い面があるのか。
VSCodeで仮想環境を切り替える

# はじめに
ローカルにあるPythonを仮想環境内で使いたい！
ということで備忘録的に画像とともにまとめました。



# 仮想環境に入る

1. `3.10.12 64-bit` をクリック
![vscode1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/7f2b91de-d846-1814-c454-d7646b1cb49d.png)

1. `+ 仮想環境の作成...` をクリック
![vscode2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/5910aa00-2f90-ad1b-cf41-f7782ba91223.png)

1. `Venv 現在のワークスペースに'.venv'仮想環境を作成します` をクリック
![vscode3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/c5830fa2-ff02-71e4-c29e-69b236e9fb22.png)

1. 
    1. 以前構築した仮想環境でよければ、`既存のものを使用 既存の".venv"環境を変更なしで使用する`をクリック
    1. 新たに仮想環境を作成する場合は、`削除と再作成 既存の".venv"ディレクトリを削除し、新しい".venv"環境を作成します`をクリック→完了
![vscode4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/fb499c10-b13d-b165-229a-2251df0a5945.png)

1. 既存のものを使用
`3.10.12 64-bit`だった部分が`3.10.12 ('.venv': venv)`に変わる
![vscode5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/6dd3f017-fd2e-ca05-7af8-1cd7e60a2959.png)
ターミナルを再起動すると、作業ディレクトリ名の先頭に(.venv)がつく
![vscode6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/b68d1a5f-1031-e521-5c29-99410a9a0373.png)


# 削除と再作成
作成したいバージョンを選択して、1. と同じようにターミナルを再起動すると、作業ディレクトリ名の先頭に(.venv)がつく
![vscode7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851617/2c4a4d5c-5ce3-3e9e-67ad-38f5e8ec288d.png)
特定のLambdaを指定した時刻に実行する(Node.js)

Lambdaで、自分自身を1分後に呼び出せるようにしてみました。

## 要約
- EventBridge Schedulerを使用
- 2種類のロールを用意する必要がある
  1. 実行ロール
  1. EventBridgeのスケジュールに付与するロール
- 作成しようとしているスケジュールと同名のスケジュールがあるとエラーになるので、先に削除が必要

## IAMロールの用意
### 1. 実行ロール
Lambdaで実行する場合、Lambdaの実行ロールに下記を含める
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "scheduler:CreateSchedule",
                "scheduler:DeleteSchedule",
                "iam:PassRole"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

### 2. EventBridgeのスケジュールに付与するロール
ResourceはLambdaのARNに置き換え
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:ap-northeast-1:123456789012:function:your-lambda-function-name:*",
                "arn:aws:lambda:ap-northeast-1:123456789012:function:your-lambda-function-name"
            ]
        }
    ]
}
```

## パッケージのインストール
```shell
npm install @aws-sdk/client-scheduler
```

## コード
```createTrigger.js
import { SchedulerClient, CreateScheduleCommand, DeleteScheduleCommand } from "@aws-sdk/client-scheduler";

const region = "ap-northeast-1"; //リージョン
const ROLE_ARN = "arn:aws:iam::123456789012:role/service-role/your-eventbridge-role-lambda-executor"; // EventTriggerに付与する用のロールのARN(2)
const LAMBDA_ARN = "arn:aws:lambda:ap-northeast-1:123456789012:function:your-lambda-function-name"; // LambdaのARN
const SCHEDULE_NAME = "OneTimeTrigger"; // EventBridge Scheduler上での表示名。なんでもOK

const eventBridgeScheduler = new SchedulerClient({
    region,
    // AWSの外部で実行する場合は、1.実行ロール が付与されたIAMユーザーのアクセスキーも設定
    // credentials: {
    //    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    //    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
    // }
});

export const createSchedule = async () => {
    const lambdaTarget = {
        RoleArn: ROLE_ARN,
        Arn: LAMBDA_ARN
    };

    const delayInMinutes = 1; // 何分後に実行するか
    const scheduledTime = new Date(Date.now() + delayInMinutes * 60 * 1000);

    // 同名のスケジュールが既に存在する場合は削除する
    await eventBridgeScheduler.send(new DeleteScheduleCommand({ Name: SCHEDULE_NAME }));

    const command = new CreateScheduleCommand({
        Name: SCHEDULE_NAME,
        ScheduleExpression: `at(${scheduledTime.toISOString().slice(0, -5)})`,
        Target: lambdaTarget,
        FlexibleTimeWindow: { Mode: "OFF" },
    });

    try {
        const response = await eventBridgeScheduler.send(command);
        console.log("Schedule created successfully:", response);
    } catch (error) {
        console.error("Error creating schedule:", error);
    }
};
```
【ServiceNow】Washington DCリリース　Service Catalog「質問にfield messageを設定する」

# はじめに
みなさんこんにちは、三井情報株式会社です。

今回は、Service Catalogのカタログアイテムの質問に、スクリプトを記述せずにfield messageを設定する方法を実装例とともにご紹介いたします。

# field messageの実装例
### 概要
カタログアイテムの質問回答欄に”不明”と記載したときに、設定したfield messageを表示させる設定を行います。

### 実装手順
（1）フィルターナビゲーターから Service Catalog > Catalog Builder を開きます。
（2）field messageを設定したいカタログアイテムを選択します。
![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/0272dfdf-b636-15a9-8c82-5cd4264a6c6d.png)
（3）「Edit catalog item」をクリックします。
![1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/58781003-79d4-36c6-2806-fe24227199f6.png)
（4）サイドバーからQuestionsを選択し、field messageを設定したい質問のUIポリシーアイコンをクリックします。
![1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/7c4cf137-ecf3-240b-2517-e51750cd6640.png)
（5）編集アイコンをクリックします。
![1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/9ac7358c-2b0c-8d1f-b2f3-908fde1dfb01.png)
（6）メッセージタイプを選択します。
![1-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/340a33bf-a4db-d21e-ed22-5afc74cba416.png)

:::note info
info･･･メッセージが緑色の文字で表示されます
Warning･･･メッセージが黄色の文字で表示されます
Error･･･メッセージが赤色の文字で表示されます
:::
（7）メッセージ文を入力します。
![1-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/47902f2b-39fe-9110-14f0-c69e80f7dfcd.png)
（8）Conditionsタブに移動し、メッセージを表示させる条件を追加します。
![1-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/f198167f-e186-9d94-9599-a5940054af97.png)
（9）Settingsタブに移動し、メッセージを表示させるタイミングを選択します。Saveをクリックします。
![1-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/592c6a88-fff5-d4e1-41f5-19bcb2a00184.png)
（10）サイドバーからReview and submitを選択し、Submitをクリックします。
![1-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/8f084d79-b7ea-c17e-5901-5a14148285e4.png)

### 実行結果
質問回答欄に”不明”と記載したときに、field messageが表示されました。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3773072/a449f210-62a4-4a4d-627e-e6bd5666e3a2.png)

## 参考
本記事は、以下のドキュメントを参照しています。

https://docs.servicenow.com/ja-JP/bundle/washingtondc-servicenow-platform/page/product/service-catalog-management/task/edit-question-cat-builder.html

## おわりに
本記事では、カタログアイテムの質問に、スクリプトを記述せずfield messageを設定する方法をご紹介させていただきました。
最後までお読みいただき、ありがとうございました。
Java基礎文法Part３

まず、基本型とは、プログラミングで使われる最も基本的なデータの種類です。

イメージ： 数字や文字など、一つの値だけを持つシンプルなデータです。
Javaには8つの基本型があります。

整数を表す型：

byte：小さな整数（-128から127）
short：やや大きな整数（約-3万から3万）
int：一般的な整数（約-21億から21億）
long：非常に大きな整数
小数を表す型：

float：小数（単精度浮動小数点数）
double：より正確な小数（倍精度浮動小数点数）
文字を表す型：

char：一文字（例：'A'、'あ'）
真偽値を表す型：

boolean：真（true）か偽（false）の二つの値だけ
ポイント：

基本型は、データそのものを直接扱います。
計算が速く、メモリ（データを保存する場所）の使用量も少ないです。
例：
```Java
int age = 15;           // 年齢を整数で表す
double height = 160.5;  // 身長を小数で表す
char grade = 'A';       // 成績を一文字で表す
boolean isStudent = true; // 学生であるかを真偽値で表す
```


参照型とは？
次に、参照型について説明します。

イメージ： 実際のデータそのものではなく、そのデータがある場所（アドレス）を指しています。
オブジェクト（物やものごと）を扱うための型です。
参照型の例：

String型： 文字列（複数の文字の集まり）を表す。
配列（Array）： 複数のデータをまとめて扱う。
自分で作成したクラスやオブジェクト： 特定の機能やデータを持つもの。
ポイント：

参照型は、データへの「参照」（リンクやポインタ）を持っています。
実際のデータは別の場所に保存されており、その場所を指し示しています。
例：
```Java
String name = "太郎";           // 名前を文字列で表す
int[] scores = {80, 90, 75};   // テストの点数を配列で表す
Student student = new Student(); // Studentクラスのオブジェクトを作成
```


基本型と参照型の違い
データの保存方法：

基本型： 変数に値そのものが保存されます。
参照型： 変数にはデータの場所が保存され、実際のデータは別の場所にあります。
コピーしたときの挙動：

基本型： 値がそのままコピーされます。変更しても元の値には影響しません。
参照型： データの場所がコピーされます。同じデータを指し示すため、片方を変更するともう片方にも影響します。
用途：

基本型： シンプルなデータ（数値や一文字）を扱うとき。
参照型： 複雑なデータ（文字列、配列、オブジェクト）を扱うとき。
なぜこの違いが重要なの？
プログラムを書くときに、データがどのように扱われるかを理解することが大切です。
基本型と参照型の違いを知ることで、予期しない動作やバグを防ぐことができます。
例題で理解しよう
基本型の例：
```Java
public class Main {
    public static void main(String[] args) {
        int a = 10;
        int b = a; // aの値をbにコピー
        b = 20;    // bを変更
        System.out.println("a: " + a); // 出力は a: 10
        System.out.println("b: " + b); // 出力は b: 20
    }
}
```
解説： bにaの値をコピーした後、bを変更してもaには影響しません。これは基本型だからです。


参照型の例：
```Java
public class Main {
    public static void main(String[] args) {
        int[] arrayA = {1, 2, 3};
        int[] arrayB = arrayA; // arrayAの参照をarrayBにコピー
        arrayB[0] = 10;        // arrayBの最初の要素を変更
        System.out.println("arrayA[0]: " + arrayA[0]); // 出力は arrayA[0]: 10
        System.out.println("arrayB[0]: " + arrayB[0]); // 出力は arrayB[0]: 10
    }
}
```
解説： arrayBはarrayAと同じ配列を指しています。そのため、arrayBを変更するとarrayAにも影響します。


まとめ
基本型（プリミティブ型）：

一つの値を直接持つシンプルなデータ型。
変数間で値をコピーすると、それぞれ独立しています。
数値や文字、一つの真偽値など。
参照型：

データへの参照（場所）を持つ複雑なデータ型。
変数間で参照をコピーすると、同じデータを共有します。
文字列、配列、自分で作ったオブジェクトなど。
LaTeX Workshop はどのように TeX ソースをコンパイルしているのか

こんにちは。とある大学院生です。

私は VS Code の LaTeX Workshop プラグインを用いて TeX ファイルをコンパイルして論文を書いています。その中で、ファイルをコンパイルしようとするたびに LaTeX Workshop がエラーを吐き、エラーコードをググっては出てくる場当たり的な解決策を適当にコピペして凌ぐ日々を過ごしています。

この原因として、調べてもそもそも内部で何が起きているのかを解説する日本語記事がない事 (と英語記事と公式ドキュメントを読みにいかなかった自分の怠慢) が考えられます。

そこで、自分の備忘録と、公式ドキュメントを読みに行くハードルを下げるため、以下に LaTeX Workshop のドキュメントから必要箇所を日本語訳したものを記事として残しておくことにしました。

# LaTeX recipes
LaTeX Workshop で「LaTeX プロジェクトをビルド」すると、`settings.json` からレシピ (`"latex-workshop.latex.recipes"`) が呼び出されます。

LaTeX Workshop のドキュメントには以下のように書かれています。

- LaTeX プロジェクトをビルドする際、 LaTeX Workshop が順番に実行するコマンド列が LaTeX recipe と呼ばれ、 `latex-workshop.latex.recipes` に定義される。
- 変数 `latex-workshop.latex.recipes` と `latex-workshop.latex.tools` として定義されたいくつかの基本的なレシピがデフォルトの LaTeX Workshop に含まれる
- 以下に 2 つのよくある例を示す
  - 1 つめは単純に `latexmk` コマンドに依存する
  - 2 つめは以下に示すコマンド列 `pdflatex` → `bibtex` → `pdflatex` → `pdflatex` を実行する
```.settings.json
"latex-workshop.latex.recipes": [
  {
    "name": "latexmk",
    "tools": [
      "latexmk"
    ]
  },
  {
    "name": "pdflatex -> bibtex -> pdflatex * 2",
    "tools": [
      "pdflatex",
      "bibtex",
      "pdflatex",
      "pdflatex"
    ]
  }
]
```
- プロジェクトをビルドする際に、基本的に最初のレシピが使用される
- 設定(`latex-workshop.latex.recipe.default`)を見よ。コマンド `latex-workshop.recieps` により他のレシピでのコンパイルをすることもできる
- デフォルトでは `latexmk` が使用される。このツールは大抵の LaTeX ディストリビューションにバンドルされ、実行には perl を要求される

# LaTeX Tools
更に、レシピ内に書かれた `tools` は `latex-workshop.latex.tools` を参照することで呼び出されます

ドキュメントには以下のように書かれています
- レシピの `tools` フィールドに現れる各 tool は `latex-workshop.latex.tools` に定義される。レシピに tool を含むには、 tool の `name` がレシピの `tools` リストに含まれなければならない
- デフォルトの値は以下で与えられる

```settings.json
"latex-workshop.latex.tools": [
  {
    "name": "latexmk",
    "command": "latexmk",
    "args": [
      "-synctex=1",
      "-interaction=nonstopmode",
      "-file-line-error",
      "-pdf",
      "-outdir=%OUTDIR%",
      "%DOC%"
    ],
    "env": {}
  },
  {
    "name": "pdflatex",
    "command": "pdflatex",
    "args": [
      "-synctex=1",
      "-interaction=nonstopmode",
      "-file-line-error",
      "%DOC%"
    ],
    "env": {}
  },
  {
    "name": "bibtex",
    "command": "bibtex",
    "args": [
      "%DOCFILE%"
    ],
    "env": {}
  }
]
```

ここでいう `command` というのはターミナル上で叩くコマンドのことであり、`args` はそのコマンドに渡す引数のことです。
これ以上の詳細は `latexmk`, `pdflatex`, `bibtex` と言った各種ツールの説明を読みに行くことになります。


# 最後に
ここに記述された内容は二次資料なので一次資料(公式ドキュメント)の変更を反映していません。正確な情報は一次資料を見に行け。

# 参考資料
[1] [Compile · James-Yu/LaTeX-Workshop Wiki · GitHub](https://github.com/James-Yu/LaTeX-Workshop/wiki/Compile)
ASUS ROG ZEPHYRUS G16 (GU603VI-I9R4070G) にUbuntuをデュアルブートでインストールした

# ASUS ROG ZEPHYRUS G16 (GU603VI-I9R4070G) にUbuntuをデュアルブートでインストールした手順

## はじめに

この記事では、ASUS ROG ZEPHYRUS G16 にWindowsとUbuntuをデュアルブートでインストールした際の手順を紹介します。主に、インストール時に遭遇した問題や、それをどう解決したかをメモ形式で残します。

## 準備

### 1. Ubuntuインストール用USBの作成

Ubuntu公式サイトからISOファイルをダウンロードし、Rufusなどのツールを使ってUSBメモリに書き込み、ブート可能なメディアを作成します。

### 2. ストレージの解放

Windows側でストレージの空き領域を作成しておきます（ディスクの管理から行います）。Ubuntuをインストールする領域を確保します。

### 3. UEFIの設定変更

次に、ASUS ROG ZEPHYRUS G16 のUEFIでいくつかの設定を変更します。

- **Secure Bootを無効化**
- **Fast Bootを無効化**

これらは、UEFIの「Boot」や「Security」メニューで設定できます。

## インストール手順

### 1. Ubuntuの起動

1. パソコンを一度シャットダウンします。
2. Ubuntuのインストール用USBを挿入し、F2キーを押しながら電源を入れます。BIOS（UEFI）の画面が表示されたらF2キーを離します。
3. 「Boot Option」でUSBドライブを選択して起動します。
表示される選択肢:
   - `Windows Boot Manager (Micron_2400_MTFDKBA1T0QFM)`
   - `UEFI: KIOXIA, Partition 1 (KIOXIA)` (USBメモリの種類により異なる可能性あり)
   - `Enter Setup`
   
   ここで、**UEFI: KIOXIA** を選択します。

### 2. インストールが進まない問題

ASUSの「REPUBLIC OF GAMERS」ロゴとUbuntuのロゴが表示されたところで画面が固まりました。この場合、次の手順でCUIモードを確認します。

- **F6キーを押す**と、CUIモードでインストールの状態が表示されます。
  - 表示されたログ: 
    ```
    Starting Network Manager Script Dispatcher service...
    [OK] Started Network Manager Script Dispatcher Service.
    ```
  この後で画面が固まりました。

### 3. ハードリセットとブートメニューからの再試行

電源ボタンを長押ししてハードリセットを行い、次の手順で再起動します。

1. 起動時に `Esc` キーを押し続けてブートメニューを開きます。
2. BIOS（UEFI）の画面が表示されたらF2キーを離します。
3. 「Boot Option」でUSBドライブを選択して起動します。


### 4. GRUBでのブートオプション編集

GRUBメニューが表示されるので、以下の手順でオプションを編集します。

1. `Try or Install Ubuntu` が選択された状態で **`e`** キーを押します。
2. `quiet splash` という行を探し、その後に **` nomodeset noapic`** を追加します。
3. 修正後、**`Ctrl + X`** を押して起動を再開します。

### 5. 起動後のインストール

画面が消えた状態で長時間待つ必要がありましたが、最終的にUbuntuのデスクトップが表示されます。
マウスパッドが反応しなくなりましたが、有線のマウスを繋いだら反応したのでその状態で進めます。

その後、デスクトップにある **`Install Ubuntu 22.04.3 LTS`** アイコンをダブルクリックしてインストールを開始します。

### 6. インストール手順

インストールは通常通り進めました。特に注意したポイントは以下です。

- Wi-Fiの設定はスキップしました（後で設定可能です）。
- 他は画面の指示に従って進めます。
- かなり待たされますが気長に進めます。

### 7. インストール後の状況

インストール完了後、再起動するとUbuntuが起動しました。この時点で、**マウスパッドが使えるようになりました**。

## まとめ

ASUS ROG ZEPHYRUS G16 にUbuntuをデュアルブートでインストールしました。同じモデルを使ってUbuntuをインストールしようとしている方の参考になれば幸いです。
[Dataflow] Apache Beam入門

Google Cloud Skill BoostのData Engineer Learning Pathを一通り受講完了したので、その中で特に分量の多かった「08Serverless Data Processing with Dataflow: Develop Pipelines」について自分なりに理解した内容をまとめます。Perplexityなども活用しながら書いております。間違い等あればご指摘ください。

## Dataflowとは
Dataflowとは、Google Cloudのサービスの一つで、サーバレスでフルマネージドのETLサービスです。特徴としてはApache Beamをベースとして作られています。そのため、バッチ処理とストリーミング処理の両方に対応できます。

## Apache Beamとは
Apache Beamとは上述したDataflowのベースとして使用されており、バッチ処理とストリーミング処理の両方に対応したオープンソースのデータ処理フレームワークです。特徴としては、多言語対応でJava、Python、Goなどの言語SDKが使用できます。また、ポータビリティ性があり、Dataflow上だけでなく、複数の実行エンジンで実行可能です。（Apache Flink、Apache Sparkなど）

## Apache Beamの基本概念
- Pipeline（パイプライン）：
データ処理の全体的な流れを表します。入力データの読み取りから変換、出力データの書き込みまでの一覧の処理をカプセル化したものです。
- PCollection（Pコレクション）：
パイプライン内のデータセットを表す抽象的なオブジェクトです。バッチデータやストリーミングデータを含むことができます。
- PTransform（P変換）：
PCollectionに対する変換操作を定義します。データの変換、フィルタリング、集約などの処理を行います。
参考：https://beam.apache.org/documentation/transforms/java/overview/
- Runers（ランナー）：
ジョブの実行環境で前述したDataflowやApache Flink、Apache Sparkの他にローカル環境での実行をするDirect Runnerを指定することができます。
- IOコネクタ：
外部ソースからの読み込みや、外部シンクへのデータ書き込みを行うための変換操作です。

以上のPipeline、Pcollection、PTransform、Runners、IOコネクタを用いた簡単なデータフロー処理の例です。
https://github.com/apache/beam/blob/master/sdks/python/apache_beam/examples/wordcount.py

Dataflowで実行するには、Pythonの仮想環境を構築し、下記コマンドを実行します。
```shell
python3 -m apache_beam.examples.wordcount --region us-central1 --input gs://dataflow-samples/shakespeare/kinglear.txt --output gs://dataflow-apache-quickstart_test-431906/results/output --runner DataflowRunner --project test--431906 --temp_location gs://dataflow-apache-quickstart_test-431906/temp/
```

上記のソースのPTransform中に記述されている、ParDo、DoFnという概念は下記の通りです。
- ParDo：
PCollectionの各要素に対して並列処理を適用するための汎用的な処理関数です。入力のPCollectionの各要素に対して、ユーザ定義の処理を適用し、新しいPCollectionを生成します。
ParDoは、DoFnのインスタンスを受け取り、それをPCollectionの各要素に適用します。

- DoFn：
ParDoで実行される具体的な処理を定義するためのクラスです。beam.DoFnを継承して作成します。DoFnはParDoによって実行される具体的な処理を定義します。

## ストリーミング処理の際に必要な概念
・イベント時間（Event Time）と処理時間（Processing Time）
イベント時間とは、イベントが実際に発生した時刻を指し、データ自体に含まれるタイムスタンプに基づきます。
一方で処理時間とは、システムがイベントを処理する時刻を指し、システムの現在時刻に基づきます。

・ウィンドウ（Window）
ストリーミングデータのようなUnboundedデータ（終わりがないデータ）の場合に、ウィンドウと呼ばれる時間ベースでデータをグループ化する機能を使って、有限サイズに分割して変換処理や集計処理を実行させます。

・ウォータマーク（Watermark）
ウォータマークはシステムが自動的に計算し、データが到着する度に再計算され、継続的に更新されます。
ウォータマークによりデータが早着か遅延が決定され、ウォータマークより前に到着すれば早着データ、あとならば遅延データとみなされます。
ウォータマークは、あるウィンドウにあるすべてのデータがいつ到着するかを推測するものです。

・トリガー（Trigger）
各ウィンドウの結果を集計するタイミングを開発者が決定するためのものです。

以上のWindow、Watermark、Triggerを用いた簡単なデータフロー処理の例です。
https://github.com/GoogleCloudPlatform/training-data-analyst/blob/master/quests/dataflow_python/7_Advanced_Streaming_Analytics/solution/streaming_minute_traffic_pipeline.py


Apache Beamのコンセプトについては下記のDataflowの資料とApache Beamの資料が大変参考になり、正確かと思われます。

https://cloud.google.com/dataflow/docs/concepts/beam-programming-model?hl=ja
https://beam.apache.org/documentation/basics/
aptのあれこれ

## aptに関すること

aptはAdvanced Package Toolの略  
apt-getはinstallに関係するものを扱うコマンド  
apt-chacheはパッケージの情報を示すものを扱うコマンド  
かつてはこれら2つをまとめたコマンドとしてaptitudeがその役割を果たしていたが現在ではaptコマンドに集約された。

### Synapticパッケージマネージャー

「APTパッケージ管理システム」のGUI版

### 設定ファイル

`/etc/apt`に設定ファイル等が格納されている。

プロキシ等の設定が格納されるファイルやディレクトリ
`/etc/apt/apt.conf`  
`/etc/apt/apt.conf.d/*`  

取得リポジトリ設定が格納  
`/etc/apt/sources.list`
`/etc/apt/sources.list.d/*`

## リポジトリの分類

Ubuntuのリポジトリは、main、restricted、universe、multiverseの4つに分かれている。