OmniAICreator/Qiita-1.07M huggingface dataset:
最小努力と最短時間でPL-300合格記

前回(AZ-900)に引き続きPL-300も無事一回で合格しました。
勉強時間は前日から始めて6時間程度。暗記量も少ないです。プラクティス試験はあまりあてになりませんでした。

毎度の如くほぼ前日＆当日の詰め込みショートカット勉強法なので、きちんと正攻法で勉強することをお勧めします。


過去の体験記はこちら：

https://qiita.com/ponponmikankan/items/fd363bb0323569d3676f

https://qiita.com/ponponmikankan/items/77202be0de32cda5893d

https://qiita.com/ponponmikankan/items/4b64124be47a34467019

https://qiita.com/ponponmikankan/items/c27d6db74bac7cb44fef


## 前提

Power BIを触り始めてから2－3年以上たちます、、が
毎度ローカルファイルやSPO等からインポートモードで作成（尖ったことはしない）。。
数字を扱うこともあまりないため、DAXを使うほどでもない小規模でシンプルなダッシュボードしか実務では利用しておりませんでした。

最近は大きめの開発をしていますが、それまではめっちゃしょぼい経験しかない。

## 参考にした勉強法

いつも鬼信頼している赤本が存在しないため、公式を確認し、Learn(20時間超)一本で勉強しました。
VMでレポートや機能の体験ができますが、時間がないためスルー（笑）
他の方の合格記を参考にすると、みなさん数週間、数か月かけて勉強しUdemy等を活用されているようです。

https://techlife-pag.com/2024/08/14/pl-300_study/

https://techblog.ap-com.co.jp/entry/2023/09/14/112349

## 実際の勉強でやったこと

### Learnを飛ばし読み（4時間程度）

https://learn.microsoft.com/ja-jp/training/courses/pl-300t00

20時間以上ありますが、データアナリストとしての役割やデータの配置方法（スタースキーマ）、リレーションの考え方等一般的な内容も多く含まれるためほかのBI等を触られたことがある方は飛ばせるんじゃないでしょうか。
個人的にはなんとなくしか知らなかった機能（インポートモデル、配置パイプライン、DAX、メジャー等）を勉強できてよい機会でした。（いままで使っていなかったことを恥じた。便利やん。）

### プラクティス評価の実施（3周くらい）

https://learn.microsoft.com/ja-jp/credentials/certifications/data-analyst-associate/practice/assessment?assessment-type=practice&assessmentId=48&practice-assessment-type=certification

やたらとインポートモードの質問が推されているのですが本番では一問も出なかった…。
PL-300に関してはプラクティス評価よりも↓のExam Topicsのほうが役立ったかも。

### Exam Topics(直前30分くらい)

https://www.examtopics.com/exams/microsoft/pl-300/

本番で出された試験が出てきます。英語ですがブラウザの翻訳機能等をつかえば楽勝（いい時代）
時間が足りず30問くらいしかできませんでしたが、プラクティス評価よりもかなり本番に近いのでやっておいた方がいいと思います。

### 試験の感想

試験時間は1時間40分で1時間20分くらいかかりました。（見直し1周）。
900番台の試験は試験時間1時間のほぼシンプルな四択問題ですが、
900より上の試験については出題形式がちょっと特殊です（プラクティスはそうなってないので注意）

後で見直せる問題が35問程度→引き返せない問題が5－6問→ケーススタディが5－6問でした。

「これ、プラクティス評価でやったやつ！！」は1問くらいしか出ないので、丸暗記では解けないかも。
ピボット、ピボット解除は謎に2－3問でました。
DAXの穴埋め的な問題も2－3問出たので基本的な関数はおさえておいたほうがよいかも。

ケーススタディは案件の要件が最初にどんと表示され、それに関する質問や実現方法について答えていきます。

…というわけで、結構緊張したんですが、今回も超最低限勉強法で無事合格！
次はDP-900を目指そうと思います。
[Flutter] 文字サイズを大きくすると周囲に空白が発生する

## 今回発生した問題

今回発生した問題はタイトル通り、Flutterでアプリを開発時にfontSizeを大きくしていくと周囲に空白が発生するというもの
<br></br>
<img width="200" alt="iPhone 15 - 2024-08-19 at 11.36.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283873/dfd23472-a8dc-0781-53d0-53316d951413.png">
<font color="Gray">font: Kiwi-Maru, fontsize: 50で発生。PaddingやGapを設定していないにも関わらず、文字の上に空白ができている</font>
<br></br>
コードは以下の通り
```sample.dart
Container(
    color: Colors.white,
    child: Text(
      "2",
      style: TextStyle(
        fontSize: 50
      ),
    ),
),
```
<br></br>
## これって結局何？
おそらくこれにはフォント自体に含まれている「<b>バウンディングボックス</b>」というものが関係していそう。

バウンディングボックスをざっくりいうと、文字のサイズや位置を決定するための見えないスペースで、実際に見ることができる文字サイズとは異なる。
文字によって表示に使う幅や高さが微妙に異なるので、特定の文字だけ切り取られたりすることなく表示するのに必要なんだそう。

デザインに精通していないので全くの初耳でした。
<br></br>

## 対処法
先ほどのコードに一行足すだけ。

```sample.dart
Container(
    color: Colors.white,
    child: Text(
      "2",
      style: TextStyle(
        height: 1.0, //追加した行
        fontSize: 50
      ),
    ),
),
```

<img width="200" alt="iPhone 15 - 2024-08-19 at 12.08.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283873/77de54fc-1b33-41c3-b1d3-180ac3b145a7.png">

これで周りのウィジェットとの間に余計なスペースを空けることなく配置できました。
参考になれば嬉しいです。

<font color="Gray">※この方法は文字によってoverflowを引き起こす可能性があります</font>
返り値って何？超初心者プログラミング。返す＝渡す

どうも！プログラミング超初心者です。

アプリを作ったりしているのですが、返り値って何？returnって何？と感じ書いてみました。

例えば以下のコードをdartで書いてみます。

```dart
  int add(int a, int b) {
  return a + b;
}

void main() {
  int sum = add(3, 4);  // 返り値の7がsumに格納される
  print(sum);  // sumの値を表示する（7）
}
```

### int は
関数が返す値の型を示しています。ここでは、この関数が整数 (int) を返す(渡す)ことを意味します。つまり、関数の結果として得られるのは整数であると宣言しています。


### add は、
この関数の名前です。この名前は関数を呼び出すときに使われます。一般的に、関数名はその関数が何をするのかを示すための説明的な名前にします。この場合、addは「足す」という意味で、2つの数を足し合わせる関数であることを示しています。


・このプログラムでは、関数addが二つの整数を受け取り、その和を計算して結果を返しています。そして、main関数でその結果を受け取って表示しています。

### (int a, int b) は、
関数が受け取る入力のリストです。これを引数と呼びます。
int a: これは最初の引数で、整数型 (int) の変数 a を**受け取ること**を示しています。
int b: これは2番目の引数で、整数型 (int) の変数 b を**受け取ること**を示しています

### {} は
関数の本体を囲む中括弧で、ここに関数が実行する処理が記述されます。

### **return a + b** は、
・**a + b:** aとbという2つの引数を足し合わせる処理です。この処理によって、2つの数の和が計算されます。
・**return** returnというのは、関数の結果を返すために使われます。ここでは、計算したa + bの値を関数の呼び出し元に返します。

# 続いて
### void 
このキーワードは、main 関数が何も値を返さないことを示しています。つまり、main 関数は実行されても呼び出し元に何も返さない、プログラムの開始点となる関数です。
### main
main はDartプログラムのエントリーポイントです。プログラムが実行されると最初に呼び出される関数であり、全てのプログラムのスタート地点となります。

### int sum
int はデータ型を示しており、ここでは sum という変数が整数 (int) を格納することを意味しています。sum は、この行で定義される変数の名前です。
### add(3, 4) 
これは add 関数を呼び出す部分です。add 関数は、2つの引数（この場合、3 と 4）を受け取り、それらを足し合わせた結果を返します。具体的には、3 + 4 の結果である 7 を返します。
### =
これは代入演算子で、右側の add(3, 4) の結果（つまり 7）を左側の sum に入れます。これにより、sum には 7 という値が保存されます。

### print(sum);:
これは print 関数を呼び出して、sum の値をコンソールに表示する部分です。print 関数は、括弧内に与えられた内容をコンソールに出力します。
この場合、sum に格納されている値は 7 なので、コンソールには 7 が表示されます。



# **返り値の意味**
返り値は、関数が計算や処理を行った結果を外部に**渡すため**の方法です。これにより、他の部分のプログラムでその結果を使うことができます。
SFのユーザー関するまとめ

SFのユーザー概念をまとめます

**1. プロファイル:**

**シナリオ:** TechCorpには、営業、マーケティング、カスタマーサポートなどのさまざまな部門があります。各部門は、Salesforceデータと機能に対する異なるレベルのアクセスが必要です。

**例:**

- **営業プロファイル**: 営業チームのメンバーは、商談（Opportunities）、リード（Leads）、アカウント（Accounts）へのアクセスが必要です。これらのオブジェクトに関するレコードを作成、編集、表示できる必要がありますが、機密の財務データや特定の管理設定にはアクセスできないようにします。
- **マーケティングプロファイル**: マーケティングチームは、キャンペーン（Campaigns）、リード、連絡先（Contacts）へのアクセスが必要です。しかし、商談のデータは必要ありません。キャンペーンの作成と管理はできますが、営業専用のデータにはアクセスできません。
- **カスタマーサポートプロファイル**: カスタマーサポートチームは、ケース（Cases）、連絡先、アカウントにアクセスできる必要があります。サポートケースの表示と管理が必要ですが、商談やキャンペーンにはアクセスできません。

**プロファイル**は、Salesforceプラットフォーム内でユーザーが何を見て、何をできるかを定義します。オブジェクトの権限、フィールドレベルのセキュリティ、ページレイアウトなどの設定が含まれます。

**2. 権限セット:**

**シナリオ:** プロファイルを設定した後、TechCorpは、営業チームの一部のメンバーに、コアプロファイルの権限を変更せずに特別な機能、例えばカスタムレポートや特定のアプリケーションへのアクセスが必要であることに気付きました。

**例:**

- **営業プロファイル**: すべての営業チームメンバーは、商談、リード、アカウントへの基本的なアクセスを持っています。
- **特別レポート権限セット**: この権限セットは、営業パフォーマンスを追跡するカスタムレポートへのアクセスを提供します。このレポートが必要な営業チームの一部のメンバーのみに、この権限セットを割り当てることができます。

**権限セット**は、プロファイルで提供される基本的な権限に追加の権限を付与することができます。これにより、ユーザーが一時的に追加のアクセスを必要とする場合や特定のタスクを実行する場合に、プロファイルを変更せずに対応できます。

**3. 公開グループ:**

**シナリオ:** TechCorpは、共同プロジェクト用のグループを作成し、レコードやタスクの管理を容易にしたいと考えています。

**例:**

- **プロジェクトチームグループ**: これは、営業、マーケティング、カスタマーサポートのメンバーを含むパブリックグループです。共同プロジェクトに関するレコード、タスク、レポートの共有に使用できます。

**公開グループ**は、Salesforce内でユーザー、役割、または他のグループを管理するために使用されます。レコードの共有、プロセスの自動化、コラボレーションの促進に役立ちます。

### まとめ:

1. **プロファイル**は、各部門（営業、マーケティング、カスタマーサポート）がSalesforce内で何を見て、何をできるかを定義します。　**ゲームのキャラクターの職業みたいと思います。**
1. 
2. **権限セット**は、特定の機能やデータへの追加のアクセスを提供します。例えば、営業チームの一部のメンバーには特別レポート権限セットを割り当てることができます。　**職業が違いキャラクターに一部共通属性を追加します。**

3. **公開グループ**は、異なる部門のユーザーを整理し、共同作業を促進するために使用されます。例えば、プロジェクトチームグループは、共同プロジェクトのためのレコードやタスクを共有するのに役立ちます。　**タスクをクリアするために、ユーザーをまとめて、チームを作成します。**

これらの機能を使用することで、TechCorpはSalesforce内でのアクセスとコラボレーションを効率的に管理し、各チームがニーズに応じた適切なアクセスと機能を持つことができます。

新しい技術を出る時、新しい概念もあります。既に分かることに関連すると、分かりやすくになります。
【ChatGPT＋Code Interpreter】でふたつの画像を切り替えるアニメGIFを作成します。


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

　今回は、ふたつの画像を切り替えるアニメGIFを作成します。切り替え方法は、中央から次の画像を出します。

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

　まずは、ニュース。

　昨日（2024/08/18）のニュースで
　　Luma AIのDreamMachineが
　　　バージョンアップした、と
　　　　お伝えしました。

　でもその内容は
　　わかりませんでした。

　どうやら
　　Text to Videoが
　　　大幅にバージョンアップした
　　　　らしいです。
　　　　　[そねちさんポスト](https://x.com/AIsonesone/status/1825189349094563872?t=ebno26b8xtzv_YXNjOLG7Q&s=19)
***
　さて、本題です。

　ふたつの画像を
　　切り替えるアニメGIFを
　　　作成します。

　“切り替える”とはいえ
　　その方法はいくつもあります。

　　　・エフェクトなどを
　　　　　単純に切り替える。
　　　・エフェクト使用して
　　　　　切り替える。

　単純な切り替えは
　　以前にやっていますので、
　　　エフェクトを使おうと思います。

　ここでは
　　ひとつの画像を割って
　　　次の画像を出します。

　出来上がりはこちら。
![central_split_transition_resized.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/bb2558cd-864e-3fe1-ecac-066690cf48f3.gif)

　手順は
　❶GPT-4oであることを確認
　❷ふたつの画像をアップロード
　❸Prompt入力
```Text:
CodeInterpreterで、
・背景は最初の画像
・次の画像を表示して、その画像を中央から左右に分割していく（背景は固定）

上記のアニメGIF（滑らかに2秒）を作成してください。
```
　❹送信
　❺ダウンロードリンクが表示
***
　本当は、
　　昨日（2024/08/18）の
　　　アニメGIFの反転を
　　　　やろうとしてたんです。

　でも
　　ちょっと
　　　うまくできなかったんですよね😅

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

　今回は、ここまで。
【React✖️css】ホバーを作りたい


# 研修中の開発備忘録です！

## はじめに！
```tsx
const AchievementImageIcon: React.FC<ImageIconProps> = ({ index, brightness, text, hoverText }) => {
  if (index < -1 || index >= images.length) {
    return null; // インデックスが範囲外の場合は何も表示しない
  }
  const image = images[index];
  // 明度を調整するスタイルを動的に生成する
  const brightnessStyle = {
    "--brightness": `${brightness}%`, // カスタムプロパティに明度を設定
  } as React.CSSProperties;

  return (
    <div className="achievement_icons">
      <img
        src={image.default}
        alt={`image-${index}`}
        className="achievement_icon"
        style={brightnessStyle} // 明度を調整するスタイルを適用
      />
      <p>{text}</p>
      <div className="tooltip">{hoverText}で獲得ピヨ！</div>
    </div>
  );
};

```

+ 呼び出し元
## 今回のメイン
```css
:root {
  --brightness: 100%;
}

.achievement_icon {
  filter: brightness(var(--brightness)); /* --brightness変数を使用して明度を調整 */
}

.achievement_icons {
  position: relative; /*親要素にrelative*/
}

.col-custom {
  width: calc(100%);
  float: left;
}

.achievement_icons {
  position: relative; /* ツールチップを相対位置に配置 */
  display: inline-block; /* 必要に応じてインラインブロック */
}

.achievement_icon {
  transition: transform 0.1s; /* ホバー時のアニメーション */
}

.achievement_icons:hover .tooltip {
  visibility: visible; /* ホバー時にツールチップを表示 */
  opacity: 1;
}

.tooltip {
  visibility: hidden; /* デフォルトは非表示 */
  align-items: center; /* 縦方向の中央揃え */
  justify-content: left; /* 横方向の中央揃え */
  background-color: #252525bd;
  color: #ffffff;
  border-radius: 5px;
  padding: 5px;
  position: absolute;
  z-index: 1;
  bottom: 70%; /* ツールチップの位置 */
  left: 70%;
  margin-left: -60px;
  opacity: 0;
  transition: opacity 0.3s;
  height: 100px; /* 縦幅を設定 */
  width: 200px; /* ツールチップの幅 */
  font-size: 20px; /* 文字サイズの設定 */
  font-weight: bold; /* 太字 */
  opacity: 0; /* 初期状態は完全に透明 */
}

```
<dl>
<dt>・　画像の読み込み</dt>
<dd>・achievement_iconsの相対位置とインラインブロック表示を利用してツールチップを配置する</dd>
<dd>・ツールチップは、アイコンにホバーすると表示され、位置やサイズ、フォントが設定されている</dd>
🚀 New Certification Alert: DataBricks Certified Data Engineer Professional Exam Just Published! 🎓

Hey Qiita community,

We are excited to announce that the **DataBricks Certified Data Engineer Professional Exam** is now live on our website! 🌟

About This Certification Exam
The DataBricks Certified Data Engineer Professional exam is designed for experienced data engineers looking to validate their expertise in building and managing scalable data pipelines using DataBricks. This certification demonstrates your ability to work with big data technologies, optimize data workflows, and implement complex data processing solutions on the DataBricks platform.

Why You Should Get Certified
**Industry Recognition**: Stand out in the competitive job market with a certification from DataBricks, one of the leading platforms in big data and AI.

**Career Growth**: Enhance your resume and open up new career opportunities in data engineering and big data roles.

**Skill Validation**: Showcase your ability to design and implement data solutions that are scalable, reliable, and optimized for performance.

Exam Details
**Duration**: 120-150 minutes

**Format**: Multiple Choice, Multiple Response, and Hands-on tasks

**Passing Score**: Typically 70% (may vary)

**Availability**: Online proctored or in-person at testing centers

How to Prepare
To ace this exam, make sure you:

**Study Official Materials**: Use DataBricks documentation, official courses, and relevant textbooks.

**Get Hands-On**: Practice on the DataBricks platform, build real-world data pipelines, and familiarize yourself with the tools and services.

**Join Study Groups**: Connect with peers, share knowledge, and solve complex problems together.

Who Should Take This Exam?
**Experienced Data Engineers**: Professionals looking to validate their advanced skills in data engineering on DataBricks.

**Big Data Specialists**: Experts aiming to enhance their credentials in big data technologies.

**Data Analysts and Scientists**: Those seeking to deepen their understanding of data engineering practices.

Get Started Now!
Don't miss out on this opportunity to advance your career and showcase your expertise. Visit our website to learn more about the DataBricks Certified Data Engineer Professional exam and start your certification journey today!

👉 https://awslagi.com/course/certified-data-engineer-professional/

Stay ahead in the data-driven world. Good luck! 🍀
AI翻訳サービス「Readable」でpdfをまるごと翻訳

## はじめに
こんにちは、株式会社TechoesのK（入社1年目、エンジニア歴3年目）です

今回はpdfのAI翻訳サービス「Readable」についてご紹介したいと思います

## 「Readable」について
Readableは、PDFファイルを瞬時に翻訳するAIツールです。

![スクリーンショット 2024-07-29 17.30.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714682/0368fbd2-ac65-cdf4-df38-53522ea18bef.png)

最大の特徴として、翻訳後もレイアウトが崩れず、英語と日本語を見開きで確認できる点が挙げられます。

アップロードしたPDFをたった30秒で翻訳し、最大100ページ、50MBまでのファイルを一度に翻訳可能です。（無料版は1500文字まで）
<br>
[リンクはこちら](https://readable.jp/translate)


## 使ってみる
<br>
まずは、こちらにpdfをアップロード
<br>

![スクリーンショット 2024-07-29 17.38.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714682/3d904bf2-71f1-b78c-5de6-8d5fff0391a7.png)

<br>
pdfのアップロードが完了すると翻訳済みのDeepLのリンクが出来るのでDeepLから右側の翻訳済みの文章をペーストして「PDF翻訳」ボタンをクリック

<br>
<br>

![スクリーンショット 2024-07-29 17.39.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714682/2e0f03fc-1af0-d221-f9ea-4a2958b255a4.png)

<br>
翻訳済みのpdfが生成完了！
<br>
<br>

![スクリーンショット 2024-07-29 17.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714682/93c6bbe7-0611-ce74-f002-cdceb8572fb6.png)

<br>
日英混合表示のpdfを見開き表示するとこんな感じ
<br>

（利用したページは[こちら](https://nextjs.org/docs/app/building-your-application/routing/defining-routes)）
<br>

![スクリーンショット 2024-07-29 17.45.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714682/a0c3606f-9364-0f08-d47c-a6a1bef67ffd.png)


<br>
見開き表示で翻訳されているのですごく見やすいですね！
<br>

## おわりに
以上、pdfのAI翻訳サービス「Readable」とその使い方について紹介しました。
英語アレルギーの人もこれで公式ドキュメントは怖くない？（...かも笑）
<br>

最後までお読みいただき、ありがとうございました。この記事が皆さんの開発作業の一助となれば幸いです。
HTMLの最初のフォーマット

<h2>未経験の方！必見！</h2>
<h3>最初のフォーマット！</h3>
<p>VScode、Eclipsなどのエディタを利用してやる場合は、以下の最初のフォーマットはショートカットキーで自動作成されます。<br>
ただ、PCの容量が少ないけど、練習で制作してみたいという方は、サクラエディタ、秀丸をインストールし、以下をそのままコピペ利用して初めて見てください。<br>
※これは大枠で練習でテキストを表示させたりする前の段階で、制作するサイトの説明などを記載する箇所となります。また、デザインを別のファイル(CSS)で対応する場合は、どのスタイルシートを読み込むのかなどの設定する場所です。</p>

```html:↓最初のフォーマットのプログラム↓
<!DOCTYPE html><!-- このファイルはHTMLですという宣言 -->
<html lang="ja"><!-- ここからHTMLが始まりますというタグ -->

<head><!-- ここから裏の設定ですよという宣言 -->
	<!-- memo:メタ情報を適切に設定する -->
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Sample Title</title>
	<meta name="description" content="サイトの説明">
	<meta propaty="og:type" content="website">
	<meta propaty="og:site-name" content="サイトのタイトル">
	<meta propaty="og:url" content="サイトのリンク">
    <meta property=”og:image” content=” サムネイル画像のURL” />
	
	<link rel="icon" href="img/favicon.ico">
	<!-- 左記のサイトでfavicon.ico作成 https://www.xiconeditor.com/-->

	<!-- CSS：デザインを別のファイル(CSS)で対応する場合 -->
	<!-- スタイル(フォントサイズ/フォントの太さ/デザインなど) -->
	<link rel="stylesheet" type="text/css" href="css/style.css">
</head><!-- ここまでが裏の設定ですよという宣言 -->
<style>
</style>
<body>
</body>
</html>
```

<h3>練習問題</h3>
<p>メモ帳でも作成可能ですが、フリーソフト：サクラエディタですと行番号も振られており、見やすいので、ぜひインストールして利用してみてください。表示されているか確認は、既存ブラウザにて確認してください。</p>
<h4>サクラエディタ</h4>

https://sakura-editor.github.io/help/HLP000112.html

<h5>ブラウザ：chrome、edgeなど</h5>
<h4>練習問題①</h4>
<p>上記のフォーマットをコピペして、以下のテキストを表示させてください。</p>
<p>【Hello World】</p>

<h4>練習問題②</h4>
<p>上記のフォーマットをコピペして、以下のテキストのフォントを太字で表示させてください。<br>
※styleの中に、フォントの太さを指定させる。</p>
<p>【Hello World】</p>

<h4>練習問題③</h4>
<p>上記のフォーマットをコピペして、以下のテキストと画像をを表示させてください。<br>
※以下の画像をダウンロードして利用してください。</p>
<p>【Hello World】</p>

![kv_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840057/9346efb3-8edb-db5b-d9d4-9e5997064e3c.png)

<p>本日の練習問題の解答は次の投稿にて！</p>
【React】imageをディレクトリ単位で読み込みたい


# 研修中の開発備忘録です！

## はじめに！
```ts
import React from "react";
import "./ImageIcon.css";
import "bootstrap/dist/css/bootstrap.min.css";

interface Image {
  default: string;
}

interface ImageIconProps {
  index: number;
  brightness: number;
}

// `require.context` の型定義
interface WebpackRequireContext {
  keys(): string[];
  <T>(id: string): T;
  resolve(id: string): string;
  id: string;
}
declare const require: {
  context(directory: string, useSubdirectories?: boolean, regExp?: RegExp): WebpackRequireContext;
};

```

+ 型定義関連（typescriptあるある）

## 今回のメイン
```tsx
const importAll = (r: WebpackRequireContext): Image[] => {
  const keys: string[] = r.keys();
  keys.sort(new Intl.Collator("ja", { numeric: true }).compare);
  return keys.map((key: string) => ({
    default: r(key)! as string, // `default` は画像のパスとして扱う
  }));
};

// `public/images` フォルダ内のすべての画像ファイルをインポート
const images: Image[] = importAll(require.context("../../images", false, /\.(png)$/));

const ImageIcon: React.FC<ImageIconProps> = ({ index, brightness }) => {
  if (index < 0 || index >= images.length) {
    return null; // インデックスが範囲外の場合は何も表示しない
  }
  const image = images[index];

  // 明度を調整するスタイルを動的に生成する
  const brightnessStyle = {
    "--brightness": `${brightness}%`, // カスタムプロパティに明度を設定
  } as React.CSSProperties;

  return (
    <div className="aws_service_icons">
      <img
        src={image.default}
        alt={`image-${index}`}
        className="aws_service_icon"
        style={brightnessStyle} // 明度を調整するスタイルを適用
      />
    </div>
  );
};

export default ImageIcon;
```
<dl>
<dt>1. 画像の読み込み</dt>
<dd>・特定のディレクトリ（今回はimages）内の画像を全て読み込む</dd>
<dd>・これらの画像はImageIconからindexを指定することで使用することができる</dd>

<dt>2. 動的な画像の明度変更</dt>
<dd>・引数（brightness）によって、適用する明度を変更する
CentOS Stream 9 に ffmpeg インストール

# 結論

* epelをインストールしておく
  * `# dnf install epel-release`
* `# dnf install ffmpeg-free --enablerepo=crb,epel`

パッケージ名は ffmpeg-free ですが、 ffmpegコマンドで実行できます。

## 参考：crbリポジトリ

centos.repo内にある。

view /etc/yum.repos.d/centos.repo
```
[crb]
enabled=0
```

* 情報源
  * [Linuxにffmpegをインストールする方法 CentOS Stream - [Linux [Red Hat/CentOSなど]/サーバー] ぺんたん info](https://pentan.info/server/linux/ffmpeg_dnf_install.html)

# 所感

rpmfusion.orgを使うやり方がエラーでうまくいかず、epel版を探したら ffmpeg-free なるパッケージがあったため、試しにインストールしてみた所、使えそうでした。
ffmpeg-freeのインストール記事が見当たらなかったため、記載しました。
少しでも参考になれば幸いです。
万年初心者がITパスポートを三週間で合格点まで行けた話。 


# 挨拶

おはこんばんにちは。
ポポノタンと申します。
エンジニア志望の元製造メンです。

当記事はタイトルにもありますように、ITパスポートを三週間で合格点まで持って行けた勉強法の備忘録として書かせていただいております。
初めての記事ですので、つたない部分もあるかと思いますがどうぞ最後まで見てやってください。

# 1.最初に

まずは、直近のITパスポートの日程を確認しました。
ITパスポートは一か月で３~４回ほど実施されています。
しかも、期間を開けずに何度も受けられるので素敵ですね:relaxed:

ぼくは受験までの期間が長く空いてしまうとだらだら勉強してしまうので、日程の会う最も近い日を受験日にしていました。
短期集中が資格取得に一番いい気がしてます:ok_hand_tone2:

もし受験してみようという方がいれば、こちらにリンクを張っておきますのでご活用ください。

https://www3.jitec.ipa.go.jp/JitesCbt/index.html

# 2.スケジュールを考える
さて、受験申し込みを済ませましたが勉強する期間が三週間しかありません。
そこで各週ごとに何をするか予定を建てました。
* １週目　参考書を読む（１周目）
* ２週目　参考書を読む（２周目）
* ３週目　過去問を解く

ざっくりすぎですね（）

# 3.いざ、勉強開始！（1～2週間目）
さて参考書ですが・・・

https://www.amazon.co.jp/%E3%80%90%E6%94%B9%E8%A8%826%E7%89%88%E3%80%91IT%E3%83%91%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E6%9C%80%E9%80%9F%E5%90%88%E6%A0%BC%E8%A1%93-%EF%BD%9E1000%E7%82%B9%E6%BA%80%E7%82%B9%E3%82%92%E7%8D%B2%E5%BE%97%E3%81%97%E3%81%9F%E5%8B%89%E5%BC%B7%E6%B3%95%E3%81%AE%E7%A7%98%E5%AF%86-%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93-%E8%A5%BF-%E4%BF%8A%E6%98%8E/dp/4297132753/ref=sr_1_1?adgrpid=126271298851&dib=eyJ2IjoiMSJ9.pNO9kY5h4ZjkOQZZwks3s3SIIa2dK4OkNZ8c4z9vU-ArAZlpyjWbYD0G1Hysl-cxqXfEfpHV7Umevi1je0AlFbNn_AB9MzuwpaKl5V7CGBQeMxqu_7aqp0ic_fr_n-Tjl11yclhpqjo-ztXFXWCD6je0e2q1r02amCgM9YnIgw9OGJQV34srU35fkSU5z493ApM-jWJfCDQDBfVdpJMbfNYVYUyPlPoSOSjuL_L_cQIAU2WEvMfl6B70OlSJrOExl2g6O3OkNVoF56Qc_4zWJ9VaU9v9zJDKEOQxqPj3GDs.VBpZJRWjdmCNPW781G4rfYdx1VS82jHSdsMzm5NPlO8&dib_tag=se&hvadid=679099999364&hvdev=c&hvlocphy=1028833&hvnetw=g&hvqmt=e&hvrand=6084057436130642846&hvtargid=kwd-1262328020363&hydadcr=26609_11789354&jp-ad-ap=0&keywords=it+%E3%83%91%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88+%E6%9C%80%E9%80%9F+%E5%90%88%E6%A0%BC+%E8%A1%93&qid=1724028700&sr=8-1

こちらを活用しました。
ぼく自身はまったく無知からのスタートでしたが、わかりやすい具体例を用いた説明と単元毎に過去問を置いてくれており、単語一つ一つがイメージしやすかったです。
この参考書は読めば読むほど理解が深まるので、何度も読むことをお勧めします:muscle:

また、どうしても理解ができない箇所についてはYoutubeで単語を調べると山のように動画が出てきますので目からの情報だけでなく耳からも情報を入れるようにしていました。

時間は惜しかったので、参考書をトイレ中やごはん中にも読んでいました。
~~いままでろくに勉強というものをしてこなかったため必死だった~~
というかんじで、二週間ほど過ごしておりました。

# 4.勉強だ！（３週間目）

三週間目はやっと過去問です。
過去問は直近から３年分をやっていました。出題形式は４択ですのでわからない単語や解けなかった問題はYoutubeや参考書で確認していました。
過去問は過去問道場が非常に使いやすいのでお勧めしておきます。

https://www.itpassportsiken.com/ipkakomon.php

本試験では過去問も出題されるのでやればやるほど合格率が上がると思います。

# 本番
試験当日は~~どちゃくそ~~緊張していました。
勉強時間的にも、他の記事を見ていると200時間要求されていたり、2～3か月は必要といわれていたりしましたので不安しかありませんでした。
しかも、いきなりわからない問題が出てきて泣きそうになっていました:joy:

気になる試験結果は・・・
**625/1000**
でした～～～（けっこうぎりぎり）
合格点は600/1000ですのでなんとかかんとかクリアラインまで持って行けました:clap:

ちなみにストラテジ系が490点マネジメント系が815点テクノロジ系が565点でした。
マネジメントがなければ詰んでました:innocent:
※各300点以上が合格ライン

# 最後に
正直な話、勉強時間もあまりとれていなかったり過去問もたくさんできていたわけではなかったので本当に合格できるとは思っていなかったです。
ですが、こうしてなんとかかんとかエンジニアの一歩を踏み出せたような気がしています。

次の目標は、基本情報技術者試験ですのでITパスポートよりももっと踏み込んだ内容の学習が必要になってくると思っていますが頑張ります:fist:

この記事がITパスポートをこれから受験する人の役に立つかはわかりませんが、こんな勉強で受かったやつもいるぞ、ということでどうか一つ大目に見てやってください。

それでは、みなさん良いエンジニアライフを～:wave:
変更があったディレクトリで pre-commit を実行する

1つのリポジトリで複数のサービスやパッケージを作っているときに、ディレクトリごとの環境でリントとかしたいですよね

探したら
https://blog.physalis.net/2021/git-hooks-dispatch
とかあったんですけど、余計な依存無しに、 git や シェルスクリプトだけで完結したかったので、雑に作りました

```bash
#!/bin/sh

files_changed=$(git diff --cached --name-only)
dirs_changed=()
for file in ${files_changed[@]}; do
  _dir=$(echo $file | sed 's/\/.*//')
  dirs_changed+=($_dir)
done

dirs_unique=($(echo "${dirs_changed[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))

if [ ${#dirs_unique[@]} -eq 0 ]; then
  echo "No directories to lint"
  exit 0
fi

base=$(pwd)
echo ${dirs_unique[@]}
for _dir in ${dirs_unique[@]}; do
  echo "cd $_dir, and run linting"
  cd $base/$_dir
  pwd
  poetry run black . --check
  poetry run isort . --check-only
  poetry run flake8 .
done
```

ただし、リポジトリ直下のディレクトリのみに対応しています
もちろん `sed` をいじればどうとでもなりますが
invalid_argument: key "" in the substitution data is not matched in the templateとなる原因

## エラー本文
```
invalid_argument: key "A" in the substitution data is not matched in the template
```

## コマンド
`gcloud builds submit --config ./cloudbuild.yaml`

## 原因
使っていないsubstitutionsがあるため

## yaml
```yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build','-t', '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}:latest','.']
    images: 
      - '${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}:latest'

#  省略　#

substitutions:
  _LOCATION: asia-northeast1
  _REPOSITORY: repo-name
  _IMAGE: image-name
  _SERVICE: service-name # This substitution is not used.
  _REGION: asia-northeast1 # This substitution is also not used.
```
[Swift] 毎回TestFligntアップロード時にコンプライアンスがありません・・・が煩わしい

##### リリース時、または他の方のテスト時にTestFligntへビルドをアップロードする事はSwift開発者なら必ず通る道だと思います。
そんな中、毎回アップロードを確認後に輸出規制の選択を回答しないといけないの、煩わしくないですか?
僕は毎回煩わしく感じていました😂初回はいいとしても、AppstoreConnect側で設定を更新してくれるわけではなく、何回も同じ回答を無駄に回答しているのが、ちっさなストレスです。

そんな僕と同じ気持ちの方のために、輸出規制の回答をしなくて済む方法を提供いたします。


### そもそも輸出コンプライアンス規制とは

https://developer.apple.com/help/app-store-connect/manage-app-information/overview-of-export-compliance

つまり、銀行アプリやパスワード管理アプリなど、暗号化してデータをやり取りするようなアプリの場合は、適宜書類の作成、申請が必要だと思われます。

さらに、こちらのドキュメントを見ていきます。

https://developer.apple.com/jp/help/app-store-connect/manage-app-information/detemine-and-upload-export-compliance-documentation/

>書類が不要な場合は、App が暗号化を使用していないこと、または書類の提出が免除されていることのいずれかであることを示せるよう、Xcode で情報プロパティリストファイル (Info.plist) を更新してください。

と、ドキュメントに答えのような文章が記載されていました😀

## [結論] info.plistの更新すればOK!!

https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations

ドキュメントに記載されている通りですが、info.Plistに

**App Uses Non-Exempt Encryption** を追加し、値を**No**で設定します。

![スクリーンショット 2024-08-19 10.00.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/72a5d357-8386-ce70-c099-2a9e95af1ae5.png)

以上になります。
FirebaseのGoogleService-Info.plistに含まれる不要なフィールドとは？

## はじめに
Firebaseプロジェクトを作成する際、生成された`GoogleService-Info.plist`ファイルを眺めていると、
- `IS_ANALYTICS_ENABLED(デフォルトでfalse)`
- `IS_APPINVITE_ENABLED(デフォルトでtrue)`
等が「これって何の設定なんだろう？」と思い、[Firebaseドキュメント](https://firebase.google.com/docs?hl=ja)を調べても、具体的な使い方が見つからず、疑問が膨らんでいきました。

以下はその一例です（値はサンプルです）。

```GoogleService-Info.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>API_KEY</key>
	<string>AIzaSyBvs8sUz9aDhobhBvh9EXCCD0M9D8-HztI</string>
	<key>GCM_SENDER_ID</key>
	<string>12345678910</string>
	<key>PLIST_VERSION</key>
	<string>1</string>
	<key>BUNDLE_ID</key>
	<string>com.example.native.app</string>
	<key>PROJECT_ID</key>
	<string>app-test-1234</string>
	<key>STORAGE_BUCKET</key>
	<string>>app-test-1234.test.com</string>
	<key>IS_ADS_ENABLED</key>
	<false></false>
	<key>IS_ANALYTICS_ENABLED</key>
	<false></false>
	<key>IS_APPINVITE_ENABLED</key>
	<true></true>
	<key>IS_GCM_ENABLED</key>
	<true></true>
	<key>IS_SIGNIN_ENABLED</key>
	<true></true>
	<key>GOOGLE_APP_ID</key>
	<string>1:12345678910:ios:f59549da64ce5774e4e7c5</string>
</dict>
</plist>
```

Firebase iOS SDKのバージョン: 10.29.0

## 結論は不要なものでした！！
調べた結果、これらのフィールドは古く、現在のFirebase SDKでは**不要なものである**ことが判明しました。Firebaseチームも、上記に加え以下の不要なフィールドを `GoogleService-Info.plist` から削除する提案をしています（2024/8/19時点）。これらはすべて、現在のSDKでは使用されていません。

https://github.com/firebase/firebase-ios-sdk/blob/6ddd42b8e0a5da411f2a35fc97c707697c48ce32/docs/FirebaseOptionsPerProduct.md#unread-googleservice-infoplist-fields


また、[firebase/firebase-ios-sdk：Discussions](https://github.com/firebase/firebase-ios-sdk/discussions/12961)にも同様の質問がありました。

### 不要とされるフィールド
- `PLIST_VERSION`（これはプロパティリストXMLスキーマの `<plist version="1.0">` 宣言とは異なります）
- `IS_ADS_ENABLED` ⇨ 以前はGoogle広告機能を有効化するためのフィールドでしたが、現在は設定ファイル内で有効化する必要はありません。Google AdMob SDKを使用し、コード内で広告ユニットIDを指定して管理
- `IS_ANALYTICS_ENABLED` ⇨ Firebase Analyticsはデフォルトで有効化されている。必要に応じて、コード内でデータ収集を有効化または無効化（[参考](https://firebase.google.com/docs/analytics/configure-data-collection?platform=ios&hl=ja)）。
- `IS_APPINVITE_ENABLED` ⇨ アプリ招待機能の有効化だが、現在はAdjust、AppsFlyer、Bitly、Branch、Kochava、などのディープリンク サービスか？（詳細は調べていないです）
- `IS_GCM_ENABLED` ⇨ Google Cloud Messaging (GCM)（すでに廃止） されており、Firebase Cloud Messaging (FCM) に移行
- `IS_SIGNIN_ENABLED` ⇨ かつてはサインイン機能の有効化を示していましたが、現在は不要。Firebaseのサインイン機能を利用する場合は、Firebase Authentication APIを使用

現状は使われていないのに、不要なフィールドのみが生成されているそうです。。
`IS_ANALYTICS_ENABLED`と`IS_SIGNIN_ENABLED`については、[#10712](https://github.com/firebase/firebase-ios-sdk/pull/10712)でメソッド削除はされているようです。




これらのフィールドがいつ頃から使われなくなったのか、ご存知の方がいればぜひ教えてください！ 

公式情報かどうかはわかりませんが、[Firebase Google Group](https://groups.google.com/g/firebase-talk/c/d2M07XBbW_8#:~:text=the%20IS_ANALYTICS_ENABLED%20boolean%20being%20NO%20is%20fine%20%2D%20that%27s%20actually%20an%20older%20bit%20of%20config%20the%20refers%20to%20Google%20Analytics%20Mobile.%C2%A0)を見ると`IS_ANALYTICS_ENABLED`については2017年にはすでに古いとされていたようです。
Next.jsのレンダリング手法

# Next.jsのレンダリング手法
1.静的サイト作成(SSG: Static Site Generation)
2.クライアントサイドレンダリング(CSR: Client Side Rendering)
3.サーバーサイドレンダリング(SSR: Server Side Rendering)
4.インクリメンタル静的再生性(SSG: Inmcremental Static Rendering)

# 1.静的サイト作成(SSG: Static Site Generation)
ビルド時にgetStaticPropsという関数が呼ばれてその関数の中でAPIコールなどを行い、ページ描画時に必要なpropsを返す。
- 静的ファイルをクライアントに返すだけなの描画が高速
- ビルド時のみデータ取得を行うためリアルタイム性が求められるコンテンツには不向き
# 2.クライアントサイドレンダリング(CSR: Client Side Rendering)
ビルド時にデータの取得は行わずにページを描画する。描画後に非同期でデータを取得してつかのデータを描画する。
- リアルタイム性が重要なページに適している
- ページに必要なデータは後から取得、描画されるためSEO的には不向き
- 基本的にSSG、SSR、ISRと組み合わせる形で利用される
# 3.サーバーサイドレンダリング(SSR: Server Side Rendering)
アクセスごとにサーバーでデータを取得するため常に最新のデータを元にしたページの描画ができる。
- リアルタイム性が求められるページに適している
- SEOに有効
- サーバーでの一定の処理があるため他の手法に比べると低レイテンシーになる
# 4.インクリメンタル静的再生性(ISR: Inmcremental Static Rendering)
SSGの応用のような手法。事前にページを生成して配信しつつ、データに有効期限が設定でき有効期限が切れた状態でアクセスがあったときバックグラウンドで再度getStaticPropsの実行とページ描画をしサーバーに保存されているページデータを更新する。
- リクエスト時にサーバー側での処理がないためレイテンシーを高く保つことができる
- ある程度新しいデータを元にしたページを表示することができる

---
Next.jsでは実装する関数や、その関数が返す値によってページのレンダリング手法が切り替わる。レンダリング手法を決定する主な要素はデータ取得の関数。
Chromebookのタッチスクリーンを無効化する方法

こんにちは、りょうです。
学校で配布されているChromebookのタッチスクリーンを無効化したいなと思ったのでまとめておきます。
ではれっつごー👍

## タッチスクリーン
Chromebookは一部の端末にはタッチスクリーンが搭載されています。
液晶パネルを指で押して反応する機能ですね。
ただこれはちょっと邪魔になるなあと思うときもあったので無効化していきます。
無効化してもマウス、タッチパッドは使えるのでだいじょぶ。

## 無効化の手順
**1: chrome://flagsを開く**
検索バーに`chrome://flags`と入力します。
そうすると別ウィンドウでこれが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/1026e622-1525-f5c3-0ca8-73edef6cfaff.png)

**2: 無効化のためのflagsを有効にする**
Search Flagsという検索バーの部分に`debugging keyboard shortcuts`と入力。
おそらくDisabledになっていると思うので**Enabled**(有効化)にし、下に表示されるRESTARTを押して再起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/97c69e00-ff2c-9c52-2dd2-be38574bd459.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/d75649e5-3fb0-559c-6c2e-8fe96cc60d88.png)

**3: ショートカットでタッチスクリーンを無効化**
まず、再起動した後も普通にタッチスクリーンは動作します。
なのでショートカットを使って無効化していきます。
`[検索(虫眼鏡マーク)] + [Shift] + [T]`を押すことで無効になります。
また、もう一度押すと有効になります。切替できるのはいいですね

![Screenshot 2024-08-16 09.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/057f24da-065b-eecc-07c9-1a2667839793.png)

## まとめ
今回はChromebookのタッチスクリーンの無効化方法の手順の紹介でした。
正直使う人はあんまいない気はしますが備忘録的な感じで残しておきます。

わからないことあったら書いてくれれば答えていきます。

**Discordにいる荒らしの情報や対策方法の共有をしている自鯖です**
ぜひ参加お願いします↓↓↓↓

https://discord.gg/ESRGwGQhxc
GROWI TypeScript/JavaScript SDKの紹介（その3：添付ファイルの操作）

[オープンソースの社内WikiであるGROWI](https://growi.org/)ではREST APIが公開されています。このAPIをより簡単に使えるよう、TypeScript/JavaScript SDKを開発しています。まだ途中ですが、徐々に機能追加していきます。

今回は添付ファイルの操作方法を解説します。

## 注意点

こちらはコミュニティSDKになります。公式への問い合わせはご遠慮ください。

## ソースコード

GROWI TypeScript/JavaScript SDKのソースコードはGitHubにて公開しています。ライセンスはMITです。

[goofmint/growi-sdk-alpha](https://github.com/goofmint/growi-sdk-alpha)

## インストール

インストールはnpm/yarn経由で行います。

```bash
$ npm install @goofmint/growi-js
# または
$ yarn add @goofmint/growi-js
```

## 使い方

まずはSDKをインポートします。

```javascript
const { GROWI } = require('@goofmint/growi-js');
// または
import { GROWI } from '@goofmint/growi-js';
```

そして、初期化します。この時、GROWIのAPIトークンを指定します。

```javascript
const growi = new GROWI({ apiToken: 'your-api-token' });
```

この他、以下のパラメーターを用意しています。

- `url` : GROWIのURLを指定します。デフォルトは`http://localhost:3000`です。
- `path` : GROWIのページパスを指定します。デフォルトは `` です。サブディレクトリにインストールしている際に指定します。

## ページの取得

添付ファイルはページに紐づいているので、まずはページを取得します。ルートからのページ取得は、以下のように実行します。返ってくるのは `Page` オブジェクトです。

```javascript
const page = await growi.root();
```

### ページ名指定での取得

ページ名（パス）が分かっている場合には、 `page` メソッドを使います。

```javascript
const page = await growi.page({path: '/ページ名'});
```

## 添付ファイルをアップロード

添付ファイルは `upload` メソッドを使います。一番簡単なのは、ファイルのパスを指定する方法です。

```javascript
const fileName = 'logo.png';
const attachment = await page.upload(path.resolve("path", "to", fileName));
```

取得した後、 `attachment.filePathProxied` で画像のURLが取得できます。以下のように本文に追加できます。

```javascript
page.set('body', `${page.body}\n\n![](${attachment.filePathProxied})`);
```

## 添付ファイルの一覧取得

`list` メソッドを使って、添付ファイルの一覧を取得できます。

```javascript
const res = await Attachment.list(page);
res.attachments // array of Attachment instances
res.limit // 10
res.page // 1
res.totalDocs // 20
```

### ファイルアップロードできるかチェック

ファイルサイズを指定して、アップロード可能かどうかをチェックできます。なお、GROWIのデフォルト値はサイズ無制限です。

```javascript
const bol = await Attachment.limit(1024 * 1024 * 10);
bol // true
```

### 添付ファイルの取得

添付ファイルを取得する際には、添付ファイルのIDを指定して `find` メソッドを使います。

```javascript
const a = await Attachment.find(id);
a // Attachment instance
```

## まとめ

GROWIは社内Wikiとして、社内システムとのデータ連係ニーズが出やすいでしょう。ぜひ、Node.js SDKを使って、GROWIをシステムから操作してください。

[OSS開発wikiツールのGROWI | 快適な情報共有を、全ての人へ](https://growi.org/)
【Revit】アドイン開発時にRevitのバージョンをアップする際の作業について

# 概要
Revitのアドイン開発時に、Revitのバージョンを上げたいということになった場合の作業についてまとめてみました。
Revitのバージョンを上げたいというのは、例えばRevit2019 → Revit2024に変更する、というような形です。

# RevitAPIについて
RevitAPIは、Revitのバージョンそれぞれにdllがあります。例えばRevit2021だったらRevit2021用のRevitAPI、Revit2024だったらRevit2024用のRevitAPIのdllがあります。

RevitAPIのdllは、Revitがインストールされているフォルダの同階層にあります。

`C:\Program Files\Autodesk\Revit (バージョン)\RevitAPI.dll`
`C:\Program Files\Autodesk\Revit (バージョン)\RevitAPIUI.dll`
`C:\Program Files\Autodesk\Revit (バージョン)\AdWindows.dll`
※(バージョン)には2019や2021等のバージョンが入ります。
※AdWindows.dllについては[こちら](https://qiita.com/MetroOsamu/items/f4a36525ed10a4c352d5)も参照ください。

# 作業
### STEP1
まずはアドインで使用しているAPIのdllを古いものから新しいものへ変更します。
例えばIDEにVisual Studioを使用している場合は、RevitAPIを参照設定しているプロジェクトについて、参照設定の変更を行います。
例)
今までの参照設定：`C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll`
新しい参照設定　：`C:\Program Files\Autodesk\Revit 2024\RevitAPI.dll`

### STEP2
アドインのdllについて、.NET Frameworkのバージョンを必要に応じ変更します。例えばIDEにVisual Studioを使用している場合は、各プロジェクトのプロパティ > アプリケーション > 対象のフレームワークから変更します。

どのフレームワークに変更が必要かは、以下のようなサイトが参考になります。

- [Revit2021](https://thebuildingcoder.typepad.com/blog/2020/04/whats-new-in-the-revit-2021-api.html)
- [Revit2022](https://thebuildingcoder.typepad.com/blog/2021/04/whats-new-in-the-revit-2022-api.html)
- [Revit2023](https://thebuildingcoder.typepad.com/blog/2022/04/whats-new-in-the-revit-2023-api.html)
- [Revit2024](https://thebuildingcoder.typepad.com/blog/2023/04/whats-new-in-the-revit-2024-api.html)

### STEP3
STEP2で示したサイトに、Revitのバージョンアップに伴うAPIの仕様変更の記載があるので、参考にしながらAPIの仕様が変わったクラスやメソッドの部分を適宜修正していきます。

:::note Info
ビルドを通してみて、ビルドエラーを確認しながら行うもの良さそうです。
:::

### STEP4
当たり前ですがアドインの処理でRevitのバージョンに関わるような処理がある部分 (例えば、Revitのバージョンによってアドインの挙動が変わるような分岐を行っている場合) や、ビルド後コマンドライン等の設定でRevitのバージョンに関わる処理の部分は、そのような箇所も対応が必要です。そのようなアドインの仕様に関わる箇所を修正していきます。また、.addinファイル内の記載の変更も行っていきます。

### STEP5
Revitを起動しアドインの動作確認・テストを行い、問題なさそうなら対応完了になります。
OpenCV imshowでマウスカーソルの位置の画素を取得する

opencvのcv::setMouseCallback()を用いると、cv::imshow()を使用した際に、マウスのクリックやポインターの位置に応じていろいろな処理を追加できます。
```c++
void cv::setMouseCallback	(	
const String & 	winname,
MouseCallback 	onMouse,
void * 	userdata = 0 
)	
```
以下のコードでは、マウスカーソルの位置に合わせて、カーソル位置のuv座標と、画素情報をコンソールに出力します。
```cpp
    cv::Mat colorImg = cv::imread("sample.png", cv::IMREAD_COLOR);
    cv::Mat srcImg;
    cv::cvtColor(colorImg, srcImg, cv::COLOR_BGR2GRAY);
    cv::imshow("test", srcImg);

    cv::setMouseCallback("test", [](int event, int x, int y, int flags, void* param)->void {
        cv::Mat* showImg = static_cast<cv::Mat*>(param);
        if (event == cv::EVENT_MOUSEMOVE) {
            if (showImg->type() == CV_8UC1) {
                printf("%d %d: %d\n", x, y, showImg->ptr<u_char>(y)[x]);
                return;
            }
            printf("%d %d\n", x, y); // グレースケールでない場合はカーソルの位置のみを出力
        }
    }, (void*)&srcImg);
    
    cv::waitKey(0);
    cv::destroyWindow("test");
```
setMouseCallbackの第3引数に渡した画像データsrcImgが、コールバック関数のparamに入ります。
第2引数の関数内でカーソル位置の画素をparamから取り出せば、画素が取り出されます。

## 動かない例
ラムダ式のキャプチャ項に表示する画像を渡す形では、コンパイルエラーとなります。
```cpp
    cv::setMouseCallback("test", [srcImg](int event, int x, int y, int flags, void* param)->void {
//                                ^^^^^^
        cv::Mat* showImg = new cv::Mat(srcImg);
        if (event == cv::EVENT_MOUSEMOVE) {
            if (showImg->type() == CV_8UC1) {
                printf("%d %d: %d\n", x, y, showImg->ptr<u_char>(y)[x]);
                return;
            }
            printf("%d %d\n", x, y);
        }
    });
```
WhatsAppにAPI接続するのに必要な代理店(BSP)

# 概要
- WhatsAppのAPIは一般公開されておらず、指定された代理店(Business Solution Providers (BSP))と契約する必要があります

# API接続時の必要事項
- 代理店(BSP)との契約(後述)
- どのWhatsAppとも紐づいていない電話番号(BSPによるかもしれませんが、関連するURLが見つかりませんでした)

## Meta社にも料金を支払う必要がある
- Meta社への料金は、送受信された個々のメッセージごとではなく、会話ごとに適用されます
  - 会話とは、ビジネスと顧客の間で交わされる24時間のメッセージスレッドのことです
  - WhatsApp Businessアカウントごとに、ビジネス電話番号全体で、毎月1,000個の無料サービス会話を利用できます
- https://developers.facebook.com/docs/whatsapp/pricing/
- https://business.whatsapp.com/products/platform-pricing



# 代理店

## Twilio
- https://www.twilio.com/en-us/messaging/channels/whatsapp
- 他にも、スマホへのPUSH通知、SMS、メール、音声サービスなど多くのインタフェースを提供している
- ドキュメントは、[こちら](https://www.twilio.com/docs/whatsapp)

## 360dialog
- https://www.360dialog.com/
- WhatsApp特化の企業
- ビジネスプランと開発パートナープランがあるらしい

## infobip
- https://www.infobip.com/whatsapp-business
- SMS、メール、音声サービスなど多くのインタフェースを提供している

## WATI
- https://www.wati.io/
- WhatsApp特化の企業
- 7日間の無料トライアルがある

## MessageBird
- https://bird.com/api/whatsapp
- SMS、メールなど多くのインタフェースを提供している
 
# 終わりに
API接続できると、ノーコードからでも送信できたり、マーケティング情報が得られたりするので、便利です。
Edgeにて画面の左側に出てくる赤紫の画面と`THE EXTENSION IS IN TRIAL VERSION THE CODE IS REQUIRED`というメッセージの原因

# はじめに

Edgeにて画面の左側に突如出てくるようになった赤紫の画面と`THE EXTENSION IS IN TRIAL VERSION THE CODE IS REQUIRED`というメッセージの原因が分かりましたので共有です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/5ce546f6-795a-cccf-9435-27c1ea307530.png)

# 結論
**Image Size Info**という拡張機能が原因でした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/c6713b0a-e8e3-de99-377d-d27f3d98275b.png)

# 対応
拡張機能削除にて対処しました

# 追記
こちらの拡張機能、作者が別の人に売ったようで、新たなオーナーが有料の拡張機能に変更したことが原因のようです。
40ドルの支払いをしないと、このモーダルが表示されるとのことです…！
（[コメント](https://qiita.com/kat_log/items/3ac70d201afb411d297a#comment-aad4a66101bf82984b3a "コメント")にて@juner さんにご共有いただきました。ありがとうございました！🙇）

# おわりに
お読みいただきありがとうございました。🙇
ネットで探したところ情報が見つからずでしたので共有です。
どなたかの参考になれば嬉しいです。
IBM i Services Directory : QSYS2.Memory_Pool_Info ビュー

[こちらのコメント](https://qiita.com/gomAnomalocaris/items/f428e0eb2d528a703f77#comment-a11b8a0c4d149f6d0989) にguri guriさんからご質問頂いた件です^^

WRKSYSSTSコマンドのメインメモリ（IBM i ではプールと呼称）関連取得値と同様な値を返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/6fc3096d-422d-5975-e4cf-c4db1733aa63.png)


各プールの割振りサイズ、最大活動ジョブ数、DBページ不在/Fault、Non-DBページ不在/Fault等の値をアクティブプール毎に1行返します。
WRKSYSSTSコマンドでは表示されない値も返されます。

## 概要
■ビュー名：QSYS2.MEMORY_POOL_INFO
■カテゴリ：実行管理サービス
■サポート：IBM i 7.2 SF99702 Level 9
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-memory-pool-info-view

## 実行例

```
SELECT * FROM QSYS2.MEMORY_POOL_INFO;
```

上記ですべてのアクティブなメモリプールの情報を返します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/f42efb4e-0479-370e-5690-031b08366840.png)

※上記の例では、別記事で使用したGOMALIB/GOMASBS1 を開始した状態です。結果、*SHRPOOL1, *SHRPOOL2 がアクティブになっています。

ちなみに上記のIBM i サービス実行結果とほぼ同じタイミングでのWRKSYSSTSコマンドの結果画面では、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/09e58442-5cb4-afbd-0fe5-7b051c69f5c3.png)

となり、Reserved Size = 予約済みサイズ(M)、 Maximum Active Thread = 最大活動であることが確認できます。
またWRKSYSSTSコマンドでは +++++ と表示されている*MACHINEプールの値が数値で表示（例では32,767)されています。

下記の辺りの情報は各プールの不在率、ページング回数ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/b678e622-d87e-d4ad-a4fe-3273056abda0.png)

※ただし最後の、TUNING_PRIORITY カラムはWRKSYSSTSコマンドだと表示されないと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/c8a8105f-f72c-3408-5997-f7364e803c62.png)

5250 WRKSYSSTSコマンドだと、、タイミングちょっとズレてて誤差ありますが近似な値が表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/fe0f99ad-6af0-a378-5c44-a1beff0f8b1a.png)


続く、TUNINGxxx というカラムもWRKSYSSTSコマンドでは返されないと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/7fcb1b8a-a95c-4629-5073-6ec30d2bf97f.png)

※マニュアルの記載は下記です。機械翻訳でちょっとわかり難いですが。。サンプルのシステムはQPFRADJシステム値が 2 なのでシステムの自動調整での最大・最小が表示されているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/66b29102-41e5-6b9c-eb5e-3c8ce7f13350.png)

※また、*MACHINEプール = 一番上の行 のTuning Minimum Faults と Tuning Maximum Faults はいずれも 10 で同一値となっていることが他のプールと異なる点ですね（他のプールはQPFRADJ 2時のページ不在数指標値の最小値と最大値が異なります）。

※あるシステムの事例で、マシンプールのFault値が3桁に届くシステム（マシンプールサイズが極端に小さいシステム）を見たことがあるのですが、このシステムではOSの基本機能（5250ジョブとの通信機能など）がページアウトされてしまい正常に動作しない、というような通常では起こらない症状がみられました。やはりマシンプールサイズは最優先で割り当てるべきだと思います。
Laravel と Inertia.js と React を使用してStorybookを起動したら`route is not defined`がでて困ったこと


# はじめに

こんにちは、エンジニアのkeitaMaxです。

Laravel10 と Inertia.js を使用して React アプリケーションを開発している際に困ったことがあったので備忘録として残しておきます。

# 困ったこと


```
<a href={route('register')}></a>
```
こんな感じでLaravelのrouteを使用してStoryBookを起動したところ、以下のようなエラーが出てしまいました。

```
route is not defined
```

が出てしまいました。


# 解決策

以下のように　`storybook/preview.js` route 関数のモックを作成しました。

```js:storybook/preview.js
import type { Preview } from "@storybook/react";
import "../resources/css/app.css";

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};

global.route = (name, params, absolute) => { // ←追加
  return `/${name}`; // ←追加
}; // ←追加

export default preview;

```

これで無事エラーが出なくなりました。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！
Lispの現代における意義

# reddit/lisp
英語圏のreddit/lispで投稿しましたら、思いのほか反響がありました。日本訳をここに投稿します。

# よくある質問
reddit/lispを見ていると、頻繁に同じ質問が繰り返し出てくるのを目にします。
「Lispは優れているにもかかわらず、なぜもっと広く使われないのでしょうか？」

私は、その答えはLispの本質そのものにあると考えています。私の意見では、Lispは知的なおもちゃです。ここでは、この問題に関する私の考えを共有したいと思います。

# 個人的なチューリングマシンへの欲求
1958年、マッカーシー博士はLispを考案し、発表しました。当時、IPL-Vというシステムが存在していましたが、マッカーシー博士はおそらくこれよりも優れたものを求めていたのでしょう。彼はかつて、自分の個人的なチューリングマシンが欲しいと言ったことがあります。Lispは多くの研究者に受け入れられ、AI研究に広く利用されるようになりました。マッカーシー博士の内心については推測するしかありませんが、彼は自分の研究を単なる仕事とは見なしていなかったと思います。彼にとって、研究は未知への楽しい挑戦であり、Lispはその探求のための楽しい知的ツールだったのです。

# 現代のプログラマーが失ったもの
ホイジンガは『ホモ・ルーデンス』で、遊びが人間の本質に深く関わっていると主張しました。彼は遊びを5つの主要な要素で定義しており、その中で最も重要なのは自由であると私は思います。もし活動が強制されたものであれば、それはもはや遊びではありません。義務によって押し付けられた真剣さほど退屈なものはありません。
![bandicam 2024-08-17 13-19-44-103.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/5907f368-8d87-2749-3cce-4fbec9a8c9d3.jpeg)


一方で、企業は利益を追求する組織です。ソフトウェア開発においては、効率が最も重要です：指定された時間内に、必要な性能を満たす製品を作り、一貫して利益を生み出すこと。そうした環境では、自由を見つけることは難しいです。効率が求められるタスクには、現在主流のPythonのような言語が優れています。会社のルールは物事の進め方を決定し、製品は既に無数に作られたウェブアプリケーションで終わることが多いです。自由な挑戦の余地はなく、ソフトウェアエンジニアたちは生活のために働く必要に駆られ、日々労働に明け暮れています。

# Lispの道
Lispは、その起源からして自由を体現しています。あの奇才、マッカーシー博士は決して仕事を義務と考えたことはありませんでした。Lispには彼の自由な魂が宿っています。Lispを企業の利益を効率的に生み出すためのツールと期待するのは無謀です。火星探査ローバーの制御ソフトウェアがCommon Lispで書かれたと言われています。NASAのエンジニアたちは、これを仕事の一環として作成したのでしょうか？私は、それが人類史上初の問題に挑戦するという知的好奇心から生まれたものであったと信じています。彼らはこの前例のない挑戦に取り組みながら、喜びに満ちて遊んでいたに違いありません。
![bandicam 2024-08-17 13-18-36-082.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/8a66b064-c22a-61d8-7b88-f3960db5d8af.jpeg)

今日、存在するプログラミング言語のほぼ99%は、仕事のために存在しています。ソフトウェア開発者たちは、企業の利益を生み出し、生計を立てる義務に追われて日々労働しています。しかし、そんな彼らもLispを遊ぶときには、自分たちの自由を存分に享受できます。Lispほど楽しいおもちゃはありません。Lispは人間の本質を満たす上で大きな貢献をしています。真剣さだけで満ちた人生は、何としても避けたいものです！Lispを楽しんで遊びましょう。新しい技術はしばしば遊びから生まれ、時には利益に結びつくことさえあります。人間の文化は遊びから発展してきました。Lispを使って楽しむ人々を見ることは、きっと天国から見守っているマッカーシー博士にとって大きな喜びとなるでしょう。
Lightning templateでIFを使う



+ [Lightning メール テンプレート、拡張レターヘッド、メール テンプレート ビルダーで Handlebars マージ言語を使用する](https://help.salesforce.com/s/articleView?id=sf.handlebars_template_language.htm&type=5)

:::note
Summer '18 では、Lightning Experience のメールテンプレートに Handlebars Merge Language (HML) が導入されました。メールテンプレートに 3 つの中括弧 ({{{) が付いた差し込み項目がある場合は、HML メールテンプレートを使用しています。差し込み項目に 1 つの中括弧 ({) または感嘆符 (!) がある場合は、SML (Salesforce Merge Language) メールテンプレートを使用しています。Summer '18 以降に作成された Lightning テンプレートは、HML メールテンプレートです。
:::

:::note
Pardot ハンドルバー マージ言語 (HML) は、%%email%% や %%assigned_user.name%% のような形式の変数タグを使用していた旧来の Pardot マージ言語 (PML) に代わるものです。
HML は %% の代わりに {{ を使用して見込み客データを結合します:
:::

以下を考慮するとLightning templateでも{{{と{{の２つの表記が使えるということ？


+ [Lightning template if/then](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ifdqr)


```
{{#if Sender.Canopy_Connect__c}}
You can alway use this link {{{Sender.Canopy_Connect__c}}}
{{else}}
null
{{/if}}
```

+ [If your lightning email template is upgraded to HML](https://ideas.salesforce.com/s/feed/0D58W0000DVGClBSQX)

この形は使えないですね。

```
{!IF({!Case.Origin ="Website",Case.Description, "")}
```

:::note alert
This template doesn’t support SML merge fields. Use the merge field picker to replace merge fields starting with "{!".: HTML Value
Attribute "data-highlighted" on element <code> is not allowed, or has an invalid value.
:::

差し込み項目としては以下が選べる。今回は実行しているUserだったのでSenderを選択してみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5528f308-063c-dea4-b103-8f403db3dc5b.png)


+ [メールテンプレートおよびレターヘッドでの差し込み項目の使用](https://help.salesforce.com/s/articleView?id=sf.merge_fields_parent.htm&type=5)

+ [Lightning メール テンプレートを SML から HML に変換する](https://help.salesforce.com/s/articleView?id=sf.email_template_convert_from_SML_to_HML.htm&type=5)
既存の Lightning メール テンプレートを変換することで、Salesforce Merge Language (SML) よりも柔軟性の高い Handlebars Merge Language (HML) を活用します。

+ [Add record detail link (merge field) in Lightning Email template (like classic)](https://ideas.salesforce.com/s/idea/a0B8W00000GdZDHUA3/add-record-detail-link-merge-field-in-lightning-email-template-like-classic)

+ [アイデアに上がったままですが、可能になっている：Lightning のメール テンプレートで条件文を許可する](https://ideas.salesforce.com/s/idea/a0B8W00000GdiQDUAZ/allow-conditional-statemements-in-email-template-in-lightning)

+ [Sales Emails and Alerts のキャンペーン](https://qiita.com/Keiji_otsubo/items/33d81c8a85cd5d1b6b99)

# This template doesn’t support SML merge fields. Use the merge field picker to replace merge fields starting with "{!".: HTML Value

+ [If condition in Email Template not working](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000NlFu)

```
{{#if Case.is_custom_true__c}}
Yes
{{else}}
No
{{/if}}
```

フィールド is_custom_true__c は 1 または 0 を返します。HML の IF 条件は、フィールド値が空白かどうかをチェックします。空白でない場合は if 部分を実行し、空白の場合は else 部分を実行します。

したがって、あなたの場合、チェックボックス フィールドは常に値を返すため、どちらの場合もYesが印刷されます。 

条件を評価して目的のテキストを返す数式フィールドをオブジェクトに作成できます。

たとえば、次の数式を使用して、Case に数式フィールド Formatted_Value__c を作成します。
GitHub Actionsでpythonファイルの型チェック、文法エラーチェック、フォーマットチェックをする

# 結論
以下のyamlを `.github/workflows` 以下に置く。

```py_checker.yaml
name: 'Check python file'
run-name: 'Check types, syntax and format.'
on:
  push:
    branches:
      - "feature/*"
    paths: 'app.py'

jobs:
  mypy:
    runs-on: 'ubuntu-latest'

    steps:
      - name: 'Checkout repository'
        uses: 'actions/checkout@v4'
        with:
          submodules: false
          fetch-depth: 0

      - name: 'Set up python'
        uses: 'actions/setup-python@v5'
        with:
          python-version: '3.10'

      - name: 'Run image'
        uses: 'abatilo/actions-poetry@v2'
        with:
          poetry-version: '1.7.1'

      - name: 'Install dependencies'
        run: |
          poetry install --no-root

      - name: 'Check types'
        run: |
          mypy app.py
  flake8:
    runs-on: 'ubuntu-latest'

    steps:
      - name: 'Checkout repository'
        uses: 'actions/checkout@v4'
        with:
          submodules: false
          fetch-depth: 0

      - name: 'Set up python'
        uses: 'actions/setup-python@v5'
        with:
          python-version: '3.10'

      - name: 'Run image'
        uses: 'abatilo/actions-poetry@v2'
        with:
          poetry-version: '1.7.1'

      - name: 'Install dependencies'
        run: |
          poetry install --no-root

      - name: 'Apply linter'
        run: |
          flake8 --max-line-length 120 app.py
  black:
    runs-on: 'ubuntu-latest'

    steps:
      - name: 'Checkout repository'
        uses: 'actions/checkout@v4'
        with:
          submodules: false
          fetch-depth: 0

      - uses: 'rickstaa/action-black@v1'
        with:
          black_args: '--line-length 120 --skip-string-normalization --check --diff app.py'
```

## 注意点
- 上記ファイルでは `app.py` だけをチェック対象にしているので、ソースコードが複数ファイルある場合は適切に指定する
- 上記ファイルでは `feature/*` という命名のブランチのみを対象にしているので、必要ならそこも適宜書き換える
- blackのコマンドも必要に応じて変える。ここではファイルに変更を加えない＋文字列の引用符をシングルクオテーションからダブルクオテーションに直さない＋1行の長さは120文字でフォーマットしている