OmniAICreator/Qiita-1.07M huggingface dataset:
「物件への投げ銭」機能をPaypalのStandard Checkoutを使って実装したのでメモ

[プレイスオブ](https://placeof.app)という物件所有者が物件の細かいスペック等を投稿できるサービスを個人で開発しています。最近「物件への投げ銭」機能をPayPalのStandard Checkoutを使って実装したのですが、PayPalを使った記事があまりなかったので少しまとめてみました。

# 何故PayPalを使ったのか
以前からYouTubeやSNSで物件情報を発信している方が増えているのが気になっていました。
個々のクリエイターをサポートするようなサービスがある一方で、物件をサポートするようなサービスがなかったので、作ってみたら面白いかなという感じです。
ただ、日本よりもアメリカや他国の方がニーズがありそうで、特にアメリカは住宅不動産手数料に関して集団訴訟が20件程度あったり和解案が先月電撃的にまとまったと思えば司法省が独禁法の調査をするかもみたいな訴訟祭りのような状態になっており、今後の状況次第ではアメリカに送金できるような手段があった方が良いかなと思いPayPalを選択しました。

# 実装のポイント
PayPalのAPIにはStandard CheckoutとAdvanced Checkoutの２つの種類がありました。今回はひとまず[Standard Checkout](https://developer.paypal.com/docs/checkout/standard/integrate/)の方を選択しました。Standard Checkoutだと決済フォームがカスタマイズ出来ないなどのデメリットがありますが、試しに実装するにはこちらで良いかと思います。
## Reactを使ったコードサンプル
いろいろなコードサンプルがありましたが、基本的にはこちらのソースコードが一番良かったです:
https://github.com/paypaldev/PayPal-React-FullStack-Standard-Checkout-Sample
## 追加実装ポイント
### 外部IDの保持
購入された商品のidなどは、reference_idかcustom_idで保持しました。
https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit
### 不必要な住所欄の削除
shipping_preferenceにNO_SHIPPINGを追加する必要がありました。
https://developer.paypal.com/docs/api/orders/v2/#definition-application_context
### Idempotency
https://developer.paypal.com/api/rest/reference/idempotency/　を参考に `PayPal-Request-Id`　を適宜追加しました。
### Webhook
受け取るWebhookの設定やURLはダッシュボードで行えました。イベント一覧は　https://developer.paypal.com/api/rest/webhooks/event-names/
にあります。

## ハマったところ
### サンドボックスにアクセスできない
開発中にサンドボックス環境にアクセスできなくなることが結構頻発しました。理由は不明ですが、sandbox環境のダッシュボードに再ログインしたりすると治ったりしました。
### そもそもログイン出来ない
sandbox環境のダッシュボードにログインができなくなることも結構頻発しました。Cookieを削除すると基本的には再ログイン出来ました。たまにローカルストレージも削除しました。
### エラーが出せない
[テストカード](https://developer.paypal.com/tools/sandbox/card-testing/) のエラーが全然出せなくて数時間詰まりました。。。下記の画像のTriggerにある名前をFirst Nameか名前全体に入力するとひとまずエラーが発生しました。
First NameとSur Nameとかに分割したりしたらエラーが出ないです。また、フォームの国によってFirst NameとSur Nameの順番が違うのでそこも注意する必要があります。
![](https://storage.googleapis.com/zenn-user-upload/cd7b12902c5f-20240422.png)
### エラーが良く分からない
上記のエラーがすべて"INSTRUMENT_DECLINED"になり、[フォームの再起動](https://github.com/paypaldev/PayPal-React-FullStack-Standard-Checkout-Sample/blob/main/client/App.jsx#L86)が走り、PayPalの良く分からないフォームが再出現します。ドキュメントは見当たらなかったですが、多分、これはStandard Checkoutの仕様かと思います。
### webhookのverifyのやり方が良く分からない
正直webhookのverifyの仕方が良く分かっていないです。[こちら](https://developer.paypal.com/community/blog/paypal-has-updated-its-webhook-verification-endpoint/) にある通り "transmission_id"等7つのパラメーターを[verify用のendpoint](https://developer.paypal.com/docs/api/webhooks/v1/#verify-webhook-signature_post)に送信しているのですが。。。
ちなみに、sandbox環境だとverify出来なさそうで、本番でしか確認出来ないのではないかと思われます。
参考:
https://zenn.dev/code_diver/articles/9f625c73ca7873
### captureしてもwebhookは使ったほうが良いのか
https://github.com/paypaldev/PayPal-React-FullStack-Standard-Checkout-Sample/blob/main/client/App.jsx#L63　
でonApproveされたあとにサーバー側でcaptureしますが、結局webhookは使ったほうが良いのかほとんど必要ないのか良く分からず。capture出来たけど、数時間後にやっぱり出来なかったみたいなことが多発するならばwebhookはしっかり調査したいと思います。
# おわりに
ひとまずStandard Checkoutの使い方はこんな感じかと思います。

なお、この機能の使い方はこちらをご参照下さい:
https://note.com/placeof/n/n62180aef7689
Pythonの備忘録 (超初心者) <if文>

僕がPythonの使い方をド忘れした時のための備忘録を作成します。

Pythonのif文では制御構造を使用して、同じコードブロックを正誤判定を実行することができる
![スクリーンショット 2024-04-22 14.24.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575336/19c43b75-d615-a729-5d44-3510f747cffc.png)

:::note warn
あくまで上記はイメージです
厳密さを必要とする場合は下記LINKを参照してください。
https://www.python.org/
:::
今回はif文の使い方の基本を書き下ろしておきます。

<!-- open属性あり -->
<details open><summary>if文を設定</summary>

```python
if 5/2 = 2.5
print("5は2で割った時2.5になります")
```
:::note alert
エラー
if 5/2 = 2.5
           ^
SyntaxError: invalid syntax
:::
構文エラー：無効な構文
と構文エラーになる

<details open><summary>if文を設定(修正版)</summary>

```python
if 5/2 == 2.5:
    print("5は2で割った時2.5になります")
```
:::note info
出力
5は2で割った時2.5になります
:::

```python
if 5/2 > 2.5:
    print("5は2で割った時2.5になります")
```
:::note info
出力
:::
5/2 > 2.5ではないため、処理が行われない

```python
if 5/2 > 2.5:
    print("5は2で割った時2.5より大きくなります")
    else: print("5は2で割った時2.5以下です")
```
:::note alert
エラー
    else: print("5は2で割った時2.5以下です")
    ^
SyntaxError: invalid syntax
:::
elseの位置がおかしい

```python
if 5/2 > 2.5:
    print("5は2で割った時2.5より大きくなります")
else: print("5は2で割った時2.5以下です")
```
:::note info
出力
5は2で割った時2.5以下です
:::
elseはifと同じレベルでなければいけない
※インデントを合わせる

### B問題(1-1)
条件1: 3で割り切れるときはfizzと出力する
条件2: 5で割り切れるときはbuzzと出力する
条件3: 15で割り切れるときはfizz-buzzと出力する(条件1かつ条件２)
条件4: それ以外はその数字を出力する

#### step1
とりあえず30まで出力してみる
```python
for i in range (31):
    print(i)
```
:::note info
出力
<details><summary>出力結果</summary>
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</details>
:::

#### step2
条件1: 3で割り切れるときはfizzと出力する
上記を条件分岐
```python
for i in range (31):
    if i % 3 == 0:
        print("fizz")
    else:
        print(i)
```
:::note info
出力
<details><summary>出力結果</summary>
fizz
1
2
fizz
4
5
fizz
7
8
fizz
10
11
fizz
13
14
fizz
16
17
fizz
19
20
fizz
22
23
fizz
25
26
fizz
28
29
fizz
</details>
:::

#### step3
条件2: 5で割り切れるときはfizzと出力する
上記を条件分岐
```python
for i in range (31):
    if i % 5 == 0:
        print("buzz")
    else:
        print(i)
```
:::note info
出力
<details><summary>出力結果</summary>
buzz
1
2
3
4
buzz
6
7
8
9
buzz
11
12
13
14
buzz
16
17
18
19
buzz
21
22
23
24
buzz
26
27
28
29
buzz
</details>
:::

#### step4
条件3: 15で割り切れるときはfizz-buzzと出力する(条件1かつ条件２)
上記を条件分岐
```python
for i in range (31):
    if i % 15 == 0:
        print("fizz-buzz")
    else:
        print(i)
```
:::note info
出力
<details><summary>出力結果</summary>
fizz-buzz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
fizz-buzz
16
17
18
19
20
21
22
23
24
25
26
27
28
29
fizz-buzz
</details>
:::

#### step5
条件4: それ以外はその数字を出力する
上記を条件分岐
```python
for i in range (31):
    if i % 15 == 0:
        print("fizz-buzz")
    elif i % 5 == 0:
        print("buzz")
    elif i % 3 == 0:
        print("fizz")
    else:
        print(i)
```
:::note info
出力
<details><summary>出力結果</summary>
fizz-buzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizz-buzz
16
17
fizz
19
buzz
fizz
22
23
fizz
buzz
26
fizz
28
29
fizz-buzz
</details>
:::
pythonでの簡単な条件分岐を書き下した。
他にもいい例があれば追記します。
AWS SAA（ソリューションアーキテクトアソシエイト）合格体験記

# なぜ取得したか
以前CLFを取得したので、次の目標としてSAAを指定したため。
そもそもCLFの学習をSAAの問題集で行っていたため、そのうち受験はするつもりでいた。
ちょうどAWSで「再受験無料キャンペーン」を実施していたため、釣られてホイホイとバウチャーを利用した。

# SAA（ソリューションアーキテクトアソシエイト）に対する所感
CLFと違い、各サービスについての問題と言うよりはベストプラクティスを求めるタイプの問題が出題される。
「絶対正解じゃないな」と思うような選択肢が半分は出るので、だいたい2択までは絞れる印象を受けた。
その2択からよりベストな方法を選べるかどうかが課題と感じた。

# 勉強方法
Udemyの講座動画を見る
Ping-tでSAA（ソリューションアーキテクトアソシエイト）の問題を解く
AWS認定資格 無料WEB問題集＆徹底解説 で問題を解く

# 勉強時間
CLF受験のあと、累計で数時間復習したくらい。
CLFの体験記には「次はもうちょっと勉強しよう」と書いたが、結局やらなかった。
（実際、再受験無料キャンペーンの再受験を本命だと考えていたため）
CLF自体、SAAの想定で学習して受験したため、実質勉強時間は累計25時間ほどだろうか。
基本情報取得レベルの下地があれば、そこまで難しくは無いと感じる。

# 今後
次は何を取ろうか考え中。
DVAかもしれないしSOAかもしれない。
SCSあたりもいいかもだし、ジャンルを変えてCCNAかもしれない。
Docker環境上のNext.jsをhttpsに対応させる

# 概要
本記事では、Docker環境上におけるNext.jsのオプション`--experimental-https`が使用できない方向けの回避処置の解説になります。

## 弊環境
- ホスト：Ubuntu22.04
- Docker : 26.0.2
- Image : node:21.7.3-bullseye

## 本題
:::note
先行事項
コンテナにrootユーザでは入ればおそらく普通に動きます。（未実証）
ですが、nodeのオフィシャルでは「コンテナはrootで動かすな！nodeユーザ使え」と言われてるので、大人しくそれに従いましょう。
:::

:::note warn
追記（執筆中）
エラーコードを再度確認しましたらmkcertが見つからずエラーを起こしてました。
暫定対処としてこちらをインストールしてもおそらく動くかと思います。
:::

各種鍵を生成します
```console
$ openssl genssl genrsa 2048 > server.key
$ openssl req -new -key server.key > server.csr
```
csr生成時に様々聞かれますが、オレオレ証明書であれば別段記入はいりません。

署名を行います
```console
$ openssl x509 -in server.csr -days 3650 -req -signkey server.key > server.crt
```

以上の工程を終えると`.key .csr .crt`の３種のファイルができるので、
```
.
├── my-app/
│ 　　　　└── package.json
├── server.crt
├── server.csr
└── server.key
```
のように設置してください。

その後package.jsonを改変して終了です。
```json:package.json
"scripts": {
    "dev": "next dev --experimental-https --experimental-https-key ../server.key --experimental-https-cert ../server.crt",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }
```

next.jsのプロジェクトルートに戻り`npm run dev`を実行して確認してください。
お疲れ様でした。

参考にさせて頂いた物
---

https://qiita.com/miyuki_samitani/items/b19aa5ac3b3c6e312bd5


https://zenn.dev/ikuma/articles/how-next-do-https-at-local
一つ一つ解説しながらUbuntu22.04にphp-fpm8.3をインストールする

ubuntuにphp-fpmを利用してphpをインストールするとき、`apt install php-fpm`を実行するとphp8.1がインストールされてしまうため、php8.3をインストールする手順をメモしました。

## バージョン情報

- Ubuntu(22.04.4 LTS)
- PHP(8.3.6)

## リポジトリをアップデート

```リモート
sudo apt update
sudo apt upgrade -y
```

* `apt update`
    * アップデート可能なパッケージのリストを更新する。例えば、インストール当時はphp8.0までしかなかったけど、このコマンドを実行することでphp8.3までインストールできる状態になる。**インストールできる状態になるだけで、インストールはしない**
* `apt upgrade`
    * 実際にインストールされているパッケージのバージョンアップを行う。update でインストール可能な最新版を取得して、upgrade で取得した最新版をインストールする
* `-y`
    * apt コマンドを実行したときに「なにか聞かれたときに、全部yesで答えるから処理を止めないでね」オプション

## Ondrej sury PPA リポジトリを追加

```リモート
sudo add-apt-repository ppa:ondrej/php
```

* Ondrej sury PPA
    * このリポジトリを利用することで、php8.3をインストールすることができる。なお**Ubuntu非公式**

## 更新を反映させるため、リポジトリを再びアップデート

```リモート
sudo apt update
```

## php8.3-fpm をインストール

```リモート
sudo apt -y install php8.3-fpm
```

## バージョン確認

```リモート
php -v
```

phpのバージョン情報が表示される

```
PHP 8.3.6 (cli) (built: Apr 11 2024 20:23:38) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.6, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies
```

Ubuntu22.04にphp8.3がインストールできた🙌
RailsでBootstrapを使ってフラッシュメッセージを表示し、自動で消す方法

## はじめに
Railsのアプリケーションにおいて、ユーザー操作に対するフィードバックは非常に重要です。この記事では、Bootstrapを利用してフラッシュメッセージをスタイリッシュに表示し、JavaScriptを使用して一定時間後に自動的に消去する方法を紹介します。

### 必要なもの
- Rails 6.0 以上
- Bootstrap 4.5.2
- Webpacker（JavaScriptの管理に）

## 実装手順

### 1. Bootstrapのセットアップ
まずは、BootstrapをRailsプロジェクトに導入します。以下のコマンドでBootstrapとその依存ライブラリをインストールします。

```bash
yarn add bootstrap@4.5.2 jquery popper.js
```

### 2. スタイルシートの設定
`app/assets/stylesheets/application.css` を `application.scss` にリネームし、Bootstrapのスタイルシートをインポートします。

```scss
@import 'bootstrap';
```

### 3. ヘルパーメソッドの定義
`app/helpers/application_helper.rb` にフラッシュメッセージのためのBootstrapクラスを割り当てるヘルパーメソッドを定義します。

```ruby
module ApplicationHelper
  def bootstrap_class_for_flash(flash_type)
    case flash_type.to_sym
    when :notice then 'alert-info'
    when :success then 'alert-success'
    when :error then 'alert-danger'
    when :alert then 'alert-warning'
    end
  end
end
```

### 4. フラッシュメッセージのパーシャル
`app/views/layouts/_notice.html.erb` にフラッシュメッセージのパーシャルを作成します。このパーシャルでは、JavaScriptを使ってフェードアウト後にメッセージをDOMから削除します。

```erb
<% flash.each do |type, message| %>
  <% if message.present? %>
    <div class="container mt-4">
      <div class="alert <%= bootstrap_class_for_flash(type) %> alert-dismissible fade show" role="alert">
        <%= message %>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
    </div>
  <% end %>
<% end %>

<style>
  @keyframes fadeOut {
    to {
      opacity: 0;
      height: 0;
      padding-top: 0;
      padding-bottom: 0;
    }
  }

  .fadeOut {
    animation: fadeOut 5s forwards; /* 5秒間でフェードアウト */
    animation-delay: 5s; /* 表示後5秒でアニメーション開始 */
    overflow: hidden; /* 高さが0になる際に内容がはみ出さないようにする */
  }
</style>
```

### 5. メインレイアウトにパーシャルを含める
`app/views/layouts/application.html.erb` で、作成したパーシャルを読み込みます。

```erb
<!DOCTYPE html>
<html>
<head>
  <title>ABCアプリケーション</title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_importmap_tags %>
</head>
<body>
  <%= render 'layouts/notice' %>
  <%= render 'layouts/sidebar' %>
  <%= yield %>


</body>
</html>
```

## まとめ
この方法で、RailsアプリケーションにBootstrapを使った美しいフラッシュメッセージを実装できます。さらに、JavaScriptを使用してメッセージが一定時間後に自動的に消えるようにすることで、ユーザー体験を向上させることが可能です。
Pythonの備忘録 (超初心者) <繰り返し処理>

僕がPythonの使い方をド忘れした時のための備忘録を作成します。

PythonのLoopでは制御構造を使用して、同じコードブロックを繰り返し実行することができる
![スクリーンショット 2024-04-22 12.03.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575336/e19bf248-960a-7689-0026-132c19021b3a.png)

:::note warn
あくまで上記はイメージです
厳密さを必要とする場合は下記LINKを参照してください。
https://www.python.org/
:::
今回はfor loopの使い方の基本を書き下ろしておきます。

<!-- open属性あり -->
<details open><summary>for loopを設定</summary>

```python
for i in range (10):
    print(i)
```
:::note info
出力
0
1
2
3
4
5
6
7
8
9
:::
range()で指定した回数だけ繰り返し処理を行っている

<details open><summary>間隔をあけてLoop</summary>

```python
for i in range(1, 10, 2):
    print(i)
```
:::note info
出力
1
3
5
7
9
:::
range(始値, 終値, 間隔値)でloopしていることがわかる

<details open><summary>間隔をあけてLoop</summary>

```python
for i in range(1, 10, 2):
print(i)
```
:::note alert
エラー
print(i)
    ^
IndentationError: expected an indented block
:::
Indentの位置がおかしいとエラーが出る
for文の後で繰り返し処置する場合はindentをずらさないといけない。


### A問題 (1-1)

```python
list = []

for i in range (10):
    list.append(i)
    print(list)
```
:::note info
出力
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
:::
listへの要素追加と表示を併せて確認すると上記のようになる。

### B問題 (1-2)

```python
list = []

for i in range (3):
    for j in range (3):
        list.append(i)
        list.append(j)
        print(list)
```
:::note info
出力
[0, 0]
[0, 0, 0, 1]
[0, 0, 0, 1, 0, 2]
[0, 0, 0, 1, 0, 2, 1, 0]
[0, 0, 0, 1, 0, 2, 1, 0, 1, 1]
[0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 1, 2]
[0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 1, 2, 2, 0]
[0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 1, 2, 2, 0, 2, 1]
[0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 1, 2, 2, 0, 2, 1, 2, 2]
:::
loop内にloopを組み込むこともできる

### B問題 (1-3)

```python
list = [1, 2, 3, 4, 5]

for item in list:
    print(item)
```
:::note info
出力
1
2
3
4
5
:::
listを利用してloopを組むこともできる
時間・回数駆動開発 タスクの効率化と継続的改善へのアプローチ

# 概要

こんにちは、ゆめみに新卒フロントエンドエンジニアとして４月から働き出しました[kawabata](https://twitter.com/haru1125632)です。

社会人になって感じることは、エンジニアという職業では働いた時間よりも、成果がより重要視されるということです（これは多くの職業に共通するかもしれません）。

今回は、「時間・回数駆動開発」という、私が試行錯誤しながら実践している手法についてご紹介します。この方法では、タスクの実行にかかる時間や回数を事前に定め、それを基に作業を進めます。完了時に予定を超えた場合や、品質が悪い場合は、その原因を分析し改善策を考えます。

# 時間・回数駆動開発とは

時間・回数駆動開発は、タスクを効率的に進めるために、必要な時間や回数をあらかじめ定める手法です。

たとえば次のようにタスクを行う前に決めておきます。

- PRを出す前にセルフレビューを３回すると決めておく
- 設計書を考える時間をあらかじめ決めておく

この方法で、セルフレビューを3回行っても不完全なPRが出てしまった場合は、「不足していた点は何か」を分析します。例えば、「セルフレビュー用のチェックリストを作成し、それを使用する」といった改善策を次回に生かします。

> エンジニアは推測するな計測せよ

この格言にもあるように、可能な限り作業は計測することで、より良い結果を導き出すべきです。

## メリット

- タスクの見積もりが正確になる
- 改善点が明確になり、具体的なアクションプランが立てやすくなる
- 無駄な時間を過ごさずに済む

## デメリット

- 創造性を制限する可能性がある
- 時間内にタスクを終えるプレッシャーがパフォーマンスに悪影響を与える


# まとめ

時間・回数駆動開発は、全ての人や全てのタスクにとって最適な方法とは限りません。しかし、自分に合った効率的な作業方法を見つける一助となります。この手法に興味を持った方は、ぜひ明日からのタスクで試してみてはいかがでしょうか。
JIRA Automation 内で作成した issue 情報を同じルール内の後続 step でスマートバリューを利用して参照したい場合は createdIssue を使う必要がある

タイトルがそのまま結論なのですが詳細を記載します。

## やろうとしたこと
[JIRA Automation](https://www.atlassian.com/ja/software/jira/features/automation) を利用して cron トリガーで issue 作成と issue の URL を slack 通知させるルールを作成したかった。

## スマートバリュー
JIRA Automation には[スマートバリュー](https://ja.confluence.atlassian.com/automation/smart-values-in-jira-automation-993924627.html)という機能があり、動的データを取り込むことができる。

## JIRA Automation 内で作成した issue 情報を同じルール内の後続 step で参照する場合は `issue`ではなく、`createdIssue`スマートバリューを利用する必要があった
https://support.atlassian.com/ja/cloud-automation/docs/jira-smart-values-issues/ の doc を読んで `{{issue.url}} `を使えば良いんでしょと思ったが、参照できなくて躓いた。サポート担当に質問したら `{{createdIssue.url}}`を使う必要があると教えてもらった。冒頭の doc にも記載があったが見落としていた。
https://support.atlassian.com/ja/cloud-automation/docs/jira-smart-values-issues/#--createdIssue--
gasのgetRangeで引っかかってしまったこと

getRange()でシートの一部を抜き出して、加工し、setValues()でシートに書き出そうとした。

ただ、抜き出した部分が１列分のデータで、それを加工して、１列にsetValuesしようとするが、

Exception: The number of columns in the data does not match the number of columns in the range. The data has 1 but the range has 5.

みたいな感じでエラーが出た。


これは結局getRange()の引数について勘違いしていて、

Sheetオブジェクト.getRange(行番号, 列番号, 行数, 列数)
が正しいのに、

自分の中で
Sheetオブジェクト.getRange(はじめの行番号, はじめの列番号, 最後の行番号, 最後の列番号)
と誤って理解していたことからエラーが出た。
通信ディジタル工学

# 通信ディジタル工学


# 達成目的

![スクリーンショット (125).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/56c008d6-d538-3cd5-1839-d7c620a33105.png)


![fig_03_01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/1f44f3c7-2dd0-cb49-565c-f0a7ad3105e3.gif)

携帯電話は常に近隣の無線基地局の電波強度を測定し続けていて、電波がある一定の強度以下になると、それまでの回線を切断して、より強度の強い別の回線に切り替えるようになっているためです。常に次の接続の準備を行っているので、利用者に意識させることなく、スムーズに切り替えることがでるのです。この仕組みは「ハンドオーバー」と呼ばれています。


https://business.ntt-east.co.jp/content/nw_system/03.html

# 波を送る

基地局からスマホ、スマホから基地局に電波を送る。
波の式は以下である。
S(t)=A(t)cos(2πfct + Θ(t))

振幅　A(t)
周波数　fc
位相　Θ(t)
上記3つは変えられる。

つまり、上記3つをうまく調整して、デジタル信号を電波に変換し情報を送ることを考える。

周波数は使える周波数帯が決まっている。
振幅と位相の変化に情報を乗せる。
![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/de6a4360-e922-540e-3c05-026a7b0df0cd.gif)


# デジタル変調器
## BPSK (Binary Phase Shift Keying)

電波で変えられる要素「振幅・周波数・位相」のうち、位相のみを変化させて変調する。2つの入力データ(0,1)を2つの位相(0,π)に対応させて送信する。

![スクリーンショット (126).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/bb9f7bb1-ef95-a093-e438-0e6fd791696a.png)

スマホ→基地局の例を考える。スマホ側から0101を送りたいときは、まず位相0でピュっと短く電波を出す。次に位相πでピュっと短く電波を出す。これを入力データと位相の対応に従って続けていく。

## QPSK
4つの入力データ(00,01,10,11)を4つの位相(0,1/2π,π,3/2π)に対応させて送信する。
(1/2πづつずらした位相に入力データを対応させる）


## てかそもそも波は周波数一定で送れないの？
### ドップラー効果
音源が移動しながら音を発するとき、進行方向に進む音は波長が短くなり、 反対に進行方向と逆方向に進む音は波長が長くなる。

* ICチップはCPUとメモリで構成されている
カードリーダー等の外部機器から電気を供給してもらって動く。

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/de6a4360-e922-540e-3c05-026a7b0df0cd.gif)


## フェージング
電波は球面で広がるの？→yes
波源から球面で広がる。ただし、遠くの受信点では球面がほぼ平面に近似できる。
波源から球面で広がるため、遠くに行けば行くほど球の表面積が増え、単位面積当たりの電力が減少する。→

https://note.com/studysanfran/n/n90cd0ff40e16

## 電波の速度
電波は電磁波の一種なので、速度は光と同じ 1[秒]間に30万[km]進みます。
（早っ！！）

## 電波の波長
波長＝1秒間に進む距離(30万km)/1秒間に振動する回数(=周波数)
例えば周波数5GHzの波長は、3.0*10^8m/5.0*10^9=0.06m=6cm

![スクリーンショット (139).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/26685edf-7fef-b2d7-3495-3d360998f222.png)

## ホイヘンスの原理

##
Wifiを使う＝ノード機器とルータ間で電波の送受信が行われている。




# LTEの仕組み

# 回折への対応
受信を考える。電波は360度あらゆる方向から飛んでくる。電波同士が干渉しあうという問題が発生する。解決策は以下である。
* マルチパスを受信しない
アダプティブアレイアンテナを⽤いる。
* マルチパスフェージングによる変動（遅延プロファイルもしくは位相
変動）を推定し、逆特性のフィルタをかける。
  等化⽅式
* 差動変調、遅延検波の利⽤
* 情報を複数のチャネルを⽤いてゆっくりと伝送
並列伝送⽅式

# フェージング
無線通信において、時間差をもって到達した電波の波長が干渉し合うことによって電波レベルの強弱に影響を与える現象

![スクリーンショット (183).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627132/fb4ab818-754d-9c80-8d35-88f3f549c6fe.png)


# 並列伝送
* 周波数分割多重伝送
* 符号分割多重伝送

# 直交周波数分割多重伝送（OFDM)


http://www.tele.soumu.go.jp/j/freq/process/
cv2.error: OpenCV(4.9.0) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:696: error: (-2:Unspecified error) could not find a writer for the specified extension in function 'cv::imwrite_'

# エラー内容の共有

```ruby:circle.py
import numpy as np
import cv2

img = np.zeros((400,400,3), np.uint8)
cv2.circle(img, (200, 200), 50, (255, 0, 0), 1)
cv2.imwrite(r'C:\Users\tmasa\OpenCV4_Programming_Getting_Started_in_Python\circle1.img', img)
cv2.imshow('img1',img)
```

これの実行時にエラーが出ました。

## 解決方法
拡張子が.imgになってました。.pngですね…
Reactしか触ったことのなかった私がVueを触ってみて

## 概要
React(Next.js)しか使ったことのない私が今回初めてVueを触ったので、Vueの初心者目線で感じたことをReactと比較して書かせていただきます。

## 私のスキル感
- （1.5年）Markup(HTML,CSS,JavaScript)
- （1.0年）React,Next.js
- （1ヵ月）Vue.js

→React(Next.js)も全て個人開発で使用のため初心者です…

## 感じたReactとVueの違い
### ファイル構成
Vueは単一のファイルで完結するので、とても理解しやすく書きやすいなと感じました。
|　 　| （Tailwind等のCSSフレームワークを使用しない場合） |
|:-:|:-:|
|React|  .jsx ＆ .css |
| Vue |  .vue |

### CSSファイルの競合
別ファイルに用意せずとも競合を意識せずに作業できるのは非常に便利だなと感じました。Reactだと毎回importするのも地味に面倒…

|　 　| （Tailwind等のCSSフレームワークを使用しない場合） |
|:-:|:-:|
|React|  sample.module.css |
| Vue |  `<style scoped>` |

### Routing
ルーティング自体に関しては現段階ではあまり大きな差は感じられませんでした。

### Routing Animation
Reactでは遷移時のアニメーションをつけるにはreact-transition-groupやFramer Motion等のライブラリをインストールして実装する必要がありました(簡単な方法があったらすみません)。ですがVueでは備え付けの`<transition>`コンポーネントを使用することで簡単に遷移時のアニメーションを実装できました。これは地味に感動しました。

### 条件分岐や反復
HTMLしか知らなかった私がReactを使い始めた時にも便利だなと思ったのが条件分岐や反復でした。jsxファイルとvueファイルで書き方が違いましたが、覚えてしまえば同様の使い方ができるのでとても便利でした。

```.jsx
<ul>
    {items.map((item, index) => (
        <li key={index}>{item}</li>
    ))}
</ul>
```
```.vue
<ul>
    <li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
```

### props,slot
単純なボタンなどでデザインは同じだけど中身の文言だけ変えたいという時にコンポーネント化してpropを渡す場合があると思いますが、Vueではわざわざpropsで渡さずとも`<slot>`で渡すことができました。
```Button.vue
<template>
  <button><slot /></button>
</template>
```
```App.vue
<template>
  <div>
    <Button @click="handleRegister">登録</Button>
    <Button @click="handleDelete">削除</Button>
  </div>
</template>
```

### 状態管理
ReactではReduxがよく使用されますが、VueにもVuex(Pinia)がありました。

### Hooks / Composition API
私がReactの学習を始めた際にReactのわかりにくさを感じたのがHooksで、しばらく理解ができなかったのですが、便利で必須な機能でした…。Vueにも同様の機能があり完全に一緒ではないですがVue3からComposition APIというもので提供されているようでした。
|　 　| 機能|
|:-:|:-:|
|React|  React Hooks |
| Vue |  Composition API |

### 学習コスト
ReactとVueを比較する様々な記事を見るとVueの方がわかりやすく、学習コストが低いという話をよく見かけます。ですが、結局バックエンドからではなくHTM,CSSから学び始めた人にとっては、自分の書いたことがそのまま全て表示される静的ページから動的なページの書き方だったり、フレームワークへの考え方だったりを学ぶことに時間がかかるので、学習コストにそんな差は無いのではないかと感じました。Vueの方が視覚的にも感覚的にも分かりやすいことは間違い無いのかもしれませんが、一からある程度きちんと学ぶ時間を取れるのであればどちらを選んでも学習コストに大差ないのではないかと感じました。(個人の意見です)

## 比較してVueの良かった点（個人の感想）
- 単一のファイルで完結するので、とても理解しやすい
- コンポーネントは全てscopeで統一すればCSSの競合を意識せずに書けて良い
- `<transition>`でリッチな表現が手軽にできる
- JSXはJavaScriptの中にHTMLを入れているという感覚だったが、Vueではその独特な感じもなくわかりやすいと感じた

## 結論
JSXに先に慣れているとあまり変わらないのではないかとも最初は思いましたが、HTML,CSS,JavaScriptと学んだ人は、Vueの方がコードを書きやすいのは間違いない。と感じました。Vueの良いところをまだまだ見つけられていないと思うのでこれからVueのいいところも見つけつつ他の言語でも精進していきます！！

**Reactしか触っていない人はVueも気軽に触ってみたらいいと思います！**

## 最後に
Routing Animationの手軽さに感動したので数分で実装したものではありますが、Routing Animationを実装したページを置いて失礼いたします。ありがとうございました。


https://vue-router-transitions.vercel.app

いつかSvelte,Astro仮想DOMを使用しないライブラリ、フレームワークも勉強しないとな…
gasで.getRange is not a functionとエラーが出た

原因は.getRangeの前のところが、シートを指定していなかったからだった。

シートの名前を記述している途中に適当にtabかなんか押して入力してしまったみたい。

名前を全て記述しなくてもサジェストみたいに出てくるのは便利だけどしっかり見ておく必要があった。
CocoaPods

## はじめに
CocoaPodsをつかうときの自分用メモ

CocoaPodsはインストールしてある前提

## pod init
対象のプロジェクトディレクトリをターミナルで開いて
```sh
pod init
```
上記コマンドをいれてPodfileを生成します｡

## pod file 編集
今回はRealmを追加する場合
```
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'RealmTest' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'RealmSwift'

  # Pods for TodoListApp

end
```
## pod install
これでターミナルでpod installコマンドを実施します｡
Pythonの備忘録 (超初心者) <List>

僕がPythonの使い方をド忘れした時のための備忘録を作成します。

PythonのList, Tuple, Dictionaryの使い方は下の図で表したような感じになっています。
![スクリーンショット 2024-04-22 12.03.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575336/e19bf248-960a-7689-0026-132c19021b3a.png)

:::note warn
あくまで上記はイメージです
厳密さを必要とする場合は下記LINKを参照してください。
https://www.python.org/
:::
今回はListの使い方の基本を書き下ろしておきます。

<!-- open属性あり -->
<details open><summary>Listを設定</summary>

```python
list = []
```
:::note info
出力
:::
listを設定するだけでは何も出力はありません。

<!-- open属性あり -->
<details open><summary>listを出力</summary>

```python
print(list)
```
:::note info
出力
[]
:::
からのlistが出力されました

### A問題 (1-1)

```python
list.appned(1)
#listに要素を追加
print(list)
#listに要素が追加されていることを確認
```
:::note info
出力
[1]
:::
appendを使うことで要素が追加されていることがわかりました
### A問題 (1-2)

```python
list = [2,5,3,7,8,4,1,9,6]
list.sort()
#リストをソートします
print(list)
#リストの内容を表示します。
```
:::note info
出力
[1, 2, 3, 4, 5, 6, 7, 8, 9]
:::
sortを使うことで要素が昇順で整列されていることがわかりました。
### A問題 (1-3)

```python
list = [2,5,3,7,8,4,1,9,6]
list.reverse()
#リストをソートします
print(list)
#リストの内容を表示します。
```
:::note info
出力
[6, 9, 1, 4, 8, 7, 3, 5, 2]
:::
reverseを使うことで元の配列を逆転させたことがわかりました。
### B問題 (1-4)

```python
list = [2,5,3,7,8,4,1,9,6]
list.sort()
list.reverse()
#リストをソートします
print(list)
#リストの内容を表示します。
```
:::note info
出力
[9, 8, 7, 6, 5, 4, 3, 2, 1]
:::
sortとreverseを使うことで降順で整列させることができた

### A問題 (1-5)

```python
list = [2,5,3,7,8,4,1,9,6]
list.remove(1)  # 1を削除します
print(list)  # リストの内容を表示します。リストから1が1つ削除された状態が表示されます
#リストの内容を表示します。
```
:::note info
出力
[2, 5, 3, 7, 8, 4, 9, 6]
:::
removeを使うことで1を削除していることを確認できた。

#### A問題 (1-5 (tip))

```python
list = [1,2,1]
list.remove(1)  # 最初に見つかった1を削除します
print(list)  # リストの内容を表示します。リストから1が1つ削除された状態が表示されます
```
:::note info
出力
[2, 1]
:::
removeで指定した要素は左側から検索されることがわかる。
※もし右から検索された場合は[1, 2]のようになるはずである

### A問題 (1-6)

```python
list = [2,5,3,7,8,4,1,9,6]
list.pop()  # リストの末尾の要素を削除します
print(list)  # リストの内容を表示します。末尾の要素が削除された状態が表示されます
```
:::note info
出力
[2, 5, 3, 7, 8, 4, 1, 9]
:::
popを使うことで末尾の6を削除することが確認できた。

### A問題 (1-7)

```python
list = [2,5,3,7,8,4,1,9,6]
print(list[0])  # リストの末尾の0番目の要素を表示します
```
:::note info
出力
2
:::
PythonのListでは下記のようなIndexとlistの要素で対応していることがわかった。

![スクリーンショット 2024-04-22 13.07.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575336/cb753f68-5c0e-88fc-376e-18c27fd4943b.png)

### A問題 (1-8)

```python
list = [2,5,3,7,8,4,1,9,6]
list.insert(1, 100)  # インデックス1に6を挿入します
print(list)  # リストの内容を表示します。インデックス1に6が挿入された状態が表示されます
```
:::note info
出力
[2, 100, 5, 3, 7, 8, 4, 1, 9, 6]
:::
Pythonのinsertでは指定したindex番号の左に要素を追加したことがわかった。

### A問題 (1-9)

```python
list = [2,5,3,7,8,4,1,9,6]
print(list.count(3))  #3の出現回数が表示されます
```
:::note info
出力
1
:::
Pythonのcountでは指定した値の要素数をカウントしたことがわかった。
【Atcoder】ABC 350 C問題


# コンテスト名

AtCoder Beginner Contest 350

https://atcoder.jp/contests/abc350

# 考えたこと
整数の組 (i,j) をswapしてsortする
↓
選択ソート？

結果
計算量$O(n^2)$なので当然TLE


# 次に考えたこと

ヒープソートを使う

結果
heapqを使えばsortだけならいけそうだが、問題文に
$「l 回目の操作で選ぶ整数 i,j を空白区切りで出力せよ。」$
と書いてあるので（自分には）不可能。

# 公式解説
https://atcoder.jp/contests/abc350/editorial/9810?lang=ja
https://atcoder.jp/contests/abc350/editorial/9832

# 考察

なるほど。そもそも最小値を見つける必要がなく、必ずi番目の数字はiになる訳か。（当たり前）
ただ、$「現在 A の中で i がどこにあるか」$を探す際にindexメゾットを使うと
$O(n^2)$になってしまうから「A の中で値 i がある位置を表す配列」を用意する必要があるわけね。

ということで公式解説の間違い例
https://atcoder.jp/contests/abc350/editorial/9832
を使って書き換えました。
```python
n=int(input())
a=list(map(int,input().split()))
answer=[]

pos=[0]*(n+1)
for i in range(n):
    pos[a[i]]=i
for i in range(n):
    if a[i]!=i+1:
        idx=pos[i+1]
        a[i],a[idx] = a[idx],a[i]
        pos[a[i]],pos[a[idx]]= pos[a[idx]],pos[a[i]]
        answer.append((i+1,idx+1))

print(len(answer))
for a in answer:
    print(*a)
```
SalesforceのLightningページを設定後組織のデフォルトに設定する方法

今回はSalesforce　Lighntnigページで組織のデフォルトに設定する方法を図で解説します
意外と分かりにくいので１ページごとに画像を添付して解説します


なお、ヘルプではここら辺の内容です

https://help.salesforce.com/s/articleView?id=sf.lightning_app_builder_customize_lex_pages_activate.htm&type=5


Lightning アプリケーションビルダーでレコードページを作成するか、既存のレコードページを開きます。
ユーザーに提供する準備ができていて編集の必要がないレコードページを開いた場合は、[有効化] をクリックします。
ページを作成した場合や調整が必要なページを開いた場合は、必要な変更を行い、[保存]、[有効化] の順にクリックします。
ページを有効化する方法を選択します。
ページを組織のオブジェクトのデフォルトにする。
Lightning ページを組織のデフォルトとして有効化すると、ページが [プロパティの上書き] パネルで表示アクションの Lightning Experience の上書きとして選択されます。



では実際の画面で見ていきましょう。

![保存001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4cf177be-0b20-3845-984f-1f352029bb76.png)


![保存002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/db4eb475-c80f-ab40-43c8-85ff495419dc.png)


![保存0031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/7272e9ae-097f-ec61-a0f0-9a21d169eeca.png)


![保存004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b918979c-56ea-6af5-756d-0ecc7f5bb7ff.png)


![保存005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f2c543f7-478e-f44c-1dbd-ed78b7d8a3c7.png)
Go言語のJson出力をjson serverの形式に揃える方法

## はじめに

Go言語で集めたデータをjsonで保存．そのjsonをjson-serverでホストしてフロントエンドから取得，及び変更する簡易な自作ツールを作成していた．
運用期間を延ばしてもそこまでjsonが肥大化する性質のツールではないためjsonもGitリポジトリで管理したい．しかし，Go言語標準ライブラリのjson encoderのデフォルトの出力形式とjson-server側で変更した際に整形される形式が異なっている．
そのため，Go言語でデータ取得した後json-serverの変更が実行された場合や，json-serverの変更が実行された後に再度Go言語でデータを取得した場合にGit上ではファイル全てが書き換えられたように認識されてしまい変更履歴が機能しない．
なのでGo言語標準ライブラリのjson encoderの出力形式をjson-serverと同じ形式にしたい．

## 対処

以下愚直にjson encoderを使用したコードとその出力．json-serverの形式と違う部分は1行にまとめられていることとHtml要素がエスケープされていることだった．

```go:main.go
package main

import (
	"encoding/json"
	"os"
)

func main() {
	type Message struct {
		Name string
		Body string
		Int  int64
	}

	m := Message{"title", "<body>content</body>", 4355}
	enc := json.NewEncoder(os.Stdout)
	enc.Encode(m)
}
```

```出力
{"Name":"title","Body":"\u003cbody\u003econtent\u003c/body\u003e","Int":4355}
```

Go言語json encoderにはインデント形式を変更する関数SetIndentとHtmlエスケープの有効無効を制御する関数SetEscapeHTMLがあるのでこのオプションを設定することで出力形式をjson-serverのものと同じにできる．
以下対処済みのコードとその出力

```go:main.go
package main

import (
	"encoding/json"
	"os"
)

func main() {
	type Message struct {
		Name string
		Body string
		Int  int64
	}

	m := Message{"Alice", "<body>content</body>", 4355}
	enc := json.NewEncoder(os.Stdout)
	enc.SetEscapeHTML(false)
	enc.SetIndent("", "  ")
	enc.Encode(m)
}
```

```出力
{
  "Name": "Alice",
  "Body": "<body>content</body>",
  "Int": 4355
}
```
Pocketの認証をワンライナーで実施する方法

# はじめに
Pocketとは，Firefoxを開発するMozillaが運営しているブックマーク保存サービスである．
IOSアプリケーションやブラウザの拡張機能でブックマークの登録ができる点．ブックマークにタグ付けする機能がある点が気に入っており常用している．そして，API機能で，機械的にブックマークの取得，追加及び変更を行える．

本記事では，API機能を用いるのに必要なアクセストークンをワンライナーで取得できるNode.js,Denoツールをご紹介する．

*事前にコンシュマーキーは発行しておく必要があります!!*

# 事前準備 : コンシューマキーを取得
下記公式ドキュメントの Step 1をブラウザで実施する．
[Pocket Authentication API Documentation](https://getpocket.com/developer/docs/authentication)

# Node.jsでアクセストークンを取得する方法

1. 下記コマンドをターミナルで実行する．
```bash
npx pocket-auth <consumer_key>
```

1. 規定のブラウザでPocketのURLが開くのでログインする．

1. こんにちは！ ユーザ名があなたの Pocket アカウントへの接続を求めています．というメッセージの下の認可ボタンを押す．


# Denoで取得する方法

1. 下記コマンドをターミナルで実行する．
```bash
deno run --allow-env --allow-net --allow-sys --allow-read --allow-run npm:pocket-auth-cli <consumer_key>
```

1. 規定のブラウザでPocketのURLが開くのでログインする．

1. こんにちは！ ユーザ名があなたの Pocket アカウントへの接続を求めています．というメッセージの下の認可ボタンを押す．
mDNSを無効化する方法

## はじめに

自宅オンプレミス環境にはDNSサーバがあり，mDNS機能を使うことがない．また，mDNSを有効にしていると常に5353ポートの通信を行うのでファイアウォールのログがその通信ばかりになり他の通信が埋もれてしまい解析しずらかった．なのでmDNS機能を無効化した．

## 無効化手順

### Avahiの無効化

1. ターミナルでAvahiを無効化する方法
```bash
sudo systemctl stop avahi-daemon.socket
sudo systemctl disable avahi-daemon.socket
sudo systemctl mask avahi-daemon.socket
sudo systemctl stop avahi-daemon
sudo systemctl disable avahi-daemon
sudo systemctl mask avahi-daemon
```

1. AnsibleでAvahiを無効化する方法
```yml
- name: disable avahi-daemon
  systemd:
    name: avahi-daemon
    state: stopped
    enabled: false
    daemon_reload: yes
    masked: true
  become: true

- name: disable avahi-daemon.socket
  systemd:
    name: avahi-daemon.socket
    state: stopped
    enabled: false
    daemon_reload: yes
    masked: true
  become: true
```

### systemd-resolvedのmDNS機能を無効化

Avahiを無効化してもArch LinuxのPCから5353ポートの通信が発信され続けていた．この通信を発しているプロセスを調べたところsystemd-resolvedだった．

1. ターミナルでsystemd-resolvedのmDNS機能を無効化にする方法
```bash
echo "MulticastDNS=no" >> /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved
```

1. Ansibleでsystemd-resolvedのmDNS機能を無効化にする方法
```yml:tasks/main.yml
    - name: Set up resolved.conf
      template:
        src: templates/resolved.conf.j2
        dest: "/etc/systemd/resolved.conf"
        owner: "root"
        group: "root"
        mode: 0644
      become: true
      notify: restart systemd-resolved
```
```yml:templates/resolved.conf.j2
[Resolve]
MulticastDNS=no
```
```yml:handlers/main.yml
- name: restart systemd-resolved
  systemd:
   name: systemd-resolved
   state: restarted
   daemon_reload: yes
  become: true
```
cloud-initを無効化する方法

## はじめに

Ubuntuサーバではcloud-initがデフォルトで有効化されている．
しかし，自宅オンプレミス環境のUbuntuサーバでは初期設定や構成管理にAnsibleを利用しておりcloud-initを利用していなかった．そのため，不要サービス無効化の一環としてcloud-initを無効化した．

## cloud-initの無効化

[cloud-init 公式ドキュメントの無効化手順](https://cloudinit.readthedocs.io/en/latest/howto/disable_cloud_init.html)
上記リンクを確認すると特定のファイルを作成する方法と，環境変数を通じてkernelにコマンドライン引数を渡す方法とがあるようだ．
1つ目のファイル作成する方法が簡単な上，他のシステムや設定と衝突しにくいと考えた．

1. ターミナルでファイルを作成する方法
```bash
sudo touch /etc/cloud/cloud-init.disabled
```

1. Ansibleでファイル作成する場合
```yml
- name: Create  /etc/cloud/cloud-init.disabled
  ansible.builtin.file:
    path: /etc/cloud/cloud-init.disabled
    state: touch
    access_time: preserve
    modification_time: preserve
  become: true
```
laravelのsailでseeder作成/実行してデータを投入する

# 環境
php 8.3.6
laravel Framework 11.4.0
composer 2.7.2

# seeder作成
```
./vendor/bin/sail php artisan make:seeder MasterAiChatSeeder
```
/database/seeders/MasterAiChatSeeder.phpのファイルを修正
```
<?php
namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class MasterAiChatSeeder extends Seeder
{
    public function run(): void
    {
        $params = 
        [
            ['chat' => 'reactは勉強中です'],
            ['chat' => 'laravelもやっています'],
            ['chat' => 'seederやFacadesを学習中です']
        ];

        $now = Carbon::now();
        foreach ($params as $param) {
            $param['created_at'] = $now;
            $param['updated_at'] = $now;
            DB::table('master_ai_chat')->insert($param);
        }
    }
}

```
# DatabaseSeederに作成したseederを追加する
/database/seeders/DatabaseSeeder.phpのファイルを修正
```
<?php
namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
         $this->call([
            MasterAiChatSeeder::class,
        ]);
    }
}

```
# seederを実行する
```
./vendor/bin/sail artisan migrate --seed
```

# まとめ
「php artisan db:seed --class=MasterAiChatSeeder」のやり方だとうまく挙動しなかったので、備忘録的に残しておきます
RailsでCanCanCanを使った権限管理: スタッフは自分のデータのみ編集可能

## RailsでCanCanCanを使った権限管理

## 導入
Railsアプリケーションにおいて、ユーザーによって操作できるデータを制限する場合、`CanCanCan` は非常に有力なツールです。このガイドでは、`Staff` モデルが自身のデータのみを編集できるようにする設定方法を紹介します。

## 前提条件
この設定を行う前に、`CanCanCan` ジェムがアプリケーションにインストールされていることを確認してください。

```bash
gem 'cancancan', '~> 3.0'
```

そして、`bundle install` を実行します。

## Ability クラスの設定
`CanCanCan` は `Ability` クラスを使用して、誰が何をできるかを定義します。`Staff` が自分自身のプロファイルのみ更新できるように設定しましょう。

```ruby
# app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new  # ゲストユーザーの場合は新しいユーザーインスタンス

    case user
    when Staff
      can :manage, Staff, id: user.id  # スタッフは自身のデータのみ操作可能
      can :read, Company, id: user.company_id  # スタッフは自身が所属する企業を閲覧可能

    when Company
      can :manage, Company, id: user.id  # 企業は自身のデータのみ操作可能
      can :manage, Staff, company_id: user.id  # 企業は所属するスタッフのデータを管理可能

    when Customer
      can :manage, Customer, id: user.id  # 顧客は自身のデータのみ操作可能
      can :read, Company  # 顧客は全企業を閲覧可能

    when AdminUser
      can :manage, :all  # 管理ユーザーは全データに対する操作権限を持つ

    else
      # ゲストユーザーの権限
      can :read, Company  # ゲストは企業情報の閲覧のみ可能
    end
  end
end

```

## コントローラの設定
`StaffsController` に `load_and_authorize_resource` メソッドを追加して、CanCanCanがリソースのロードと権限チェックを自動で行うようにします。

```ruby
# app/controllers/staffs_controller.rb
class Staffs::RegistrationsController < Devise::RegistrationsController
  load_and_authorize_resource :class => 'Staff'
  
  def edit
  end

  def update
    if @staff.update(staff_params)
      redirect_to @staff, notice: 'スタッフ情報が更新されました。'
    else
      render :edit
    end
  end

  private

  def staff_params
    params.require(:staff).permit(:name, :email, :department)
  end
end
```

## エラーハンドリング
`current_user` メソッドが定義されていない場合、`current_ability` メソッドをオーバーライドしてカスタムユーザーメソッドを指定する必要があります。

```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # アクセス権限がない場合に元いたページに戻す。直接URLを入力して訪れた場合などはフォールバックでルートパスへ。
  rescue_from CanCan::AccessDenied do |exception|
    redirect_to request.referer || root_url, alert: "アクセス権限がありません。"
  end

  def current_ability
    @current_ability ||= Ability.new(current_staff)
  end
end
```

## まとめ
この設定により、スタッフは自分自身のプロフィール情報のみを編集することが可能となります。`CanCanCan` を使用することで、複雑な権限設定も容易に実装でき、セキュリティの向上にもつながります。
Workato：フィールド定義（スキーマ）をコピーする簡単な方法

# はじめに

Workatoでは、各コネクタのCustom Actionなど、サンプルJSON（各アプリケーションから出力されるJSON形式のレスポンス）をもとにパラメータフィールドを定義することが可能です。

しかし、サンプルJSONではなく、Workatoで定義済みのスキーマJSONをコピーして他で利用したい場合もあると思います。そのような場合は、次の手順でスキーマJSONを他のパラメータフィールドへ簡単にコピーすることができます。

# 手順

## １．コピーしたいパラメータフィールドの「Edit Schema」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/a50cc414-8f15-b28a-1a1c-e3029855289c.png)

## ２．エディタの内容を全てコピーします。
コピー後、`Cancel`をクリックして閉じます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/c30041a3-7d79-73a7-937c-903e44b02864.png)

## ３．コピー先のパラメータフィールドの「Add fields manually」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/8d5e0aed-eff7-fb97-c8cb-fc756b738a30.png)

なお、既に定義済みのフィールドの場合は、`Clear`をクリックし、パラメータフィールドを初期化してから上記の手順を進めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/19a7685b-92ed-b5b9-cb5e-866da1b717f1.png)

## ４．適当な名前のフィールドを作成します。
どのような名前でも構いません。このフィールドは後で削除されます。入力後、`Add field`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/f8d7e65d-6ea4-6db7-63fc-a4d585be350f.png)

## ５．「Edit Schema」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/0f4d888c-4fc5-706d-5377-bf13de0002a9.png)

## ６．エディタの内容を、２でコピーした内容に置換（ペースト）します。
ペースト後、`Update`をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/85d9b48a-96be-1983-e834-d91b4f031d74.png)

## ７．パラメータフィールドのスキーマがコピーされたことを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d27e5e3c-8328-d8c3-01b8-dd039fa4fd70.png)
Azure Data Factoryの概要

AzureのETLツール「Azure Data Factory」の概要です。


## １．ドキュメント

・Microsoft Learn	
Microsoftが提供するサービスのドキュメントが参照できるサイトで、ハンズオンも充実しています。	

Azure Data Factoryのページはこちら。	
https://learn.microsoft.com/ja-jp/azure/data-factory/



## ２．Azure Data Factoryの機能

Azure Data FactoryはGUI開発が可能で、処理はSparkの並列分散処理基盤で実行されます。	
Azure DevOps や GitHub を使用したCI/CD もサポートしています。	

他のサービスとの連携はこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690949/920ee81b-f916-060d-6cef-1031d24dd010.png)

Azure Data Factoryではデータの抽出、変換処理ができ、作成したデータを活用することができます。
上の図で赤く色づけしている箇所について簡単に解説します。

#### （１）データ抽出
オンプレミスやクラウドで管理しているデータを、コピーアクティビティでBlobやData Lake Storageなどのデータストアに移動します。

#### （２）データ変換
データ変換用のアクティビティを利用してデータの加工を行います。以下のサービスを利用することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690949/48fa9b2c-2339-77e6-c92a-f9882f0464f8.png)

#### （３）データ活用
データストアにデータを保存し、業務ファイルやBIツールなどから参照します。



## ３．Azure Data Factory インスタンスを構成するコンポーネント
Azure Data Factory ではワークフロー (パイプライン) を作成してスケジューリングしたり、スケジュール化したワークフローを監視することができます。
主なコンポーネントについて解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690949/5cae8841-8416-5122-92f0-db5017dbc3af.png)



## ４．アクティビティ一覧
Azure Data Factory で利用可能なアクティビティの概要を記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690949/611dc45b-879b-e935-1740-faa2fed0e623.png)



## ５．料金
料金は以下に対してかかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690949/74b48fdf-2b1a-e7ed-d1bf-2a986d96c5b3.png)

https://azure.microsoft.com/ja-jp/pricing/details/data-factory/data-pipeline/



以上です。
Global Azure 2024 ショートセッション登壇して Azure Migrate の話をした

2024/4/20 に日本マイクロソフト株式会社品川本社で行われた Global Azure に現地参加＆ショートセッション登壇しました。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/346a9e37-f9b4-35a9-36da-cac245aa1a77.png">

# Global Azure とは

https://jazug.connpass.com/event/311408/

Global Azure とは世界中の Azure コミュニティが一斉に開催する Microsoft Azure のコミュニティイベントで、4/18-20 の 3 日間にわたって世界各地で開催されました。
日本でも 4/20 に札幌東京福岡の 3 か所同時開催（東京は二部屋！）＋オンライン視聴もあり、ついっ… X もハッシュタグ [#GlobalAzure](https://twitter.com/search?q=%EF%BC%83GlobalAzure&src=typed_query) [#jazug](
https://twitter.com/search?q=%EF%BC%83jazug&src=typed_query) で大変盛り上がりました！

東京現地も 100 名近くの方が参加されていたようで、最後にあった懇親会も大賑わいでした。
私はショートセッションで Azure Migrate の話をさせていただいたので、その内容をこちらにも少し書きます。

# Azure Migrate とは何か

とーってもざっくりというと…
・ Azure への移行のために必要な機能が集まったもの
・ Azure へ移行したい環境を評価し適切な Azure リソースを提示
・ そのまま Azure へ移行もできる
ようなものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/23344911-ea2b-12fd-861b-96a147a264bd.png)

# 既存環境を整理し移行後をイメージ

VMware や Hyper-V、物理サーバー、他社クラウドを検出して評価します。
サーバーのスペックではなく、実際の稼働率を考慮して推奨サイズなどを提示してくれます。
その場合の金額もグラフで表示。
実は OS がもう Azure では使えません、なんていうのも見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/4aec8848-f27c-daf6-c00d-bcc8f815c565.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/b84207fb-3170-46a8-9eb9-1300f1910b9a.png)

# 評価の設定

仕様するリージョンやストレージの種類、3 年予約や節約プランを使うかなどの設定や、Windows Server のライセンスを持っていれば Azure 上で安価に使用することができるのでそういったことが設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/061652b8-f35e-d310-5ccb-6e565982b8b4.png)

# 評価をするには

アセスメントサーバーという、評価用サーバーが必要です。

方法 1 : Azure Migrate の検出用イメージ（.VHD）から Hyper-V に仮想マシンをホスト
構成図では水色の部分です。Azure Migrate 上の VHD ファイルを Hyper-V にもって行ける場合はこの方法でしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/b822b124-bb5b-cf42-9101-ad592b0dfda5.png)

方法 2 : 物理 or VM の Windows Server 2022 で PowerShell を実行
こちらも水色の評価用サーバー。2019 も使えますが 2022 が推奨となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/b7e84c44-b3d4-8345-d3f7-7e0b6e946502.png)

方法 3 : CSV を使用する
Azure Migrate に CSV のテンプレートが用意されています。
実環境に対して疎通させるのが難しい場合、手軽に使用できます。
CSV なので実際の稼働状況は見ることができないですが、会社の偉い人を説得する資料を作りたいあなたにお勧めです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335429/f9933b09-e39e-7a0f-0e06-0561bfa93de3.png)

# Azure へ VM 中身そのまま移行も可能

どう考えても不要なログファイルとかも残っているような状態で中身そのまま移行することも可能です。
ですが、
・ SaaS に移行できないか
・ PaaS に移行できないか
・ VM を新規作成して同じ役割のサーバーを作り直せないか
全て検討してどうしても無理、どうしても保守期限切れで間に合わない、っていう場合のみ検討するのがよいと思います。保守期限切れという大きなタイミングで新規の VM に移行できなかったものを、その後正しく新規の VM に移すことは難しいんじゃないでしょうか。
これは本当に最後の最後の手段として使ってもらえるとよいかと思います。

# おしまい

たのしかった～～～～～～
エンジニアに転職して3年目の今の気持ち

## はじめに
どうもこんちは！
現在フリーランスとして開発系のエンジニアをやらせてもらってます。

久しぶりに記事でも書くかぁ～と思いましたが
まぁ技術的な記事を書く意欲はもちろん起こらないので、
日常というか今までの振り返りを書いていこうと思います。

エンジニアに転職して、2年半くらいになります。
今までの経歴や、どんな気持ちで仕事をしていたかなどを徒然なるままに書いていきます。

暇な人は見てやってください～

## 1年目
当時27歳になるタイミングで転職しました。
前職はコールセンターや通信系の営業をしており、IT系というかパソコンは苦手でしたｗ

転職のきっかけは親しい友人がエンジニアに転職して1年くらいたって、
まぁなんか良い感じで仕事していたんで、転職の1つの候補くらいでエンジニアを考えてました。

そんで未経験でもOKな会社に応募して、面接が通りました。
当時はよっしゃー！合格したぞー！とか思ってましたが、今思えば誰でも採用しているような感じでしたｗ

最初の1カ月は座学で勉強して、毎週テストがありました。
最初の2週間後のテストで不合格の人は不採用で去っていきましたｗ

2週間だけは試験期間で、そこから本採用という会社でしたｗ
まぁそこでエンジニアとしてというか、人として学習意欲があるのかどうかをチェックしていたんでしょうな。

2カ月目は経歴詐称のスキルシートを渡されて、それを元に面談練習をしました。
1カ月しか研修してないので、経歴3年のスキルシートはきついってｗｗｗ

まぁ当時はそんなもんかくらいで思ってました。
今も思えばアホですなｗ

そこからＳＥＳで客先常駐という形で配属になりました。
当たり前ですが、現場の求める能力と、自分のスキルが合っていないので
精神的に病んでいきました。

現場の同期や先輩にかなり助けてもらいましたが、私は結構限界きてました。
そんな中、社外の勉強会に参加したり、転職活動を進めていく中でとあるＣＴＯの方からお誘い受けて
業務委託という形で働くことに決めました。

ちょうどSES会社に転職して1年経ったくらいにそこを退職しました。
最初の1年目は精神的にかなり病んでましたなｗ

今振り返ると、もっとうまく立ち回れたなーとは思うけど、
当時の自分には難しかったなｗ

まぁ詐称はよくないっすわｗ
1年で見切りをつけて退職して良かったと思ってます。

ずるずる安月給で働いている先輩方を見ていましたが、正直思考停止してましたわ。
私と同時期にかなーりの人数が辞めたので、改めてヤバい会社だったなと思います。

## 2年目
ひょんなことからフリーランスになりましたｗ
元々はまともなSES会社に転職予定でしたが、どうせならチャレンジしてみるか！と思って飛び込みました。

仕事もフルリモートになったので、なんかエンジニアって感じだなと思いましたｗ

正直この1年間は自分にとってはかなり緩い感じの期間でした。
知り合ったCTOの方や、プロジェクトのリーダーも当時の自分にできる程度のタスクを振っていただいてたので、めちゃくちゃ忙しくて大変！という感じは少なかったです。

あとは経歴を詐称してないので、精神的にもかなり楽でした。
でも仕事をしていて単価に見合った仕事が出来てないなとひしひしと感じました。

そして単価は下がりましたｗ
まぁこれはしょうがないですねｗ

それでも1年目よりはかなり上がって生活にもゆとりができて、心も安定しました。
今振り返ると、2年目は心がとても安定していました。

自身で勉強会も積極的に開催して、交流会にも積極的に参加してました。

でも最後のほうは、なんか1カ月くらい思い切って休みたいと思い、仕事のやる気がなくなってきました。
そこでプロジェクトの途中ではあったのですが、退場して自分の為に時間を使うことにしました。

中途半端な形で退場してしまったのは申し訳なかったですが、
自分を守るためにもそのような決断にしました。

そこから1カ月ニートしながら転職活動をしました。
しかしなかなか面談が通らず、2か月目もニートになりましたｗｗ

5社面談したのですが、全て不採用で結構焦ってました。
6社目の面談が終わってあまり期待をしてなかったのですが、なんと採用！

っしゃあああああああああああ！！！と部屋の中で声でましたｗ

2年目は緩い感じの期間で、勉強もあまりしなくなりました。



## 3年目
3年目はレバテック経由で、採用も決まり結構緊張してました。
今はその現場に参画して、4カ月くらいなんですが、なんとかやれてます。

現場のメンバーのスキルが高いので、なんとかついていこうと頑張っています。

基本設計から経験できる現場なので、この現場でスキルアップして1年後の単価を上げて行きたいです！
プライベートでは筋トレを結構頑張ってます。

仕事もプライベートも充実させて、メリハリのある生活をしていきたいです。
エンジニアとしては、ようやく仕事の進め方がなんとなく見えてきたい感じがしています。

現場でどういう立ち回りをすれば評価が良くなるのか、そのアクションの方法など
これが1年目からできていたらなぁと思いますｗ

スキル的にはまだまだなので、現場のベテラン社員からどんどん吸収していきたいですね。


## これから
これからは自分の単価を上げる為に、設計を1人でできるように今の現場を頑張ります。
1年後くらいに転職活動してみて、単価70万くらいを目指します。

あとは、プライベートでも筋トレなど充実して健康な生活を送りたいっすね。


## おわりに
こんな感じでダラダラと書きましたw
また気が向いたら技術的なことも書いていきたいと思います。

最後まで読んでいただきありがとうございました！
今からはじめるvim入門　基礎編 （１）


## はじめに

vimを知らない人や、興味がある人向けに説明する記事です。

筆者も仕事上で使用していますが、とても便利で色々な人に知ってもらいと思い記事にしました！ また、復習や新たな発見も兼ねて書いて行きたいと思っています。

## vimとは
vim(ヴィム）と読みます。
ターミナル上で動作するCUIエディタです。CUIというのは、MacのターミナルやWindowsのコマンドプロンプトなどを指してます。
キーボードから手を離さずに操作することができ、大変便利です。
４つのモードを切り替えて操作します。覚えることは多いですが、慣れてしまえば効率よく作業が行えます。

## モードについて
基本的にはどのモードに移行するにもノーマルモードから移行します。

![vim_mode.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3758020/8b1771ad-7cb7-b0c9-9b77-b68c7c32b6da.jpeg)
<br>ここからは４つのモードについて解説します。
<br>

* ノーマルモード<br>
vimを起動した際の一番最初のモードです。
テキスト編集に特化したモードで、主にカーソル移動、ヤンク（コピー）、貼り付け、削除などが行えます。
**ESC**を押すことで各モードからノーマルモードに戻ります。
自分の操作が分からなくなり困ったらESCを連打しましょう！そうすれば道が開けるはず、、
<br>
主なコマンドは以下になります。

【カーソル移動】
|コマンド  |説明  |
|---|---|
|ｈ  |左に移動  |
|j  |下に移動  |
|k  |上に移動  |
|l  |右に移動  |
|0  |行の先頭に移動  |
|$  |行の末尾に移動  |
|^ |行の先頭（空白でない)に移動  |
|w |次の単語の先頭(空白でない)に移動  |
|e |次の単語の末尾(空白でない)に移動  |
|b |前の単語の先頭(空白でない)に移動  |
|f{文字} |次の{文字}に移動  |
|F{文字} |前の{文字}に移動  |
|gg |ファイルの先頭に移動  |
|G |ファイルの最終行に移動  |

数字入力後に押すとその数字分だけその操作を行います。
例：2w 2個目の単語の先頭に移動
f{文字}の次の移動を連続に行うには ; 戻るには , を入力
<br>
【ヤンク（コピー）、貼り付け、削除】
|コマンド  |説明  |
|---|---|
|y  |コピー  |
|p  |貼り付け  |
|d  |削除  |
|x  |１文字を削除  |

yyやddなど文字を連続で入力すると行のコピー、削除になります。
pやdで貼り付け、削除を繰り返す場合、. を使用します。
di]で[]の中身を削除できます。


【その他】
|コマンド  |説明  |
|---|---|
|g*  |カーソル上にある文字を検索  |
|gu  |小文字にする  |
|gU  |大文字にする  |
|r{文字}  |{文字}に置換する |
|>  |インデントを1つ追加(空行は含まない) |
|<  |インデントを１つ削除 |
|u  |undo |
|Ctrl+r  |redo |
|Ctrl+a  |カーソルの右側で一番近い数値をインクリメント |
|Ctrl+x  |カーソルの右側で一番近い数値をデクリメント |


　>Gでファイル末尾までインデント(空行は含まない)、>{数字}jで下に{数字}分インデントできます。

　<br>
* ビジュアルモード<br>
v、Ctrl+vなどでこのモードに移行します。
ノーマルモードのカーソル移動を使用して選択範囲を決めます。その後、yやdでコピー、削除などが行えます。
コピー、削除の動作を行った後はノーマルモードに戻ります。


<br>
下記のコマンドはすべてビジュアルモードに移行します。<br>

|コマンド  |説明  |
|---|---|
|v  |選択  |
|V  |行選択  |
|Ctrl+v  |矩形選択  |

　<br>
* 挿入モード<br>
i,aなどでこのモードに移行します。
文字の入力、削除などが行えます。

<br>
下記のコマンドはすべて挿入モードに移行します。

|コマンド  |説明  |
|---|---|
|i  |カーソルの前  |
|a  |カーソルの後  |
|o  |後に改行  |
|O  |前に改行  |
|cw  | カーソルの位置から文字列を削除 |
|ciw | カーソル上の文字列を削除 |

<br><br>
* コマンドラインモード<br>
：、/によってコマンドラインモードに移行します。
/の後の文字列を検索することが出来ます。
繰り返し行う場合、nで次を検索し、Nで前を検索します。
:はexコマンドと呼ばれており様々なことが出来るため、ここでは簡単なものだけ紹介します。

|コマンド  |説明  |
|---|---|
|:w  |ファイルを保存  |
|:w {ファイル名}|{ファイル名}で保存  |  |
|:wq |ファイルを保存して終了|
|:q! |ファイルを保存せずに終了|
|:{数字} |{数字}行目に移動|


-------------
今回紹介させて頂いたものはほんの一部でしかありませんが、基本的なvimの使い方は出来るようになるかと思います。
vimにはvimtutorという練習ツールがあるため、是非試してみてください。
筆者も覚えるのは大変でしたが、少しずつ出来ることが増える喜びがあり、苦痛ではありませんでした.（今もまだ新たな発見があります汗)
vimはコマンドの組み合わせによって色々なことが出来ます。興味のある方は調べたり使ってみたりして試してみるといいかもしれません。
次回はコマンドラインモードについてか、vimのカスタマイズ方法について書きたいと思います。(たぶん)
ForEachの箇所で発生するCannot convert value of type 'Range<Int>' to expected argument type 'Binding<C>' というエラーメッセージを解消した話

# 概要
タイトルのエラーがForEach文の箇所に出たのを解消しました。
![Group 10629.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576326/c1679da9-4e00-cca0-b847-4a3dd82399fc.png)
単純にForEach周りを修正するだけで解消されるエラーなら良いのですが、今回はそうではなかったため、メモとして残しておきます。

## 環境
MacBook M1
MacOS Sonoma 14.4.1
Xcode 15.3

# 詳細

パッとみた時にForEach周りの記述が誤っているのかと思いがちだが、実際にはForEach文内で記述している箇所に何らかのエラーが存在すると表示されるエラーになります。

私の場合はForEach内のButtonに対して`.accessibilityIdentifier()`を設定しようとした時に、`.accessibilityIdentifier()`内で使用している定数がプロジェクト内に存在しない状態でビルドをしようとしていたため発生していました。
プロジェクト内に定数を追加し、ForEach内のエラーとなる要素を全て排除した上でビルドを行った結果、タイトルのエラーが解消されました。
【ChatGPT＋DALL-E3】落書きから画像生成する。


　どうも、カーブミラーです。

　今回は、落書きから画像生成します。一昨日（2024/04/20）も書きましたが、肖像画的な感じでした。今回は、ポーズになります。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　一昨日（2024/04/20）
[【ChatGPT＋DALL-E3】ノートに描いた落書きから画像を生成してもらう。](https://qiita.com/kabumira/items/abe51bb36246a6ec03bc)
　　を書きましたね。

　昨日（2024/04/21）のお昼、
　　X-Twitter上で
　　　ChatGPT＋DALL-E3での
　　　　キャラにポーズをつける方法が
　　　　　ポストされました。
[理想のポーズを描く方法](https://twitter.com/BearDahlia05/status/1781878080879087933?t=1WmQovqIfGq0E67pDYq_sg&s=19)

　ここでは、
　　イラスト屋のイラスト画像と
　　　自分のキャラ画像を
　　　　使っていました。

　私は、
　　ポーズを探す手間が大変だ、と
　　　思い、落書きを選択しました。

　とはいえ、
　　一昨日の落書きを
　　　ごらんのように
　　　　うまくもありません。

　それでも
　　落書きなら
　　　手に覚えがあります。
***
　ということで
　　はじめていきますね。

　まずは、落書きを用意して
　　スマホカメラで撮影。

　ここは
　　お絵描きアプリなんかを
　　　使ってもいいかもしれません。

　では、はじめます。
***
***user***
![IMG_20240422_104508426.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/dbf66b9f-4736-4d5e-af57-106f434d1b33.jpeg)
このイラストのポーズを覚えてください。

***ChatGPT***
このイラストのポーズは覚えています。何か具体的な質問やリクエストがあれば教えてください。

***user***
ポーズを説明してください
（ここは私が確認したかったので）

***ChatGPT***
このイラストに描かれているのは、リラックスして座っている人のスケッチです。右膝は曲がっており、右足の裏が地面についています。左脚は横に伸ばされており、左足の側面が地面についています。腕は自然に体の前に置かれ、左腕は膝の上、右腕は右膝の横にあります。このポーズはカジュアルでリラックスした雰囲気を演出しています。

***user***
このポーズを実際の若い男性にさせてください。

***ChatGPT***
![1713754218275.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/326c358a-175f-0734-1a8e-cb9326a7d6ee.jpeg)

***user***（修正が必要だね）
左脚の側面が地面についている。正方形で描画

***ChatGPT***
![1713754232817.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/f31dddb0-0547-9b48-9f09-92f07b26dfee.jpeg)
***

　おおよその
　　ポーズになりました。

　ここでは、
　　ストレートに
　　　流しましたが、
　　　　実は紆余曲折ありました。

　まぁ、
　　主に、落書きのポーズを
　　　取らないこと、でしょうか😅

　そこは
　　指示をして
　　　修正していくしかありません。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。