OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Jam体験会レポート 〜体験から社内への展開に向けて〜

先日、AWS主催のAPN（AWS パートナーネットワーク)向けのAWS Jam体験会へ参加させていただく機会がありました。今回は各社2名という定員だったのですが、運良く参加することができたので、体験した所感や今後社内への展開にむけたアクションなど記録として残しておきます。

# AWS Jamとは？
- 事前に周到に準備された課題シナリオを実際のAWS環境を利用しながらクリアして、得点を競い合うイベントです(ハンズオン形式の学習コンテンツ)。

- 似たものにGameDayがありますが、Jamには複数のヒント(手がかり)が用意されています。課題がお手上げのときには、この手がかりを使ってヒントを得ることができますが、手がかりを使うとペナルティ(減点)が発生してしまいます。課題の残り時間を考慮しながら手がかりを使うのか、使わないほうがいいのか、このあたりはチームごとの戦略にも依存してきます。

- 課題(チャレンジ)には「Easy」「Medium」「Hard」の三段階のレベルがあり、課題のレベルごとに所要時間や得点が異なります。難しいほど得点も高くなります。

- 課題への取り組み方法は、一つのチャレンジにみんなで取り組む「モブ型」、二人で取り組む「ペア型」、一人で取り組む「ソロ型」がありますが、今回の体験会では、「モブ型」で実施しました。

- チーム課題にチャレンジすると、CloudFormationで環境が構築されるため、少し時間がかかります。
- チーム戦なので、ダッシュボードで全チームの状況(得点、ヒントの利用状況など)を見ながら課題への取り組み方法を考えることになります。
- あとで振り返るための Google Documentが用意されており、学んだこと、わからなかったことを記載するようになっています。が、そんな余裕はなかったです(笑)。

## 事前準備
- AWS Skill Bulder アカウントの事前作成
  - 事前に手順が配布されますので、その手順に沿って AWS Skill Builderのアカウントを作成しておきます。
  - 特に料金はかかりません。
- AWSパートナーセントラルアカウントの事前作成
    - APN向けということで、AWS パートナーセントラルのアカウントが必要となりますので、AWSパートナーセントラルのアカウントを持っていない場合は、作成しておく必要があります。
  - APN所属の会社で認定試験など受けている人はすでに持っていると思います。

## Jamの流れ
1. まずは、チーム分けになります。今回はあらかじめチームが指定されており、自分の名前のあるテーブルへ着席です。今回のチームは4名構成です。
1. 名札に名前を書いて皆が揃うまで大人しく待ちます。JAMステッカーとCertifiedステッカーを頂きました。サングラスのサルの名前は知らないですw
![IMG_8302.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117386/89053430-6d44-052a-0aaa-0c73923eeb03.jpeg)
他にホワイトボードも用意されていて構成図を書いてもよいようになっています。が、これも余裕がなく使いませんでした(笑)。
1. Jam Eventへ参加してスタートです。自己紹介をしてチームへジョイン、チーム名を決定(既存のチーム名の変更)します。
1. 準備が終わると課題が表示されます。言語の選択、ダークモード・ライトモードの選択ができるようになっています。翻訳がおかしいケースもあるようなので、これは認定試験と同様に英語に変更してみると意味がわかるかもしれません。
1. 課題を選択してクリアしていきます。詳しくはブログに記載できないので、まずはここまでにしておきます。


# 所感
- 資格取得のためのインプット、操作するためのハンズオンとは異なり、実際に複数のサービスに対して関係性を意識しながら操作して課題をクリアすることで、より理解度が高まるものと感じました。
- 自分が普段さわっていない疎遠なサービスの課題はやはりクリアに時間がかかってしまいます。
- 参加するまではどんな感じだろうと少しドキドキはありましたが、参加してみると、みんなでこれどうするんだっけ、とかこれこうしたらいいんじゃないです？とかコミュニケーションを取りながら進める形式なので、課題解決を楽しめるプログラムだと実感しました。
- 自分が解けなかった課題については、自分で復習する、または講師やチームメンバーにレクチャーしてもらうことで理解度は深まるものと感じます。
- チーム対抗戦なので、つよつよエンジニアがいれば結構スムーズに解ける問題も多いが、初心者だけのチーム編成だと課題のクリアは厳しいかもしれません。このへんはチーム編成にも工夫が必要になるかもしれません。
- つよつよエンジニアだけ集めて完全ソロで得点を競うってのも面白そうです。

# 社内展開に向けて
Jamの存在や雰囲気は知っていましたが、今回自分が体験したことでJamコンテンツの素晴らしさを実感しましたし、継続的な学びと実践に加えて効果的なスキルアップが図れそうだと改めて思いました。資格だけ取って実際にAWS案件に参画できてない人にも有効そうですね。

Jamはマジで全AWSエンジニアに体験してほしい！！と思いましたので、まずは社内への展開に向けてどういう形式でできるかはAWSさんと相談になるかと。Skill Builderの有償サブスクリプションが必要らしいのでこのへんがハードルになりそうな予感です。

# まとめ
AWS Jam体験会へ参加してきましたので、イベントの概要とその所感について書いてみました。

今回現地参加するre:Invent 2023でもJamセッションがありましたので、早速申し込んでみました。
よかったら誰か一緒に参加しませんか？

海外でのJamはどんなものなのか、、、
そして社内での展開についてはまたの機会にご報告できたらなと思います。
webapp-manager が起動しない (Linux Mint)

## 経緯
- ウェブアプリをポチポチと登録していたら、マネージャが起動しなくなりました。

### 環境
- webapp-manager 1.3.2
- Linux Mint 21.2 (Xfce)

## 現象
- ウェブアプリを起動しても、ウィンドウが開かず、何も起きません。
    - アプリを削除してインストールし直しても変化はありません。
- 生成済みのウェブアプリは問題なく起動、編集が可能です。
    - 生成されたウェブアプリは、単なるランチャーなので、当然なのですが…。
- ターミナルからマネージャを起動してみると、エラーを吐いて終了していました。

## 原因
- アイコンに設定した画像に、マネージャが対応できなかったようです。
    - 問題の画像は「アニメーションgif」でした。
    - ランチャーは、アニメgifでも、問題なく対応しているようです。

## 解決
- アイコンに指定していた画像ファイルを削除したところ、ウェブアプリはデフォルトアイコンに変わり、マネージャが起動するようになりました。
- ランチャーを編集して、静止画像を登録し直しました。
Asteriskでひかり電話にIPv4/v6同時にRegister

自分用メモとしての記載

# ひかり電話のIPv6
ひかり電話ではIPv4/v6の両方でSIPを受けることができる。IPv4のみの対応の場合、相手がIPv6でかけてきた場合、受けることができない。
参考：[スマホ de ひかり電話 で一部電話番号に発信できない](https://intinfinity.com/index.php/archives/441)

そこでIPv6のRegisterを行う必要がある。IPv6をRegisterする場合IPv4でのRegister時にまとめてIPv6のアドレスをContactヘッダーに乗せる必要がある。
参考：[音声利用 IP 通信網サービス（第 2 種サービス タイプ 2）](https://www.ntt-west.co.jp/info/katsuyo/pdf/09/tenpu21_2.pdf)


# Asteriskでの設定
Asteriskのpjsip.confを見るとcontactをRegister時に追加で送るような設定は見当たらない。
しかし、type=registerのcontact_header_paramsを設定するとContactヘッダーの後ろにkey=valueのような形式でパラメータをつけることができる。

目標とするContactヘッダーの中身は以下の通りである(IPv6アドレスは[]で囲む)。
```
Contact: <sip:電話番号@v4アドレス:5060>,<sip:電話番号@v6アドレス:5060>;
```

試行錯誤したところ、","をcontact_header_paramsで送るには二重引用符でくくってAsteriskで特殊文字でなく文字として判定させればいいことが分かった。
その結果、以下のような形で設定を行うとRegister時に余計なパラメータが付くがIPv4/v6のRegisterが行えることが分かった。
```
contact_header_params = a="\",<sip:電話番号@v6アドレス:5060>\;a=\"v"
```

# Register以外の設定について
transport, aor, identify, endpointについてはIPv4と同様の設定をIPv6アドレスで行う必要がある。
SIPサーバーのIPv6アドレスはDHCPv6で取得することが可能。
google_mlkit_text_recognitionで日本語用言語パッケージを指定するとエラーが出るとき

Flutterで[TextRecognition](https://pub.dev/packages/google_mlkit_text_recognition)を使う際、pub.devの記載に従って日本語の言語パックを指定すると以下のエラーが出ました

`java.lang.AbstractMethodError: abstract method "java.lang.String com.google.mlkit.vision.text.TextRecognizerOptionsInterface.getConfigLabel()"`

環境
- google_mlkit_text_recognition: 0.10.0
- Flutter: 3.13.5
- エミュレータ: Android Pixel5

## 解決
pub.devでは、Android用に言語パックを指定する際の例として以下のように記載されています
```gradle
dependencies {
    implementation 'com.google.mlkit:text-recognition-japanese:16.0.0-beta6'
}
```

betaの記述を取り除けば問題なく動きました。

```gradle
dependencies {
    implementation 'com.google.mlkit:text-recognition-japanese:16.0.0'
}
```
Vue.js学習の個人メモ

# 「一日で基本が身に付く！Vue.js」石亀　広大　[著]

この本を終えると、JavaScriptにおけるVue.jsのメリットがわかる！
ついでに以下のアプリを作成できる
・TODOアプリ
・画像ビューワー



## Vue.jsはJavaScriptフレームワーク

プログレッシブ(斬新的)フレームワーク
　→規模によって段階的に利用できる
コンポーネント志向
　→部品の組み合わせで構築できる

フロントエンドのフレームワークは他にも
　RaectやAnglar

　例えばDjangoは?
　　Pythonで実装されたWebアプリケーションフレームワーク

Vue.jsは学習コストが低い
→HTMLとJavaScriptに馴染みがあればすぐ理解できる

Vue.jsと比較されることが多い他のフレームワークでは、Babelやwebpackの利用が前提だが、Vue.jsは必要なし。
(Vue.jsでも必要に応じてwebpackなどツールを導入できる)

デバックにはDevToolsが欠かせない。
GoogleGhromeでは「Chrome DevTools」というWEB開発ツールが標準で用意されている。

「console.log()」はJacaScriptの通常開発と同様に利用可能。

```script.jsファイル
new Vue({
  el: '#app'
  });
```
```index.htmlファイル(CDN利用時)
 <body>
    <div id="app">hello Vue.js</div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./script/script.js"></script>
  </body>
```



## Vue.jsのポイント

通常のJacaScript
　１．HTMLの要素を取得
　２．データを変更
　３．HTMLへの繁栄

Vue.jsでは
　データバインディング機能により、保持しているデータと画面に表示されているデータが同じ状態になる
```script.js
new Vue({
  el: '#app',
  data() {
    return {
      count: 0
    };
  },
```

```index.html上にそのまま数値を表示できる。バインディング。
 <p>{{ count }}</p>
```




### Vueインスタンスのプロパティ
・el　→Vueインスタンスを結びつけるHTML要素を指定
・data　→データを入れておく場所
・methods　→メソッドを定義する場所
・computed　→算出プロパティ。バリエーションに使える。
・template　→HTMLテンプレート
・components　→外部モジュールとして取り込んだコンポーネントをHTMLテンプレートとして使える



## Vue.jsのキーワード
・レンダリング(以下の記述が人に説明しやすいので忘れ防止で記載する)
　→あるルールに従って記述されたデータを、人間が読める形に整形してブラウザに表示すること

・Vue.jsの「差分レンダリング」「仮想DOM」
　→更新が必要な部分だけレンダリングする差分レンダリング
　→通常のDOMとは違い、更新が必要な部分を検出するために利用する仮想DOM
　※DOM(Document Object Model)→　JacaScriptから操作する際に使われる仕組み

・JavaScriptのメソッドの書き方
「this」はオブジェクトそのものを差し、同じオブジェクトのプロパティを利用するときに使う。

```script.js
new Vue({
  el: '#app',
  data() {
    return {
      count: 0
    };
  },
  methods: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    }
  }
```

・条件付きレンダリング
v-if, v-elseはVue.js特有の要素
<br>

・双方向バインディング
v-model
```script.js
const app = new Vue({
  el: '#app',
  data() {
    return {
      name: 'name_test'
    };
  }
```
```index.html
 <input v-model="name" type="text" name="" />
```
　→ただし、イベントハンドラ記載したほうが自由度が高い
<br>

・バリデーション
computedで記載
```script.js
new Vue({
  el: '#app',
  data() {
    return {
      name: 'name',
    };
  },
  computed: {
    isInValidName() {
      return this.name.length < 4;
```
<br>

・リストレンダリング
v-for
v-bind
　:key="i" →v-bind:key="i"の短縮形
　v-forの変数i(indexが入っている)をkey属性にバインディングしている。　※Vue.jsが識別できるようにする
<br>

・スタイルバインディングで見た目を動的に変える(以下、v-bindの省略)
```script.js
new Vue({
  el: '#app',
  data() {
    return {
      range: 10,
    };
  },
  computed: {
    bindStyle() {
      return `width: ${this.range}px; height: ${this.range}px;`;
    }
  }
```
```index.html(v-vind短縮)
<div :style="bindStyle"></div>
```
<br>

・クラスバインディング
```script.js
new Vue({
  el: '#app',
  data() {
    return {
      isActive: true
    };
  },
```
```index.html(v-vind短縮)
<div :class="{'is-active': isActive}"></div>
```
今更ながらB550 Vision D-P(GIGABYTE)の不具合をまとめる

GIGABYTEから発売されたVisionシリーズ（以降はAeroシリーズと統合したっぽい？？）のマザーボード、B550 Vision D-Pですが、2年使ってて結構不具合が多いのでまとめてみます。

<<構成>>
B550 Vision D-P
Ryzen7 5700G
Corsair Dominator Platinum DDR4-3200 64GB
Vision RTX 3070

## メモリスロットがガバい
これは物理的な話です。今まで何十枚もマザーボードを扱ってきましたが、「メモリを差し込んだのに接触が悪くてエラーが発生」なんてふざけた現象はこれが初めて。普段から信頼性が高いGIGABYTEなだけあって少し残念。対処法はラッチが閉まった後もさらに力を込めて奥までしっかり差し込むこと。

## チップセットのUSBが不安定すぎる
このマザーボードのバックパネルには6本のUSB-A端子があって、そのうち上３つはCPU内蔵コントローラーで下３つはB550チップセット内蔵コントローラーで制御している。
んでチップセット側のUSBがまぁ酷い。
重たいゲームを動かせばキーボードもマウスもブッツブツです。多分チップセットのバス帯域がカツくなると周辺機器が全部影響されるっぽい。クソ仕様です。
LianLiのRGBファンコンも内部コネクタで繋いでますが、そいつも影響されてブツブツ切れます。

これはどちらかといえばチップセット側の問題であってGIGABYTEの問題じゃないかもしれませんが、かなり致命的なのでCPU直結USB端子のみを使って対処しています。

## RGB Fusionがバグる
一応グラボも同じVisionシリーズなので、相性問題は特に無いはずなのですが、RGB Fusionでグラボが検出されなくなる。これも結構頻繁なので面倒です。

## 要するにI/Oが不安定
さらっと思いつくのはこのぐらいですが、一言でまとめればI/O関係の不具合が結構目立つマザーボードです。BIOSを更新しても再発したり、メモリを定期的に刺し直さないといかなかったり、何かとメンテナンスに知識と体力を割かれるのはいくらオタクでも厳しい部分はあります。
来年あたりにZ790 AeroGを購入しようと思っていますが、今度はIntelとGIGABYTEを信じて期待してます。
Pythonフレームワーク FastAPIの特徴

FastAPIは、現代的な、高速（高性能）な、Web APIを構築するためのPythonフレームワークです。

以下に、その特徴とメリット、デメリットを簡単に説明します。


### 特徴
- **非同期処理**: FastAPIはPythonの`async`と`await`をフルサポートしており、非同期プログラミングを容易にします。
- **型ヒント**: Python 3.6以上の型ヒントを使用して、パラメータのバリデーションを自動化し、エディターサポート（自動補完、型チェック）を提供します。
- **データモデルの自動生成**: Pydanticライブラリを使用して、リクエストとレスポンスのデータモデルを定義します。
- **ドキュメントの自動生成**: Swagger UIとReDocを通じて、リアルタイムでAPIドキュメントが自動生成されます。

### メリット
- **高速なパフォーマンス**: Starlette（ASGIフレームワーク）上に構築されているため、非常に高速です。
- **直感的**: 型ヒントと自動ドキュメント生成により、エンドポイントの作成が直感的で簡単です。
- **柔軟性**: 複雑なユーザ認証システムやデータベース接続など、多様な機能を簡単に統合できます。
- **開発の迅速化**: 自動ドキュメントと型ヒントによって、バグの少ないコードを迅速に開発できます。

### デメリット
- **学習曲線**: 非同期プログラミングや型ヒントに不慣れな場合、初心者には少し学習が必要かもしれません。
- **非同期対応のライブラリ**: 非同期処理をフルに活用するためには、非同期に対応したライブラリが必要ですが、これが不足している場合があります。
- **生態系の若さ**: FastAPIは比較的新しいため、FlaskやDjangoのような成熟したフレームワークほど豊富なリソースやプラグインが存在しない場合があります。

FastAPIは、パフォーマンスと開発速度のバランスが取れているモダンなAPIフレームワークとして、多くの開発者に選ばれています。初心者であっても、ドキュメントが非常に充実しているため、比較的短期間で習得と利用が可能です。



### APIとは？
APIは「Application Programming Interface」の略で、ソフトウェアやプログラム間で互いに通信するための規則やプロトコルの集まりです。APIは、特定のサービスや機能にアクセスするために、開発者がプログラム内で使用できる命令や関数を提供します。

例えば、ウェブAPIでは、ウェブサービスがインターネットを介して情報を共有するためにHTTPプロトコルを利用しています。これにより、ユーザーのリクエストに基づいて、データの読み取り、書き込み、更新といった操作が可能になります。APIは、ウェブサイト、アプリ、クラウドサービスなど様々な場面で利用され、異なるソフトウェアやサービス間での相互運用性を高めます。



### プロトコルとは？
プロトコルは、コンピュータやデバイス間の通信における共通の言語や規則のセットです。これにより、異なるシステムやネットワークがデータを交換し、互いに理解し合うことが可能になります。通信プロトコルは、データの形式、タイミング、送信方法などを定義し、信頼性の高いデータ転送を実現するために必要です。

例えば、インターネット上ではHTTP（HyperText Transfer Protocol）がウェブサーバーとクライアント（ウェブブラウザ）間の通信に使用され、メール送信にはSMTP（Simple Mail Transfer Protocol）が使われます。これらのプロトコルは、特定の規則と標準に従っており、全世界のデバイスがスムーズに通信できるようにしています。
[Linux] ゴミ箱に関する調査メモ

# 目的
ファイルやディレクトリをゴミ箱に移動させるプログラムを作成した時の調査メモを備忘録として記録する。

# ゴミ箱の場所
Freedesktop.orgの仕様[^1]によると、デスクトップ上にある「ゴミ箱」は`$XDG_DATA_HOME/Trash`にあるとのこと。なお、`$XDG_DATA_HOME`が設定されていない、或いは空の場合には`$HOME/.local/share`がデフォルトとして使用される[^2]。

Trash配下には以下のサブディレクトリがあり、これらを活用してゴミ箱機能を実現・管理している。
- `/info`
    - `/files` にあるファイルとディレクトリを管理するための情報ファイルが格納されるディレクトリ
    - 情報ファイルは`/files`にあるファイルらと同一名で拡張子に`.trashinfo`が付与されたファイルが格納されている(例: hoge.txtをゴミ箱に移動させたら、hoge.txt.trashinfo)
- `/files`
    - ゴミ箱に入れられたファイルとディレクトリが格納されるディレクトリ


# <ファイル・ディレクトリ名>.trashinfoの実装
Freedesktop.orgにサンプルが掲載されている。
```
[Trash Info]
Path=foo/bar/meow.bow-wow
DeletionDate=20040831T22:32:08
```

`.trashinfo`が準拠すべき仕様は以下の通り。
- 最初の行は必ず`[Trash Info]`でなければならない
- `Path=`と`DeletionDate=`以外のキーペアが存在する場合は他の行を無視する
- 複数の`Path=`や`DeletionDate=`がある場合は、最初に記載されているものが使用される

他にも付随する仕様に以下のものがある。
- ファイルやディレクトリをゴミ箱に入れるとき、実装は最初に`$trash/info`に対応するファイルを作成しなければならない
- `/info`にはサブディレクトリがないこと
- etc.

# ゴミ箱内に同名ファイル・ディレクトリが存在する場合
GUIなどを使ってファイル・ディレクトリをゴミ箱に移動させる際、ゴミ箱内に同一名のファイル・ディレクトリが存在している場合には名前に".数字"を追加して保存する模様。
```
$ ls ~/.local/share/Trash/info/
hoge.2.trashinfo   hoge.trashinfo   test.2.txt.trashinfo   test.txt.trashinfo

$ ls ~/.local/share/Trash/files/
hoge  hoge.2  test.2.txt  test.txt
```

`info`ディレクトリ内にある`Path=`には同一であることから、`Path=`以降の文字列を参照して「元に戻す」機能を実現している
```
$ cat ~/.local/share/Trash/info/test.txt.trashinfo  
[Trash Info]
Path=/tmp/test.txt
DeletionDate=2023-11-05T01:46:55Z

$ cat ~/.local/share/Trash/info/test.2.txt.trashinfo
[Trash Info]
Path=/tmp/test.txt
DeletionDate=2023-11-05T10:47:15
```

[^1]: https://specifications.freedesktop.org/trash-spec/trashspec-latest.html
[^2]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
[typescript]Promise関数の種類、並列処理、並列処理とその使い分け

この記事を読むにあたって以下の前提知識を踏まえていると、より理解しやすいと思います。

 - javascriptでアロー関数の書き方を理解している。
 - `async`, `await`を使用した非同期処理を理解している。
 - node.jsの実行環境でjavascriptをコードを動かしたことがある。
   - typescriptであればplaygroundを使用したことがある。
 - typescriptの基本的な文法と理解している。



**今回書いたコードは[typescript playground](https://www.typescriptlang.org/play?ts=5.1.6#code/MYewdgzgLgBBA2BTRAHGBeGBDCBPMwMAFALYSLABcMYAriQEaIBOAlNQArMgkCW5AHgBuIXgBMAfBilhEAdxhce-RESLNEEEPCGJW0mAG8AUDDiIoAFV4lEIWlDX70Uk2bOhI2xADp4IAHMiACIoAAt+GBRuYE0IGEQADwoHRDFg1lN3DS0dVUyzAF8AGhgyCkzC1gBuY2MAenqYQDI5QHQlQDPFQDAXYyIcfEIiZ1csz2g4KCxmWEwUFgAzEGYSLAJfMBA5QdqzLDksXlglPnIfLHh4IgBtBGQUIgBGAAZn1lKb1CIAJmfH17gkD4AZh+rAAugUYKNYIgwGIMFF5otlqsfOtNjURuBcr5-EEAAbRECxCDxM7wBLJYCpOFJFJQNIwKA2RAwAAkhhhcIAtONJlBCmVePBeOZPGI8ZVWFs6o0YIAXtw63V6eAIxCGRkxkFg0D58NmzAWSxWsVRG2lZkNxChopgIDmMEuT2exW+zuBz3BGvc2D2B3+tyI5GAEMKmrGnL1iKNKLR5shWO8fkCRAJMTi2HOFLpDNpVPpcKZtjZHNhMB5OqmAr4wtF4HFkq2QA)で確認できます。** 🤭


実行環境 

typescript


## 結論

- **並列処理のメリット**
  - 総合的な処理が早い
- **並列処理のデメリット**
  - 並列で走りたい処理が多い場合、通信先のサーバーへの負荷が重くなる。
  - 通信先のAPIサーバーのスペックが小さい場合、レスポンスが不安定になりエラーが返却されてしまう。

- **直列処理のメリット**
  - APIを叩く場合、通信先のサーバーに負荷を軽減できる。
- **並列処理のデメリット**
  - 総合的な処理時間がかかる。


## 用意

並列、直列時の実行時間を検証してみます。
まず、決められた秒数で待機するスリープ関数を定義します。

```typescript
const sleep = async (msec:number):Promise<void> => new Promise((resolve) => {
  setTimeout(() => {
    resolve()
  },msec)
```
引数にミリ秒を入れることによって、その時間だけ待ってくれます。

並列、直列処理で各自で実行時間を検証します。
ここでは処理時間が1,2,3秒かかる関数を３つ用意します。

それでは並列処理から見てみましょう。
並列処理をする際は、`Promise.all` を使用します。引数は非同期関数の配列になります。
並列処理をする方法は`Promise.all`,`Promise.any`,`Promise.allSettled`の三つの方法があります。
それぞれ、返却された非同期関数の値によって実行結果が変わりますがここでは説明を割愛させていただきます。
実務では`Promise.all`を使用することが多いです。


### 並列処理
非同期関数を実行する際は`即時実行関数`でラップして動かします。
```typescript
(async () => {
  const start = performance.now();
  await Promise.all([sleep(1000), sleep(2000), sleep(3000)])
  const end = performance.now();
  console.log(`process all executed executed time ${end - start} mili second`)
})();
```
実行した際に実行時間を計測してみます。

![スクリーンショット 2023-11-05 15.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410008/69b07b0a-9c3f-e446-b94d-5ec2abaecc2c.png)

実行時間は3秒ほどでした。
並列処理だと`Promise.all`の引数の関数が一斉に動作します。
そのため、実行時間は一番時間のかかる`sleep(3000)`の3秒になります。

### 直列処理
並列処理と同様、非同期関数を実行する際は`即時実行関数`でラップして動かします。
また直列処理は、`for文`を使用して行うことができます。

```typescript
(async () => {
  const start = performance.now();
  for (const sec of [1000,2000,3000]) {
    await sleep(sec)
  }
  const end = performance.now();
  console.log(`process all executed executed time ${end - start} mili second`)
})();
```

実行した際に実行時間を計測してみます。

![スクリーンショット 2023-11-05 16.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410008/a767fa58-a6e1-bf8d-bf38-344f216d6cb0.png)

実行時間は6秒ほどでした。
直列処理は次の関数の処理が行われないと、後続の処理が走らないようになっています。
そのため1回目の関数で1秒、2回目の関数で2秒、3回目の関数で3秒で合計6秒かかったことになります。

徒競走で例えると並列処理がヨーイドン！っで一斉スタート、直列処理がリーレー競争みたいなイメージです。参考までに。
周りと差をつける「おしゃれ」「業務効率化」のためのChromeの拡張機能

# ある日のこと
太陽光がいっぱい差し込んでくるカフェでPCを開いて、スマートに足を組んで軽快な音を立てながらMacBookのキーボードを叩く外人さん。
ひと段落したというようにEnterを押して、傍にあったホットコーヒーを飲んでまたキーボードを叩き出す。
(私)...いや、かっこよ。

↓本題↓

# 初めに
エンジニアの皆さん、日々の激務お疲れ様です。
冒頭、早起きした休日に日比谷で目の当たりにした光景ですが、あれずるいですよね。

平日の自分を思い出してみたら、眠い目をこすりながらPCを開いて、タスクの確認をした後に迷うことなく見慣れたChromを開いて淡々と作業をこなす自分がいました。

注：つまんないっていってるわけでは全くない。

でも、冒頭の外人さんには及ばないけど、そのいつもの景色(画面)をちょっとでもおしゃれに飾ることができたら、モチベーションが上がるってもんだと思いませんか？？

そんな同胞の皆さんのために、毎日の仕事を楽しくするChromの拡張機能をまとめてみました！
その時の気分に合わせて、使い分けてみるのはどうでしょうか？

# PCスペック

PC：MacBook Air
チップ：M1
メモリ：16GB

# 目次
**【綺麗な画像でホーム画面を鮮やかに！】**

* Momentum
* Tabliss
* Embark

**【シンプルでかっこいい！業務効率化ホーム画面！】**

* Committed
* Workspace Launcher
* Tab Notes

# 【綺麗な画像でホーム画面を鮮やかに！】

## Momentum

<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/5831a52a-ff32-d5af-c880-ae885d290839.png" alt="スクリーンショット 2023-11-03 19.30.27.png">

### 機能
* ブックマーク(画面左上)
* 検索(画面左上)
* 天気(画面右上)
* 時間(画面中央)
* Momentumからの一言※名前の変更可能(画面中央)
* TODOの作成(画面中央下)
* TODOリスト(画面右下)

## Tabliss

<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/8056e957-a58c-d171-85bb-510a316ffc13.png" alt="スクリーンショット 2023-11-03 19.29.01.png">

### 機能

* 設定(画面左上)
* 全画面表示切り替え(画面左上)
* 画像以外表示切り替え(画面左上)
* 背景画像※更新タイミング設定可能(画面中央)


## Embark
<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/f07aa9fe-1f3b-2050-69b6-23ca6b95053b.png" alt="スクリーンショット 2023-11-05 15.19.46.png">

### 機能
* 背景画像※12/24時間単位で切り替え可能
    * 公式の「拡張機能のオプション」から設定可能


# 【シンプルでかっこいい！業務効率化ホーム画面！】

## Committed
<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/f3ce1ff2-ba04-8026-ef61-5db3af060517.png" alt="スクリーンショット 2023-11-05 15.05.25.png">

### 機能
* 時刻表示※表示内容設定可能(画面中央上)
* 設定(画面左上)
* TODOの作成/表示(画面中央)

## Workspace Launcher

<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/df21119b-a151-94a4-ca70-9d2118adea9d.png" alt="スクリーンショット 2023-11-05 15.27.14.png">

### 機能
* ワークスペースの登録/編集(画面中央上)

## Tab Notes

<img width=700 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/122a24e1-bd4c-afcd-ec01-cc254802bc8e.png" alt="スクリーンショット 2023-11-05 15.38.47.png">

### 機能
* メモ機能

# 終わりに

拡張機能の中でも有料プランが用意されているものもあるので、ちょっとした気分転換に使ってみようと思っている方は注意しながら使ってみてください！

以上、最後まで読んでいただき、ありがとうございました！
Composeサイズの違うテキストの下部を揃える方法

Composeでサイズの違うテキストの下部を揃える方法です。
ポイントアプリなので、数字のポイントと単位でサイズが違うけど位置が揃っているデザインなどがあったりします。
その時に便利な方法です。


![スクリーンショット 2023-11-05 16.18.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/b77329d2-3a72-af50-466a-0a4318f053b4.png)


```TextSample.kt
@Composable
fun TextSample() {
    Row {
        Text(
            text = "1000",
            modifier = Modifier.alignByBaseline(),
            maxLines = 1,
            fontSize = 25.sp
        )
        Text(
            text = "P",
            modifier = Modifier.alignByBaseline(),
            maxLines = 1,
            fontSize = 10.sp
        )
    }
}

```

`alignByBaseline()`を設定するといい感じに揃えてくれます。
STI（Single Table Inheritance）を使用するメリットは？

# はじめに
皆さん、お疲れ様です。
今回、Railsの学習中に **STI（Single Table Inheritance、シングルテーブル継承）** について引っかかる部分がありましたので、備忘録として技術記事を作成しました。
もし同じく学習中の方でSTIの理解度について不安がある方への参考資料になればと思います...！

:::note warn
**説明**
この記事はプログラミング初学者なりに纏めた記事になっておりますので、内容等に誤り等がある場合がございますのでご了承下さい。
もし誤りに気づかれた際は、コメント等でご教授いただけると助かります🙇‍♂️
:::

# STIとは？
そもそも、STIとは何なのか？
その説明からしていきたいと思います。

STI（「Single Table Inheritance」または「シングルテーブル継承」）とは、オブジェクト指向プログラミングの継承の概念をデータベースのテーブルに適用したものです。
RailsでのSTIを使うと、複数の関連するクラスを単一のデータベーステーブルで扱うことが出来ます。

つまり、スーパークラス（親クラス）とそのサブクラス（子クラス）がデータを同じテーブルに保存し、区別するために一つのカラム（通常は```type```カラム）を使用する、という流れになります。

### STIの例
例えば、交通手段を扱うアプリケーションを作っているとしましょう。
その中で、多くの共通の属性（color・brand・modele...etc）を持つ「Car」「Truck」「Motorcycle」といったクラスがあるとします。
これらのクラスは、「Vehicle」クラスから継承されているとします。

STIを用いる事で、「これらすべてのクラスに対して単一の```vehicles```テーブルを使うことが出来る！」と言う事になります。

# 今回の疑問点
今回、既に用意されている《Ruby on Rails》を用いた記事投稿アプリ、その中の管理者専用の記事一覧画面に実装されている、セレクトボックスを用いた検索機能についてコードを読み解いていました。

ちなみに、検索機能については下記の通り実装されています。
- 記事の「カテゴリ」についての検索
- 記事の「著者」についての検索
- 記事の「タグ」
```ruby:views/admin/articles/index.html.erb
<%= form_with model: @search_articles_form, scope: :q, url: admin_articles_path, method: :get, html: { class: 'form-inline' } do |f| %>
  <%= f.select :category_id, Category.pluck(:name, :id), { include_blank: true }, { class: 'form-control' } %>
  <%= f.select :author_id, Author.pluck(:name, :id), { include_blank: true }, { class: 'form-control' } %>
  <%= f.select :tag_id, Tag.pluck(:name, :id), { include_blank: true }, { class: 'form-control' } %>
<% end %>
```

上記コードの《```Category.pluck(:name, :id)```》《```Author.pluck(:name, :id)```》《```Tag.pluck(:name, :id)```》部分は、```plunk```メソッドを用いて、( )内に指定したカラムの値をモデルから配列として取得する内容となっています。

ただし、今回のアプリケーションは```categories```テーブル・```authores```テーブル・```tags```テーブルは存在しません。
その為、```taxonomies```テーブルの```type```カラムに各レコードが表すサブクラスの名前「Category」「Author」「Tag」を保存しており、STIを用いる事で```type```カラムのそれぞれのレコードから値を取得出来るように実装しています。

実は、このコードを紐解いて調べている際、一つ疑問に感じた部分があります...。
それは...

***なんで各モデルに対するテーブルを作成せず、単一のデータベーステーブルで扱うようにしているのだろう...***

正直なところ、「各モデルのテーブルを作成して、それらでデータを管理する方が分かりやすくないか？」と疑問に感じてしまいました...笑

# STIを使用しているメリット
ここからは、STIを使用するメリットについてお話ししていきたいと思います。
まず、STIを使用するメリットとしては以下の通りだと考えています。

## 1. データベースの単純化
STIを使うと、複数の関連するクラスのデータを1つのテーブルで管理することが出来るようになる。
これは、データベースの設計をシンプルにし、同時にテーブル間の関連を管理する複雑さを減らす事に繋がる。

例えば、「Car」「Truck」「Motorcycle」がある場合、これらを個別のテーブルとして管理するのではなく、一つの```vehicles```テーブルで管理する事でテーブルの数が減り、データベースを管理しやすくなる。

## 2. クエリの単純化
関連する複数のタイプのオブジェクトを一つのテーブルに保持することで、データへのクエリが単純化する。

先ほどの例で説明すると...
特定の属性に基づいて全ての車両タイプを検索するとき、単一のテーブルを対象とするだけで良いので、JOIN操作などが不要になる。これにより、クエリの書き方が簡単になり、データを高速に取得する事が出来るようになる。

# まとめ
通常、各クラスごとにテーブルを作る事になると、同じような構造のテーブルが複数できてしまって、メンテナンスや管理が大変になってしまいます...💦

そんな時にSTI（Single Table Inheritance）を使用して、複数の関連するモデルを単一のデータベーステーブルで管理出来るようにする事で、**データの整合性を保ちつつ、コードのメンテナンスを効率的に行うことが出来る**ようになります...！
また、共通の属性やメソッドは親クラスに一度書くだけでOKなので、**コードの重複が減り、よりDRY（Don't Repeat Yourself）な設計が可能**になります。

慣れないうちはテーブルが存在しない事に困惑してしまうかもしれませんが、コードリーディングに慣れると仕組みとしてはそこまで複雑なものでは無いですね！
docker-compose up時にwebpack-dev-serverが起動されるようにする

## はじめに
railsのフロントエンドにwebpackerを使っていると`webpack-dev-server`を使った方がコンパイルに使う時間を短縮できます。
環境構築にdockerを使っていると仮定して`dockre-compsoe up`時に`webpack-dev-server`も起動されるように設定ファイルを編集します。

## 環境
`rails 6.1.6`
`ruby 3.0.6`
`webpacker 5.4.3`

## docker-compose.yml
railsが動いているコンテナの`command`で下記のように指定します。
```yml
command: bash -c "rm -f tmp/pids/server.pid && ./bin/webpack-dev-server & bundle exec rails s -b '0.0.0.0'"
```
Embulk v0.11.1 をdockerを使って実行する

## 実現すること
- embulkを実行するdockerイメージを作成する
- ローカル環境の設定ファイルをマウントして、dockerイメージを実行する

## 前提条件
- Mysqlはローカル環境に存在しているMysqlを使用する
- Embulkバージョン：0.11.1
- プラグインの読み込みはrubygemsを使用する

## embulk.properties を作成する
以下の内容が記述されたファイルを作成する。
```
jruby=file:///usr/src/app/jruby-complete-9.4.5.0.jar
```

## Dockerfile を作成する

```Dockerfile
# EmBulkの実行にはJavaが必要なため、Javaが含まれているベースイメージを使用します
FROM openjdk:8-jre-slim

# 作業ディレクトリを設定します
WORKDIR /usr/src/app

# install curl
RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*

# install jruby
RUN curl --create-dirs -o "./jruby-complete-9.4.5.0.jar" -L "https://repo1.maven.org/maven2/org/jruby/jruby-complete/9.4.5.0/jruby-complete-9.4.5.0.jar"
RUN chmod +x ./jruby-complete-9.4.5.0.jar

# Embulkをダウンロードして実行可能にする
RUN curl --create-dirs -o ./embulk -L "https://dl.embulk.org/embulk-latest.jar" && \
    chmod +x ./embulk

# install Ruby gems
COPY ./embulk.properties /root/.embulk/embulk.properties
RUN ./embulk gem install embulk -v 0.11.1 # Embulk と同じバージョンを指定
RUN ./embulk gem install msgpack -v 1.7.2
# RUN ./embulk gem install bundler # if you need Bundler
# RUN ./embulk gem install liquid  # if you need Liquid

# Embulkのプラグインをインストール
# 以下の例ではMySQLのプラグインをインストールしています
RUN ./embulk gem install embulk-input-mysql && \
    ./embulk gem install embulk-output-mysql

# Embulkの実行コマンドを設定します
ENTRYPOINT ["java","-jar","./embulk","run","./config/config.yml"]
```

## Dockerfile からイメージを構築する
```bash
docker build ./ -t embulk-mysql-to-mysql --progress plain --no-cache 
```

## config.yml の作成
```yaml
in:
  type: mysql
  host: host.docker.internal
  user: root
  password: password
  database: dbname
  table: product
  select: "id, name, email"
out:
  type: mysql
  host: host.docker.internal
  user: root
  password: password
  database: dbname
  table: product2
  mode: insert
```

## コンテナを実行する
```yaml
docker run -v /usr/local/embulk/config:/usr/src/app/config embulk-mysql-to-mysql
```

## 参考にしたサイト
https://zenn.dev/dmikurube/articles/what-changes-in-embulk-v0-11
https://joker1007.hatenablog.com/entry/2021/05/28/021140
ブラウザバックって何が良くないの?

はじめまして。関西でQAエンジニアをしているRyoTaniともうします。

今回は、テストケースや観点でみかける「ブラウザバック」について、制限される理由を整理してみました。
業務で仕様をレビューされる際や、テストでやる/やらないを考える際にご活用いただけると幸いです。


# ブラウザバックとは
ブラウザバックとは、ブラウザの戻るボタンを押して前のページに遷移する操作のことです。

サイトによっては、ブラウザバックすると強制ログアウトするなど、などがあります。
セキュリティのために必要なこととは理解してますが、個人的にはめんどくさいのであまりやってほしくないとおもっています。

# なぜ良くないと言われるのか
まとまった記事を見つけられなかったのですが、「個人情報の漏えい」「データ不整合」が大きな理由のようです。
他、「動作の不安定」「UXの低下」が懸念される場合があるようです。

# 原因
## 個人情報漏えい
ブラウザのキャッシュとして残っている申し込み画面などで入力された情報が問題になります。

セキュアなページでは不正アクセスがないようブロックされていますが、ブラウザバックしてセキュアではないページに遷移してしまうと、CSRF攻撃やXSS攻撃で盗まれるリスクが発生します。
[「キャッシュに残る個人情報」にご用心：ブラウザの「プライベートモード」を使うべき理由 | ライフハッカー・ジャパン](https://www.lifehacker.jp/article/130628caching/)



## データ不整合
想定しないタイミングでサーバに情報が送られてしまうことが問題になるようです。

例えば、フォーム入力後、送信したあとにブラウザバックすると、フォームの入力内容が再送信されて２重登録が発生する場合があるそうです。
他には、ユーザーがページの一部を変更した後に戻ると、変更前の状態に戻ってしまう可能性があります。

## 動作の不安定
ページの状態やデータが予期しない方法で変更されることが問題になるようです。

## UXの低下
ユーザが意図しないページに遷移してしまうことで、ナビゲーション制御が外れてしまうことが問題になるそうです。
GoogleMapsAPIを使用した開発2(現在地取得)

# 1.はじめに
投稿された情報（緯度経度）からGooleMapsAPIを使用して地図を表示、地点間のルート検索機能、周辺情報の取得を実装したので知識の定着、復習のために記事を書きます。
一度に書くと長くなるので、4回にわけて投稿していきます。
今回はその2回目で現在地取得まで実装します。

# 2.環境
Ruby (2.6.4)
Rails (6.1.7)
Maps JavaScript API	

# 3.前提条件
APIキー取得済み
投稿機能を実装している
[GoogleMapsAPIを使用した開発1（地図の表示）](https://qiita.com/uuuDi_97722/items/6a064cf7e40d91a517c0)まで実装している

# 4.実装

## 1.viewの修正
```diff_ruby
      <div class="map">
        <div id="map_index"></div>
+       <div><button id="current-location-button" class="btn btn-primary">現在地を取得する</button></div> # 追記
      </div>
```

## 2.現在地を取得しマーカーを追加、ボタンにクリックイベントを追加
```javascript
  const currentLocationButton = document.getElementById('current-location-button'); // ①
  currentLocationButton.addEventListener('click', getCurrentLocationAndAddMarker); // ②
```
①`document.getElementById('current-location-button')`でHTML内のcurrent-location-buttonというIDを持つ要素を取得しています。

②.`addEventListener('click', getCurrentLocationAndAddMarker)`で取得した要素に対して、クリックイベントが発生したときにgetCurrentLocationAndAddMarker関数を呼び出すようにイベントリスナーを追加しています。

- これにより、ユーザーがボタンをクリックすると、getCurrentLocationAndAddMarker関数が実行されます。
- getCurrentLocationAndAddMarker関数については次で説明していきます。

## 3.現在地を取得しマーカーを追加する関数を作成(getCurrentLocationAndAddMarker関数)
```javascript
  // 変数宣言
  let currentLocationMarker; // 現在地のマーカー

  function getCurrentLocationAndAddMarker() {
    if (navigator.geolocation) { // ①
      navigator.geolocation.getCurrentPosition(function (position) { // ②
        const currentLatLng = { // ③
          lat: position.coords.latitude,
          lng: position.coords.longitude
        };

        if (currentLocationMarker) { // ④
          currentLocationMarker.setMap(null);
        }
        currentLocationMarker = new google.maps.Marker({ // ⑤
          position: currentLatLng,
          map: map,
          title: "現在地"
        });

        currentLocationMarker.addListener('click', function () { // ⑥
          infoWindow.setContent(
            `<strong> 現在地 </strong>`
          );
          infoWindow.open(map, currentLocationMarker);
        });

        map.setCenter(currentLatLng); // ⑦

      });
    } else { // ⑧
      alert("このブラウザでは位置情報が利用できません");
    }
  }
```
①`if (navigator.geolocation) { `でブラウザが位置情報をサポートしているかを確認しています。
- サポートされている場合は、位置情報の取得を試みます。

②`navigator.geolocation.getCurrentPosition(function (position) {`でユーザーの現在の位置情報を非同期で取得します。
- 成功時には、コールバック関数が実行され、取得された位置情報が position パラメータとして渡されます。

③では、positionオブジェクトから緯度と経度を取り出し、currentLatLng オブジェクトに格納します。

④は、既に地図上に表示されているマーカーがあれば削除するコードです。

⑤取得した位置に新しいマーカーを作成し、地図上に表示します。

⑥マーカーがクリックされた時の動作を追加します。マーカーをクリックすると、現在地と表示されたInfoWindowが開きます。
- openメソッドの最初の引数`map`は、InfoWindowを表示する地図オブジェクトです。
- 2番目の引数`currentLocationMarker`は、InfoWindowをどのマーカーに関連付けて表示するかを指定します。
- 今回の場合、`currentLocationMarker`は現在地を示すマーカーです。

⑦`map.setCenter(currentLatLng);`で地図の中心を現在地に設定します。

⑧は、ブラウザが位置情報をサポートしていない場合には、アラートで通知するコードです。

# 5.おわりに
ここまでで、現在地取得機能を実装できました。
間違いがあればご連絡いただけると助かります。
Gitの使い方をまとめる

はじめまして。
入社約半年が経過したむーこ(@mu-ko) と申します。
文系未経験からこの業界に入りました。

研修が明けて正式にお仕事を始めたのですが、Gitの使い方を先輩に何度も指摘されてきました。
改めてGitの使い方についてまとめたので、整理のために投稿したいと思います。

自分がまず分かるかどうかを前提に記事を書きましたので、分かりにくいところがあるかもしれません。
下記に参考にさせていただいたサイトもあるので、並行してご覧いただければ幸いです。
自分でも「こう書けばもっと分かりやすくなるかも！」と思ったら積極的に編集していこうと思います。
また、違うこと、語弊がありそうな箇所があればご指摘ください。

**■リベース**
リベース：ブランチの根元を新しい```Develop```に更新すること。

**■マージ**
マージ：ブランチ内での実装が終わった時に、```Develop```にブランチを合流させること。

**■ブランチの削除**
ブランチの削除：作成したブランチをもう使わない時に、ツリーを綺麗に見せるためにブランチを削除すること。
ブランチを削除してもコミットは残るため、歴史が変わることはありません。

**■スカッシュ**
スカッシュ：いくつかあるコミットを一つのコミットにまとめること。
注意点:sourcetreeを使用する場合、パスに日本語が含まれていると、
「~の子とインタラクティブなリベースを行う」を押してもステージ上に何も表示されません。
そのため、パスに日本語が含まれている場合はパスを変更するか、
TortoiseGitを使い分けてスカッシュを行ってください。

参考サイト
・SourceTreeでスカッシュができない
[Sourcetreeで「～の子とインタラクティブなリベースを行う」ができない (teratail.com)](https://teratail.com/questions/177475)
・SourceTreeのスカッシュ方法について
[すぐ忘れる！SourceTreeを使ったリベースとスカッシュの手順](https://qiita.com/ryounagaoka/items/7c129e98a7f81c507a61)
ゾーニングとマスキングについて

## 前置き

前回FCSWの構築についてQiitaで投稿をしたので今回は上記について書いていきたいと思います。
インフラでサーバの構築をやられている方は、ご存じの方が多数だと思います。
大規模環境になるとストレージの導入をしたりします。
そんなストレージを導入したときに参考にした資料を基に簡単に説明させていただきたいと思います。

![image_thumb6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573738/1d3c9eac-ec28-4c32-bbaa-7cc4c07f22ea.png)



# ゾーニングとマスキングとは？
まず、マスキングとゾーニングは外部ストレージへ関わる用語なので、セットで覚えておくと良いと思います。
パスに関しては基本的に「サーバーは繋がっている物理的な線上にあるストレージを探しに行く」動作をしていてます。
物理的に接続してあるストレージは全部見えてしまいます。それを制御するのがマスキングとゾーニングになります。

## マスキングとは？
![image_thumb7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573738/ece6504c-c533-d2a9-41aa-f652f43e71d0.png)

マスキングとは、通常外部ストレージ側で設定する項目です。
マスキングとは、「見えないように隠す」という意味です。
とあるサーバーからはストレージ上のこのLUNはアクセスさせないように隠す(マスクする)という設定がマスキングになります。


## ゾーニングとは？
![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573738/b4460051-376c-8f77-be15-b370497241f0.png)

FCSWにて通常出てくる用語です。
ゾーニングとは、アクセスできる区画を作ることです。

例えば、
上記図では、上のサーバーはストレージにアクセス出来ますが、下のサーバーはストレージにアクセス出来ません。
そんな設定が出来るのがゾーニングです。
vimでインクリメントする際に、0埋めされた数字も10進数として扱って欲しい

# 対処法

以下の設定を行うことで、0始まりの数値でも10進数扱いしてくれるようになる (デフォルトでは8進数扱い)

```.vimrc
set nrformats=
```
話し合いを有用なものにするために、ドキュメントベースで議論を行う

### 背景
- みなさん、議論してますか。コードだけ書いていたい気持ちもありますが、それだけでは足りないので、我々は必要に応じて、チーム内外の人間と議論しますよね
- 議論するときに、一対一ならともかく、複数人で会話していると、だんだん会話が複雑になっていき、話をしているメンバー以外が置いてけぼりになってしまうことがあります

Aさん「この件、どうします？　APIのスキーマ、まだ決まってませんよね」
Bさん「あ、それならこないだ話したあれがあるじゃないっすか、あの……」
Aさん「あー、購入APIのやつ？　あれを流用する感じですか？」
Bさん「そうです。レスポンスは少し変えなきゃだけど。パターンが違うときの考慮とか」
Aさん「確かにね。でもパターンの場合分けについて、PMに確認しましたっけ？　例の件」
Bさん「一応投げてはいますけど。Slackで確認中とあるんで、近々回答くれるんじゃないかな……」

周り「何の話をしてるんだ……？」


### 問題点
- 周りが議論についていけず、結局何をどうするのかわからない
- 当事者同士があたかも納得しているように見えるが、**実は当事者も雰囲気で会話していて、結局何がどう決まったのかはっきりしていない**こともある。なので後になって「以前話したあの件、結局どういう結論になったんでしたっけ？」と振り出しに戻ることがある。

### ドキュメントを中心に会話しましょう
- 口頭だけの会話に終わらず、文書をメインに議論を進めましょう
- 具体的な進め方は以下のとおりです。

1. 議論を始める前に、誰かが議事録担当を申し出る
2. 議事録担当が、Google　DocumentなりNotionなりを画面共有し、そこに内容を記載していく。画面共有することで全員がドキュメント（議事録）を意識して議論するようになる。
3. 議事録担当は、内容を理解していなくても、聞こえた内容をそのまま記載していく（理解しようと努めてしまうと、手が止まってしまうため）
4. 不明点や曖昧な点があったら、途中議論をストップさせて、そこを明確にする

### どんなメリットがあるのか？
- 議論の終了とともに議事録が完成するので、議論に参加できていない人も内容を把握できる
- リアルタイムの議論についていけなくなっても、参加者はそのドキュメントを読めば理解を追いつかせることができる
- 「自分たちの発言が文書化されている」という意識のもと議論するので、メンバーがより具体的な発言をしてくれるようになる
- 議事録を担当することで、議論の舵取りをすることができる
    - 途中、議論が暗礁に乗り上げそうになったら、「すいません、少し整理させてください」とか「◯◯さん、先ほどの発言ですけど、もう少し具体化させたいので、聞いてもいいですか？」と場をリセットできる
    - 私はよくこれをやっている。特に自分がメンバー内で最も理解が浅いときなどに役立つ。
    - 知識がないときほど議事録を買って出よう。手っ取り早く知識を吸収できる。

### より有用な議事録にするために
- 可能であれば、誰かの発言をメモするときは、発言者の名前も記載しておく
    - 後で「この発言した人だれだっけ？　もっと話を聞きたいんだけど」と思った時に確認できる
        - tanakasan)DBの考慮は必要？
        - satosan)現行を踏襲で良いはず
    - ↑みたいな感じで、漢字変換をせずにローマ字表記だと、サクッとタイプできる
- いくつかの案が出たときは、番号を振って、それぞれのメリデメを整理する
    - みんな「ああしよう、こうしよう」「それがいい、それでいこう」みたいな話し合いをしているが、実はきちんとメリデメの観点から会話できていないことが多い
    - なので方針を決めるときも、なんとなく雰囲気で決まってしまったり、発言力の大きな人の意向でふわっと決まってしまったりする
    - それを避けるために、各案のメリットとデメリットを整理する。「◯◯さん、先ほどこの案がいいとおっしゃいましたが、具体的にはどんなメリットとデメリットがありますか？」と聞いてみる
    - メリデメを整理した結果、採用すべき案が決まったら、採用したことを示す何らかの印を番号の隣に付けておく。⭐マークとか。


### まとめ
- ふわっとした議論にならないためにも、ドキュメントを中心に会話をしましょう
- 単に議事録を取るのではなく、それを画面共有し、議事録を見ながら議論することで、参加者たちがより具体的かつ明確な発言をしてくれるようになります
1242x2208のSimulatorを生成出来なくて困ったら

1242x2208のスクショを撮りたくて、iPhone 8 PlusなどのSimulatorを生成しようとしたが、iOS 17.0が選べない。

- Xcode
- Settings...
- Platforms
- `+`
- iOS...
- iOS 16.4 Simulator

のように選んで古いiOSを追加すると、`New Simulator`の`OSVersion`に`iOS 16.4`が追加され、Simulatorを生成出来るようになる。
google.script.runをasync/awaitで書く

<h1> 導入 </h1>

GASのWebアプリでサーバー側に処理をさせたい場合、google.script.runを使用しますが、コールバック地獄に陥りがちです。

```js
//理想
const value = google.script.run.myFunction();
console.log(value);

//現実
google.script.run.withSuccecssHandler(console.log).myFunction();
```
今回は、理想通りに書けるようにするのが目的です。

<h1>ソースコード</h1>

```js
const $ = new Proxy({},{
    get(t,p){
        return (...a) => new Promise((r1,r2) => {
            google.script.run.withSuccessHandler(r1)
                             .withFailureHandler(r2)
                             [p](...a);
        })
    }
});
```

<h1>使い方</h1>

```js
(async () => {
    const value = await $.myFunction("hogehoge");
    console.log(value);
})()
```

<h1>解説</h1>

Proxyの詳しい仕様はこちら(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy)

簡単にいえば、プロパティの読み込み時の動作をカスタマイズできるということです。
例えば、どんなプロパティを読み込んでも、特定の文字列を返すことができます。

```js
const proxy = new Proxy({},{get(t,key){return key}});
console.log(proxy.aiueo) //aiueo
console.log(proxy.admo) //admo

//Proxyによって、全ての値をプロパティ名と同一にしている
```
これを利用して、サーバ側から呼び出す関数を指定しています。Proxyを使用しないと、
```js
const $ = {

    myFunction : (...argus) => new Promise(...),
    //...

}
```
のように、すべての関数について逐一ソースコードを書き換える必要があるため、大変不便です。
Pythonの Ruff (linter) でコード整形もできるようになりました

**要約**: Flake8 + Black + isort はもうすべて Ruff だけで置き換えられる。

---

PythonのLinterとして、すでに [Ruff](https://github.com/astral-sh/ruff) を使われている方も多いと思います。Ruffは Rust で実装された高速なPython用Linterで、従来よく使われていた Flake8 に比べて数十倍短い時間で処理が終わるほか、Flake8の主要なプラグインの代替も初めから搭載されています（[Lintルール一覧](https://docs.astral.sh/ruff/rules/)）。

その成功が約束されている（？）ためか、Ruff の知名度がまだ低いころから [GitHub Actions公式のPythonチュートリアル](https://docs.github.com/ja/actions/automating-builds-and-tests/building-and-testing-python)は早々に Flake8 を Ruff に置き換えていました。

そして、2023年10月末にリリースされた v0.1.2 あたりから、ついにLintだけでなく、コードフォーマット（コード整形）の機能も正式に搭載されました。公式のブログ記事はこちら：

https://astral.sh/blog/the-ruff-formatter

Pythonのコード整形といえば今までは [Black](https://github.com/psf/black) が主流でした。その代替を目指す Ruff のフォーマット機能は Black よりも30倍以上高速で（画像は公式ブログから引用）、Black と 99.9% 以上の互換性があると謳っています。

![フォーマット速度の比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95370/c7a94da7-8bbd-3d06-60a6-bb28733f2ccb.png)


速度の面だけでなく、従来よく使われてきた Flake8, Black, isort という別々のツールがすべて Ruff ひとつだけで済むようになるのも嬉しいポイントでしょう。

- (Linter) Flake8 → **Ruff** !!!
- (Formatter) Black → **Ruff** !!!
- (import sorting) isort → **Ruff** !!!

## VS Code の設定

明示的にフォーマッタとして Ruff を使うようにするには、設定ファイルを以下のように書き換えればOKです。[Ruff の拡張機能](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)を入れておくことをお忘れなく。

```javascript
  "[python]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnType": true,
    // ...
  }
```

Flake8やisort用の拡張機能は、もし入っていたら、できれば削除してしまいましょう。

また、他のエディタをお使いの方には [ruff-lsp](https://github.com/astral-sh/ruff-lsp) があります。

## コマンドラインで実行

新たに、コードフォーマットのための `format` コマンドが増えました。

```bash
# formatter を実行
ruff format .
# linter を実行
ruff check . --fix
```

## (おまけ) GitHub Actions の設定

これは linter の話ではありますが、 `ruff check` に `--output-format=github` を付けると、LintエラーをGitHubのインラインアノテーションにしてくれます。

```yaml
- name: Run Ruff (lint)
  run: ruff check --output-format=github .
- name: Run Ruff (format)
  run: ruff format . --check --diff
```

## pyproject.toml

フォーマット機能に関しては、特に設定なしでBlackと同じ挙動を目指そうとしてくれます。

なお過去のRuffの `pyproject.toml` での設定は現状そのままでも動作しますが、今後は lint の設定と format の設定を分けて記述するようになっています。詳細は公式ドキュメント (https://docs.astral.sh/ruff/configuration/) を参照してください。

```toml
[tool.ruff]
# ...

[tool.ruff.lint]
# ...

[tool.ruff.format]
# ...

[tool.ruff.lint.isort]
# ...
```
クロスアカウントでEC2からS3バケットへPUTする方法

## 概要
アカウントAのEC2からアカウントBにあるS3バケットへオブジェクトをputする方法について調べたので記載します。

## 方法
①アカウントBでIAMロールを作成

ポリシーにS3バケットへのフルアクセスを付与
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/6ccd31cd-4395-28aa-ccfe-10b12b68829e.png)

信頼関係のプリンシパルにアカウントAのIDを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/f2931a32-7b67-c966-07ce-2791ba11aafb.png)

②アカウントAでIAMロールを作成

ポリシーのResourceにアカウントBで作成したIAMロールのARNを記載
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/db222d3e-de46-d2d0-e47b-400172700ecc.png)

信頼関係にEC2を許可
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/5e43437e-9339-0f27-af69-b861a21dcde3.png)

③EC2インスタンスからCLI設定ファイルにロールのプロファイルを作成
ec2に接続後、.aws/configファイルを開き下記を記載
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733779/333c6ea3-758a-9930-1550-357088897dc6.png)

## 確認
sample.txtというテキストファイルを作成し対象のS3バケットへコピーできるか確認する
>aws s3 cp sample.txt s3://DOC-EXAMPLE-BUCKET --profile profilename''


## 参考記事
https://repost.aws/ja/knowledge-center/s3-instance-access-bucket
https://qiita.com/KJ_/items/46025db761dcfa212957
lambda式の記述方法

## lambda式の記述方法を教えて下さい。
ChatGPT
もちろん、大丈夫です。
lambdaはPythonの便利な機能の一つで、
**簡単な無名関数（名前を持たない関数）を作成するため**に使用されます。

### 基本的な形式
```python
lambda <arguments>: expression
```
## 例1: 引数を一つ取るlambda関数
```python
f = lambda x: x + 10
print(f(5))  # 出力: 15
```
## 例2: 複数の引数を取るlambda関数
```python
g = lambda x, y: x * y
print(g(2, 3))  # 出力: 6
```
## Tkinterとlambdaを組み合わせる
Tkinterで**ボタンのコマンドなどに引数を渡す際に**、  
**lambdaを使うことがよくあります**。
```python
import tkinter as tk

def show_message(msg):
    print(msg)

root = tk.Tk()
button = tk.Button(root, text="Click Me", command=lambda: show_message("Button was clicked!"))
button.pack()

root.mainloop()
```
この例では、
**show_message関数をcommandに直接指定する代わり**に、
**lambdaを使用して引数msgを関数に渡しています**。

注意点として、**lambdaは簡単な関数を定義する場面でのみ使用するのがベスト**です。
**複雑なロジックや複数の行が必要な場合は、通常の関数定義を使用する方が良い**でしょう。

以上が**lambdaの基本的な使い方**となります。  
何か質問があれば、お気軽にどうぞ！

#### tkウィジェットに対して使う場合だけ、『lambda: method(args)』のパターンでOKなんですね？
ChatGPT
はい、正確にはその通りです。
Tkinterのウィジェット、
特に**Buttonのcommand属性など**、  
**コールバック関数に引数を渡したい場合**によく使われます。

**Buttonのcommand属性**は、
 1. **関数を受け取り**、
 2. **ボタンがクリックされたときにその関数を実行**します。

しかし、**直接引数を持つ関数をcommandに割り当てると**、  
**ウィジェットが作成されるときにその関数が即座に実行**されてしまいます。

このような状況を避けるために、
**lambdaを使用して無名関数を作成し、**  
**この無名関数内で**  
**実際のコールバック関数を引数とともに呼び出します**。
例：
```python
btn = tk.Button(root, text="Click me", command=lambda: some_function(some_argument))
```
上記のように、**lambdaを使用すること**で、
**ボタンがクリックされたときにのみ**  
**some_functionが引数some_argumentとともに呼び出される**ようになります。

簡単に言うと、  
**Tkinterのコールバックで引数を使用する場合**、  
**lambdaを使うのが一般的な方法**です。
erbで＝つけ忘れて2時間悩んだから俺は今後絶対に=を忘れない。

# はじめに
業務でビューを書いてるときに文字列が出力されず2時間悩んだ結果`<%`と書いており`=`が抜けていたのが原因だった。
悔しい。
二度と忘れないためにerbの主なタグを以下にまとめた。
怒りに任せて`<%` `<%=`以外のタグもまとめた。

## 1. `<%=`: 出力付きのERBタグ

`<%=` タグは、Rubyコードを実行し、その結果をHTMLに出力します。
### 例:

```erb
<%= "Hello, Rails!" %>
上記のコードは、以下のように出力されます:
```

```html
Hello, Rails!
```
## 2. <%: 出力なしのERBタグ
<% タグはRubyコードを実行するだけで、結果をHTMLに出力しません。主に制御構文 (if, loopなど) で使用されます。
### 例:
```erb
<% name = "Rails" %>
<%= "Hello, #{name}!" %>

Hello, Rails!
```

### 例:
```erb
<% if logged_in? %>
  <p><%= "Hello, #{current_user.name}!" %></p>
<% else %>
  <p>Welcome, Guest!</p>
<% end %>
```

## 3. コメント: `<%#`

ERB内でのコメントは `<%#` を使用します。このタグ内のコードやテキストは実行されず、出力もされません。

### 例:

```erb
<%#= "This will not be shown or executed" %>
```

## 4. HTMLをエスケープしない出力: `<%= raw ... %>` または `<%= ... .html_safe %>`
デフォルトでは <%= はHTMLをエスケープしますが、エスケープせずに出力したい場合には raw メソッドか .html_safe メソッドを使用します。

### 例:
```erb
<%= raw "<strong>Bold Text</strong>" %>
<%= "<strong>Bold Text</strong>".html_safe %>
```
```html
<strong>Bold Text</strong>
```

## 5. 配列やハッシュのループ: `<% ... .each do |variable| %>`

配列やハッシュの各要素をループして処理する場合には `.each` メソッドとともにこのタグを使用します。

### 例:

```erb
<% @users.each do |user| %>
  <p><%= user.name %></p>
<% end %>
```
## 6. 条件文: `<% if ... %>`, `<% elsif ... %>`, `<% else %>`
条件に基づいて特定の部分を表示する場合には、条件分岐を行います。

例:
```erb
<% if @user.admin? %>
  <p>Welcome, admin!</p>
<% else %>
  <p>Welcome, user!</p>
<% end %>
```
## 7. ケース文: `<% case ... %>`
複数の条件に基づいて処理を分岐させる場合には、ケース文を使用します。

例:
```erb
<% case @user.role %>
<% when "admin" %>
  <p>Admin rights</p>
<% when "user" %>
  <p>User rights</p>
<% else %>
  <p>No rights</p>
<% end %>
```

## 8. 安全な結合: `<%= [var1, var2].join.html_safe %>`
文字列の結合を行い、その結果をHTMLとして扱う場合には、.join メソッドと .html_safe メソッドを組み合わせて使用します。

例:
```erb
<%= ["<strong>", @user.name, "</strong>"].join.html_safe %>
```
超初心者が忘れっぽい自分のためのLINE Botを作ってみた

# LINE Botって自分でも作れる！
企業アカウントでよくあるチャットボット。
皆さんも1つや2つ使っていると思います。
私自身も使っていますが、これは企業のためのもの、会社とか事業者じゃないと作れないものだと思っていました。

それが…なんと…**個人でも！ましてはITスキル激低の私みたいな超初心者でも作れると！！！**

# さっそく作ってみる！
さぁ、さっそく作ってみよう！
作るなら自分が便利に使えるものがいいなー
そうだ、いっつも宅配ボックスの暗証番号忘れちゃうから教えてくれるBotにしよう！
毎回画像フォルダに保存してあるスクショを探すのめんどくさいんだよね…
あー、あと自宅の郵便番号も忘れるし、ポストの開け方も忘れるし、西暦⇔和暦の変換も…
って私どんだけ忘れっぽい（覚えられない）んだー:joy:
![7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/6c657e7e-bad4-d234-2888-03be3ddf5d5c.jpeg)

# 作成に必要なもの！
- [LINE](https://developers.line.biz/ja/)
- [Make](https://www.make.com/)
- Googleスプレッドシート

なんとたったこれだけ！
これだけでLINE Botができるとか凄すぎ:open_mouth:

# できたのがコチラ！
https://x.com/NRie363584/status/1723167597062189104?s=20

ちゃんと動いてる！感動ー:laughing:

# 作成手順！
### Googleスプレッドシートの作成
下記のように返答してもらいたい内容を記入したシートを作成しました。
(内容はダミーです)
![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/262c09c3-bbb6-dd9e-a7f8-2ed9c8d0b862.jpeg)

### GoogleSheetsとLINE Botの連携
下記の動画をがっつり参考にさせていただきました。
[プログラミング未経験者歓迎! Makeで作るノーコードLINE Bot入門](https://www.youtube.com/live/LjN0VW1bg5w?si=AecGdi2KZorhd4Ws)
教え方が丁寧で最高です:blush:

簡単に書きますと
LINE Divelopersに登録しLINE公式アカウントを作成、LINE Official Account ManagerでBotにするための設定をした後、Make のシナリオを作る。
ただこれだけ！
ちなみに今回のシナリオはこんな感じ。
![プロトアウト2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/e5276c61-f26e-d023-cf2f-2bab38029e17.jpeg)
わぁ、とってもシンプルー:smile:

LINEに打ち込んだ文字をGoogleスプレッドシート内のキーワード列で検索し、あったら返却の内容を返す、なかったら既定の文章を返すように設定してあります！
キーワードは全部打たなくても、一部分が合致すれば返してくれるから楽チンだー:relieved:
- キーワードがあったら返却の内容を返す設定
![プロトアウト3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/fe366236-d66c-292c-575b-174ab924c7de.jpeg)
- キーワードがなかったり、送られてきたのがテキストでない場合に既定の文章を返す設定
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/bbf6ab51-a135-549c-ab43-99c227364d19.jpeg)

### リッチメニューの設定
少しでも楽するために（文字の打ち込みを減らすため）、リッチメニューを設定しました。
今回は①宅配ボックスの暗証番号、②自宅の郵便番号、②ポストの開け方の３種類。
LINE Official Account Managerでテンプレートと画像を設定し、アクションを選ぶだけ！
![9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/ae44e9ab-616e-9e51-df50-7e1c27b15623.jpeg)
今回はそれぞれのテキストが打ち込まれるアクションにしましたが、リンクなどを設定することも可能です。
便利～:heart_eyes:

# ちょっと挑戦！
LINEに打ち込んだ文字がGoogleスプレッドシート内のキーワード列になかった場合、そのまま登録してくれると便利だなと思いますが、果たしてそんなことができるのか！？
ちょっと挑戦してみました！

![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/8e5fcb8d-97e7-867a-25ae-76d019b95f9a.jpeg)
もう１つ分岐を増やしてみました！

それぞれのモジュールの設定は下記のとおりです。
![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583099/cb39ad68-b0e3-f5f6-2b27-f040c39610b9.jpeg)

これでLINEに打った文字がキーワード列になかった場合Googleスプレッドシートに登録されるようになったわけですが、問題点が１つ…
**キーワードにも返却にも同じ内容が登録されちゃう！**
色々試行錯誤したのですが、現段階で列ごとに登録する方法がわからず…
まぁ同じ内容が登録されても一部分が合致していれば返してくれるし、今のところ問題なし:wink:（ポジティブ！）
これは今後の課題にしたいと思います！

# 最後に！
宅配ボックスの暗証番号を忘れて画像フォルダのスクショを探す…
もう何十回やったことでしょう…
これからはこのLINE Botに聞いたらすぐ教えてくれる！最高！

正直Botというものがこんなに簡単にできるとは思ってなかった！
IT凄すぎ…（感想が拙すぎる:joy:）
もちろん今回作成したBotは超超超シンプルで、もっともっと奥が深いものだとは思いますが、ITに疎い自分でもできるんだと感動しました！

このLINE BotはGoogleスプレッドシートの更新を忘れず（ここ大切！）、使い続けたいなーと思います:laughing:
aws cloud practitioner資格取得勉強時にお世話になった教材纏め

## *はじめに
<br />
AWS Skill Builderだけで勉強するも良いと思います。<br />
AWS Cloud Questを活用すると楽しい。<br />


https://aws.amazon.com/jp/training/digital/aws-cloud-quest/

:::note info
2023年10月2日より日本語化対応がされました。
:::

<br />

## *おすすめ書籍

<br />

AWS認定資格 クラウドプラクティショナーの教科書: 合格へ導く虎の巻 CloudTech制作委員会シリーズ 

https://amzn.asia/d/7R3XdPO

![81LOcZqrQxL._SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738983/f35bbc2f-21e0-4e0c-acad-a9c27e47bece.jpeg)

<br />

AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー　改訂第2版 

https://amzn.asia/d/674u9fS

![81ioyZPkXfL._SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738983/f275e566-45ec-5801-6729-17166ee55851.jpeg)

-----
:::note warn
Kindle Unlimited登録者向け
:::


フラッシュカード AWS Certified Cloud Practitioner 認定 (MAISON DIGITAL BOOKS) 

https://amzn.asia/d/7HY4LL4


![71IaHLCG83L._SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738983/4c3da3a0-7971-0b7b-1fb0-eb9bbb233813.jpeg)

<br />

## *おすすめUdemy講座

<br />

https://www.udemy.com/share/108I1U3@GaEqdo2mrsYEsYFwU9HHUW_3AMxJZsqeXkGHXtAV17Z_TWRw2PBHazGw4w2uzlTsFQ==/

https://www.udemy.com/share/101I2O3@AUJH0ZIoppcSGN6yalUz4upfgSld701ArzeiZAEDcMUxse5FKAZCmCmN9HrHYT5cEQ==/

https://www.udemy.com/share/103mIg3@t0X6gfMXykMN5zH_A8LJttDOiSdMuF_eePvG70iDNENpuZJ24DPJIaa7-fwh1Bx3Nw==/

## *終わりに
公式の教材（AWS Skill Builder）が優秀なため、教材購入は趣味の域かなと思います。
私は管理ページにズラーって教材が並んでいるのを見ると嬉しくなると言う性癖持ちなので、色々買いました。
教材ご購入を検討されている方のお役に立てると嬉しいです。
Material Tailwindインストールメモ

# はじめに
Material Tailwindを最近使用しているのですが、インストール時にTailwind CSSの公式サイトを見てインストール後、Material Tailwindの公式サイトを見てインストールという手順を踏んでいます。
IDEはVSCodeを想定しています。

インストールのたびに各公式サイトを訪れるのは手間なので、自分用に手順をまとめておきます。
手順は公式サイトを確認すれば全て記載されているものです。

# Tailwind CSSインストール
下記コマンドでインストール
```shell
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

インストール後、生成されたtailwind.config.jsを編集
```diff_javascript:tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
+ content: [
+   "./index.html",
+   "./src/**/*.{js,ts,jsx,tsx}",
+ ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

index.cssに下記を追加
```css:index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

VSCodeで`@tailwind`の箇所で警告がでてしまうので、設定を行い解消します。
下記拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss

その後、下記記述をsetting.jsonやdevcontainer.jsonに追加します。
```json
"files.associations": {
   "*.css": "tailwindcss"
}
```
setting.jsonは上記をそのまま追加すれば大丈夫です。
devcontainer.jsonは下記のように追加します。

```diff_json:devcontainer.json
{
  "service": "nota-de-misterio-frontend",
  "dockerComposeFile": "../docker-compose.yml",
  "workspaceFolder": "/workdir",
  "customizations": {
    "vscode": {
      "settings": {
        "files.associations": {
          "*.css": "tailwindcss"
        }
      }
    }
  }
}

```


# Material Tailwindインストール
下記コマンドでインストール
```shell
npm install @material-tailwind/react
```

tailwind.config.jsを下記のように修正
```diff_javascript:tailwind.config.js
/** @type {import('tailwindcss').Config} */
+ const withMT = require('@material-tailwind/react/utils/withMT');

+ export default withMT({
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
+ });
```

以上で完了になります。

# 参考
- [Tailwind CSS公式](https://tailwindcss.com/)
- [Material Tailwind公式](https://www.material-tailwind.com/)
- [【IT】Tailwind CSSのVSCodeでのエラーについて](https://note.com/t_ak66/n/nc96698cc758e)
Excel今日のトリビア　エクセルのセルからハイパーリンクを削除すると、文字数以上のバイト数が減少する

# 環境
Excel 365 Windos 11 pro

# 実験方法
 1. エクセルにURLを入れる
 2. どうかするとハイパーリンクになる
 3. 保存してファイルサイズを確認する
 4. 右クリックでハイパーリンクの削除
 5. 上書き保存
 6. ファイルサイズを確認
 7. Len LenBで文字数を確認。今回は純粋に英語のみのURL


# 例
今実際のサイズの下３桁が963
ディスク上のサイズが656
Len、LenBの結果が30
というURLがセルにあり、ハイパーリンクを削除して上書きします。

すると
931
656
とディスク上のサイズは変わりませんが、ファイルサイズは減少します。
しかし$963-30=933$ですがこの場合2Byte余計に減少しています。
この余計に減少するバイト数はランダムです。
36のURLが２つあり、同時にハイパーリンクを削除すると、17バイトだけ余計に減少します。

# 結論
## 余計なバイト数について
余計なバイト数はセルの書式か、データ型がハイパーリンクであることのフラグではないかと思います。
これはなぜか奇数になることがあるため、複数の要素があると考えられるためです。

## ディスク上のサイズが変わらなくてもファイルサイズは確実に減少する
Disk上のサイズは変わらなくても、ファイルサイズは減少するので、不要なハイパーリンクは削除しておいたほうが良いという結論が導かれました。これは4000くらいあると200KBは減少します。

## サンプルVBA
一応アクティブなシートのハイパーリンクを削除するマクロを示しておきます。
しかし、これはワークシート単位なので、記録しながら削除するようにしています。
テキストファイルはタブ区切りで、Unicode（UTF-16のはずです）。

### 空白が記録されることがある
しかし、よくわからない空白セルが記録される場合があります。
もしかすると、HyperLinkのフラグ？だけ残っているのでしょうか。Hyperlinkを貼ったり削除したりした場合、空白セルでもそのフラグが残るのかもしれません。
### 考察
コピー＆ペーストを繰り返すシートではあらかじめClearAllしてから貼り付けていると、このような空白セルは記録されませんでした。
なので、コピー＆ペーストはすべてクリアをしてから行ったほうが良いようです。

```vb
Sub Delete_WorksheetHyperLink()
' For Excel
' 今アクティブにしているワークシートのすべてのハイパーリンクを削除
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim xHyper As Hyperlink, xHypers As Excel.Hyperlinks
Dim FSO As Object: Set FSO = CreateObject("Scripting.FilesystemObject")
Dim fsor As New Scripting.FileSystemObject
Dim TS
Dim R As Range, URng As Range
Set TS = FSO.OpenTextFile(FSO.BuildPath(wb.Path, fsor.GetTempName) & "_" & ws.Name & "_DeleteHyplerlink.txt", 2, True, TristateTrue)
TS.WriteLine "DateTime:" & Now
TS.WriteLine "WorkSheet:" & ws.Name
TS.WriteLine "WorkSheetName" & vbTab & "Address" & vbTab & "CellValue" & vbTab & "hyperlinkName" & vbTab & "HyperlinkDisplay"
Set URng = ws.UsedRange
For Each R In URng
 If R.Hyperlinks.Count > 0 Then
   Set xHypers = R.Hyperlinks
     For Each xHyper In xHypers
     TS.WriteLine ws.Name & vbTab & R.Address & vbTab & R.Value & vbTab & xHyper.Name & vbTab & xHyper.TextToDisplay
       xHyper.Delete
     Next
'     If R.Value = "" And R.Formula = "" Then R.ClearContents
  End If
Next
TS.Close
End Sub
```