OmniAICreator/Qiita-1.07M huggingface dataset:
【Ruby】ArrayとHashの便利メソッドまとめ(随時更新)

# はじめに
RubyのArrayとHashの便利メソッドをまとめてあります。
ぜひ辞書としてご活用ください。

# Array
### 取得([], first, last, index, select, find)
- n番目の要素を取得
要素数を超えるとnilが返る
```ruby
array = ['red', 'blue', 'green']
p array[1]
# => 'blue'
p array[5]
# => nil
```
- 後ろからn番目を取得
要素数を超えるとnilが返る
```ruby
array = ['red', 'blue', 'green']
p array[-1]
# => 'green'
p array[-5]
# => nil
```
- 先頭・末尾を取得
```ruby
array = ['red', 'blue', 'green']
p array.first
# => 'red'
p array.last
# => 'green'
```
- indexを取得
要素が存在しないとnilを返す
```ruby
array = ['red', 'blue', 'green']
p array.index('blue')
# => 1
p array.index('yellow')
# => nil
p array.index{|e| e == 'blue' || e == 'green'}
# => 1
```
- 条件で複数取得
```ruby
array = [5, 4, 3, 2, 1]
p array.select{|e| e % 2 == 0}
# => [4, 2]
```
- 条件で1件取得
条件を満たす要素が存在しない場合はnilを返す
```ruby
array = [5, 4, 3, 2, 1]
p array.find{|e| e % 2 == 0}
# => 4
p array.find{|e| e > 5}
# => nil
```

### 追加(push, unshift)
- 末尾に追加
```ruby
array = ['red', 'blue', 'green']
array.push('yellow')
p array
# => ['red', 'blue', 'green', 'yellow']
```
- 先頭に追加
```ruby
array = ['red', 'blue', 'green']
array.unshift('yellow')
p array
# => ['yellow', 'red', 'blue', 'green']
```
### 削除(pop, shift)
- 末尾を削除
```ruby
array = ['red', 'blue', 'green']
p array.pop
# => 'green'
p array
# => ['red', 'blue']
```
- 先頭を削除
```ruby
array = ['red', 'blue', 'green']
p array.shift
# => 'red'
p array
# => ['blue', 'green']
```

### 確認(empty?, include?)
- 空配列かどうか
```ruby
array = []
p array.empty?
# => true
```
- 要素が存在するかどうか
```ruby
array = ['red', 'blue', 'green']
p array.include?('red')
# => true
```

### 変形(compact, flatten)
- nilを削除
```ruby
array = ['red', nil, 'blue', nil, 'green']
p array.compact
# => ['red', 'blue', 'green']
```
- 多次元配列を1次元配列にする
```ruby
array = [['red', ['blue']], 'green']
p array.flatten
# => ['red', 'blue', 'green']
```

### 変換(to_h)
- Hashに変換
2要素の2次元配列のみ可能
```ruby
array = [['apple', 'red'], ['banana', 'yellow']]
p array.to_h
# => {'apple'=>'red', 'banana'=>'yellow'}
```

# Hash
### 取得([])
- keyからvalueを取得
keyが存在しない場合はnilが返る
```ruby
hash = {'apple' => 'red', 'banana' => 'yellow'}
p hash['apple']
# => 'red'
p hash['grape']
# => nil
```
### 追加([]=)
- keyとvalueを追加
```ruby
hash = {'apple' => 'red', 'banana' => 'yellow'}
hash['grape'] = 'purple'
p hash
# => {'apple'=>'red', 'banana'=>'yellow', 'grape'=>'purple'}
```
### 削除(delete)
- keyとvalueを削除
keyが存在しない場合はnilが返る
```ruby
hash = {'apple' => 'red', 'banana' => 'yellow'}
p hash.delete('apple')
# => 'red'
p hash
# => {'banana'=>'yellow'}
p hash.delete('grape')
# => nil
```

### 確認(empty?, key?, has_key?)
- 空Hashかどうか
```ruby
hash = {}
p array.empty?
# => true
```
- keyが存在するかどうか
```ruby
hash = {'apple' => 'red', 'banana' => 'yellow'}
p hash.key?('apple')
# => true
p hash.has_key?('apple')
# => true
```

### 変換(to_a)
- Arrayに変換
2次元配列になる
```ruby
hash = {'apple' => 'red', 'banana' => 'yellow'}
p hash.to_a
# => [['apple', 'red'], ['banana', 'yellow']]
```
PHP sprintf関数の意味・動作

なかなか使う機会がなく知らなかったのでメモ。

### PHPマニュアル

[sprintf](https://www.php.net/manual/ja/function.sprintf.php)

## 説明：

```jsx
sprintf(string $format, mixed ...$values): string
```

フォーマット文字列 **`format`** に基づき生成された文字列を返します。

## 例

```php
$example .= sprintf("<a href=\"%s?hoge=%s&fuga=%s&foo=%s&baz=%s\" class=\"%s\">", "hoge", $fuga, $foo, $baz, $boo, $bar);
```

**自分なりの理解**
＄fromatの中身の％の数分＄valuesを渡す。
n番目の%に置換される文字列が$valuesのn番目のあたる引数。

%sみたいなのは指定子でsの場合は引数を文字列で扱う。
%sの場合は引数を文字列として置換する。
MariaDBでユーザー情報一覧取得SQL

# 概要

* MariaDBのユーザー一覧ほしいんだけど。
* ユーザーごとのアクセス制御ってどうなってたっけ？

そんな時。

# やり方

```sql
SELECT * FROM mysql.user;
```

# 参考サイトさん

https://www.ipentec.com/document/software-mariadb-list-user

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.2075
10.5.4-MariaDB
値分析 (Values)

[Teradata Vantage - Vantage Analytics Library](https://docs.teradata.com/r/Vantage-Analytics-Library-User-Guide/January-2022)[2022/9/22時点]の翻訳です。
(リリース番号 : 2.1.1 | リリース日 : January 2022)
> この記事はVantageアナリティクスライブラリ シリーズのコンテンツです。

# 概要
値分析はアナリストがデータの性質や品質を判断するために役立ちます。
データの合計行数、データのユニーク性、ゼロや空白、Nullを含む、正数または負数などを把握する事が出来ます。

# 前提条件
・Teradata Vantageインスタンスにアクセスできること。
・Vantage アナリティクス・ライブラリがインストールされていること。

::: note info
Vantage アナリティクス・ライブラリのインストールについて、既にVantageを導入頂いているお客様はTeradataサポートサービスにお問い合わせください。
Vantage Express (評価版)やクラウドサービスのDIYでご利用頂く場合は[Teradata Dounload](https://downloads.teradata.com/download)からダウンロードし利用可能です。
Vantage アナリティクス・ライブラリのインストール手順は「[Vantageアナリティクス・ライブラリのインストール](https://qiita.com/ykswi/items/12d0da2ac69b4b161881#vantage%E3%82%A2%E3%83%8A%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AF%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)」の記事に従い行います。



:::

# データの準備
## サンプルデータの入手とデータベースへの格納方法
こちらの「[チュートリアル用のサンプルデータを用意する](https://qiita.com/tmsky/items/4d86ca35aef753290020)」を参照ください。

# 実行方法
## SQLから実行する場合の例
```SQL
CALL td_analyze (
  'values',                                                /* 分析手法　*/
  '
  database        = QID;                                   /* データベース名 */
  tablename       = Superstore;                            /* テーブル名 */
  columns         = Row_ID,Ship_Date,Customer_Name,Profit; /* カラムリスト */
  '
);
```
:::note information
出力結果をテーブルに書き込む場合は以下オプションを指定可能です。
outputdatabase = 出力データベース名;
outputtablename = 出力テーブル名; 
overwrite = {true | false}; --- 未指定の場合はtrueで上書きします
:::
## 出力結果
|xdb|xtbl|xcol|xtype|xcnt|xnull|xunique|xblank|xzero|xpos|xneg|
|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|
|QID|Superstore|Row_ID|INTEGER|9994|0|9994||0|9994|0|
|QID|Superstore|Ship_Date|VARCHAR(128) CHARACTER SET UNICODE|9994|0|1334|0||||
|QID|Superstore|Customer_Name|VARCHAR(128) CHARACTER SET UNICODE|9994|0|793|0||||
|QID|Superstore|Profit|FLOAT|9994|0|7287||65|8058|1871|

## 出力結果の説明
| カラム名 | データタイプ | 説明 |
|:-|:-|:-|
|xdb|VARCHAR (128)|データベース名|
|xtbl|VARCHAR (128)|テーブル名|
|xcol|VARCHAR (128)|カラム名|
|xtype|VARCHAR (128)|データタイプ|
|xcnt|FLOAT|レコード数|
|xnull|FLOAT|値がNULLの数|
|xunique|FLOAT|値のユニーク数|
|xblank|FLOAT|値が空白の数|
|xzero|FLOAT|値が0の数|
|xpos|FLOAT|値が正の値の数|
|xneg|FLOAT|値が負の値の数|

# おわりに
:::note information
サンプルコードはSQL関数から掲載し順次Pythonコードも掲載していく予定です。
:::

:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
チュートリアル用のサンプルデータを用意する

> この記事はVantageアナリティクスライブラリ シリーズのコンテンツです。

> **注意**
チュートリアルで利用するサンプルデータは[Kaggle](https://www.kaggle.com/)で掲載されているサンプルデータを利用しています。

# 使用するデータ
## スーパーストア　データセット
このデータは、ある巨大スーパーマーケットにおける売上に関するデータです。
データには売上に関する情報と顧客や商品の属性情報が含まれます。

## データセットのダウンロード
スーパーストア データセットの取得はこちらのサイトからダウンロード可能です。
[Superstore Dataset](https://www.kaggle.com/datasets/vivek468/superstore-dataset-final)


# データセットのVantageへの格納
## 買上明細データ
買上明細データは、ダウンロードしたスーパーストア データセットを格納するテーブルです。
Teradata Studioと言うツールを使いデータをロードします。

### テーブル定義
```SQL:Superstore
Create table Superstore
(
     Row_ID	        integer
    ,Order_ID	    varchar(128)
    ,Order_Date	    varchar(128)
    ,Ship_Date	    varchar(128)
    ,Ship_Mode	    varchar(128)
    ,Customer_ID	varchar(128)
    ,Customer_Name	varchar(128)
    ,Segment	    varchar(128)
    ,Country	    varchar(128)
    ,City	        varchar(128)
    ,State	        varchar(128)
    ,PostalCode	    varchar(128)
    ,Region	        varchar(128)
    ,Product_ID	    varchar(128)
    ,Category	    varchar(128)
    ,SubCategory	varchar(128)
    ,Product_Name	varchar(256)
    ,Sales	        float
    ,Quantity	    integer
    ,Discount	    float
    ,Profit	        float
);
```

### データのロード
Vantageへデータとロードするにはこちらの記事を参照ください。
<iframe width="560" height="315" src="https://www.youtube.com/embed/3XAcdmBdSsg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### データの説明
|カラム名|データタイプ|説明|
|:-|:-|:-|
|Row_ID|integer|行番号|
|Order_ID|varchar(128)|注文番号|
|Order_Date|varchar(128)|注文日付|
|Ship_Date|varchar(128)|出荷日|
|Ship_Mode|varchar(128)|配送モード|
|Customer_ID|varchar(128)|顧客ID|
|Customer_Name|varchar(128)|顧客名|
|Segment|varchar(128)|顧客セグメント|
|Country|varchar(128)|国|
|City|varchar(128)|都市|
|State|varchar(128)|州|
|Postal Code|varchar(128)|郵便番号|
|Region|varchar(128)|居住地域|
|Product_ID|varchar(128)|商品ID|
|Category|varchar(128)|商品カテゴリ|
|Sub_Category|varchar(128)|商品サブカテゴリ|
|Product_Name|varchar(256)|製品名|
|Sales|float|売上金額|
|Quantity|integer|売上数量|
|Discount|float|値引き|
|Profit|float|損益|

## 顧客マスタ
顧客マスタはスーパーストア データセットから生成した買上明細データから作成します。

### テーブル定義
```SQL:Customer
Create table Customer
(
     Customer_ID	varchar(128)
    ,Customer_Name	varchar(128)
    ,Segment	    varchar(128)
    ,Country	    varchar(128)
    ,City	        varchar(128)
    ,State	        varchar(128)
    ,PostalCode	    varchar(128)
    ,Region	        varchar(128)
);
```

### データ挿入
```SQL:Customer
Insert into Customer
Select
     Customer_ID
    ,Customer_Name
    ,Segment
    ,Country
    ,City
    ,State
    ,PostalCode
    ,Region
From
    Superstore
Order by
    1,2,3,4,5,6,7,8
;
```

### データの説明
|カラム名|データタイプ|説明|
|:-|:-|:-|
|Customer_ID|varchar(128)|顧客ID|
|Customer_Name|varchar(128)|顧客名|
|Segment|varchar(128)|顧客セグメント|
|Country|varchar(128)|国|
|City|varchar(128)|都市|
|State|varchar(128)|州|
|Postal Code|varchar(128)|郵便番号|
|Region|varchar(128)|居住地域|

# おわりに
#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
IBM Cloud Advocate v2 が日本語対応したので受けてみた

IBM Cloud認定資格のIBM Cloud Advocateが日本語対応したので受験してきました。今回はその受験レポートをしたいと思います。

# IBM Cloud認定資格とは？ IBM Cloud Advocateとは？
下記の図がIBM Cloudの認定資格の一覧で、難易度や出題範囲によって資格が分かれています。
IBM Cloud Advocateは左下のAssociate向けの資格となっていて、もっとも難易度が優しい試験です。IBM Cloudの基礎の勉強を始めた方がもっと知識を深めたい、自分の理解度を確認したいという場合に受験するのがオススメかなと感じました。
さらに今までは英語のみの対応でしたが、日本語対応がされたので、英語が得意ではない私でも問題なく解き進める事ができました。（ただ翻訳の精度はあまり高くないです。。）
![スクリーンショット 2022-10-11 10.28.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600839/05809e89-75ce-0094-5944-05b0e5ffe970.png)
# IBM Cloud Advocate v2の試験内容や範囲
試験時間は90分間で、65問中39問以上正解で合格となります。4択問題で合格点が60%です。
公式には下記の項目で出題されると記載されています。クラウドの基礎的な内容からIBM Cloudの基礎的な知識について出題されるようになっています。
1. クラウドコンピューティングの概要
1. クラウドサービスと展開モデル
1. IBM Cloudの基礎
1. IBM Cloudアカウントの基本事項
1. IBM Cloudで利用可能なサービス

受験の方法は、テストセンターでの受験と自宅でのオンライン受験の2パターンあります。公式サイトから簡単に申し込む事ができます。

詳細については[公式サイト](https://www.ibm.com/training/certification/C9003700)をチェックしてみてください。

# おすすめの勉強方法
1. 公式サイトの研修
[公式に研修プラン](https://www.ibm.com/training/path/ibmcloudadvocate2022)が用意されています。基本的に英語なのはネックですが、クラウドの基礎からIBM Cloudの基礎的な内容まで体系立てて構成されているので、理解しやすくまとまっています。

2. IBM Cloud 柔らか層本
日本語で学びたい場合には教科書として[技術よりな人が最初に読むIBM Cloud柔らか層本v4](https://ibm.ent.box.com/v/ibmcloud-yawaraka)を利用するのもオススメです。ページ数は多いですが、IBM Cloudについてほとんど漏れなくパワーポイント資料で分かりやすくまとめられています。
個人的には仕事でIBM Cloudについて分からない事があれば真っ先に参照しています！

# 感想
・仕事でIBM Cloudの勉強をするようになって約半年という立場としても、思っていたより難易度は低かったです。勉強を始めたての人でも積極的にチャレンジするべきだと思います。
・試験時間は90分あるので、見直しの時間は十分に用意されていました。
・英語が苦手な人でも翻訳サイトを使うなり、日本語資料を使えば対策は簡単だし、試験も日本語なので取得しやすい資格だと思いました。
・今後はさらに難易度の高い資格にもチャレンジしていきます。
アクセストークン

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)

-------------

# Sandbox access token not generating

+ [Sandbox access token not generating](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000K1DsX)

1. created whatever needed to generate access-token from Postman & successfully generated access token.
2. Now made hit to the API around 3k and fetched data.
3. After a certain number if I try to generate access token, its showing  invalid grant type. And also at the same time I am not able to log in to my Salesforce account.
4. After around 30min, I am able to generate access token from Postman again without making any changes.


1\. Postmanからアクセストークンを生成するために必要なものを作成し、アクセストークンを正常に生成しました
2\. 3k あたりで API にヒットし、データをフェッチするようになりました。
3\. アクセストークンを生成しようとすると、特定の数の後、無効な付与タイプが表示されます。同時に、Salesforce アカウントにログインできません。
4\. 約 30 分後、変更を加えることなく、Postman からアクセス トークンを再度生成できます


# その他

+ [freee関係のまとめ](https://qiita.com/Keiji_otsubo/items/ad0cfe3230ebaf52fb78)
+ [CURLコマンドを使ってfreee APIにアクセスする](https://qiita.com/Keiji_otsubo/items/723a1535cc8babb343b7)
+ [Salesforce Reports and Dashboards REST API](https://qiita.com/Keiji_otsubo/items/d6ceda32fdd8fe132b60)
+ [Apex Wrapper SalesforceメタデータAPI（apex-mdapi）で指定ログイン情報の使用](https://qiita.com/Keiji_otsubo/items/43f633ae40495cf1e984)
VSCode備忘録


# 入れたextension
Markdown All in One by Yu Zhang: All you need to write Markdown (keyboard shortcuts, table of contents, auto preview and more)
Remote - SSH by Microsoft: Open any folder on a remote machine using SSH and take advantage of VS Code's full feature set.
Remote - SSH: Editing Configuration Files by Microsoft: Edit SSH configuration files
LaTeX by Mathematic Inc.: LaTeX language support for Visual Studio Code.  
LaTeX Workshop by James Yu: Boost LaTeX typesetting efficiency with preview, compile, autocomplete, colorize, and more.

# 自分用初期設定

## 予測変換からの入力をoff
設定から `Accept`で検索して、「Editor: Accept Suggestion On Commit Character」の項目を off にする。

本当は、LaTeX Workshopではsuggestionのリストの表示自体を消したいが、まだやり方わかっていないのでとりあえず放置。

Ref: [【予測変換OFF】Visual Studio Codeで予測変換をOFFするには](https://digitor.jp/textbook/vscode-conversion/)

## LaTeX Workshop
プレビューを表示しているとき、以下のコマンドで該当部に遷移。
・`Ctrl+Alt+J`: TeX → pdf 
・`Ctrl+左クリック`: pdf → TeX 
Ref: [LaTeX Workshop を使いこなす - Qiita](https://qiita.com/Yarakashi_Kikohshi/items/a9357dd469320ffb65a0)

# トラブルシューティング
## sshでリモートに入れたextensionがうまく機能しなかった場合
### 症状
localに「Remote -SSH」を入れて、接続先(以下remote)にextension(具体的にはLaTeX Workshop)を入れて使っていた。その際、いくつかのlocalからはremoteのextensionが使えていたのに、あるlocalからはうまく機能しなかった(インストールしてあるはずなのに、extensionの表示が暗転しており、使えるべき機能が表示されていなかった。具体的にはLaTeX Workshopの`Build LaTeX project`を行う再生ボタン▶️が現れなかったり、pdfが読み込めなかった。)。
一度そのextensionをアンインストールしてインストールし直すと、その端末のlocalでは使えるようになる。しかし、他の元々使えていたlocalでは逆の症状が発生する。これらでextensionを再インストールすると、使えるようになるが元々使えていなかった環境が再現される という堂々巡り。

### 原因と解決法
原因は、トラブルが発生した端末ではVS Codeが最新版ではなかったことだった。その根源的な理由は使っているMacでVS Code.appをアプリケーションフォルダに入れておらず、アップデートを行うことができないようになっていたため、古いバージョンで使い続けていた。
というわけで、VS Code.appをアプリケーションフォルダに入れて、アップデートをかけた。その結果、他の端末で共通して使えている環境が問題があった端末でも使えるようになった。

### 考察
他に使っているMacでは、アプリケーションフォルダにVS Code.appがないにも関わらず、アップデートはできていたし、問題も発生していなかった。インストール時の設定やフォルダの設定が何かアップデートを阻害していた可能性がある。
多分、当初現れていた問題はVS Codeのバージョンが扱えるextensionのバージョンがうまく揃っていなかったことが原因だと思われる。古いバージョンのVS Codeでは最新バージョンのextensionが使えなくてその辺のバージョン差でうまくいっていなかったのではないか。
React + TypeScript で Ant Designを簡単に試してみる

## はじめに

本記事は、
「フロントエンドの開発効率を向上するヒントを教え合おう！」イベントの参加記事です。

https://qiita.com/official-events/5fdc281997d5754d8ac9

## Ant Designとは？
Ant Designは、中国のAlibabaが開発したフロントエンドのUIフレームワークです。
商用利用が可能で、Webアプリとモバイルアプリの両方に対応する膨大なコンポーネントライブラリが用意されています。

日本だとMUIなどの方が人気があって、少し影が薄いかもしれませんが、
海外の特に中国系企業で多く使われています。

https://ant.design/

## 環境構築

まずはreactをインストールします。

```
$ npx create-react-app antd-app --template typescript
```

そしてantdをインストール。

```
$ cd antd-app
$ npm install antd
```

問題なくインストールできていれば以下のコマンドで、
Webサーバが立ち上げ、```http://localhost:3000```にてReactの初期画面が表示されるかと思います。


```
$ npm start
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/13542a1b-65cd-1489-4a88-abb7d43b8727.png)

## Ant Designを試す

antdからコンポーネントと、それに当てるcssをimportしていきます。

```typescript
import { Button } from 'antd';
import 'antd/dist/antd.css';
```

App.tsxの中身を以下のように書き換えます。

```typescript
import React from 'react';
import { Button, DatePicker, Space } from 'antd';
import 'antd/dist/antd.css';
import Typography from 'antd/lib/typography/Typography';
import Title from 'antd/lib/typography/Title';
import Paragraph from 'antd/lib/typography/Paragraph';

function App() {
  return (
    <div style={{margin: "50px"}}>
    <Typography>
    <Title>タイトル</Title>
    <Paragraph>
      こちらは段落です。
    </Paragraph>
      <Space>
        <DatePicker />
        <Button type="primary">ボタン</Button>
      </Space>
    </Typography>
    </div>
  );
}

export default App;
```

うまく読み込まれれば、以下のような画面に切り替わると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/95a899d3-b8d3-b17f-32a4-ef7b108c9fa1.png)

# まとめ

非常に簡単でしたね。
他にも様々なコンポーネントが用意されているので、
いろいろ試してみるのも良いかと思います。

次回は、Ant Designを使ってお問合せフォームを実装していきたいと思います。

次の記事はこちら↓

https://qiita.com/shimajiri/items/fb3949ad059dce1d65f8

## 参考

https://ant.design/docs/react/introduce

https://typescript-jp.gitbook.io/deep-dive/tsx/react
lodashのimportでtree shakingが効かないパターン

先日、業務中にこんなコードに出会いました。

```js
import _ from "lodash";

// ここは適当なオブジェクトです
const user = {
  username: {
    first: "taro",
    last: "yamada",
  },
};

const userCopy = _.cloneDeep(user);
```

あれ？この書き方ってtree shaking効くのかな？
そういえばlodashって、lodash-esと2パターンあったけど、何が違うんだっけ？
と思ったので、試してみました。

## 結論
先に結論ですが、こうなりました。
lodashはES Module形式で書かれていないため、tree shakingを使用するにはlodash-esを使用する必要がありました。

| パターン                             | ファイルサイズ | tree shaking | 
| ------------------------------------ | -------------- | ------------ | 
| lodashで関数を指定**せず**import    | 69.5kb         | ×            | 
| lodashで関数を指定**して**import    | 69.5kb         | ×            | 
| lodash-esで関数を指定**せず**import | 81.4kb         | ×            | 
| lodash-esで関数を指定**して**import | 12.1kb         | ○           | 

## 検証
実際に以下の通り試してみました。

### ファイル構成
app
┣ node_modules
┣ dist
┃  ┗ bundle.js
┣ src
┃  ┗ app.js
┣ package.json
┣ package-lock.json
┗ webpack.config.js

### webpackの設定

```js:webpack.config.js
const path = require("path");

module.exports = {
  mode: "production",
  entry: "./src/app.js",
  output: {
    filename: "bundle.js",
    path: path.join(__dirname, "dist"),
  },
};
```

先に必要なライブラリを入れておきます。
`npm i webpack webpack-cli lodash lodash-es`

### パターン1. lodashで関数を指定**せず**import
前述の通り、そもそもlodashはES Moduleに対応していないため、関数指定の有無に関わらずtree shakingが効きません。
```js:app.js
import _ from "lodash";

const user = {
  username: {
    first: "taro",
    last: "yamada",
  },
};

const userCopy = _.cloneDeep(user);
```

productionモードでバンドルします。
`npx webpack`
![Screen Shot 2022-10-11 at 8.49.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659776/f1d0e21c-b667-7abf-69de-dc3f45af9b7e.png)
69.5kbでした。

### パターン2. lodashで関数を指定**せず**import
```js:app.js
import { cloneDeep } from "lodash";

const user = {
  username: {
    first: "taro",
    last: "yamada",
  },
};

const userCopy = cloneDeep(user);
```
tree shakingが効かないため、パターン1と同じ結果となりました。
![Screen Shot 2022-10-11 at 9.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659776/8c448ee8-362f-7ef0-8b23-3e5cb0f2c4a7.png)

### パターン3. lodash-esで関数を指定**せず**import
```js.app.js
import _ from "lodash-es";

const user = {
  username: {
    first: "taro",
    last: "yamada",
  },
};

const userCopy = _.cloneDeep(user);
```
lodash-esはES Module形式なのでtree shakingに対応していますが、バンドルサイズはlodashより増えています。
tree shakingが出来ていないようです。
![パターン3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659776/7dbb6f11-062d-62dd-92e0-0d175d6f5eb1.png)

### パターン4. lodash-esで関数を指定**して**import
```js:app.js
import { cloneDeep } from "lodash-es";

const user = {
  username: {
    first: "taro",
    last: "yamada",
  },
};

const userCopy = cloneDeep(user);
```
最後にこちらのパターンですが、明らかにバンドルサイズが小さいですね。
tree shakingが成功しました。
![パターン4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659776/d49ab08d-e842-7617-e40b-7307da3a7ba1.png)

## まとめ
以下の事が分かりました。
- lodashではなくlodash-esを使用する
- 使用する関数のみimportする

誤り等ございましたら、恐縮ですがご指摘いただけますと幸いです。
Microsoft365のTeamsでanonymousからの着信を拒否したいんだけど

# 概要

* Teamsの通知があるので『緊急か！？』と急いで見てみると下記。(#^ω^)ﾋﾞｷﾋﾞｷ…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f3063a02-29e7-5953-a2ab-47ea4ef7b17e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/dbb121a3-9c37-3e0f-a2ac-d0852f42b09e.png)
* anonymous = 非通知設定で電話かけてきてる。
* anonymousからの着信はすぐ（2～3秒くらいで）切れる。

**anonymousからの着信を拒否したい。**

# やり方

設定 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/74516c81-58ea-fe86-bf3c-f17b334ca637.png)

プライバシー ⇒ 発信者IDのない通話をブロック 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4289cbdf-4701-cebe-086b-e7d8bc7b1dc5.png)

# 複数端末にTeamsをインストールしている場合

例えばデスクトップ、ノートパソコン、携帯電話、の3つにTeamsをインストールしている場合。

仮にデスクトップで『発信者IDのない通話をブロック』設定をすれば、別端末にその設定が反映される。
（設定が同期される）


# 蛇足

anonymousはおそらく電話番号存在チェックみたいなことをしているスパム。
（ポートスキャンみたいなことやっていると思われる）

『通知がうざい』という理由もあるけど、『セキュリティ』の面でも着信拒否しておく。


# 参考サイトさん

https://tooljp.com/Teams/Menu/TeamsMenuConfig/Teams-Block-calls-without-a-caller-ID.html

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.2075
Microsoft Teams バージョン 1.5.00.21668 (64 ビット)
童話「おおかみと7ひきのこやぎ」から学ぶ。ログイン画面のセキュリティー対策

童話「おおかみと7ひきのこやぎ」を娘に読み聞かせていたら、この話から読み取れる教訓がログイン画面のセキュリティー対策にも役立ちそうだと思ったので記事にすることにしました。

# 童話「おおかみと7ひきのこやぎ」とは

グリム童話の1つであり、かなりメジャーな話なのでご存知の方が多いと思いますが、最初にこの記事で肝となる部分をおさらいします。
画像には「[いらすとや](https://www.irasutoya.com/)」の素材をたくさん使わせていただきました！ありがとうございます :pray: 

話はお母さんやぎが出かけて7匹の子やぎだけで留守番するところから始まります。
![スクリーンショット 2022-10-07 0.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/1c5b441c-eb71-4b57-8416-d669e3e7ecc7.png)
そこへオオカミがお母さんヤギのふりをしてやってきました。
![スクリーンショット 2022-10-07 0.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/2b8fb838-6196-4c72-00b2-dc1c7e2402a1.png)
オオカミは声を綺麗にするためにチョークを飲み込んで...
![スクリーンショット 2022-10-07 0.19.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/3fcb7de9-abc7-2097-f99e-6ce62f683a53.png)
オオカミは白い粉で足を白くして...
![スクリーンショット 2022-10-07 0.26.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/03e71e73-0458-a254-d42b-c539c8d64fdb.png)
こうして子やぎたちはドアをあけてしまい、オオカミに食べられてしまいます。

## どうすればよかったのか？

様々な対策があるとは思いますが、オオカミが突破できた理由の1つは子やぎたちがオオカミだと気づいた理由を開示してしまったことだと思います。
次のようにただ「ドアはあけません」とだけしか言わなければオオカミは何を改善すれば良いかわからずに詰んでいたと思います。
![スクリーンショット 2022-10-07 0.34.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/1cbd7b4c-f1b7-c3fb-5a97-0215591de55e.png)
![スクリーンショット 2022-10-07 0.36.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/d027f3dc-b67a-fb53-980e-8ec5700637e5.png)

# ログイン画面にあてはめる

この話をログイン画面に当てはめてみます。

それっぽい情報を入力...
![スクリーンショット 2022-10-07 0.45.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/c4b9dd17-a5e2-7b25-9792-70f9c3f90ead.png)
メールアドレスを変えて次々にトライ...
![スクリーンショット 2022-10-07 0.50.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/ead536af-06e5-b268-6cb0-7278b4f0dd1a.png)
「メールアドレスが存在しません」が消えたのでメールアドレスはあっているぽい！!
あとはパスワードだけを変えて試せば良いので成功率が格段に上がります。
また、たとえログインされなかったとしても`fuga@example.com`というメールアドレスのユーザーが存在することが漏れてしまうので良くありません。

## どうすればよかったのか？

こちらもエラーメッセージでヒントを出しているのが問題なので、ヒントにならないメッセージに変えましょう。

![スクリーンショット 2022-10-07 1.00.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/d6dad690-bf01-4910-0889-247200f7268a.png)

これであれば、メールアドレスが間違っているのかパスワードが間違っているのか、それとも両方が間違っているのかわかりません。

# まとめ

Webアプリケーションのベストプラクティスを学んでいると、入力フォームではユーザーが迷わないように丁寧にエラー原因を伝えましょう！と書かれていることが多いです。
そのノリでログイン画面を作ると、この記事に書いたようにエラー原因を詳細に伝えてしまうことがあります。
ログイン画面やパスワードリセット画面などアプリケーションの入口となる部分では悪意のあるユーザーがログイン情報を盗もうとしている可能性を踏まえて、ヒントを与えないエラーメッセージを心がけるようにしましょう。
RSpecを読む、駆け出しエンジニア。

## 駆け出し歴、1年5ヶ月
Railsで開発を行っている駆け出しエンジニアです。
RSpecでのテストを書いているのですが、自身がテストを書くときに意識している **文脈** について
共有したいと思い記事にしました。

駆け出したばかりの頃の自分へ向けた内容になっています :walking_tone1:

## 例とするテストコード
下記のようなテストコードがありました。
今日はこれを日本語で読んで行きたいと思います。

```rb
describe "drink?" do
  subject { UniversityStudent.new(age: age).drink? }

  context "19歳の場合" do
    let(:age) { 19 }

    it "お酒を飲んではいけないこと" do
      expect(subject).to be_falsey
    end
  end

  context "20歳の場合" do
    let(:age) { 20 }

    it "お酒を飲んでもいいこと" do
      expect(subject).to be_truthy
    end
  end
end
```

## 辞書を参考に
英語は難しいので、下記の辞書を参考にしながら読んでみます :sunglasses:
```
describe => 説明しよう！
subject => 本日のお題は
context => の話なんだけど
let => とさせてくれ
it  => それはね
```

## 1行ずつ読み解く
まずは1行ずつ解析します。

`describe "drink?" do` は **お酒飲んでもいいの? について説明しよう!** とします
`subject { UniversityStudent.new(age: age).drink? }` は
**本日のお題は age歳の大学生はお酒を飲んでもいいの?** となります。

*大学生に関わらず、お酒は20歳になってから* **← ここ重要** :beer:

どんどんいきます。

`context "19歳の場合" do`　は **19歳の場合の話なんだけど**
`let(:age) { 19 }` は **ageを19歳とさせてくれ**
`it "お酒を飲んではいけない" do` は **それはね"お酒を飲んではいけないこと"**

以後、繰り返しです。

## 読み解いた結果
つなげて読むと
```
お酒飲んでもいいの? について説明しよう！
  本日のお題は age歳の大学生はお酒を飲んでもいいの?

  19歳の場合の話なんだけど、
    ageは19とさせてくれ

    それはね "お酒を飲んではいけないこと"
      本日のお題は "だめだよ" となることが予想される

  20歳の場合の話なんだけど、
    ageは20とさせてくれ

    それはね "お酒を飲んでもいいこと"
      本日のお題は "いいよ" となることが予想される
```

今回のような実装をする場合、私は仕様を整理して、閾値を意識した上記のような物語を考えます。
そして、今回行った `英=>和` の逆の変換 `和=>英` を行い、
`it` `context` の文章や `let` の値について埋めていくのが良いのかなと考えています :sunny:

## まとめ
お酒は20歳になってからにしましょう :beers:

## ほんとうのまとめ
すみません、本当のまとめです。
動くドキュメントとして、読んで理解できるテスト作成を行って行きたいと思います。
最後まで読んで下さり、ありがとうございました :grin:
関連リストのカスタム ボタンでクロスドメイン エラーが発生する


+ [Related List Custom Button giving cross-domain error](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000Jdws3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/38cc7338-fd7b-e0ae-9cd9-0508a4f04544.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/14a37660-3df1-ef5b-d600-a99819f0ba86.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/937f1502-5507-d4ea-b158-a9d263582aa3.png)
UnrealEngineでaws-sdk-cppを利用する

以下の記事で作ったプラグインのaws-sdk-cppを更新しようとしていろいろはまったので内容をメモしておきます。

https://qiita.com/mechamogera/items/e0c519e4788ad71ac092

# 環境 

UE4.27.2
aws-sdk-cpp 1.9.353

# 導入方法

以下に導入手順があるのでそれに従います。

https://aws.amazon.com/jp/blogs/gametech/how-to-integrate-the-aws-c-sdk-with-unreal-engine/

## 導入ではまったところ

上記の文書を見ずに最初にaws-sdk-cppのコードをgithubから取得してビルドして利用しようとすると
AWS_DEEP_CHECKSやAWS_USE_IO_COMPLETION_PORTSなどが定義されていないというエラーでUnrelEngine側のビルドでエラーになりました。
上記の文書にあるとおり[プロジェクト名].Build.csにbEnableUndefinedIdentifierWarnings = false;を追加することで回避できました。

# 利用ではまったところ

## S3のGeneratePresignedUrl利用個所でのクラッシュ

Aws::Stringを反す[GeneratePresignedUrl](https://sdk.amazonaws.com/cpp/api/0.12.9/d7/db7/class_aws_1_1_s3_1_1_s3_client.html#a0901782a18d510adf5a38958cbfc5e27)関数の利用個所でエディタプレイでクラッシュするという現象が発生しました。
クラッシュではaccess violationが発生しており文字列のメモリ解放部分で起きているようでした。

おそらくメモリ管理方法がUnrealEngine側とSDKのdll側で異なりdll内で確保したAws::StringのメモリをUnrealEngine側で解放するする際に解放メモリのサイズの食い違いが起きたのではないかと思います。
力技でGeneratePresignedUrlの返り値をconst char*にした関数をaws-sdk-cppに用意してビルド、利用するとクラッシュは発生しなくなりました。
本来は以下にあるようにaws-sdkのメモリ管理方法をUnrealEngineにあわせる必要があるのではないかと思います。

https://docs.aws.amazon.com/ja_jp/sdk-for-cpp/v1/developer-guide/memory-management.html

2023/09/14追記：[UnrealEngineでaws-sdk-cppのメモリ管理をUnrealEngineと合わせる - Qiita](https://qiita.com/mechamogera/items/689351daee13c841dd25)を書きました。

## S3のPutObjectが遅い環境がある

[PutObject](https://sdk.amazonaws.com/cpp/api/0.12.9/d7/db7/class_aws_1_1_s3_1_1_s3_client.html#a4fa3b1458095f704266ec12d0198930c)でアップロードが遅い環境がありました。
一般的なWebでのSpeedTestでは問題なさそうでバージョンが古いaws-sdkなら速かったです。
原因はまだよくわかっていません。
【AtCoder】WAが出た時の対処法(灰色コーダー向け)【競技プログラミング】

問題を読み、コードを書き、入力例で確認し、全部OKだった。
意気揚々と提出したら **無慈悲な「WA」** 。
どこが間違っているかもわからない・・・。どうしよう・・・。

そんな時の対処法をお伝えします。
なお、この記事は初心者～灰色の方向けに書いていますので、茶色以上の人には当たり前に感じることが多いと思います。
また、難易度が高めの問題で起こりがちなWAも書きません。
**茶色以上の人は勝手に頑張ってくれ。**

# そもそもサンプル通ってますか？
自分の手元でテストしたときは全部合ってる！と思ってたけど、
「Yes」を出力する問題で「YES」を出力しているとか
「Hello!」を出力する問題で「Hello」を出力しているとか
そういったしょーもねえミスが無いかをまず確認しましょう。
コンテスト中の提出でもサンプル(入力例)が合っているかは提出画面の「詳細」から確認できます。

# コードの見直しをする
まずはコードの見直しです。自分が意図した動作どおりのコードになっているか確認しましょう。

## 変数名間違い
変数名、aとaaとaaaとかでやってませんか？
xとXで別のものを表したりしていませんか？
**今すぐやめましょう。**
こういった変数名の付け方をしているとaに代入すべきところをaaにしてしまったとか、変なミスに繋がりがちです。
普通はサンプルを試した時に気づくんですが、何故かサンプルは通っちゃうことがあるんですね・・・。

ans(answerの意味)とかcountとか、なるべくなにを表しているのかわかりやすい変数名にしましょう。

## i,j見間違い
以下のコードを見てください。

```python:
for i in range(N):
    for j in range(N):
        ans+=A[i][i]
```

ん？ってなりましたか？
iとjのループを回しているのにA[i][i]になっていますね。
ほんとはA[i][j]でないといけないところ、A[i][i]にしてしまうとかはありがちです。
なんせiとj、めっちゃ似ている。

iとkにしましょう。jには故郷の村を焼かれたというくらいの気持ちで避けましょう。

# 少数が含まれる計算
28*(25/100)はいくらでしょうか？
計算してみましょう。

```python:
print(28*(25/100))
```

【出力結果】
7.0

OK。では25*(28/100)はいくらでしょう。

```python:
print(25*(28/100))
```

【出力結果】
7.000000000000001

**は？**

はい、これが少数計算の誤差です。コンピューターは無限小数を扱えないので誤差が出る可能性があります。
「/」(割り算)は極力避けましょう。可能な限り「//」(割り算の商)を使いましょう。

例外の場合として出力結果の指定に「出力との絶対誤差または相対誤差が10^(−6)以下のとき正解と判定される。」とあればばんばん使ってOKです。

# WAになるケースを探す
コードは合ってそうだなとなったらどのケースでWAになっているか確認します。

## 制約の端っこ確認
制約が1≤N≤10^5なら必ずN=1のケースを確認しましょう。
可能ならN=10^5のケースもやっておきましょう。
制約の端はコーナーケース(例外的な処理が必要なケース)になりがちです。

## 偶数の場合、奇数の場合両方試す
問題によりますが入力が偶数の場合と奇数の場合で別の処理が必要なことがあります。
偶数の場合、奇数の場合両方を入力して試してみましょう。

## もうとにかくいろいろ試す
上記2つでは合ってそうなのに！となったらとにかく色々なパターンを試してみましょう。
自分で正答の値がわかるパターンを作って、実行して確認を繰り返しまくります。
このケースはここで処理しているから通るはず、というケースも必ず試しましょう。
人間は愚かなので思いもよらないミスがあるものです。

## 自動化してしまう(上級者向け)
例えば以下のような問題の場合を考えます。

>A=A1,A2,A3,...,ANについて、(Ai,Aj)の最大公約数が1になる組の個数を出力せよ。
1≤N≤10^5
1≤Ai≤10

(i,j)全組の最大公約数を確認すると計算量がO(N^2)になるので当然Nが最大のケースでTLEします。が、少なくとも答えは出せますね。
このようにゴリ押しで答えを出すコードと、自分で書いたコード両方を実行してみて出力の一致しないケースを探すという方法です。
入力の値もランダムで作れるようにしてしまえばいろいろなケースを高速で試すことができます。

# 最後の手段　テストケースの確認
コンテスト中ではなく、過去問を解いている時の方法です。

AtCoderは公式がテストケースを公開しています。

https://www.dropbox.com/sh/nx3tnilzqz7df8a/AAAYlTq2tiEHl5hsESw6-yfLa?dl=0

コンテスト後だいたい1週間から2週間程度で公開されるようです。

これでWAになるケースを直接確認します。
正解を確認するのも大事ですが、 **なぜ間違っているのか** を確認するのも大事です。

皆さんも良い競プロライフを！
Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「Azure Virtual Machines(VM)」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「Azure Virtual Machines(VM)」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azure のアーキテクチャとサービスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/azure-fundamentals-describe-azure-architecture-services/)
◇対応するモジュール
[Azure Virtual Machines について説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-azure-compute-networking-services/2-virtual-machines)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「Azure管理インフラストラクチャ」](https://qiita.com/fsd-jume/items/cbbfe233a868901cf1e7)

## Azure Virtual Machines(VM)
**Azure上で提供されている仮想マシン**
※Virtual Machine(仮想マシン)
⇒物理的なハードウェア(サーバ等)内に作られた仮想的なコンピュータ
・完全な制御とカスタマイズを提供するIaaSサービス
・仮想プロセッサやメモリ、ストレージ、ネットワークが含まれ、それぞれを自由にカスタマイズ可能
**◇使用例**
・アプリの実行環境やバックアップ環境、開発/検証環境などの環境構築
・オンプレミス環境をクラウドに拡張したり、クラウドへの移行(リフトアンドシフト)
・DR拠点としての一時的な利用

**◆AzureにおけるVMのスケーリング
VMをグループ化して管理し、回復性や高可用性を提供**

**◇仮想マシンスケールセット**
負荷分散が行われるVMのグループを作成して管理できる
⇒負荷や決められたスケジュールによって自動的にVMの増減が可能
・ロードバランサを自動的に配置して、リソースを効率的に使用する

**◇仮想マシン可用性セット**
物理的な障害や計画メンテナンス時にも継続的な動作を提供
⇒自動的にVMを更新ドメインと障害ドメインの2つのドメインに分散配置
　　
**・更新ドメイン(UD：Update Domain)**
同時に再起動できる単位(サーバ単位)でVMをグループ化
⇒計画メンテナンス時にすべてのVMが1度に再起動することを防ぐ

**・障害ドメイン(FD：Fault Domain)**
共通の電源やスイッチ、ネットワーク( =ラック単位)でVMをグループ化
⇒ラック単位の物理的な障害が発生しても継続動作を提供
※障害ドメインは最大3つ、東日本/西日本リージョンは2つまで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/1240c1cb-e692-9c6f-c694-820b11dec573.png)

## 次の学習内容
**◆Azure Virtual Desktop(AVD)**

https://qiita.com/fsd-jume/items/c680203a6c97b9e464d9

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

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
Python,Ruby,PHP,Java,JavaScript,Perlの自動試験(ユニットテスト)の比較 | プログラミング言語比較


<a href="https://qiita.com/yuki_kimoto/items/f9c2454e7f9130ddb003">Qiita > プログラミング言語の比較</a>

プログラミング言語Python,Ruby,PHP,Java,JavaScript,Perlの自動試験(ユニットテスト)の比較

# Python

https://qiita.com/_dakc_/items/e663359c81645bc4e65e

# Ruby

https://qiita.com/jnchito/items/ff4f7a23addbd8dbc460

# PHP

https://qiita.com/yamato1491038/items/7aa0168a6145749db78c

# Java

https://qiita.com/ryuutamaehara/items/c8efb304b73cc0542e6f

# JavaScript

https://qiita.com/jintz/items/61af86a12b53b24ef121

# Perl

https://perlzemi.com/blog/20090221123410.html
【bash】変数に代入した値を使って、変数名を作り、その値を参照する

~~もっと良い書き方はないのでだろうか？~~
コメントいただいた内容で更新しました。すっきり！

```bash
bash-3.2$ ENV=QA
bash-3.2$ echo $ENV
QA

bash-3.2$ SECRET_QA='this is a secret for qa'
bash-3.2$ echo $SECRET_QA
this is a secret for qa

bash-3.2$ echo SECRET_${ENV}
SECRET_QA

bash-3.2$ echo \$SECRET_${ENV}
$SECRET_QA

bash-3.2$ eval echo \$SECRET_${ENV}
this is a secret for qa

もしくは

bash-3.2$ eval echo \"\$SECRET_${ENV}\"
bash-3.2$ eval "echo \"\$SECRET_${ENV}\""
bash-3.2$ eval 'echo "$SECRET_'"${ENV}"'"'
bash-3.2$ eval echo $"$"SECRET_${ENV}""
```
WEB開発をやり始めてみる(Ruby:Cloud9環境構築)

# 目的
web開発としてRubyの学習を始めてみる。
環境はCloud9で作成しています。

# やったこと
```ruby
### 環境を整えます
$ sudo yum update && sudo yum upgrade
```
```ruby
### バージョンを指定します(3.0.2)
$ rvm -v
rvm 1.29.8 (1.29.8) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]

$ rvm get stable
Downloading https://get.rvm.io
略

$ rvm install ruby-3.0.2
Searching for binary rubies, this might take some time.
略

$ rvm list
 * ruby-2.6.3 [ x86_64 ]
=> ruby-3.0.2 [ x86_64 ]

$ rvm use 3.0.2
Using /home/ec2-user/.rvm/gems/ruby-3.0.2

$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
```
AWS S3 オブジェクトの保護についてまとめ

## 概要

AWS Solution Architect Associate試験で問われがちなS3のアクセス制御・誤削除防止など、「オブジェクトの保護策」についてまとめてみました

## アクセス制御

### ACLによる読み取り・書き込み制限

パブリックアクセスをブロックするなどの設定を行い、直接URLからオブジェクトにアクセスできるのを防ぐ
デフォルトではバケット内のオブジェクトがプライベートアクセスとなっており、所有者以外はアクセスできない

### バケットポリシーの設定

IAMユーザー・ロール・AWSアカウント・サービスに対してアクセス制御を行う。
特定のIPアドレスを許可/拒否、バケット内のオブジェクト・ディレクトリごとにアクセス制御を行えるなど、ACLより柔軟に設定ができる。
一つのポリシーで100個までルールを設定できる。

バケットポリシーのサンプル

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "IPAllow",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
         "arn:aws:s3:::sample-bucket/sample-object"
      ],
      "Condition": {
	      "NotIpAddress": {"aws:SourceIp": "192.123.72.0/24"}
      }
    }
  ]
}
```

NotIpAddressで指定されたIP以外からのsample-backetのsample-objectへのアクセスを拒否する

### 署名付きURLの使用

プライベートバケット内のオブジェクトを共有するためには署名付きURLを使用する。
URLを作成するときは、アクセスを許可するHTTPメソッドと有効期限を設定する。

ユースケースとしては
- 一般向けに公開しているWebサイトで、ユーザーに画像を配布する
- 外部アプリケーションから動画などをアップロードする

などが挙げられる。


## 誤削除を防ぐ

### MFA Delete（多要素認証）
オブジェクトを削除するときにMFAの値を入力する必要がある。
MFA Deleteが有効になっているときはバージョニングを無効にすることができない。
CLI上で設定が可能。（コンソールでは不可）

### バージョニングの有効化

バージョニングを有効化すると、同一のキーを持つオブジェクト（同じファイル）をアップロードしたときに新バージョンとして保存され、以前のオブジェクトは上書きされず保持される。
同一オブジェクトをアップロードしても上書きされず、別オブジェクトとして保存されるので、放っておくと気づいたらバケット内にオブジェクトが溜まっていくという状態になるかも。
ライフサイクルルールと組み合わせることで、特定の日数以前のバージョンは自動的に削除という設定もできる。


### オブジェクトロックの設定
Write Once Read Many(WORM)モデルを使用して、オブジェクトが削除・上書きされることを一定期間or無期限防止できる。
オブジェクトロックを有効化すると自動でバケットのバージョニングが有効になる。

## 参考

[署名付き URL を使用したオブジェクトの共有](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html)
[S3 オブジェクトロックの仕組み](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/object-lock-overview.html)
[S3 バケットでのバージョニングの使用](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/Versioning.html)
Module: OmniStudio FlexCard Building and Publishing Unit: Work with Child FlexCards


 正直なところ何の事だか全く理解できない。何をしているのかも... これって何？

[フレックスカードのアクティブ化/プレビュー中のエラー](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FxkQZ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0ce4feca-fc7f-e5fb-4312-9d699402b7cf.png)


# {"IPResult":{"error":"No Active Procedure Found: ApigeeRequest_Post"},"error":"No Active Procedure Found: ApigeeRequest_Post"}

+ [Work with Child FlexCards with OmniStudio Issue](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Kge3t)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/535f7db1-517f-bf1e-a740-7963a62ff0c0.png)

:::note
同じようなエラーメッセージに対して権限セットの設定が提案されています。 


Create an Omnistudio Permission Set for Standard Experience Users

https://help.salesforce.com/s/articleView?id=xcloud.os_create_an_omnistudio_permission_set_for_standard_experience_users_7203.htm&type=5

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007eqcNySAI
:::
C言語忘備録2 基本文法

# printf scanfの指定子
%c char 文字
%s char* 文字列
%d int 整数
%f float 単精度浮動小数点数
%lf double 倍精度浮動小数点数
```c
#include<stdio.h>
int main(void){
  char c,C[10];
  int n;
  double d;
  float f;
  scanf("%c %s %d %lf %f",&c,C,&n,&d,&f);
  printf("%c %s %d %f %f",c,C,n,d,f);
  return 0;
}
```
# 小数点桁数指定
```c
#include<stdio.h>
int main(void){
    double a=10,b=3;
    printf("%.1lf %.2lf %.3lf",a/b,a/b,a/b);
    return 0;
}
```
結果 3.3 3.33 3.333
%.1の数字部分により小数第何位かが変わってくる。
# unsigned long long int 最大値のデータ型
unsigned long long int a= 285212673;
printf("%llu", 285212672);
【キータ超初心者】初めての投稿

## どうすれば、投稿できるのかもわからない。。。からスタート

キータの情報は、いつも参考にさせて頂いているのですが、
投稿する側になるのは、初めてなので、サンドボックスがてら、書いてみます。

という訳で、早速、本文を書きあげました！
![2022-10-11_08h38_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/c91d072b-c800-2597-2a90-a63e2c674f28.png)

## 最初の悩み

↓を見て書き、右下の緑の「Qiitaに投稿」ボタン押下。(ﾄﾞｷﾄﾞｷ)

https://qiita.com/Qiita/items/c686397e4a0f4f11683d

![2022-10-11_08h38_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/c296d6fa-c9c9-9741-2451-875d84853199.png)

## あれれ、なぜか投稿が出来ない。。。(ｶｲﾀﾓﾉｶﾞﾑﾀﾞﾆﾅﾙｶﾓ｡｡｡ｼｸｼｸ)

実は、左下にこっそりと、メッセージが出てたんですね。

  - 「タイトルを入力してください」
  - 「タグは、1つ以上指定してください」
![2022-10-11_08h38_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/87b248ff-e330-744c-5a98-6ae665b8b278.png)

という訳で、ここにもしっかり書く

![2022-10-11_08h06_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/ba5630ca-de2e-f4b7-99b7-2f40724568bf.png)

タイトルとタグは、とりあえず何でもよいです。
何かを入力する必要があったのですが、どの部分を指しているのか、
これだけ大きい文字で書かれていても、悩む人はいるんです。。。(汗)
気を取りなおして、「Qiitaに投稿」ボタン押下。(ﾔｯﾀ、初成功＼(^o^)／)

## 次の悩み

- 投稿したら、最初から完璧な記事は書けないので、修正したくなります。って、どこから?

投稿した記事の左 ... から 編集するを選択でした。
![2022-10-11_08h08_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/5c72a18b-fa3b-7338-8f71-9be168fe995e.png)

## 少しカッコよく

- 見出し部分の作成方法が分からない。。。

当たり前のように、使われている見出しですが、知らないと出せない壁がありました。。。

## 見出しを付けたい

「## 見出し」と書けば良くて、Markdown(マークダウン)の書き方を知る必要がありました。
↓

https://qiita.com/tbpgr/items/989c6badefff69377da7

カッコいい記事のMarkdownを見て、コピペから始めてみるのも良いかもしれません。
![2022-10-11_08h08_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/c08c0aff-305b-d007-433d-bfb5950eef66.png)

## あと、練習なので、続けて投稿しようとすると...

![2022-10-11_08h20_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2910496/14b21316-e9b9-6779-291a-c68b2983e7eb.png)
「投稿頻度が高すぎます。しばらく時間をおいてから再度アクセスしてください。」
と表示されてしまい、、ここで練習は終了です。

同じ悩みになった人で、参考になれば幸いです。
ぜひとも、最初の壁?をクリアーして、投稿側に回ってみてください。
Raspberry Pi OS の /boot 内のファイル一覧

RaspberryPi の /boot 内のファイル

|ファイル名|説明|
|:---:|:---|
|cmdline.txt|カーネルに渡すコマンドライン|
|config.txt|RaspberryPi 初期ブートに使うパラメータ。start.elf 以降に使用される|
|bootcode.bin|GPU用ブートローダ|
|start.elf|Raspberry Pi 3 まで用ファームウェア|
|startx.elf|Raspberry Pi 3 まで用ファームウェア。カメラドライバとコーデックを含む|
|startcd.elf|Raspberry Pi 3 まで用ファームウェア。コーデックや 3D などを使わない簡易版|
|startdb.elf|Raspberry Pi 3 まで用ファームウェア。ファームウェアのデバッグバージョン|
|start4.elf|Raspberry Pi 4 用ファームウェア|
|start4x.elf|Raspberry Pi 4 用ファームウェア|
|start4cd.elf|Raspberry Pi 4 用ファームウェア|
|start4db.elf|Raspberry Pi 4 用ファームウェア|
|fixup*.dat|start*.elfのリンカファイル|
|issue.txt|ファイルの版など|
|ssh or ssh.txt |ファイルが存在した場合、ssh が有効になる|
|wpa_supplicant.conf|WiFi セットアップのための設定ファイル|
|*.dtb|Linuxカーネル起動時に用いる、Raspberry Pi の各モデルのハードウェア定義ファイル|
| kernel*.img|Raspberry Pi の各モデル用に用意されたLinuxカーネルイメージ|
| kernel1.img|BCM2835 Raspberry Pi / Zero 用Linuxカーネルイメージ|
| kernel17.img|BCM2836/2837 Raspberry Pi 2 / 3 用Linuxカーネルイメージ|
| kernel171.img|BCM2711 Raspberry Pi 4 用Linuxカーネルイメージ|
| kernel18.img|BCM2837/2711 Raspberry Pi 2 / 3 /4 用Linuxカーネルイメージ|
|overlays|デバイスツリーオーバーレイファイルを収納するフォルダ。外付けデバイスなどのハードウェア用。|
|u-boot.bin|u-bootを使う場合、u-boot実行ファイルをこの名前で格納することが多い|

デバイスツリーオーバーレイファイルは config.txt ファイルによって指定され、読み込まれます。

参考：
「Raspberry Pi Documentation - Configuration」
https://www.raspberrypi.com/documentation/computers/configuration.html

「树莓派/boot分区内的文件有什么用？-开源基础软件社区-51CTO.COM」
https://ost.51cto.com/posts/1647
Webページにツールチップを出すには？

# Webページにツールチップを出すには？
1. ツールチップ要素に、以下のスタイルをあてておく。
   ```
   position: absolute;
   box-shadow: 3px 3px gray;
   z-index: 適当な大きな数;
   ```
1. 一旦、適当な位置指定で配置
1. getBoundingClientRectで配置位置を得る
1. 本当に配置したい位置との差分を計算して、位置指定して配置

# コード例
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="OJZaPgW" data-user="TownLarge" 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/TownLarge/pen/OJZaPgW">
  ToolTip Test</a> by large.town.sky (<a href="https://codepen.io/TownLarge">@TownLarge</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 解説
## position: absolute;
他の要素と無関係な場所に絶対位置配置するために指定します。

https://developer.mozilla.org/ja/docs/Web/CSS/position

:::note info
absolute以外にfixedでも似た効果を出せます。
スクロールした場合、absoluteはページと一緒に移動するのに対し、fixedは位置が変わりません。
:::
:::note warn
fixedの場合、画面外にはみ出た場合にスクロールしてもアクセスできなくなる事にご注意ください。
:::

## box-shadow: 3px 3px gray;
ページ本体から浮いている視覚効果を出すための影を付けるスタイルです。

https://developer.mozilla.org/ja/docs/Web/CSS/box-shadow

:::note info
サイズやぼけ効果や色などが調整できます。
:::

## z-index: 適当な大きな数;
たいていの場合は、指定しなくても動作します。他のページ要素にz-indexを指定している場合は、親要素も含めて負けない大きな値を指定する必要があります。

https://qiita.com/Yametaro/items/399a383b48ec2082997e

## なぜ２度位置指定するのか？
absoluteやfixed で位置指定する場合の基準座標系は複雑です。

- 親要素を辿っていき、一番近くにある包含ブロックを基準とする
- 包含ブロックが無い場合、初期包含ブロックを基準とする

:::note info
包含ブロックは、以下のいずれかの条件を満たす要素
  - positionがstatic以外
  - transform または perspective の値が none 以外
  - will-change の値が transform または perspective
  - filter の値が none 以外、または will-change の値が filter (Firefox のみ)
  - contain の値が paint
:::

厳密に計算するには、この様な複雑な仕様通りに基準座標系を計算する必要があります。それだけでなく、初期包含ブロックを正確に取得するのが困難です。

:::note warn
初期包含ブロックは、多くの場合ビューポートですが、そうでない場合もあります。
:::

このため、たまに間違う複雑な計算をするより、仮に配置して、ずれを補正する方が確実です。実際に、初期包含ブロックが謎領域なため、ノート・リンク付与アプリが誤動作して、とんでもない場所にツールチップを出しているページがありました。（修正済み）

<iframe width="560" height="315" src="https://www.youtube.com/embed/Cchk67vGZaQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
【やらかし】git mergeしすぎた話

# はじめに

名刺の肩書きに“エンジニア”と書かれる仕事に就いたのは丁度1年前、細々と色んな業務をこなしてきた。
そして**最近ようやく念願のコーダーとして案件に参加する**事になった。

そんな私がgitで悪戦苦闘するお話。

こんな失敗もあるんだな、と誰かの知識に繋がれば私の失敗も成仏されると思う👼

# git mergeってやればやるほど良い？（いいえ）

gitを使うのはこれが初めてという事はなく、複数人でのgit管理は3回ほど経験がある。ただどれも大きな規模のものではなく、コミットログを（強く）気にする必要がないレベル。

これまでずっと私はgit mergeはやればやるほど良いと思っていた。理由下記の通り。

- git mergeすればするほど、コンフリクトを発生させずに済み、他メンバーに迷惑をかけないはず。
- git mergeすればするほど、ローカルの開発環境でエラーが出にくいはず。だって最新だもん。

> git mergeすればするほど、コンフリクトを発生させずに済み、他メンバーに迷惑をかけないはず。
> 

**いや、コミットログ汚してるからコードレビューする人、見づらくて堪らんのよ！！！！**

人から指摘されて気付いたが、自分の作業ブランチのコミットログに自分以外の人たちのコミットログがてんこ盛り。
もうどれが私の作業か、全く分からないカオスな状況。

**自分のコードをマージする時にコンフリクトの解消すればいいやん！！！！**

本当うっかりしていた。developブランチが最新になり次第、都度git mergeしてた。大袈裟目に考えると、developブランチが最新になると毎回コンフリクト解消してたという…無駄…。自分のコードをマージするときにコンフリクト解消すれば1回で済むよねっていう話。

> git mergeすればするほど、ローカルの開発環境でエラーが出にくいはず。だって最新だもん。
> 

**いや意味分からん！！！**

当時の私の考えは、
『最新developブランチをmergeすれば、これまでずっとエラーだったところが開発が進んで、エラー出なくなるよね！』
だったが、冷静に考えて自分の開発部分と関係なかったら、他の画面がエラー出してても問題ない。

# おわりに

コードレビューしてもらう先輩の苦い顔をされてた。git mergeはしまくるもんじゃない。最後でいいんだ、最後で。
もし開発途中でdevelopブランチを取り込みたい時は、[git rebase](https://qiita.com/KTakata/items/d33185fc0457c08654a5)等もっと良い方法がある。しっかりgitも勉強して、適切な行動をとっていきたい…。
無料で読める英語の書籍たち

タイトルそのままだが、オンラインで、無料で提供されているありがたい書籍達のリストです。


## プログラマが知るべき97のこと

https://97-things-every-x-should-know.gitbooks.io/97-things-every-programmer-should-know/content/en/

[「プログラマが知るべき97のこと」、自分なら何を書きたいか - Qiita](https://qiita.com/e99h2121/items/c57b6dfdaeda04e882e8)

## 退屈なことはPythonにやらせよう

[O'Reilly Japan - 退屈なことはPythonにやらせよう](https://www.oreilly.co.jp/books/9784873117782/)

https://automatetheboringstuff.com/

![](https://www.oreilly.co.jp/books/images/picture978-4-87311-778-2.gif)

## Think python

[Green Tea Press – Free books by Allen B. Downey](https://greenteapress.com/wp/)
[ThinkPython](https://cauldron.sakura.ne.jp/thinkpython/)

## SRE Books

https://sre.google/books/

![](https://lh3.googleusercontent.com/JvM0JKKuZNJMWAC5iZPm4j-mdS9ORpZbpEWzg0zmJ0i2_xgIcju0OLXJ-zmnvz_GtFFGHe9qZ9Dz-6W0u5fRLFQaRlOI_hGzbetw)


## Linux Command line

https://linuxcommand.org/tlcl.php


## Googleのソフトウェアエンジニアリング

https://abseil.io/resources/swe-book

<img src="https://abseil.io/img/swe_at_google.2.cover.jpg" width=40% />


## Microservice Architecture

[『Microservice Patterns』 まとめ - Qiita](https://qiita.com/yasuabe2613/items/3bff44e662c922083264)

https://microservices.io/

## ハッカーと画家

http://www.paulgraham.com/articles.html

[「ハッカーと画家」は非エンジニアにも読んでほしいオタク野郎の取説 - Qiita](https://qiita.com/e99h2121/items/7187615dfa1d624a8583)

## AWS Cookbook

https://github.com/awscookbook

[はじまりは神本『AWS Cookbook』との邂逅　元アンチCDKの私が「CDK、できる…」と思った理由 - ログミーTech](https://logmi.jp/tech/articles/326643)


## Infrastracture as Code 3章

http://kief.com/

https://www.thoughtworks.com/insights/books/infrastructure-as-code-2nd-edition



## free programming books

https://github.com/EbookFoundation/free-programming-books

https://github.com/EbookFoundation/free-programming-books/blob/main/books/free-programming-books-langs.md


追記していきます～。
takeメソッドについて

### takeメソッド
先頭から任意の数の要素を取得
使い方は下記の通り。

(%w使用し、配列の要素をスペースで区切り配列を作成する)
```
irb(main):040:0> %w(Ruby Python Java C Smalltalk Brainfuck)
=> ["Ruby", "Python", "Java", "C", "Smalltalk", "Brainfuck"]
```

（takeメソッドで先頭から3つの要素を取得）
```
irb(main):041:0> %w(Ruby Python Java C Smalltalk Brainfuck).take(3)
=> ["Ruby", "Python", "Java"]
```
2022/10/11主にITとかセキュリティの記事

XDR（Extended Detection and Response）(10/7)
https://eset-info.canon-its.jp/malware_info/term/detail/00180.html

サイバー攻撃から身を守る4つのステップ(10/9)
https://news.mynavi.jp/techplus/article/20221009-2472064/

安心・とかちの暮らし（１６４）「フィッシング詐欺に気をつけて！」(10/9)
https://kachimai.jp/article/index.php?no=2022913105659

Facebookユーザー100万人のパスワードが盗まれた可能性、Meta発表(10/8)
https://forbesjapan.com/articles/detail/50983

Intel Alder LakeのBIOSのソースコードが流出。ハッキング被害か。4ChanとGitHubにアップされる(10/9)
https://www.nichepcgamer.com/archives/intel-alder-lake-bios-source-code-leaked-online.html

インドでブロックのVideoLAN、反論の機会なければ法的手段も辞さずと(10/9)
https://www.zaikei.co.jp/article/20221009/692641.html

北朝鮮のＩＴ技術者、米サイト登録し外貨獲得…核・ミサイル開発の資金源か(10/8)
https://news.infoseek.co.jp/article/20221008_yol_oyt1t50211/?tpgnr=world

デジタル庁、2022年度のガバメントクラウド対象クラウドサービスを発表(10/9)
https://www.zaikei.co.jp/article/20221009/692645.html

Notionのデータベースを1つのデータベースで管理する(10/9)
https://note.com/okayasu0110/n/nb642478ea4a9
MarkdownからExcelのテスト仕様書を作成するツールを作りました

## はじめに

テスト仕様書は大体Excelのことが多く、バージョン管理と相性悪いので可能ならテキストベースで管理したい。  
そんな悩みは皆さん共通なようで多くの先人たちがMarkdownからExcelに変換するツールを作ってくれています。
* [eval-spec-maker](https://github.com/ryuta46/eval-spec-maker)
* [Markdownのテスト仕様書を管理したい！](https://qiita.com/k-watanb/items/5909704f0e80b1e25d51)

私は当時 `eval-spec-maker` しか知らなかったので、  
プロジェクトでそれを採用しバージョン管理と相性よくて最高！とか思っていました。

ただ、ほかも同様なのですがMarkdownごとに個別のExcelファイルを作ってくれるものの、
最終的なテスト仕様書ってやっぱり1ブックにまとめる羽目になるわけでここが手動なのが最近面倒だなと思うようになりました。
（バージョン管理できるようになっただけでも大変ありがたいのに、欲目が出てきました。）

最初は、出したExcelをまとめるPowerShellでも作ろうかなとも思ったんですが、
結構仕事で使いはじめてきたのでExcel変換部分も自分でプログラム管理しておきたいなということで自分で作ってみました。

## やりたいこと

表紙、変更履歴、とテストケースのテンプレートシートが用意されたExcelのテンプレートファイルを用意して、
テストケースのテンプレートをMarkdownファイル分量産して埋め込んでくれる。
また、最終的にはCIで使えるようにDockerで起動できるようにしたい。

## 言語選定

みんなPythonでやっているし、Pythonでいいか！とか思って始めていると、
私が使っているテスト仕様書がオブジェクトや条件付き書式を設定しており、
`openpyxl` などで破壊されてしまうことがわかりました。

自分の検索力で調べた結果としては自分がやりたいことはJavaのApache POIじゃないとダメそうでした。
今更Java言語で開発する気はないのでKotlinに決めました。

## ライブラリ選定

とはいえApache POI生で使うのはしんどいなーとか。
Markdown Parserないのかなぁとかいろいろ調べた結果以下のライブラリを見つけたので、
こいつで何とか作ろうという結果になりました。

| ライブラリ                                | 用途 |
|:--------------------------------------|:-----|
| [flexmark-java](https://github.com/vsch/flexmark-java) | MarkdownのParser |
| [JXls](https://jxls.sourceforge.net/) | Apache POIベースの Excelテンプレートライブラリ |

## できたもの

> テストケースのテンプレートをMarkdownファイル分量産して

ここの部分はあきらめました。
先にMarkdownファイルの分だけ、埋め込み先のシートを用意しておく必要があります。
とはいえ最初の一回だけなのでそこまで負荷にならないかな？と思っています。

### Markdown

以下のようなMarkdownを用意
```
$ cat ./example/mdSpec.md | head -n 17
# テストケース名

## 大項目１

### 中項目１

#### 小項目１

1. 1-1-1 確認手順1
1. 1-1-1 確認手順2

* [ ] 1-1-1 想定動作1
* [ ] 1-1-1 想定動作2

- 1-1-1 備考1
- 1-1-1 備考2
$ 
```

### テスト仕様書テンプレートファイル

以下のようなテンプレートファイルを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948871/cdd3c546-b56a-0480-2b2c-848026a204da.png)

> :information_source: ：`jx:each` で指定する `items` は `{Markdownファイル名}.cases` になります 

### 実行

```bash
docker run -it --rm \
  -v $(pwd):/workspaces kazuki0529/md-test-spec2excel \
    /workspaces/example /workspaces/template/template.xlsx /workspaces/dist/out.xlsx
```

### できたExcel

こんな感じでそれっぽく出力されました。
上のほうにあるヘッダー（作成日とか作成者）がオブジェクト（カメラ）なのですが消えていませんし、
条件付き書式も無事生き残っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948871/9540b636-5281-1b66-a217-610167cb5915.png)

### リポジトリ

* [GitHub kazuki0529/md-test-spec2excel](https://github.com/kazuki0529/md-test-spec2excel)
* [Docker kazuki0529/md-test-spec2excel](https://hub.docker.com/r/kazuki0529/md-test-spec2excel)

## 最後に

セルの高さを自動調整はできないみたいなのでそこはPowerShellとか使うか、
確認手順や確認項目の行数に応じて行幅をN倍にするとかですかね。
とはいえ一旦実用レベルにはなったような気がしたので公開してみました。

`README.md` が全然整備できてないのでそこも修正したいと思います。