OmniAICreator/Qiita-1.07M huggingface dataset:
【Ruby on Rails】データ変更前の値を取得する

# 概要
レコードの更新前後に、あるカラムにおける変更前の値を取得したい場面って結構ある気がするので、そんな時に使える方法を調べてみました。

## changesメソッド
changesメソッドは、Active Recordモデルの属性の変更内容を返すメソッドです。このメソッドを呼び出すと、属性の変更前後の値がハッシュとして返されます。キーは属性名で、値は変更前後の値の配列です。

```
# ユーザーモデルの名前属性を変更する例

user = User.find(1)
puts user.name
# => "Alice"

user.name = "John"

puts user.changes
# => { "name" => ["Alice", "John"] }
```

## attribute_in_databaseメソッド
attribute_in_databaseメソッドは、データベースに保存されている属性の値を返すメソッドです。このメソッドを呼び出すと、属性の現在のデータベース上の値が返されます。

```
# ユーザーモデルの年齢属性のデータベース上の値を取得する例

user = User.find(1)
puts user.age
# => 29

user.age = 30

puts user.attribute_in_database(:age)
# => 29

# {column_name}_in_databaseでも同様の結果が得られる
puts user.age_in_database
# => 29
```
上記の例では、Userモデルのage属性が変更されました。attribute_in_databaseメソッドを呼び出すことで、現在のデータベース上のage属性の値である29を取得することができます。

## previous_changesメソッド

previous_changesメソッドは、dbに保存した後に直前の変更内容を返すメソッドです。

```
# ユーザーモデルのステータス属性を変更する例

user = User.find(1)
puts user.status
# => "active"

user.status = "inactive"
user.save

puts user.previous_changes
# => { "status" => ["active", "inactive"] }
```
上記の例では、Userモデルのstatus属性が変更されました。変更では"active"から"inactive"に変更されました。previous_changesメソッドを呼び出すことで、db更新後に直前の変更の内容を取得することができます。


## attribute_before_last_saveメソッド
attribute_before_last_saveメソッドは、Active Recordモデルの属性が最後に保存される前の値を返すメソッドです。このメソッドを呼び出すと、属性の最後の保存前の値が取得できます。

以下にサンプルコードと使い方の説明を示します。

```
# ユーザーモデルの名前属性を変更して保存する例

user = User.find(1)
puts user.name
# => "John"

user.name = "Alice"
user.save

puts user.attribute_before_last_save(:name)
# => "John"

# {column_name}_before_last_saveでも同様の結果が得られる
puts user.name_before_last_save
# => "John"
```
上記の例では、Userモデルのname属性が変更されて保存されました。attribute_before_last_saveメソッドを使用して最後の保存前の値を取得しています。結果として、最後に保存される前のname属性の値である"John"が取得されます。

## セッターのオーバーライド
セッターメソッドのオーバーライドでも、変更前の値を取得することができます。
```
class User < ApplicationRecord
    def name=(*)
        @name_before_changed = name
        super
    end
end
```
セッターをオーバーライドしてインスタンス変数に変更前の値を入れておくことで、変更前の値を保持しておくことも可能です。(あまりイケてる感じはしませんが、、)

## gemを利用する
バージョン管理のgem（例：paper_trail）を使用すると、モデルの変更履歴を管理し、変更前の値を簡単に取得できます。具体的な使用方法はジェムによって異なりますので、各ジェムのドキュメントを参照してください。
UiPath初心者向け：クリックや文字入力がシステム、サイトとの相性が悪い場合について(待機、要素の検出)

# 1,はじめに
UiPathを始めた頃にUI操作で躓いたことがあったので、それを初心者の方でもわかりやすいようにまとめてみました。
# 2,システム、サイトとの相性が悪いとは
:::note warn
「文字を入力アクティビティはすべて機能しているのに、入力したことがシステムに情報が反映されない」などを指します。
:::
:::note alert
実務ではUiPathとの相性が悪いシステム、サイトは常にあると思った方がいいです。
:::

# 3,このような場合の対処法として、待機アクティビティを利用する。
:::note info
基本的には、**クリック後のロード待ち、サイトを開く、サイトの移動**などで待機アクティビティを使用します。
:::

実務ではシステムと相性が悪いときに、**「待機アクティビティ」** を使うことで、入力したことを認識してくれることがあります。
基本的な使い方も含めて、待機アクティビティについて説明します。

# 4,待機アクティビティは、2つ存在していて、場面によって使い分けます。
:::note info
**(1)「待機」アクティビティ**
「クリック後のロード待ち」や「文字を入力後、数秒の指定したい」ときに使用する。
:::

![待機.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/8ee0cbc2-cb82-2676-7cac-74c1d41b8d60.png)

:::note warn
**このアクティビティは、指定した時間分、待機するものです。**
:::

Studioのバージョンが新しいので、アクティビティの表示が異なると思います。
実務の場合は、「待機」とアクティビティを検索すれば、出てくると思います。
今回の場合は、待機=DelayのDeだけで検索結果に出てきました。
私は文字を入力アクティビティがシステム、サイトにときにこの待機アクティビティを使い、5秒待機させます。

:::note info
**(2)「要素の存在を確認」アクティビティ**
「サイトを開く」、「サイトの移動」、「文字を入力後、反映後に何かポップアップやメッセージが出力される」ときに使用する。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/13862a9b-28c8-fa73-336b-8cf59a80fd36.png)

:::note warn
**このアクティビティは、基本的に時間の指定はしなくてよくて、ある要素(例えば、アイコンやポップアップなど)が現れるまで、待機するものです。**
:::

プロパティのタイムアウト(ミリ秒)について、
このアクティビティが完了するまでの待機する時間です。
何も入力しなければ、**30秒待機します。**

しかし、待機に30秒以上かかるシステムもあると思います。
そのときは、待機時間を入力します。
例として、60000を入力していますが、入力ミスではありません。
アクティビティの仕様で、**60000=60秒**のことを指します。
ここは注意してください。

次に存在の有無について、これはきちんと指定した画面が出たかを変数に格納してチェックしたいときに使います。
この時の変数は、**Boolean型**です。

私は文字を入力アクティビティ後に、ポップアップなどが出てくるときに、
よく使っています。

## 5,練習問題
:::note info
**ドロップダウンリストのとき、「項目を選択」アクティビティ？**
:::

いつもなら「項目を選択」アクティビティでやりたいんですが、
それができないシステムもあると思います。
その場合、どう対処しますか？

例えば、
　対象のドロップダウンリストを「クリック」
→ドロップダウンリスト一覧が出るまで5秒「待機」
→ドロップダウンリストが確実に出たことを確認するために、「要素の存在を確認」
→選択したいものを「クリック」
などがありますね。

# 6,最後に
今後もこのような記事を書いていくので、困っている方の助けになればいいなと思っています。
iTerm2でホットキーを割り当てて現在いるスクリーンにウィンドウを表示する方法

毎回忘れてしまうので・・・

## ホットキーウィンドウの設定

Preferences > Keys > Hotkey
から、`Create a Dedicated Hotkey Window`を選択

## 現在カーソルがあるウィンドウで開く設定

Preferences > Profiles > プロファイルを選択 > Window > Screen > Screen with Cursor

以上で、現在いるスクリーンにiTerm2のウィンドウが表示されるようになりました！ :tada:
テスト97

```vb

Sub Excel_SQL_JOIN2()
'-----------------------------
'参照設定
'Microsoft ActiveX Data Objects 6.1 Library

'Excel内で2つのシートを使って右外部結合と
'左外部結合をするためのサンプルSQL....〆('ω' )
'-----------------------------
Dim CN As ADODB.Connection
Dim RS As ADODB.Recordset
Dim MyPath As String
Dim i As Long
Dim sh_Main As Worksheet
Dim sh_Data1 As Worksheet
Dim sh_Data2 As Worksheet
Dim sh_chk As Worksheet
Dim Last_Row1 As Long
Dim Last_Row2 As Long

Set CN = New ADODB.Connection
Set RS = New ADODB.Recordset

MyPath = ThisWorkbook.FullName

CN.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
               "Data Source=" & MyPath & ";" & _
               "Extended Properties='Excel 12.0;HDR=YES' "

With ThisWorkbook

    Set sh_Main = .Sheets("メイン")
    Set sh_Data1 = .Sheets("テストデータ1")
    Set sh_Data2 = .Sheets("テストデータ2")
    Set sh_chk = .Sheets("チェック")
    
End With

sh_Data2.Cells.Delete
sh_Data1.Cells.Copy Destination:=sh_Data2.Cells

'最終行取得
Last_Row1 = sh_Main.Cells(Rows.Count, "A").End(xlUp).Row
Last_Row2 = sh_Data2.Cells(Rows.Count, "A").End(xlUp).Row

'左外部結合
Set RS = CN.Execute("SELECT DISTINCT A.商品コード, B.商品コード " & _
                                  "FROM [メイン$A1:B" & Last_Row1 & "] AS A " & _
                                  "LEFT OUTER JOIN [テストデータ2$A1:B" & Last_Row2 & "] AS B " & _
                                  "ON A.商品コード = B.商品コード")
i = 2

With sh_chk
    
    .Cells.Clear
    
    .Range("A1:B1").Value = Array("商品コード_メイン", "商品カテゴリコード_テスト")

    RS.MoveFirst

    Do Until RS.EOF
    
        .Cells(i, "A").Value = IIf(IsNull(RS.Fields(0)), "Null", RS.Fields(0))
        .Cells(i, "B").Value = IIf(IsNull(RS.Fields(1)), "Null", RS.Fields(1))

        i = i + 1
        RS.MoveNext
    
    Loop

End With


'右外部結合
Set RS = CN.Execute("SELECT DISTINCT A.商品コード, B.商品コード " & _
                                  "FROM [メイン$A1:B" & Last_Row1 & "] AS A " & _
                                  "RIGHT OUTER JOIN [テストデータ2$A1:B" & Last_Row2 & "] AS B " & _
                                  "ON A.商品コード = B.商品コード")

i = 2

With sh_chk
    
    .Range("D1:E1").Value = Array("商品コード_メイン", "商品カテゴリコード_テスト")
    
    RS.MoveFirst

    Do Until RS.EOF
    
        .Cells(i, "D").Value = IIf(IsNull(RS.Fields(0)), "Null", RS.Fields(0))
        .Cells(i, "E").Value = IIf(IsNull(RS.Fields(1)), "Null", RS.Fields(1))

        i = i + 1
        RS.MoveNext
    
    Loop
    
    .Columns("A:E").AutoFit
 
End With


Dim myRange As Range
Dim myFind As Range

Set myRange = sh_Data1.Columns("A")

With sh_Main
    '最終行取得
    Last_Row1 = sh_Data1.Cells(Rows.Count, "A").End(xlUp).Row
    
    For i = 2 To Last_Row1
    
        Set myFind = myRange.Find(What:=Trim(.Cells(i, "A").Value), _
                                    LookIn:=xlValues, _
                                    LookAt:=xlWhole, _
                                    MatchCase:=False)

        If Not myFind Is Nothing Then
        
            .Cells(i, "B").Value = Trim(sh_Data1.Cells(myFind.Row, "B").Value)
            
        Else
        
            .Cells(i, "B").Value = ""
            
        End If
    
    Next i

End With

Set RS = Nothing
Set CN = Nothing

MsgBox "処理が終了しました。", vbInformation

End Sub
ReactアプリをNetlifyにデプロイする備忘録

## React-router-domを使ったアプリをNetlifyにデプロイ
普通にデプロイするだけならいいけど、React-router-domを使ったReactアプリをデプロイしたときNetlifyでは「Page not found」と言われて怒られてしまう。これの解決に苦労したので備忘録を残しておこう。

### 「_redirects」ファイルをpublicフォルダ直下に配置する
たったこれだけです。では_redirectsファイルにはどのような記述をすればいいでしょうか。下記が記載するべきコードです
`/*    /index.html   200`
この記載をした_redirectsファイルをpublicフォルダー配下に置きましょう。
deviseを導入し、ログアウトするためのpath

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/fa15ed46-eb42-544c-8e4d-a56d39eba364.png)
1:rails routesコマンドを実行し、ログアウトのpathを確認し、viewのlink_toの中にdestroy_user_session_pathと記述する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/f34def12-0668-c6a0-8e25-0089fb373075.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/c657e300-e164-59b0-31a5-341a256864a7.png)
gem 'dotenv-rails'の使い方

## 1. はじめに

Ruby on Railsを使って開発を行う際、セキュリティの観点から公開すべきでない情報（APIキー、データベースのパスワードなど）を環境変数として扱うことが推奨されます。`dotenv-rails`は、環境変数を手軽に管理するためのgemです。

## 2. `dotenv-rails`のインストール

まずは、新しいまたは既存のRailsプロジェクトに`dotenv-rails`をインストールします。Gemfileに以下の行を追加します。

```ruby
gem 'dotenv-rails', groups: [:development, :test]
```

そして、ターミナルで`bundle install`を実行します。

## 3. `.env`ファイルの作成と設定

プロジェクトのルートディレクトリに`.env`ファイルを作成します。このファイルに環境変数を設定します。例えば、APIキーを環境変数として設定する場合、以下のように記述します。

```shell
MY_API_KEY=your_api_key_here
```

## 4. 環境変数の使用

環境変数は`ENV`オブジェクトを通じて参照します。例えば、上記で設定したAPIキーを参照するには以下のようにします。

```ruby
api_key = ENV["MY_API_KEY"]
```

## 5. 安全な管理

`.env`ファイルは重要な情報を含むため、公開リポジトリにチェックインすることは避けるべきです。`.gitignore`ファイルに`.env`を追加して、Gitのバージョン管理から除外します。

```shell
echo '.env' >> .gitignore
```

## 6. 開発環境と本番環境での環境変数の管理

開発環境と本番環境で異なる環境変数を設定する場合、それぞれ専用の`.env`ファイルを作成します。例えば、開発環境専用のファイルは`.env.development`とし、本番環境専用のファイルは`.env.production`とします。これらのファイルにそれぞれの環境で使用する環境変数を記述します。

## 7. トラブルシューティング

`dotenv-rails`の使用中に問題が発生した場合、以下の点を確認してみてください。

- `.env`ファイルがプロジェクトのルートディレクトリに存在しているか。
- `ENV["変数名"]`の"変数名"が`.env`ファイルに設定した変数名と一致しているか。
- `bundle install`を実行した後にRailsサーバーを再起動しているか。
GitLFSを使いたい時(Mac)



### 経緯
Githubでグローバルリポジトリ生成
GithubDesktopでクローン
...
作業
...
コミットしたら「100MB以上のファイルがあって無理」と言われた　←　今ここ
#### この場合はGitLFSを使いましょう

### やること１：SSHを使えるようにする
SSHキーを作ったことない人、または作ったか覚えてない人はここから↓
[既存の SSH キーの確認](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys)


Githubの対象リポジトリからSSHキーをコピーする
![スクリーンショット 2023-06-02 20.43.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2643266/7e85fd7b-8a72-3ce4-d782-51593f1b88d6.png)



ターミナルでクローンしたいローカルリポジトリに移動
移動後SSHを用いてクローン
~~~
git clone 先ほどコピーしたSSHキー
~~~

### やること２ （初めての人は）GitLFSをインストールする
Github公式ページを見ながらGitLFSをインストールしましょう
[Git Large File Storage をインストールする](https://docs.github.com/ja/repositories/working-with-files/managing-large-files/installing-git-large-file-storage)
brewがインストールされていればこれでOK↓
~~~
brew install git-lfs
~~~
brewがインストールされていない場合は以下の順番で実行
~~~
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
~~~
~~~
brew install git-lfs
~~~

### やること3 GitLFSを使ってグローバルリポジトリにpush
詳しいことはこちらで↓
[Git Large File Storage を設定する](https://docs.github.com/ja/repositories/working-with-files/managing-large-files/configuring-git-large-file-storage)

やること1でクローンしたディレクトリに移動
例えばpsdファイルが100MB以上あったら、
~~~
git lfs track "*.psd"
~~~
のように”git lfs track "*.フォルダの形式"で入力

特別なことはここで終わりです！あとは通常通りにpushするだけでできるはず...。
~~~
git add .
git push origin ブランチ名
~~~
Laravelの内部処理改善の為、コントローラー処理速度を測定する

### 始めに
システムのパフォーマンス改善を行う時に、数値でビフォー・アフターを見て、改善できたかを確認するのに、処理始まりと、処理の後で、どれくらい時間がかかっているか知りたい時に便利な方法です。

### 実装方法
調査するコントローラーのコンストラクタとデストラクタを使って、数行コードを入れるだけで簡単に数値を確認することが出来ます。

コンストラクタに、処理開始時の時間の値を取ります。
デストラクタに、処理終了時の時間の値を取ります。
それの差を求め、URLアクセスした場合に、実行したURL、かかった時間をLOGに出力するコードとなります。


``` php:App\Http\Controllers\Controller.php
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Log;

class Controller extends BaseController
{
    private $time_start;
    private $time_end;
    
    // コンストラクタ
    public function __construct()
    {
        $this->time_start = microtime(true); //実行開始時間を記録する
    }

    // デストラクタ
    public function __destruct()
    {
        $this->time_end = microtime(true);
        $time = $this->time_end - $this->time_start;
        Log::debug('実行ページ:'.url()->current().' 実行時間:'.$time.'秒');
        
    }


}

```

### 用途

以下のような時に、どれほどの効果があったかを確認するには、状況把握に数値を取りたいと思いました。
・PHPの処理で重いものを、軽くなるようにコードを書き直した時。
・データベースのインデックスを増やして、レスポンスを改善した時

ページ表示時に画像表示するまでの応答が長いケースは、内部処理のレスポンスが遅いと判断して、内部処理の改善する時に、数値を取って確認するには良いかと思います。

ECシステムやWebメディアなどは、ページビューが売上に相関性がありますので、大事な事と思います。
「Team Geek」を読んで刺さった心得

# はじめに
社内の部会にて「**無差別級の最強エンジニアを決めるための祭典**」と称してテックスキルとビジネススキルテストのようなものがありました。
その中で「**Team Geek**」についての出題があり、気になったので後日書籍を購入して読んでみました。
個人的に好きな内容の一部を記事にして共有させてもらいます！！

https://www.oreilly.co.jp/books/9784873116303/

あと、以前投稿した記事↓が思いのほか多くの方に見てもらえて、**チームビルディング**や**リーダーシップ**の記事の需要を感じたので、今回も多くの方の参考になれば幸いです！！

https://qiita.com/m_saito_ari/items/366f6850d5c1cf39c3ec


# Team Geekってどんな本？
Googleでエンジニアとして働いていた著者の体験談を交えながら、「**他人とうまくやるコツ**」や「**チームビルディング**」、「**有害な人への対処法**」などについて語っている本です。要所要所で**海外的な冗談**を交えながら話が進んでいくので、そこも面白いところです。

# 早い段階で、高速に、何度も失敗せよ
>**完成していないものを見られたら、何か言われるんじゃないかと本当に不安だ。細かいところまで見られて、バカだと思われないだろうか。**

おそらく開発者あるあるですよね？ローカルで作業をして未完成のものは誰にも見えない場所で作るという。

Team Geekにおいてはこれはタブーで「**隠したらダメになる**」と。

正しい方向に進んでいるのか、上手くいっているのかをチーム内で**早い段階で**共有しておくことはとても重要です。
「**目玉の数さえ十分あれば、どんなバグも深刻ではない**」ってやつで1人で抱えて仕事をすることはそれだけでリスクになるということですね。

また、早期にフィードバックを得ることができるのはそれだけ失敗のリスクを下げることにも繋がります。
「**早い段階で、高速に、何度も失敗せよ**」です。


# 優秀なチーム作りにはHRT
>**謙虚(Humility)**
世界の中心は君ではない。君は全知全能ではないし、絶対に正しいわけでもない。常に自分を改善していこう。
**尊敬(Respect)**
一緒に働く人のことを心から思いやろう。相手を1人の人間として扱い、その能力や功績を高く評価しよう。
**信頼(Trust)**
自分以外の人は有能であり、正しいことをすると信じよう。そうすれば、仕事を任せることができる。

優れたチームを作るためにはこの三本柱(通称：HRT)が大事で、これは人間関係やコミュニケーションを円滑に進めることができるそうです。

業務上のアドバイスをするのにも、相手に**尊敬**をもって接することで言葉選びが柔らかくなり、過度な摩擦を避けることができる。
アドバイスを受ける側も自身に**謙虚**でいることで、相手からの意見を柔軟に受け入れることができる。
お互いを自身に恩恵をもたらす存在であると**信頼**すること。
どれも大事なことですね。

# 船にはキャプテンが必要
>**「マネジメント」病の治療法は「サーバントリーダーシップ」である。マネージャーの役割として最も重要なのは、執事や召使いのようにチームに奉仕することだ。**

「ピーターの法則」によると多くの人は、無能なマネージャーの下についた経験があるそうです。
その経験を持った新人のマネージャーは「**管理したくなる衝動**」に駆られるケースが多く、これが悲惨な事態を招くとしています。(マネージャーなんだから「管理」しなきゃ！と思うのは当然だと思いますけどね…)

ここでいう悲惨な事態とは必要以上にマイクロマネジメントしたり、パフォーマンスの悪い人を排除したり、チームを破壊しかねない事態のことです。
そして、その治療法が「**サーバントリーダーシップ**」であり、チームに奉仕することが重要であるとしています。

サーバントリーダーの立場でHRT(謙虚・尊敬・信頼)の雰囲気を作りだし、時にはチームの方向性を示し、時にはチームメンバー間の人間関係を取り持ったりするのが、リーダーの役割なのですね。

>**チームをリードするときには、自分の考えを伝えて平静を保つことが重要である。なぜならチームは(意図するしないにかかわらず)君の反応や行動を見ているからだ。
その様子を把握するには、会社の組織図を歯車のように見ればいい。コードを書くエンジニアの歯車は小さくて歯が少ない。エンジニアの上司であるマネージャーもまた別の歯車だ。最終的にはCEOの歯車にたどり着く。これは最も大きな歯車であり、数百もの歯がついている。**

小さな歯車であるエンジニアに対し、**マネージャーは歯車が大きい為、周りへの影響が大きく出やすく**、それは組織図の上に行くほど大きくなっていきます。
マネージャーが1回転するうちにエンジニアの歯車は2回も3回も回ってしまうわけですよね。

これは非常事態になると如実に出てきてCEOやマネージャーが焦ると下のエンジニアにも不安や焦りが伝播して、悪い方向に物事が進むわけです。恐ろしいですね…

# 有害な人に対処する
>**普通の人たちを排除するようなエリート指向のフラタニティではなく、ネガティブなふるまいを拒否するような文化を作るほうが健全だ。排除するのはあくまで振る舞いであり、特定の個人ではない。**

※ここでいう「**有害な人**」というのは振る舞いが有害であることを指します。

その人自身を排除するのではなく、その**振る舞い**を排除するという考え方です。
よく言う「**人格否定ではなく、行動そのものを注意しなさい**」ってことに近いですね。

個人に対して「いい」、「悪い」というのは単純すぎる考えであり、**有害な振る舞い**を批判することが建設的で実践的であるとしています。




 
# おわりに
いかがだったでしょうか？
Team Geekには文化の醸成の仕方、後輩育成の心得など様々な観点で勉強になることが多いです。
有名な書籍ですが、未読の方はぜひ読んでみてください。
からのはいれつもんだい

# 空の配列問題
「**配列のすべての要素が条件を満たすならtrueを返す**」ってやつ。

このテーマがTwitterで盛り上がったときにすぐに手元でKotlinの `all` `any` `none` を読み直した。

**なるほど、たしかに！** と思ったが、 **true一択派**の圧がすごくて驚いた。



学生時代に少しかじったC言語ではどう書いていただろうか。

要素数が1以上でないときの処理は仕様による、

でも良いと思っていたが、**true一択**と言わなければセンス無しと判定されるようだ。

こんな風に書かなければならないのかな？

```c
#include<stdio.h>
#include <stdbool.h>


typedef struct {
    bool flagA;
} Item;


bool Items_IsAllA( Item items[] , int len ) {
  for ( int i = 0; i < len; i++ ) {
      if ( ! items[ i ].flagA ) return false;
  }
  return true;
}

int main() {
  Item items1[0];
  int len1 = 0;
  bool r1 = Items_IsAllA(items1, len1);
  
  Item items2[1];
  int len2 = 1;
  bool r2 = Items_IsAllA(items2, len2);
  
  Item items3[1];
  items3[0].flagA = true;
  int len3 = 1;
  bool r3 = Items_IsAllA(items3, len3);

  printf("r1=%d r2=%d r3=%d \n", r1, r2, r3);
  return 0;
}

// r1=1 r2=0 r3=1 
```

先生に、（上司や客に）
「なぜ **配列のすべての要素が条件を満たすならtrueを返す** という要求なのに、**一つでも条件を満たさない要素があればfalseを返して、それ以外はtrueを返す** という処理にしたのですか？」

と訊かれたらなんと答えればよいのだろうか。

「そんなの自明だし、こっちのほうが**センスがよい**からです。もっと**論理的・数学的思考**を身につけてください。」

と言うのだろうか。

それともこう書くべきなのかな？

```c

bool Items_IsAllA( Item items[] , int len ) {
  int trueCount = 0;
  for ( int i = 0; i < len; i++ ) {
      if ( items[ i ].flagA ) trueCount++;
  }
  return trueCount == len;
}

```



どちらにせよ　**自分と異なる考えを馬鹿にするメンタル** の人間は客前には出せないと考える経営者や営業マンは多いんじゃないかな。

客の定義にもよる？


### Twitterの反応

例え話で、

**「当店の女性従業員は全てノーパンです」という店にいったら従業員は全て男性だった**


というのがあって、良いい例えだと思ったし、面白かった。
たしかに店は**嘘は**ついていない。


---

「こんな時間にツイッターをやらないのが本当に良いプログラマ」

というツイートもあった。

**確かに!**
ソートされてないMultiIndexの列を持つDataFrameで、groupbyで演算すると`PerformanceWarning`が発生するときがある

# 環境
* Python 3.11.2
* pandas 2.0.2

# 起きたこと
列が`MultiIndex`で、列名がソートされていないDataFrameがあります。

```
In [474]: df = pandas.DataFrame({("x","a"):[1,2,3],("y",""):["a","b","b"],("x","b"):[5,6,7]})

In [481]: df
Out[481]: 
   x  y  x
   a     b
0  1  a  5
1  2  b  6
2  3  b  7
```

このDataFrameに対して列`"y"`をキーにして`groupby`で演算すると、`PerformanceWarning`が発生しました。

```
In [485]: tmp = df.groupby("y")

In [486]: tmp.sum()
<ipython-input-486-d2970d0aff60>:1: PerformanceWarning: dropping on a non-lexsorted multi-index without a level parameter may impact performance.
  tmp.sum()
Out[486]: 
   x    
   a   b
y       
a  1   5
b  5  13
```

「`level`引数なしでソートされていない"multi-index"を削除した」とみなされたようです。
明示的に列を削除している訳ではありませんが、[pandas.core.groupby.DataFrameGroupBy.sum](https://pandas.pydata.org/docs/dev/reference/api/pandas.core.groupby.DataFrameGroupBy.sum.html)関数から[pandas.DataFrame.drop](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop.html)関数が呼ばれていました。

具体的な関数呼び出しは以下の通りです。


[pandas.core.groupby.DataFrameGroupBy.sum](https://github.com/pandas-dev/pandas/blob/37783d4bcb9f5a75126f9d9a8b695cea73b2d39f/pandas/core/groupby/groupby.py#L2354) -> [pandas.core.groupby.DataFrameGroupBy._reindex_output](https://github.com/pandas-dev/pandas/blob/37783d4bcb9f5a75126f9d9a8b695cea73b2d39f/pandas/core/groupby/groupby.py#L4181) -> pandas.DataFrame.drop


# 対策
`groupby`に`"y"`ではなく`("y","")`を指定すれば、`PerformanceWarning`は発生しません。

```
In [476]: df.groupby(("y","")).sum()
Out[476]: 
       x    
       a   b
(y, )       
a      1   5
b      5  13
```


またメッセージ通り、列がソートされていれば`PerformanceWarning`は発生しません。

```
In [477]: df1 = pandas.DataFrame({("x","a"):[1,2,3],("x","b"):[5,6,7],("y",""):["a","b","b"]})

In [478]: df1
Out[478]: 
   x     y
   a  b   
0  1  5  a
1  2  6  b
2  3  7  b

In [480]: df1.groupby("y").sum()
Out[480]: 
   x    
   a   b
y       
a  1   5
b  5  13

```

# 補足
`groupby`に`"y"`を渡したときと`("y","")`を渡したときで、なぜ挙動が違うのかを教えてもらいました。

https://ja.stackoverflow.com/questions/95076/
registry設定によるマクロのブロック無効化方法

## はじめに
インターネットから取得したマクロを含むOfficeファイルは、マクロの実行がブロックされる仕様となっている。
これは、Mark of the Web(MOTW)がファイルに付与されユーザをマルウェア感染などから保護している。
といっても、業務上意図的にマクロを有効化するニーズはもちろんあるわけで、マクロ有効化の方法はMSのサイトにも公開されている。[^1]
その他の有効化手段として、registryの設定でもマクロのブロックの無効化が可能といった情報を知ったので、実際に試してみた。
[^1]: https://learn.microsoft.com/en-us/deployoffice/security/internet-macros-blocked#mark-of-the-web-and-zones

## registry設定値とその役割
こちらのサイト[^2]を参照に設定値とマクロのブロック機能が有効化されるのか無効化されるのか確認する。
* registry hive : HKEY_CURRENT_USER
* registry path : software\policies\microsoft\office\16.0\excel\security
* value : blockcontentexecutionfrominternet
* value type : REG_DWORD
* data : 1 (マクロのブロックが有効)
* data : 0 (マクロのブロックが無効)
[^2]: https://admx.help/?Category=Office2016&Policy=excel16.Office.Microsoft.Policies.Windows::L_BlockMacroExecutionFromInternet

## 実行環境
* OS : Windows 10
* Excel 2016

## 実行内容
### 下準備
マクロを含むexcelファイルを用意し、インターネット上からダウンロードする。
デフォルト状態のregistryの設定を確認したところ、該当する設定はなかった。

### デフォルト状態(レジストリに設定なし)でマクロのブロック状態を確認
用意したexcelを開き、メッセージの内容を確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/7752d289-4d0d-40ef-fcee-0400bd2da21a.png)
「編集を有効にする」を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/01bacc6a-603e-7c28-e995-b2bebf83621c.png)
マクロのブロックが機能していることが確認できる。

### マクロのブロックを無効化設定しマクロのブロック状態を確認
registryにマクロのブロックを無効化する設定を導入する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/b664388f-e1c3-c2e1-21f9-b42052151135.png)
用意したexcelを開き、メッセージの内容を確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/d43938d3-2b71-49c8-1972-abc0e0ac03b3.png)
「コンテンツの有効化」を押下すると、メッセージは何も表示されずマクロが実行できる状態になっていることを確認できる。

### マクロのブロックを有効化設定しマクロのブロック状態を確認
registryにマクロのブロックを有効化する設定を導入する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/17c7e5f6-422e-a1d0-db76-78670887c52d.png)
用意したexcelを開き、メッセージの内容を確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102676/3b08e3f4-109b-dcab-18ca-b8ed17287cde.png)

## まとめ
おおむね想定した通りにregistryの設定でマクロのブロックが無効化できることが確認できた。
しかしexcelで表示されるメッセージが細かく変化することは想定外だった。この変化は何がハンドルしているか気になるところ。
また、一般的なユーザがマクロのブロックを無効化する手段としては他の方法で事足りるため、registry設定でマクロのブロックを無効化する必要性はないように感じた。
そのため、社内で設定しているユーザがいればヒアリングなど事情の確認は必要だろう。

## 参考
* [Macros from the internet will be blocked by default in Office](https://learn.microsoft.com/en-us/deployoffice/security/internet-macros-blocked)
* [Block macros from running in Office files from the Internet](https://admx.help/?Category=Office2016&Policy=excel16.Office.Microsoft.Policies.Windows::L_BlockMacroExecutionFromInternet)
ファイルをbytesで読み込んで、plt.show()可能なnumpy形式までの変換を丁寧にみていく

## 記事の目的
f.readで読み込んでからのファイル形式の理解が深まる

## 準備するもの
画像データを適当にとってきて、filename = のところを書き換えたら使えます

```python
import matplotlib.pyplot as plt
import numpy as np
import cv2 


# 型確認のための汎用メソッド
def showDetail(obj,name):
    obj_type = type(obj)
    print(f"type({name})",obj_type) 
    if obj_type == np.ndarray:
        print(f"{name}.shape",obj.shape) 
    
filename = 'images/testImage.jpg'

# Read image into memory
payload = None
with open(filename, 'rb') as f:
    payload = f.read()
showDetail(payload,"payload") # type(payload) <class 'bytes'>

frombuff = np.frombuffer(payload, dtype='uint8') # byteをnumpyにしている(1次元)
showDetail(frombuff,"frombuff") # frombuff.shape (3002800,)

input_data = cv2.imdecode(frombuff, cv2.IMREAD_UNCHANGED) # numpyを画像の形式にdecodeしている。
showDetail(input_data,"input_data") # input_data.shape (2565, 3500, 3)


plt.imshow(input_data) 
plt.show()

```
AWS Lambda(Go)で複数のイベントからリクエストを受け取る方法

日本語の記事などが一つもなかったので備忘録も兼ねて

# 結論
Lambdaはジェネリクス型では対応できないため、reflectを使用する（一つのLambdaのみで対応する場合）

# 実装

```
// go version 1.19
package main

import (
	"context"
	"fmt"
	"reflect"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type TestEvent struct {
	events.SNSEvent
	events.APIGatewayProxyRequest
}

func mixHandler(context context.Context, event TestEvent) {
	switch {
	case !reflect.DeepEqual(event.SNSEvent, events.SNSEvent{}):
		// SNSの処理
	case !reflect.DeepEqual(event.APIGatewayProxyRequest, events.APIGatewayProxyRequest{}):
		// APIGateWayの処理
	default:
		fmt.Println("こちらは不明のリクエストを受け付けています。")
		logStr := fmt.Sprintf("%+v", event)
		fmt.Println(logStr)
		valueType := reflect.TypeOf(event)
		fmt.Println(valueType)
	}
}

func main() {
	lambda.Start(mixHandler)
}
```

# 解説
Lambdaにリクエストする予定のイベントの型を定義
（今回のケースだと、API GatewayとSNS）
```
type TestEvent struct {
	events.SNSEvent
	events.APIGatewayProxyRequest
}
```

reflect.DeepEqualで構造体比較をして、値が入っていれば処理に移る
```
switch {
	case !reflect.DeepEqual(event.SNSEvent, events.SNSEvent{}):
		// SNSの処理
	case !reflect.DeepEqual(event.APIGatewayProxyRequest, events.APIGatewayProxyRequest{}):
		// APIGateWayの処理
	default:
		fmt.Println("こちらは不明のリクエストを受け付けています。")
		logStr := fmt.Sprintf("%+v", event)
		fmt.Println(logStr)
		valueType := reflect.TypeOf(event)
		fmt.Println(valueType)
	}
```

以上です。

# おまけ（ジェネリクス型を使った失敗）
```
package main

import (
	"fmt"
	"reflect"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type TestInterface interface {
	events.APIGatewayProxyRequest | events.SNSEvent
}

// ジェネリクス型
func mixHandler[T TestInterface](event T) {
	switch (interface{})(event).(type) {
	case events.SNSEvent:
		fmt.Println("こちらはSNSからのリクエストを受け付けています。")
		logStr := fmt.Sprintf("%+v", event)
		fmt.Println(logStr)
	case events.APIGatewayProxyRequest:
		fmt.Println("こちらはAPI Gatewayからのリクエストを受け付けています。")
		logStr := fmt.Sprintf("%+v", event)
		fmt.Println(logStr)
	default:
		fmt.Println("こちらは不明のリクエストを受け付けています。")
		logStr := fmt.Sprintf("%+v", event)
		fmt.Println(logStr)
		valueType := reflect.TypeOf(event)
		fmt.Println(valueType)
	}
}

func main() {
	lambda.Start(mixHandler)
}

```

こんな感じでジェネリクス型を定義して、受け取ったイベントをswitchで型判別して処理する方法を最初行おうとしていました。
ただ、 `lambda.Start(mixHandler)` で　`cannot use generic function mixHandler without instantiation`エラーが発生して断念しました。
（ジェネリクス関数を使用する時はインスタンス化して使用しないといけないため、Lambdaでは使用できない）
※使用できる方法などあれば教えていただきたいです。
```
    // これは使用可能
	t := events.SNSEvent{}
	mixHandler(t)
```
JetpackCompose TextViewの文字間隔を変更する

JetpackComposeで文字と文字の間のスペースを変更しようと思います。
あまり使用しないので、忘れてしまう前に残しておきます。

```.kt
Text(
    modifier = Modifier.padding(top = 10.dp),
    style = androidx.compose.material3.Typography().headlineLarge,
    letterSpacing = 24.sp,
    text = "文字間隔"
)
```

![Screenshot_20230602_172607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/63346d70-b100-b9b2-de70-235978fc46bf.png)

``letterSpacing``を設定してあげると変更できるので必要がある際は試してみてください。
Rの勉強記事まとめ

# はじめに
最近、研究関係でRを使う機会が多いのですがPythonに比べると勉強するための文献があまり見つからず、書籍に関してはほぼほぼなくなってきた印象です。
一方で、Rはwebで公開されている内容は多く、勉強するにはwebを参照しないといけないような状況に感じましたため、備忘録も兼ねて個人的に勉強になった記事をまとめてみました。

# Rで計量政治学入門
タイトルには計量政治学とありますが、記載されている内容は政治学に限られたものでなく、前処理から地理情報の可視化、環境構築まで、日本語でのR入門として非常に勉強になる内容です。

https://shohei-doi.github.io/quant_polisci/


# 疫学や公衆衛生に関わる業務のための R
前処理や可視化がかなり手厚く、はじめてRに取り組むにはかなり勉強になります。

https://epirhandbook.com/jp/index.html

# Bayesian Analysis in R

Stanを使ったベイズ分析について。

https://marissabarlaz.github.io/portfolio/bayesian/

# Ecological Statistics

環境統計

https://fukamilab.github.io/BIO202/

# Geocomputation with R
地理情報を可視化する技術について。

https://r.geocompx.org/

# Geospatial Health Data: Modeling and Visualization with R-INLA and Shiny
地理空間情報の可視化とダッシュボード開発まで。shinyでの可視化まで触れているのは非常に勉強になります。

https://www.paulamoraga.com/book-geospatial/

# Visualising WRC Rally Stages With rayshader and R

空間の分析などでは、地形情報をプロットするために3Dの可視化などを使う機会がありますが、rashaderを使って、3Dで地形情報やラリーコースのプロットについて解説されています。

https://rallydatajunkie.com/visualising-rally-stages/index.html

# Surrogates
ガウス過程を用いたサロゲートモデル。

https://bookdown.org/rbg/surrogates/



# Deep Learning and Scientific Computing with R torch
TorchのRでの実装の仕方。

https://skeydan.github.io/Deep-Learning-and-Scientific-Computing-with-R-torch/

# みんなのRcpp
Rcppについて。

https://teuder.github.io/rcpp4everyone_ja/

# GPU Computing with R
RでのGPU処理について。

https://jaredlander.com/content/2021/09/GPUComputingWithR.html#1

# Mastering Spark with R
Sparklyrについて。

https://therinspark.com/

# Big Data with R - Exercise book
DBと連携したRでの処理の仕方について。研究よりも実務向き。

https://rstudio.github.io/bigdataclass/index.html


# R Markdown Cookbook
Rでのドキュメンテーション作成について。

https://bookdown.org/yihui/rmarkdown-cookbook/

# 私たちのR
Rコーディングの基礎

https://www.jaysong.net/RBook/

# R for Data Science
書籍で出ているRではじめるデータサイエンスのページ。
初版と２版がそれぞれ別のページである。

https://r4ds.hadley.nz/

https://r4ds.had.co.nz/

# Google's R Style Guide
GoogleでのRのコーディングルール。

http://www.okadajp.org/RWiki/?Google%27s+R+Style+Guide

# 最後に
今回、研究のために久々にRを使っているのですが、Rstudioの発展もあり、分析からレポーティングまでシームレスにできる環境がかなり整備され、論文等を書くにはRとRstudioってめっちゃ便利なんだなと思いました。
また、研究者の方が書かれている記事が多いことからか、Rの記事は専門性の高い記事が多く、この他にもめちゃめちゃ勉強になる記事がいっぱいありました。大変ありがたい時代です。
【Firebase エラー】「Users does not have permission to access」

# 事象

Firebaseを使ったiPhoneアプリ開発で以下の画像のようにビルド時に
### 「Users does not have permission to access」
といったエラーと遭遇しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/2f6e77e0-90f8-b27f-c515-b3211fb36f1a.png)

# 原因

以下の画像のようにFirebaseのStorageのRuleの設定で
「read」のみ「allow」に設定していたのが原因でした。

この状態だとユーザーは「読む」ことができても
アプリ内にデータを「書き」込んで保存することができないからです。

![スクリーンショット 2023-06-02 18.33.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/563b6562-4bfa-1868-260a-7a2d59e4b632.png)

# 解決方法

以下の画像のように「Firebase」の「Storage」の「Rule」の設定で
「read」だけでなく「write」も「allow」に設定します。

こうすることで、ユーザーは「読む」だけでなく
アプリ内にデータを「書き」込んで保存することができます。

![スクリーンショット 2023-06-02 18.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/157d3a6c-4b64-fc80-3517-201705de3941.png)

# 参考文献
[Swift]FireBaseのStorageで「User does not have permission to access」というエラーが出る
https://teratail.com/questions/365436
技術者としての後悔と後悔しないための方策

知り合いのfacebookの書き込み

>たとえば、自他ともに「やらかしてしまった……！」と思えてならない出来事があったとする。
次の瞬間、やらかしの当事者らには後悔の波が押し寄せる。「あのとき、あんなことをしなければ」。「あのとき、自分があのような状態になっていなかったならば」。

何かをやらかしてしまったことより、　
何かをやらずにいたことの後悔の方が多い。　

たとえば、中学３年になったときの吹奏楽部からの退部。　
器楽部の顧問の音楽の先生との対立で、何人か一緒に辞めた。　
私は小学校４年から油絵を習っており、小学校の頃は絵画部だった。　
中学校の美術部にも、小学校の頃の絵画部の人が何人かいた。　
同じ絵画教室で油絵を習っていた人もいた。　
何の問題もなく３年性は美術部員として活動した。　

もし、当時、名古屋ディレクターズバンドがあれば、　きっと相談に行ったと思う。
器楽部の先生がこんなこと言ってくるけど、どうしたらいいでしょうかって。　

今思えば、名古屋ディレクターズバンドがなくても、音楽関係者に相談すればよかったのかもしれない。　
幼稚園の頃に習っていたオルガンの先生とは疎遠だった。　
一度、指導を受けに行った金城学園のクラリネットの先生とも疎遠だった。　
そうか、学外の音楽活動と疎遠だったのがいけなかったのかもしれない。　

# 原子力発電所事故
## チェルノブイリ発電所事故

チョルノービリ（チェルノブイリ）事故

https://www.fepc.or.jp/nuclear/safety/past/chernobyl/index.html

チェルノブイリ原発の爆発

https://www.shippai.org/fkd/cf/CA0000644.html

チェルノブイリ原子力発電所事故の原因

https://atomica.jaea.go.jp/data/detail/dat_detail_02-07-04-13.html

チェルノブイリ原発事故

http://www.rri.kyoto-u.ac.jp/NSRG/Chernobyl/Henc.html

チェルノブイリ原子力発電所事故と東京電力福島第一原子力発電所事故の規模の比較

https://www.env.go.jp/chemi/rhm/h30kisoshiryo/h30kiso-02-02-06.html

### 後悔　チェルノブイリ

事故が起こってから、なぜ調査に出かけなかったのだろう。　
他人事という意識はなかった。
原子力発電所の事故の可能性について専門家ではないという意識があったのかもしれない。　
まだ、安全分析についての経験がなかったからかもしれない。

出かける費用の工面ができなかったのかもしれない。　
素人のあなたが行ってなにになるのという家族の暗黙の声がしたのかもしれない。　

今となっては、後悔が残る。




## スリーマイルアイランド原発事故

米国原子力発電所事故特別委員会第１次報告書（抜粋）

http://www.aec.go.jp/jicst/NC/about/ugoki/geppou/V24/N05/197910V24N05.html

スリーマイルアイランド事故

https://www.fepc.or.jp/nuclear/safety/past/three_mile/index.html

スリーマイル島原発事故の化学工学による検証

https://www.jstage.jst.go.jp/article/kaihatsukogaku/31/1/31_19/_pdf

米国スリーマイル島原発事故の問題点

https://www.rri.kyoto-u.ac.jp/NSRG/seminar/No110/TMIKagaku1979.pdf

https://www.scj.go.jp/ja/info/kohyo/09/11-07-y.pdf

https://www.scj.go.jp/ja/info/kohyo/09/11-07-y.pdf



### 後悔　スリーマイル

チェルノブイリに行かなかった後悔よりは、小さいかもしれない。　
スリーマイルに行くのなら、その前にチェルノブイリに行かなきゃって思いがある。

フィラデルフィア、ワシントンDC、ニューヨークから、それぞれ２、３時間の距離だっていうことを調べたのが、今日が初めてって。

事故後、ワシントンDCは訪問したことがある。NISTでの会議。　

スリーマイルまで足を伸ばせばよかったと後悔している。 

# 福島原発事故

「想定外」3.11 東日本大震災をIT技術者が振り返る 

https://qiita.com/kaizen_nagoya/items/80433f4bf7fe116bddd1


## 後悔　福島　

チェルノブイリ、スリーマイルとの大きな違いは、事故前にそれなりに近くまで行ったことがある点。

原子力発電所は、中部電力浜岡原子力発電所だけ見学したことがある。　
海沿いで、津波が来た時の対策について質疑があった。　

名古屋市電気主任技術者の見学会に同伴させていただいた。　

# 交通事故　

## 飛行機　

## 鉄道

## 自動車

交通事故死を減らすのにプログラマが主導できる事項13選。仮説（21）。安全(26) 

https://qiita.com/kaizen_nagoya/items/4d46bbf0dde44d7bb99a 

プログラマが安全な系のためにできること。仮説(66) 

https://qiita.com/kaizen_nagoya/items/a9667ab0d1e48438edba

### 後悔　自動車

自動車安全にもっと早く、速く取り組むとよかった。　
北海道のアイシン精機の豊頃試験場に参加した公設試が、北海道と愛知県の名古屋市という、交通死亡事故者数１番を争う当事者が参加していたのに。有効な提案を出せていなかった。


名古屋で自動車関係のソフトウェア設計する際にあるといい知識 

https://qiita.com/kaizen_nagoya/items/9f01d55e4bd0bd931c96



Network Defined Vehicle v.s. Software Defined Vehicle 

https://qiita.com/kaizen_nagoya/items/978403a5c3905ef0478a





JAXA/IPA クリティカルソフトウェアワークショップ WOCS言語関連発表(改定版) 

https://qiita.com/kaizen_nagoya/items/4789832baf494cb74626

プログラマが安全工学シンポジウムで発表する動機、題材、技法。安全（22）

https://qiita.com/kaizen_nagoya/items/b7adf3001eb325166e52

# 自然災害　

自然災害のほとんどが人災だと思うというお話をしたことがある。　

科学技術では、ありとあらゆることを想定していて、対策は考えている。　
実際に、対策に投資するかどうかは人間が決めるからだ。
PowerShellでもCtrl+Dでexitしたい

# こんなことがあります
Windowsが開発機なのでWindows Terminalを使ってLinuxにSSHしているが、exitする時、LinuxはCtrl+Dで抜けられるのに、PowerShellではexitと打たないといけなくて、これが地味に面倒くさい。。。

# これで解決
PowerShellのプロファイルに次の内容を記述すればOK!

```powershell
Import-Module PSReadLine
Set-PSReadlineKeyHandler -Key Ctrl+D -Function DeleteCharOrExit
```
## 手順
1. プロファイルを作成する
1. プロファイルを編集して保存する
1. PowerShellに入り直す

### プロファイルを作成する

```powershell
if (!(Test-Path -Path $PROFILE)) {
  New-Item -ItemType File -Path $PROFILE -Force
}
```

### プロファイルを編集して保存する
次のコマンドでメモ帳が開きます。

```powershell
notepad $PROFILE
```

次の内容を記述しますして保存します。
```powershell
Import-Module PSReadLine
Set-PSReadlineKeyHandler -Key ctrl+d -Function DeleteCharOrExit
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66855/83ef5ef4-ec1e-cc29-06b0-e546eebf087d.png)

### PowerShellに入り直す
exitしてPowerShellに入り直せば、Ctrl+Dでexitできるようになっています。

# 参考資料
* [PowerShell で Ctrl+D で exit する](https://bayashi.net/diary/2020/0627)
* [プロファイルについて - PowerShell | Microsoft Learn](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7.3)
Ajman Massage Center

A massage center in Ajman is a wellness establishment that offers a variety of massage and bodywork services to promote relaxation, reduce stress, relieve pain, and improve overall health and well-being. These services may include Swedish massage, deep tissue massage, hot stone massage, aromatherapy massage, and reflexology, among others. Full body massage in Ajman may also offer additional services such as facials, body treatments, and yoga or meditation classes. Massage in Ajman employs trained and licensed massage therapists who use various techniques and modalities to tailor each massage session to the individual needs and preferences of their clients.
Best Massage Center in Ajman
Ajman, one of the seven emirates in the UAE, has become a hub for relaxation and rejuvenation through its massage centers. Massage therapy is a popular method to de-stress, ease tension, and promote wellness. Ajman massage centers offer various types of massages including Thai, Indian, Chinese, Filipino, and Vietnamese. Whether it’s a full-body oil massage or a Korean massage, the massage centers cater to every individual's preferences.
The massage centers in Ajman are known for their relaxing ambiance and professional therapists who provide a range of services. The spas offer treatments such as hot stone massages, aromatherapy massages, deep tissue massages, and reflexology massages. Visitors can choose from a variety of spa packages that include massages, scrubs, facials, and other beauty treatments.
Several hotels in Ajman have also established their massage centers, offering guests the convenience of having a relaxing massage within their hotel. These hotel massage centers often use high-quality products and offer luxurious treatments.
For those living in Ajman or nearby areas, massage centers near Ajman offer easy access to a variety of massages. Visitors can book appointments or walk in to enjoy a much-needed massage session.
Overall, Ajman has become a popular destination for those seeking relaxation and rejuvenation through massage therapy. With numerous massage centers, spas, and hotel massage services, visitors are sure to find the best massage center in Ajman that meets their needs.
For more information: https://www.ajmanmassagecenters.com/
Telnetでメールを送るスクリプト

# はじめに

SMTPサーバまたはSMTPのようなプログラムを立てた時、ローカルから Telnet コマンドでメールを流してテストしたい時があります。しかし、Telnet 操作中には誤字が入ったり間違ったりすることも多いので簡単にスクリプト化したくなります。一番簡単な text/plain メールや、テキストの添付ファイルが付いたメールを送るスクリプトを紹介します。

# シンプルなテキストメール(text/plain)を送りたい



## Usage
```
./mailsend.sh | telnet 127.0.0.1 25
```
##  mailsend.shの中身
```
#!/bin/sh

echo "HELO 127.0.0.1"
sleep 1
echo "MAIL FROM: test@example.com"
sleep 1
echo "RCPT TO: test@example.com"
sleep 1
echo "DATA"
sleep 1
echo "From:test@example.com"
echo "To:test@example.com"
echo "Subject: Test Mail"
echo ""
echo "test"
echo "."
sleep 1
echo "QUIT"

```

# 添付ファイルが付いているメール(multipart/mixed)を送りたい

添付ファイルが付いた multipart/mixed メールだと、ヘッダにboundaryやcontent-typeなどのヘッダが必要になります。

## usage
```
./mailsend_attach.sh | telnet 127.0.0.1 25
```

## ./mailsend_attach.shの中身
```
#!/bin/sh

echo "HELO 127.0.0.1"
sleep 1
echo "MAIL FROM:test@example.com"
sleep 1
echo "RCPT TO: test@example.com"
sleep 1
echo "DATA"
sleep 1
echo 'MIME-Version:1.0'
echo "From:test@example.com"
echo "To:test@example.com"
echo "Subject: Test Mail for Attachment"
echo 'Content-Type: multipart/mixed; boundary="-----VM2CLL6AQ4USQX4JOG3XAB1A795I
F0B_0_000045AD"'
echo ""
echo "This is a multi-part message in MIME format."
echo "-------VM2CLL6AQ4USQX4JOG3XAB1A795IF0B_0_000045AD"
echo "Content-Type: text/plain; charset=US-ASCII"
echo "Content-Transfer-Encoding: 7bit"
echo "test"
echo ""
echo "-------VM2CLL6AQ4USQX4JOG3XAB1A795IF0B_0_000045AD"
echo 'Content-Type: text/plain; name="test.txt"'
echo "Content-Transfer-Encoding: base64"
echo 'Content-Disposition: attachment;filename="test.txt"'
echo ""
echo "dGVzdCB0ZXN0"
echo "-------VM2CLL6AQ4USQX4JOG3XAB1A795IF0B_0_000045AD--"
echo "."
sleep 1
echo "QUIT"

```

git cloneも可能です。
```
https://github.com/mihyon/mailsend.git
```
Elixirの対話モードで基本を実行してみた

# 概要
Elixirの対話モードで基本を実行してみました。以下のページを参考にしました。

https://elixirschool.com/ja/lessons/basics/basics#%E5%AF%BE%E8%A9%B1%E3%83%A2%E3%83%BC%E3%83%89-2

# Elixirの対話モード

以下の通りコマンドを実行しました。
```
$ iex 
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 2+5
7
iex(2)> 2+5==7
true
iex(3)> String.length("the")
3
iex(4)> 255
255
iex(5)> 0b0110
6
iex(6)> 0o644
420
iex(7)> 0x1F
31
iex(8)> 3.14
3.14
iex(9)> .13
** (SyntaxError) iex:9:1: syntax error before: '.'

iex(9)> 1.0e-10
1.0e-10
iex(10)> true
true
iex(11)> false
false
iex(12)> :foo
:foo
iex(13)> :foo == :bar
false
iex(14)> is_atom(MyApp.MyModule)
true
iex(15)> :crypto.strong_rand_bytes 3
<<33, 30, 30>>
iex(16)> "Hello"
"Hello"
iex(17)> "dziękuję"
"dziękuję"
iex(18)> "foo
...(18)> bar"
"foo\nbar"
iex(19)> "foo\nbar"
"foo\nbar"
iex(20)> 2 + 2
4
iex(21)> 2 - 1
1
iex(22)> 2 * 5
10
iex(23)> 10 / 5
2.0
iex(24)> div(10, 5)
2
iex(25)> rem(10, 3)
1
iex(26)> -20 || true
-20
iex(27)> false || 42
42
iex(28)> 42 && true
true
iex(29)> 42 && nil
nil
iex(30)> !42
false
iex(31)> !false
true
iex(32)> true and 42
42
iex(33)> false or true
true
iex(34)> not false
true
iex(35)> 42 and true
** (BadBooleanError) expected a boolean on left-side of "and", got: 42

iex(35)> not 42
** (ArgumentError) argument error
    :erlang.not(42)
iex(35)> 1 > 2
false
iex(36)> 1 != 2
true
iex(37)> 2 == 2
true
iex(38)> 2 <= 3
true
iex(39)> 2 == 2.0
true
iex(40)> 2 === 2.0
false
iex(41)> :hello > 999
true
iex(42)> {:hello, :world} > [1, 2, 3]
false
iex(43)> name = "Sean"
"Sean"
iex(44)> "Hello #{name}"
"Hello Sean"
iex(45)> name = "Sean"
"Sean"
iex(46)> "Hello " <> name
"Hello Sean"
iex(47)> 
```

# まとめ
何かの役に立てばと。
【ChatGPT無＋JavaScript】関数を作成したら、どうする？


　どうも、カーブミラーです。
　今日は、台風2号の影響で、
　　東京も風雨が酷いです。

　それはさておき
　　今回は、
　　　ChatGPTに
　　　　JavaScriptの関数の作成を依頼。
　　　　　単純なものです。

　　ここでの話題は、
　　　そこではありません。

　　その先に
　　　いろいろとあるかと
　　　　思います。

***
　　まずは、
　　　コードをそのまま使うわけには
　　　　いきません。
　　　**コーディングルール**を
　　　　適用する必要が
　　　　　ありますよね。

　すでに、
　　コードが出来上がった状態で、
　　　以下のプロンプトを
　　　　使用してみてください。

```text:コーディングルールプロンプト
次のコーディングルールに従って、コードの修整をお願いします。

#コーディングルール
引数名は、“prm_”を先頭に付加。
関数内の変数は、“wk_”を先頭に付加。
ループで使用する変数は、“lp_”を先頭に付加。
```
　簡単ですが、
　　エディタで全置換する危険性を
　　　考えたら、安全かと。

　さて、
　　次は、仕様書かな？

```text:仕様書プロンプト
関数の仕様書を作成してください。
コードの記述は必要ありません。
シグネチャはいりません。
使用例はいりません。
```

どうでしょうか？
まぁ、
　コーディングルールも
　　仕様書も会社によって、
　　　さまざまですから、
　この仕様に合っているかは
　　わかりませんけどね。

適度に作り直してください。
ではでは。

記事が書けて、よかったよかった。
laravelのcollectionで連想配列を追加する方法

# 環境
- php:8.1
- laravel:9.23.0

# 対象
- laravelのcollectionで連想配列を使いたい人


# 方法
以下のようにすると出来ます。
```php:Controller.php
$users = DB::table('users')->get();
$items = collect();
foreach ($users as $user) {
    $itemLists = [];
    $itemLists['id'] = $user['id'];
    $itemLists['name'] = $user['name'];
    $itemLists['mail '] = $user['mail'];
    $items->push($itemLists);
}
```
Build 2023から見えるMicrosoftが描く未来

https://news.microsoft.com/build-2023/

最近のMicrosoft Build 2023での発表により、我々はAIの未来について新たな視点を得ました。多数の新サービスがリリースされたこのイベントは、AIを中心としたテクノロジーの現在と未来を探求する舞台となりました。

今回の記事では、OpenAIエンジニアの視点からMicrosoftの目指す方向を探ります。Microsoftのメッセージは一体何だったのか、そしてそれが意味するものは何なのかを考えて整理してみました。


## Microsoft Build 2023でのメッセージ

![Copilot-stack-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/655360e1-5a8f-d169-b737-b083ef6d4b14.png)
発表にあった上図がシンプルに表していますが、Microsoftが最も力を入れて伝えたかったメッセージは、ユーザーのあらゆる業務をMicrosoft Copilotと、その補完的存在である **"your copilots"** でサポートするということです。これらの補助ツールは、作業を円滑に進めるための重要な役割を担っています。

Microsoft Copilotは業務の補助を行うAIで、その行為はまるで副操縦士が操縦士をサポートするようなものです。一方、**"your copilots"** とは何か？これはMicrosoft Copilotを補完するAI補助ツールを指し、自社もしくはサードパーティによって開発されています。その目的は同じくユーザーの作業をサポートし、業務をより効率的に進めることです。

Microsoft Build 2023で発表された多くの新サービスは、これら **"your copilots"** の開発を容易にするためのものとなっています。Microsoftは、より多くのツールが補助ツールとして開発され、個々のユーザーや企業のニーズに適した形で作業をサポートする世界を描いているのです。

一方で、こうしたMicrosoftの取り組みは、AIと人間の共同作業の未来像を示しています。AIはもはや単なるツールではなく、我々の"副操縦士"となり、我々の作業をより効率的で、より簡単なものにする存在となるでしょう。


**"your copilots"** という概念は、ユーザーが自分自身のニーズに適した特定のツールを選択・利用できる未来を示しています。それぞれの補助ツールは、ユーザーが必要とする特定の業務を支援し、その業務をより効率的に行うことを可能にします。これはまさにパーソナライズされたAI支援の世界への一歩と言えるでしょう。

また、Microsoftが提供するこれらの新サービスは、開発者が新しい **"your copilots"** を作り出すことを助けるためのものです。これにより、開発者はユーザーのさまざまなニーズに対応した補助ツールを提供できるようになるでしょう。


## Microsoft Build 2023で発表されたサービス

### Microsoft 365 Copilot

https://www.youtube.com/watch?v=S7xTBa93TX8&t=7s&ab_channel=Microsoft365

Teams, PowerPoint, Excel, Wordなどの様々なツールと連携して、アジェンダ・資料作成や資料の分析からメール作成まで、あらゆる業務を支援してくれるサービス。

### Microsoft Fabric

https://www.youtube.com/watch?v=X_c7gLfJz_Q&t=1s&ab_channel=Microsoft

従来Azure上で行っていた高度なデータ統合・分析ツールをまとめたエンドツーエンド統合分析プラットフォーム。Azure SynapseやPower BIなど幅広いサービスを統合し、組織の“すべてのデータ”を分析できるようになるサービス。AzureやPower Platformのサービスまで統合して **Microsoft** という名前をつけるほど力を入れていることが想像される。

### Azure AI Studio

https://www.youtube.com/watch?v=DaIYrlMOj7I&ab_channel=Microsoft

**"your copilots"** を作るための統合開発環境。Microsoftのサービスだけでなく、オープンソースやHugging Face Hubといったものも利用することが出来ます。

### Microsoft Dev Home/Drive/Box

クラウド上で利用できる開発用ワークステーションDev Box
ローカルでの開発効率を上げるDev Home
開発する上でのマシンI/Oの課題を解決するDev Drive

これら3つのサービスは開発者の生産性を向上させることを目指しています。

## まとめ：Microsoftが描くの新たな Copilot

Microsoft Build 2023は、AIが現代のビジネスや作業環境における重要なパートナーとなることを強く示したイベントでした。それぞれのユーザーに合わせたAI補助ツールが、作業をよりスムーズで効率的なものに変え、業務を革新する道を切り開きます。

Microsoftの最新のAIツール、Microsoft Copilotはユーザーを積極的にサポートし、その他の補助ツール **"your copilots"** もまた個々のユーザーのニーズに適応したサポートを提供します。また、Microsoftはこれらのツールを支え、開発者が新たな **"your copilots"** を生み出すための各種サービスを提供しています。

新たに発表されたMicrosoft 365 Copilot、Microsoft Fabric、Azure AI Studio、Microsoft Dev Home/Drive/Boxなどのサービスは、開発者が新しいAI補助ツールを開発する際の支援を行い、組織全体の作業効率を向上させるためのプラットフォームとなります。

さらに、MicrosoftはAIの運用を安心して行えるためのAI OrchestrationツールやAI Infrastructureも一貫して提供しています。これにより、ユーザーと開発者は安全かつ信頼性の高い環境でAI補助ツールを活用できます。

このように、MicrosoftはAIと人間が協力し合い、互いを補完する新たな働き方を目指していることがわかります。AIはユーザーの信頼性の高いパートナーとなり、開発者はその可能性をさらに広げるための新たなツールを生み出すことができるでしょう。
【UnityWebGL】SpeechSynthesisUtterance(Web Speech API)をiOS Safariで利用できるようにする

# はじめに
UnityWebGLではブラウザが提供している音声合成API(WebSpeechAPI)のSpeechSynthesisUtteranceを利用することが可能ですが、iOS Safariのみ対応方法が特殊でしたので実装方法を記録します。

# iOS Safariでの挙動
speechSynthesis.speakを実行するとエラーの発生等のイベント発行されず、命令が無視される挙動を行います。


# iOS SafariのWebSpeechAPI仕様
初回はJavaScript上のユーザーイベントから呼び出す必要があるという制限がありユーザーイベントから呼び出された後は任意に実行することができます。
よって、初回はダミーのユーザーイベントを実行することで本仕様の回避を行います。

# 実装方法
* 初回ダミーWebSpeechAPIの実行
HTML側のJavaScriptに画面をタッチすると音声0のダミー音声合成再生イベントが発生するようにイベントを登録します。
```javascript
    function handleTouchEnd() {
      // ダミー音声合成を実行
      var speechSynthesis = window.speechSynthesis;
      var utterance = new SpeechSynthesisUtterance('');
      utterance.volume = 0; // 音量を0に設定
      speechSynthesis.speak(utterance);

      // イベントリスナーを削除
      unityCanva.removeEventListener('touchend', handleTouchEnd);
    }

    unityCanvas.addEventListener('touchend', handleTouchEnd);
```

* WebSpeechAPIの実行
二回目以降は他のOSのブラウザと同様に*.jslibファイルからSpeechSynthesisUtteranceを呼び出すことができます。

```javascript
mergeInto(LibraryManager.library, {
    TextToSpeech: function (speechString) {
        if (!('SpeechSynthesisUtterance' in window)) {
            console.log("SpeechSynthesisUtteranceに非対応のブラウザです。");
        } else {
            var synthesis = new SpeechSynthesisUtterance();
            synthesis.volume = 1;
            synthesis.rate = 1;
            synthesis.pitch = 1;
            synthesis.text = UTF8ToString(speechString);
            synthesis.lang = "ja-JP";
            speechSynthesis.speak(synthesis); // 発言を再生
        }
    },
});
```

# 参考スレッド

https://fogbugz.unity3d.com/default.asp?1259405_68ph0a2cmn0aupuj
[Oracle Cloud] Windowsサーバのディスク使用率を、OCI Monitoring のカスタムメトリック用情報として収集する（ ocicli を利用 )

# 目的
OCI Monitoring では、Windowsサーバーのディスク使用率を監視するメトリックが無いため、
値を収集して、カスタムメトリックで監視する。
Python SDK を使ったサンプルはよく公開されているが、OCICLIを使った例があまりなかったため、
記事として残す。

# 前提
1. インスタンスプリンシパルの設定
以下の記事を参考にさせて頂き、収集スクリプトを実行するWindowsサーバで認証を可能にする。
[[Oracle Cloud] インスタンスプリンシパル を OCI Go SDK で使ってみた](https://qiita.com/sugimount/items/159852749851282a33e6)

2. ocicliをインストール
以下の記事を参考にさせて頂き、ocicli をWindowsサーバにインストールする
[[Oracle Cloud] Windows Serverにoci cliをインストールする](https://qiita.com/NSO-KC/items/f35fbd16976f8036615c)


# やってみる

以下のスクリプトを、powershellスクリプトとして保存して、実行する。

※ 以下変更が必要
　　word 変数：取得したいドライブレターの文字を指定
　　compartmentId：対象となるコンパートメントのOCID指定

```powershell
$word = "CD"
foreach ($letter in $word.ToCharArray()) {

$drive=$letter
$value=[Math]::Round((Get-PSDrive $drive).Used / ((Get-PSDrive $drive).Used + (Get-PSDrive $drive).Free) * 100, 1, [MidpointRounding]::AwayFromZero);
$timestamp=Get-Date -Format "yyyy-MM-ddTHH:mm:ss+09:00"

$str_metric_json = @"
[
    {
        "namespace": "custom_metrics",
        "compartmentId": "xxxxxxx",
        "name": "windisk",
        "dimensions": {
            "DRIVE": "$drive"
        },
        "datapoints": [
            {
                "timestamp": "$timestamp",
                "value": "$value"
            }
        ]
    }
]
"@

Write-Output $str_metric_json | Out-File metric.txt -Encoding default
oci monitoring metric-data post --metric-data file://metric.txt --endpoint https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com --auth instance_principal

}
```
【Android】Android13未満で通知許可を必ず行わないとアプリを開けないようにする対応

# はじめに
こんにちは、個人でアプリを作成している時（公開はしないもの）通知許可を必ずONにしてからアプリを開く仕様にしたいと思い実装が完了したのでメモとして。
ちなみにタイトルでAndroid13未満としているのは去年Android13が登場しその時に通知に関する権限許可が必要になりました。13以降はカメラパーミッションと似たような処理通知許可ダイアログが表示されるので実装方法が少し変わるかなと思い13未満ということを追記しました。

https://developer.android.com/about/versions/13/changes/notification-permission?hl=ja

# コードの確認
ちなみに今回は既にあるアプリから追加の仕様での作成になり元々がJavaで作成していたため引き続きJavaでの実装で実装しました。
```java: MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 通知設定リクエスト処理
    requestNotification();
    ・・・・
    途中処理抜粋
}

/**
  * 通知が許可がされているかどうかチェックする
  *
  * @return true 許可 / false 未許可
  */
private boolean checkNotificationFlg() {
    NotificationManagerCompat notificationManagerCompat =　　NotificationManagerCompat.from(this);
    return notificationManagerCompat.areNotificationsEnabled();
}

/**
  * 通知許可画面遷移(設定画面)
  */
private void requestNotification() {
    // 未許可の場合は設定画面の通知許可画面へ遷移する
    if (!checkNotificationFlg()) {
        Intent intent = new Intent();
        intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
        intent.putExtra(Settings.EXTRA_APP_PACKAGE, this.getPackageName());
        startActivity(intent);
        // 設定画面からアプリに戻った時に実行される
        notificationLauncher.launch(intent);
    }
}

/**
  * 通知許可判定Launcher
  */
private final ActivityResultLauncher<Intent> notificationLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
    result -> {
        // 未許可のまま戻ってきた場合はアプリを終了する
        if (!checkNotificationFlg()) {
            finish();
        }
    });
```
# アプリの動き
上記コードの動きとしては以下ような図になります。
なぜダブルチェックにしているかというと設定画面から戻った時に未許可のまま戻ることも考えるとダブルチェックにしなければいけなと思いましたので実装としてダブルチェックしています。
![スクリーンショット 2023-06-02 17.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117699/fd1b990b-68ca-46c4-4ef1-c47da8e3387c.png)
# 最後に
この辺りのチェックはどうすればいいのだろうと少し悩んだ箇所でもありました。
なんだかんだ言ってパーミッションがあると開発側としては楽かもしれないですね。笑
また、もっといい実装方法がありそうな気もしますが一つの実装として温かく見ていただいてたら嬉しいです。
最後までご覧いただきありがとうございました。
Amazon ElastiCacheの基礎

A ElastiCache, Redis, Memcachedってデータベースのパフォーマンス問題を解いているときによく出てくるので内容をまとめてみました。

Amazon ElasiCacheはAWSが提供するマネージド　インメモリーのKey-valueストアで、要はよくアクセスするデータをメモリーに保存して読み込み早くしようぜ！という用途で使われる。

ElastiCacheは２種類ある。

- Memchached(メムキャッシュドじゃなくてメムキャッシュディーって読む)
まずはシンプルにインメモリーストア使って読み込み早くしたい！場合に第一選択肢になる。ただしMulti-AZ非対応、揮発性(電源オフしたらデータ消える)、フェイルオーバー非対応。

- Redis
より高機能なインメモリーストアで、Multi-AZ対応、不揮発性、フェイルオーバー対応。さらにデータのランキングやソートも可能でよりエンタープライズ向け。


### ElasitChachを検討する典型的なケース

データベースへのReadアクセスが頻繁に発生しパフォーマンスが悪化している、かつReadするデータが頻繁に変更されない場合はElastiCacheを設置することでパフォーマンスが改善される。

### ElasitChachが解決策にならないケース
- 上記でも触れたが、Readするデータが頻繁に変わる場合はElastiCache自体が最新データを取得するためにデータベースにアクセスする必要がありパフォーマンス改善は見られない。

- ReadではなくWriteの場合はElastiCacheではなくデータベース自体のコンピューティングリソースをスケールアップする。
- 複雑で処理が長いORALクエリの場合はRedshiftを代わりに検討する。