OmniAICreator/Qiita-1.07M huggingface dataset:
【SwiftUI】ScrollViewのバウンスを無効にする

# はじめに
バウンスありとなしではアプリの印象がとても変わります。
SwiftUIのScrollViewはバウンスがありで、変更することができないので`SwiftUI-Introspect`を使用してバウンスを無しにしてみます
|||
|-|-|
|![Simulator Screen Recording - iPhone 14 Pro - 2023-08-03 at 21.06.12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/87a5fce6-1ef3-2cd3-4a48-e7e401b7a980.gif)|![Simulator Screen Recording - iPhone 14 Pro - 2023-08-03 at 21.05.50.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e2a712e8-3fd5-caca-5b1c-80e46c6dee1c.gif)|

https://github.com/siteline/SwiftUI-Introspect

# ライブラリのインストール
全体的な流れはこちらを参考にしてください

https://tech.amefure.com/swift-package-manager

:::note warn
**注意**
`SwiftUIIntrospect`のみチェックをいれます
![スクリーンショット 2023-08-01 16.18.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/31800ab3-7bad-0ab0-78fc-fb8934daa2a3.png)
:::

# 実装
```swift
import SwiftUI
import SwiftUIIntrospect

struct ContentView: View {
    @State private var isPresented = false

    var body: some View {
        ScrollView {
            ForEach(0..<50) { _ in
                Text("サンプルセル")
            }
        }
        .introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in
            scrollView.bounces = false
        }
    }
}
```

# おわり
これは結構好き嫌い分かれるところだと思うのでアプリ内で切り替えできるようにするといいかもしれません。
Excel VBAでシート単位に別ファイルにしたい

# 1. はじめに
* Excelのブックにあるシート単位にファイルを分割したい
* Excel VBAで一括でファイル名をシート名で自動保存したい

# 2. 開発環境
* Excel 

# 3. Excelマクロの作成
## 3.1. 開発 > Visual Basicを選択する
![スクリーンショット 2023-08-03 20.23.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/ccff66c2-668c-7aa0-089f-d81004ed6585.png)
* 開発タブが表示されていない場合、リボンとツールバーで開発にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/a612074e-68c3-ca1d-9a0e-bc303c2dbbf0.png)

## 3.2. プロジェクトを右クリックして、標準モジュールを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/dda67b7f-18a2-02a1-4ce8-6d1b71e85253.png)

## 3.3. Excel VBAマクロを記述する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/53847855-baf1-c3fc-726b-f2d864697475.png)

```vb:
Sub saveSheet()
    Dim shObj As Worksheet
    Dim newBook As Workbook
    Dim newBookName As String
    Dim folderParent As String
    
    'シートの保存先はこのブックと同じとする
    '必要に応じてこの変数を変更する
    folderParent = ThisWorkbook.Path & "\"
    
    'ワークシートの分だけ繰り返す
    For Each shObj In Worksheets
        
        'シートを新しいブックにコピーする
        shObj.Copy
        
        '移動先のブックがアクティブになっているので変数に格納する
        Set newBook = ActiveWorkbook
        
        'シート名を変数に格納しておく
        newBookName = newBook.ActiveSheet.Range("C6") & "_" & shObj.Name & ".xlsx"
        
        '新しいブックを名前を指定して保存する
        newBook.SaveAs folderParent & newBookName
        
        '新しいブックを閉じる
        newBook.Close
    
    Next shObj
End Sub
```

## 3.4. Excelマクロを保存して、マクロを実行する

# 4. 参考文献

https://www.tekizai.net/entry/vba_sheet_split_1
SSHでアクセスできない

## 備忘録
スクール学習中で分からなかったことや解決したことの備忘録です

スクールの課題でVPCで仮想ネットワークを作成するというものがあったのですが、実際にVPC、サブネット、インターネットゲートウェイ、EC2を作成して、SSHも「0.0.0.0/0」で許可し、いざ接続！と意気込んたもののアクセスできず・・・

## 結論
結論としてはそもそもインターネットの出入り口の役割もつインターネットゲートウェイがデタッチ(停止状態)になっていて出入り口が封鎖されていたこと、ルートテーブルのルートがローカルしか無かったことが原因でした。
つまり、ルートがローカル(VPCのIPアドレス)だけだったので入り口はあっても出口がなかった状態だったということですね。

インターネットゲートウェイをアタッチにして、ルートの送信先を「0.0.0.0/0」ターゲットをing-xxxxxxxx(インターネットゲートウェイ)に設定して解決しました。
ChatGPTでテーブル定義からテストデータの生成

# ChatGPTでテーブル定義からテストデータの生成

テストしていてふと思ったのですが、データベースに登録するデータいちいち作成しなくても、ChatGPTに作成させれば、すぐ終わるのでは？

## 実際の生成

#### 質問1
```
""" CREATE TABLE categories (
	id bigserial NOT NULL,
	"name" varchar(255) NOT NULL,
	created_at timestamp NULL,
	updated_at timestamp NULL,
	CONSTRAINT categories_pk PRIMARY KEY (id)
);  """に対するテストデータをSQLで10件作って
```
CREATE TABLEからデータを作成するようにお願いしました。

####  結果1
```
INSERT INTO categories ("name", created_at, updated_at) VALUES
('Category 1', '2023-08-03 12:00:00', '2023-08-03 12:00:00'),
('Category 2', '2023-08-03 12:10:00', '2023-08-03 12:10:00'),
('Category 3', '2023-08-03 12:20:00', '2023-08-03 12:20:00'),
('Category 4', '2023-08-03 12:30:00', '2023-08-03 12:30:00'),
('Category 5', '2023-08-03 12:40:00', '2023-08-03 12:40:00'),
('Category 6', '2023-08-03 12:50:00', '2023-08-03 12:50:00'),
('Category 7', '2023-08-03 13:00:00', '2023-08-03 13:00:00'),
('Category 8', '2023-08-03 13:10:00', '2023-08-03 13:10:00'),
('Category 9', '2023-08-03 13:20:00', '2023-08-03 13:20:00'),
('Category 10', '2023-08-03 13:30:00', '2023-08-03 13:30:00');
```
それなりに作成してくれました。

####  質問2
```
nameには適当なそれらしいカテゴリーを作成してください
```

####  結果2

```
INSERT INTO categories ("name", created_at, updated_at) VALUES
('Electronics', '2023-08-03 12:00:00', '2023-08-03 12:00:00'),
('Home & Kitchen', '2023-08-03 12:10:00', '2023-08-03 12:10:00'),
('Fashion', '2023-08-03 12:20:00', '2023-08-03 12:20:00'),
('Books', '2023-08-03 12:30:00', '2023-08-03 12:30:00'),
('Sports & Outdoors', '2023-08-03 12:40:00', '2023-08-03 12:40:00'),
('Beauty', '2023-08-03 12:50:00', '2023-08-03 12:50:00'),
('Toys & Games', '2023-08-03 13:00:00', '2023-08-03 13:00:00'),
('Health & Fitness', '2023-08-03 13:10:00', '2023-08-03 13:10:00'),
('Automotive', '2023-08-03 13:20:00', '2023-08-03 13:20:00'),
('Pet Supplies', '2023-08-03 13:30:00', '2023-08-03 13:30:00');

```
それらしいデータ作ってくれました。英語ですが問題ないです。

#### 質問3

```
また、created_at、updated_atは適当に散らした値で作成してください
```
#### 結果3

```
INSERT INTO categories ("name", created_at, updated_at) VALUES
('Electronics', '2023-08-03 08:10:25', '2023-08-03 08:10:25'),
('Home & Kitchen', '2023-08-03 09:20:50', '2023-08-03 09:35:15'),
('Fashion', '2023-08-03 10:30:10', '2023-08-03 10:40:35'),
('Books', '2023-08-03 11:40:30', '2023-08-03 11:50:45'),
('Sports & Outdoors', '2023-08-03 12:50:55', '2023-08-03 13:00:25'),
('Beauty', '2023-08-03 14:00:15', '2023-08-03 14:10:35'),
('Toys & Games', '2023-08-03 15:10:25', '2023-08-03 15:20:45'),
('Health & Fitness', '2023-08-03 16:20:35', '2023-08-03 16:30:55'),
('Automotive', '2023-08-03 17:30:45', '2023-08-03 17:40:15'),
('Pet Supplies', '2023-08-03 18:40:55', '2023-08-03 18:50:35');

```
それらしいテストデータを作ってくれました。


## 考察

* きちんとしたテストデータを作成できました。
* ツール化すると面白いと思います。
* DDLと実行するSQLとで、テストデータとテスト項目も作成もできそうです。
* 結合するテーブルも作成してくれそうです。
* テーブルのカラム追加など変更するとテストデータの修正がめんどくさい。そこを自動生成してくれるとありがたいですね。
* DBのテストは自動化できそうですね。
自作ライブラリを jsDelivr から取得

専用のファイル置き場がない状況で、既存のサービスなどで使うために自作の JavaScript ライブラリをどこかに置きたいことがあります。そういうときは GitHub と jsDelivr の組み合わせが便利です。

# jsDelivr

大量にアクセスされるファイルをキャッシュして高速に配信する仕組みを CDN (Contents Delivery Network) と呼びます。

jsDelivr は CDN の 1 つです。

https://www.jsdelivr.com/

# GitHub 連携方法

jsDelivr に登録手続きを行わなくても、GitHub に公開リポジトリがあれば jsDelivr から配信できます。

:::note info
自作のライブラリや、CDN への登録情報が見当たらない既存のライブラリを利用するのに便利です。
:::

トップページにある GitHub のタブをクリックすれば利用方法が表示されます。それを引用して解説を加えます。

```
// load any GitHub release, commit, or branch
// note: we recommend using npm for projects that support it
https://cdn.jsdelivr.net/gh/user/repo@version/file
```

`user`, `repo`, `version`, `file` の部分を書き換えれば、GitHub にある公開リポジトリのファイルが取得できます。GitHub を開いて URL からこれらの情報を取得するのが簡単です。バージョンは git タグを指します。

:::note info
npm でサポートされているプロジェクトは、そちらを使うようにとのことです。以下で jQuery を例に使用方法が説明されますが、これは例であって、本来は npm として参照して欲しいということのようです。
:::

```
// load jQuery v3.6.4
https://cdn.jsdelivr.net/gh/jquery/jquery@3.6.4/dist/jquery.min.js
```

GitHub での URL と比較します。

* https://github.com/jquery/jquery/blob/3.6.4/dist/jquery.min.js

これを書き換えて jsDelivr の URL が得られます。

* `https://github.com/` → `https://cdn.jsdelivr.net/gh`
* `/blob/` → `@`

:::note alert
GitHub で raw ファイルのリンクは取得できますが、大量のアクセスを捌くことは想定されていません。これが配信専用の CDN を間に挟む理由です。
:::

```
// use a version range instead of a specific version
https://cdn.jsdelivr.net/gh/jquery/jquery@3.6/dist/jquery.min.js
https://cdn.jsdelivr.net/gh/jquery/jquery@3/dist/jquery.min.js
```

マイナーバージョンやリビジョンを省略すれば、指定した範囲内の最新版が取得できます。

記事執筆時点（2023 年 8 月 23 日）では 3.6 系の最新版は 3.6.4、3 系の最新版は 3.7.0 のため、それらが取得されます。

:::note warn
バージョンを省略した場合、最新バージョンが push されてから配信に反映されるまで最大 1 日程度のラグがあるようです。配信に反映されてもブラウザ側ではいつまでも古いキャッシュを使い続ける傾向があり（明確な期間は不明）、その場合はブラウザ側でキャッシュをクリアしないと更新されません。

バージョンを省略せずにフルで指定した場合、push 後すぐにアクセスできます。致命的なバグの修正はバージョンを省略せずに指定した方が無難です。
:::

```
// omit the version completely to get the latest one
// you should NOT use this in production
https://cdn.jsdelivr.net/gh/jquery/jquery/dist/jquery.min.js
```

バージョン指定を完全に省略した場合、最新版が取得されます。

:::note alert
製品では使用するべきではないと注意書きがあります。メジャーバージョンアップなどで非互換が発生することがあるためでしょう。
:::

```
// add ".min" to any JS/CSS file to get a minified version
// if one doesn't exist, we'll generate it for you
https://cdn.jsdelivr.net/gh/jquery/jquery@3.6.4/src/core.min.js
```

リポジトリに minify したファイルが置かれていなければ、自動で生成してくれます。

:::note info
自作ライブラリだと毎回 minify して push するのは手間なので、これは助かります。
:::

```
// add / at the end to get a directory listing
https://cdn.jsdelivr.net/gh/jquery/jquery/
```

URL の最後に `/` を付ければ、ディレクトリ内のファイルが列挙されます。

# 参考

https://kamoqq.info/post/cdn-jsdelivr/

https://sutara79.hatenablog.com/entry/2015/05/29/130043
OpenAPIのスキーマファイルでバリデーションチェックをする

# 1. はじめに
* OpenAPIのスキーマファイルで文字列について単項目のバリデーションチェックを行いたい
* OpenAPI Generatorでソースコードをジェネレートした時に、チェック処理も自動生成できるようにしたい

# 2. 開発環境
* OpenAPI 3.0.0

# 3. スキーマファイル
## 3.1. 英字の場合
```YAML
parameters:
  - name: input
    in: query
    required: true
    schema:
      type: string
      pattern: '^([a-zA-Z])+'
```

## 3.2. 数字の場合
```YAML
parameters:
  - name: input
    in: query
    required: true
    schema:
      type: string
      pattern: '^([0-9])+'
```

## 3.3. 特殊文字の場合
```YAML
parameters:
  - name: input
    in: query
    required: true
    schema:
      type: string
      pattern: '^([#$%&-=@*+/.[?_\]\])+'
```
* ```[```, ```]``` を記述する時はエスケープする必要がある

## 3.4. 全角文字の場合
```YAML
parameters:
  - name: input
    in: query
    required: true
    schema:
      type: string
      pattern: '^([^\x01-\x7E])+'
```

## 3.5. 複数チェックをする場合
* 例： 英数字をチェックする場合
```YAML
parameters:
  - name: input
    in: query
    required: true
    schema:
      type: string
      pattern: '^([a-zA-Z]|([0-9])+'
```
* ```|``` でパイプで繋げることで複数条件を指定することができる

# 4. 参考文献

https://qiita.com/YoshijiGates/items/0380d153090426c08506
【ちょっと便利な小技_part 1】Visual Studio Codeでflutter開発

#### VisualStudioCodeでのflutter開発途中で便利だと感じたものを紹介

今回は**StatefulWidget**を**StatelessWidget**に、
または**StatelessWidget**を**StatefulWidget**に変えたいなと思った時の変換方法を紹介

# 変換方法
1\.まずは**StatefulWidget**または**StatelessWidget**を選択
![スクリーンショット 2023-08-03 19.43.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524075/204773c1-e377-81e0-4ee2-c722d187bf20.png)

2\.次に『cmd』＋『.』(Mac)
※下記の画像のようなのが表示されます
![スクリーンショット 2023-08-03 19.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524075/19c4eb72-c664-d4fb-f1c6-0f5f6604f8e5.png)

3\.あとは『Convert to StatelessWidget』を選択


# 最後に
これで急に変更したくなってもすぐに変更できます👍
これからも便利なことを投稿します。
Terraformを用いてACMで証明書を発行する際にドメインを複数登録する方法

Terraformで証明書を発行する際に以下のように一つの証明書に複数のドメインを入れたいときとかありませんか？
![スクリーンショット 2023-08-03 193446.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3439167/41ec590f-c3a1-b231-af4c-f0750cedd4c3.png)
画面上でポチポチ操作するときは「この証明書に別の名前を追加」をクリックすれば追加できますが、この操作をTerraformで行うときに少し詰まったのでその方法を共有させていただきます。

# 結論
subject_alternative_namesを使うことで追加できます。
具体的には以下のようになります。

```
resource "aws_acm_certificate" "tokyo_cert" {
  domain_name       = "example.com"
  subject_alternative_names = ["*.example.com"]
  validation_method = "DNS"

  tags = {
    Name = "example"
  }

  lifecycle {
    create_before_destroy = true
  }
}
```
subject_alternative_names = ["_*_.example.com"]と記載することが、画面上での操作で言うところの「この証明書に別の名前を追加」をして「*.example.com」と入力する操作に相当します。

# 参考

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate
[PowerShell] シンボリックリンクを作るメモ

# はじめに

PowerShellでのシンボリックリンクの作り方を毎回調べているのでメモとして残す事にしました。
改めて見ると大したことないですが。

# 環境

```
> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.3.6
PSEdition                      Core
GitCommitId                    7.3.6
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
```

# コマンドレット

```powershell
New-Item -ItemType SymbolicLink -Path $path -Value $target
New-Item -ItemType SymbolicLink -Path $path -Name $name -Value $target

New-Item -ItemType SymbolicLink -Path $path -Target $target
New-Item -ItemType SymbolicLink -Path $path -Name $name -Target $target
```

## 解説

実体のある`$target`のシンボリックリンクを`$path`に作る。

```powershell
New-Item -ItemType SymbolicLink -Path $path -Value $target
```

`-Value`パラメータは、エイリアスとして`-Target`を持っているので以下のようにも書ける。

```powershell
New-Item -ItemType SymbolicLink -Path $path -Target $target
```

ディレクトリと名前を別々に指定したい場合は、以下のようにも出来る。

```powershell
New-Item -ItemType SymbolicLink -Path $path -Name $name -Value $target
```

## 実行

シンボリックリンクを作るには管理者権限が必要。
例えば以下のような関数で監理者権限を調べられる。

```powershell
function isAdmin {
  $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
  return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
```

そして以下のようにすると、監理者権限が無いとエラーメッセージが表示されるように出来る。

```powershell:makeSymlink.ps1
param(
  [Parameter(Mandatory = $true)][string]$target,
  [Parameter(Mandatory = $true)][string]$path,
  [Parameter()][string]$name
)

function isAdmin {
  $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
  return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

function makeSymLink {
  param(
    [Parameter(Mandatory = $true)][string]$target,
    [Parameter(Mandatory = $true)][string]$path,
    [Parameter()][string]$name
  )
  $value = isAdmin
  if (!$value) {
    Write-Host "管理者権限が必要"
    return
  }
  if ($name -eq "") {
    New-Item -ItemType SymbolicLink -Path $path  -Value $target
  }
  else {
    New-Item -ItemType SymbolicLink -Path $path  -Name $name -Value $target
  }
}

makeSymLink -target $target -path $path -name $name
```

これだとわざわざ管理者権限を取ってから実行しないといけないので面倒。
そこで、スクリプトファイルを管理者権限で実行するスクリプトを用意すると便利。
例えば以下のようになる。

```powershell:callAsAdmin.ps1
param(
  [Parameter(Mandatory = $true)][string]$script,
  [Parameter()][string]$args
)
Start-Process pwsh -ArgumentList "-NoExit", $script, $args -Verb RunAs -Wait
```

これを実行するには以下のようにする。

```console
> callAsAdmin.ps1 makeSymlink.ps1 "-target test.txt -path test1.link"
> callAsAdmin.ps1 makeSymlink.ps1 "-target test.txt -path . -name test1.link"
```
ChromeからDockerで構築したNextcloudにSAMLでログインできない問題

# はじめに

自宅サーバーでNextcloudやGitLabを動かしてSSOで利用できるようにしたいなと考え、その第一歩としてKeycloakとNextcloudの設定を行いました。今回の問題は設定を終えて、Google Chromeでログインを試そうとした時に発生しました。

今回のサーバー構成です。
- Nginx: リバースプロキシ
- Keycloak: IdPサーバ
- Nextcloud: SP

リバースプロキシの後ろにKeycloakとNextcloudを設置し、例えば`http://localhost:8080/keycloak`にアクセスするとKeycloakの管理画面が表示されるような設定となっています。

# 発生した問題

Nextcloudのログイン画面でSSO＆SAMLログインボタンを押下し、Keycloakでログインを行いました。ログイン後、Nextcloudにリダイレクトすると、そこで**複数ページを経由して最初のログイン画面に戻されてしまいました**。

![nextcloud-login-page-saml.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594132/c020e379-28fd-d60c-3015-7f5d5ed47ee1.jpeg)


Keycloakの管理画面を確認してみると、セッション情報が保存されていたことから、ログイン自体は問題なく行われていることが分かりました。

キャッシュを削除してみたり、シークレットモードで試してみたりしましたが、やはり上手く行きませんでした。しかしブラウザをFirefoxに変更して試してみたところ、Nextcloudにログインすることができました。

このことからGoogle Chromeに問題があるのではと考えました。

# 問題の原因

Chromeのコンソールを確認してみると、以下のようなエラー情報が表示されていました。

```
Mark cross-site cookies as Secure to allow setting then in cross-site contexts
```

どうやらセキュリティ強化のため、異なるオリジン間の場合、HTTP通信を使用しているとクッキーが保存できないとのこと。

# 解決策

今回は自宅専用のサーバーということでいわゆるオレオレ証明書でhttps通信することにしました。

```Dockerfile
FROM nginx:1.25.1

WORKDIR /etc/nginx

RUN openssl req -new -days 365 -x509 -nodes -keyout cert.key -out cert.crt -subj "/"

RUN service nginx start
```

`/etc/nginx`内に証明書と秘密鍵が作成されるので、これをもとにNginxの設定も変更します。

```conf
# 省略
  server {
    listen 443 ssl;
    ssl_certificate      /etc/nginx/cert.crt;
    ssl_certificate_key  /etc/nginx/cert.key;
    # 省略
  }
```

プロトコルを変更したことでURLも変更になるので、対応するKeycloakやNextcloudの設定も変更を行います。

コンテナを起動しhttpsでNextcloudのログイン画面へアクセスします。自己署名ということで警告文が表示されますが無視して進み、再度ログインを行います。すると、Google ChromeでもSAMLでログインできるようになっています。

![nextcloud-saml-login-success.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594132/48fed77b-6a64-4298-2517-6f38020ef478.jpeg)
lsblk

```
[linuxstudy@xxxx ~]$ lsblk
NAME                MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                   8:0    0   20G  0 disk 
├─sda1                8:1    0    1G  0 part /boot
└─sda2                8:2    0   19G  0 part 
  ├─centos-root     253:0    0 17.5G  0 lvm  /
  └─centos-swap     253:1    0  1.5G  0 lvm  [SWAP]
sdb                   8:16   0    8G  0 disk 
├─sdb1                8:17   0    1G  0 part /usbmemory2
├─sdb2                8:18   0    1K  0 part 
├─sdb5                8:21   0    1G  0 part 
├─sdb6                8:22   0    1G  0 part 
│ ├─datagroup-data1 253:2    0  612M  0 lvm  
│ └─datagroup-data3 253:4    0  400M  0 lvm  
└─sdb7                8:23   0    1G  0 part 
  └─datagroup-data2 253:3    0  428M  0 lvm  
sr0                  11:0    1  9.5G  0 rom  /run/media/linuxstudy/CentOS 7 x86_64
```
【VSCode】たまたま見つけたMacBookショートカットキー11選

こんにちは。
Flutterでの開発を始めて2年目の新米エンジニアです。

今回は、自分がVSCodeでの開発中にたまたま打ち間違えて見つけた偶然の産物（ショートカットキー）たちをご紹介します！
※たまたま見つけたとか言いつつ、先輩から教わったものも含まれます。

癖付けるとトラックパッドを使わずに作業ができるようになるので、
作業を効率化したい未経験エンジニアの皆さんはぜひ見ていってください！

## PCスペック
チップ：Apple M1
メモリ：16GB
OSバージョン：13.3.1(a)

## VSCodeバージョン
1.78.2(Univarsal)


## ショートカットキー一覧

## 行ごと範囲選択
### `command + shift + 十字キー`

これは定番ですね！
ただ、これのおかげでいちいちトラックパットに手を移さなくて良くなり、
だいぶ効率的になります！

`shift`と`command`を押しながら、`←`または`→`を押すことで、
現在のカーソルの位置から行の端まで範囲選択できます。

`shift`と`command`を押しながら、`↑`または`↓`を押すことで、
現在のカーソルの位置からファイルの先頭・最後まで範囲選択できます。

## 単語の区切りまで範囲選択
### `option + shift + → or ←`

`shift + command`と違って、`shift + option`を押しながら、
`←`または`→`を押すことで、現在のカーソルの位置から単語の区切りの位置まで範囲選択できます。

## コードの複製
### `option + shift + ↑ or ↓`

`option　+　shift`を押しながら、`↑`または`↓`を押すことで、
カーソルが当たっている行、もしくは選択した範囲のコードを丸ごと複製できます。

`command + C` → `command + V`の操作が一瞬でできちゃいますよって感じです！

メソッドや変数を丸ごとコピーしたい時に便利です！

## 一致する文字の選択
### `command + D`

ファイル内で、選択した文字と一致する文字にカーソルを合わせてくれます。
変数名の修正を一括で行いたいときに便利です。

## ファイル内検索
### `command + F`

これはVSCodeに限らず、サイトとかでも使えますね！

ファイル内の検索バーが表示されます。
あらかじめ、検索したい文字を選択した状態で押すと、
検索バーの表示と同時に、その文字でフォルダ内検索を実行してくれます。

## プロジェクト内検索
### `command +　shift + F`

プロジェクト内の検索バーが表示されます。
`command + F`と同じく、検索機能のショートカットキーですが、
検索範囲がファイル内のみでなく、プロジェクト内で検索ができます！

## ファイル検索
### `command + P`

こちらも検索機能のショートカットキーですが、
ファイルの検索機能が立ち上がります！
プロジェクトが育ってきて、対象のファイルがどの階層にあるかわからなくなってしまった時などにおすすめです！

## エクスプローラ起動
### `command + shift + E`

サイドバーにエクスプローラが表示されます！
この際、エクスプローラ側にカーソルが当たるので、
もう一度`command + shift + E`を押すと、コード側にカーソルが移動してくれます！

## フォルダをすべて閉じる
### エクスプローラが選択されている状態で `command + ←`

エクスプローラ上で開いているフォルダを全て閉じてくれます！

## コードの移動
### `option + ↑ or ↓`

カーソルがあたっている行、もしくは選択された行を丸ごと移動できます！
条件分岐で判定を逆にしたい時によく使います！

## メモを開く
### `command + N`

新規のINIファイルを開くことができます。
作業ログなどのメモを取りたい時に使えます。

癖付けておくと、即座にメモを取り始めたい時とかに
聞き漏らさずにメモを取り始めることができるので、よく使います！

## 終わり

以上！
これいいよ！ってショートカットがあったらコメントください！
オープンソースのサーバーレスフレームワーク Skeet が GraphQL 及び SQL(リレーショナルデータベース) に対応しました

![skeet-graphql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/10990e63-615c-de24-929c-af3e2ba02f00.png)


gm! ELSOUL LABO Co-founderのkishi.solです。

約1年間に渡り開発していた、超速アプリ開発のオープンソースフルスタックサーバーレスフレームワーク "Skeet" ですが、ついに v1 のメジャーリリースを発表することができました。
いつも応援ありがとうございます！

本リリースによって、Skeet において GraphQL 及び SQL(リレーショナルデータベース) を利用しての開発が可能になりました。


## 新しい Next.js (React) + GraphQL API サーバー オプションの追加

![skeet-create-got-graphql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/f86f098b-f2b4-6372-22af-444714a60ce2.png)


Skeet は GCP (Google Cloud) と Firebase 上にフルスタックアプリを構築できるオープンソースのサーバーレスフレームワークです。

API から Web・iOS・Android アプリまでを TypeScript で超速開発することができます。

今回のアップデートにより、GraphQL や SQL(リレーショナルデータベース) を活用したアプリケーションの開発にも対応しました。

![skeet-next-graphql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/ee6b7a3a-6eac-d31a-0f54-78c219a527f5.png)


SQL(リレーショナルデータベース)への対応を通じて、SQL と NoSQL (Firestore) のハイブリッドな開発が可能になりました。
これにより、開発者は両方のデータベースタイプのメリットを取り入れることが可能となります。

リレーショナルデータベースは、関係性を持ったデータを扱うのに優れており、データ検索やトランザクション処理などでの整合性を保つことが容易です。一方で、NoSQL（Firestore など）は、柔軟性が高くスケーラビリティに優れているため、大量のデータや急速なデータ増加に対応するのに適しています。

Skeet のハイブリッド開発環境により、データの関係性が重要なビジネスロジックはリレーショナルデータベースで、ユーザーデータやログなどの大量データは NoSQL でそれぞれ最適に管理することが可能となります。これは、一つのアプリケーション内で最高のパフォーマンスを引き出すための重要な戦略となり得ます。

## データベースと API の可視化: Prisma と Apollo の活用

このアップデートでは、Prisma と Apollo というツールを活用して、データベースや API を UI で可視化できるようになりました。これにより、開発者はコードを書くだけでなく、直感的にデータ構造を理解し、操作することができます。

![prisma-studio.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/363bbb5b-715e-8e1c-f3b0-4f1263a47e92.jpeg)


Prisma (https://www.prisma.io/) は、SQL(リレーショナルデータベース)を TypeScript や JavaScript で簡単に扱うことができる ORM です。Skeet では Prisma を用いてデータベースのスキーマをシンプルかつ柔軟に定義でき、マイグレーションは自動生成され、開発に役立つ TypeScript の型も提供されます。また、Prisma Studio はデータベースを GUI で操作することを可能にし、開発者がデータの操作や確認を容易に行うことができます。

![apollo-console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/d27ee8c1-858e-8a83-7bfb-6b78bedffb50.png)


Apollo (https://www.apollographql.com/) は GraphQL API サーバーを開発するための強力なツールです。Apollo の開発者コンソールでは、GraphQL のスキーマを可視化し、リアルタイムで API のテストを行うことができます。

新しい UI では、使いたい GraphQL Query や Mutation、データの内容をクリックするだけで、実際にフロントエンドで利用する GraphQL を生成できます。

これらのツールの活用により、Skeet は開発者がより直感的かつ効率的にアプリケーションを開発するためのプラットフォームを提供します。このアップデートにより、開発者はさらなる生産性の向上を実現できます。

Skeet は世界中すべてのアプリケーション開発現場の開発・メンテナンスコストを削減、開発者体験を向上させるためにオープンソースとして開発されています。

Skeet を用いた最先端のアプリ開発をぜひ体験してみてください。

Skeet ドキュメント: https://skeet.dev/ja/

Skeet (GitHub): https://github.com/elsoul/skeet-cli
RDS for PostgreSQLの監査ログで取得行数を出力する

こんにちは。インサイトテクノロジーの松尾です！

さて、本記事では RDS for PostgreSQL の監査ログ (pgaudit) で select などが実行された際の取得行数を出力する方法を紹介します！

## PostgreSQL 15 から可能になった pgaudit での取得行数出力

実は PostgreSQL 14 以前の `pgaudit` では、取得行数を監査ログへ出力することができませんでした。そのため監査ログで `select` 文が出力されていても、その `select` 文でどれくらい大量のデータが返されたかを監査ログからは確認できませんでした。

PostgreSQL 15 では `pgaudit` のオプションとして取得行数を出力するオプションが追加されました。ラメータは `pgaudit.log_rows` です。オプションです。デフォルトでは無効になっています。

> pgaudit.log_rows
>
> Specifies that audit logging should include the rows retrieved or affected by a statement. When enabled the rows field will be included after the parameter field.
> 
> The default is off.

参考) https://github.com/pgaudit/pgaudit#pgauditlog_rows

RDS for PostgreSQL で使用する場合には、パラメータグループで設定します。では早速有効にしてみましょう！

![RDS for PostgreSQLでのpgaudit.log_rows設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480312/b7e44ab4-4137-001a-2a82-f7aff715b04c.png)

※ちなみに Aurora PostgreSQL の PostgreSQL 15 互換バージョンでは未対応のようです。

## 取得行数の出力

有効にして出力してみた結果です。
![RDS for PostgreSQLでのpgaudit.log_rows出力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480312/d4e430e1-1d14-96a7-d728-c8c500b0f0b6.png)

説明にあるよう、後ろの方に 14 という取得行数が出力されていますね！

## おわりに

本記事では RDS for PostgreSQL 15 の監査ログ (pgaudit) で select などが実行された際の取得行数を出力する方法を紹介しました。本文中にも記載しましたが、Aurora の PostgreSQL 15 互換バージョンではまだ対応していないようです。対応が待ち遠しいですね！
Playwrightでページ末端にスクロールしたい

ブラウザの表示領域に入らないと描画されない要素が原因でVRTが落ちたので、スクロールしてからスクリーンショット取得する試みをした際のメモです。

## 環境

- Playwright: v1.36.2


## End, Home キーでスクロールする

`page.keyboard.press` で、 `End`, `Home` キー押下してページ末端や先頭へスクロールできます。

```ts
// ページ末端へスクロール
await page.keyboard.press('End')
await page.waitForTimeout(500) // スクロール完了までwait

// ページ先頭へスクロール
await page.keyboard.press('Home')
await page.waitForTimeout(500) // スクロール完了までwait
```

scrollend 発火まで待つやり方がよく分からなかったので雑にwaitしています。

もっといいやり方があったら教えてもらえると嬉しいです！

## 参考

https://playwright.dev/docs/api/class-keyboard#keyboard-press
Modeler FlowでカスタムのSQLクエリーを実行する

Watson Studio on CP4DaaSのModeler FlowでカスタムのSQLクエリーを実行してみます。

* テスト環境
    * CP4DaaS (2023/8/3)
    * Dallas


以下のように、「データ資産インポート」ノードの「データ資産の変更」クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/52f54775-f438-837f-b4e5-57340865d8b5.png)

SQLクエリーを発行したいDBを接続から選びます。そして、いったんどんな表でもよいので一つ表を選びます。ここでは「HELLO」というテーブルを選んでいます。カスタムのSQLクエリーで読みたい表とは全く関係なくて構いません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f1e9e0e0-c0de-790c-8ba2-e433a3ba5c9e.png)

一旦このままプレビューするとHELLOのテーブルの内容が見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/1242ab25-82ab-ea8d-014a-6c47ecb63741.png)

「読み取り方式」で「SELECTステートメント」を選びます。そして、SELECTステートメントを記述し、プレビューします。今度はSELECTステートメントで指定したSELECT文が実行されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/17c6c1eb-fb97-1b85-c89b-fd07431a744c.png)

一旦どんな表でもよいので選ぶというところが、ちょっと面倒なところになります。

#### 参考:データ資産ノード

https://dataplatform.cloud.ibm.com/docs/content/wsd/nodes/dataassetimport.html?locale=ja&audience=wdp&context=cpdaas
【Laravel】Seederを使って初期データを設定する

## はじめに
Laravelには、データベースに初期データを追加するための便利な機能である`Seeder`が組み込まれており、データベースの初期状態を簡単に設定することができます。

## Seederとは
`Seeder`は、Laravelのデータベース初期化機能の一部であり、データベースに初期データを追加するためのクラスです。Seederを使用することで、開発環境やテスト環境のデータベースを簡単に初期化し、必要な初期データを追加することができます。

## Seederを作成する
Laravelでは、artisanコマンドを使用してSeederを作成することができます。以下のコマンドを実行すると、新しいSeederクラスが生成されます。

```
php artisan make:seeder UsersTableSeeder
```
上記の例では、UsersTableSeederという名前の`Seederクラス`が作成されます。Seederクラスは`database/seeders`ディレクトリに作成されます。

作成されたUsersTableSeeder.phpファイルの初期状態は下記のようになっています。

```php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class UsersTableSeede extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}
```
`runメソッド`がSeederを実行した時に処理されるメソッドです。

## 処理を記述する
今回は、Usersテーブルとモデルを用意して初期データを登録してみます。

```php
class UsersTableSeede extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
       User::create([
        'id' => 1,
        'name' => 'tarou',
        'email' => 'hello@example.com',
       ]);

       User::create([
        'id' => 2,
        'name' => 'yamada',
        'email' => 'world@example.com',
       ]);
    }
```

## DatabaseSeederを編集する
作成したSeederファイルは、``DatabaseSeeder.php``から呼び出すようにして使用します。

```php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
    }
}
```
作成したSeederクラスを``call()メソッド``に渡します。

## 実行する
下記のコマンドを実行するとテーブルにデータが登録されます。

```
php artisan db:seed
```

DatabaseSeeder.phpに記述しなくても、特定のSeederだけ実行することができるコマンドもあります。

```
php artisan db:seed --class=UserTableSeeder
```
pytorch + cuda 11.8

pytorch を cuda 11.8 対応でインストールしようとすると

```
Collecting lit (from triton==2.0.0->torch)
  Downloading https://download.pytorch.org/whl/lit-15.0.7.tar.gz (132 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 132.3/132.3 kB 28.3 MB/s eta 0:00:00
  Installing build dependencies ... error
  error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [3 lines of output]
      Looking in indexes: https://download.pytorch.org/whl/cu118
      ERROR: Could not find a version that satisfies the requirement setuptools>=40.8.0 (from versions: none)
      ERROR: No matching distribution found for setuptools>=40.8.0
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
```

みたいな感じでエラーになる。

ちなみに setuptools は 68.0.0 とかが入って、>=40.8.0 の条件満たしてるはずなのに・・・

と、そっちばかり対処していたけど外れ。


```
(py3.11.4) $ pip3 cache purge
(py3.11.4) $ pip3 install lit
(py3.11.4) $ pip3 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
```

という感じで lit だけ先に入れておけば回避できた。


![インストールスクリプト](https://64.media.tumblr.com/f51c1918d9fa116d44d6526bf82db650/a4b0dfeb920dac04-f2/s1280x1920/94375c3eff4e6f147927a4027d46260edaa5ea7c.png)
dumpe2fs

```
[linuxstudy@xxxx ~]$ sudo dumpe2fs -h /dev/sdb1
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   /usbmemory
Last mounted on:          /usbmemory2
Filesystem UUID:          45d9c0a6-98b7-4091-9d13-8e510b7738c8
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         not clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              65536
Block count:              262144
Reserved block count:     13107
Free blocks:              257701
Free inodes:              65524
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      63
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Filesystem created:       Thu Jun 29 20:36:58 2023
Last mount time:          Fri Jul 28 12:55:11 2023
Last write time:          Fri Jul 28 12:55:11 2023
Mount count:              17
Maximum mount count:      -1
Last checked:             Thu Jun 29 20:36:58 2023
Check interval:           0 (<none>)
Lifetime writes:          120 kB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          256
Required extra isize:     28
Desired extra isize:      28
Default directory hash:   half_md4
Directory Hash Seed:      e7c76377-046d-4c27-8f6d-761d1819ae84
```
【Linux】シェル環境のカスタマイズと使用（その１）

- 対話型シェル起動時に読み込まれるファイル
~/.bashrc
/etc/bashrc

- Debian系の代表的な派生ディストリビューション
Ubuntu: デスクトップおよびサーバー向けに人気のあるディストリビューションで、ユーザーフレンドリーな操作性が特徴。

- Debian系のシステムで全ユーザーのbash起動時に共通の処理を実行させるためには、/etc/bash.bashrc ファイルを編集する必要がある。このファイルは、全てのユーザーがbashシェルを起動した際に共通で読み込まれる設定ファイル。

- ログインシェルとしてbashが起動した際に、読み込む設定がない場合には .bash_profile もしくは .bash_login が読み込まれる。これらのファイルはユーザーのホームディレクトリに存在する。

- .bash_profile と .bash_login の両方が存在する場合、.bash_profile が優先して読み込まれる。ただし、.bash_profile が存在しない場合には .bash_login が読み込まれる。これらのファイルはログインシェルが起動した際に、ユーザーの環境や設定をカスタマイズするために利用される。

- ログインシェルとしてbashが起動した際に、読み込む設定がない場合は .bashrc ファイルが読み込まれまない。.bashrc ファイルは非ログインシェル（例えば、新しいターミナルウィンドウを開いた際のシェル）が起動した際に読み込まれる設定ファイル。

※ 補足 
具体的に、以下のような順序でbashが読み込む設定ファイルが決定される。

・ログインシェルが起動した場合:
.bash_profile（または .bash_login）が存在する場合は、そのファイルが読み込まれる。
.bash_profileが存在しない場合で、.bash_loginが存在する場合は、そのファイルが読み込まれる。
1と2のファイルが存在しない場合は、.profileが読み込まれます（ただし、Ubuntuなど一部のディストリビューションではデフォルトで .profile も .bash_profile も読み込まない）。

・非ログインシェルが起動した場合:
.bashrcファイルが存在する場合は、そのファイルが読み込まれる。
このように、ログインシェルでは .bash_profile や .bash_login が読み込まれることが期待され、非ログインシェルでは .bashrc が読み込まれることが期待される。ただし、システムや設定によって動作が変わることもあるため、環境に応じて適切な設定を行うことが重要。

- envコマンドをオプションなしで実行した場合、現在のシェルの環境変数のリストが表示される。

- シェル関数を確認するためのコマンド
```bash:bash
declare -f
---または---
set
---または---
typeset -f
```

```zsh:zsh
functions
---または---
typeset -f
```

- bashのログイン時、環境設定ファイルを読み込む順番
    /etc/profile:
    システム全体の環境変数や共通の設定を定義するためのファイル。システム全体の設定がここで行われる。

    ~/.bash_profile:
    ユーザーごとの個別の設定を定義するためのファイル。ログイン時にこのファイルが存在する場合、他のファイルは読み込まれない。

    ~/.bash_login:
    ~/.bash_profileが存在しない場合、代わりにこのファイルが読み込まれる。

    ~/.profile:
    ~/.bash_profileと~/.bash_loginも存在しない場合、このファイルが読み込まれる。
在宅環境整えた

コロナ禍かからこれまで(2023/6月頃まで)ずっとオフィスに出社していたのですが、
引っ越しをして物理的に遠くなったので在宅するようになって、ようやく在宅ワークの環境を整えました。
整える前は、ソファ＆ダイニングテーブル(?)でやってたので集中力がごっそり削れる感じの環境でした・・ :cry:

前提として、あまりこだわりがない&知識もないので、概ねオフィスで使われていたもの(使ったことがあるもの)を参考に選びました

# 机

買ったもの: ニトリの昇降デスク(マーフィー2 120 DBR),  **手動** での昇降デスク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26310/0badb9b6-8a68-c4c8-7b40-c2c7a21bfb4b.png)

https://www.nitori-net.jp/ec/product/6201500s/

選んだときのこだわりポイント
* 昇降デスク
    * スタンディングは基本しないですが、座ってるときに足組んだりしたいので、細かに調整できるものが良くて昇降機能は必須
    * 電動だと高いしそこまで高機能である必要もない
* 広すぎない/引っ越しのときに引っ越せるか
    * 大きい机を部屋に置くのは厳しいので、狭すぎず大きすぎないサイズ感が良い
    * 引っ越しのときに搬出・搬入できるかは重要ですがニトリを信用しているのでニトリで。(最悪、解体&再度組み立てができるかどうかが重要)

使ってみての感想
* ハンドルを手でくるくる回して昇降させるのですが、別に大変ではない
* 机のサイズは広くないけど、そんなに物おかないので必要十分感あるサイズ
* コードを通す穴が空いてますが、真ん中にあってディスプレイを置くには邪魔になりそう
    * 自分は、ディスプレイアーム買ったので関係なかったでした

# 椅子

買ったもの: オカムラのsylphy
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26310/69fb3503-6301-454f-f529-c2a37be28f2d.png)

- [公式](https://product.okamura.co.jp/ext/DispCate.do?volumeName=00001&lv0=%E3%83%81%E3%82%A7%E3%82%A2%EF%BC%8F%E3%82%BD%E3%83%95%E3%82%A1&lv2=%E3%82%BF%E3%82%B9%E3%82%AF%E3%83%81%E3%82%A7%E3%82%A2&lv3=%E3%82%B7%E3%83%AB%E3%83%95%E3%82%A3%E3%83%BC&itemID=t000100000924)
- [amazon](https://www.amazon.co.jp/gp/product/B00L9TBCWQ/ref=ppx_yo_dt_b_asin_title_o01_s00)

選んだときのこだわりポイントは大きくはなく、以下の理由から職場で使っていたのが個人的に良かったのでそれを買いました(この椅子のはず)
* 姿勢悪く座るタイプだし、業務中はずっと座りっぱになるので、椅子はちゃんとしたものを買いたい
* 真面目に選ぶと実際の座り心地を試してない椅子は買いたくないし、椅子もピンキリで選択肢が多いので、真面目にイチから選ぼうとすると時間がかかる

公式サイトから買うと、いろんなオプションを組み合わせられて良いのですが高いし配送に時間がかかり、
アマゾン基本セットのようなオプションの組み合わせのやつだと数日で届くし値段もだいぶ安くなってよかったでした。

基本セットだとキャスターがフローリングに優しくないやつで、オプションでカスタマイズすると届くのがだいぶ遅くなってしまうので、
別売りの交換キャスターを買いました
https://www.amazon.co.jp/gp/product/B07XQ7D6QX/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1
コクヨのやつを買いましたがちゃんと椅子に装着でき、交換もとても簡単でした :smiley: 

# ディスプレイ

買ったもの: DellのDell 34インチ曲面USB-Cモニター – S3423DWC

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26310/f555b594-e59a-2f82-649b-14600ea22203.png)

* [公式](https://www.dell.com/ja-jp/shop/dell-34%E3%82%A4%E3%83%B3%E3%83%81%E6%9B%B2%E9%9D%A2usb-c%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC-s3423dwc/apd/210-beid/)
* [amazon](https://www.amazon.co.jp/gp/product/B09WNFVJRJ/ref=ppx_yo_dt_b_asin_title_o00_s00)

選んだときのこだわりポイント
* 仕事用にしか使わないのでハイスペックである必要はない
    * ゲームとかはテレビでやる
* 曲面のワイドディスプレイ
    * よくあるサイズのディスプレイ2つ置きも便利ですが、1つだとスッキリして好き
* USB-Cでmacに給電できる
    * macにつなぐケーブルが1本で、ディスプレイに表示できて充電もできるのでとても楽ちん

# モニターアーム

買ったもの: エルゴトロン LX デスク モニターアーム
https://www.amazon.co.jp/gp/product/B07Q8TJ2KL/ref=ppx_yo_dt_b_asin_title_o00_s01

Dell公式のは高かったのと、調べてみるとこれが評判良いらしいので買いました。

https://www.ergotron.com/ja-jp/%E8%A3%BD%E5%93%81/%E8%A3%BD%E5%93%81%E8%A9%B3%E7%B4%B0/60-589
ディスプレイと接続部分は、このカチッとはめればOKなやつを買おうか迷ったのですが買っていないです。
オフィス利用だとあったほうが便利だろうとは思いますが、家での利用だとめったに取り外しをすることないので必要なさそう。

# 感想

全部で結構な値段が飛んでいきましたが、
ソファで開発してたときに比べたら腰が痛くなることなく集中力を取り戻せて快適に仕事できてるのでハッピーです。
【Ruby】空のハッシュに自己代入(+=)したい

# できなかったこと
{}を定義したhashに自己代入演算子を使ったがエラー
```ruby
hash = {}
hash[:hoge] += 1 # => undefined method `+' for nil:NilClass (NoMethodError)
```

# 解決策
ハッシュにデフォルト値0を設定し解決
```ruby
hash = Hash.new(0)
hash[:hoge] += 1 # => 1
```

# Hash.new(0)とは？
ハッシュにはキーに対応する値が存在しない時のデフォルト値を設定できる。`Hash.new(0)`でハッシュを生成した場合、デフォルト値が0になる。
設定がない場合、デフォルト値はnilになる。

```ruby
hash = {} # => {}
hash.default # => nil

hash = Hash.new(0) # => {}
hash.default # => 0
```

# なぜ自己代入演算子(+=)が使えたのか
自己代入演算子を使わない場合を考えて納得。
```ruby
hash[:hoge] = hash[:hoge] + 1
# hash[:hoge] = 0 + 1 (hash[:hoge]が0で評価されるためエラーにならない)

hash[:hoge] = hash[:hoge] + 1
# hash[:hoge] = nil + 1 (hash[:hoge]がnilで評価されるためエラーにならない)
```

# 参考
https://docs.ruby-lang.org/ja/latest/method/Hash/s/new.html
TypeScriptでのSymbolとは？

# TypeScriptでのSymbolについて
TSの勉強中にSymbolの方についてのイメージがわかなかったので記事漁っていたら、以下の記事がわかりやすかったのでほぼ真似の形でメモとして残す。<br />
- [参考元のリンク](https://qiita.com/kono-hiroki/items/c4def53763784de40221)

# シグネチャーが同じで型が違う場合
```diff_tsx
class Car {
    id: string;
    name: string
}

class Human {
    id: string;
    name: string
}

function callHuman(human: Human) {
    console.log(human);
}

const car = new car("1", "GTR");

callHuman(car); // Not Error
```

上記のように型が違っても**シグネチャー**が**一緒なら**受け付けてしまう。
よくない。。。

# シグネチャーが異なり型が違う場合
先ほどは型は違っていましたが、**シグネチャーは一緒**でした。
そうした場合、エラーが**起こらず**動いてしまう。
そのためSymbolを用いてエラー出した。
以下のように記述することでSymbolを用いて先ほどの問題を解決できるらしい。

```diff_tsx
const carType = Symbol();

class Car {
    [carType]: any;
    id: string;
    name: string
}

const humanType = Symbol()

class Human {
    [humanType]: any;
    id: string;
    name: string
}

function callHuman(human: Human) {
    console.log(human);
}

const car = new car("1", "GTR");

callHuman(car); // Error
```

# まとめ
**(ポイント)**
- 型が違う
- シグネチャーが同じ

上記の2点の場合、エラーが起きて欲しいのに起きないことがあるため、そのバグを潰すためにSymbolを使うというイメージができた。
(合っているかはわからないが。。。)
(合っていると思っている。)
<br />
元の記事の人、ありがとうございます！
【AWS】AWS Organizations への既存アカウント招待について

# はじめに
AWSの利用が拡大し、複数のAWSアカウントを管理する必要が生じたタイミングで、AWS Organizations の利用検討、導入するケースがあるかと思います。

そこで行われるのが【AWS Organizations への既存AWSアカウント招待】です。

既存AWSアカウントの招待の手順についてはウェブ上で多くの記事が存在していますが、実施をしてふと気になったことについても記載したいと思います。

# 既存AWSアカウント招待の概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/857ff300-6dcc-4bcb-5e4c-2138443c7edf.png)

左側の `Aアカウント` がAWS Organizations導入前に作成したAWSアカウントです。
右側はAWS Organizationsを活用したマルチAWSアカウント環境です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/4406161c-fc65-637b-395c-260638e0ef68.png)
社内で請求処理の簡素化をしたいという話が上がったため、`Aアカウント` をAWS Organizations配下に移す（招待）方法を実施しました。

# 招待方法（AWS Organizations管理者アカウント上での操作）
既存AWSアカウントの招待についてはとても簡単で、AWS Organizationsの管理アカウント上で`AWS Organizations > AWSアカウント > 招待` から画面右上にある `AWS アカウントを招待`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/c661b17f-88ef-62e4-fea5-cdc549192d37.png)


次の画面で`既存のAWSアカウントを招待` と選択し、招待するAWSアカウントのメールアドレスまたはアカウントIDを入力して、`招待を送信` をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/96c68a48-7866-51bb-d42c-f417f77a4917.png)

# 承認方法（招待されるAWSアカウント上での操作）
招待されるAWSアカウント上で、`AWS Organizations > AWSアカウント > 招待`から画面右上の `招待を承認する` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/90190039-507d-644d-49b1-c873c7f24cb3.png)


# ふとした疑問が・・・
上記の流れで招待を行ない、Aアカウントを AWS Organizations 配下のメンバーアカウントにすることが出来ました。
今後のAWS利用料の請求は、一括請求機能で AWS Organizations の管理アカウントの支払い（正確には管理アカウントに登録された支払方法での支払い）となりました。

そこでふとした疑問が浮かびます。

「招待前にメンバーアカウント登録されていた支払い情報はどうなってるんだろう・・・？」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/7684f84f-7d92-7224-5f2e-8eaa39b2ed6e.png)

招待されたメンバーアカウントはこれまでクレジットカード払いでの支払いとしていたため、
もしその設定が残っている場合、その情報を念のために消しておきたいと思ったからでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/7817213b-3524-f7ac-63e1-cec6911e1ef9.png)

マネジメントコンソールで確認すると支払い方法は残っている状態で、削除も出来ないという状況でした。


# AWSサポートに聞いてみた
今回の事象についてAWSサポートへ問い合わせてみました。
下記に記載するのはAWSサポートとのやり取りの要約です。


>【質問事項（要約）】
>Q1. Oraginzation招待を承認したアカウントにて、支払い情報としてクレジットカード情報がデフォルト支払い先として登録されたままとなっているが、この状態で AWS Organizations 側に請求は統合される認識であっているか
>
>Q2. 上記状態でクレジットカード情報を削除したいが、その方法/必要な手続きを教えてほしい
>
>【AWSサポートからの回答（要約）】
>A1. Q1 については認識通り、今後のAWS利用料はOrganizationsに請求がいく。
>A2. Q2 については、Organizations配下のメンバーアカウントであっても、1つ以上の有効な支払方法の登録が必須となるため、削除はできない。

# 回答からまた疑問が・・・
>A2. Q2 については、Organizations配下のメンバーアカウントであっても、1つ以上の有効な支払方法の登録が必須となるため、削除はできない。

この回答を見て「おや？」となりました。
これまでAWS Organizations配下に新規でAWSアカウント（メンバーアカウント）を作成した際に支払い方法を意識して登録をしたことがなかったからです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/fc4d6bd0-d487-5da1-3286-79871312db64.png)

気になったので、以前 AWS Organizations 配下に新規作成したAWSアカウント（メンバーアカウント）の支払い方法を見ると、以下のメッセージが表示されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822205/825b0818-461c-42b4-2ac9-f7144d0ebb00.png)

新規作成の場合についてはデフォルトの支払い設定は登録されない状況になるようです。

# 最後に
冒頭にも記載しましたが、既存AWSアカウント招待についてはウェブ上で多くの記事が公開されていますが、支払い方法については触れられているものがなかったことと、AWS Organizations を中心にAWSアカウント管理をしていると意識しない部分で、この仕様の発見が面白いと感じたので記事にしてみました。

皆様も確認してみてください。
サクラエディタで該当行マークを外す

# 概要

下記をやると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/548f17af-b1f9-6d78-bfdd-82c340fed25c.png)

行番号の色が変わる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ccc5d550-3b16-229b-148d-ef354d5b6657.png)

この変わった行番号の色を元に戻したい。

『変わった行番号の色』のやっかいなところは、ファイルを閉じて再度開いても引き継がれてしまう点。

# やり方

1. 検索
1. ブックマーク
1. ブックマークの全解除

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c87e92b4-7ea0-2284-e428-d8766e670666.png)

# 参考サイトさん

https://boukenki.info/sakuraeditor-gaitougyou-mark-kesu-houhou/

# バージョン

Microsoft Windows [Version 10.0.19045.3271]
サクラエディタ   v2.4.1.2849 32bit (tag v2.4.1)

TODO:ファイルを閉じたらブックマークを全解除する設定があるかどうか調べる。
【Python】２つの数値の合計

# 実装内容
 与えられた整数の配列 array から2つの数を選んで合計を targetSum とする組み合わせを見つける関数 twoNumberSum を作る。

# 実装
```python:two_number_sum.py
def twoNumberSum(array, targetSum):
    storage = set(num for num in array)

    for num in array:
        target = targetSum - num
        if target in storage and target is not num:
            return [num, target]

    return []

# テスト
if __name__ == "__main__":
    array = [3, 5, -4, 8, 11, 1, -1, 6]
    targetSum = 10
    print(twoNumberSum(array, targetSum))
```

# 解説
- twoNumberSum(array, targetSum):
array: 数値のリスト（整数の配列）。
targetSum: 目標の合計値（整数）。

- storage = set(num for num in array):
arrayの要素を集合 (set) に格納する。集合を使うことで、後で特定の要素を高速に検索できるようになる。

- for num in array:
配列 array の各要素 num に対して、以下の処理を繰り返す。

- target = targetSum - num:
num と targetSum の差を計算し、その結果を target に代入する。

- if target in storage and target is not num:
target が storage (配列 array の要素の集合) に存在し、かつ target が num と異なる場合に以下の処理を行う。

- return [num, target]:
num と target を含む2つの数のリストを返す。この2つの数の合計は targetSum となる。

- return []:
関数がループを終了しても2つの数の組み合わせが見つからなかった場合、空のリスト [] を返す。
【Photoshopで簡単！】画像の背景を伸ばす方法

画像の背景がもう少し欲しいという時に、Photoshopで簡単に背景を伸ばす方法について紹介します。
![スクリーンショット 2023-08-03 18.09.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/c3cb74b1-d23a-9be1-c4fd-2a7f5b7e1dfa.png)


# Photoshopで画像を開く
まずPhotoshopで背景を伸ばしたい画像を開きます。
![スクリーンショット 2023-08-03 15.49.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/6ecb92c5-273f-4f39-b840-b009ce6958da.png)

# 背景レイヤーから通常レイヤーに変更
以下の画像のように背景レイヤーになっている場合は、レイヤーパネル上でレイヤーをダブルクリックして背景から通常のレイヤーに変更しておきます。
![スクリーンショット 2023-08-03 16.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/c3e12139-96ea-3cc9-6d63-7480265cf6ca.png)
![スクリーンショット 2023-08-03 16.06.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/19e9e3dd-e028-401a-ff54-84162a8334b3.png)
![スクリーンショット 2023-08-03 16.08.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/4f22a9d7-5018-39b3-cd83-a4c581567ee5.png)
# 伸ばしたい領域設定
#### ①イメージ→カンバサイズを選択
![スクリーンショット 2023-09-05 18.47.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/4e79fd38-30d4-1c6b-9d06-3536cff81b47.png)
#### ②「変更後のファイルサイズ」を設定
幅・高さ：伸ばしたい分の大きさを指定します。
基準位置：どの方向に伸ばしたいのかを指定します。
![スクリーンショット 2023-08-03 16.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/bf8ef74f-9dc1-9490-9be8-82b840f0ae0b.png)

#### ③OKを押下で画像のように指定した分の大きさ・方向で設定できます。
![スクリーンショット 2023-08-03 16.17.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/7b3d5403-b25c-84f6-9dc0-d688cfec7bc8.png)

# 領域を塗りつぶす
#### ①自動選択ツールで先ほど作成した、引き伸ばしたい部分を選択
![スクリーンショット 2023-08-03 16.29.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/e9a5bad3-9d36-e404-51b4-ea5f59d7f399.png)

#### ②編集→コンテンツに応じた塗りつぶしを選択します
![スクリーンショット 2023-08-03 17.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/0b2e30b9-73de-680c-348e-326bbf1881d4.png)

#### ③プレビューで塗りつぶした状態を確認
![スクリーンショット 2023-08-03 17.28.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/2b176da2-5560-4ba4-650c-584de16a0bad.png)

#### ④OKボタンで伸ばしたい領域分を画像に合わせて塗りつぶしてくれます。
![スクリーンショット 2023-08-03 17.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524155/65536531-2916-3dfe-27a8-8afe50e512d2.png)

以上、Photoshopで画像の背景を伸ばす方法を説明させていただきました。
覚えてしまえば簡単な作業なので、ぜひ覚えておきたい方法です。
Bitriseで、過去のアーカイブビルドにアクセスする

# 概要

Bitriseは、執筆時点では過去200日経過したビルドはBitriseのUIから表示されることはありません。
これで困るのが過去にリリースしていたアプリを再度動かすとなった時です。
ここでは、過去のアーカイブにアクセスする手順をご紹介します。


## 公式

公式の情報です。

https://devcenter.bitrise.io/en/api/managing-an-app-s-builds.html#listing-the-archived-builds-of-an-app

公式の情報にも、

> By default, you can only view builds that aren't older than 200 days. This is true for most API endpoints, too. 

とあります。しかし、その続きに

> However, you can also view older, archived builds by calling the GET /apps/{app-slug}/archived-builds endpoint.

と、archived-builds APIがあることを説明しています。
こちらを利用してアーカイブ情報にアクセスします。

### curlでのAPIアクセスしてアーカイブ情報を取得

```
curl -X 'GET' \
  'https://api.bitrise.io/v0.1/apps/APP-SLUG/archived-builds?after=1609459200&before=1640995200' \
  -H 'accept: application/json' \
  -H 'Authorization: THE_ACCESS_TOKEN'
```

afterやbeforeの値を目的にあった値に調整して、上記のコマンドを実行します。
`APP-SLUG` に関しては、アーカイブを取得したいBitrise上のアプリのURL `https://app.bitrise.io/app/○○` の○○に示される部分、
Authorizationの `THE_ACCESS_TOKEN` は、BitriseのウェブサイトのProfile settingsからsecurityを選択し、パーソナルアクセストークンを作成して設定してください。

https://devcenter.bitrise.io/ja/accounts/personal-access-tokens.html#パーソナルアクセストークンの作成

このcurlが成功した結果、以下のようなjsonが返ってきます。(データは削ったり加工したり省略しています)

```
{
  "data": [
    {
      "started_on_worker_at": "2021-10-28T09:40:05Z",
      "finished_at": "2021-10-28T10:14:59Z",
      "slug": "00000000-0000-0000-0000-000000000000",
      "status": 1,
      "status_text": "success",
      "abort_reason": "",
      "branch": "master",
      "build_number": 1,
      "commit_hash": "",
      "commit_message": "",
      "tag": "",
      "triggered_workflow": "release",
      "triggered_by": "webhook",
      "machine_type_id": "",
      "stack_identifier": "osx-xcode-13.0.x",
      "original_build_params": null,
      "pipeline_workflow_id": "00000000-0000-0000-0000-000000000000",
      "pull_request_id": 0,
      "pull_request_target_branch": "",
      "pull_request_view_url": "",
      "credit_cost": 0,
      "build_artifacts": []
    }
  ]
}
```

## ビルドページにアクセスする

先ほど取得したデータで重要なのが `slug` という値で、目的とするビルドのslug値を元にURLアクセスします。
今回の場合、slug値は `00000000-0000-0000-0000-000000000000` なので、
`https://app.bitrise.io/build/00000000-0000-0000-0000-000000000000` というURLにアクセスすることで、無事目的のビルドのページにアクセスできるはずです。
スッキリわかるJava入門 第３版を読んでみて- part４ -配列

# はじめに
こんにちは(・ω・）ﾉ
今回は配列について学びました！

## 第４章　配列
### 1.配列のメリット
データ構造...一定のルールに従ってデータを格納する形式
代表的なもの __配列__

配列とは...
　同一種類の複数データを並び順で格納するデータ構造
＜イメージ＞
箱が連続して並んでいる
[0][1][2][3][4][5][6][7]

箱の一つひとつを __要素__
配列の各要素には同一種類のデータしか格納できない
　⇨「１つ目には数値、２つ目には文字列」のようなことはダメ🙅

各要素にある番号を __添え字__
添え字は0から始まる決まりになっている

### 2.配列の書き方
配列の作成には以下の２ステップが必要
Step1.配列変数の宣言
　`要素の型[]　配列変数名`
Step2.要素の作成と代入
　`配列変数名 ＝ new　要素の型[要素数]`
上記のStep1,2を同時に行うことも可能
例：`int []scores = new int[5];`

配列の要素数の取得
　`配列変数名.length`
配列の利用方法
`scores[1]=10;`のように添え字を用いて利用する
※添え字は「０」からなので「１」は先頭から２番目に代入されることに注意

配列の初期化
変数の値を取り出す前には必ず値を代入して初期化する必要がある
⇨コンパイルエラーとなってしまうから

しかし...
配列の要素は自動的に初期化されるためコンパイルエラーにならない
要素がどのような値で初期化されるかは型によって決まる
・int,doubleなどの数値...０
・boolean型...false
・String型...null

配列作成、初期化の省略記法
1.`要素の型[]配列変数名=new要素の型[]{値1,値２,値３,...};`
2.`要素の型[]配列変数名={値１,値２,値３,...};`

### 3.配列と例外
範囲外要素の利用による例外の発生
　ArrayIndexOutOfBoundsException
　上記エラー発生
### 4.配列のデータをまとめて扱う
for文と組み合わせて使うことができる
```
for(int i = 0;i < 配列変数名.length; i++){
配列変数名　[i]を使った処理
}
```
拡張for文
```
for(要素の型　任意の変数名　:　配列変数名){
︙
}
```
### 5.配列の舞台裏
```
public class Main{
    public static void main(String[] args){
        int[] arrayA = {1,2,3};
        int[] arrayB;
        arrayB = arrayA;
        arrayB[0] = 100;
        System.out.println(arrayA[0]);
    }
}
```
上記の結果は1ではなく100！？
なんで...?

コンピュータはデータをメモリに記録
⇨最初の要素のアドレスが代入される

:sparkles:int[] scores = new int[5]を実行した際のメモリの様子
1.int型の要素を5つ持つ配列がメモリ上に作成される
2.int[]型の配列変数scoresがメモリ上に作成される

:sparkles:プログラムからscores[n]と指定されたら
1.scoresから番地を取り出し配列を見つける
2.見つけた配列の先頭要素からn個後ろの要素の区画を読み書きする

配列を指し示す動作...　__参照__
メモリ上の番地を代入する変数... __参照型変数__
intやboolean... __基本型変数__

上記のことから
arryBでコピーした時にarrayAの先頭番地もコピーしている
⇨変数arrayBは変数arrayAと同じ配列を参照している
arrayB[0] = 100;とarrayA[0] = 100;は同じ

だからarrayA[0]は100が出てくる

### 6.配列の後片付け
__ガベージコレクション__ 
実行中のプログラムが生み出したメモリ上のゴミを自動的に片付ける

__null__ ...何もない
配列を意図的に参照されないようにする

:sparkles:nullとは
1.int[]型などの参照型変数に代入するとその変数は何も参照しなくなる
2.int型などの基本型変数は代入できない

NullPointerException
nullが格納されている配列変数を利用しようとすると発生する
### 7.多次元の配列
これまでの配列は1次元配列
1次元配列を元に縦の並びを追加したもの... ２次元配列

2次元配列の宣言
　`要素の型[][]配列変数名　＝　new　要素の型[行数][列数];`

2次元配列の要素の利用
　`配列変数名[行の添え字][列の添え字]`

## まとめ
配列の添木が０から始まることを気をつけたいなと思いました！
配列の舞台裏の例題をはじめに見た時はarrayA[0]は１だと思ってましたが舞台裏のメモリではあんな風に動いていたんですね ((¯ω¯*))ﾌﾑﾌﾑ
裏の動きをしっかり理解できたのはよかったと思いました！

今回もありがとうございました！
ではまた〜　＊˙︶˙＊)ﾉ"