OmniAICreator/Qiita-1.07M huggingface dataset:
DynamoDBで大量データをまとめて書き込みたい

# はじめに
勉強がてら家計簿アプリを作成していた際に詰まった事柄のメモです。
アプリが持つ機能として”毎月のクレジットカード明細を画面上からアップロードできる”機能を持たせようとしていて、
クレジットカード明細は毎月大体100件前後のデータだったので、
画面でポチッとアップロードボタンを押すとすぐ登録処理が完了してほしいと考えていました。

# いざ実装しようとしてみると・・・
ググってみるとDynamoDBで複数件まとめてデータ登録するには"BatchWriteItem"を利用すればよいと分かったので、
１００件ほどのデータをBatchWriteItemでputすると下記エラーにぶち当たりました。
```
 at 'requestItems' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 25, Member must have length greater than or equal to 1]"
```
このタイミングで[BatchWriteItemのAPIリファレンス](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html#API_BatchWriteItem_Examples)を読んで見ると、(←まず最初に読むべきでした)
下記文言が書いてあり、どうやら1度に扱えるデータは25件までとのことが分かりました。
"BatchWriteItem"って名前なのにバッチ処理じゃないじゃん！
```
 A single call to BatchWriteItem can transmit up to 16MB of data over the network, consisting of up to 25 item put or delete operations. 
```

# どうすれば1度にまとめて登録出来るのか
単純に「もし100件登録したいなら4回処理を回せばよいのか？」と思いましたが、実際にその通りでした。

まず登録したいデータを配列に持たせます。
```javascript
let arrayProcessingData = [];

for (let index = 0; index < parsedData.length; index++) {
  //DBに書き込みたい各データを用意する処理部分は割愛
  let addData = {
    id: ID,
    paymentmonth: paymentmonth,
    dateofpayment: parsedData[index].dateOfPayment,
    payer: payer,
    payment: payment,
    paymentdestination: parsedData[index].paymentDestination,
  };
  arrayProcessingData.push(addData);
}
```

次に格納したいデータを25件ごとになるよう、requestArryに格納していきます。
```javascript
let requestArry = [];
let current_requestArry = [];
let item_count = 0;

arrayProcessingData.forEach(function(obj, index) {
  item_count++;
  let requestObj = {
    PutRequest: {
      Item: obj,
    },
  };
  current_requestArry.push(requestObj);
  if (item_count % 25 == 0) {
    requestArry.push(current_requestArry);
    current_requestArry = [];
  }
});

//25件に満たない場合の格納処理
if (current_requestArry.length > 0 && current_requestArry.length != 25)
  requestArry.push(current_requestArry);
```

最後にrequestArryごとにbatchWrite処理を回していきます。
```javascript
for (let x in requestArry) {
  let Dynamo_params = {};
  Dynamo_params = {
    RequestItems: {
      [TABLE_NAME]: requestArry[x],
    },
  };

  try {
    await docClient.batchWrite(Dynamo_params).promise();
    console.log("dynamoへ書き込めた!!");
  } catch (err) {
    console.log("dynamoへの書き込み処理でエラー:", err);
  }
}
return;

```
# 実装後の反省事項
batchWrite時のエラーキャッチが不十分な所もあるのですが、
何よりも[BatchWriteItemのAPIリファレンス](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html#API_BatchWriteItem_Examples)をちゃんと最後まで読めば、サンプル実装文にやりたいことに近いことが書いてあったことを見逃していたことです。
やっぱり公式ドキュメントを見ることは大事だと改めて思い知らされた事柄でした！
ServicePortalで参照フィールドの( i )アイコンを消したい

# ServicePortalで参照フィールドの( i )アイコンを消したい
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/8d9cc3b8-cb36-8284-3e31-116b23dc4f81.png">

## 経緯
サービスポータルでカタログアイテムを作っている時、参照フィールドにつく( i )のアイコンが邪魔だなと感じた。
参照しているレコードの余計な情報まで見えちゃうし、権限によっては修正できちゃうし。そんなことは望んでいないのだ。
参照フィールドに[辞書属性](https://docs.servicenow.com/ja-JP/bundle/sandiego-platform-administration/page/administer/reference-pages/concept/c_DictionaryAttributes.html)の `ref_decoration_disabled=True` をつけてみたが、特に変化は見受けられない。なんなの。[^1]
どうしたもんかとコミュニティ投稿を探ってみたら見つけられたので備忘録として。
(2023/02/21追記)誤記修正ついでにTokyoバージョンのEmployee Centerでも確認しましたが、同様でした。

## 前提条件
- PDIのSun-Diegoで確認
- adminユーザーで操作
- テスト用のカタログアイテムでの初期表示はこちら
    ![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/9e385360-c4b4-2b7e-3e4e-d897a132e143.png)

## すべての参照フィールドから( i )アイコンを削除する場合
1. [Service Portal] > [Portals]を開く
1. 設定したいレコードを開く
1. [CSS変数]のセクションで、以下を追記する
    ```CSS:CSS
    .add-on > button.lookup {
        display:none;
    }
    ```
    ![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/b54db837-bec5-14cb-441c-bbbdc464e6f3.png)

1. レコードを更新する
1. ポータルで結果を確認する
    ![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/aa5e79a3-0c4f-12ac-9883-455a69934451.png)


## 特定の参照フィールドのみ( i )アイコンを削除する場合
※「特定のフィールド」がたくさんあるとあまりオススメできない。
1. ブラウザの開発者ツールなどで、要素のIDを確認する
    Chromeでの例
    1. [F12]キーで開発者ツールを開く
    1. [要素]タブから、( i )アイコンを含むフィールドの `<span>` タグを見つける(画面のハイライトを見ながら)
    1. id部分を `右クリック > [属性を編集]` でidをコピーする(画像だと「sp_formfield_reference_ref2」)
    ![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/164ccf09-2f81-3824-23e6-abd19f135c97.png)

1. [Service Portal] > [Portals]を開く
1. 設定したいレコードを開く
1. [CSS]のセクションで、以下を追記する
    ```CSS:CSS
    #sp_formfield_reference_ref2 > .add-on > button.lookup {
     display:none;
    }
    ```
    ![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/8c191e56-5e0b-253d-eeaf-dc2456348842.png)

1. レコードを更新する
1. ポータルで結果を確認する
    ![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/3e9fa947-e684-04e5-a41d-81ebb96e92ae.png)

以上


# 参照したコミュニティ投稿記事

https://community.servicenow.com/community?id=community_question&sys_id=a6786347dbd3c550be625ac2ca9619de

https://community.servicenow.com/community?id=community_question&sys_id=c4544a5edb9d20509e691ea6689619f5

https://community.servicenow.com/community?id=community_question&sys_id=e02fc3e1dbdcdbc01dcaf3231f96191f

# おまけ
[^1]:辞書属性について
サービスポータルでは反応しないが、クラシックUIではちゃんと動作するようだ。
    1. 対象のフィールドのAttributesに `ref_decoration_disabled=true` を追加する。
        すでに記載がある場合はカンマ区切りで追加。
    ![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/ac297ef0-f67a-ae29-fad8-b15cc898a62a.png)

    1. フォームで結果を確認する
        画像の上側が属性なし(未定義 or false)、下側が属性を有効化後。
        ![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2841320/dd876654-02f5-b9a7-d232-93e5a43c132a.png)
【Ruby】配列要素を集計したい！

# はじめに

配列要素を集計したいときの書き方をいくつかまとめました。

次のようなユーザー配列について、出身地別のユーザー数を求めることを考えます。

```ruby
# 集計したいユーザー配列
user_list = [
  { user_id: 1, hometown: '東京都' },
  { user_id: 2, hometown: '大阪府' },
  { user_id: 3, hometown: '東京都' },
  { user_id: 4, hometown: '北海道' },
  { user_id: 5, hometown: '大阪府' },
  { user_id: 6, hometown: '東京都' }
]
# 出身地ごとの人数を次のようにハッシュにまとめたい
{"東京都"=>3, "大阪府"=>2, "北海道"=>1}
```

※ サンプルコードの実行環境

```bash
$ ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
```

# 方法1: 手続き的に書く

```ruby
result = {}
user_list.each do |user|
  result[user[:hometown]] ||= 0
  result[user[:hometown]] += 1
end
result
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
```

もう少しRubyらしく書きたいですね。

# 方法2: `group_by`を使う

```ruby
user_list.group_by { |user| user[:hometown] }.transform_values(&:length)
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
```

最初に空ハッシュを用意する必要がなくなり簡潔な記述になりました。

# 方法3: `tally`を使う

```ruby
user_list.map { |user| user[:hometown] }.tally
# => {"東京都"=>3, "大阪府"=>2, "北海道"=>1}
```

Ruby2.7で追加された比較的新しいメソッドである`Enumerable#tally`を使ってシンプルに記述することもできます。

# 参考

- [Enumerable#group_by (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html)
- [Enumerable#tally (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/tally.html)
- [Ruby 2.7.0 リリース](https://www.ruby-lang.org/ja/news/2019/12/25/ruby-2-7-0-released/)
Kms Encrypt Decrypt をCliで行う


aws-cli で文字列をencrypt・decryptしたメモ。

# Encrypt

１回目以下でためしたところ

```
aws kms encrypt --key-id 'kms key id' --plaintext 'my plain text' --profile 'my profile'
Invalid base64: "my plain text"
```
上のようなエラーになる。

そこで以下のようなコマンドでencryptコマンド実行する。
```
aws kms encrypt --cli-binary-format raw-in-base64-out --plaintext 'my plain text' --key-id 'kms key id' --profile 'my profile'

{
    "CiphertextBlob": "ciphertext...",
    "KeyId": "arn:aws:kms:ap-northeast-1:MY_AWS_ACCOUNT_ID:key/kms key id",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
```

上のコマンドで正常に実行されて、CiphertextBlobを確認できる。


# Decrypt
```
aws kms decrypt --key-id 'kms key id' --profile 'my profile' --ciphertext-blob "ciphertext..."

{
    "KeyId":"arn:aws:kms:ap-northeast-1:MY_AWS_ACCOUNT_ID:key/kms key id",
    "Plaintext": "bXkgcGxhaW4gdGV4dA==",
    "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
```
このようにPlaintextがbase64で表示される。

```
aws kms decrypt --key-id 'kms key id' --profile 'my profile' --ciphertext-blob "ciphertext..." --query Plaintext --output text | base64 -d

my plain text
```

decryptして入力の文字列と同じ値になっていること確認できました。
Dataverseのテーブルを作成時、プライマリ列を設定する必要があります

Dataverseのテーブルを作成時、プライマリ列を設定する必要があります。
設定しないと、デフォルトは「name」になります。
修正できないので、プライマリ列を再設定したら、テーブルを削除し、再作成になってしまいます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/c4c745db-b388-2963-419f-d5637d8b4613.png)
【SpringSecurity】認証を行うカラムを変更する


# はじめに
SpringSecurityを使ったログイン機能を作成した際に、SpringSecurityの認証に関してネット上で調べていたら、ほとんどがDBのカラム名が「username」と「password」で行っているものばかりで、どうにか「userid」カラムで認証できないかと思い調べて実装できたのでメモ（簡単に）

# 結論

```:AccountRepository.java

-public interface AccountRepository extends JpaRepository<Account, Integer> {

	public Account findByUserid(String userid);
}

```

これでとりあえずはuseridカラムでの認証可能。
「findBy + カラム名（最初は大文字）」で好きなカラム名にできる。

まだ実装段階なので不具合などの可能性もありますが…

# 前提
SpringSecurityの実装済み。
コンピュータ マウスが機能しない場合の対処方法

私たちの多くは、コンピューターのマウスがコンピューター システムの最も重要な部分であることを知っていますが、理由もなく動作しなくなることがあります。では、PC でマウスとキーボードを使用できない場合はどうしますか?

私たちはコンピュータ時代の初めからマウスとキーボードを使用してきましたが、現在ではこの 2 つの代わりにタッチ スクリーンが使用されています。タッチ スクリーンを使用している場合は、マウスとキーボードを使用する必要はありません。ただし、通常の PC を使用していて、タッチ スクリーンに切り替えたくない場合は、問題ありません。

## ユーザーが直面する最も一般的な問題のいくつかは次のとおりです。

### ラップトップがマウスを検出しない

これは、初心者の間で最も一般的な問題です。電源ボタンが機能していないときに発生します。ラップトップを再起動して 10 ～ 15 分待ってから、マウスとキーボードを使用してみてください。

### マウスをクリックしても PC が応答しない

これは 2 番目に多い問題です。マウスをクリックすると、カーソルが画面に表示されます。ただし、マウスが機能しない場合もあります。この場合、F11 キーを押して PC を再起動する必要があります。

### マウスがフリーズしています

これは 3 番目に多い問題です。マウスがフリーズしている場合は、マウスをゆっくり動かしてから、もう一度クリックしてみてください。それでも動作しない場合は、USB ケーブルを取り外して再接続できます。

### ボーナスのヒント

始める前に、[Joltfly](https://joltfly.com/ "Joltfly") という名前の Web サイトからこの素晴らしい [mouse test](https://joltfly.com/mouse-test/ "Mouse Test") をチェックして、問題をよりよく理解できることを言及しておく価値があります。マウスまたはタッチパッドで。

### ほこりをきれいにする

これは、ラップトップのマウスが機能しない一般的な理由の 1 つです。この背後にある理由はほこりであり、定期的にほこりを掃除していないと、マウスが機能しなくなります。そのため、ほこりをきれいにしてきれいな布で拭く必要があります。

### 新しいドライバーをインストールする

あなたはラップトップを持っていて、古いドライバーを使用しています。新しいドライバーをインストールして、システムを再起動する必要があります。ドライバが正しくインストールされていないと、マウスが機能しなくなります。

### ラップトップを再起動します

マウスの問題を解決できない場合は、ラップトップを再起動する必要があります。ラップトップを再起動するには、電源ボタンを 10 秒間押し続ける必要があります。

＃＃＃ 結論

コンピューターのマウスを機能させたい場合は、上記のヒントに従う必要があります。これらのヒントは非常にシンプルで従うのが簡単で、ほんの数分で目的の結果が得られます.
AIの前処理をOpenCVで行うときによく使う処理

・BGRからRGBへチャンネルの順序変更
・画素値正規化
・点順次(NHWC)から面順次(NCHW)へ形式変更

```
cv::Mat img_rgb(img.size(), img.type());
int from_to[] = { 0,2, 1,1, 2,0 };  // BGR->RGB
cv::mixChannels(&img, 1, &img_rgb, 1, from_to, 3);

cv::Mat img_rgb_float;
img_rgb.convertTo(img_rgb_float, CV_32F);
img_rgb_float *= 1. / 255;

// 点順次から面順次
cv::Mat tmp[3];
cv::split(img_rgb_float, tmp);
cv::Mat dst;
cv::vconcat(tmp, 3, dst);
```
【JavaScript】-(ハイフン)が入っているオブジェクトのプロパティを取得する

<h2>問題</h2>
以下のような-(ハイフン)が入っているオブジェクトのプロパティを取得する時に詰まったのでメモです。

```
const obj = {
    key: "value",
    "my-key": "my-value"
};
```

<h2>解決策</h2>
以下の記法(ブラケット記法)だとうまくいきます。

```
obj["my-key"]
```

<h2>過程</h2>
真っ先に思いついた以下の記法(ドット記法)だと取得することができませんでした。

```
obj.my-key // NG
```

変数名に-を使うことは**基本的にNG**だそうです。
同様にプロパティ名にもNGです。
文字を区切りたいときは-ではなく_を使うほうが良いみたいです。

ただし、フロントエンド開発でダミーデータが用意されていて、プロパティ名に-が入ってることもあるかもしれません。
そのような時はブラケット記法でオブジェクトにアクセスすることができます。

<h2>参考</h2>
<a href="https://jsprimer.net/basic/object/">JavaScript Primer</a>
ヘッドレスCMSでの、フリガナや傍点の実現方法

# TL;DR
フリガナや傍点による表記に対応していないヘッドレスCMSにおいて、特定のマークダウン記法を利用することで、それらの表記を実現しました。

# 背景
弊社で運営している[メディア](https://fashiontechnews.zozo.com/)では、[microCMS](https://microcms.io/)というヘッドレスCMSを利用しています。とても便利で使いやすく、使用方法の[説明ブログ](https://blog.microcms.io/)も充実しています。

ただ、[リッチエディタ](https://document.microcms.io/manual/how-to-use-richeditor)では、HTMLタグを使えない仕様になっています。それについても対処法は[丁寧に説明](https://blog.microcms.io/input-richeditor-and-html/)してくださっているのですが、フィールドを切り替えるのが少し大変です。

特に今回は、文章中に<ruby>フリガナ<rt>ふりがな</rt></ruby>や<ruby>傍点<rt>・・</rt></ruby>をふりたかったため、文章ごとに切り替えるのは大変で現実的ではありませんでした。そのためいくつか工夫を加えて、フリガナと傍点を実現しました。

# 解決策
非エンジニアが利用するツールなので、書きやすい記法が必要でした。そのためHTMLタグではなく、Markdownの記法を利用することとしました。
また、リッチエディタのフィールドでのみ解決するのではなく、様々な場所で広く使えるということも考慮に入れました。

## それぞれの解決策
### フリガナ
`{フリガナ|ふりがな}`という記法を検知して、rubyタグを使った`<ruby>フリガナ<rt>ふりがな</rt></ruby>`に置き換え、<ruby>フリガナ<rt>ふりがな</rt></ruby>を表示できるようにしました。

### 傍点
`《《傍点》》`という記法を検知して、CSSのtext-emphasisを適用し、<ruby>傍点<rt>・・</rt></ruby>を表示できるようにしました。

## なぜそれぞれで解決策を分けたのか？
当初は、傍点もフリガナと同じ記法で利用していましたが2つの問題が発生しました。
1. 1文全体など長い範囲に傍点をふりたい場合に、文字数を数えるのが大変
1. 画面幅が狭く、傍点をふっている文章に改行が入ってしまうと対応できず、改行がおかしくなる

2つ目の問題については、改行が入ってしまうと傍点が１行目に偏り、改行位置も文字間もおかしくなってしまいます。
![傍点のスタイル崩れ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146971/02d773b6-966a-565c-75d5-b95fc723f5c8.png)


# 実装
適用したいフィールドの全ての文字列で、正規表現を用いて該当のMarkdown記法を検知し、それぞれ置き換えを行いました。

```tsx
const replaceToRubyTags = (text: string): string => {
  // {漢字|かんじ}のようなMarkdown記法を検知できる正規表現
  const regex = /{([^{|]+)\|([^|}]+)}/g
  const replaceTag = '<ruby>$1<rt>$2</rt></ruby>'
  return text.replaceAll(regex, replaceTag)
}

const replaceToEmphasis = (text: string): string => {
  // 《《傍点》》のようなMarkdown記法を検知できる正規表現
  const regex = /《《([^《》]+)》》/g
  const replaceTag = "<span style='text-emphasis:filled'>$1</span>"
  return text.replaceAll(regex, replaceTag)
}
```

今回のMarkdown記法は、いくつかのMarkdownで使われているものの中で、通常の文章表現では出現しにくいものという観点で選びました。


# まとめ
フリガナや傍点による表記に対応していないヘッドレスCMSにおいて、それらを表示する工夫についてお伝えしました。参考になりましたら幸いです。
Xbox コントローラーのジョイスティックが機能しないのはなぜですか?

Xbox コントローラーを使用している場合は、コントローラーが応答しなくなったり、ジョイスティックが正しく機能しないことがあることに気付いたはずです。この問題は、いくつかのトリックを適用することで簡単に修正できます。

ジョイスティックの問題を解決しようとしている場合は、特定の理由で問題が発生する可能性があることを知っておく必要があります。一般的な理由のいくつかは次のとおりです。

最も重要なことは、ゲームパッド コントローラーのトラブルシューティングを行う前に、この (Web サイト : https://gamepadtest.com) でコントローラーをチェックして、コントローラーの誤動作を再確認し、誤動作の根本原因を見つけることです。

## バッテリー

長時間使用すると電池が消耗し、ジョイスティックが正常に動作しなくなることがあります。

## ハードウェアの損傷

中古のジョイスティックを使用している場合は、破損している可能性があります。

## 解決

ジョイスティックの問題を解決するのは簡単ですが、次のヒントに留意してください。

### 1. 新しいジョイスティックを使用する

新しいジョイスティックは古いジョイスティックよりもはるかに優れています。古いジョイスティックを使用している場合、ジョイスティック自体に損傷を与える可能性があります。

### 2. 電源を切断します

電源を切断するには、スイッチをオフにする必要があります。

### 3. 電池を交換する

ジョイスティックが機能しない場合は、電池を交換する必要があります。

### 4.接点をきれいにする

コンタクトを適切に動作させるには、コンタクトをクリーニングする必要があります。

### 5. 圧力をかける

ジョイスティックを使用できない場合は、ジョイスティックに圧力をかける必要があります.

### 結論
これらのヒントを適用することで、ジョイスティックの問題を簡単に修正できます。記事が気に入っていただければ幸いです。そのようなゲームの記事をさらにお楽しみに。
TFLint 0.40.0へのVerUpで既存コードがエラー

# 現象

CI/CDパイプラインで、Terraformの静的解析にTFLintを使っていた。
ある日突然、これまで問題なかった既存コード部分で急にエラーが出るようになった。

# 原因

TFLintのバージョンアップ（0.39.3->0.40.0）で、
* terraform_required_version
* terraform_required_providers

のチェックがデフォルトでEnableとなったこと。

Terraformコードが
```
 ├ backend
 ├ modules <- モジュールとして切り出し
 └ hoge <- 実行用ディレクトリ。modulesを読み込んで利用。
```
のような構成となっており、version/providerの記述はhoge内のみだったため、
modules内のコードに対して、上記チェックがエラーになっていた。

# 解決策
バージョン固定すると、バグfixや有用な修正があっても入らなくなってしまうので、やりたくない。
以下の記述を追加し、当該チェック内容をDisableにすることで対応。

#### .tflint.hcl
```
rule "terraform_required_version" {
  enabled = false
}

rule "terraform_required_providers" {
  enabled = false
}
```

# 感想
モジュール化すると、同じ現象に遭遇する気がする。
Terraform的にモジュール化をおススメしないということはないと思うが、この変更はどういう意図なんだろう。
地図に情報をビジュアライズする方法

Tableauの自己学習を行い、自分の振り返りをかねて拙い文ではありますがまとめました。

__使用環境__
・Tableau Public（無料）

__使用データ__
・新型コロナウィルス感染症対策
全国の感染者数　オープンデータ
https://corona.go.jp/dashboard/

こちらの下記URLをクリックするとjson形式でダウンロードします。
https://opendata.corona.go.jp/api/Covid19JapanAll

## データの準備と読み込み
上記サイトでオープンデータをダウンロードしてこちらをTableau Publicに読み込んで実施します。

ダウンロードが完了したら、Tableau Publicを立ち上げて、ダウンロードしたjsonファイルを読み込みます。
![スクリーンショット 2022-09-28 11.35.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591484/7fe084e8-508c-9707-d7b7-8df6e513cd03.png)



## データのビジュアライズ

今回のデータは都道府県ごとにコロナ感染者数が累計でカウントされているデータとなってます。今回は、最新の日付で都道府県別のコロナ感染者数を地図で表示するという形にしたいと思います。

__・手順１__
今回のデータがNpatiNpatientsが感染者数ですが、文字列のデータとなっております。それだと地図でのマッピングができないので数字のデータ形に変更します。
![スクリーンショット 2022-09-28 12.27.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591484/185faffd-d58b-b648-c143-08af65633097.png)

上記画像は文字列型のデータのNpatientsをINT型に変更するよという処理になります。

__手順２__
今回は地図として使用したいため、ディメンションのName jpが都道府県に値するデータとなります。これをクリックし、地理的役割、都道府県/州をクリックする。
![スクリーンショット 2022-09-28 12.30.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591484/fd37527b-b691-5999-fb83-233d2d1e1d75.png)

__手順３__
Name jpをダブルクリックし、ビジュアライズされ、下記画像のように列に経度（生成）、行に緯度（生成）という形で自動的に表示されます。今回は、感染者数の数を都道府県別で色で表現するため、1で作成した感染者数を下記のように入れます。
![スクリーンショット 2022-09-28 12.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591484/961d3178-35be-bb56-feab-27c693c379b7.png)

__手順４__
次に、感染者数を色でどこが多いのかと、何人なのかを把握するためにテキストで表示する。
![スクリーンショット 2022-09-28 12.50.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591484/75e9a98c-a67b-0b30-83fb-126fde5c8a7c.png)

このようにして、地図に情報をビジュアライズすることができました。




ここまで読んでくださりありがとうございました。
少しでも、参考になれば幸いです。
【Ruby】sortとsort_byってどう違う？

# はじめに

Rubyで配列要素を並び替える際に使う`sort`/`sort_by`メソッド。
名前も役割も似ているメソッドですが、その呼び出し方や内部挙動は大きく異なります。
この記事では2つのメソッドの違いをまとめました。

※ サンプルコードの実行環境

```bash
$ ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
```

# `Enumerable#sort`

全要素を昇順ソートした配列を生成して返します。
ブロックがない場合は、要素そのものを`<=>`で比較してソートします。

```ruby
ary = (1..10).to_a.shuffle
# => [3, 4, 1, 8, 10, 9, 6, 2, 7, 5]
ary.sort
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

ブロックが渡された場合は、ブロックの評価結果を用いてソートします。

```ruby
ary = [{:id=>1, :name=>"Taro"}, {:id=>2, :name=>"Hanako"}, {:id=>3, :name=>"Ichiro"}]
ary.sort { |a, b| a[:name] <=> b[:name] }
# => [{:id=>2, :name=>"Hanako"}, {:id=>3, :name=>"Ichiro"}, {:id=>1, :name=>"Taro"}]

# 降順ソート
ary.sort { |a, b| b[:name] <=> a[:name] }
# => [{:id=>1, :name=>"Taro"}, {:id=>3, :name=>"Ichiro"}, {:id=>2, :name=>"Hanako"}]
```

# `Enumerable#sort_by`

ブロックの評価結果を`<=>`で比較して、全要素を昇順ソートした配列を生成して返します。

```ruby
ary = [{:id=>1, :name=>"Taro"}, {:id=>2, :name=>"Hanako"}, {:id=>3, :name=>"Ichiro"}]
ary.sort_by { |user| user[:name] }
# => [{:id=>2, :name=>"Hanako"}, {:id=>3, :name=>"Ichiro"}, {:id=>1, :name=>"Taro"}]

# 数値による降順ソートは負の数を使えば可能
ary.sort_by { |user| -(user[:id]) }
# => [{:id=>3, :name=>"Ichiro"}, {:id=>2, :name=>"Hanako"}, {:id=>1, :name=>"Taro"}]

# 文字列による降順ソートは「Array#reverse」を使うなどの工夫が必要
ary.sort_by { |user| user[:name] }.reverse
# => [{:id=>1, :name=>"Taro"}, {:id=>3, :name=>"Ichiro"}, {:id=>2, :name=>"Hanako"}]
```

ブロックがない場合はEnumeratorを返します。

# 内部挙動の比較

`sort`と`sort_by`ではブロック評価の呼び出し回数が異なります。
[Enumerable#sort_by (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/sort_by.html)にもあるように、ブロック評価が行われる度にグローバル変数`$n`を増やす方法で回数を確認してみます。

```ruby
class Integer
  def count
    $n += 1
    self
  end
end

# 並び替えを行う配列
ary = (1..10000).to_a.shuffle
```

**`Enumerable#sort`の場合**

```ruby
$n = 0
ary.sort { |a, b| a.count <=> b.count }
# => [1, 2, ..., 10000]
$n
# => 273696
```

`sort`では要素比較する度にブロック評価が行われます。

**`Enumerable#sort_by`の場合**

```ruby
$n = 0
ary.sort_by { |i| i.count }
# => [1, 2, ..., 10000]
$n
# => 10000
```

`sort_by`でブロック評価が行われる回数は、配列の要素数と等しくなります。

したがって実行パフォーマンスの観点から、ブロックを渡して呼び出す場合は`sort_by`を使った方が良いとわかります。

# まとめ

- 配列要素そのものでソートする場合、`sort`を使えばブロックを渡さずに書ける
- ブロックを渡すなら`sort_by`を使う方が良い
    - `sort`では要素を比較する度にブロック評価が行われる
    - `sort_by`では各要素に対して1回ずつブロック評価が行われる

# つぶやき

この記事を書く中で、`<=>`には「三方比較演算子」以外に「宇宙船演算子」という呼び方があることを知りました。
みなさん`<=>`をどうやって呼んでいるのでしょうか。
(wikipediaのページタイトルを踏まえると、もしかしたら「宇宙船演算子」の方が一般的な呼び方なのかも…？)

# 参考

- [Enumerable#sort (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/sort.html)
- [Enumerable#sort_by (Ruby 3.1 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/sort_by.html)
- [宇宙船演算子 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%AE%87%E5%AE%99%E8%88%B9%E6%BC%94%E7%AE%97%E5%AD%90)
iOS15以降のクラッシュログ解析

![Xcode-13.1](https://img.shields.io/badge/Xcode-13.1-brightgreen) 

## はじめに
iOS15 のクラッシュログのフォーマットが変わっており symbolicatecrash だと解析できずわりとつまづいたので備忘録。

symbolicatecrash じゃなくて CrashSymbolicator.py を使うらしいです。

https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes

> To support the new JSON-format crash logs generated in macOS Monterey and iOS 15, Instruments includes a new CrashSymbolicator.py script. This Python 3 script replaces the symbolicatecrash utility for JSON-format logs and supports inlined frames with its default options. For more information, see: CrashSymbolicator.py --help. CrashSymbolicator.py is located in the Contents/SharedFrameworks/CoreSymbolicationDT.framework/Resources/ subdirectory within Xcode 13. (78891800)

## 使うやつ
* dSYM ファイル
* クラッシュログ（拡張子 ips のやつ）
* CrashSymbolicator.py

## dSYM取得
Debug Information Format を DWARF with dSYM File にして ipa を作成する。

<img width="600" alt="dsym" src="https://user-images.githubusercontent.com/34936885/192680388-ee7ae904-7e4c-4fd3-8afb-6a80b853185d.png">

xcarchive ファイルを開くと下記のように dSYM ファイルがあるので取得する。

<img width="300" alt="archive" src="https://user-images.githubusercontent.com/34936885/192680369-7c5ca71e-0eb7-449e-b8a5-de7edc6a2df3.png">

## クラッシュログ取得
実機に ipa を入れてクラッシュさせる。
（実機をつないで Xcode の Window > Devices and Simulators からインストールできるらしい）

実機の設定 > プライバシー > 解析および改善 > 解析データで該当アプリを検索してログを取得する。
（共有 > AirDrop で Mac に送れる）

## シンボル化
ついにシンボル化！

クラッシュログと dSYM ファイルを同じフォルダに配置する。

<img width="193" alt="directory" src="https://user-images.githubusercontent.com/34936885/192680418-65ab4f95-b7ee-432c-b3fb-2752acf1743b.png">

1. ターミナルを開いて cd で該当フォルダに移動
2. 下記コマンド実行  
    ```
    python3 /Applications/Xcode.app/Contents/SharedFrameworks/CoreSymbolicationDT.framework/Resources/CrashSymbolicator.py -p foo.ips -d Foo.app.dSYM -o piyo.ips
    ```

piyo.ips がシンボル化されたログです:confetti_ball:

## おわりに
symbolicatecrash でやると No crash report version になり dSYM が違うのか？とかわりと悩みましたが iOS 15 からは CrashSymbolicator.py を使うようです。

あまり CrashSymbolicator.py を使う機会はないかもしれませんが:innocent:

## 参考
* [iOSアプリケーションのクラッシュログを見つける方法とiOSのクラッシュログをシンボル化する方法](https://qiita.com/MaShunzhe/items/1c98dcb07fd63e756589)
* [実機デバッグしたときにクラッシュログを端末から取得する](https://qiita.com/ichikawa7ss/items/9d53301c67449831a94e)
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その037

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: データと自動化
データ管理と分析管理の演習

にある練習問題5問目をご紹介します

今回の内容は動画でも解説してあります

https://www.youtube.com/watch?v=P1MhwvJDHUs


<iframe width="560" height="315" src="https://www.youtube.com/embed/P1MhwvJDHUs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

問題はこちらです

![コンポーネント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ad937646-762e-9118-8fe0-50394dffb997.png)

正解はCです

コンポーネントは20個までです

２０個以上だとこのようなエラーが出ます

ダッシュボードごとに保存または作成できるダッシュボードコンポーネント数は 20 個以下です。 保存するには、まずダッシュボード検索条件のエラーを解決してください。

![エラー０１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/300b7644-a9b7-fa26-9852-eda1ad2d0bf6.png)



３個や１５個で作成成功。
２０個以上でエラーが出ることは動画でも確認できます

ご確認ください


<iframe width="560" height="315" src="https://www.youtube.com/embed/P1MhwvJDHUs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
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/ku_a_i/items/9c68e8aed3c2c066bc60

# Ruby

https://qiita.com/mzmz__02/items/0f73224dd77fe7d24c1b

# PHP

https://qiita.com/mpyw/items/b00b72c5c95aac573b71

# Java

https://qiita.com/zaburo/items/b8c2ab8db7b972d614e7

# JavaScript

https://qiita.com/mzmz__02/items/6e85c1210824d55f64f2

# Perl

https://perlzemi.com/blog/20170130148603.html
【Flask】 flask-mailでメールを送信する

## flask-mailでGmailを使ったメールの送信方法を確認する

### Code

```send_mail.py
from flask import Flask
from flask_mail import Mail, Message

app = Flask(__name__)

app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587                             # TLSは587、SSLなら465
app.config['MAIL_USERNAME'] = 'your_id@gmail.com'
app.config['MAIL_PASSWORD'] = 'Gmail app password'        # GmailのApp用のmパスワード設定をしておく必要あり
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USE_SSL'] = False
app.config['MAIL_DEFAULT_SENDER'] = 'your_id@gmail.com'    # これがあるとsender設定が不要になる
mail = Mail(app)


@app.route('/')
def index():
    return """
    <p><a href="/send_mail">Send Mail</a></p>
    """


@app.route("/send_mail")
def send_mail():
    msg = Message('Test Mail', recipients=['xxx@gmail.com'])
    msg.body = "Hello Flask message sent from Flask-Mail"
    mail.send(msg)
    return "Sent"


if __name__ == ('__main__'):
    app.run(host='0.0.0.0', port=5050, debug=True)
```
#### 送信前
![index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699739/d5d3a5d7-86bc-24e5-61c7-633fd888e6c9.png)

#### 送信後
![send_mail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699739/acb6b020-6b71-6b64-3608-f907e07f97a8.png)
[npm]エラー"npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead"の対応

# エラー
laravelのLaravel Breezeの環境構築過程で`php artisan breeze:install`を実行していると、
下記エラーによって正常に処理が実行されなかった
```
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead
```
試しに、`npm -g update`をしたところ、同様のエラーが2回繰り返して出てきた。
※補足に全文を記載

### エラーのDeepL日本語訳
npm WARN config global `--global`, `--local` は非推奨です。代わりに `--location=global` を使ってください。

# 環境
- Windows10
- npm version:8.11.0

#　対応方針と対応結果概要
同じエラーに対しての解決法を発見したので、以後そのやり方で実施。
https://stackoverflow.com/questions/72401421/message-npm-warn-config-global-global-local-are-deprecated-use-loc

結果として、実行できていなかった`php artisan breeze:install`は正常に実行されるようになった。
ただ、`npm -g update`においては、2回表示されていたエラーが１回になったのみだった。
処理自体はうまくいってるので今日はここまでとする。


# 解決手法
どうやらconfigで`--global`, `--local`という部分の記載方法が `--location=global`に変更になったということらしい。
よって、解決方法はconfigファイルを編集すればよいはず。

### 設定ファイル
- C:\Program Files\nodejs\npm.cmd
- C:\Program Files\nodejs\npm

### 変更箇所
- 'C:\Program Files\nodejs\npm.cmd' 12行目
    ```
    変更前
    FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO (
    変更後
    FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix --location=global') DO (
    ```
- 'C:\Program Files\nodejs\npm' 23行目
    ```
    変更前
    NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix -g`
    変更後
    NPM_PREFIX=`"$NODE_EXE" "$NPM_CLI_JS" prefix --location=global`
    ```

# 補足
- `npm -g update` 実行結果　対応以前
    ```
    C:----> npm -g update
    npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
    npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
    
    added 2 packages, removed 2 packages, changed 317 packages, and audited 320 packages in 3m
    
    42 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    
    ```
- `npm -g update` 実行結果　対応後
    ```
    C:---->npm -g update
    npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
    
    changed 319 packages, and audited 320 packages in 3m
    
    42 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
    ```

- php artisan breeze:install` 実行結果　対応前
    ```
    C:---->hp artisan breeze:install
        npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
    ```
- php artisan breeze:install` 実行結果　対応後 
※別のエラーが出たがこれは本件とは別のため詳細は記述しない
    ```
    C:---->php artisan breeze:install
    
    up to date, audited 767 packages in 5s
    
    79 packages are looking for funding
      run `npm fund` for details
    
    found 0 vulnerabilities
        npm ERR! Missing script: "build"
    npm ERR!
    npm ERR! To see a list of scripts, run:
    npm ERR!   npm run
    
    npm ERR! A complete log of this run can be found in:
    npm ERR!     C:\Users\[user_name]\AppData\Local\npm-cache\_logs\2022-09-28T02_37_18_215Z-debug-0.log
    
       INFO  Breeze scaffolding installed successfully.
    
    ```
Streamlitで複数ページのWebアプリを作る【2022年版】

以前、[Streamlitで複数ページのWebアプリを作る](https://qiita.com/yoichi_t/items/e9759f1f2253f8106d78)という記事を書きましたが、公式に複数ページアプリの対応がされたようなので試してみました。


## これまではどうしていたか？

これまでもマルチページなアプリを作ることはできていましたが、裏技的な操作が必要でした。

https://qiita.com/yoichi_t/items/e9759f1f2253f8106d78


## MultiPageなアプリの作成

[公式ドキュメント](https://docs.streamlit.io/library/get-started/multipage-apps)があるので、そちらを確認してもらうのが早いと思います。
以下、私の理解を書き連ねておきます。

### 構成

複数ページのアプリを作成するためには、基本的にはページに対応するpythonファイルを置くだけです。

ホームに対応するpythonファイルと同じディレクトリに、 `pages` ディレクトリを作成し、その下にpythonファイルを配置します。その他のディレクトリにファイルがあっても無視されるようです。

```
- src
  |- home.py
  |- pages/
       |- page1.py
       |- page2.py
```

これで、 `home.py` をrootに、サイドバーに `page1`、`page2` が表示されるようになります。
↓こんな感じでページへのリンクがサイドバーに固定表示されます（下図オレンジで囲った部分）。

![スクリーンショット 2022-09-28 9.48.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66005/e49fbff8-d475-da27-ed8b-76b61fc763d9.png)


### サイドバーに表示されるページ名のルール

表示ルール、表示順のルールについては[公式ドキュメント](https://docs.streamlit.io/library/get-started/multipage-apps#how-pages-are-labeled-and-sorted-in-the-ui)が正確なのでこちらを見てもらえればと思います。

#### ファイル名の構成要素

以下のような構成でファイル名をブロックにわけて扱うようです。

```
{prefix}_{label}.py
```

- prefix: 数値
- separator: `_`, `-`, (space)
- label: prefixを除いた文字列

なお、これらの3つの要素全てを備えている必要はありません。

#### 表示順序

1. prefixがあれば、prefix（数値）でソート
2. prefixがなければ、labelでソート
    - label部分に数値があっても、prefixではないのでその値でソートはされない

#### 表示ページ名

prefixは削除され、label部分がサイドバーに表示されます。
このとき、separatorはスペースに変換されます。

```
e.g.　　　　　　　　　ファイル名    ->   表示名 
    [1_sample_1.py] -> [sample 1]
    [sample_1.py]   -> [sample 1]
```

先頭に数値を持ってきたい場合には、prefixを付けるか、`_`などのseparatorを追加すれば良いです。

```
e.g.  　　　　ファイル名     ->   表示名 
    [_1_sample.py]  -> [1 sample]
    [0_1_sample.py] -> [1 sample]
```

こんな感じ。


### 実際にやってみる

https://github.com/tok41/try_streamlit

`src` 以下にstreamlitのファイルを置いています。
その他は環境構築関係なので、無視しちゃってOKです。

### できたもの

できたものはこんな感じ（あまり意味はないけど、ベータ分布とディリクレ分布を可視化してみた）。

![streamlit_multi_app_sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66005/c6b70376-86ab-278d-19a1-b953d8bf24c6.gif)

ファイルを置いておくだけでMulti Pageなアプリができました。


## 参考

- [Multipage apps - streamlit documentation](https://docs.streamlit.io/library/get-started/multipage-apps)
- [Creating True Multi-Page Streamlit Apps — The New Way (2022)](https://towardsdatascience.com/creating-true-multi-page-streamlit-apps-the-new-way-2022-b859b3ea2a15)
- [Introducing multipage apps!](https://blog.streamlit.io/introducing-multipage-apps/)
[Azure Functions] リモートビルドするように設定してデプロイしたら、CICDのzipデプロイが失敗するようになった

# はじめに結論

- funcコマンドデプロイ時にアプリケーション設定が自動で書き換えられていた
    - リモートビルド(Functionsランタイムでビルド)する設定になっていた
- 組んでいるCICDでは、AzureDevOpsのパイプラインを用い、MicrosoftHostedAgentでビルドした資産をzipデプロイする
    - ビルド後の資産にはビルド設定ファイルが含まれておらず、リモートビルドしようとして落ちていた
- なのでリモートビルドするためのアプリケーション設定をOFFったら成功するようになった

# 環境

- FunctionsランタイムOS：Linux
- アプリケーションランタイム：Node16
- コーディング言語：Typescript

# 失敗するようになった経緯

- これまではCICD(AzureDevOpsのReleasesパイプライン)は成功していた
- 色々あって、VSCodeを使ったデプロイ(リモートビルド)をやりたくなったので下記コマンドを実行
    - `func azure functionapp publish $appName --build remote`

その時参考にしたサイト

https://dev.to/azure/running-headless-chromium-in-azure-functions-with-puppeteer-and-playwright-2fgk

- 試したいことは終わったので、CICDのデプロイを動かしたところ失敗

## 失敗したリリースパイプラインのログ

抜粋し、一部改変

```log
2022-09-28T01:53:58.1244834Z ##[section]Starting: Deploy Azure Function App
...
2022-09-28T01:54:04.4089082Z Package deployment using ZIP Deploy initiated.
2022-09-28T01:56:43.2424115Z Running oryx build...
2022-09-28T01:56:43.7017455Z Command: oryx build /tmp/zipdeploy/extracted -o /tmp/build/expressbuild --platform nodejs --platform-version 16 -i /tmp/8daa0f468b80c00
...
2022-09-28T01:56:43.7045398Z Running 'npm run build'...
2022-09-28T01:56:43.7049424Z > XXXXXXXXX@1.0.0 build
2022-09-28T01:56:43.7050004Z > tsc --project ./tsconfig.build.json
2022-09-28T01:56:43.7050186Z 
2022-09-28T01:56:43.7050815Z error TS5058: The specified path does not exist: './tsconfig.build.json'.
```

`npm run build`をしようとして、`tsconfig.build.json`がないため落ちてる

# 原因

それもそのはず、CICDではビルドしたArtifactがzipデプロイされており、TS→JSにトランスパイルされているので`tsconfig.build.json`やら`tsconfig.json`などの設定ファイルはデプロイ資産に入っていない

## なぜリモートビルドが動いたのか？

`func azure functionapp publish $appName --build remote`
こちらのコマンドを使用した際の引数でリモートビルドを指定するかどうかで動きが変わるものと思っていたが、どうやらAppServiceのアプリケーション設定を書き換えてしまうようだ。
前後比較したわけではないので定かではないが、見覚えのないアプリケーション設定がいくつか追加されていた。

https://learn.microsoft.com/ja-jp/azure/azure-functions/run-functions-from-deployment-package#general-considerations

>プロジェクトでリモート ビルドを使用する必要がある場合は、WEBSITE_RUN_FROM_PACKAGE アプリ設定を使用しないでください。 代わりに、SCM_DO_BUILD_DURING_DEPLOYMENT=true デプロイ カスタマイズ アプリ設定を追加します。 Linux の場合は、さらに ENABLE_ORYX_BUILD=true 設定を追加します。 詳細については、「[リモート ビルド](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-deployment-technologies#remote-build)」を参照してください。

こちらを見ると、下記2つがリモートビルドのために書き換えられたor追加されたのだと思われる。

- `SCM_DO_BUILD_DURING_DEPLOYMENT=true`
- `ENABLE_ORYX_BUILD=true`

# CICDを元通り動くようにする

リモートビルドのためのアプリケーション設定を、どちらも`false`に変えてあげるだけ

- `SCM_DO_BUILD_DURING_DEPLOYMENT=false`
- `ENABLE_ORYX_BUILD=false`

# 参考サイト

https://logico-jp.io/2022/02/21/disable-to-build-applications-during-deploying-to-app-service/

https://learn.microsoft.com/ja-jp/azure/azure-functions/deployment-zip-push#deployment-customization

https://github.com/microsoft/Oryx/blob/main/doc/hosts/appservice.md#nodejs
デザインパターン_基本

## 参考

[デザインパターンについて](https://qiita.com/developer-kikikaikai/items/8e7858c130c8ae8df488)
[C言語で デザインパターンにトライ！　デザインパターン一覧](https://qiita.com/developer-kikikaikai/items/8e7858c130c8ae8df488)
[TECHSCORE(テックスコア) デザインパターン](https://www.techscore.com/tech/DesignPattern/)
[今さら聞けない！デザインパターンとは【初心者向け】](https://magazine.techacademy.jp/magazine/9195#sec1)
[【Java】デザインパターンって何？23 種の概要を掴もう](https://style.potepan.com/articles/35080.html)

## まずデザインパターンとは
「オブジェクト指向における再利用のためのデザインパターン」という本(通称「GoF本」)で紹介された、オブジェクト指向で再利用性の高い設計をするための23個のパターンである。
また、それ以外にも、もっと幅広く、『よく出会う問題とそのスマートな解決策』という意味でも使われることがあります。

一言で言うなら「よく出会う問題とそれにうまく対処するための設計」である。

引用:[TECHSCORE(テックスコア) デザインパターン](https://www.techscore.com/tech/DesignPattern/)
## デザインパターンのメリット
### メリット

#### 再利用性の高い柔軟な設計ができる
これまでは、設計者の直感/経験などに左右していた設計が、デザインパターンを使用することで経験の少ない設計者でも熟練の設計者と同等レベルの知識を得ることができ、設計力の向上ができる。

### 技術者どうしの意思疎通が容易になる
デザインパターンを熟知している技術者同士であれば「〇〇〇パターンで行きましょう」とか「〇〇〇パターンが応用できるのではないでしょうか」というようにパターン名で設計の概要の合意を取ることが可能になり、タイムロスを抑えられるようになる。


引用:[TECHSCORE(テックスコア) デザインパターン](https://www.techscore.com/tech/DesignPattern/)

## デザインパターンの種類
### 生成
・Abstract Factory
・Builder
・Factory Method
・Prototype
・Singleton

### 構造
・Adapter
・Bridge
・Composite
・Decorator
・Facade
・Flyweight
・Proxy

### 振る舞い
・Chain of Responsibility
・Command
・Interpreter
・Iterator
・Mediator
・Memento
・Observer
・State
・Strategy
・Template Method
・Visitor

引用:[【Java】デザインパターンって何？23 種の概要を掴もう](https://style.potepan.com/articles/35080.html)

## おわりに
今後はデザインパターンの種類の中身について書いていきます。
【Swift】delegateに関して備忘録

こんにちは。
社会人1年目のエンジニアです。
今回はdelegateに関して備忘録としてまとめておこうと思います。

## そもそもdelegateとは
デザインパターンの１つ。
あるクラスから、他のクラスに処理を「任せる」こと。

任せる処理内容の例：ボタンをタップした際の処理、何かイベントを検知した際の処理

## delegateの実装手順
1. protocolを宣言
1. 処理を任せる側の実装
1. 処理を任せられる側の実装
1. delegateを呼び出す

### protocolの宣言
プロトコルとは、**クラスや構造体が保持するプロパティやメソッドなどの決まり事を定めるもの**です。
今回では、任せる処理をメソッド(**デリゲートメソッド**)として定義します。
```swift
protocol PrintDelegate {
    func displayLetter()
}
```

### 処理を任せる側の処理
デリゲートメソッドを使用し、処理の流れを記述します。
```swift
class DisplayLetter {
    
    var delegate: PrintDelegate? = nil
    
    func clickButton() {
        print("clickButtonに入りました")
        if let printDelegate = self.delegate {
            printDelegate.displayLetter()
        }
    }
}
```
変数delegateでは、**プロトコルを実装したクラスのインスタンス**を設定します
メソッドclickButtonでは、変数delegateのnilチェックを行い、
nilでなければ、プロトコル内で定義したdisplayLetterメソッドを実行します。

### 処理を任せられる側の実装
デリゲートメソッドを実装します。
```swift
extension ViewController: PrintDelegate {
    func displayLetter() {
        print("Delegateを行いました。")
    }
}
```
今回では、protocol内でdisplayLetterメソッドを定義しているので、
その中身を実装していきます。
protocol内で定義したメソッドが複数ある場合、全て実装しないとエラーになります。

### delegateを呼び出す
```swift
@IBAction func buttonTapped(_ sender: Any) {
    print("ボタンを押しました")
    
    let displayLetter = DisplayLetter()
    displayLetter.delegate = self
    displayLetter.clickButton()
}
```
変数displayLetterでは、先ほど実装したDisplayLetterクラスのインスタンス化を行い、
使用できるようにします。
そして、delegate先を自身(ViewController)にします。
最後に、クラス内のclickButtonを呼び出します。

## 実行結果
手順は以上になります。
実行してみると下記のように出力されます。

![スクリーンショット 2022-09-28 11.22.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2880542/b6036f85-59e9-3d59-632d-617462caadaf.png)
まず初めに呼び出す前の「ボタンを押しました」が呼ばれます。
その後、クラス内の「clickButtonに入りました」が呼ばれます。
最後に、デリゲートメソッドを実装した際の「Delegateを行いました。」が呼ばれます。

動画で撮ると下記になります。
順に呼ばれていることがわかると思います。
![result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2880542/9e301f42-9ee3-1a49-61eb-ab2665e4883d.gif)

以上がdelegateに関する説明でした。
自分自身も全て理解しているわけではないので、
理解が深まり次第記事を更新していきたいと思います。
Google Tag Manager のサーバーサイドタギングについての理解

参考記事はこちら

[About Google Tag Manager](https://developers.google.com/tag-platform/tag-manager?hl=ja)

# Google タグマネージャーとは

Googleタグと同じ機能を待つタグマネジメントシステム

Webサイトやモバイルアプリにタグを設定することができ導入が簡単

タグの整理やバージョン管理、サードパーティやコミュニティが開発したタグテンプレート、コラボレーション、セキュリティ機能もサポートしている

タグの展開を最適化

タグの設定エラーを抑制

# サーバーサイドタギングとは

タグコードをWebサイトやアプリからクラウドに移動することが可能

メリットは、

- Webサイトやモバイルアプリのパフォーマンスとセキュリティを向上
- 依存する資産を独自ドメインで提供することが可能

REST APIについて記載があったのでこちらのリンクも記載する

[REST APIとは？ざっくりと理解してみる【初心者向け】 - Wiz テックブログ](https://tech.012grp.co.jp/entry/rest_api_basics)

タグマネージャーのヘルプはこちら

[タグ マネージャー ヘルプ](https://support.google.com/tagmanager/?hl=ja#topic=3002579)

# サーバーサイドタギングについての詳細

参考記事
[サーバーサイド タグ設定の概要 | Google タグ マネージャー - サーバー側 | Google Developers](https://developers.google.com/tag-manager/serverside/intro?hl=ja)
## クライアンドサイドタグとサーバーサイドタグの違いとは
### クライアントサイドタグの場合
ページ内のコンテナを使用する＝ユーザーのブラウザやスマホ上で実行される

そこから様々なコレクションサーバーへ測定データを送信する

Webブラウザ上で実行されているタグマネージャーのWebコンテナが、タグで発火したデータをそれぞれ個別でデータを送信しているというわけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/673036/4ee58f64-2962-eaf2-1e4e-c7d9fa522bf8.png)

### サーバーサイドタグの場合
クライアントサイドはユーザーのブラウザやスマホ上で実行されていた

しかしサーバーサイドはそうではなく、GTMの利用者の管理するサーバー上で実行される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/673036/12f5fd1d-7894-b6f6-76aa-e5db68aef6ba.png)
利用者の管理するサーバーコンテナとWebブラウザ上のタグが交信して、処理をすべてGCPのプロジェクト上で行う

詳細はというと

- サーバーがユーザーのデバイスからウェブリクエストを受信する
- そのリクエストをイベントに変換する
- 各イベントはコンテナのタグやトリガーや変数によって処理される
- サーバーコンテナのタグやトリガーや変数は、クライアントサイドのコンテナと同じように機能する
- 各イベントがトリガー条件に一致するかどうかを確認した上で、一致する場合には処理対象のイベントデータを送信するタグを発行する

> **イベントとは**
> イベントは、ユーザーがウェブサイトのコンポーネントを操作したときに発生します。イベントには次のようなものがあります（これらに限定されません）。
> 
> - ウェブページの読み込み
> - リンクのクリック
> - フォームの送信
> - 動画再生
> - 購入
> - 登録
> - アプリのインストール
> [イベント | タグ | Google Developers](https://developers.google.com/tag-platform/devguides/events?hl=ja)

すると以下のメリットがある
- データの分析方法やサーバーからの送信先は利用者がすべて管理できる
- アクセス権によりタグでできることが一目でわかる
- ポリシーを使用するとコンテナの境界を設定可能
### 違いについてのまとめ
- 両者の違いは、処理を実行する場所が異なる：Webブラウザやアプリ上か、GTM管理者のクラウド上か
## サーバーサイドコンテナについての課題とは
- ユーザーのデバイスで取得した測定データをどのような方法でサーバーコンテナへ送信するのか
- サーバーコンテナに送信された測定データをどのような方法でイベントに変換するのか
課題の解決法としては、新しいエンティティであるクライアントをサーバーコンテナに実装することで解決可能
## クライアントの仕組みとは
クライアントは、ユーザーのデバイス上で実行されるソフトウェアと、クラウド管理者のサーバーコンテナをつなぐアダプターとして機能する
- クライアントはデバイスから測定データを受信する
- データを一つ以上のイベントに変換する
- コンテナで処理するデータをルーティングする
- その結果をパッケージ化してリクエスト元に返送する
詳しい説明はこちら
[サーバーサイド タグ設定の概要 | Google タグ マネージャー - サーバー側 | Google Developers](https://developers.google.com/tag-manager/serverside/intro?hl=ja#how_clients_work)

# まとめ

- サーバーサイドタギングはクライアントという新たなエンティティによって成立している
- クライアントサイドと比較するとユーザーデバイスの読み込み速度に影響を与えづらくなる
- 理由は、処理をクラウド管理者が所有しているプロジェクト上のサーバーで行うから
BottomNavigationBarを使用したページのサンプルコード

# はじめに
<!-- 発端や概要を記載 -->
BottomNavigationBarの実装方法をいつも忘れてしまうので、備忘録としてコピペで使えるサンプルコードを記事にします。
↓こういう感じの動きになります。
![BottomNavigationSample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/a4ae634d-b981-6dad-bc95-4f29718e0371.gif)

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [BottomNavigationBarを使ったページのサンプルコード](#BottomNavigationBarを使ったページのサンプルコード)
1. [サンプルで表示しているページ](#サンプルで表示しているページ)

<!-- 各チャプター -->
<a id="#BottomNavigationBarを使ったページのサンプルコード"></a>
# BottomNavigationBarを使ったページのサンプルコード
```dart:bottom_navigation_page.dart
class BottomNavigationPage extends StatefulWidget {
  const BottomNavigationPage({Key? key}) : super(key: key);

  @override
  State<BottomNavigationPage> createState() => _BottomNavigationPageState();
}

class _BottomNavigationPageState extends State<BottomNavigationPage> {
  // 表示するページ
  static const _screens = [
    HomePage(),
    AccountPage(),
  ];

  // どのページを表示するか指定するindex
  int _selectedIndex = 0;

  // BottomNavigationBarタップ時のイベント
  void _onTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: _screens[_selectedIndex],
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: _selectedIndex,
          onTap: _onTapped,
          // ここにアイテムを登録する
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'ホーム'),
            BottomNavigationBarItem(icon: Icon(Icons.person), label: 'アカウント'),
          ],
          type: BottomNavigationBarType.fixed,
        ));
  }
}
```

<a id="#サンプルで表示しているページ"></a>
# サンプルで表示しているページ
### ホーム画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/9c33dc8f-c132-00a9-be0b-e111fc5692f2.png)
```dart:home_page.dart
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('ホーム'),
      ),
      body:
      const Center(child: Text('ホーム画面')),
    );
  }
}
```

### アカウント画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/8572510c-6544-9c15-2320-30e54512887f.png)
```dart:account_page.dart
class AccountPage extends StatelessWidget {
  const AccountPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('アカウント'),
      ),
      body:
      const Center(child: Text('アカウント画面')),
    );
  }
}
```
【超初心者向け】VSCodeでTSをコンパイルする環境を作る

# ねらい
TypeScriptをVSCodeでコンパイルする環境を作ること

# 誰に向けて
筆者自身と初心者に向けて

# 簡潔に手順説明
## ①Node.jsをインストールする
https://nodejs.org/ja/

筆者は推奨版の16.17.1をインストールしました。
インストールが完了したらnext連打=>finishでおｋ

## ②typescriptをグローバルにインストールする
コマンドプロンプトにコピペしてEnter
```
npm install -g typescript
```

## ③ 任意のフォルダを作成する

## ④ ③で作成したフォルダをVSCodeで開く

## ⑤ VSCode上部のTerminal(ターミナル)から新規ターミナル作成

## ⑥ package.jsonを作る
⑤で開いたターミナルにコピペしてEnter
```terminal
npm init -y
```

## ⑦ tsconfig.jsonを作る
続けてコピペしてEnter
```terminal
tsc --init
```

## ⑧ 各フォルダ、ファイルを作る
作るものは以下の3つ。

* コンパイル元フォルダ
* コンパイル元フォルダの中のtsファイル
* コンパイル先フォルダ

今回は順に以下のようにした。
* from
* from/main.ts
* to

わかりやすくするための変な名前です。

## ⑨ コンパイル元とコンパイル先をtsconfig.json内で指定する
`tsconfig.json`内の`rootDir`と`outDir`を編集する。

筆者の場合、`rootDirが29行目に、outDirが52行目に`コメントアウトしてあった。
```tsconfig.json
...
    "rootDir": "./from",
...
    "outDir": "./to", 
...
```

## ⑩ コンパイルする
ターミナルでコピペしてEnter
```terminal
tsc
```

これでtoフォルダにmain.jsファイルが作成されていたら成功です。

# 躓いたポイント
## ⑦のtsc --initでエラー発生
以下のようなエラーが発生しました。
```
tsc : ファイル C:\Users\***oshienai***\npm\tsc.ps1 を読み込めません。
 C:\Users\***oshienai***\npm\tsc.ps1 はデジタル署名されていません。こ
プトは現在のシステムでは実行できません。スクリプトの実行および実行ポリシーの
詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlin
D=135170) を参照してください。
発生場所 行:1 文字:1
+ tsc --init
+ ~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityExcep
    + FullyQualifiedErrorId : UnauthorizedAccess
```
雑にエラーの一部である、
> デジタル署名されていません。このスクリプトは現在のシステムでは実行できません

部分をコピペして検索してみました。

https://kondeneenen.com/powershell_digitalsignature/

この記事を参考に、さらに簡潔にまとめると、VSCodeのTerminalで以下を入力。
```terminal
Get-ExecutionPolicy -list
```

`Process undefined`を確認する。
続いて、以下を入力
```terminal
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass 
```

その後、再度以下を入力
```
Get-ExecutionPolicy -list 
```

`Process Bypass`を確認する。

再度`tsc --init`と打ってみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666100/803c6964-1fd1-2a0e-753f-3cdb56746624.png)
このような画面が表示されたらおそらく成功です。
本記事⑧に戻りましょう。

# 参考にした記事

https://zenn.dev/kiriyama/articles/a01a56c53876f2

https://qiita.com/nemutas/items/0a266ec58c76ae3ee43a

# 最後に

誰かの助けになれば幸いです。

何かあったらコメントください。
コーディングにおけるSEO対策は結局のところ何が重要なのか

コーディングを行う際、
検索エンジンに情報をわかりやすく伝えるようにタグを設定する必要があります。

もし検索エンジンに情報が伝わりにくいコードになっていると、いくら質の高いコンテンツを設計しても、思うようにSEO対策できません。Webサイトへのアクセスも生まれず、成果を上げるには広告に頼らざるを得なくなるでしょう。

そのため、サイトのコーディングの時点で、
SEO対策を意識したタグの設計をする必要があります。

たとえば、

<　title>

<　h2>

<　h3>

<　h3>

<　h2>

<　h2>

のように、情報の位置関係をわかりやすくします。
これが


<　title>

<　h3>

<　h4>

<　h2>

<　h4>

<　h2>

のように情報の位置関係がバラバラだと、
検索エンジンもサイト情報を正しく理解できません。

サイトのコーディングをする際は、
タグの位置関係を正しく理解した上で設置しましょう

タグにおけるSEO対策の方法は、
以下のサイトでも詳しく解説しています。

https://wordgym.jp/
Linux make install を用いずにカーネルをインストールするには

●make install を用いずに手作業でカーネルをインストールするには

1. ビルドしたカーネルイメージファイル bzImage を vmlinuz-(VERSION) という名前で /boot に置く

2. System.map を同様にSystem.map-(VERSION) という名前で /boot に置く

3. /boot/vmlinuz, /boot/System.map というバージョンがつかない名前でもアクセスができるよう、シンボリックリンクを張る

4. 必要に応じて mkinitramfs または mkinitrd で初期 RAM ディスクを作成し、/boot/initrd.img-(VERSION) とする

5. ブートローダに新しいカーネル用の設定を追加する。GRUB Legacyならば /boot/grub/menu.lst、GRUB2 ならば /etc/grub.d/ ディレクトリ配下のファイルなどを適切に編集する（GRUB2 ではさらに grub-mkconfig（またはgrub2-mkconfig）コマンドで、設定内容を /boot/grub/grub.cfg 設定ファイルに反映させること）

●/boot/vmlinuz-(VERSION) 
カーネルイメージのファイル（ビルドしたカーネル本体）。
zImage 形式と bzImage 形式の二種類があり、ロードされるカーネルのデータが自己伸長可能なフォーマットで圧縮されている。

●/boot/config-(VERSION) 
該当するバージョンのカーネルをビルドする際のカーネル設定ファイル（カーネルコンフィギュレーション）である /usr/src/linux/.config のバックアップ。
カーネルのビルド時に make oldconfig として読み込むことができる「現在動いているカーネルのカーネルコンフィギュレーション」

●/boot/initrd.img-(VERSION) 
段階的ブートを行う際の、仮のファイルシステムの内容をまとめたイメージファイル（初期 RAM ディスクイメージ）。
make install を用いた場合は必要に応じて自動的に生成。
手動でインストールを行う場合には、mkinitrd、mkinitramfs、dracut コマンドで作成できる。

●/boot/System.map-(VERSION) 
カーネルがメモリ上に展開される際の、シンボルとアドレスのマッピングを記述したファイル（アドレスマップ）。
カーネルのビルド時に /usr/src/linux/System.map として同時に作成


●カーネルモジュールのインストールを行うと、モジュールは /lib/modules/(VERSION)/ にインストールされる。VERSION の部分は、uname -r として得られるカーネルのバージョン文字列。
MariaDBでpartition運用をしてハードディスクを節約

## Mysqlと同様にmariadbでもpartitionを使えます（当たり前ですが）
#### 設定の前に
パーティションはあらかじめ作成しておかないといけません。
また、ある程度決まった法則で消せるデータにしか有効ではありません。
私はommysqlでしか使い道がありませんでしたが、十分に有効な手立てでした。

#### 1.作成
    PARTITION BY RANGE  COLUMNS(`ReceivedAt`)
Create（or Alter）Tableの際にこういう設定をしてこのカラムは範囲でパーティションを付けると宣言をしておきます。
なお、主キーに含まれてないカラムは指定できません。
詳しくは[公式ドキュメント](https://mariadb.com/kb/en/range-columns-and-list-columns-partitioning-types/)を見てもらったほうがいいです。

    alter table Syslog.SystemEvents add partition (partition P202211 values less than ('2022/12/01 00:00'))

これはパーティション名がP202211というパーティションをSyslog.SystemEventsに追加するSQLです。

    values less than ('2022/12/01 00:00')

となっているのはすでにP202210というパーティションがless than ('2022/11/01 00:00')を持っているからです。

#### 2.削除
**partitionはいきなり削除してもデータの不整合が起きないことがわかりました。
最後のdrop partitionを実行してください。**

~~まずはパーティション内のデータをすべて削除します。~~
~~select count(ID) from Syslog.SystemEvents where ReceivedAt < '20211001'~~
~~delete from Syslog.SystemEvents where ReceivedAt < '20211001'~~
~~削除はまとめてやるとtemp領域を食い尽くしてディスクをめちゃめちゃつかうので、~~
~~件数によっては日付毎はおろか。。。~~

~~delete from Syslog.SystemEvents where ReceivedAt < str_to_date('20211001 01:00','%Y%m%d %H:%i');~~
~~commit;~~
~~delete from Syslog.SystemEvents where ReceivedAt < str_to_date('20211001 02:00','%Y%m%d %H:%i');~~
~~commit;~~
~~のような事態に陥ります。ので、毎月cronなどで動かすのは怖いといえば怖いのですが、~~
~~確実にpythonなどでsql分をスクリプト化しておくことをお勧めします。~~

そして原因はわからないのですが、

    SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, PARTITION_ORDINAL_POSITION, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='SystemEvents';
これでパーティションにデータがないことを確認したかったのですが、データが残っているように見えました。
```
+--------------+--------------+----------------+----------------------------+------------+
| TABLE_SCHEMA | TABLE_NAME   | PARTITION_NAME | PARTITION_ORDINAL_POSITION | TABLE_ROWS |
+--------------+--------------+----------------+----------------------------+------------+
| Syslog       | SystemEvents | P202110        |                          2 |     135124 |
+--------------+--------------+----------------+----------------------------+------------+
```

    select * from Syslog.SystemEvents partition (P202110);
が、このようにパーティションを指定してselectを発行しても結果は0だったので、削除します。

    alter table Syslog.SystemEvents drop partition P202110;
これでパーティションが削除され、ハードディスクの空き容量がそれなりに復活します。