OmniAICreator/Qiita-1.07M huggingface dataset:
paizaラーニング問題集「みんなでしりとり」を解いてみた

https://paiza.jp/works/mondai/b_rank_skillcheck_archive/word_chain

▼考え方

この問題を解くために私が考えた内容1.～3.を以下に示します。

1. しりとりから脱落したか否かを、辞書statusで管理します。keyはしりとりを行う人の番号です。valueは、1はしりとりから脱落していないことを示し0は脱落したことを示します。

2. しりとりを行ったログM行分を1行ずつ、問題文にあるしりとりのルールに基づいて処理します。すべて処理し終わった後に、statusからしりとりから脱落せずに残っている人の情報を求めます。

3. 「N人目のしりとりが終わった後は1人目に戻る」および「しりとりから脱落した人は飛ばす」処理を行います。

▼コード
```py
########## 処理0(準備) インプット,リストや変数定義 ###########

N,K,M = map(int,input().split())

d = [""]*K
for i in range(K):
    d[i] = input()

# 考え方1.
status = {}
for i in range(N):
    status[i+1] = 1

# n: 現在のしりとりの発言者の番号を示す変数
n = 1

# restart: restart=1のとき次のしりとりの発言者が最初の人であることを示し、restart=0のとき次の発言者が最初の人ではないことを示す変数
restart = 1

# mlog: しりとりを行ったログを格納するリスト
mlog = [""]*M

########## 処理1 しりとりから脱落せずに残っている人の情報を求める処理 ###########

# 考え方2.
for i in range(M):

    # m: しりとりを行ったログ1行分を格納する変数
    m = input()
    
    if (m not in d) or ((restart != 1) and (i != 0) and (m[0] != mlog[i-1][-1])) or (m in mlog) or (m[-1] == "z"):
        status[n] = 0
        restart = 1
    else:
        restart = 0
        
    mlog[i] = m

    # 考え方3.
    if N != 1:
        n += 1
        if n > N:
            n = n % N
        while status[n] == 0:
            n += 1
            if n > N:
                n = n % N
        
print(sum(v == 1 for v in status.values()))
for k,v in status.items():
    if v == 1:
        print(k)
```
【VSCode】GitHub Copilot ChatでWeb検索を使用する方法

## Web Search for Copilotを使用する

Web Search for Copilotという拡張機能を導入するとGitHub Copilot ChatでWeb検索を使用して最新の情報が取得できるようになります。

### 拡張機能をインストール

以下のページの「インストール」をクリックして拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-websearchforcopilot

### TavilyのAPIキーを取得する

を使用するにはTavilyまたはBingのAPIキーが必要です。
今回はデフォルトで設定されているTavilyを使用します。
まず、[Tavily](https://tavily.com)にサインアップします。
サインアップすると以下の画面が表示され、TavilyのAPIを取得できます。

![スクリーンショット 2024-10-31 18.54.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/351d3163-b77e-3197-3277-a590b6cb21d6.png)

### APIキーを登録する

初めて`@websearch`を記述してGitHub Copilot Chatを使用した際に以下のようにAPIキーの入力欄が表示されます。

![スクリーンショット 2024-10-31 14.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/feb5f1a2-ad1a-feef-7d03-c4d18a9fe7ec.png)

上記で取得したAPIキーを入力して登録します。


以上で導入は完了です。
試しに「Next.jsの最新バージョンは何ですか」と質問すると2024年10月時点では15である旨の回答が得られました。

![スクリーンショット 2024-10-31 18.27.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/339555d1-b54c-73c5-f71d-8597bf04d34a.png)

## GitHub Copilotの設定を変更する

GitHub Copilotの設定を変更することで拡張機能なしでBingでのWeb検索が利用可能になります。
GitHub Copilotの設定画面の「Copilot access to Bing」を「Enabled」に変更します。

![スクリーンショット 2024-10-31 19.40.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/6c4b7a3e-dc1b-ac5a-7211-f28586798cc9.png)

https://github.blog/changelog/2024-10-29-web-search-in-github-copilot-chat-now-available-for-copilot-individual/

拡張機能を使用する場合と同様に「Next.jsの最新バージョンは何ですか」と質問すると以下のような回答でした。

![スクリーンショット 2024-10-31 19.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/2aafa969-189b-a6d7-fb36-b9c42ea7b07e.png)

質問の仕方を変えたところ正しい情報を得られました。

![スクリーンショット 2024-10-31 19.38.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ddc49adc-327a-c6ab-0189-6adc63cfa188.png)
[Flutter] TextField を Row で横並びに配置したところビルドエラーになった

# コード

```dart
Row(
  children: [
    TextField(
      controller: _lastNameController,
      decoration: const InputDecoration(
        labelText: '姓',
        hintText: '姓を入力してください',
      ),
    ),
    TextField(
      controller: _firstNameController,
      decoration: const InputDecoration(
        labelText: '名',
        hintText: '名を入力してください',
      ),
    ),
  ],
),
```

# エラー

```zsh
════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
An InputDecorator, which is typically created by a TextField, cannot have an unbounded width.
This happens when the parent widget does not provide a finite width constraint. For example, if the InputDecorator is contained by a Row, then its width must be constrained. An Expanded widget or a SizedBox can be used to constrain the width of the InputDecorator or the TextField that contains it.
'package:flutter/src/material/input_decorator.dart':
Failed assertion: line 962 pos 7: 'constraints.maxWidth < double.infinity'
```

# エラーの説明

`TextField` は固有の幅を持っていない。
しかし、`TextField` やその内部に存在する `InputDecorator` は、特定の幅の制約が必要で、無限の幅が指定されている場合、`InputDecorator` は正しくレイアウトできず、エラーが発生する

今回の場合、`Row` が `TextField` の親ウィジェットであるが、`Row` 自体は子ウィジェットに対して幅の制約を与えない

# 解決策

`TextField` に幅の制約を与えてあげる

```dart
Row(
  children: [
    Expanded( // ExpandedでTextFieldを囲う
      child: TextField(
        controller: _lastNameController,
        decoration: const InputDecoration(
          labelText: '姓',
          hintText: '姓を入力してください',
        ),
      ),
    ),
    Expanded( // ExpandedでTextFieldを囲う
      child: TextField(
        controller: _firstNameController,
        decoration: const InputDecoration(
          labelText: '名',
          hintText: '名を入力してください',
        ),
      ),
    ),
  ],
),
```
【Tableau Desktop】日付フィルタを降順に表示したい

# はじめに
この記事では、Tableau Desktop上で日付フィルタを降順にする方法について記載します。

業務内でTableauを用いてダッシュボードを作成し始めた当初、「年月フィルタは降順にした方が使いやすい！」というお声をいただくことが多くありました。

弊社のダッシュボード作成を行う中で欠かせない部分になるのですが、意外と設定方法に関する記事が少なかったため、今回の記事を書くに至りました。

今回は、サンプルスーパーストアを用いて手順を記載していきます！
<br>
※Tableau Desktopのみでしか作成できない部分にはなるので、ライセンスによっては設定不可能な場合もあります。


# 手順
## ①計算式を作成する
最初に、計算フィールドの作成から「DATETRUNC」を使用した式を作成します。
フィールド名は混在しないよう、(フィルター用)などを末尾につけておくと判別しやすくなるかなと思います。

まず「DATETRUNC関数」とは…というところについて説明します。
DATETRUNC関数は以下のように使用されます。
<br>
DATETRUNC("month",[オーダー日])
<br>
**簡単に言えば、指定された日付(オーダー日)を指定された精度(month)で切り捨て、新しい日付を返す！という関数です。**

ただし上記の計算式の場合、DATETRUNC関数は時間まで返してしまうので、今回に関しては**以下のように「DATE」を1番前につけて日付だけ返すようにします。**
<br>
**DATE(DATETRUNC("month",[オーダー日]))**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/7e93b72b-07a9-e5dc-12bb-7b4e00fe345e.png" width="60%">
<br>
## ②「既定のプロパティ」から並び替えを設定する
次に、作成した計算式のピルを右クリックし、**既定のプロパティから「並び替え」を選択**します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/bdf936a7-e924-92af-61fb-e8739532f87a.png" width="40%">
<br><br>
すると並び替えの設定ができますので、順序を「降順」に設定します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/a83f72f6-8e0d-2624-e2c3-2b6b4376f935.png" width="40%">
<br><br>

## ③日付形式を設定する
この段階でもフィルター自体は日付降順になっているのですが、このままだと日付形式が「yyyy/mm」として表示されます。

表示形式を変更したい場合は、**「オーダー日(フィルター用)」のピルを右クリックし、既定のプロパティから「日付形式」を選択**します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/8c726133-9122-5d19-7a95-c46e3fc564b1.png" width="30%">
<br>その後、使用したい日付形式を選択すると、希望の表示形式になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/0a8a2136-6d56-d488-9a56-9cc761e73342.png" width="40%">
<br>
また、希望の表示形式がない場合は、以下のようにカスタムの書式設定で設定することも可能です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/56785724-268f-785a-c463-94df012a488b.png" width="40%">

## ④フィルターへ移動

作成・設定が完了したピルをフィルターに移動させます。
その際、どのようにフィルターするかの設定を行う画面が表示されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/c7a5b55e-9738-9d90-e80c-8241ac3eddee.png" width="30%">
<br>
ここで、**「個別の日付」を選択**し、表示させたいフィルター範囲を設定すると…

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3870445/3457ebb6-333b-f733-610f-9f596f437673.png" width="50%">

このように日付フィルターを降順に設定することができました！

# 最後に
見る側の立場に立つと、やはり新しいものから日付を表示させた方が使いやすいのではないか…と個人的に思います。

より使いやすいダッシュボード作成のためのTipsとして、是非試していただけると幸いです！

最後までご覧いただきありがとうございました！
GASの関数をPromiseでラップする (魔法のオブジェクトProxy)

[株式会社 ONE WEDGE](https://onewedge.co.jp/)の[@Shankou](https://qiita.com/Shankou)です。
今回は少し短めにGAS(Google Apps Script)の関数をWebアプリ側から呼び出す際に？少しだけ使いやすくする工夫を紹介したいと思います。
みなさんはProxy使ってますか？？

今回は以下の様なGASの関数を例に使います。

``` js
/**
 * 利用者自身の情報を取得する関数
 * @return {Object} - { email: String, name:String, parson: Object }
 */
function getSelf () {
  const response = People.People.getBatchGet({
    resourceNames: ['people/me'],
    personFields: 'names,emailAddresses'
  }).responses[0];

  // エラーハンドリング
  if (!response || !response.person) {
    throw new Error('利用者情報の取得に失敗しました。');
  }

  const person = response.person;

  return {
    email: person.emailAddresses?.[0]?.value || 'メールアドレスがありません',
    name: `${person.names?.[0]?.familyName || ''} ${person.names?.[0]?.givenName || ''}`.trim(),
    person
  };
}
```

この関数をWEBアプリ側から使用する場合、以下のように使用することができます。

``` js
function onSuccessGetSelf(result) {
    console.info(result)
}

function onFailureGetSelf(e) {
    console.error(e)
}

google.script.run
    .withSuccessHandler(onSuccessGetSelf)
    .withFailureHandler(onFailureGetSelf)
    .getSelf();
```

別にこのままでも問題は特にないです。
でも、コールバック関数の形って今はあまり使わないですよね？
後続処理を書くのも大変ですし、、、
コールバック関数ではなく、async/awaitで書けた方が可読性も高いと思いませんか？
そんなあなたにおすすめしたいのがこの魔法のオブジェクト！Proxy!

``` js
// 魔法のオブジェクト!Proxy!
const GSRun = new Proxy(google.script.run, {
  get(target, method) {
    return (...args) => 
      new Promise((resolve, reject) => {
        target
          .withSuccessHandler(resolve)
          .withFailureHandler(reject)
          [method](...args);
      });
  }
});

// ざっくり使い方
(async () => {
    try {
        console.info(await GSRun.getSelf());
    } catch (e) {
        console.error(e);
    }
})();
```

まず、Google Apps Scriptのgoogle.script.runをラップするプロキシオブジェクトGSRunを定義します。
Proxyオブジェクトは、JavaScriptの機能の一つで、他のオブジェクトの動作をカスタマイズするためのものです。具体的には、オブジェクトのプロパティへのアクセスやメソッドの呼び出しなどの基本的な操作をトラップ（捕捉）し、これらの操作を制御したり、変更したりすることができます。
例えば、プロパティの取得時に特定の処理を行ったり、設定時にバリデーションを行ったりすることができます。
多用しすぎると処理が追いにくくなるので注意が必要ですが、一定の範囲であればとても便利な機能になります。

getトラップは、プロキシオブジェクトがプロパティにアクセスされた際に呼び出され、targetは元のオブジェクト（ここではgoogle.script.run）、methodは呼び出されるメソッドの名前を引数として受け取ります。
メソッドが呼び出されると、引数を受け取るアロー関数が返され、Promiseを作成します。

今回は`getSelf`を例にしましたが、他のGAS関数が増えたとしても、特別気にすることもなく同様のコードを書くことで呼び出すことが可能です！
(呼び出しの関数名はProxyで動的に取得しているので、これ一つ置いておくだけで全て解決できます！)

言葉で説明すると難しいProxyですが、知っておくと便利な機能でもあるので、みなさんもぜひ使ってみてください。
Linux (ディレクトリ構造とlsコマンドについて)

## Linuxディレクトリ
システム全体で2台の物理ディスクがある場合、Windowsでは2つのディレクトリツリーができるが、Linuxでは何台のディスクがあろうがシステム全体で1つのディレクトリツリーしか持たない。

また、Linuxの各ディレクトリについて確認する。
- ### /bin
Linuxシステムの動作に最低限必要な重要度の高いコマンドを格納している

- ### /dev
キーボードなどのハードウェアをファイルとして扱えるように用意された特殊なファイルであるデバイスファイルを格納しているディレクトリである。

- ### /etc
設計ファイルを置くためのディレクトリである。Linuxを管理・運用する上で非常に重要なディレクトリである。

- ### /home
ユーザーごとに割り当てられるホームディレクトリが配置されるディレクトリである。
ホームディレクトリとは、ユーザーごとに割り当てられる個人用のディレクトリのことでユーザー名がそのままディレクトリ名になっている。
ユーザーはこのホームディレクトリ内に自由にファイルやディレクトリを作成して作業を行うことができる。

- ### /sbin
実行ファイルを置くためのディレクトリであるが、こちらは管理者ユーザー向けのコマンドが置かれている。

- ### /tmp
一時的なファイルを置くためのディレクトリ。
このディレクトリ内のファイルは定期的に削除する設定になっているディストリビュージョンも多いため、ファイルの保存先として選んではいけない。

- ### /usr
各種アプリケーションと付随するファイルを置くためのディレクトリ。
追加でアプリケーションをインストールした際に、実行ファイルやドキュメント、ライブラリなどがこのディレクトリの下に配置される。

- ### /var
変化するデータを置くためのディレクトリ。
アプリケーションの動作する上で作成されたデータやログ、電子メールなどが格納される。

## ホームディレクトリとチルダ展開
引数をつけないでcdコマンドを実行すると、ホームディレクトリに移動することができる。
``` CLI:ホームディレクトリに移動する
cd
```

また、チルダを用いることでもホームディレクトリへ戻ることができる。
コマンドラインのチルダ(~)は、シェルによりホームディレクトリのパスへと自動的に置き換えることができる。

シェルのこの機能のことをチルダ展開と呼ばれ、これを利用することでホームディレクトリ配下へのディレクトリへ移動することができる。

## lsコマンドの使いかた
lsコマンドでファイルやディレクトリの一覧を確認することができるが、複数のファイルを指定するとき大変である。
そのために、「*」や「?」を用いることでファイル名の一部をパターンで指定することにより複数のファイルを指定することができる。
これをパス名展開と呼ばれている。

``` CLI:ファイル名がbaから始まるものを表示させる
＄ls ba*
```

``` CLI:特定の拡張子のファイルを一覧表示させたい場合

$ ls .*html
```

?では、任意の1文字だけに対応する点が異なる。
例として、ba??と入力すると「ファイル名がbaから始まり、全体の長さが4文字」のファイルを表示させる。

## lsコマンドのオプション
- ### -lオプション
ファイル名だけでなく、ファイル属性などの詳細情報を同時に表示させることができる。

- ### -aオプション
隠しファイルも含めたすべてのファイルを表示する

- ### -Fオプション
ファイル名の後ろにファイル種類を表す記号を追加し表示する。

- ### -wオプション
指定した数値の横幅で表示するオプションである。

## コマンドのオプションについて
- オプション指定の基本
オプションは2つ以上指定することができる。
この場合、別々にスペースを区切り記述すること、もしくは-の後ろにまとめて記述することができる。
``` CLI:
ls -a -F
ls -aF
```
コマンドの引数とオプションを同時に指定する場合もある。
この場合は先にオプションを記述し、あとにコマンドの引数を書く。
例では、-aオプションと-Fオプションを指定しつつ、引数を/(ルートディレクトリ)にしている場合である。
``` CLI:
$ ls -a -F /
```

- 引数を取るオプション
オプション自体が引数を取ることもある。
例として-wオプションにおいて以下のように記述することで、30桁で表示するように指定することができる。
``` CLI:
$ls -w 30
```
この30はlsコマンドへの引数ではなく、-wオプションに対しての引数である。
また、引数を取るオプションではオプションと引数の間のスペースは省略することができる。
``` CLI:これらは同等
$ls -w 30
$ls -w30
```

- ロングオプション
一般的にオプションは「ハイフン + 英数字1文字」で指定することができるが、「--...」というハイフン2文字で始まるオプションもある。
例として次のオプション「--quote-name」ではファイル名をダブルクォーテーションで囲んで表示させることができる。
``` CLI:これらは同等
$ls --quote-name
```

ロングオプションは他のオプションと重複しない場合省略することができる。先ほどのコマンドの場合は以下のように省略して記述することができる。
``` CLI:
$ ls --quote
```
widthのような引数を取るロングオプションでは、引数との間にスペースを入れるか、もしくは=記号で引数を指定する。
``` CLI:これらは同等
$  ls --width 30
$ ls --width=30
```


#### 参考文献
> [新しいLinuxの教科書](https://www.sbcr.jp/product/4797380941/)
RailsのRansackとsort_linkで簡単に並び替え機能を実装する方法【Bootstrap対応】

## 背景
実務で検索機能を実装する際、データの並び替えもできるようにしたい、という要望がありました。既にRansackを使った検索機能は実装済みでしたが、並び替え機能も追加するために sort_link を活用することになりました。この実装内容をまとめて記録として残します。また、今回の実装はBootstrapを用いてスタイリングしており、基本的なデザインの調整も行いました。

## Ransackとは
Ransackは、Ruby on Railsにおいて簡単に検索機能を追加できるGemです。Ransackを使うと、条件に基づいたデータの検索ができるフォームや、指定したカラムによる並び替えが可能になります。検索ロジックを簡潔に書けるだけでなく、カスタムした条件にも対応しやすく、特に管理画面などでのデータ検索や並び替えが必要な場面で重宝します。

## sort_linkとは
sort_link は、Ransackが提供するメソッドの一つで、並び替えリンクを生成します。sort_link を使用することで、簡単に指定したカラムの昇順・降順で並び替えが可能になります。ボタンやリンクをクリックするだけで並び替えが行われるため、UI/UX向上にもつながります。また、カスタマイズ可能なクラスを指定することで、スタイルも自由に調整できます。

## 実装手順
1. テーブルの構造
今回はBootstrapを使い、スタイルを設定しています。以下のようなテーブル構造で各列に sort_link を設置し、データを並び替え可能にします。

```
thead.table-dark
  tr
    th.text-nowrap
      = sort_link(@search, :created_at, "登録日", {class: "text-decoration-none text-white"})
    th.text-nowrap
      = sort_link(@search, :delivery_enduser_created_at, "送信日", {class: "text-decoration-none text-white"})
    th.text-nowrap 店舗名
    th.text-nowrap クライアント名
    th.text-nowrap 電話番号
    th.text-nowrap 理由
    th(style="min-width: 40px;") 通話メモ
    th(style="min-width: 40px;") コメント
    th.text-nowrap 詳細情報
```

※「delivery_enduser_created_at」はモデルファイルで専用のスコープを定義しています。
```
  ransacker :delivery_enduser_created_at do
    Arel.sql('delivery_endusers.created_at')
  end
```

sort_link メソッドの第一引数には、@search オブジェクトを指定しています。このオブジェクトは、Ransackでの検索条件を保持するもので、並び替えリンクでもこれを利用します。

第二引数には並び替えを行いたいカラム名を指定し、第三引数に表示するカラムのタイトルを渡します。

最後のオプション引数には、Bootstrapを使ったクラス (text-decoration-none text-white) を指定し、リンクのデザインを調整しています。

2. 並び替えの動作
sort_link をクリックすると、指定したカラムのデータが昇順・降順で切り替わります。例えば、「登録日」をクリックすると、その列のデータが昇順に並び替えられ、再度クリックすると降順に切り替わります。これにより、ユーザーは簡単に見たい順序でデータを整理して表示することができます。

3. Bootstrapでのスタイリング
今回は thead.table-dark クラスを使ってヘッダーにダークテーマを適用しています。また、各リンクに text-decoration-none や text-white クラスを追加して装飾を取り除き、見やすい白文字に設定しました。さらに、ヘッダー行の一部に min-width スタイルを直接指定することで、列幅の固定も行っています。

## まとめ
sort_link を活用することで、Ransackの検索機能に並び替え機能を簡単に追加でき、ユーザーにとって使いやすいUIを構築することができます。
Polarsのpolars.Expr.clipとは何なのか調べてみた

# はじめに
今年の7月にPolarsのv1.0.0がリリースされ、現在はv1.12.0が最新です。
私はリリース直後にpolars-jaユーザーグループが開催した「リリースノートを読む会」に参加し、その中で触れられた`clip`関数に興味を持ちました。
かなり時間が経ってしまいましたが、この関数について調べてみることにしました。
以下の点が特に気になったポイントです。

## 調査のポイント
`clip`関数がどのような処理を行うのか
どのような場面で役に立つのか

## 結論
ざっくり結論を記載します。

* どのような関数か  
→ `clip`関数は、指定した最小値や最大値を境界として、値がその範囲を超える場合に境界値に変換することができる関数です。  

* どのような場面で使用されるのか  
→ データの前処理や異常値の処理に使用されるようです。

この後に関数の概要、サンプルコードを記載します。

# `clip`関数の概要と使い方
公式ドキュメントを確認したところ、`clip`関数は、データフレームやシリーズ内の数値や時間などの値を指定した範囲に収めるために使用されるようでした。例えば、データに異常値があった場合に除去せずに使用したいというような処理や、値を一定範囲内に保つ必要がある場合に使用されるものだと思われます。

以下はPolarsでの使用例です。
#### Polarsでのclip関数の使用例①
```python
import polars as pl

# DataFrameの作成
df = pl.DataFrame({
    'A': [1, 2, 3, 4, 5],
    'B': [10, 20, 30, 40, 50]
})

# 値を特定の範囲内に制限する
clipped_df = df.with_columns([
    pl.col('A').clip(2, 4),
    pl.col('B').clip(20, 40)
])

```

出力結果:
```
shape: (5, 2)
┌─────┬─────┐
│ A   │ B   │
│ --- │ --- │
│ i64 │ i64 │
╞═════╪═════╡
│ 2   │ 20  │
│ 2   │ 20  │
│ 3   │ 30  │
│ 4   │ 40  │
│ 4   │ 40  │
└─────┴─────┘
```

#### Polarsでのclip関数の使用例②

```python
import polars as pl

# DataFrame作成
df = pl.DataFrame({"a": [0, 1, 2, 3, 4, 5, 6], "min": [1, None, 1, 3, 4, 6, None]})
df.select(pl.col("a").clip("min"))
```
出力結果:

```
shape: (7, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 1   │
│ 1   │
│ 2   │
│ 3   │
│ 4   │
│ 6   │
│ 6   │
└─────┘
```

#### 解説
使用例②については、サンプルコードを見て動かしただけだと私は理解できなかったので、ChatGPTを使用して解説してもらいました。

1. まず、a と min の2つの列を持つPolarsのDataFrameを作成します。
1. a 列には0から6の整数が含まれています。
1. min 列には、クリッピング時の最小値として使う値が設定されています。一部には None（欠損値）も含まれており、クリッピングに影響を与えます。
1. pl.col("a").clip("min") は、列 a の値を、min 列の値でクリッピングする操作です。
1. clip 関数は a 列の各値を確認し、対応する min 列の値が設定されていれば、その値以下にはならないように制限します。たとえば、 a 列の最初の値 0 は min 列の 1 でクリップされるため、結果は 1 になります。
1. min 列の値が None の場合、その行のクリッピングには影響しないため、元の値がそのまま出力されます。

上記の流れから、0 から始まる a 列の値が、指定された min 列の最小値によって制限されるため、上記の出力結果となることがわかりました。


## Pandas の `clip` 関数

Pandasにおいても同様に`clip`関数が存在しています。
Pandasでは、`DataFrame` または `Series` に対して `clip` 関数を使用することができます。

```python
import pandas as pd

# DataFrameの作成
df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
clipped_df = df.clip(lower=2, upper=4)
print(clipped_df)
```

出力結果:
```
   A  B
0  2  10
1  2  20
2  3  30
3  4  40
4  4  50
```

## まとめ
`clip`関数は、指定した最小値や最大値を境界として、値がその範囲を超える場合に境界値に変換することができる関数であり、データの前処理や異常値の処理を行う際に使用されることがあるようです。
また、Polarsだけでなく、Pandasにおいても`clip`関数が提供されています。

## 参考

https://github.com/pola-rs/polars/releases/tag/py-1.0.0

https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.clip.html#polars-expr-clip

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.clip.html
はじめての後輩！どうやったらちゃんと指導できる？？

## はじめに

こんにちは！今回、新人指導をする立場に初めてなり、そこで色々学べているので、それらをまとめていきたいと思います！
私の所属するチームでは、若手メンバに、なかなか機会のない指導の経験を積ませる意味合いを込めて2年目社員に1年目社員に対する指導を行う機会が与えられています。

## 指導することの自分へのメリット

### 復習による知識の再取得
まずは何と言っても1年目に学んだことの復習になることです。

教えるためには、より深い理解が必要です。
1年目に学んだオブジェクト指向の知識や不具合の定義など、正直忘れていることも多かったのですが、説明をするにあったって先輩からいただいた指摘、アドバイス、自分の修正後の回答を見直す機会が生まれました。

それらを踏まえて自分の言葉にして説明することで思い出すこと、理解を深めることもできました！


また、新人の子もインターネットで時間をかけ調べ、理解したことを頑張って自分なりの言葉で説明してくれるので自分より知識が上回りなるほどそういうことかと思うことも少なからずあります。


### 良い行動を目撃することからの刺激

日々、指導している新人メンバのことを見ているといいなと思える行動が数多く見受けられます。

例えば、テスト実施の際、同じような手順で同じようなことをテストするようなっていた際、「なぜ？」とそのことを質問していました。与えられたものをそのまま何も考えずに行っていくのはなくちゃんと目的を考えながら行っていることのを見て関心しました。自分もその精神は持ち続けていきたいです！

また、ある日行った指導が、次の日には行動に反映していくことです。指導している数も多いのですがそれらを取りこぼしなく身に着けていくのは本当にすごい！


このように一つ下のメンバが近くでよい行動を行うのを見ることはかなりの刺激になります！見習っていきたいです！



## 難しいなと思ったこと

#### 言語化スキルを引き出す方法

日々報告に対し、言語化スキルを高めさせる質問をすることで成長を加速させることができます。
メンバの成長のためそのような質問をする必要があるのですがこれがなかなか難しいです...
ひねり出して、「(学んだことがあったらそれを)どう業務に活かせそう？」、「どういうことが難しかった？」、「(タスクが遅れていたら)遅れている理由はなに？」などと質問しています。

自分でも回答が難しいなと思うことを質問するのは意地悪な感じがして若干気が引けますがこれも成長を加速させるため...！質問をひねり出す力も挙げていきたいなと思います。


#### 適切な量の指導
私は2年目、チームに配属されてから1年以上たっているためチームでの、ビジネスマンとして行うべきことが分かってきている段階にあります。そのため、当然のように行っていることは指導から漏れてしまいがちです。かといってなにもかも横で付きっ切りで教えるのは自分の業務も進めていけませんし、何より新人の精神的な負担になると思います。
これらは経験の中で適切な指導を目指していきたいなと考えています。


## おわりに

これからも新人の指導をガンガン行っていきます！指導中に学べることがたくさんあると思いますので、それの学び追記していきますね！最後まで読んでくださってありがとうございました！
RailsでGoogleスプレッドシートにデータを自動登録する方法：Google APIとGCPの設定ガイド

## 実装背景
今回の実装では、RailsアプリケーションからGoogleスプレッドシートへ自動的にデータを登録する機能を構築しました。この機能により、DBに保存せずスプレッドシートでデータを管理する必要があったため、その内容をまとめました。

## Googleスプレッドシートについて
Googleスプレッドシートは、Googleの提供するオンライン表計算ツールです。リアルタイムでのデータ共有や編集、さまざまなプラグインの活用ができるため、多くのプロジェクトでデータ管理ツールとして活用されています。また、APIを通じてプログラムからデータの取得・更新が可能です。

## GCPについて
GCP（Google Cloud Platform）は、Googleの提供するクラウドサービスプラットフォームであり、API管理やデータベース、AIツールなど幅広いサービスが提供されています。今回は、GCPでGoogleスプレッドシートと連携するために「Google Drive API」および「Google Sheets API」を利用し、Railsアプリからスプレッドシートにデータを登録します。

## 実装手順

・必要なgemの登録
RailsアプリからGoogleスプレッドシートを操作するため、以下のgemを使用します。
```
gem 'google_drive', '~> 3.0'
```
バージョン指定について：google_driveはバージョン1系ではgoogle/api_clientを直接読み込む必要があるため、バージョン3以上を指定することで不具合を防止しています。

### GCP設定と認証情報ファイルの取得
・Google Cloud Consoleにアクセスし、ログインします。
リンク：https://cloud.google.com/cloud-console?hl=ja

アカウント作成後は、
・新規プロジェクトを作成
・Google Sheets API と Google Drive API の有効化
・「APIとサービス」 > 「ライブラリ」に移動し、「Google Sheets API」と「Google Drive API」を検索し、各APIを有効化します。
![スクリーンショット 2024-10-28 10.46.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670873/3fb9b191-70f3-9afe-432c-dcdaed52aa60.png)

・サービスアカウントの作成
→「APIとサービス」 > 「認証情報」に移動し、「認証情報を作成」ボタンをクリックし、「サービスアカウント」を選択し、サービスアカウントの名前を設定し、作成を完了します。

・認証情報（JSONファイル）の取得
→作成したサービスアカウントの「鍵」セクションで「鍵を追加」 > 「新しい鍵を作成」を選択します。
→「JSON」を選択し、「作成」ボタンをクリックすると、認証情報ファイル（JSON形式）がダウンロードされますので、このファイルにあるデータを環境変数で設定をします。
```
GOOGLE_SHEET_ID=
GOOGLE_PROJECT_ID=
GOOGLE_PRIVATE_KEY=
GOOGLE_CLIENT_EMAIL=
GOOGLE_TOKEN_URI=
```

コントローラーに下記のを設定
```
require "google_drive"
```

最後にアクションで実際にスプレットシートにデータを出力する処理を実装します。
```
  def save_to_google_sheet(vendor)
    # 必要な認証情報を環境変数から読み込む
    credentials = {
      type: "service_account",
      project_id: ENV['GOOGLE_PROJECT_ID'],
      private_key: ENV['GOOGLE_PRIVATE_KEY'],
      client_email: ENV['GOOGLE_CLIENT_EMAIL'],
      token_uri: ENV['GOOGLE_TOKEN_URI']
    }

    # 認証情報を使って特定のシートにアクセス
    worksheet = GoogleDrive::Session.from_service_account_key(StringIO.new(credentials.to_json)).spreadsheet_by_key(ENV['GOOGLE_SHEET_ID']).worksheet_by_gid("215102901")

    # データを追加
    worksheet.insert_rows(worksheet.num_rows + 1, [[
      Time.now.strftime("%Y-%m-%d"), #申込日時
      vendor.user_name, #名前
      vendor.user_namekana, #名前（カナ）
      vendor.email, #メールアドレス（任意）
      vendor.tel, #電話番号
      vendor.zipcode, #郵便番号
      vendor.address, #住所
      vendor.inquiry_type, #問い合わせ内容
      vendor.consult #具体的な相談内容
    ]])
    worksheet.save
  end

```
## 補足
Google Sheets APIには使用量の上限があり、1分あたりのリクエスト数が制限されます（例：1分に最大300件の読み取りリクエスト）。上限を超えると「429: Too many requests」のエラーが発生し、一定時間後に再試行可能です。

参照：
https://support.google.com/a/answer/10445916?hl=ja#:~:text=Drive%20API%20%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE,%E5%90%88%E8%A8%88%E3%81%AB%E9%81%A9%E7%94%A8%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

## まとめ
この実装により、Google Cloud Platformのサービスアカウントを使用してGoogleスプレッドシートにRailsアプリから自動的にデータを登録できるようになりました。DBの利用を避けつつ、スプレッドシートでのデータ管理を可能にするこの方法は、外部のユーザーとリアルタイムでデータ共有を行いたい場合に有効です。環境変数を利用した認証情報管理や、Google APIの操作に関する基本的な知識を活用することで、シンプルで安全な連携が実現しました。
Googleカレンダーの表示がいろいろと変わったせいで七五三が祝日になります（2024年10月）

# はじめに
Googleカレンダーの表示が最近微妙に変更されていました。
素の設定のままだと11月15日などで他の祝日とともにその他の行事が表示されているようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399121/ba46b864-914c-e96d-d0cd-66e03c8dc3f9.png)

ちょっと今までのよりカッコ良くなってますね。

この機能はカレンダー設定の 
「地域限定の祝日」の項目箇所で設定のオンオフが可能です。
まあここまではシンプルなんですがこれで解決はしません。

# 問題アリ
埋め込み用に作成したものもアプリ版と設定の同期は当然していないっぽいです。
カレンダー埋め込みコードのものは素の機能のカスタマイズの場合も反映されないです。

PCで設定した後にスマホ版で開いてみても反映されていたりしなかったりします。

# 解決方法？？
~~ということでアプリ画面でも設定修正しましょう。~~
~~あるいはGoogleCalendarAPIを利用して、参考のサイトでも利用して表示させるようにしましょう。~~

# おわりに
~~自分は素のカスタマイズでいっぱい反映させてたので明日からどうなるか楽しみです~~
~~やはりGASでもささっと利用できてないとこの先生きのこれなさそうですね。~~

# 追記
アプリ版は別に関係なくても対応できそうでしたので記事作成しました。

https://qiita.com/ajt_yaiyai/items/57ee926c6ad1b5a153b1

# 参考

なぜか七五三の日が祝日判定に？ Google Calendar APIの罠

https://fikaweb.jp/dev/google-calendar-api-holiday/

GoogleCalendarAPIの日本の祝日が国民の祝日以外も祝日扱いするようになった件

https://zenn.dev/gomo/articles/2ff8501f7afaff
paizaラーニング問題集「長テーブルのうなぎ屋」の自分のコードを改善してみた

以前、以下の問題を解きましたが、自分のコードに改善できる部分がありましたので、改善しました。

▼問題

https://paiza.jp/works/mondai/b_rank_skillcheck_sample/long-table

▼以前の自分のコード

https://qiita.com/toytoy24/items/9cc0eada748aadd239c9#comment-43a60e3662eb918b6eb5

```py
n,m = map(int,input().split())
s = []
senkyaku_flag = 0

for _ in range(m):
    
    a,b = map(int,input().split())

    for j in range(b,a+b):

        if j > n:
            j = j % n

        if j in s:
            senkyaku_flag = 1
            break
        else:
            s.append(j)

    if senkyaku_flag == 1:
        for _ in range(j-b):
            s.pop()
   
    senkyaku_flag = 0

print(len(s))
```

▼改善の概要と、改善後のコード

▽改善の概要

改善したのは、問題文の「いずれか一つでも既に先客に座られている座席があった場合、一人も座らない」部分です。先客に座られている座席があればsenkyaku_flag=1とし、senkyaku_flag=1ならば、すでに座ったグループ全員のデータをpopで取り除く方針でした。

改善後は、senkyaku_flagおよびpopは使用せずdelでスライス指定して範囲削除する方針としました。この改善によってコード数を減らすことができました。

▽改善後の自分のコード

改善した部分をコメントで示します。

```py
n,m = map(int,input().split())
s = []
# senkyaku_flagは使用しないためコメントアウト 
#senkyaku_flag = 0

for _ in range(m):
    
    a,b = map(int,input().split())
    
    for j in range(b,a+b):
        
        if j > n:
            j = j % n
        
        if j in s:
            # delでスライス指定して範囲削除する処理を追加
            if j != b:
                del s[-(j-b):]
            break
        else:
            s.append(j)

    # popは使用しないためコメントアウト
    #if senkyaku_flag == 1:
        #for _ in range(j-b):
            #s.pop()

print(len(s))
```
JavaScriptを利用してモンテカルロ法でπの近似値を求めてみた

# はじめに
モンテカルロ法でπの近似値を求めるミニアプリをJSで作りました。

[デモ](http://monte-calro-circle.wealthy-design.com/)

画面：
![スクリーンショット 2024-10-31 17.55.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682035/daf308c8-1560-04ca-5758-e49053208cdd.png)

# モンテカルロ法とは
モンテカルロ法とは、確率と統計に基づき乱数を利用して複雑な問題の近似解を求める手法で、元々は原子炉のシミュレーションに使われていました。この方法の考案には、1940年代にジョン・フォン・ノイマンとスタニスワフ・ウラムが関わり、第二次世界大戦中のマンハッタン計画での原子炉挙動予測に活用されました。モナコのカジノ名に由来し、現在では金融工学や物理、工学など多分野で応用されています。

# 円周率（π）を推定するステップ
1. ランダムな点を生成する
正方形の範囲内（キャンバス全体）に、ランダムな位置の点を連続的に生成し、プロットします。

1. 条件を満たす点をカウントする
各点が円の内部か外部かを判定します。円の中心からその点までの距離が、円の半径より小さい場合であれば「円の中」とみなし、カウントを増やします。円の内側の点は青、外側の点は赤で描画されます。

1. 比率を計算して円周率を推定する
円内にある点の数を、全体の点の数で割り、その比率を用いて円周率を近似します。円が正方形に内接している場合、この比率はπ/4に近づくため、円周率の推定にはこの比率を4倍した値を利用します。

# コード

```html:mcc.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Monte Carlo Circle</title>
    <style>
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>

<h1>モンテカルロ法で円を描画する</h1>
<canvas id="monteCarloCanvas" width="500" height="500"></canvas>
<p id="piValue"></p>

<script>
    // キャンバスとコンテキストの取得
    const canvas = document.getElementById('monteCarloCanvas');
    const ctx = canvas.getContext('2d');
    const width = canvas.width;  // キャンバスの幅
    const height = canvas.height;  // キャンバスの高さ
    const radius = width / 2;  // 円の半径（キャンバスの半分）
    let insideCircle = 0;  // 円の中に入った点の数
    let totalPoints = 0;  // 全体の点の数

    // 正方形と円を描画
    ctx.strokeRect(0, 0, width, height);  // 外枠の正方形を描画
    ctx.beginPath();
    ctx.arc(radius, radius, radius, 0, Math.PI * 2);  // 円を描画
    ctx.stroke();

    // モンテカルロ法で点をランダムに描画
    function monteCarlo() {
        for (let i = 0; i < 1000; i++) {
            // ランダムな点のx, y座標を生成
            const x = Math.random() * width;
            const y = Math.random() * height;

            // 点と円の中心との距離を計算
            const dist = Math.sqrt(Math.pow(x - radius, 2) + Math.pow(y - radius, 2));

            // 距離が半径より小さい場合、円の中にある
            if (dist < radius) {
                insideCircle++;
                ctx.fillStyle = 'blue';  // 円の中は青色
            } else {
                ctx.fillStyle = 'red';  // 円の外は赤色
            }

            // 点を描画（小さな四角形で表現）
            ctx.fillRect(x, y, 2, 2);
            totalPoints++;
        }

        // モンテカルロ法で円周率の近似値を計算
        const piEstimate = (insideCircle / totalPoints) * 4;
        document.getElementById('piValue').textContent = `推定された円周率: ${piEstimate}`;
    }

    // 一定間隔でモンテカルロ法を実行
    setInterval(monteCarlo, 100);
</script>

</body>
</html>
```
セマンティックHTMLとは？

Webページの構造や意味を明確にするために、適切なHTMLタグを使用してコンテンツをマークアップすることを**セマンティックHTML**といいます。従来のHTMLでは、`<div>`や`<span>`といった汎用的なタグを使用して見た目中心のマークアップが行われていましたが、セマンティックHTMLでは、`<article>`、`<aside>`、`<nav>`といった意味を持つタグを使用することで、Webページの内容を機械が理解しやすくなります。

### なぜセマンティックHTMLが重要なのか？

セマンティックHTMLを使用するメリットは多岐にわたります。主なメリットは以下の通りです。

* **アクセシビリティの向上:** スクリーンリーダーなどの支援技術を利用するユーザーにとって、Webページの構造を理解しやすくなり、アクセシビリティが向上します。
* **SEO効果の向上:** 検索エンジンは、セマンティックHTMLを使用してWebページの内容を理解し、検索結果のランキングに反映させます。適切なタグを使用することで、検索エンジンがWebページのトピックを理解しやすくなり、検索順位の向上に繋がります。
* **コードの保守性向上:** セマンティックHTMLを使用することで、コードの構造が明確になり、開発者にとって理解しやすく、保守しやすいコードになります。また、CSSとの連携もスムーズになり、スタイリングの効率も向上します。
* **Webページの再利用性向上:** コンテンツを意味ごとに適切にマークアップすることで、Webページの再利用性が高まります。例えば、`<article>`タグで囲まれたコンテンツは、他のWebページやアプリケーションで再利用することができます。
* **将来の技術への対応:** Web技術は常に進化しています。セマンティックHTMLを使用することで、将来的な技術の変化にも対応しやすくなります。


### 具体的なセマンティックHTMLタグの例

以下は、よく使用されるセマンティックHTMLタグの例です。

* `<article>`: 記事やブログの投稿など、独立したコンテンツを表します。
* `<aside>`: メインコンテンツとは関係のない補足情報（サイドバーなど）を表します。
* `<nav>`: ナビゲーションメニューを表します。
* `<header>`: ページやセクションの見出しを表します。
* `<footer>`: ページやセクションのフッターを表します。
* `<main>`: ページのメインコンテンツを表します。
* `<section>`: ページをテーマごとに分割するセクションを表します。
* `<figure>`: 画像、図、表、コードリストなど、独立したコンテンツを表します。
* `<figcaption>`: `<figure>`要素内のコンテンツのキャプションを表します。


### セマンティックHTMLを使う上での注意点

* **要素の入れ子構造に注意:**  要素の意味を正しく反映するように、適切な入れ子構造を使用する必要があります。例えば、`<article>`の中に`<aside>`を入れることは適切ではありません。
* **過剰な使用を避ける:**  すべての要素をセマンティックなタグでマークアップする必要はありません。`<div>`や`<span>`が必要な場合もあります。
* **適切なタグを選択する:**  複数のタグが候補となる場合は、最も適切な意味を持つタグを選択する必要があります。


### まとめ

セマンティックHTMLは、Webページのアクセシビリティ、SEO、保守性、再利用性を向上させるために重要な技術です。適切なタグを使用することで、Webページの内容を機械が理解しやすくなり、より良いWeb体験を提供することができます。学習コストも低く、大きなメリットがあるので、ぜひ活用してみてください。

### 参考文献
- https://developer.mozilla.org/ja/docs/Glossary/Semantics
【git】- オプションで直前にいたブランチを指定できる

## はじめに

git の操作を効率化したいエンジニア向けに、`-`オプションを紹介します。
<br>

※すでに`-`オプションをご存知の方には役立たない記事なのでスルーしてください。

## `-`オプションで直前にいたブランチを指定できる

たとえば次のシナリオを考えます。
<br>

1. ベースブランチ`develop`にいる
2. 作業ブランチ`hogehoge`を作って作業
3. マージまで完了したのでベースブランチ`develop`に戻る
<br>

この場合、gitコマンドの流れは次のようになります。
<br>

```bash
$ git branch          # ベースブランチ develop にいることを確認
* develop
$ git switch hogehoge # 作業ブランチを切る
# ... コミット, プッシュなどは省略
$ git switch develop  # ベースブランチ develop に戻る
```
<br>

このとき、最後の`git switch develop`の代わりに`git switch -`と指定することで、直前にいたブランチ（つまり`develop`）に戻ることが可能です。
<br>

```bash
$ git branch          # ベースブランチ develop にいることを確認
* develop
$ git switch hogehoge # 作業ブランチを切る
# ... コミット, プッシュなどは省略
$ git switch -        # 直前にいたブランチ（つまり develop）に戻る
```
<br>

`develop`に戻った後で再度`git switch -`を実行すると、直前にいたブランチ（今度は作業ブランチの`hogehoge`）に再び戻ります。
<br>

`switch`コマンド以外でも`-`オプションは利用可能です。
<br>

仕事では develop ブランチでリベースする際に`git rebase -`のように使うことが多いですね。

## おわりに

ベースブランチと作業ブランチを行ったり来たりするケースが多いため、この`-`オプションはかなり有効です。
<br>

最近知ったばかりですが、かなり多用しています。
<br>

他にも便利な git コマンドはたくさんありそうなので、見つかり次第アウトプットしていきます。
SwiftでSOLID原則（2b/3）

## はじめに
前回の記事[「SwiftでSOLID原則（2a/3）」](https://qiita.com/generosity-naman/items/7e4f1a7769baaa71d41d) では、ソフトウェアデザインの中心である SOLID 原則 の概念を紹介シリーズにオープン/クローズドの原則（OCP）について詳しく解説しました。この記事では、リスコフの置換原則（LSP）に関して、Swiftを使った例で、紹介したいと思います。

## リスコフの置換原則（LSP）
リスコフの置換原則は、サブクラスがスーパークラスの代替として利用可能であるべきとする概念です。プログラム内でスーパークラスのオブジェクトをサブクラスのオブジェクトに置き換えても、システムの正確な動作が保証される必要があります。つまり、サブクラスはスーパークラスと同じインターフェースを実装し、予期しない動作を起こさないようにする必要があります。

### 概念的な例：
家電製品を操作するリモコンをイメージしてみましょう。リモコンは、テレビ、DVDプレーヤー、またはステレオシステムなど、異なるデバイスに対しても同様に動作します。どのデバイスでも基本的な機能（電源のオン/オフ、音量調整など）が同じように動作するため、リモコンを異なるデバイスで使っても問題ありません。

### Swiftでの実例：
Bird（鳥）クラスを考えましょう。例えば、このクラスに fly メソッドがあるとします。LSPに従うならば、スズメやペンギンのようなすべてのサブクラスもこのメソッドを実装し、Birdクラスとして一貫して動作することが求められます。飛べないペンギンの場合も、「飛ばない動作」としての実装が必要です。

```swift
// Birdの基本クラス
class Bird {
    func fly() {
        print("Flying high!")
    }
}

// 飛べる鳥
class Sparrow: Bird {
    override func fly() {
        print("Sparrow is flying!")
    }
}

// 飛べない鳥
class Penguin: Bird {
    override func fly() {
        print("Penguin can't fly!")
    }
}

// 使用例
let birds: [Bird] = [
    Sparrow(),
    Penguin()
]

for bird in birds {
    bird.fly()  // LSPによって、すべてのBirdはflyメソッドを持つが、それぞれの実装は異なる
}

```
&ast;&ast;解説: ここでは、`Bird` クラスと、そのサブクラスである `Sparrow` と `Penguin` を定義しています。リスコフの置換原則に従い、Bird クラスの `fly()` メソッドは、どのサブクラスでも使用でき、サブクラスごとに異なる動作を持たせています。この設計により、一貫性のあるインターフェースで異なる振る舞いが実現されています。

### 適用性：
この原則は、継承とポリモーフィズムを使用する場面において特に重要です。適切な設計により、異なるクラス間で予測可能で一貫性のある動作を実現できます。

### 実装方法：
サブクラスがスーパークラスで定義された契約（プロトコルやインターフェース）を遵守するよう設計します。LSPを満たすために、スーパークラスでの動作をサブクラスで正しく継承し、動作の一貫性を確保します。

### メリット：
- コードの相互運用性が向上し、異なるクラス間での共通の動作が可能になります。
- ポリモーフィックな設計がしやすくなり、クラス間の結合が低く保たれます。

### 留意点：
LSPを守るための設計には注意が必要であり、特に複雑なクラス階層を作成する際は設計の慎重さが求められます。

## 結論:
ここまでで、SOLID原則の三つの重要な原則である「単一責任の原則」、「オープン/クローズドの原則」と「リスコフの置換原則（LSP）」　について掘り下げて学びました。次回の記事では、インターフェース分離の原則 と 依存性逆転の原則 に注目し、Swiftでの具体的な実装例とともに、その効果とメリットを紹介します。
次の記事まで、ハッピーコーディング！
ドメインとIPアドレスを繋ぐDNSとは？仕組みからレコードの種類までを解説

<br>

# ■ はじめに

DNSはインターネットでWebサイトにアクセスしたりメールを送受信したりする時に使われます。
意識していなうちに大きな役割を持つこのDNSですが、どのようなモノや仕組みかはぱっと分かりにくいものだと思います。
この記事ではDNSの基礎知識から具体的な動作、DNSレコードの種類やキャッシュの仕組みまでを解説します。

# ■ 目次
<br>

1. [DNSとは？](#1-dnsとは)
2. [DNSの基本的な仕組み](#2-dnsの基本的な仕組み)
3. [DNSサーバーの役割と種類](#3-dnsサーバーの役割と種類)
4. [代表的なDNSレコードの種類](#4-代表的なdnsレコードの種類)
5. [DNSキャッシュとTTL](#5-dnsキャッシュとttl)
6. [まとめ](#6-まとめ)

# 1. DNSとは？
<br>

DNS（Domain Name System）は簡単に言うと
**人間が覚えやすいドメイン名とコンピュータが理解できるIPアドレスを対応させるシステム**です。  

例えばWebブラウザに「www.test.com」と入力した場合にはDNSがこのドメイン名を解析し、対応するIPアドレス（「192.0.2.1」の形式）を返します。
これによりユーザーはIPアドレスを特段意識せずにドメイン名でWEBサイトへアクセスできるようになっています。

- **ドメイン名とIPアドレスの対応付け**  
  もしDNSがなければインターネット上の各サービスにアクセスするためにIPアドレスを直接入力する必要がありました。
  このDNSがあることでドメイン名がIPアドレスに変換され、インターネットの利用が非常に便利なものになっています。

# 2. DNSの基本的な仕組み
<br>

DNSは階層構造をもつ複数のDNSサーバーによってドメイン名の解決が行われます。

1 **リクエスト送信**  
   ユーザーがブラウザにドメイン名を入力すると、その情報がまずDNSリゾルバ[^1]に送られます。
<br>

2 **DNSリゾルバからルートDNSサーバーへ**  
   DNSリゾルバはドメイン名のIPアドレスを直接持っているわけではないため、まずはルートDNSサーバーに問い合わせを行います。
   
   :::note
   ドメインは**test.co.jp**であれば**test**と**co**と**jp**に分かれており、
   - jpをトップレベルドメイン（TLD）
   -  coをセカンドレベルドメイン（2LD）
   -  testをサードレベルドメイン（3LD）
   と呼びます。
   :::
   
   このルートDNSサーバーは全てのトップレベルドメイン（TLD）の情報を管理しています。
<br>

3  **階層的なサーバー検索**  
   ルートサーバーは対象ドメインのTLDサーバーを案内します。
   次にTLDサーバーは該当する権威DNSサーバー[^2]にリクエストを転送します。
<br>

4 **権威DNSサーバーの応答**  
   最終的に権威DNSサーバーがドメイン名と対応するIPアドレスをDNSリゾルバに返します。
   このIPアドレス情報を受け取ったリゾルバはブラウザに結果を返し、ユーザーがドメイン名でアクセス可能となるのです。

# 3. DNSサーバーの役割と種類
<br>

DNSにはいくつかの種類があり、それぞれ異なる役割を果たしています。

- **ルートDNSサーバー**  
  インターネット全体のDNSのトップに位置し、TLDサーバー（例：.comや.jp）の情報を提供します。
<br>

- **TLDサーバー**  
  特定のトップレベルドメイン（TLD）のDNS情報を管理しています。
  .comドメイン全体を管理するTLDサーバーは、各ドメイン名の次の権威DNSサーバーを案内します。
<br>

- **権威DNSサーバー**  
  ドメイン名に関する最終的な情報（IPアドレスやDNSレコード）を持っており、最終的にIPアドレスを返します。
<br>

- **キャッシュDNSサーバー（リゾルバ）**  
  各ISPや企業が設置しているキャッシュDNSサーバーは、IPアドレスの問い合わせを効率化するためにキャッシュを行い、過去にアクセスされた情報を保存しておきます。

# 4. 代表的なDNSレコードの種類
<br>

DNSでは各ドメイン名に異なる役割をもつレコードが設定されており以下のようなものがあります。

- **Aレコード**  
  ドメイン名に対応するIPv4アドレスを指定するレコード
  最も基本的なレコードで、WebサイトのIPアドレスが含まれている
<br>

- **AAAAレコード**  
  IPv6アドレスを指定するレコードで、IPv6対応のインフラに用いられる
<br>

- **CNAMEレコード**  
  別のドメイン名にエイリアスを設定するためのレコードで、別名でのアクセスを可能にする
  例えば「www.example.com」を「example.com」にリダイレクトするような設定ができる
<br>

- **MXレコード**  
  メールの送受信サーバーを指定するレコード
  メールを適切なサーバーに配送するために利用される

# 5. DNSキャッシュとTTL
<br>

DNSは効率的なアクセスのためにキャッシュを利用します。
このキャッシュにはTTL（Time To Live）という有効期限が設定されており、期限が切れると再度問い合わせが行われます。
<br>

- **DNSキャッシュ**  
  過去の問い合わせ結果を保存することで、再アクセス時にスピーディーにIPアドレスを取得する
<br>

- **TTL**  
  キャッシュの有効期限を指定する数値で、TTLが切れると再問い合わせを行い最新の情報に更新される
  TTLの値が短いとIP変更が速やかに反映される代わりに、頻繁な問い合わせが発生するためトラフィック[^3]が増加する

# 6. まとめ
<br>

 - **DNSの役割**
     - ドメイン名とIPアドレスを対応付け、利便性を向上
 - **DNSの仕組み**
     - リゾルバがルート、TLD、権威DNSサーバーを通じてIPアドレスを取得
 - **DNSサーバーの種類**
     - ルートサーバー、TLDサーバー、権威DNSサーバー、キャッシュDNSサーバーが協力してドメイン名解決を実現
 - **DNSレコードの種類**
     - A、AAAA、CNAME、MXなど用途に応じた多様なレコードが存在
 - **DNSキャッシュとTTLの役割**
     - キャッシュにより高速なアクセスを実現し、TTLでキャッシュの更新頻度を管理

[^1]:**リゾルバ**（resolver）はDNSサーバへドメイン名を照会し、対応するIPアドレスを調べたりその逆にIPアドレス→ドメイン名を調べたりするソフトウェア
[^2]:ドメイン名とIPアドレスが対応づけられたゾーン情報を保持し、他のDNSサーバに 問い合わせることなく応答を返すDNSサーバのこと
[^3]:通信回線やネットワーク上で送受信される信号やデータのこと
Tiktokで1400いいね以上を得たお笑いAIがシャドウバンされた話

![2024y10m31d_170931546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683844/58f39371-d094-d645-527f-881d2f637e13.png)
↑10月31日17時09分時点のアナライズ↑

お笑いAI"netaAI"が生成したコントを公開するtiktokチャンネルで、コントが1400いいねを得ました。
結果、なぜかシャドウバンされました。
何がどう誤検知されたのか…

https://www.tiktok.com/@netaai_tiktok/video/7430351775493836040

netaAIは既に面白さで九割九分の人間を超えています。
インプレッション以外は全て足りています。
仕事・取材等お待ちしております。

Tiktokで1400いいねを得たからといって、お笑いを見ない層に向けたコメディを生成している訳ではなく、きちんと さらば青春の光, ファイヤーサンダー, Aマッソ, 滝音, かもめんたる, 等を学習させた上でのコメディを生成しています。

また、LLMのチャットボックスに自然言語で注文を書いてお笑いを生成させる、というような馬鹿な真似はしていません。きちんと形式言語で、頭を使って、VScodeと睨めっこした上で生成させています。

テレビ局は、LLMに自然言語でネタを注文して、つまらないものが出力されて、嘲笑する、なんてことをしている場合ではありません。私を見て下さい。
Huawei Switch から rsyslog にログを送る

## どんな記事か
Huawei スイッチから syslog を送る設定に詰まった。原因はファシリティが一致していなかったため。


## 目次
1. 開発環境
2. 概要
3. 前提条件とトポロジ
4. 課題
5. 原因
6. 解決方法
7. まとめ

## 開発環境
Fedora41 / rsyslog / CloudEngineS5735
 
## 概要
今回は、HuaweiのスイッチからSyslogを送れない問題について解説する。原因はファシリティの設定ミスマッチであり、この問題はネットワーク機器以外からのログ転送でも発生し得るため、同様の課題に直面した際に役立てば本望。

### 前提：
各ノードは疎通が確認されている (pingが通る)
Syslog Serverにはrsyslogが稼働しており、PC-BからSyslogの送信は成功している

### 課題：
Switch (LabB-Core) からSyslog ServerへのSyslog送信が失敗している

### 原因：
SwitchとSyslog Serverのファシリティ設定が一致していなかった


## 前提
### トポロジ
![10292024SwitchSyslog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357222/61306521-a582-d282-adeb-eefe3979de93.png)

各ノードは疎通確認済み
Syslog Serverにはrsyslogが稼働中
PC-BからSyslogは送信可能

## 課題
Switch の Config
https://support.huawei.com/enterprise/en/doc/EDOC1000178167/89b6f3b4/configuring-the-device-to-output-logs-to-a-log-host

```Switch
[HUAWEI] info-center loghost 10.100.1.201 port 514 transport udp
[HUAWEI] info-center source default channel logbuffer state on level notification
```

この状態で、Switch で display logbuffer が更新されても Syslog Server に送信されなかった。ミラーポートに接続したWireSharkを確認すると、Switch から Syslog Server に向かって Syslog が送信されていた。ここから、受信がうまくいっていないことに気づく。

## 原因
正常に Syslog Server に反映されている PC-B からの Syslog が送信されるときのパケットと、Switch からの Syslog パケットを比較した。すると、冒頭数値  (LOCAL7/LOCAL0) が異なることが分かった。これはファシリティというらしい。

:::note
ファシリティというのは、ログの種類を指定する箇所で、cronやmailなどがあり、今回指定するlocal0（～7）は独自に使用できるファシリティになっています。
(引用：https://qiita.com/sugar_salt75/items/1d1980d5b66becc9f38f)
:::

Huawei Switch (CloudEngine S5735) では local0〜7 が選択できる。


## 解決方法
Switch で Facility を変更
```Switch
[HUAWEI] info-center loghost 10.100.1.201 facility local0
```

なんとなく編集していたため気づかなかったが、/etc/rsyslog.conf でファシリティを設定していた。Syslog Server で受け取る設定をしているファシリティと一致しないとドロップされる様子。


## まとめ
一日詰まったが、何とか Syslog が送れて (受け取れて) 良かった。やっと検証環境が出来たので、ネットワークをいじったときのログを検証する。
コンピュータ言語の変換　webにこんなのがあった。


こんなのがありました。これでは、コンパイラを作る気がなくなってしまいます。ちょっと試したところ、まだバグを発生するみたいだけど。NULLの処理に問題があるなあ。数値表現の型の範囲外の動作にも問題がある。[Debug]ボタンがありますが。GAME言語やBrainfuckのような特殊な言語はないみたい。スーパーコンピュータを使っているらしいです。有料だということで、今の所、手が出ません。

https://aicodeconvert.com/
【イベントレポート】モバチキ 〜Mobile Tips 共有会〜 #6

## はじめに

普段は大分県でエンジニアをやっています

久しぶりに福岡県のエンジニアイベントに参加してきました

https://moneyforward.connpass.com/event/333150/

目的はモバイル開発界隈に ElixirDesktop を布教することです

https://github.com/elixir-desktop/desktop

Elixir によるモバイル開発は、すでに実践配備されているのです（ @piacerex さんのスライド参照）

<script defer class="speakerdeck-embed" data-id="376dd3d1889e4997940029544a2f357c" data-ratio="1.7843866171003717" src="//speakerdeck.com/assets/embed.js"></script>

ElixirDesktop によるモバイル開発の手順は @the_haigo さんの記事をご覧ください

https://qiita.com/the_haigo/items/f419bda951bb60145556

上記のお二人、 @the_haigo さん、 @piacerex さんの登壇を見届けるため、大分から参戦してきました

ちなみに直近のElixirモバイル開発イベントはこちら

https://fukuokaex.connpass.com/event/334452/

## 会場

株式会社マネーフォワードさんの福岡開発拠点で開催されました

https://fukuoka.moneyforward.com/

実は以前、宇宙 x Elixir のイベントでもお邪魔しています

https://moneyforward.connpass.com/event/284805/

オレンジ色と白の明るいスペースで、和やかにイベントを楽しむことができました

## LT

Swift からは随分離れていたこともあり、色々新しい話を聞けて満足しました

最初は TCA の話

https://x.com/nakaji573/status/1851204388305715210

https://github.com/pointfreeco/swift-composable-architecture

テストしやすくなった、というのが良くわかりました

続いて Periphery というツールの紹介

https://x.com/nakaji573/status/1851206956851347485

https://github.com/peripheryapp/periphery

Periphery は本当に導入が簡単で、私もその場で実行できました

https://x.com/nakaji573/status/1851209566803099905

あと、マネーフォワードの方々は自然に英会話できていて圧倒されました

そして、いよいよ @the_haigo さんの登壇

https://x.com/nakaji573/status/1851212590569177521

<script defer class="speakerdeck-embed" data-id="392c87b70bfc44dba79b75a49e8dcf7e" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

「Elixir でモバイル開発ってどういうこと！？」みたいな空気の中、丁寧に説明してくださいました

会場からの反応も上々で、十分布教できたのではないでしょうか

https://x.com/nakaji573/status/1851213335704084835

続いて AR アプリ開発のお話

https://appadvice.com/app/e3-83-a6-e3-82-af-e3-83-a2-e3-82-b9-e3-83-8a-e3-83-83-e3-83-97/6502643077

https://apps.apple.com/us/app/id6502643077

https://x.com/nakaji573/status/1851219177450979395

行列演算の話など、リアルに試行錯誤した過程が面白かったです

最後に画面遷移の実践的なお話

https://x.com/nakaji573/status/1851221752359297473

XCode の更新のせいで、ギリギリまでシミュレーターが動かないという逆境の中、見事にライブコーディングされていました

## 懇親会

懇親会の一幕で @piacerex さんの登場(いつもの姿で)

https://x.com/nakaji573/status/1851228366084387013

是非、イベントにも気軽に遊びにきてください

https://x.com/nakaji573/status/1851231096031072366

余談ですが、 Elixir エンジニアは少なくとも海外ではメッチャ高給取りです

https://x.com/nakaji573/status/1851229055808626915

https://survey.stackoverflow.co/2024/technology/#top-paying-technologies

改めて、11/6(水)のイベントで Elixir モバイル開発のディープな話が聞けます

https://fukuokaex.connpass.com/event/334452/

是非、ご参加ください

## まとめ

リアルな体験談やライブコーディングなど、面白い LT が詰まっていて良いイベントでした

やはりオンラインの方がイベントの緩い空気感などが直に伝わって良いですね

またオンラインイベントにもどんどん参加したいと思います（体と時間と財布に相談しながら）
データサイエンティスト検定合格体験記

# はじめに

みなさんこんにちは！
はつかぜ株式会社サポート室のSと申します。
本日はデータサイエンティスト検定（以下DS検定）のリテラシーレベルに合格したので、その体験記を書いていきたいと思います。

# DS検定とは
DS検定とは、一般社団法人データサイエンティスト協会が開催しているデータサイエンティストとしての実務能力と知識を有することを証明する試験です。試験内容はデータサイエンティストとして必要なスキルが「データサイエンス力」、「データエンジニアリング力」、「ビジネス力」の3つに分類され、各々出題されます。


# 使った参考書と勉強法
【使った参考書】
①データサイエンティスト検定（リテラシーレベル）公式リファレンスブック
②徹底攻略データサイエンティスト検定[リテラシーレベル]対応問題集

新しい試験のため参考書などはあまり種類がないですがこの2冊をしっかりやれば大丈夫かと思います。範囲が膨大なので、試験に受かることを意識するのであれば沢山の教材に手を出すよりこの2冊に絞って学習する方が現実的かと思います。

【勉強法】
①のテキストは内容がずっしりしていて、全て読み込んで理解するのは結構大変だと思います。私は文系出身なので特にそう感じました（理系の方であれば結構簡単なのかな？）。「データサイエンス力」と「データエンジニアリング力」の項目は数学の知識が必要だったり大変ですが、「ビジネス力」の項目は比較的楽でした。理系科目苦手な方は大まかに理解できればいいくらいの気持ちで読み進めていくといいと思います。実際そんな感じでも合格できました。

②の問題集は全部暗記するくらいの気持ちで回しましょう。試験の時の対応力や自信がつきます。

# 受験した時のこと
私が受験したときは試験時間90分、出題数90問でした。時間に対して問題数が多く、また問題がかなり難しく感じたので試験中はずっと落ちたなと感じていました。結果としては合格基準の80%よりかなり余裕を持って合格できたので、ネガティブにならず最後まで頑張ることが大事だと思いました。

# 最後に
はつかぜ株式会社では、DS検定以外にも基本情報技術者試験やAWS認定資格などの取得サポートを社員に対して積極的に行っています。

はつかぜ株式会社では、IT学習や業務に役立つ情報を定期的にお届けしていきたいと思っています。
システム開発のお問い合わせ・ご相談はこちら https://www.hatsukaze.co.jp/inquire/
VBAを使わずにFletでExcelとAccessデータベースを制御

# VBA不使用でAccessデータベースとExcelを制御してみた
Fletを使って、VBAを使わないユーザーインターフェイスを作ってみました。

# まずは動画をご覧あれ
YouTubeに同んな感じの動画をあげてみました。
https://youtu.be/a_tQW0qhpX8

どうも操作が下手くそ！！

# Fletからpywin32を呼び出すと嫌というほどエラーが出る
いろいろと試してみましたがFlatやFlaskのようなマルチスレッド環境からpywin32を呼び出せないようです。
で、苦肉の策として低水準Socketでタスクを分けて通信し制御する方法を開発してみました。

非同期なので、ちょっとどんくさい。
AWSの開発環境構築手順：RDS編

# RDSとは？

ChatGPTに質問しました。

> Q:RDSに関して5行程度で教えてください。

> A:
AWSのRDS（Relational Database Service）は、クラウド上で管理されたリレーショナルデータベースを簡単に利用できるサービスです。
MySQL、PostgreSQL、MariaDB、Oracle、SQL Server、Amazon Auroraなどの主要なデータベースエンジンをサポートし、自動バックアップ、フェイルオーバー、リードレプリカなどの機能で高可用性とスケーラビリティを提供します。
運用管理が不要なため、スケーリングやパッチ適用も自動化され、負担を軽減できます。
また、セキュリティグループでネットワークアクセスを制御し、安全なデータベース環境を構築できます。

DBサーバーを構築してくれるサービスです。
MySQLとPostgreSQLの完全な互換性を持つAuroraが存在しますが、オーバースペックで高額になりそうなので、今回は純粋なPostgreSQLを採用しました。

# 作業内容

## サブネットグループを作成

RDS>サブネットグループと進んで、[DB サブネットグループを作成]を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/83cae525-ce17-a649-fa6f-50ca9def8ed0.png)
<br>

- 「名前」をproject-dev-subnet-groupと入力
- 「VPC」でproject-dev-vpcを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/2bab09dd-8399-29b6-b33b-ae011d18be57.png)
<br>

- 「アベイラビリティーゾーン」でap-northeast-1a、ap-northeast-1cを選択
- 「サブネット」でprivateサブネットを選択する
- [作成]を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/4afa07ef-2b04-3c27-d38c-adda63c65c92.png)
<br>

## DBインスタンスを作成する

RDSの画面で[データベースの作成]を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/5c0d8dae-1332-bde4-4bb5-9310ad8d5cbc.png)
<br>

- 「標準作成」を選択
- 「PostgreSQL」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/4cccff7b-fefc-d9e0-ab3b-029a095e4898.png)
<br>

- 「開発/テスト」を選択
- 「単一の DB インスタンス」を選択
※本番環境では「マルチ AZ DB インスタンス」を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/45a07c2d-f673-7bb1-6256-f423b11408bf.png)
<br>

- 「DBインスタンス識別子」にproject-dev-rdsを入力
- 「セルフマネージド」を選択して、「パスワードを自動生成」にチェックを入れる
**※後で自動生成されるパスワードを控える**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/1ccb13c1-1d05-779d-2ff5-f67622c05d9c.png)
<br>

- 「Virtual Private Cloud(VPC)」でproject-dev-vpcを選択
- 「DBサブネットグループ」でproject-dev-subnet-groupを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/48f89ec2-45a3-1ac6-9c1f-bfcb0f0bd3d5.png)
<br>

「VPCセキュリティグループ」で「既存の選択」を選択して、project-dev-rds-sgを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/f25dc70d-3345-7b01-889e-5854d2ddb04a.png)
<br>

追加設定を開いて、「最初のデータベース名」にproject_devを入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/2c88332f-7431-4478-af7c-7d24a75d9a60.png)
<br>

[データベースの作成]を押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/626c3606-cd73-588a-362c-70a6538443f6.png)
<br>
OSPF - Filtering with Summarization (the not-advertise keyword)

## Operating Environment
OS: Windows 11
VM: VMware® Workstation
Software：CML 2.7.2
Hardware：N/A

## Network Topology
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/8cacd2aa-6d25-0267-dbc2-38688a302688.png)

## Inter-Area Summarization Confirmnation
### R3
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/e1ffefb5-bfd8-7afd-ed92-60a0e1d49cf7.png)

## Configuration of filtering using the summary function
### R2
#### For summary commands with the cost keyword, executing them with no in front only removes the cost setting.
![Screenshot 2024-10-31 163623.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/c45d499d-f859-5af4-0942-87837a4ecc77.png)
### R3
#### Summarized routes still exist.
![Screenshot 2024-10-31 164407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/c90d0056-899c-1ee0-8c1a-343dcf088e92.png)
### R2
#### Use the not-advertise keywordto filter routes. The advertise keyword is required to delete a summary command.
![Screenshot 2024-10-31 165009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/ec680771-1ec0-d185-c6c6-b32a3f7e69a2.png)
### R3
#### 172.16.2.0/24 is filtered.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3923257/13d9b7cc-ca7a-6ff3-0fc3-15c076fe9a2b.png)
【python】openpyxlの挿入で＠が出た時


# 具体例

```python
from openpyxl import load_workbook

org = 'hogeExcel.xlsx'
sheet_name = 'fuga'
sheet_name2 = 'fugafuga'

wb = load_workbook(org)
ws = wb[sheet_name]
ws['C2'] = "=UNIQUE({0}!$A$3:$B$1000)".format(sheet_name2)
wb.save(org)
wb.close()
```

で、Excelを確認すると

```excel
=@UNIQUE(fugafuga!$A$3:$B$1000)
```

と記載されており、「#NAME?」というエラーが出る。  
@を削除すると期待通りの結果は得られる。  
のでアットマークをなんとかしたいぜという人のためのメモ。  


# 解決例

結論から言うとUNIQUE関数はそのままでは使えないっぽいです。
日本語ドキュメントがなかったので機械翻訳に頼ったまとめが下記。

- openpyxlではSORTやUNIQUEのようなExcel関数(数式)は初期仕様に含まれていない
- ArrayFormulaを使うことでExcelの配列数式に対応可能
- _xlfnを使うことで初期仕様に含まれていない数式を動かせる

https://stackoverflow.com/questions/75590855/excel-file-needing-a-recovery-when-i-create-a-file-that-uses-unique-function-wit  

https://tongere.hashnode.dev/python-openpyxl-styling-a-spreadsheet


……ということで修正したものがこちら。

```python
from openpyxl import load_workbook
from openpyxl.worksheet.formula import ArrayFormula
from openpyxl.utils import FORMULAE

org = 'hogeExcel.xlsx'
sheet_name = 'fuga'
sheet_name2 = 'fugafuga'

wb = load_workbook(org)
ws = wb[sheet_name]

# 変更箇所
alist = list(wb[sheet_name2]['A3:B1000'])
blist = [list(tup) for tup in zip(*alist)]  # 要素取り出し
clist = [list(x) for x in zip(*blist)]      # 転置
cnts = len(set(list(map(lambda c: str(c[0].value)+str(c[1].value), clist)))) # UNIQUE後の長さ

if "UNIQUE" in FORMULAE:
    ws["C2"] = ArrayFormula("C2:D{0}".format(cnts+2), "=UNIQUE({0}!$A$3:$B$1000)".format(sheet_name2))
else:
    ws["C2"] = ArrayFormula("C2:D{0}".format(cnts+2), "=_xlfn.UNIQUE({0}!$A$3:$B$1000)".format(sheet_name2))

wb.save(org)
wb.close()

```

```"UNIQUE" in FORMULAE```　でopenpyxlの初期仕様に含まれている数式か判定していますが、SORTやUNIQUEは含まれていないのが分かっているのでこれはおまじないです。  
ほかの関数使うときに使いたいやつ。  

ArrayFormulaの引数は単純に（戻り値範囲,数式）でよいかと。  
ここの引数をずっと間違えていてファイル開けなかったので戻り値範囲を正しく入力しましょう……。  
あと、戻り値範囲をしているように、たとえ配列だろうが1行しか返さない仕組みのようなので、UNIQUEみたいに列数が可変のものは範囲も可変にしておいた方が安牌かなと。  
1行ずつ貼られると思ってなかったので、そのまま広めの範囲したら#N/A地獄が始まりました。つらい。  

ちなみにArrayFormulaはopenpyxl v3.0にはなかったです。  
v3.1.4に上げたら動いたので、バージョン古そうな人はそのあたりにアプデするとよいかも。