OmniAICreator/Qiita-1.07M huggingface dataset:
ホバー時に文字をオーバーレイで表示させるエフェクトをdata属性を使って実装

![0331.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288781/429475ad-a966-5d64-198c-884b0cc5ae0a.gif)
↑このように画像にホバーしたら文字がふわっと出てくるエフェクトをdata属性と疑似要素を使って実装してみました。

# data属性（data-○○）に出したい文字列を入れる
```html:html
<div class="wrapper">
  <div class="box" data-hover="ほげほげ">
    <img src="https://picsum.photos/id/237/300/300">
  </div>
  <div class="box" data-hover="ふがふが">
    <img src="https://picsum.photos/seed/picsum/300/300">
  </div>
  <div class="box" data-hover="ぴよぴよ&#13;&#10;改行">
    <img src="https://picsum.photos/id/1084/300/300">
  </div>
</div>
```
ここではdata-hoverとしていますがdata-に続く文字列はわかりやすい任意のものでOKです。
改行したい場合は`&#13;&#10;`と入れて、cssで`white-space: pre;`を指定します。


# 疑似要素のcontent: attr(data-○○);で出力
```css:css
 /* 横並びのくだりは省略 */

.box {
  position: relative;
}

.box > img {
  width: 100%;
  position: relative;
  z-index: 1;
  vertical-align: bottom;
}

.box::before {
  content: attr(data-hover); /* data-hoverの値を表示 */
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.3s;
  color: #fff;
  text-align: center;
  font-size: 18px;
  font-weight: bold;
  line-height: 2;
  white-space: pre; /* これがないと改行が効かない */
  z-index: 3;
}

.box::after {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #000;
  opacity: 0;
  transition: opacity 0.3s;
  z-index: 2;
}

.box:hover::before {
   opacity: 1;
}

.box:hover::after {
  opacity: 0.5;
}
```

# コード全文はこちら
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="wvEbNjz" data-user="sogawa-BitStar" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sogawa-BitStar/pen/wvEbNjz">
  hoverしたらdataの文字を出す</a> by sogawa-BitStar (<a href="https://codepen.io/sogawa-BitStar">@sogawa-BitStar</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
一緒にシフトに入る人を教えてくれるLINEBotを作ってみた。


はじめまして！
飲食業で働いている会社員です。普段は店舗を回ったりしています。

各店のシフト閲覧をどうしているか聞いたところ、ほぼ全店が日ごとのシフトを写真撮影してスマホで保存しているとの回答。

もう少し楽に見ることができないかなぁと考え、噂のLINEBotで作成できないか試してみることにしました！

# 完成品！　LINEBotでシフトチェック！


https://twitter.com/j30229/status/1641790609211162626?s=20

# 完成するまで


まずは、店舗にてヒアリング・・・すると

・写真だと似たようなサムネイルなので探すのが面倒。
・誰との勤務なのかを知りたい。
・不規則なシフトなので確認が大変。
などなど
店舗では下記の表で1日のシフト表が作成されているのですが、これを写真で毎回確認するのは確かにしんどい。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/8afd4c10-7518-1e27-cda7-db9e3d20df44.png"width="300px">

よし、LINEで日付を入れると必要な情報が返ってくるBotを作成してみよう！
# 使用ツール
・[Make](https://www.make.com "Make Home")
・[SSSAPI](https://sssapi.app "SSSAPI")
・Googleスプレッドシート
・LINE
・[LINE Developers](https://developers.line.biz/ja/ "LINE Developers")(とLINE Official Account Manager)
# 製作開始
## １－１　APIデータに使用するGoogleスプレッドシートを作ろう
まず、店舗が普段使用しているEXCELデータに抽出用のシートを追加作成しGoogleスプレッドシートへ貼り付けます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/26ea445a-b35e-8cf0-0bf1-ab42fab6a6cb.png"width="500px">
## １－２　　SSSAPIを使用してAPI化！
https://sssapi.app/
こちらのサイトで名前を付けて、GoogleスプレッドシートのURLを貼り付るだけ！
できたらGoogleスプレッドシート側の共有に

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/edddce9a-d869-9ef0-33b8-a3f7e4e8c9a3.png"width="300px">
## １－３Makeでシナリオ作り
LINEでメッセージを受け取り→Toolsで日付文字列を読み取り→HTTPでデータを読み取り→JSONで変換し→LINEで返す！（というイメージ）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/f61f712a-d592-0dbd-5416-45c1dfc67d52.png"width="600px">
左下から
１）LINEモジュールはLINE Developersで作成したLINEアカウントと紐づけるだけ

２）Toolsモジュールは日付を打つ際に/を入れない場合は不要です。今回は3月31日を331と表記しています。

３）HTTPモジュール。 ここは一番苦労しました。
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/63525e12-3610-ed5d-5046-efc3f5c33965.png)
クエリを設定することで、LINEで入力した文字列でフィルタリングした結果を取得させたかったのですが、どうにもうまく動いてくれません。
赤丸で囲ってある部分をよーく睨んでみると…
アンダーバー2個必要だったんですね…長いと思ったんですよ…

https://sssapi.app/help/api_call/#1%E4%BB%B6%E5%8F%96%E5%BE%97

４）JSONモジュールに当該APIのサンプルを読み込ませ認識させます。

５）一番右のLINEモジュールに応答部分の設定をします。
![スクリーンショット (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3293453/6823bbf7-7e81-eee5-1f9c-97fa59b2610e.png)
JSONにサンプルを読み込ませて認識できていればTextに上記のように設定できます。

これで完成です！



# 最後に
シンプルなBotですが、動作すると感動しますね。

店舗の方々に触って頂き、様々な要望や壁を頂きました。

最大の壁は写真で管理を超えること！（写真を返す作りにする手もありますが）

ここまで読んで頂きありがとうございました。
Raspberrypi3にGxsm3をインストールする

## はじめに
大学院で原子間力顕微鏡(AFM)の研究を行っているものです。日本語の資料がなかったので他の研究室の人が同じように困っていたらと思い書きました。
ここでは、Soft DB社のSPMコントローラとその制御ソフトであるGXSM3の環境構築について書いていきたいと思います。

:::note warn
時間がたつとリンクが切れたりすると思うので適宜公式サイトを検索してください。
:::

:::note
Gxsm3とはGnome X Scanning Microscopyの略称で原子間力顕微鏡(AFM)をはじめとした走査型プローブ顕微鏡(SPM)用に開発されたソフトウェアでMK2-A810やMK3-PLL、MK3-HV1などの制御に必要となります。([公式サイト](https://gxsm.sourceforge.net/index.php))
:::

:::note
raspberrypy3でMK2-A810の制御を行うための環境構築を行います。以下のものが必要となります。
- Raspberry Pi3(Gxsm3のインストール先)
- Windows PC(MK2-A810のDSPコードの更新に必要)
- SSD(ラズパイをbootする)
- MK2-A810
:::
## 1. MK2-A810のアップデート
### 1.1 windowsマシンにSoft DB社から提供されているドライバーとmini debuggerをインストールします。
[MK2-A810の商品ページ](https://www.softdb.com/scanning-probe-microscopy/mk2-a810/)にDriver Installerがあるのでドライバーのインストールを行う。その下のほうにSR2_NG software installer(SR3_Applications_Installer***.zip)があるのでそれを押してツールのインストールを行う。
### 1.2 DSPコードを取得する
MK2-A810の中のFPGA用のコードを取得する必要がある。いろいろな方法があるが、[公式](https://sourceforge.net/p/gxsm/svn/HEAD/tree/trunk/Gxsm-3.0/plug-ins/hard/MK2-A810_spmcontrol/FB_spmcontrol_MK2_A810.out)から落とすのが楽。

::: note 
最新版のGxsmを使いたいなら、最新のDSPコードが必要
:::
### 1.3 MK2-A810のDSPコードの更新
まず、MK2-A810とWindows PCを接続しオレンジ色にLEDが点灯するか確認してください。

:::note alert
LEDが赤色でしたら、Driver周りでエラーが起きているので対応が必要です。
:::
次に、1.1でインストールしたSR3_Applicationsを開き、SRx_Analog810.outを実行。DSPコードを選択するボックスが出るので1.2でダウンロードしたファイルを選択。
あとは、勝手に進む。終わったら、MK2-A810の電源を落としDSPコードを最新のものに出来た。

## 2 ラズパイにGxsm3環境を構築する
### 2.1 ラズパイにGnomeを導入する。
まず、boot用のSSDに64bit GUI　Raspberry Pi OSを焼き付け、USB Bootし基本設定を終わらせる.
次にデスクトップ環境であるGnomeのインストールを進めていく。

``` 
wget　https://github.com/TerraGitHuB/gnomeforpi/archive/refs/heads/stable.zip
unzip stable.zip
cd gnomeforpi-stable
sudo ./gnomeforpi-install
sudo update-alternatives --config x-session-manager
reboot
```
そこそこ時間がかかるのでLANでの作業がおすすめ。また、途中ででてくる選択肢はlightdmで問題ない。
再起動するとデスクトップがGnomeに代わっていればOK。

2.2 GXSM3の導入
[公式](https://sourceforge.net/p/gxsm/discussion/297458/thread/3f0faafe/)に従えば基本的に問題はない。

:::note warn
ライブラリについては訂正する必要がある。
:::
```
sudo apt-get install subversion automake make dkms g++ rapberrypi-kernel-headers
svn checkout https://svn.code.sf.net/p/sranger/svn/trunk/SRanger sranger-svn
svn checkout https://svn.code.sf.net/p/gxsm/svn/trunk/Gxsm-3.0 gxsm-svn
cd sranger-svn/SR_MK2_MK3Pro/kernel-module/src/
sudo make
sudo make install
sudo cp 49-sranger_mk23.rules /etc/udev/rules.d/
```
ここで電源を落としてからMK2-A810とラズパイを接続する。
```
sudo make load
```
ここからGXSMのビルドが始まるのだが大量のライブラリをインストールする必要があり、公式のドキュメントが古いという問題点がある。
[Github](https://github.com/pyzahl/Gxsm3/blob/master/debian/control_ubuntu22.04)を見て上側にあるライブラリをすべてインストールする。
```
sudo apt-get install ***
```
あとはビルドをするだけである。
```
cd gxsm-svn
./autogen.sh
sudo make
sudo make install
```
これにて完成である。
```
gxsm3
```
でGxsm3が起動する。
##　あとがき
誰かの助けになればいいなと
後で細かいとこ修正していきます。
AWS + Terraform – ECS に deploy は成功するが全くログが表示されない (dockerプロセスが起動してないっぽい)

# 解決

ECSサービスで「サービスを更新」に進むと

<img width="438" alt="image" src="https://user-images.githubusercontent.com/13635059/229123096-b0188e16-a60d-44b3-a509-01b0df3d6295.png">

「必要なタスク」が0個になっていた

![image](https://user-images.githubusercontent.com/13635059/229123010-264d34ce-e865-49a8-9fb0-a5da455ece04.png)

これを1に変えてサービス更新するとプロセスが起動し、ECSインスタンスの画面でログも表示されるようになった

# Terraform

Terraformのコードでいうとこの箇所だ
ここを1にしてみた

```
resource "aws_ecs_service" "default" {
  ...
  desired_count                     = 1
}
```



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Cloud CustodianでEC2を定時で起動、停止を簡単に設定する

## はじめに
Cloud Custodianで特定のタグがついているEC2を定期的に起動停止することをやってみました。
今回Cloud Custodianで作成するのはLambda、EventBridgeです。

## Cloud Custodianとは
CNCFの一つのプロジェクトで、AWS、Azure、Google Cloud Platformなどのクラウドインフラストラクチャ上に存在するリソースの管理と保護を行うオープンソースのツールです。
https://cloudcustodian.io/

## まず用意するもの
Lambdaが使用するロールをEC2の操作をできるようにポリシーを含んだ状態で用意する。下記が例
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances",
                "ec2:DescribeInstances"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
```

EC2に任意のタグを用意する。下記が今回用意したもの
key：autoStartStop
value：true

## Cloud Custodianをインストール
```
pip install c7n
```

## Custodianで使用するポリシーファイルを作成する。

ファイル名：ec2-start-stop.yml
```
policies:
  - name: ec2-auto-start
    resource: aws.ec2
    mode:
      type: periodic
      schedule: "cron(10 12 * * ? *)"
      role: "arn:aws:iam::xxxxxxxxxxx:role/xxxxxxxxx" # 事前に用意したロールARNを追加
    filters:
      - "tag:autoStartStop": "true"
    actions:
      - start

  - name: ec2-auto-stop
    resource: aws.ec2
    mode:
      type: periodic
      schedule: "cron(0 12 * * ? *)"
      role: "arn:aws:iam::xxxxxxxxx:role/xxxxxxx" # 事前に用意したロールARNを追加
    filters:
      - "tag:autoStartStop": "true"
      - "State.Name": "running"
    actions:
      - stop
```

コードの解説
resource: aws.ec2はポリシーが適用されるAWSリソースタイプを指定します

type: periodicはperiodicを指定することで、ポリシーが定期的に実行されます

schedule: "cron(0 12 * * ? *)"は実行されるタイミングをcron式で指定します。（0 12 * * ? *の指定はテストのためこの時間にしています。。。）

role: "arn:aws:iam::xxxxxxxxx:role/xxxxxxx"はLambda関数に適用されるIAMロールのARNを指定します

filters:はautoStartStopタグがtrueに設定されたEC2インスタンスに対してのみポリシーが適用されます

actions:はフィルタリングされたリソースに対して実行される操作を定義します

## Custodianを実行する

※実行する前にAWSの認証情報の設定を行なってください。

下記コマンドで実行する
```
custodian run -s output ec2-start-stop.yml
```

## 実行すると
こちらのようなLambdaとEventBridgeが作成される。
![スクリーンショット 2023-03-31 21.38.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1810458/d56abc23-a6f9-9ca0-3cf8-922c8724cd34.png)
![スクリーンショット 2023-03-31 21.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1810458/35a833b9-c7ce-709d-daa9-9f18bb8b03a8.png)

このようにポリシーを作成し実行することで簡単にLambdaとEventBridgeが作成されます。

## 最後に
Cloud Custodianを使用することで簡単にEC2を定時起動と停止を構築することができました。
もうすこしCloud Custodianで難しい処理や複数アカウントでの実装方法を勉強したいと思いました。
た～みなる 2023年メモ

*【Linux】*

*【MacOS】*

*【iOS/iPadOS/Android】*

*【Windows】*

・・・なにやら、TeraTerm5なるバージョンが出るそうですね...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1349578/31dfacdd-111d-5996-56ec-055f70f4a438.png)


このペースだと、RCは 2024年Q1頃？いや、2023年末か？

※そのほか追記中です
【SwiftUI】言語設定を作成する

# はじめに
アプリ内で言語の設定ができるようにPickerを作成しました。

# こんな感じ
![スクリーンショット 2023-03-31 21.23.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c280d45a-2935-6059-83e0-fca1192cd7a0.png)

# 実装
```swift
public extension Locale {
    static var availableLocalizedLocales: [String] {
        return Locale.availableIdentifiers.compactMap {
            Locale(identifier: $0).localizedString(forIdentifier: $0)
        }
        .sorted()
    }

    var languageName: String {
        localizedString(forLanguageCode: language.languageCode?.identifier ?? "") ?? ""
    }
}
```

```swift
import SwiftUI

struct ContentView: View {
    @State private var selectedLanguage: String = ""
    var body: some View {
        Picker(selection: $selectedLanguage) {
            ForEach(Locale.availableLocalizedLocales, id: \.self) { localizedLocales in
                Text(localizedLocales).tag(localizedLocales)
            }
        } label: {
            Text("Language")
        }
        .pickerStyle(.menu)
        .padding()
    }
}
```

# おわり
この実装のいいところは自分で言語リストを作らなくていいところです！
標準で用意されている言語リストを使用しています
blender内蔵のpythonにおいて各種ライブラリをインストールする

# Pandasライブラリを例にする

windowsターミナル(or PowerShell or コマンドプロンプト)を
`C:\Program Files\Blender Foundation\Blender 3.5\3.5\python\bin>`
にて開く

以下のコマンドを実行する
```
.\python.exe -m pip install pandas
```
ファイルツリーのフォルダ名をクリックしたらフォルダ名の前の矢印の向きが切り替わるようにする。

# ファイルツリーのフォルダ名のspanタグの左側に矢印をつけたい。フォルダ名をクリックすると矢印の向きが切り替わるするようにしたい。

## まずは簡単な例で、spanタグに矢印をつける方法を理解する。

矢印をspanタグの左側に追加するには、styleタグの::before疑似要素を使用する。
::before疑似要素は、要素の内容の前に装飾を追加するために使用する。

この例では、.arrow-rightクラスが適用された<span>要素の左側に、矢印（▶︎）を追加している。margin-rightプロパティを使って、矢印とテキストの間のスペースを調整できる。

矢印のデザインやスタイルはカスタマイズできる。


```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Arrow Left Example</title>
  <style>
    .arrow-right::before {
      content: "▶︎";
      margin-right: 5px; /* 矢印とテキストの間のスペースを調整する */
    }
  </style>
</head>
<body>
  <span class="arrow-right">Text with arrow on the left</span>
</body>
</html>
```

# 矢印の向きが入れ替わるようにしていく。クリック時にクラスを切り替えて矢印の方向を変更する
#### styleタグの説明
styleタグで右向き（▶︎）と下向き（▼）の２つの::before疑似要素を用意する。

矢印のデフォルトスタイル（▶︎）と、arrow-downクラスが適用された場合のスタイル（▼）を定義している。

#### htmlのbodyの説明
フォルダ名のspanタグには、デフォルトの右向きの矢印（▶︎）を付加する。

#### scriptタグの説明
constは、定数の宣言に使用される。
idが"arrowElement"の要素のデフォルトのスタイルを取得し、arrowElementと名付ける。

arrowElement.addEventListener('click',関数);とは、arrowElementのクリック時に関数を実行するイベントリスナーである。

arrowElement.classList.toggle('arrow-down')は、arrowElementという要素のクラスリストにarrow-downというクラス名が存在する場合は削除し、存在しない場合は追加するという操作を行う。

※タグには複数のリストを付加できる。クラスリストと呼ぶ。
※toggleとは、日本語訳すると「機能や状態のON/OFFを切り替える仕組み」である。

arrowElementに'arrow-right'と'arrow-down'両方のクラスが適用されている時、片方の矢印しか表示されない。
かつ、後に記述されたルールが優先されので、Webページでは矢印の向きが切り替わる。

優先度の説明は長くなるので、コードの下に書く。

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Toggle Arrow Example</title>
  <style>
    .arrow-right::before {
      content: "▶︎";
      margin-right: 5px;
    }

    .arrow-down::before {
      content: "▼";
    }
  </style>
</head>
<body>
  <span class="arrow-right" id="arrowElement">Click to toggle arrow direction</span>

  <script>
    const arrowElement = document.getElementById('arrowElement'); 
    arrowElement.addEventListener('click', () => {
      arrowElement.classList.toggle('arrow-down');
    });
  </script>
</body>
</html>
```

## arrowElementに'arrow'と'arrow-down'両方のクラスが適用されている時、片方の矢印しか表示されないのはなぜか。
これは、CSSのカスケード（継承）と特異性（詳細度）の仕組みによって決まる。

CSSでは、複数のスタイルルールが同じ要素に適用される場合、特異性という概念に基づいてルールの優先順位が決まる。
特異性が高いルールほど、適用される確率が高くなる。
特異性は以下のように計算される。

1. インラインスタイル（要素のstyle属性に直接記述されたスタイル）が最も高い特異性を持つ。
2. セレクタの中でIDセレクタ（#id）の数が次に高い特異性を持つ。
3. セレクタの中でクラスセレクタ（.class）、属性セレクタ（[attr]）、および疑似クラス（:pseudo-class）の数が次に高い特異性を持つ。
4. セレクタの中で要素セレクタ（element）および疑似要素（::pseudo-element）の数が最も低い特異性を持つ。

上のコードでは、.arrow-right::beforeと.arrow-down::beforeの2つのスタイルルールがある。
両方ともクラスセレクタと疑似要素を使用しているため、特異性は同じである。

特異性が同じ場合、後に記述されたルールが優先される。

arrowElementにarrow_rightとarrow-downの両方のクラスが適用されている場合、.arrow-down::beforeルールが優先されるため、矢印は下向きに表示される。
.arrow::beforeルールは上書きされ、表示されない。



### （感想）
要素に複数のclassを付加できることを知らずclasslistの意味が最初は分からなかった。
toggleについても知らなかったので戸惑った。
EBS VolumeIdleTimeがゼロだがIOPSやスループットが上限に達していない場合のパフォーマンス改善方法

# はじめに
DBなどのパフォーマンス改善のためEBSをチューニングしよう!となりメトリクスを見たとき、
以下の右半分のようにアイドル時間（`VolumeIdleTime`）が既にゼロになっているときがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858685/6036db35-c51a-d542-22df-d7fc54efcc25.png "右半分はアイドル時間がゼロになっている")


ここで 
**「ディスクが完全にBusy状態だからIOPSやスループットを上げるしか無い!!」** 
と思うのは時期尚早です。

実は、この状態でもEBSのIOPSやスループットに余裕がある場合はよくあります。
それがなぜ発生するのか、どうすればディスクのパフォーマンスを改善できるのかを説明します。

# VolumeIdleTimeについて
自分は勘違いをしていたのですが、"VolumeIdleTimeがゼロ = Disk性能上限に達している" というわけではありません。
VolumeIdleTimeがゼロというのは、あくまで **ずーーっと読み書きが続いているというだけ** で、
極端な話、1ミリ秒に1回のReadでもそうなります。

EBSのパフォーマンスを改善するなら、
VolumeIdleTimeに心奪われず、IOPSとスループットを見る必要があります。

# CloudWatchメトリクスでIOPSとスループットを確認する
IOPSとスループットは、CloudWatchメトリクスでカスタムグラフを作ってしまうのがおすすめです。
URLにすべての設定情報が埋め込まれているので、チームメンバーへの共有も簡単です。

### 設定手順
1. CloudWatchメトリクス→EBS→ボリューム別メトリクスでボリュームIDを検索
2. `VolumeReadOps`, `VolumeWriteOps`, `VolumeReadBytes`, `VolumeWriteBytes` を選択
3. 統計は `合計`、期間は `1分` を選択
   - [EBSのメトリクスはデフォルト1分間隔で取得されています](https://aws.amazon.com/jp/about-aws/whats-new/2021/01/amazon-ebs-announces-cloudwatch-metrics-with-1-minute-granularity-on-all-ebs-volume-types/)
4. 数式を追加 → 空の式で始まる を選択
5. `(VolumeReadOps+VolumeWriteOps)/60` と `(VolumeReadBytes+VolumeWriteBytes)/60` の式を設定
   - 各メトリクスが60秒の合計値になっているので、1秒あたりにするために60で割ります
6. 式以外のチェックを外して非表示に
7. Y軸をIOPSとスループットで左右に分ける
   - IOPSはk, スループットはmと単位が違うので、Y軸は分けたほうが見やすくなります

↓こちらVolumeIdleTimeの1枚目と同じ時間で設定した例です↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/858685/71640585-2330-c594-ddd5-b1f7e8c7c1f7.png "設定例")

こうして確認することで、同じVolumeIdleTimeがゼロの時間（大体右半分）でも、
IOPSやスループットには差があることがわかります。
そして、どちらも上限値に達しておらず余裕があるなら、
闇雲にIOPSやスループットを上げてもパフォーマンスは改善してくれません。

※ディスク性能の要素としては、[EBS用のネットワーク帯域](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-optimized.html)もありますが、今回は割愛してます

# パフォーマンス改善に向けたチューニング

ここまでで、`VolumeIdleTime` がゼロというのはディスク性能上限に達したという意味ではなく、
あくまでIOPSやスループットに着目するべき、というのがわかりました。

そして、パフォーマンスに問題があるにも関わらず、IOPSやスループットに余裕があるのであれば、
まず**性能を十分に使い切れるように EBS以外の要素をチューニングする**必要があります。
十分に使い切れるようになった後は、**IOPSとスループットを上げてさらにパフォーマンスを改善**できます。

チューニングについて、一般的には「I/O処理の並列化」、「I/Oサイズを大きくする」といった改善策がありますが、
使われているOSやミドルウェアによって対応は千差万別です。

自分がDBのパフォーマンス問題に取り組んだ際には、
OSとミドルウェアのレイヤーにボトルネックがあり読み書き速度が遅くなっていました。
そのボトルネックを取り除くことでIOPSとスループットが上限に達するようになり、
その後のIOPSとスループット増強で飛躍的にパフォーマンスが改善しました。

# 終わりに

EBSの`VolumeIdleTime`がゼロだが、IOPSやスループットが上限に達していない謎が解けたでしょうか。
ディスクのパフォーマンス改善にあたっては、多数のメトリクスに惑わされず、
正しい数値に焦点を合わせてチューニングをしていってください。
【Anaconda】condaのアップデートの警告を消す方法

# 環境
- macOS
- iTerm2
# 概要
pythonのパッケージをインストールしてたらずっと警告↓が出てて煩わしかったので、いい加減にcondaのupdateをやろうと思いました。
```
==> WARNING: A newer version of conda exists. <==
  current version: 4.12.0
  latest version: 23.3.1

Please update conda by running

    $ conda update -n base -c defaults conda

```
これは
- 現在のバージョン：4.12.0
- 最新のバージョン：23.3.1

でアップデートした方がいいよという警告です。

そんなんすぐ
```
conda update -n base -c defaults conda
```
でできると思いきや同じ警告が出るばかり、、、

なんか苦戦したんで記事に残します。

# 解決方法
簡潔に言うと、私の場合はAnacondaを最新バージョンにアップデートしてみた後でやったらできました。
### Anacondaのアップデート
```
conda update -n base conda -c anaconda
```
これによりcondaを含むパッケージが優先度の高いanacondaチャンネルに優先される。

### condaのアップデート
警告で散々出てきたコマンドを打ち込んであげる。(最後のcondaをbaseの後に変えた)
```
conda update -n base conda -c defaults
```
これによりcondaを含むパッケージが優先度の高いpkgs/mainチャンネルに優先される。
要するに一旦anacondaチャンネルに変えてもとに戻すと警告を消すことができたと言うことです。

こんな感じで警告を消すことができました。
ここまで見てくれてありがとうございます。

# 参考
[https://github.com/conda/conda/issues/6591](https://github.com/conda/conda/issues/6591)

# 余談
今回初めてQiitaに投稿してみるのですが、 備忘録としても見れるし、自分の理解を整理できるので悪くないですね。
C#のソースコードからVisual Studio 2022でクラス図を作成する

# 1. はじめに
* Visual Studio 2022からC#のプログラムソースからクラス図をリバースで作成したい

# 2. 開発環境
* Visual Studio 2022 Community
* C#
* .NET 6
* Windows 11

# 3. クラスデザイナーのインストール
* ```ツール``` > ```ツールと機能を取得```を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/19c6d7b6-18e4-1afc-f415-1e58c858dba3.png)

* ```個別コンポーネント``` > ```クラスデザイナー```をチェックして、変更ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/db782617-8d05-5818-e8fd-5ba9ad56d39a.png)

* インストール画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/d7047f3f-e88c-9d0f-bbed-74746ed9e048.png)

* 作業中の場合、下記画面が表示されるため続行ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/408caeda-cf28-24ab-85dd-98eb6be77c6e.png)

* インストールが完了する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/c4b3158e-fc02-8d8c-97a5-1ea54549b368.png)

# 4. クラス図を作成
* プロジェクトを右クリックして```追加``` > ```新しい項目```を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/f0a4c3fb-7a3e-9345-b714-e8f6721c1393.png)

* ```クラスダイアグラム```を選択して、任意の名前を入力して追加ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/2b336a83-6751-5249-bfcd-aa6a9ad02945.png)

* クラスデザイナーにクラス図を作成したいプロジェクトをドラッグ&ドロップする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/a4b306d8-b4fa-74e9-41e9-071d1f5a2659.png)

* クラス図が作成できた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/e3becad7-bf96-b30b-eaed-1dfeb06f4867.png)

# 5. 参考文献

https://learn.microsoft.com/ja-jp/visualstudio/ide/class-designer/how-to-add-class-diagrams-to-projects?view=vs-2022

https://soft-rime.com/post-6314/
Ruby を利用して Aws lambda function からS3にあるJsonファイルを読込



やりたいこと
---
  Ruby を利用して Aws lambda function からS3にあるJsonファイルを読込したい。


手順
---
1. S3の該当なDirにJsonファイルを用意します。
2. LambdaFunctionを作成する。
![スクリーンショット 2023-03-29 11.01.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989503/98a8100b-a82b-6055-7715-ee81517f554a.png)

Rubyコード
---

```
require 'aws-sdk'
require 'time'

def lambda_handler(event:, context:)

    # Set region
    region = 'us-east-1'

    # API client for S3
    s3 = Aws::S3::Client.new(region: region)
    ##### 引数を格納
    # S3のバケット名
    bucket_name = event['bucket_name']
    execute_day = Time.parse(event['execute_day']).strftime("%Y%m%d")
    # S3Pathを生成する [my_folder/20230303/index.json]
    obj_key = 'my_folder/' + execute_day.to_s + '/index.json'
    # S3にあるJsonファイルを読込
    resp = s3.get_object(bucket: bucket_name, key: obj_key)
    data_json = JSON.parse(resp.body.read)

    # Jsonを返す
    return { statusCode: 200, body: data_json}
    
end
```

上記でS3にあるJsonファイルの読み込みができます。
続いて「data_json」の中身を確認しましょう！
data_jsonがHash型でデータを持っているためキーを指定してデータが取れます。

```
例：
puts data_json["user"]
# output:↓
# [{"user_id"=>3, "name"=>"John Smith", "email"=>"johnsmith@test.com"}, {"user_id"=>2, "name"=>"Cherry", "email"=>"cherry@test.com"}, {"user_id"=>2, "name"=>"Starry ", "email"=>"blue@test.com"}]

例：
puts data_json["order"]
# output:↓
# [{"order_id"=>1, "user_id"=>"3", "order_detail_id"=>"1001"},{"order_id"=>2, "user_id"=>"3", "order_detail_id"=>"1002"}]
```

プライベートテストイベントを作成
---
1. Lambda Function の[Test] (テスト) タブを選択します。
2. [Test event] (テストイベント) で、次の作業を行います。
    - [Template] (テンプレート) を選択します。
    - テストの [Name] (名前) を入力します。
    - イベント JSONに渡したいパラメータを用意します。
    - 保存をクリック
    
3.[Test] (テスト) をクリックする。
4.テスト結果を確認するには、[Execution result] (実行結果) で、[Details] (詳細) を展開します。
上記でテスト準備ができます。

##### 参考リンク
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/testing-functions.html

![スクリーンショット 2023-03-29 11.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989503/a6da66f2-3967-d37a-3f31-0f51d8145c95.png)

![スクリーンショット 2023-03-30 10.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989503/3363839e-20a2-2c27-98f8-bf834a90d9d7.png)

テストを試しましょう
---
テストする前にDeployをしないと作成したコードが反映されないので、テスト前にDeployを押してください。
[Test] (テスト) をクリックする。

```
結果：

Test Event Name
test

Response
{
  "statusCode": 200,
  "body": {
    "user": [
    {
      "user_id": 2,
      "name": "John Smith",
      "mail": "johnsmith@test.com"
    },
    {
      "agency_id": 3,
      "name": "Cherry",
      "mail": "cherry@test.com"
    }],
    "order": [
      {
        "order_id": 1,
        "user_id": 2,
        "order_detail_id": "1001"
      },
      {
        "order_id": 2,
        "user_id": 3,
        "order_detail_id": "1002"
      }
    ]
  }
}
```

以上。
JetpackComposeとViewModel

# JetpackComposeとViewModelの運用

- JetpackComposeでのViewModelの運用方法に疑問を抱いたので、軽く調べたメモ用とする。

## サンプルコードを見て学ぶ

以下サンプルコード↓
```Kotlin
class HelloViewModel : ViewModel() {
    private val _name = MutableLiveData("")
    val name: LiveData<String> = _name

    fun onNameChange(newName: String) {
        _name.value = newName
    }
}

// 画面単位といった大きな粒度でViewModelと結合する
@Composable
fun HelloScreen(helloViewModel: HelloViewModel = viewModel()) {
    val name: String by helloViewModel.name.observeAsState("")
    HelloContent(name = name, onNameChange = { helloViewModel.onNameChange(it) })
}

// 子Composableには純粋なパラメータとコールバックでやりとりをする
@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}
```
**注意点**は以下の二つ
###### 1, ViewModel自体を子Composableに渡さない
コンポーザブルは、**必要なものにのみ渡す** ことが重要です。
これにより子Composableの依存関係が明確になり、また再利用性、テスト容易性が高まります。以下のようなコードにしないこと。
```Kotlin
@Composable
fun HelloContent(helloViewModel: HelloViewModel)  {
    /* ... */
}
```
###### 2, ViewModelをCompositionLocalで配布しない
[CompositionLocal](CompositionLocal)は子Composableに暗黙的にデータを伝えることが出来ます。
これにより、バケツリレーが解消される一方、データが追いにくくなるというデメリットもあります。
公式による[CompositionLocal を使用すべきかどうかの判断](https://developer.android.com/jetpack/compose/compositionlocal?hl=ja#deciding) によると、本来ViewModelを必要としていない子ComposableからもViewModelのインスタンスが参照できてしまうことに触れ、CompositionLocalでViewModelを保持すべきでないと明言されています。

上記をまとめると、Jetpack ComposeとViewModelは疎であるべきであり、大部分でViewModelを意識しない形にすることが理想でしょう。
【Rails】RSpecのモック/スタブの違いと必要性

# 前提

以下のような背景から、外部APIのテストにはモックやスタブを使うのが一般的。

- 現在、自前アプリに外部APIを組み込んで機能開発することが一般的
  ↓
- 外部APIは従量課金のものが多いが、テストはどうするか
  ↓
- RSpec実行のたびに外部APIを叩くのはコストが無駄
- かつ、外部APIのロジックは提供元が担保するので、そもそも叩く必要性は薄い
  ↓
- モック・スタブを使うことで、あたかも外部APIを叩いた体でレスポンスデータ(固定値)を返してくれる
  ↓
- 開発者はデータ返却後の後続のテストを書けば良い

# 例

Faraday.newでconnectionオブジェクトを作成し、
connection.postでHTTPリクエスト(POST)を発行するAPIの例。

# モック

- APIレスポンスの代わりに返すオブジェクト

```ruby
# ex
connection = double
#=> ダミーのオブジェクトをconnectionに代入しておく
```

# スタブ

- APIリクエストなどの代わりに実行するメソッド

```ruby
# ex
allow(Faraday).to receive(:new).and_return(connection)
#=> Faraday.new すると connection が返却されるように処理を変えるということ

allow(connection).to receive(:post) { Faraday::Response.new(status: 400) }
#=> connection.new すると Faraday::Response が返却されるように処理を変えるということ
```

# 挙動

- アプリケーション本来の動き
    - Faraday.newすると、connection(APIクライアント)が返却される
    - connection.postすると、Faraday::Responseオブジェクト(HTTPリクエストの結果)が返却される

- specでの動き
    - Faraday.newすると、connection(モック)が返却される
    - connection.postすると、Faraday::Responseオブジェクト(400)が返却される

# まとめ

- モックとスタブを利用し、返却するオブジェクトを固定しておくことで、あたかもAPIリクエストを発行したかのようにテストすることができる
- 正しいリクエストならば正しいレスポンスが返却される前提があるので、そこはAPI提供元に委ねる、その代わりレスポンスを得た後のアプリケーションの挙動を検証する、という考え方が基本

# 参考

https://qiita.com/fuku_tech/items/261e958b35ab809213da
指定したディレクトリ以下で、-nameオプションを使用して「特定の名前のファイルまたはディレクトリ以外」のすべてを削除する方法

## 指定した名前のファイル（ディレクトリ）以外を削除するコマンド
* とあるディレクトリで、テスト用のファイルをぽこぽこ作ってしまい、`hoge`という必要なディレクトリ以外のすべてのファイルやディレクトリを一括削除したいな、という局面がありました。
* 実行したことがないコマンドだったので、調べて以下コマンドで実施したら無事にできました。

```terminal
$ find /path/to/directory -mindepth 1 -maxdepth 1 ! -name 'hoge' -exec rm -r {} +
```

* `! -name`がポイントですね。

### 各オプションの説明
* `find`: ファイルを検索するコマンド。
* `/path/to/directory`: 検索するディレクトリのパスを指定。
* `-mindepth 1`: 検索を開始する階層の深さを指定。ここでは、指定したディレクトリ直下から探索を開始するために1を指定。
* `-maxdepth 1`: 探索する階層の深さを指定。ここでは、指定したディレクトリ直下のみを探索するために1を指定。
* `! -name 'hoge'`: -nameオプションで指定した名前以外を探すために、!オプションで`'hoge'`という名前以外を指定。
* `-exec`: -execオプションを使用すると、指定したコマンドを検索結果の各項目に対して実行できる。
* `rm -r`: rmコマンドはファイルを削除するために使用される。-rオプションは、ファイルがディレクトリの場合に再帰的に削除することを指定。
* `{}`: -execオプションで指定されたコマンドの引数として、検索された各ファイルまたはディレクトリのパスを指定。
* `+`: -execオプションの最後に+を指定すると、検索結果全体に対して一度だけコマンドを実行。これにより、ファイルやディレクトリが多数ある場合でも、1つずつ削除する必要がなく、処理が高速化される。
Ubuntu20.04にPHP5.6をインストールする【備忘録】

# Ubuntu20.04にPHP5.6をインストールする

## 背景
* 案件の関係でPHP5.6環境を用意しなければならなかったのですが、結構ハマってしまったので備忘録を残します。

## インストールの流れ
### (1)Ubuntuに元から入っているPHPを削除
### (2)aptをアップデート
```sh
sudo apt update
```

### (3)ソフトウェアプロパティコモンをインストール
```sh
sudo apt install software-properties-common
```
:::note alert
私はここを飛ばしていたせいで長い時間ハマってしまいました。
:::

### (4)PPAのインストール
```sh
sudo add-apt-repository ppa:ondrej/php
```
:::note info
```Press [ENTER] to continue or Ctrl-c to cancel adding it.```が出たらエンターを押して少し放置。
```Error: retrieving gpg key timed out.```エラーになったらCtrl＋Cで仕切り直し。
:::
* うまくいけばいろいろインストールされます。

### (5)再度aptアップデート
```sh
sudo apt update
```

### (6)PHP5.6のインストール
```sh
sudo apt install php5.6
```
※その他のライブラリもインストールする場合は下記
```sh
sudo apt install php5.6 php5.6-gd php5.6-mysqlnd php5.6-imap php5.6-mbstring php5.6-xml php5.6-bcmath php5.6-opcache php5.6-zip
```

### (7)確認
```sh
php -v
```

## Mysql5.7インストール
* 5系はaptに入っていないので入ってるリポジトリを取得する必要がある
### アプトアップデート
```sh
apt-get update
```

### wgetのインストール
```sh
apt-get install wget
```

### リポジトリの置き場を作成
```sh
mkdir /downloads
```

### リポジトリを取得
```sh
wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.deb
```

### リポジトリからパッケージを取得
```sh
dpkg -i mysql-apt-config_0.8.12-1_all.deb
```

### ubuntu bionicを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920579/8472c2c9-8131-1084-fd45-ab0897a697bb.png)

### 8.0を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920579/8dcb1223-661b-d149-fa8d-eac6cb9891b0.png)

### 5.7を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920579/a65a2edb-c9fa-1fbe-dcc6-1434a74285c3.png)

### aptキーを追加する
```
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 467B942D3A79BD29
```
:::note info
Ubuntu公式以外からパッケージを取得するには、このコマンドで認証する鍵情報を取り込んでおく必要がある。
:::

### aptをアップデートする
```sh
sudo apt update
```

### リポジトリが正常に追加されたかを確認
```sh
sudo apt-cache policy mysql-server
```

### 必要なパッケージをインストール
```sh
sudo apt install -f mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7*
```

### ルートのパスワードを設定

:::note alert
ここでパスワード設定しないと入れないので注意
:::
AWS – ECS でログが表示されない？ CMD echo するだけのDockerfileを作って試してみる

# Dockerfile

CMD で echo してしまうのが手っ取り早そうだ

```dockerfile
FROM alpine

CMD echo "HELLO ECS FROM ALPINE!!"
```

# 準備

ECRにイメージをpushする
タスク定義を作る
ECSでサービスを作成する、または更新する

# ログが表示された

<img width="1144" alt="image" src="https://user-images.githubusercontent.com/13635059/229105969-481ce24b-dbb6-4db6-a210-7741667fa453.png">


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
@layer

# @layerを使用した詳細度の設計

```css
@layer a {
    div#sample span {
        color: red;
    }
}
@layer b {
    div span {
        color: green;
    }
}
@layer c {
    span {
        color: blue;
    }
}
```
このように記載した場合、@layerによってグルーピングされたレイヤー単位での記述順でスタイルが適用されるため、@layer cで記述されたスタイルが適用される

```css
@layer c,a,b;
@layer a {
    div#sample span {
        color: red;
    }
}
@layer b {
    div span {
        color: green;
    }
}
@layer c {
    span {
        color: blue;
    }
}
```
また、@layer c,a,bと優先順を指定することもでき、この場合@layer bが最優先となる


それらを応用し、scssファイルでスタイルを分割定義し、インポート再利用することも可能
```scss
@layer base {
  body {
    font-family: sans-serif;
  }
}

@layer components {
  .button {
    padding: 8px 16px;
    border: 1px solid black;
    background-color: white;
    color: black;
    &:hover {
      background-color: black;
      color: white;
    }
  }
}

@layer utilities {
  .hidden {
    display: none;
  }
}
```

```scss
@use 'styles' as styles;

.main-content {
  font-size: 16px;
  @extend styles.base; /* extends the base layer */
  .my-button {
    @extend styles.components.button; /* extends the components layer */
  }
  .is-hidden {
    @extend styles.utilities.hidden; /* extends the utilities layer */
  }
}
```
[memo] ffmpegでmp3をaacに変換

## 手順

### インストール

Homebrew で`libfdk_aac`に対応したffmpegをインストール
```zsh
$ brew tap homebrew-ffmpeg/ffmpeg
$ brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-fdk-aac
```

### 変換

```zsh
$ ffmpeg -i music.mp3 -vn -c:a libfdk_aac -vbr 4 music_vbr4.m4a
```

`-vn`オプションで映像を無視。

## 罠になりそうなポイント

* VBR(可変ビットレート)で変換する場合は`libfdk_aac`つきのffmpegが必要だが、標準では`libfdk_aac`はついていない模様。
* Homebrewで普通にffmpegを入れても`libfdk_aac`つきのものは入らない。
* 映像を変換しようとしてエラーが出る。`-vn`オプションで映像を無視する必要がある。  
  映像などないと思われるかもしれないがアルバムアートが映像扱いで埋め込まれている場合がある模様。


---
gistの記事の転載です:
https://gist.github.com/acevif/fa55e3e49134ec41ecfe77f11b9d2438
jruby + ActiveRecord + jdbc + mysql(mariadb）のミニマムサンプル

以下サンプルソース

``` file:Gemfile
source "https://rubygems.org"

gem 'activerecord'
gem 'activerecord-jdbcmysql-adapter'
```


```sample.rb
require "jdbc/mysql"
require "active_record"

ActiveRecord::Base.establish_connection(
  :adapter  => 'mysql',
  :url => 'jdbc:mysql://localhost:3306',
  :username => 'root',
  :password => '',
  :charset => 'utf8mb4',
  :encoding => 'utf8mb4',
  :collation => 'utf8mb4_general_ci'
)


# p ActiveRecord::Base.connection
pp ActiveRecord::Base.connection.execute("show databases")
```

### 実行方法

以下、Windows上での動作確認。PowerShellを前提とする

```
$ bundle exec jruby .\sample.rb
```

jrubyは予めインストールされている状態。

### 動作環境

```
$ jruby -v
jruby 9.4.2.0 (3.1.0) 2023-03-08 90d2913fda OpenJDK 64-Bit Server VM 11.0.12+7 on 11.0.12+7 +jit [x86_64-mswin32]
```

jrubyを入れた時点でbundleコマンドも一緒に入るみたい

```
$ gcm jruby

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     jruby.exe                                          1.0.0.0    c:\jruby-9.4.2.0\bin\jruby.exe
```
```
$ gcm bundle

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     bundle.bat                                         0.0.0.0    c:\jruby-9.4.2.0\bin\bundle.bat
```
venv による Python 仮想環境構築速習

## venv とは
venv とは Python 公式の仮想環境管理ツール。virtualenv という非常に似たツールがあるが、その一部を**公式として**切り出して取り込んだものが venv である。よって、類似の virtualenv, pyenv 等よりもよい体験、サポートが期待できる。

## Install
```bash:bash
$ sudo apt install -y python3-venv
```

## Usage
- 仮想環境を構築する
```bash:bash
# 仮想環境の置き場所を作る（名前は任意）
$ cd ~
$ mkdir .venvs
# 仮想環境を構築する
$ cd .venvs
$ python -m venv sampname
```
- 仮想環境に入る
```bash:bash
# 方法1
$ . ~/.venvs/sampname/bin/activate
# 方法2
$ source  ~/.venvs/sampname/bin/activate
```
- 仮想環境に各種パッケージをインストール
```bash:bash
# インストールされているパッケージを確認するコマンド（どちらでもよい）
$ pip list
$ pip freeze

# numpy をインストール
$ pip install numpy

# インストールされているパッケージを確認するコマンド（どちらでもよい）
$ pip list
$ pip freeze
```
- 仮想環境から抜ける
```bash:bash
# カレントディレクトリに依存しない
$ deactivate
```
- 仮想環境を破棄
```bash:bash
$ rm -rf ~/.venvs/sampname
```

## Tips
- Pytorch をインストール
  - [公式ページ](https://pytorch.org/get-started/locally/)からコマンドをコピーし貼り付ける
```bash:bash
# 例: Stable(2.0.0), Linux, Pip, Python, CPU 
$ pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
```

- wheel をインストール
  - japanize_matplotlib, torchviz をインストールする際に、**error: invalid command 'bdist_wheel'** というエラーが生じるため、先にこれをインストールしておくとよい
```bash:bash
$ pip install wheel
```
- 環境の複製（おひっこし）
```bash:bash
# requirements.txt に環境（パッケージ一覧）を書き出す
$ pip freeze > requirements.txt

# 新しい仮想環境で requirements.txt の内容を一括インストール
$ pip install -r requirements.txt

---

# cf. バージョン表記を削って書き出す（最新バージョンがインストールされるようになる）
$ pip freeze | cut -d= -f1 > requirements.txt
```

- PyTorch 事前学習済みモデルを用いる際、デフォルトでは .pth ファイルが~/.cache/torch/hub/checkpoints/ 配下に生成される
  - ファイル生成場所を変更したい場合は、環境変数 $TORCH_HOME を設定する等いくつか方法がある（「ダウンロードしたモデルはどこに保存されますか?」のセクションを参照）

https://runebook.dev/ja/docs/pytorch/hub

## ひと言
Anaconda は pip と競合するため、~~嫌いです~~あまり好きではありません。venv や Docker で環境を管理するのがよいと思います。ご清覧ありがとうございました。
LINEからシフト入力ができるLINEBotを作ってみた

初めまして！初投稿です。

## 自己紹介


私はスーパーマーケットのお惣菜部門でチーフをやっています。

今、世の中ではいろいろなものがデジタルに置き換えられており、
私の会社でも、その流れは来ています。

教育する立場でもある私がまずデジタルに触れて学んでみたい、
将来はさらに __デジタル化__ を推進する立場ありたい。

そのような思いから、デジタルを学んでいたときに、 __LINEBot__ に出会いました。

## 私の業務上の課題
私の業務の一つに __「シフト作成」__ があります。
この業務一つとっても、いろいろな問題があります。
例えば、
・希望公休を記入するためのシフト表を掲示したら、翌日になくなっていた（これは特殊かもしれません）
・希望公休をExcelに転記する作業が時間がかかる、ミスがおきる
・パートさんが希望公休を書くためだけに、休日にお店に来る
      
など。

このような問題を解決する __LINEBot__ に挑戦してみました！

## 使用するツール

・LINE
・Make
・Google スプレッドシート
・Google フォーム

## 完成したLINE画面はこちら
<blockquote class="twitter-tweet"><p lang="zxx" dir="ltr"><a href="https://t.co/SxNvJ4lL2G">pic.twitter.com/SxNvJ4lL2G</a></p>&mdash; さとう (@sato45287047196) <a href="https://twitter.com/sato45287047196/status/1641765162507173889?ref_src=twsrc%5Etfw">March 31, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/8ff6e552-5245-95df-e1d6-2d20c06f4ac5.jpeg"width=40%>
なにか文字を入力すると、次のアクションに誘導します。
 __公休入力__ と打つと、希望公休が入力できるGoogleフォームが表示されます。 
__締切日__ もこのときに知らせてくれます。

こちらは __Googleフォーム__ の画面です
<img src="(https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/586eb22b-9692-c3fc-ab1d-402c6f6fe2ec.jpeg"width=75%>
名前を選択した後、公休や有給が欲しい日にちにチェックをつけます。

入力した後は __シフト確認__ と打つと、自分を含め、回答者全員の希望公休が見れるスプレッドシートのURLが表示されます、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/75d4b495-1eaf-aee4-eebf-4dcad0dab233.jpeg"width=40%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/9d04fb8a-22a1-e7e9-2db3-55a0cb173d30.jpeg" width=40%>

このスプレッドシートは希望公休が反映された __シフト表__ としてそのまま活用できるので、シフト作成者の作業負担軽減にも繋がります。

## こちらがMAKEのシナリオです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/fbacbccb-5c54-f0df-3d5a-cfdfe554b09c.png"width=75%>

今回は  __Google Sheets__ の __Serch Rows__ を使用しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/dd2c2b03-330a-75d9-b319-a397334b224b.png"width=75%>

シート上のA列のキーワードがLINEで入力されると、B列、C列のキーワードが返ってくる仕組みにしました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/d265ba47-1fc3-044e-8184-68581d422afb.png"width=75%>

LINE上でキーワード以外のテキストを入力すると、指定のテキストが返ってくるように設定しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/7cc53cd3-a20b-80f7-3212-efe5d510e76b.png"width=75%>

一連の流れをフロー図にするとこのようになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294174/2f97735f-9bc4-87a9-d4d6-76a0f8c42c3f.png"width=75%>

## あとがき
初めは「このキーワードを入力すると、このキーワードを返してくれる」という仕組みもわからず、Youtubeやブログ記事など、いろいろなコンテンツから情報収集するところからだったので、苦労しました。また、最初はLINE上で日付を入力すると、スプレッドシートに希望公休が反映されるということをしたかったのですが、技術上厳しく、Googleフォームを活用するなど、やりたいことのゴールは変えず、手段を色々変えながら作成するのは、大変でしたが、 __ゴールにだんだん近づいていく感覚は感動的でした。__  今後はUIの改善や、さらなる自動化を目指していきたいです。
【全3回】AWSで静的サイトを公開する　③HTTPSで公開

第1回でドメイン取得
https://qiita.com/mugihara/items/551e7b0d2367400e1ed3

第2回でHTTP接続まで行いました
https://qiita.com/mugihara/items/e9db47aebbd72a7d4a96

今回でHTTPSでサイト公開を完了させます。

SSL/TLS証明書を発行する

<b>SSL/TLS証明書</b>とは
ウェブサイトとユーザーのブラウザ間の通信を暗号化するために使用されるデジタル証明書のこと。
現在のプロトコルはTLSであるが、現場では慣例的にSSL証明書と呼ばれることも多い。
証明書発行局（Certificate Authority, 通称CA）で発行されており、通信が暗号化されていること、ウェブサイトが信頼できるものであることをユーザーに示せる。

1.ACMで「証明書をリクエスト」をクリック
![スクリーンショット (143).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/169e2179-75fa-780d-483f-2d351725d169.png)

2.「パブリック証明書をリクエスト」にチェックし次へ
![スクリーンショット (144).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/c419d2b2-b289-2b36-8790-33bca12a5640.png)

3.ドメイン名を入力、検証方法は「DNS検証」を選択、キーアルゴリズムは「RSA2048」を選択して「リクエスト」クリック
![スクリーンショット (145).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/50212a5e-0eda-7257-804c-5d2dc799a509.png)

4.検証が完了するとこのような画面になるので確認します。
![スクリーンショット (147).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/cebb6ac7-6821-d9e6-48ac-9bcbf3c1ce73.jpeg)

5.CloudFrontへアクセスして「CloudFrontディストリビューションを作成」をクリック
![スクリーンショット (148).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/a873c867-1c01-f6ed-0746-265675992ba8.png)

6.オリジンドメインに（前回のS3の静的ウェブサイトホスティングのバケットウェブサイトエンドポイントのURLの「http://」を除いた部分）を入力、名前は自動で入力される。ドメイン名を入力。カスタムSSL証明書はACMで作成したものを選択。「ディストリビューションを作成」をクリック。
![スクリーンショット (149).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/4f1633c8-e8fd-94e8-0923-6fc5aa6b9593.png)
![スクリーンショット (150).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/160cd7be-c31b-400e-5211-179103925373.png)

7.ディストリビューションが作成されたことを確認。
![スクリーンショット (151).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/08d95b3b-5925-03f4-6cbd-e5d65bebe327.jpeg)

8.Route53に移動し「レコードを作成」をクリック。レコード名に「wwwを入力」。レコードタイプは「CNAME」に設定し、値は7の「ディストリビューションドメイン名」を入力する。「レコードを作成」をクリック。
![スクリーンショット (152).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3276718/79ad849d-12e7-abda-d7bc-961c8995c501.jpeg)

9.しばらく待って、ステータスが有効になったら完了です。

サイトが見れるようになりました！

https://www.owl-light.net/
CSS Selectors Level 4 後半

# CSS Selectors Level 4について

## :scope
:scopeは現在のスコープ内でマッチする要素を指定するための擬似クラス
通常JavaScriptで作成されたシャドウDOMに使用します

例えば、以下のようなHTMLがある場合
```html
<div id="example">
  <h1>Example</h1>
  <p>Some text here.</p>
</div>
```
```css
#example h1 {
  color: red;
}
```
JavaScriptを使用して#example要素内にシャドウDOMを作成し、h1要素を含める場合、上記のCSSではh1要素に適用されない
これを回避するために:scopeを使用してスコープ内で要素を選択する
```javascript
const shadowRoot = document.getElementById('example').attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
  <h1>Example</h1>
  <p>Some text here.</p>
`;
```
```css
#example :scope h1 {
  color: red;
}
```


## :focus-visible
:focus-visibleは要素がフォーカスを受け取っている場合にスタイルを適用するためのCSS擬似クラス
:focusと似ているが:focus-visibleは要素がキーボード以外の入力方法によってフォーカスを受け取った場合は適用されない

タブキーを使用してフォーカスを移動した場合にのみスタイルを適用したい場合は:focus-visibleを使用する

```css
input:focus-visible {
  box-shadow: 0 0 0 3px rgba(0, 0, 255, 0.5);
}
```

## :focus-within
:focus-withinは要素内の子孫要素がフォーカスされた時にスタイルを適用するための疑似クラス

```html
<div class="container">
  <label for="input">Name:</label>
  <input id="input" type="text" name="name">
</div>
```
```css
.container:focus-within {
  border: 1px solid blue;
}
```
この場合、子要素であるinputがフォーカスされた時にdiv.containerにborder: 1px solid blueのスタイルが適用される

また、以下のようにinputにフォーカス時に別の子要素にスタイルを当てる使い方も可能
```html
<div class="container">
  <label for="input">Name:</label>
  <input id="input" type="text" name="name">
</div>
```
```css
.container:focus-within label {
  border: 1px solid blue;
}
```

## :has()
指定したセレクタを内包する要素にスタイルを適用

```css
div:has(p) {
  background-color: yellow;
}
```
子要素にpを持つdivに対し黄色の背景色を付けるという意味になる

```css
div:has(:not(p)) {
  background-color: yellow;
}
```
逆にpを持たない（p以外の何かを持つ）divに対してスタイルを適用できる
組み合わせにより複雑な設定も可能

## :lang()
:lang()は要素の言語属性に基づいてスタイルを適用するための擬似クラス
`<p lang="en">`と`<p lang="ja">`で異なるlang設定されている場合にそれぞれスタイルを適用することが可能

```css
p:lang(ja) {
  color: red;
}

p:lang(en) {
  color: blue;
}
```
前方一致・後方一致の設定方法について

:lang(ja)はlang="ja"だけでなく、lang="ja-JP"やlang="ja-Hira"などの要素にもスタイルを適用

:lang(|-ja)はlang="ja"だけでなく、lang="en-US-ja"やlang="zh-TW-Hant-ja" などの要素にもスタイルを適用

```css
:lang(ja) {
  color: red;
}
:lang(|-ja) {
  color: red;
}
```
【Node.js】今更ながらSlackでChatGPTアプリを作ったよ

Slack公式のChatGPTのアプリがあるのにも関わらず、
今更ですが、SlackでChatGPTアプリを作りました。


### SLACKアプリ作成

こちらの記事を見て作成する。
https://qiita.com/tatsuya1970/items/e45af6b4b2131979b940

## OpenAI 

OpenAIのページへ
https://openai.com/api/

[Get Started]
[![Image from Gyazo](https://i.gyazo.com/6b2bc6c20e7467e0b392f6138076bcd5.png)](https://gyazo.com/6b2bc6c20e7467e0b392f6138076bcd5)

"Verify you are human"と表示されたら、ボタンをクリックする。
<img src="https://i.gyazo.com/62aa216cf79e091a80983bddb2f1d0b1.png" width="50%">


Log in
<img src="https://i.gyazo.com/c03a36c1c2c9abba34d5079a2c8225d2.png" width="50%">


メールアドレスをいれて、[Continue]
<img src="https://i.gyazo.com/7f826f448fbacd6fccf20d5701e1a21b.png" width="50%">


パスワードをいれて、[Continue]
<img src="https://i.gyazo.com/ba52b5a2cbe34935bc62f8e24001f4fb.png" width="50%">


こんな画面になる。
右上の「personal」をクリック
[![Image from Gyazo](https://i.gyazo.com/659725cd230ad8eb9592170400fdd20d.png)](https://gyazo.com/659725cd230ad8eb9592170400fdd20d)

「View API keys」をクリック
[![Image from Gyazo](https://i.gyazo.com/791759527f5cbe754908d1843858443a.png)](https://gyazo.com/791759527f5cbe754908d1843858443a)

「＋ Create new secret key」をクリック
[![Image from Gyazo](https://i.gyazo.com/5a197c7e5f90e9fa09d760af46df7d63.png)](https://gyazo.com/5a197c7e5f90e9fa09d760af46df7d63)

APIキーが生成される。
下図の緑色のコピーボタンを押して、「OK」
[![Image from Gyazo](https://i.gyazo.com/fa767b8ec9332afeab213f55584ef127.png)](https://gyazo.com/fa767b8ec9332afeab213f55584ef127)

このAPIキーをファイル「.env」にペーストする。

```.env
OPENAI_API_KEY="OpenAIのAPI"
SLACK_SIGNING_SECRET="SlackのSigning Secret"
SLACK_BOT_TOKEN="SlackのBot User OAuth Token"
```

ターミナルで OpenAIのパッケージをインストールする

```
$ npm install openai
```


コードは以下

``` index.js
'use strict';

require("dotenv").config();

const { Configuration, OpenAIApi } = require("openai");

const configuration = new Configuration({
    apiKey: process.env.OPENAI_API_KEY,
});

const { App } = require('@slack/bolt');

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET
});

//メッセージが投稿された時に呼ばれるメソッド
app.message(async ({ message, say }) => {

  const openai = new OpenAIApi(configuration);

  const completion = await openai.createChatCompletion({
    model: "gpt-3.5-turbo",
    messages: [{ role: "user", content: message.text  }],
  });
     
  const res = completion.data.choices[0].message.content;
  await say(res);
});

//アプリが起動時に呼ばれるメソッド
(async () => {
  await app.start(process.env.PORT || 3000);
  console.log('⚡️ Bolt app is running!');
})();

```

<br>
Slackおよびサーバーの設定をした後、
Slackで呟くと、ChatGPTが反応します。

※Slackおよびサーバーの設定はこちらをご参照
https://qiita.com/tatsuya1970/items/e45af6b4b2131979b940


[![Image from Gyazo](https://i.gyazo.com/9a26f245a0c6dfedf745805f4bd6c627.png)](https://gyazo.com/9a26f245a0c6dfedf745805f4bd6c627)

<br>
以上です。
PythonでのClosure

標記を使う機会がありましたので、残しておきます

使った理由は、Exceのカラム番号を定数にセットする際に、1つ1つ指定するのが辛いのと、
間違えていた場合の精神的ダメージ、工数的ダメージが大変大きかったからです

Qiitaを見るレベルの方だと、細かい説明はいらないと思いますので、コードと使い方のみ残します


```closure.py
def base(num: int):
    outer_num = num
    def inc():
        nonlocal outer_num
        outer_num += 1
        return outer_num
    return inc

counter = base(0)
NAME_COL = counter() # return 1
ADDRESS_COL = counter() # return 2

counter = base(10)
TEL_COL = counter() # return 11
```


ポイントは[nonlocal](https://docs.python.org/ja/3/reference/simple_stmts.html#the-nonlocal-statement)で、1つ上の階層のf_aを指定するところでしょうか
このnonlocalがないと、
>`local variable 'f_a' referenced before assignment

 で怒られてしまいます

この記事がどなたかのお役に立つと嬉しく思います
WindowsでSLコマンドをビルド(sl.exe)

Qiita初投稿

[SLコマンド](https://ja.wikipedia.org/wiki/Sl_(UNIX))をWindowsで実行できるようにしました(WSLでじゃなくて`sl.exe`をビルドした)。
ただビルドするだけと思いきやWindowsでは`curses`というライブラリが使えないので、`pdcurses`というライブラリで代用しました。
# 必要なもの
Chocolateyで全部入ります
- GCC
- Make
- Git
# 流れ
- gitでclone
- pdcursesをビルド
- ファイルを少し編集
- slをビルド
- 完
# リポジトリをクローン
```bash
git clone https://github.com/mtoyoda/sl
cd sl
git clone https://github.com/wmcbrine/PDCurses
```
# PDCursesをビルド
出来上がる`pdcurses.a`を`libncurses.a`にリネームしておきます。`n`に注意しましょう。
```bash
cd PDCurses/wincon
make
rename pdcurses.a libncurses.a
cd ../.. # sl.cがあるディレクトリへ戻る
```
# Makefileを編集
slディレクトリ直下の`Makefile`の9行目の`CFLAGS`を編集して、ヘッダファイルとさっきのビルドしたやつを参照させます。
```bash:sl/Makefie
# ----- before -----
CFLAGS=-O -Wall
# ----- after  ----- 
CFLAGS=-O -Wall -I./PDCurses -L./PDCurses/wincon
```
# 仕上げ
slディレクトリ直下において、
```bash
make
```
これで`sl.exe`ができました!
![スクリーンショット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1570746/21ddfde5-7490-07ec-0e26-17c6ff921109.png)
Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「Azure Files共有の管理」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure Files共有の管理」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure でのストレージの実装と管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-storage/)
◇対応するモジュール
[Azure Files 共有を管理する](https://learn.microsoft.com/ja-jp/training/modules/configure-azure-files-file-sync/3-manage-file-shares)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「ファイル共有やBLOBデータのためのストレージ比較」](https://qiita.com/fsd-jume/items/e272f42e72629f1cba72)

## Azure Files共有の管理
### Azure Files共有使用時の考慮事項
・Azure Files共有はストレージアカウントにデプロイされる

**◆ポート445を開く**
・SMBプロトコルはTCPポート445経由で通信
⇒ポート445に関する下記を確認
　-ポート445が空いていること
　-FWでクライアントからのTCPポート445がブロックされていないこと

**◆安全な転送を有効にする**
・`Secure transfer required`設定でストレージアカウントのセキュリティ強化
⇒ストレージアカウントへの要求をセキュリティで保護されたもののみに制限
・安全な転送が有効になっている場合はHTTPSによる接続が必要
⇒HTTPでアカウントに接続すると接続は拒否

### Azure Files共有のマップ
**◆Windows**
・Azure PortalでWindows/Windows Serverに接続可能
・共有をマップするドライブを指定し、認証方法を選択
⇒実行するPowerShellコマンドが提供

**◆Linux**
・LinuxマシンでAzure Files共有への接続も可能
⇒CIFSカーネルクライアントを使用してマウント可能
・ファイルマウントの実行方法
　-`mount`コマンドを使用してオンデマンドで実行
　-`/etc/fstab`にエントリを作成することで起動時に(永続的に)実行

## 次の学習内容
**◆ファイル共有スナップショット**
次回の投稿が完了したらリンクをこちらに掲載します。

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3