OmniAICreator/Qiita-1.07M huggingface dataset:
「pread() read only *** of *** from ***」エラー対応

# tl;dr
* nginx.confの設定をデフォルト値に変更orコメントアウト： `output_buffers 2 32k;`

# 内容
なぜかBootstrapのcssだけ読み込めず、chromeで `ERR_EMPTY_RESPONSE` エラーが発生。nginx側では掲題のエラーが発生していた。
事象としては、nginxのgzip機能でCSSデータをzip化しようとする際に発生。
キャッシュ機能をオフ `open_file_cache off` にしてみたが、解決せず、読み込むバッファ値 `output_buffers` を調整／オフにしたら解決した。項目について、

http://mogile.web.fc2.com/nginx/http/ngx_http_core_module.html#output_buffers
> ディスクから応答を読み込むために使われるバッファの数 とサイズ を設定します。

との説明だが、ネットでも情報が少なく正直どういう項目か理解出来ていない。
この項目デフォルトのnginx.confにはそもそも項目がないためデフォルトはオフになっているのかもしれない。
ちなみにzip化処理のエラーのため、nginxのgzip機能をオフ `gzip off;` にすることでも一応解決はする。

# 環境

* nginx:1.15.8-alpine
* Docker Engine v20.10.24

# 参考
https://toritori0318.hatenadiary.jp/entry/20180603/1527963903
【Docker】「Docker Desktop starting…」が終わらず、最後にはtimeoutする

# 概要
DockerDesktopを起動しようととすると、「Docker Desktop starting…」が終わらず、終いには下記のようにtimeoutメッセージが出た。
```
An unexpected error occurred
A timeout occured while waiting for a WSL integration agent to become ready.

This can occur when starting after an abrupt termination. To work around the issue, please terminate WSL (wsl --shutdown) and start Docker Desktop again. If the issue persists please collect diagnostics and submit an issue (Overview ).

Error details:
1 error occurred:

starting WSL integration service: synchronising agents: starting added distros: 1 error occurred:
waiting for WSL integration for Ubuntu: waiting for WSL distro integration to become ready in “Ubuntu”: timeout
```

# 解決策
管理者で実行すると時間はかかったが起動した。
対症療法的で、原因は不明ながら、めんどうな作業をする前に試してみてください。
Railsで生SQLを書く際にヒアドキュメントを使う

## 問題
RailsでSQLを書きたくなった時、そのまま書いていくと横に長くなっていくため見づらい。、
以下の例程度であれば良いですが、joinが複数発生したりすると大変です。
```ruby
value1 = 10
value2 = 20
HogeHoge.find_by_sql("SELECT `id`, `value` FROM hogehoge WHERE `id` between #{value1} AND #{value2}"
```


## 対策
自分はヒアドキュメントを使い、以下のように書いています。

```ruby
value1 = 10
value2 = 20

sql = 
  <<~SQL.squish
    SELECT
      `id`, `value`
    FROM
      hogehoge
    WHERE
      `id` between #{value1} AND #{value2}
  SQL

=> "SELECT `id`, `value` FROM hogehoge WHERE `id` between 10 AND 20
```

`<<~`でインデントを付けても先頭のホワイトスペースを除去します。
`String#squish` で改行コードやタブを含む、先頭と末尾、連続したホワイトスペースを1つのスペースに変換します。（`.squish`をするので`<<~`ではなく`<<-`でも同様の結果になります。）
`SQL ~ SQL`とすることでエディタ上でSQLに対するSyntax Highlightが効くことが多いです。

ログ上では1行で表示され、余計な改行や空白を含まないSQLを見やすく書くことができました。


---
ちなみに自分はヒアドキュメントを引数に渡す場合、括弧をまたいでヒアドキュメントで書くよりも先に変数に入れてから渡すほうが好きです。
```ruby
HogeHoge.find_by_sql(<<~SQL.squish)
  ...
SQL

↓

sql = 
  <<~SQL.squish
    ...
  SQL
HogeHoge.find_by_sql(sql)
```
PHP の Carbon 型オブジェクトを使い回してはいけない

# Carbon 型に実装されているメソッドは破壊的メソッド

PHP で時刻を扱うには Carbon というライブラリが使用できます。

ですが、`Carbon\Carbon` 型のオブジェクトは可変 (mutable) であり、実装されているメソッドは破壊的 (destructive) メソッドのため、オブジェクトそのものの値が変更 (modify) されてしまいます。

> when you use a modifier on a Carbon instance, it modifies and returns the same instance
> https://carbon.nesbot.com/docs/

```php:carbon_example.php
<?php

require_once "vendor/autoload.php";
use Carbon\Carbon;

$now = Carbon::now();
print("now        = " . $now . "\n");

$myDatetime = $now->startOfHour();
print("now        = " . $now . "\n");
print("myDatetime = " . $myDateTime . "\n");

// 何なら代入する必要もない
$myDatetime->addMinutes(30);
print("now        = " . $now . "\n");
print("myDatetime = " . $myDateTime . "\n");
```

```bash
$ php -f carbon_example.php
now        = 2023-04-22 21:28:23
now        = 2023-04-22 21:00:00
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:30:00
myDatetime = 2023-04-22 21:30:00
```

ですので、値を再利用したい場合は copy() などを挟む必要があります。

```diff_php:carbon_example2.php
 <?php

 require_once "vendor/autoload.php";
 use Carbon\Carbon;

 $now = Carbon::now();
 print("now        = " . $now . "\n");

+// copy() を挟むことで元のオブジェクトに影響を与えない
-$myDatetime = $now->startOfHour();
+$myDatetime = $now->copy()->startOfHour();
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");

-$myDatetime->addMinutes(30);
+$myDatetime->copy()->addMinutes(30);
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");
```

```bash
$ php -f carbon_example2.php
now        = 2023-04-22 21:36:35
now        = 2023-04-22 21:36:35
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:36:35
myDatetime = 2023-04-22 21:00:00
```

# CarbonImmutable を使おう

しかし、それではくどいため CarbonImmutable を使うのが良いかもしれません。この型を使うと、`addMinutes` などのメソッドを呼び出しても元のインスタンスは変更されず、新しいインスタンスを戻り値として返します。

> when you use it on CarbonImmutable, it returns a new instances with the new value.

```diff_php:carbon_example3.php
 <?php

 require_once "vendor/autoload.php";
-use Carbon\Carbon;
+use Carbon\CarbonImmutable;

-$now = Carbon::now();
+$now = CarbonImmutable::now();
 print("now        = " . $now . "\n");

 $myDatetime = $now->startOfHour();
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");

 $myDatetime->addMinutes(30);
 print("now        = " . $now . "\n");
 print("myDatetime = " . $myDateTime . "\n");
```

```bash
$ php -f carbon_example3.php
now        = 2023-04-22 21:40:03
now        = 2023-04-22 21:40:03
myDatetime = 2023-04-22 21:00:00
now        = 2023-04-22 21:40:03
myDatetime = 2023-04-22 21:00:00
```

# おわりに

他にもハマりそうな人が居るかもしれない思ったので記事にしました。公式ドキュメントのかなり最初の方に書かれているので、もしかしたら自分以外の人はそんなミスは犯さないのかもしれませんが……orz
find_each

今まであまりよく考えずにfindやeachメソッドを使ってきましたが、find_eachの存在を知り、調べてみました。

結論としては、大量のデータを取得するときにfindやeachだとメモリを圧迫するので、メモリを節約しながら大量のデータを取得する場合にはfind_eachを使った方が良いようです。

:::note
find_eachメソッドは、大量のレコードに対してループ処理を実行したい場合にメモリ不足を防ぐことが出来るメソッド
:::

# find_each
大量のレコードを扱う場合に使用することができます。例えば、1万件以上のレコードがある場合に、allやeachを使うとメモリを圧迫してしまうことがありますが、find_eachを使うと一定数ずつレコードを取得しながら処理を行うことができます。

以下は、usersテーブルからidが1以上のユーザーを全て取得し、それぞれのnameを出力する例です。
```
User.where("id >= 1").find_each do |user|
  puts user.name
end
```
この例では、idが1以上のユーザーが膨大にいる場合でも、find_eachを使うことで、一度に取得するレコード数を制限しているため、メモリを圧迫することなく処理を行うことができます。


# じゃあ基本的にはfindeachを使うべき？
find_eachは膨大なレコードを処理する場合にメモリの使用量を抑えられるため、非常に有用です。

しかし、1つのレコードだけを取得する場合や、少数のレコードしか取得しない場合は、findの方がより簡潔かつ直感的です。つまり、データベースから取得するレコードの数によって、使い分けるべきです。
さらば学歴？　エンジニア採用の動向

学歴ではなくスキルで人材を確保したいー

日本ではコロナ後にこう考える経営者が増えている。

## 中小企業の嘆き
筆者がお会いした中小企業の経営者から、「DX化に対応しきれない」「うちにはDX人材がいない」といった悩みを聞くことがあった。続けて「アイデアはあるんだけどねぇ」と嘆く。

一方でIT系企業をはじめ、すでにDXの準備を整えていた企業には追い風が吹いている。大手保険会社の支店長は「お客様がオンライン商談に抵抗がなくなったことで、営業コストがぐっと下がった。商材をAIがおすすめするシステムも好評」と力を込めた。

## スキル人材を狙うには？
2023年4月14日付けの日本経済新聞には、スキル採用の例としてサイバーエージェント（以下、CA）を紹介している。CAでは来春入社予定者として、高校中退から42Tokyoを経た蔀綾人さんを採用した。

蔀さんが通学していた42Tokyoは、母体のフランスでは教育機関として認められ、世界中に支部が広がっている。1年半ほどの基礎課程ではC言語やLinuxを中心とした堅実な課題をクリアしていく。

42Tokyoのユニークな点は、教師がおらず、学生たちが協力し合う「ピアラーニング」を採用していること。六本木の高層ビルに設けられた教室は、24時間365日開かれ、エンジニア経験のない人たちにもその門下が開かれている。

ただし、4週間の入学試験「ピシン」は相当にハード。運営スタッフに話を伺ったところ、「合格者の特徴は、1日12時間ほどコードに向き合い続けている人たち」。さらにメンバー間でのコミュニケーションも重視される。入学後も、1日5時間以上の学習が必要。規定より学習が遅れた場合は、退校の憂き目にあう。

蔀さんのように、十分なハード／ソフトスキルを兼ね備えた人材が、スキル採用を突破する。

## いま、私たちは何をすべきか
スキル人材を狙うのであれば、”正しい自己研鑽”が必要だ。
キャリアの目標を明確化し、寄り道のないロードマップを描くことが得策と考える。

学習方法に関しては個人差がある。書籍や動画の自己学習でメキメキ力をつける者もいれば、42Tokyoのような学習機関に属する方が早く成長する者もいる。そのほかにメンターの利用、学習プロジェクトやセミナー、小規模な案件を獲得して学びながらお金を得る、といった選択肢が数多ある。

ブレない学習を続けるため、時には第三者の意見も大切。現役エンジニアや採用担当者とおしゃべりして、自分を鼓舞しよう。

いまの学びが、未来の自分に繋がっている。
prittier,blackを利用してvscodeのコードを綺麗に統一

# 〇prettier code formatter とblack
上記２つはどちらもコードを自動できれいに書き換えてくれる拡張機能です。インデントやスペースの数、「'」と「"」など、人によって書き方が違うコードを保存時に書き換えてくれます。

ただしpythonはprettier code formatteが非対応のため、blackを利用する必要があり、「基本的はprettier code formatteを使い、pythonの時のみblackを利用する」という設定をします。

## ・prettier code formatter
こちらは拡張機能からインストールを行います。
インストール後、左下にある歯車のマークをクリックして設定を開き、
上にある検索欄にて「editor.defaultFormatter」と検索し、「Prettier-Code Formatter」を選択します。
![1674787482211-Jmqo5Wv8Be.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/6c73b187-3914-0374-6144-f84ca05f16f2.png)
次に「editor.formatOnSave」と検索して「Format On Save」にチェックを付けます。これでファイル保存時にFormatterを適用する設定ができました。
![1674787587810-1YcJ1iJ6ys.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/c9526967-8448-62cf-e97b-b8620d35fe44.png)
## ・black
続いてblackはターミナルにて「pip3 install black」と入力します。
ダウンロードが終わったら先ほどのように設定を開き、「python.formatting.provider」と検索して「black」を選択します。
![1674787952448-MhQBGv5CWX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/ae1d8944-6093-e279-550b-6cbfb9371705.png)
Ctrl + Shift + Pを押して、上の検索欄にて「Preferences: Open User Settings (JSON)」と検索してクリックすると「settings.json」というファイルが開かれます。
「"[python]": { "editor.defaultFormatter": null },」を書き加えて保存してください。
![1674789653701-LWu56JnENK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120604/48675973-34c4-e5ea-aa5a-ce29669984ea.png)
※設定を色々変えている方はほかにもコードが記述されていると思いますが、とりあえず下の４行が書かれていれば大丈夫です。

これでpythonの時はblack、それ以外の時はprettierでフォーマットしてくれます。

※フォーマットしたくないファイルや一部分などを指定することもできます。
pythonの場合は「# fmt: skip」など、言語によって違うのでここでは割愛します。
アーリーリターンとは

## アーリーリターンとは

メソッドが実行中に特定の条件を満たした場合にその時点でメソッドから返すこと


・通常
メソッドは最後まで実行されてから返す値が決まる

・アーリーリターンを使う
特定の条件を満たした場合に、それ以降の処理をスキップして早期にメソッドを終了し値を返すことができる
→コードの可読性や保守性が上がる
GCPのストレージについて

# GCPのストレージについて
## ストレージ種類

1. ストレージを選択する時主な考慮事項はアクセス時間です。
    - ナノ秒（ns）、10⁻⁹秒
    - マイクロ秒（us）、10⁻⁶秒
    - ミリ秒（ms）、10⁻³秒
2. もう一つ考慮事項は永続性です。
    - キャッシュでが、データアクセスのレイテンシが最短であるが、サーバーがシャットダウンしたら、データが失われる
    - ディスクドライブの場合、耐久性は高いが、故障する可能性がある、この場合、冗長化でリスクが下げる
3. GCPのストレージサービスは以下通り。
    - キャッシュ用のマネージドRedisキャッシュサービス
        - MemorystoreとのマネージドRedisサービスです、１GB～30GBまで構成できる
    - 仮想マシンで使用するための永続ディスクストレージ
        - GCE,GKEの仮想マシンに接続永続ディスク
        - 接続永続ディスクはSSD及びHDD構成で使用できる、いずれも６４TBまで拡張できる。
        - 高いスループットが重要の場合、SDDを選択する
            - HDDではレイテンシが大きくなりますが、コストは下がる
            - 永続ディスクのデータは自動暗号化される
    - リソース全体でファイルへの共有アクセスを提供するオブジェクトストレージ
        - CGPはCloud Storageとのオブジェクト　ストレージサービスを提供する
        - Cloud Storageに格納されるファイルは原子性をもつ単位で取扱われます。
        - Cloud Storageは同時実行とロック機能はサポートされない。
        - バケットはCloud Storageの組織論理単位です、バケット名はグローバルで一意でなければならない
        - バケットはは実際のディレクトリーではないため、サブディレクトリーなの機能をサポートされない
        - Cloud Storage Fuseを使用すると、ファイルシステムとして、バケットをマウントして
          ファイルシステムコマンドを使用してファイルのアップロードとダウンロードすることができる
    - 長期にわたる、頻度が低いアクセス要件に対応するアーカイブストレージ
4. GCSの種別、以下通りである。
    - Standard
        - バケット作成する時、作成場所を指定して、バケットとその内容はこの場所に保存され、単一リージョン
          または複数リージョンにデータを格納することができる、リージョンバケットはゾーン全体冗長する
        - データは頻繁に使用される場合、利用される、ファイルのアクセスやアップロードの時
    - Nearline
    - Coldline
        - NearlineとColdlineはデータのアクセス頻度は低い時、使用される。
        - Nearlineは想定されるのは月1回未満との設計です
        - Coldlineは想定されるのは年1回以下との設計です

    以下の図は
5. バージョニングとライフサイクル
    - バケットのバージョニングは有効にすると、ファイルは削除、上書きされるたびに、オブジェクトのコピーがアーカイブされる
    - Cloud Storageには、ライフサイクル管理ポリシーも導入されている、このポリシーはルールの集合で、ルールには条件とアクションが含まれる

## ストレージデータモデル
1. GCP上使えるデータモデルは以下のカテゴリーである
    - オブジェクト
        - GCS（Cloud Storage）
    - リレーショナル
        - Cloud SQL
        - Cloud Spanner
            - Cloud SQLとCloud Spannerなどのリレーショナルデータベースは、トランザクションをサポートする
            - Cloud SQLはマネージドデータベースサービスであり、MySQLとPostgreSQLを提供する
              Cloud SQLは水平拡張できないが、垂直拡張（メモリ、CPU）に拡張できる
            - Cloud Spannerはグローバルで分散する必要がある、かつデータ量が非常に多い時、全てのサーバーで整合性とトランザクションの完全性を保証するため使用される、Cloud SQLと比べて、大幅にコストが高くになる
            - Cloud Spannerの構成では、インスタンス名、インスタンスID、Node数の指定は必須である
        - BigQuery
            - データウェアハウス及びアナリティクスアプリケーション向け設計されたサービスである
            - BigQueryはマネージドサービスで、ストレージだけではなく、クエリ、統計、器械学習分析ツールも提供
            - BigQueryを使用するには、まずデータを格納するデータセットを作成する。
    - NoSQL
      NoSQLデータベースはリレーショナルモデルを使用しないため、固定の構造やスキーマは必要なし 
        - Cloud Datastore
            - Datastoreはドキュメントデータベースであり、テキスト系のドキュメント保存ための意味ではなくドキュメントはキーと値のペアで構成される。
            - Datastoreを使うため、Entityを作成する必要があり
        - Cloud Filestore
            - Cloud FilestoreはマネージドNoSQLデータベースであり、ドキュメントデータモデルを使用する
            - Cloud Filestoreは分散されて、データを格納、同期、参照するために設定された
            - Cloud Filestoreはトランザクションをサポートし、マルチリージョンのレプリケーションも実現
        - BigTable
            - Bigtableは別のNoSQLデータベースで、Datastoreと異なって、ドキュメント構造ではなく、列指向データベースです、多数の列を含むテーブルを格納する
            - Bigtableはデータ量が多く、データの取り込みが高速で実行されるため設計されて、整合性ありかつサブミリ秒のレイテンシを実現する
            - インスタンス名とIDを指定、本番モードまたは開発モードを選択できる、本番クラスタでは最低３つクNode

2. GCP上ストレージソリューション選択時のガイドライン
    - 読み書きパターン
    - 整合性
    - トランザクションサポート
    - コスト
    - レイテンシ
Laravel、Opensearch間の認証の高速化

### 背景
EC2上のLaravelからOpenseachへの接続をしたいので、認証を行いたい。

### 不具合
最初の認証だけリクエストに1s近い時間がかかってしまう。

### 原因、解決法
普通にAWSの不具合ぽい。
EC2のhop limitがデフォルトで1になっているので、
```
aws ec2 modify-instance-metadata-options
        --instance-id YOUR-INSTANCE-ID \
    --http-put-response-hop-limit 3 
```
でhop limitを２以上にすると認証時の遅延無くなる

### 参考記事
https://github.com/aws/aws-sdk-php/issues/2506
ファイル名を小文字から大文字にリネームしてSVNコミット

開発環境：Eclipse
開発言語：Java
ファイル名の一部を小文字から大文字にリネームし、SVNコミットしようとすると、リネーム前のファイルが消えリネーム後のファイルはコミットされない問題が発生しました

～原因～
大文字、小文字の差異があってもファイルの違いをSVNが認識できないため、リネーム後のファイルも削除されてしまう
～解決方法～
リネーム前のファイルを削除した後、リネーム後のファイルをコミットするようにする
コーディング練習_1日目

# はじめに
コーディング練習１日目です。

# コーディング内容
リスト内の数字の中で、値の大きなもの２つの差をリストに追加していき、使用した値の大きなもの２つはリストから除外する。
この処理を繰り返していき、最後にリストに残った値を出力する。

# 実装
```python:sample.py
# 関数内で型明示する
from typing import List

class Solution:
    def lastStoneWeight(self, stones: List[int]) -> int:
        def remove_largest():
            # リストの最大値が入っているインデックス番号を取り出す。
            index_of_largest = stones.index(max(stones))
            # 一番重い石が取り除かれるように、順番を入れ替える。
            stones[index_of_largest], stones[-1] = stones[-1], stones[index_of_largest]
            # 引数を指定しない場合、リストの最後の値が取り除かれる。
            return stones.pop()

        while len(stones) > 1:
            stone1 = remove_largest()
            stone2 = remove_largest()
            # もし上位２つの重さの石の差が異なるなら、
            if stone1 != stone2:
                # その差をリストに加える。
                stones.append(stone1 - stone2)

        # リストに残った最後の要素を返す
        return stones[0] if stones else 0

# テスト
if __name__ == "__main__":
    list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
    print(Solution().lastStoneWeight(list1))
```

# ポイント
```python:
# リストの用意
stones = [1,2,3,4,5,6,7,8,9,12,10]

# 対象の数字が入っているインデックス番号を返す。
stones.index(12)
# 出力：9

# インデックス番号を指定しなければ、最後の要素が取り除かれる。
stones.pop()
# 出力：１０

# もしリスト(stones)があるなら１を、それ以外の場合は0を返す。（結果、条件式の書き方）
stones[0] if stones else 0
```

# 参考
https://leetcode.com/problems/last-stone-weight/
pythonで基本波抽出

# pythonで基本波(第一高調波)を抽出する

pythonには非常に便利なライブラリがたくさんありますが，基本波波形を抽出するものを見つけられなかったので実装してみました。
pythonの練習にも良いかも...

今回はcsvファイルで準備したダミー波形から基本波を抽出してみたいと思います！

ダミー波形はこんな感じ...
完全に自分用なのできっちり１周期分のデータじゃないとうまく動きません:sweat_smile:
2deg刻みで１周期分(358degまで)の180点としてみました。

<img width="200" alt="dummy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/9913482a-7293-18da-bdfb-60ccc39438f0.png">


フーリエ級数展開のn=1まで足し合わせたものが基本波なので，numpyを使って計算する関数はこんな感じになります...

```python:BASIC_WAVE.py
def BASIC_WAVE(data):
    x = data[:, 0]
    y = data[:, 1]

    #周期T
    T = x[-1] #x最後の値
    pi = np.pi
    
    #各係数を計算
    a0 = 2/T * np.sum(y*np.cos(0*2*pi*x/T))
    a1 = 2/T * np.sum(y*np.cos(1*2*pi*x/T))
    b1 = 2/T * np.sum(y*np.sin(1*2*pi*x/T))
    
    #基本波(第一高調波)
    Y = a0/2 + a1 * np.cos(2*pi*x/T) + np.sin(2*pi*x/T)
    
    return x, Y
```

とてもシンプルでスバラシイ✨

実際に使ってみるとこんな感じ...
```python:test.py
#元データファイル名(pythonプログラムと別の階層ならパス)
raw = 'dummy.csv'

#元データをnumpy配列として読み込み
data = pd.read_csv('dummy.csv',encoding='shift_jis',index_col=None).values

#基本波を計算
#元データファイル名(pythonプログラムと別の階層ならパス)
raw = 'dummy.csv'

#x,yラベルを取得(無理やりですみませんm(__)m)
data = pd.read_csv(raw,encoding='shift_jis',index_col=None)
xlabel = data.columns.values[0]
ylabel = data.columns.values[1]

#元データをnumpy配列として読み込み
data = pd.read_csv(raw,encoding='shift_jis',index_col=None).values

#基本波を計算
x, Y = BASIC_WAVE(data)

#波形表示
%matplotlib inline#jupyterじゃない場合は不要
plt.rcParams['font.family'] = ['IPAexGothic']
plt.rcParams['figure.figsize'] = [8, 6]
plt.style.use('ggplot')

fig, ax = plt.subplots()
ax.plot(x, data[:,1]) #元波形プロット
ax.plot(x, Y)         #基本波波形プロット

plt.ylabel(ylabel)#タテ軸のラベル
plt.xlabel(xlabel)#ヨコ軸のラベル
plt.show()
```
:::note warn
jupyter notebookでの使用を想定しています。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485281/d5e2a2ec-6db2-fd77-cc28-682ce8ac1f81.png)


基本波計算できました！
良い感じではないでしょうか。

では，お疲れ様でした！
【Amazon Linux 2023】EC2からmariaDBへ接続方法

# 背景
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/hosting-wordpress-aml-2023.html

このドキュメントを参考に、Amazon Linux 2023でwordpressをインストール時に、以下の局面で問題が起きた。
![スクリーンショット_2023-04-24_9_46_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779582/c4b11fed-2938-3ad8-b4fe-060a6e32cbf4.png)
mysqlニワカな自分が原因で、馬鹿正直に「mysql -u root -p」を打ったら以下の始末に追われてしまったのである。
![スクリーンショット_2023-04-24_10_01_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779582/40f5d47e-17e8-0a53-86c0-ef3ee7382798.png)

この時passwordには、「password」と入力してみたり、何も打たずにEnterだけ押したりとしてみたのだが、うまくいかず...。

# 解決策
```
sudo su -
```
このコマンドでルートユーザーに切り替え、
```
mysql -u root -p
```
再度コマンドを入力。
パスワードを求められるので、spaceキーを一回だけ打ってEnterキーを打つ。
![スクリーンショット_2023-04-24_10_10_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779582/ace40c57-2a2d-7534-73dc-15a1ea641a1e.png)
上手くいきました。
つまりデフォルトのパスワードには、半角1文字分の空文字が指定されていたのですね。

最終的に、以下のコマンドでパスワードを設定することにより、
```
ALTER USER 'root'@'localhost' IDENTIFIED BY '設定するパスワード';
```
次回以降、パスワードを求められた際、「設定するパスワード」でログインすることができるようになります。

![スクリーンショット_2023-04-24_10_15_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779582/7760920c-ab9c-66de-52b1-6b20953a0856.png)

例えばこんな感じでパスワードを設定することによって、次回パスワードを求められた際は、「password」と入力してログインできるようになります。
デリバリー・パフォーマンス領域

# 初めに
記事をご覧いただきありがとうございます！
PMBOK第７版を元にプロジェクト・マネジメントについて勉強しております。
章立てでまとめておりますので、ご自身のあったものをご覧ください。

#### ステークホルダー
https://qiita.com/ryota_haga/items/b8d6e8c0919d5c45c10c
#### チーム
https://qiita.com/ryota_haga/items/c6d5876b461f760e0d11
#### 開発アプローチとライフサイクル
https://qiita.com/ryota_haga/items/345595cb69ef196ffda2
#### 計画
https://qiita.com/ryota_haga/items/a408b24c5dc2bfaa2a50
#### プロジェクト作業
https://qiita.com/ryota_haga/items/bec958cc55f3c6b04406
#### デリバリー
https://qiita.com/ryota_haga/items/0c5574e2f1c5e4960a41
#### 不確かさ
〜作成中〜

# 6 デリバリー・パフォーマンス領域における成果
〜更新中〜

# 引用
- [プロジェクトマネジメント知識体系ガイド（PMBOKガイド）第7版＋プロジェクトマネジメント標準](https://www.pmi-japan.shop/shopdetail/000000000028/)


# 関連記事
- [概要](https://qiita.com/ryota_haga/items/31b40dd5b20a75739619)
- [1.ステークホルダー・パフォーマンス領域](https://qiita.com/ryota_haga/items/b8d6e8c0919d5c45c10c)
- [2.チーム・パフォーマンス領域](https://qiita.com/ryota_haga/items/c6d5876b461f760e0d11)
- [3.開発アプローチとライフサイクル・パフォーマンス領域](https://qiita.com/ryota_haga/items/345595cb69ef196ffda2)
- [4.計画パフォーマンス領域](https://qiita.com/ryota_haga/items/a408b24c5dc2bfaa2a50)
- [5.プロジェクト作業パフォーマンス領域](https://qiita.com/ryota_haga/items/bec958cc55f3c6b04406)
- [6.デリバリー・パフォーマンス領域](https://qiita.com/ryota_haga/items/0c5574e2f1c5e4960a41)
packer.nvimのUndefined global `use`への対応

# はじめに
2ヶ月ほど前、以下の記事を読んでVimに興味を持ちました。

https://note.com/navitime_tech/n/nf6cae399ae75

私の中でのそれまでのVimのイメージは、「大学の講義で使ったことがある（しかし定着しなかった）Emacsのライバル」であり「新人研修で遭遇した閉じれなくなった過去があるエディタ」でしたが、上記の記事を読んで、それまで使っていたVSCodeからすぐに乗り換えることは難しそうだけど「慣れると早そうだな」と感じたことを覚えています。

その後、@yutkatさんの書かれた以下の記事を読み、VSCodeでVim（Neovim）を使える[VSCode Neovim](https://marketplace.visualstudio.com/items?itemName=asvetliakov.vscode-neovim)を知りおよそ1ヶ月使用した後に、最近では徐々に[Neovim](https://neovim.io/)自体へのエディタの移行を進めています。

https://zenn.dev/yutakatay/articles/vscode-neovim

# packer.nvimについて
Neovimのプラグインマネージャについて、Vim scriptよりLuaで設定を書いてみたかったこともあり、私は[packer.nvim](https://github.com/wbthomason/packer.nvim)を使っています。packerはコマンドでのプラグイン管理を始め、Neovim標準のプラグイン管理機能に対して様々な追加機能を提供してくれます。以下の記事を参考にさせていただき、導入に至りました。

https://qiita.com/delphinus/items/8160d884d415d7425fcc

# Undefined global \`use\`について

packerでは`packer.startup`で受け取った関数内でuse関数を使うことでプラグインを読み込みます。その際に私の環境では以下のようなWarningが頻発していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2304176/ac85ae75-ae91-111e-c321-3cc237cdf502.png)

プラグインのロード自体に問題はなかったのですが、あまり気持ちのいいものではないですよね。

# 対処

調べてみたところ、以下のIssueを見つけました。

https://github.com/wbthomason/packer.nvim/issues/243

上記によれば、

- この事象`packer.startup`に渡された関数内で使用されたuse関数をlspが認識できず発生しており、以下のいずれかによって解消できる。
  1. lspのグローバルにuseを追加する
  1. `packer.startup`に渡す関数がuseを受け取るようにする（推奨🌟）


とのことです。

実際に、下記のように`packer.startup`に渡す関数にuseを渡すことで、このWarningは解消することができました。

``` lua
packer.startup(function(use)
  use 'XXX/YYY'
end)
```

# おわりに

2021/3/4にCloseされた上記のIssue以降に、packerのリポジトリのREADMEには以下のような記述が追加されています。

> Note that if you get linter complaints about use being an undefined global, these errors are spurious - packer injects use into the scope of the function passed to startup. If these errors bother you, the easiest fix is to simply specify use as an argument to the function you pass to startup.

よって、現在は公式に解決済みの問題となりますが、参考にする情報の更新時期やlspとの組み合わせによっては、同様の問題が発生し得ると思い記載しました。まだまだ初心者ですが、少しずつVimスキルも向上させていきたいです💪
RubyでAtCoder ABC275(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC275のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Find Takahashi
https://atcoder.jp/contests/abc275/tasks/abc275_a
```ruby:a-275.rb
gets
h = gets.split.map(&:to_i)
puts h.index(h.max) + 1
```
## 解説
問題文に高さは相異なるとあるので、`h.max`で最大の高さを求めindexメソッドを使ってその位置を出力すればOKです。

# B - ABC-DEF
https://atcoder.jp/contests/abc275/tasks/abc275_b
```ruby:b-275.rb
a, b, c, d, e, f = gets.split.map(&:to_i)
puts ((a * b * c) - (d * e * f)) % 998244353
```

# C - Counting Squares
https://atcoder.jp/contests/abc275/tasks/abc275_c
```ruby:c-275.rb
array = Array.new(9){ gets.chomp }

ans = 0
9.times do |i|
  9.times do |j|
    next if array[i][j] == "."
    (i + 1).times do |y|
      for x in j + 1..8
        next if array[y][x] == "."
        dy = i - y
        dx = x - j
        ii = i + dx
        jj = j + dy
        yy = y + dx
        xx = x + dy
        ans += 1 if ii < 9 && jj < 9 && yy < 9 && xx < 9 && array[ii][jj] == "#" && array[yy][xx] == "#"
      end
    end
  end
end
puts ans
```
<追記>
ブロック付きcountを使った別解になります。
```ruby:別解1
array = Array.new(9){ gets.chomp }
points = []
9.times do |i|
  9.times do |j|
    points << [i, j] if array[i][j] == "#"
  end
end

def d(x, y, nx, ny)
  (nx - x) ** 2 + (ny - y) ** 2
end

ans = points.combination(4).count do |(x0, y0), (x1, y1), (x2, y2), (x3, y3)|
  # 以下、３つの条件(位置の条件、長さの条件、対角線の長さの条件)を検証
  x3- x2 == x1 - x0 && y3 - y2 == y1 - y0 && x3- x1 == x2 - x0 && y3 - y1 == y2 - y0 &&
  d(x0, y0, x1, y1) == d(x0, y0, x2, y2) && d(x0, y0, x1, y1) == d(x2, y2, x3, y3) && d(x0, y0, x1, y1) == d(x1, y1, x3, y3) &&
  d(x0, y0, x3, y3) == d(x1, y1, x2, y2)
end
puts ans
```
```ruby:別解２
array = Array.new(9){ gets.chomp }
points = []
9.times do |r|
  9.times do |c|
    points << [r, c] if array[r][c] == "#"
  end
end

ans = points.combination(4).count do |(r0, c0), (r1, c1), (r2, c2), (r3, c3)|
  dr = r1 - r0
  dc = c1 - c0
  next if r3 - r2 != dr || r2 - r1 != dc.abs - dr || c3 - c2 != dc
  
  if dc >= 0
    c1 - c2 == dc + dr.abs
  else
    c2 - c1 == dc.abs + dr.abs
  end
end
puts ans
```
<追記>
コメントでいただいた別解になります。
```ruby:別解3
require "matrix"

def get_4_apexes(x, y)
  (1..8).each do |len|
    (1..len).each do |vx|
      v = Vector[vx, len - vx]
      pt = Vector[x, y]
      apexes = 4.times.map {
        pt += v
        v = Matrix[[0, -1], [1, 0]] * v
        pt
      }
      f = apexes.all? {|pt|
        0 <= pt[0] && pt[0] <= 8 && 0 <= pt[1] && pt[1] <= 8
      }
      yield(apexes) if f
    end
  end
end

field = Array.new(9) { gets.chomp }

puts 8.times.sum {|x|
  8.times.sum {|y|
    enum_for(:get_4_apexes, x, y).count {|apexes|
      apexes.all? { |pt| field[pt[1]][pt[0]] == "#" }
    }
  }
}
```
## 解説
（他の方の提出結果を参考にしました）

ｙは前の行、xは後ろの列を表し、`array[i][j]=="#"`かつ`array[y][x]=="#"`であるような位置で正方形の4点の内2点を固定します。そして、正方形であることを利用してiとyの差分dyおよびjとxの差分dxから残った2つの点(ii,jj)と(yy,xx)を求めます。最後に、これらの点が縦横の大きさがともに9の二次元平面内にあればansをインクリメントします。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
moonlander の配置


Ctrl + ` を設定して、
それを英数キーとして使えば
ワンクリックで 日本語、英語の切り替えができます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592558/85657037-8c6e-cefa-ad20-ef108f66c911.png)
GiNZA を HTTP Server 化する ginzaserver 2023年令和最新版

# 目的 Objective

自然言語処理エンジンの GiNZA をPythonに依存せず、また複数台での処理やタンタイムプラットフォームに依存しない仕組みを作ることが目的です。JavaやC#などの環境からもGiNZAを利用できます。

Mecab, Cabocha と比較してセットアップも容易です。


https://megagonlabs.github.io/ginza/

# インストール

## GiNZA のインストール

```
pip install -U ginza ja_ginza
pip install -U ginza ja_ginza_electra
```

## ginzaserver のインストール

```
pip install git+https://github.com/oyahiroki/ginzaserver
```
# ginzaserver の起動

```
ginzaserver 8888 0
```

一つ目のパラメータにはサーバーのポート番号、
二つ目のパラメータには利用するエンジンのオプションを指定します。

オプション0 : 実行速度重視モデル
pip install -U ginza ja-ginza
オプション1 : 解析精度重視モデル (メモリ容量16GB以上を推奨)
pip install -U ginza ja-ginza-electra

解析精度重視モデルの場合、手元での測定では２～４倍の処理時間になります。

# ginzaserver を利用する

以下のようなHTTP POSTまたはHTTP GETで利用できます。
処理対象テキストのサイズが大きくなる場合はPOSTを利用してください。

POST
```
curl -X POST -H "Content-Type: application/json" -d "{'text':'今日はいい天気です'}" http://localhost:8888/
```

GET
```
curl http://127.0.0.1:8080/?text=%E3%81%93%E3%82%8C%E3%81%AF%E3%83%86%E3%82%B9%E3%83%88%E3%81%A7%E3%81%99%E3%80%82
```

# 結果

GiNZAを直接Pythonで実行したときと同じJSONが返ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/cf291be0-28f9-2942-2f12-1a611cf44b3d.png)

# Ginza をJavaから利用する

Java 向けには専用のJSONパーサーを準備中です。

https://github.com/oyahiroki/nlp4j/tree/master/nlp4j/nlp4j-ginza

# ソースコード

中身がどんなものか心配な方はソースコードをご確認ください

https://github.com/oyahiroki/ginzaserver

---

以上


# 参考になるかもしれない記事

https://qiita.com/oyahiroki/items/9ded9204551dbcea1a70
ORACLEのDBに登録されるCLOB型のデータを文字列で取得する方法

使用しているDB:Oracle

substar関数を使いDBで設定されているVARCHARの桁数で分割して取得する

```sql:select
select
  DBMS_LOB.SUBSTR(NAIYOU_SYOUSAI, 120, 1) AS 詳細1
  , DBMS_LOB.SUBSTR(NAIYOU_SYOUSAI, 120, 121) AS 詳細2 
from
  TABLE_SIEN 
ORDER BY
  UPD_DATE DESC offset 1 rows fetch next 2 rows only
```
offsetはスキップする行
fetch nextは読み込む行数
フォルダの移行バッチ組んでみた(自分用に)

@echo off

:input_source
set /p source="コピー元フォルダのパスを入力してください: "

if not exist "%source%" (
    echo "%source%"が見つかりませんでした。再度入力してください。
    goto input_source
)

:input_destination
set /p destination="コピー先フォルダのパスを入力してください: "

if not exist "%destination%" (
    echo "%destination%"が見つかりませんでした。再度入力してください。
    goto input_destination
)

set /p foldername="新しいフォルダの名前を入力してください: "
set destination=%destination%\%foldername%

if not exist "%destination%" (
    mkdir "%destination%"
)

echo *******************************
echo *     コピーするファイル一覧    *
echo *******************************
echo.

set /p secmove="コピー時にアクセス許可を継承する場合は/sec、移動する場合は/moveを指定してください。(指定しない場合はEnterを押してください): "
set /p secmove2="アクセス許可の継承と移動を両方行う場合は/secmoveを入力してください。(指定しない場合はEnterを押してください): "

if /i "%secmove2%"=="/secmove" (
    robocopy "%source%" "%destination%" /E /COPYALL /DCOPY:T /R:3 /W:10 /V /LOG+:%~dp0\robocopy.log /L /NP /TEE /XO /XF /XD /TS /FP /BYTES /NS /NC /NJH /NJS /SEC /MOVE
) else if /i "%secmove%"=="/sec" (
    robocopy "%source%" "%destination%" /E /COPYALL /DCOPY:T /R:3 /W:10 /V /LOG+:%~dp0\robocopy.log /L /NP /TEE /XO /XF /XD /TS /FP /BYTES /NS /NC /NJH /NJS /SEC
) else if /i "%secmove%"=="/move" (
    robocopy "%source%" "%destination%" /E /COPYALL /DCOPY:T /R:3 /W:10 /V /LOG+:%~dp0\robocopy.log /L /NP /TEE /XO /XF /XD /TS /FP /BYTES /NS /NC /NJH /NJS /MOVE
) else (
    robocopy "%source%" "%destination%" /E /COPYALL /DCOPY:T /R:3 /W:10 /V /LOG+:%~dp0\robocopy.log /L /NP /TEE /XO /XF /XD /TS /FP /BYTES /NS /NC /NJH /NJS
)

echo.
echo *******************************
set /p confirm="上記のファイルをコピー/移動しますか？ (Y/N): "

if /i "%confirm%"=="Y" (
    echo コピー/移動を開始します...
) else (
    echo コピー/移動をキャンセルしました。
SonarQubeでvm.max_map_countのエラーが出た時の対処法

docker-composeでSonarQubeを起動した時にvm.max_map_countに関するエラーが出て躓いたので、備忘録がてら記録。

## SonarQubeの起動
以下のdocker-compose.ymlを作成。9000ポートは別のアプリ(MinIO)で利用していたので9999ポートを利用。
```yaml
version: "3"
services:
  sonarqube:
    image: sonarqube:community
    hostname: sonarqube
    container_name: sonarqube
    depends_on:
      - db
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
    ports:
    - "0.0.0.0:9999:9000"
  db:
    image: postgres:13
    hostname: postgresql
    container_name: postgresql
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
      POSTGRES_DB: sonar
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data

volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  postgresql:
  postgresql_data:
```
以下のスクリプト経由で起動。
```sh
#!/bin/bash
set -ex
if [ "$1" == "up" ]; then
  docker-compose up -d --build
elif [ "$1" == "down" ]; then
  docker-compose down
fi
````
この状態でlocalhost:9999にcurlしても通らない。
`docker logs`で状態を確認する。

```sh
$ docker logs 862e55b4b91e
：（省略）
[2023/04/24 8:23:55.829 AM] bootstrap check failure [1] of [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
[2023/04/24 8:23:55.829 AM] ERROR: Elasticsearch did not exit normally - check the logs at /opt/sonarqube/logs/sonarqube.log
：（省略）
2023.04.23 23:36:03 INFO  app[][o.s.a.SchedulerImpl] Process[ElasticSearch] is stopped
2023.04.23 23:36:03 INFO  app[][o.s.a.SchedulerImpl] SonarQube is stopped
```
ElasticSearchが落ちていた。プロセスが利用可能なマップ領域が不足している模様。
検索すると、以下の文献が見つかった。
[Elasticsearch の max_map_count パラメータの変更](https://techdocs.broadcom.com/jp/ja/ca-enterprise-software/it-operations-management/digital-operational-intelligence/1-2/481537750/481537753/504650229/504650233.html)

`/etc/sysctl.conf`に`vm.max_map_count = 262144`を追記して再起動する。
今度は無事にcurlが通った。
```
$ curl localhost:9999

<!DOCTYPE html>
<html lang="en">
：（省略）
```
yarn のレジストリ修正とか

# yarnとnpmはやれることは同じ

基本的にyarnpkg,npmはやれることは同じです。

# 今回起きた問題

```
info No lockfile found.
[1/4] Resolving packages...
error An unexpected error occurred: "http://localhost:4873/@mui%2fmaterial: connect ECONNREFUSED ::1:4873".
info If you think this is a bug, please open a bug report with the information provided in "C:\\Users\\nknig\\_varius\\V\\yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

```

これは前にデバックのしやすさの為にローカルでライブラリを管理していたのですが、それでレジストリの修正をしたのが原因だったようです。

もとに戻します()

# やり方

```
npm config set registry "http://registry.npmjs.org/"
```
これだけです。
ちなみにgithub packagesを使っている人は npm.pkg.github.comになるっぽいです。適宜読み替えてくださいナ。

それじゃ👍

## 参考記事

https://qiita.com/ymaru/items/cf513ab05fe0ebac7d3b

## 個人PJ

https://github.com/nknighta/v
vbsの作法 その61

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
sin波を描画せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e97c1df5-532d-497c-e6bb-d06068e53029.png)


# サンプルコード

```


Dim objIE
Set objIE = WScript.CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.Menubar = false
objIE.Toolbar = false
objIE.Navigate "about:blank"
objIE.Document.Write "<html><head></head><body>"
objIE.Document.Write "<canvas id=""canvas"" width=""300"" height=""300""></canvas>"
objIE.Document.Write "<script type=""text/javascript"">"
objIE.Document.Write "var canvas = document.getElementById(""canvas"");"
objIE.Document.Write "var ctx = canvas.getContext(""2d"");"
objIE.Document.Write "function draw(data) {"
objIE.Document.Write "    ctx.strokeStyle = ""#f0f"";"
objIE.Document.Write "    ctx.lineWidth = 2;"
objIE.Document.Write "    ctx.moveTo(0, 150);"
objIE.Document.Write "    for (var i = 1; i < canvas.width; i++)"
objIE.Document.Write "    {"
objIE.Document.Write "        ctx.lineTo(i, 150 - data[i] * 30);"
objIE.Document.Write "    }"
objIE.Document.Write "    ctx.stroke();"
objIE.Document.Write "}"
objIE.Document.Write "var src = ["
ds = 220 * 2 * 3.1415 / 8000
s = 0
for i = 0 to 300
	v = Sin(s)
	objIE.Document.Write CStr(v) + ","
	s = s + ds
next
objIE.Document.Write "];"
objIE.Document.Write "draw(src);"
objIE.Document.Write "</script></body></html>"
Do While objIE.Busy
    WScript.Sleep 100
Loop
'iHtml = objIE.Document.body.innerhtml
'msgbox iHtml
Set objIE = Nothing





```

以上。
vbsの作法 その60

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
Windows11でInternet Explorer11を起動して、htmlを流し込め。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/45433ee4-8cc6-b444-bd35-c6d4fe25e340.png)

# サンプルコード

```
Dim objIE
Set objIE = WScript.CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.Menubar = false
objIE.Toolbar = false
objIE.Navigate "about:blank"
objIE.Document.Write "<html>" & vbcrlf
objIE.Document.Write "<head>" & vbcrlf
objIE.Document.Write "<title>タイトル</title>" & vbcrlf
objIE.Document.Write "</head>" & vbcrlf
objIE.Document.Write "<body>" & vbcrlf
objIE.Document.Write "<table border=4 width=""100%"" height=""100%"">" & vbcrlf
objIE.Document.Write "<tr>" & vbcrlf
objIE.Document.Write "<td align=""center"" valign=""middle"">" & vbcrlf
objIE.Document.Write "<font size=+4>Hello world!</font><br>" & vbcrlf
objIE.Document.Write "</td>" & vbcrlf
objIE.Document.Write "</tr>" & vbcrlf
objIE.Document.Write "</table>" & vbcrlf
objIE.Document.Write "</body>" & vbcrlf
objIE.Document.Write "</html>" & vbcrlf
Do While objIE.Busy
    WScript.Sleep 100
Loop
Set objIE = Nothing


```

以上。
Power Virtual AgentsとPower Automateを連携する

### はじめに

前回、[Power Virtual Agents for Teamsを使ってチャットボットを作成しました](https://qiita.com/k-kimino/items/c8788d466fceb9441724)。今回はPower Automateと連携することでできる幅を広げます。

### Power Automateのフローを作成する

#### Power Virtual AgentsからPower Automateを呼び出す
Power Virtual AgentsからCall an actionでPower Automateのフローを作成します。
![CallPowerAutomate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/cf6438f1-a594-8616-8233-93cfec7afa29.png)

#### Power Automateのフローを作成する

まずはできるだけシンプルに連携したいので単に文字列を返すだけの処理を作成しました。
![SimpleFlow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/8d768a4b-ef1c-e303-9761-12fcf5a75fbe.png)

#### Power Automateの処理をPower Virtual Agentsのフローの中に組み込む

最後に作成したPower Automateの処理をActionとしてPower Virtual Agentsのフローに組み込みます。Power Automateで作成した処理がPower Virtual Agentsのトリガーによって呼び出され、結果がPower Virtual Agents側で取得できていることがわかります。
![PVA+PA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/8138fbb9-3bab-007b-7a02-5312fc19b9c6.png)

### まとめ

今回はPower Virtual AgentsとPower Automateを連携させました。難しい処理は書いていないので簡単に、さらにTeamsの中のアプリから完結させることができました。Power Automateの良さはM365や外部サービスとの連携にあると思うのでこれを基盤にPower Automate側の処理を高度化させることでもっと複雑なことがノーコードで実現できそうです。
Power of One

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)



+ [Average Number of Activities on Leads](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7hzaSAB)
+ [クローズされた商談あたりのタスクの平均数](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A8JJVSA3)

+ [アカウントごとの平均アクティビティ数を作成する方法](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PeMvA)

# 意義

+ [Power of One](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PkofD)

:::note
Check the checkbox Sum and click on apply. Now save and run your report to see the magic. When you scroll to the very bottom of your page you will now see two numbers. One being the classic record count as we know it, in this case counting each contact held in the report. And a second one which is the SUM of the Power of One for each individual account record. This number is logically lower (or the same) than the total count of the child records and gives you the total of accounts in your report. 

https://www.radnip.com/the-power-of-one-the-best-reporting-trick-of-all-time/

チェックボックス合計にチェックを入れ、適用をクリックします。レポートを保存して実行し、魔法を見てみましょう。ページの一番下までスクロールすると、2 つの数字が表示されます。1 つは従来のレコード カウントで、この場合はレポートに保持されている各連絡先をカウントします。2 つ目は、個々のアカウント レコードの Power of One の合計です。この数は、子レコードの合計数よりも論理的に低く (または同じ)、レポート内のアカウントの合計を示します。 
:::

# Tips & Tricks: "The Power of One" the Greatest Formula Ever Written*

+ [Tips & Tricks: "The Power of One" the Greatest Formula Ever Written*](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7RsPSAV)

レポートでカウントするオブジェクトに新しいカスタム フィールドを作成します (私のアドバイス: Salesforce 組織内の  すべてのオブジェクトでそれを行います)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/4524ec24-56fc-7e19-3787-eb7f58e2008e.png)

ステップ 2. 出力タイプを選択する 
 
選択: 数値 (小数点以下 0 桁)
 ***フィールドに「Power of One 」という名前を付けないでください***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9fc46729-629b-2a28-58d4-bdf17e13d265.png)


ステップ 3. 数式を作成する

```
1
```

それだけです、ただのナンバーワン、他には何もありません... なに？なんでそんな目で見るの？？？[保存] をクリックすると、SFDC 組織に何千、何百万、何億ものレコードが存在するかどうかに関係なく、そのオブジェクトの既存のすべてのレコードに番号 1 が付けられます。 SFDC 組織があり、星が輝き、太陽が明るく燃えているように。それで、大きなf * ing取引は何ですか??? それはただの 1 です... アカウントに Power of One フィールドを作成し、アカウントを見ると 1 しかありません。レポートを取得し、光沢のある新しい「Power of One」フィールドを追加して、Summarize(SUM) を選択します 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/633fabbe-d6b8-2a6d-50fd-caee61913f55.png)


次に、レポートを実行します... *** ネタバレ注意: ここで魔法が起こります ***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/026ac569-5bdb-6050-9865-911163595d76.png)


これで、オポチュニティ オーナーの数、アカウントの数、オポチュニティの数、オポチュニティ プロダクトの数、電球、ウィジェット、壁に飾られたビールのボトルなどを取得できます。すべて The Power of One を使用して取得できます。
一時的にテキストにメモったURLを後でブラウザで一気に開きたいときのメモ

# 前置き
普段からブラウザを複数タブ開いて閲覧して、必要なくなったら消していくというスタイルを取っているのだが、特性と時間の都合上、タブ数が膨大になってしまう時がある（特に論文調査の時とか）
Pocketなどのブックマークツールを使っていてもいいが、入れたり消したりが手間だし時間がかかるし面倒である。
そういう時には一旦[Copy All Urls](https://chrome.google.com/webstore/detail/copy-all-urls/djdmadneanknadilpjiknlnanaolmbfk)などの拡張機能を使ってURL一覧をテキストファイルに保存し、後でまた見なおすことにしている。その時のちょっとしたテクニックのご紹介。

# やり方
1. テキストファイルのあるディレクトリで、コマンドプロンプト等からpythonのインタプリタモードに入り、以下を実行
    ```py
    with open("テキストファイル.txt") as f:
        linkList = [s.rstrip() for s in f.readlines()]
        print(linkList)
    ```
    表示されたものをコピーしておくこと。

2. 上で取得したものをurlListの部分にコピペし、以下のコードをchrome等ブラウザの開発者ツールのコンソールタブで実行する
    ```js
    urlList = ["url1","url2","url3","url4"]
    for(i=0;i<list.length;i++){
        window.open(urlList[i])
    }
    ```
開くときはブラウザのメモリを一気に消費するため注意すること。
# 参考
[Pythonでファイルの読み込み、書き込み（作成・追記）](https://note.nkmk.me/python-file-io-open-with/)
Databricksクラスターのメトリクス画面がリニューアルされました！

こちらで触れられている新機能です。

**Ganglia replaced with cluster metrics**

https://docs.databricks.com/release-notes/runtime/13.0.html#ganglia-replaced-with-cluster-metrics

Databricksランタイム13.0以降では、GangliaメトリクスがDatabricksクラスターメトリクスで置き換えられます。Databricksランタイム12以下では、Gangliaメトリクスを使用し続けることができます。クラスターメトリクスで充当できないGangliaメトリクスに依存するワークフローがある場合には、Databricks担当者にお問い合わせください。

クラスターの**メトリクス**タブからアクセスできます。左上のドロップダウンで**ハードウェア**が選択されている際には、CPUやメモリーの使用量を確認することができます。
![Screenshot 2023-04-24 at 6.16.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/53e01162-d3df-ea74-b0f8-d48d4d15b751.png)
![Screenshot 2023-04-24 at 6.16.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4676e0e5-fe54-ea79-dc3c-cd1a753fe4b2.png)

左上のドロップダウンで**Spark**が選択されている際には、Sparkタスクやシャッフルの状況を確認することができます。この他GPUのメトリクスも参照可能です。
![Screenshot 2023-04-24 at 6.16.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/a91f4494-e87c-1197-abdd-7fc2b162f174.png)
![Screenshot 2023-04-24 at 6.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/24731803-49b0-c015-8758-ee6eaad5e19d.png)

右上のドロップダウンではクラスター全体、各ノードのメトリクスを選択することができます。

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

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

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
成長を目指すエンジニア必見！目標設定をしないエンジニアが後悔する理由と目標設定の重要性と具体的な設定方法

# TL; DR
最近、若手エンジニアとの1On1で話したのですが、世の中を喋るのが上手いけど、具体的な部分について実態を感じない、掴みどころがない若手エンジニアがいました。

哲学者的としてなら良いけど、自分自身がなりたいエンジニアをもう少し具体的にイメージして５年後、３年後、１年後とブレイクダウンして今の目標設定を作っていった方が良いという話をしました。

若手エンジニアは、具体的に目標設定する事でそれを失敗した時を怖がっていて、かっこ悪いと思って目標設定していなかったり、見えない未来について目標設定しても途中で色んな事がおこるので今を一生懸命に過ごしたいという感じでした。

これは、真面目すぎる事が起因してると思います。目標達成なんか失敗しても良いし、常に軌道修正しても良い。ほとんどの社長さんは、常に軌道修正しながら前に進んでる。進まないと分からない事を悩んでも仕方なく、先ずは決めてしまって、進んでしまう事が重要と説明しました。間違っていても随時軌道修正すればよいだけです。

# 若手エンジニアに成長するために送る言葉
エンジニアとして成長するためには、具体的な目標設定が欠かせません。しかし、目標を設定することに恐怖心を感じたり、現実感を持てないという若手エンジニアもいます。こうしたエンジニアが成長するためには、自己肯定感を高め、失敗を恐れずに挑戦することが必要です。

まず、目標を設定することが大切です。目標を設定することで、自分自身を評価し、自己成長に繋がる道筋を描くことができます。目標を設定する際には、長期的なものから短期的なものまで、段階的に設定していくことが望ましいです。また、目標を設定する際には、具体的かつ明確な内容にすることが重要です。どのようなスキルを身につけたいのか、どのようなプロジェクトに関わりたいのか、具体的に考えることで、目標達成への道筋が見えてきます。

しかし、目標を設定することに恐怖心を感じる若手エンジニアもいます。こうしたエンジニアは、失敗を恐れるあまり、目標設定を避けてしまうことがあります。しかし、失敗は成長の機会でもあります。失敗を経験することで、自己肯定感を高め、次に向けた学びや改善点を見つけることができます。失敗を恐れずに挑戦することが、エンジニアとして成長するために必要です。

また、現実感を持てないという若手エンジニアもいます。目標を設定する際には、自分がどのようなエンジニアになりたいのか、どのようなプロジェクトに関わりたいのかを明確にすることが大切です。具体的なイメージを持つことで、目標を現実的なものとして捉えることができます。また、目標を設定しても、途中で色々なことが起こることがあります。しかし、それらは軌道修正のチャンスでもあります。失敗や障害を乗り越えながら、目標に向かって前進することが大また、目標を設定することで、自分が今何を学ぶ必要があるか、どのようなスキルを身につける必要があるかが明確になります。例えば、「5年後にはシステムアーキテクトとして活躍している自分」をイメージする場合、どのような知識やスキルが必要かを明確にすることができます。

さらに、目標設定はモチベーションを高める効果もあります。目標を達成するためには、努力や学習が必要ですが、その努力が目的に向かっていると感じることができれば、自然とモチベーションが高まります。

ただし、目標設定に失敗した場合に落ち込んだり、自信を喪失することがないようにするためにも、目標設定の仕方が重要です。目標はあくまで目的地であり、達成するための手段としてのプロセスも重要です。プロセスを大切にし、失敗を受け入れながら常に修正しながら進むことが大切です。

最後に、目標設定は個人的なものであり、他人と比較することは避けるべきです。自分が望む未来に向けて、自分なりの目標を設定し、自分なりのスピードで進んでいくことが重要です。若手エンジニアには、自分自身を信じ、自分の目標に向かって一歩ずつ進んでいく勇気を持ってほしいと思います。

若手エンジニアが目標設定に失敗した場合には、先輩エンジニアや上司に相談することも重要です。彼らは過去に同じような問題を抱えたことがあるかもしれませんし、経験からアドバイスをくれることもあります。また、他の若手エンジニアとの交流を通じて、自分と同じような目標を持つ人たちと切磋琢磨しながら成長することもできます。

さらに、目標設定に成功した場合でも、目標を達成した後には、次なる目標を設定することが重要です。目標を達成した後には、成長のスピードが落ちることがあるため、新しい目標を設定して、常に成長し続けることが必要です。

最後に、若手エンジニアには、自分が何をしたいのか、どのような未来を望むのかをしっかりと考え、自分なりの目標設定をすることをおすすめします。目標を達成するためには、常に努力と継続が必要ですが、その先には自己実現と成長が待っています。若手エンジニアたちは、自分自身を信じ、自分なりの目標に向かって一歩ずつ進んでいくことが大切です。

# まとめ
- 将来の目標設定は失敗しても良いのでやるほうが良い
- 軌道修正する事や失敗する事を恐れる必要はない
- プライドがあるなら捨てて、やらない恥の方がもったいないと思って色々と相談したり、自分を解放すべき

# 最後に
エンジニアの皆さん、エンジニア未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
ChatGPTボットはメンションしなくたって返事してくれるもんさ

ChatGPTを使ったチャットボットは面白いけどいちいちメンションするのめんどくさいじゃないですか。普通の人間みたく返信するかどうか本人に考えさせましょ。こんな感じで。

![2023-04-23_14h16_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/b6d4d2b3-4a8f-8adb-8335-e667edfdb3f3.png)

プログラムはこんな。過去の履歴を突っ込んで返信する必要があればYESと返させます。

```py
    def should_reply(self, messages):
        prompt = ""
        for m in messages:
            prompt += f"{m['user']}:{m['text']}\n"
        prompt += f"\nあなたは{self.bot_id}というチャットAIでこれまでこのように会話をしてきました。会話に返信する必要があると思う場合はYESと答えてください。お礼を言われた場合も返信する必要があるためYESと答えてください。"
        answer = get_chatgpt(user_content=prompt, temperature=TEMPERATURE_STRICT)
        return "YES" in answer
```
別のDatabricksワークスペースに接続するためにDatabricksコネクターを活用

[Use the Databricks connector to connect to another Databricks workspace \| Databricks on AWS](https://docs.databricks.com/external-data/databricks.html) [2023/4/4時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

本書では、別のDatabricksワークスペースに接続するためにDatabricksコネクターを使用する構文のサンプルを示します。このコネクターは、Databricksランタイム13.0以降に含まれるDatabricks JDBCドライバーを活用します。

:::note warn
**重要！**
ほとんどのデータ共有オペレーションでは、Delta Sharingをお勧めします。[Delta Sharingによるデータ共有](https://qiita.com/taka_yayoi/items/3a53516c4434c0ee76f0)をご覧ください。
:::

# 別のDatabricksワークスペースに接続する

Databricks Sparkコネクターを用いることで、別のDatabricksワークうsペースに設定されている計算リソースに接続し、現在のDatabricksワークスペースに結果を返却することができます。クエリーが成功するには、両方のワークスペースでアクティブな計算資源にアクセスできる必要があります。

JDBCドライバーは`jdbc:databricks://`のURLに登録されています。リモートでワークスペースのリソースにアクセスできる権限を付与するパーソナルアクセストークンを設定、使用する必要があります。[Databricksパーソナルアクセストークンを用いた認証](https://qiita.com/taka_yayoi/items/fa7f10bc80475c513383)をご覧ください。

:::note
**注意**
クラスターにアタッチされているDatabricks JDBCライブラリを使用している場合、Databricksランタイムに含まれているバージョンではなくクラスターにアタッチされているライブラリバージョンが使用されます。
:::

# 別のDatabricksワークスペースからデータを読み込む

以下のサンプルのように、データを読み込む際にDatabricks Sparkコネクターを使用するためにフォーマット`databricks`を指定することができます。

```py:Python
df = (spark.read
  .format("databricks")
  .option("host", "<host-name>.cloud.databricks.com")
  .option("httpPath", "/sql/1.0/warehouses/<warehouse-id>")
  .option("personalAccessToken", "<auth-token>")
  .option("dbtable", "<table-name>")
  .load()
)
```

# 別のDatabricksワークスペースに外部テーブルを作成する

Databricksワークスペースに、別のDatabricksワークスペースにリンクされる外部テーブルを登録することができます。

以下の例では、Databricksシークレットに格納されている資格情報を取得するために`secret`関数を用いる構文をデモしています。

:::note
Databricksシークレットの詳細については、[secret function](https://docs.databricks.com/sql/language-manual/functions/secret.html)をご覧ください。
:::

```sql:SQL
CREATE TABLE databricks_external_table
USING databricks
OPTIONS (
  host '<host-name>.cloud.databricks.com',
  httpPath '/sql/1.0/warehouses/<warehouse-id>',
  personalAccessToken secret('<scope>', '<token>'),
  dbtable '<table-name>'
);
```

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

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


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
スマホ動画をffmpegで「回転」「音量調整」（再エンコード無し）

ちょっと動画を横に回したい、音量上げたいというときに勝手に再エンコードして映像が劣化するコマンドは筋が悪いです。

## 90度回転

横向きで撮影したのに縦型動画として保存されている場合は以下のコマンドで90度回転できます

`ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=90 out.mp4`

`-c copy` で音声も映像も素通しさせ、メタデータのみを編集しているのがポイント

## 音量調整

音量だけ10dB向上

`ffmpeg -i input.mp4 -c:v copy -af volume=10dB out.mp4`

`-c:v copy` で映像を素通しさせ、音声のみ編集しているのがポイント
Sassの開発環境

この記事ではフロントエンドの開発に置いて必要なSassを使用するための環境を記載します。

Sassファイルで記載したものは1度コンパイルしてcssファイルに変換する必要があります。

○使用するライブラリ
npm or yarn

○使用するパッケージ
・nodemon
・sass

```json:package.json
{
  "name": "responsive_original",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts":{
    "build-css": "sass scss/style.scss css/style.css",
    "watch-css": "nodemon -e scss -x \"npm run build-css\""
  },
  "dependencies": {
    "nodemon": "^2.0.22",
    "sass": "^1.62.0"
  }
}
```

○手順
1.ソースファイルまでディレクトに移動し,``yarn init``を実行しpackage.jsonファイルを作る
2.``yarn add ~``でnodemon、sassパッケージを追加する


``scripts``内で記載している
・build-css
・watch-css
のコマンドを使用して実際にファイルのコンパイル、監視を行うことができる。

○``build-css``
sassパッケージを使用してscssファイルをcssファイルにコンパイルしている。(場所も指定できる)

○``watch-css``
このコマンドを使用することでscssファイルを編集した際に自動でcssファイルに変換してくれる
eオプション
→監視するファイル拡張子を指定(今回は.scss)
xオプション
→変更があった際に実行するコマンドを指定する(今回はbuild-cssをnpm runで実行)
Ruby初学者の私が2週間前の自分に伝えたいこと

この記事はRuby初心者の方のために書きました。

## 自己紹介
こてかんです。普段はインフラ運用保守をしています。2週間前にRubyを学び始めました。
プログラミング歴は[ progate ](https://prog-8.com/)を一通り終わらせたレベルでした。


## 困ったこと
- 基礎知識の引き出しがない。
- 「なぜ、そのコードを書いたのか?」を説明できない。
当初の私は、本/Udemy/Qiita/ChatGPT...などいろんな教材に手を出して学習を進めていました。
そのため学んだ知識が散らかっていて歯抜けになっているような状態で、分からない問題にぶつかるたびに結局その部分の基礎知識まで学び直すケースもありとても効率の悪い勉強をしていました。

## おすすめの学習方法
Rubyの学習には脱・初心者のためのおすすめ本があります。
通称「チェリー本」 この本を1ページ目から手を動かしてサンプルコードを実行しながら、読み飛ばさずに通読しましょう。

[プロを目指す人のためのRuby入門[改訂2版] 言語仕様からテスト駆動開発・デバッグ技法まで](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E6%94%B9%E8%A8%822%E7%89%88-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design/dp/4297124378/ref=pd_lpo_1?pd_rd_w=BOTbr&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=0FWP07AZGGP2XVP8SFZ3&pd_rd_wg=6FyE9&pd_rd_r=d3efd458-b77d-4253-99b8-641f4fcaa33a&pd_rd_i=4297124378&psc=1)
伊藤 淳一 (著)

ちなみに約500ページあって、内容も濃いです。(汗)
私には難しすぎて理解できないところも多くありました。
この点、「最後まで読み切るコツ」について著書より一部引用します。
>- 「これを全部理解しなきゃいけないのか」と考えるのではなく、頭の中にインデックス（索引）だけ作って、どんどん読み進める読書スタイルにチェンジしてください。  
>- 「あ、そういえばあの本になんか書いてあったな」と思い出して、読み返せるようにしておくことです。
>- 各章には例題を設定してあるので、難しい章であっても最低限そこだけは本書の説明に従って自分でコードを書いてみてください。それ以外の部分は「必要になったらあとで読み返す」という気持ちでどんどん読み進めてもらって結構です。その代わり、必ず最後まで読み終えてください！ 途中で力尽きてしまうと、頭の中にインデックスを作ることすらできないからです。

この投稿を書いている現在なんとまだ私は通読の途中でしてw
残りの3割はひきつづき取り組もうと思っています。
一緒にがんばりましょ～

## さいごに
初学者にとって学習教材は無数にあって混乱しますよね。

Rubyを始める日本人なら「チェリー本」の存在をだれでも知ってますよね。
わざわざおすすめせずともみんな読んでいる「チェリー本」ですが、
今回は私の学習体験として良い入門本を"通読"することの効果を実感したため紹介しました。
いち参考としていただければ幸いです。

※補足：ChatGPT4.0もフル活用がおすすめ。（有償で）

## 参考
- [Amazon: プロを目指す人のためのRuby入門[改訂2版] 言語仕様からテスト駆動開発・デバッグ技法まで / 伊藤 淳一 (著)](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E6%94%B9%E8%A8%822%E7%89%88-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design/dp/4297124378/ref=pd_lpo_1?pd_rd_w=BOTbr&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=0FWP07AZGGP2XVP8SFZ3&pd_rd_wg=6FyE9&pd_rd_r=d3efd458-b77d-4253-99b8-641f4fcaa33a&pd_rd_i=4297124378&psc=1)
- [youtube: だれでもエンジニア / 山浦清透](https://www.youtube.com/@KiyotoUniv/featured)