OmniAICreator/Qiita-1.07M huggingface dataset:
【Drupal】Viewsの最強機能 Contextual Filter 解説するよ

Viewsの最強の機能の一角、「**Contextual Filter**」使いこなせてますか？ 

私はWeb業界に入って、Drupalが始めてだったので理解するのに一番時間がかかった機能でした。（SQLとか知る由もない）

このシリーズでは三記事に渡って、Contextual Filter の基礎から応用までを段階的に解説していきます。

今回は **Introduction編** です。

:::note info
SQLの基本的な知識があると更に理解が深まります。
SQLシリーズも執筆してます。

こちらもぜひ。
[【SQLマスターへの道】NULL値を制御「COALESCE」](https://qiita.com/umekikazuya/items/85b10b3dc63909bc43dd)
[【SQLマスターへの道】条件付きソート「CASE・WHEN」](https://qiita.com/umekikazuya/items/a0132b6ac5123002932e)
[【SQLマスターへの道】入社年度で学ぶ 「BETWEEN」](https://qiita.com/umekikazuya/items/61c16a36824c334e31e5)
:::

## その前にContextってなに？

「ある特定の条件・状況」です。つまりシチュエーションですね。

例えば...。
- URLのPathに応じて投げるSQLクエリを変えたい
- ログインユーザーのIDを利用したSQLクエリを構築したい
- 言語に応じて、見せるコンテンツ/見せないコンテンツを制御したい

とか。シチュエーションに応じたフィルタリングをしたいために作られた機能が、Contextual Filter ですね。

## Contextual Filter って？
「シチュエーションに応じたフィルタリング機能」です。

DrupalのViewsが提供するデータの絞り込み機能ですね。SQLでいうとこの**WHERE句**です。

Argumentを動的に設定したいSQLクエリを作るにはもってこいです。
※ 固定値を設定して、あえて静的なフィルターにすることもできます。

## なにができる？
全部は紹介できませんが、私がに多用/乱用している使い方を2つ紹介します。

- フィールド値による絞り込み（BaseTableで設定しているEntityが持つフィールドのみ対象です）
- Views自体の表示制御（これめちゃくちゃ強い）

## 推しポイントは？
ちゃんと使いこなした際のメリットはめちゃくちゃ大きいです。

- ModelロジックのComponent化。（MVC）
- ViewロジックのCompoent化。（MVC）
Frontend Engineerにも一箇所のView Displayを説明すればいいですよね。
- クエリキャッシュを活かせるのでパフォーマンス面に優しい
- Configファイルが圧迫しない（複数のエンジニアで開発している際のコンフリクトリスク減）
- Etc…

Contextの渡し方/受け取り方の組み込みさえできれば、かなりメンテナンスしやすい作品ができます。

## え待って…。Viewsって標準のフィルターもあるよね？
はい。あります。

![スクリーンショット 2024-06-16 0.17.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/bec7199f-4b4b-c563-7308-cd4f7217a118.png)

でも決定的な違いがあります。

**静的 or 動的** です。

※ 標準のフィルターを Static Filter って僕は呼んでいます。この記事でもそう呼びます。

## Static Filter はいつ使うの？
Drupalに1年半捧げて、ありえないほどViews作ってきて答えが出たんですが、使うときは決まって1つ。

**「Exposed Filter を利用する時」のみです。**

つまり、GUIのフィルターが必要か否かです。

![スクリーンショット 2024-06-16 0.30.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/6e5e00c4-689d-7aa4-e9ff-319622502e3b.png)

ExposedFilterはまじで便利。
GUI設定のみで組み込んでくれてるのはあついです。（独自のForm実装がいらないので。）

## Contexual Filter はいつ使うの？
ほぼ全てですね。

**Argumentを動的に設定したいSQLクエリを作るにはもってこいです。**
**※ 固定値を設定して、あえて静的なフィルターにすることもできます。**

詳しくは次回の**How To編**でご紹介します。

単一のディスプレイのみで、Model/View ロジックの Component化 ができます。(MVC) 
もちろん、Context の渡し方をちゃんと組み込む必要はあります。

まさかですが、カテゴリの数だけ記事一覧のViewsDisplayを作成してないですよね？

## まとめ
いかがでしょうか？

WHERE句を設定したいなら、「Contextual Filter」しかありえないです。
WHERE句を変更するようなFormを実装する要件が出て始めて、「Static Filter」の選択肢が出てくるかと思います。
（もちろんそれすらも Contextual Filter でやってしまうことも多いですが...笑）

Argumentを動的変更したり、あえて静的(固定)にするということもできます。

Component化できる、クエリキャッシュを活かせる、メリットはかなり大きいと思います。

次回は **How To** 編 !!
細かい設定方法とその手順を詳しく解説します。

お楽しみに。

## Document

[公式: Contextual Filter](https://www.drupal.org/node/1578558)
PythonでPostgreSQLに接続してSQL実行（SqlAlchemy）

最新版は[こちら](https://yurutech.tech/2025/04/24/%E3%80%90python%E3%80%91postgresql%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%97%E3%81%A6sql%E5%AE%9F%E8%A1%8C%EF%BC%88sqlalchemy%EF%BC%89/)
## やること
下記のようなテーブルからリストとして[[hoge1, hoge2], [hoge3, hoge4]]を取得します
＊その他SQL文であればなんでも実行できると思います

|Column1|Column2|
|-------|-------|
| hoge1 | hoge2 |
| hoge3 | hoge4 |

## 概要
- sqlalchemyでポスグレに接続してSQLを実行  
- ソースは[github](https://github.com/ShamNeko88/database_manager)に置きました
- [github](https://github.com/ShamNeko88/database_manager)にはPosgreSQL以外のDB接続も追記していく予定です
- 使いまわしたいのでクラスである程度の事は吸収してもらう（クラスのお勉強）
- 今回はデータを一行ずつリスト形式で出力（[[hoge1, hoge2], [hoge3, hoge4]...]）

## 前提
- postgresのデータベース構築済み
- Pythonの基礎知識がある（クラス等）
## ソース
DB情報は下記を例とします。
- ユーザー名:  postgres
- password:   postgres
- ホスト:         localhost:5432
- データベース名: hoge
- テーブル名: hogehoge

```python
from sqlalchemy import create_engine, text


class ConnectPostgreSQL:
    """
    PostgreSQLに接続するクラス

    Args:
        user_name (str): ユーザー名
        password (str): パスワード
        host (str): ホスト
        database_name (str): データベース名

    Methods:
        execute_sql: SQL文を直接実行
    """
    def __init__(
          self, user_name: str, password: str,
          host: str, database_name: str
    ):
        # DB接続に必要なエンジンを作成
        self.engine = create_engine(
            f"postgresql://{user_name}:{password}@{host}/{database_name}"
        )

    def execute_sql(self, sql: str, get_result: bool = False) -> list:
        """
        SQL文を直接実行

        Args :
            sql (str): SQL文
            return_result (bool): 結果を返すかどうかのフラグ。デフォルトはFalse
        """
        with self.engine.begin() as connection:
            input_sql = text(f"{sql}")
            result = connection.execute(input_sql)
            if get_result is True:
                sql_result = []
                for row in result:
                    sql_result.append(list(row))
                return sql_result


# ポスグレに接続
con_psg = ConnectPostgreSQL(
    "postgres", "postgres", "localhost:5432", "hoge"
)
sql = "SELECT * FROM hogehoge"
result = con_psg.execute_sql(sql, get_result=True)
# リストで結果を返す
print(result)

>>> [[hoge1, hoge2], [hoge3, hoge4]...]
```
260. Single Number III の解き方メモ

https://leetcode.com/problems/single-number-iii/description/

# 問題概要

配列numsには、1回だけ出現する整数が2種類、残りはちょうど2回出現する。時間計算量O(N)、空間計算量O(1)という制約のもと、1回だけ出現する整数を求めなさい。

# 解き方メモ

`nums = [A, B, X, X, Y, Y]` とします。

まずnumsをすべてxorすると`A ^ B`となります。これをPとします。

```
P = A ^ B ^ X ^ X ^ Y ^ Y
  = A ^ B ^ (X ^ X) ^ (Y ^ Y)
  = A ^ B ^ 0 ^ 0
  = A ^ B
```

ここで「Aのビット目はiだが、Bのiビット目は0」というようなiに着目します。AとBは別の数字なので、そのようなiは必ず存在し、xorの性質上、Pのiビット目は1になります。

numsのうち、iビット目が1になるものを抽出し、それをすべてxorすると、その結果はAになります。たとえば、AとXのiビット目が1とすると

```
A ^ X ^ X = A ^ (X ^ X)
          = A ^ 0
          = A
```

`P = A ^ B` すなわち `B = P ^ A` のため、Aを求めることができれば、Bも求めることができます。

```rust
impl Solution {
    pub fn single_number(nums: Vec<i32>) -> Vec<i32> {
        let p = nums.iter().fold(0, |acc, num| acc ^ num);
        let i = (0..).find(|x| (p >> x) & 1 == 1).unwrap();
        let a = nums.iter().filter(|&num| (num >> i) & 1 == 1).fold(0, |acc, num| acc ^ num);
        let b = p ^ a;

        vec![a, b]
    }
}
```
AWSサーバーレスで問い合わせの仕組みを作る（APIGateway・DynamoDB）

AWSやらサーバーレスやら、これまでエアプで人に話してきた。
営業寄りの仕事だったからそれでよかった。八百屋はトマトの育て方を知らなくてもトマトを売れる。

でも、重い腰を上げてイチから作ることにした。
技術寄りのマネージャーを目指すことにしたからだ。

## つくるもの
- Webサイトの問い合わせフォームをデータベースに保存する
- フォームは名前とメールアドレス・問い合わせ内容のみ
- Webサーバーとか意識したくない。サーバーレスでつくる

へんに複雑にせず、シンプルに。
実務で使うならもっとごちゃごちゃとするが、学習のためには単純な仕組みを理解することから。

問い合わせ内容の一覧表示をしたくなるが、そちらは次回。

## 仕組み
フォーム送信時にAPIをコール。入力内容をDynamoDBに保存する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816528/e5aa78bd-c9e0-b234-5e3a-6854b56a2fb7.png)

APIGateway から直接 DynamoDB へデータ保存する。

## できたもの
一応、目的は達成できた。

問い合わせフォーム
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816528/7dbae244-f859-7454-e289-56d49acde8c0.png)

DynamoDBの保存結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816528/aafe573d-14a0-7193-06dd-1db017dd4157.png)

フロント部分はほぼChatGPTにお願いして作った。
自分で変更したのはAPIコールと若干のパラメータをいじっただけ。
大変に効率がよい。ただし、手ごたえがなく地力を身に着けた感じがしないのが悩みどころ。

## 悩んだ点
### とにかくAPIGatewayの設定がよく分からない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816528/9bff9a55-9351-2034-d24d-48259d04c57d.png)

「メソッド」「統合」「リクエスト」・・・。単語レベルでは意味が分かるが、これらがどんな役割なのか理解していないことが分かった。

さらに「マッピングテンプレート」という謎の機能で1時間悩んだ。
後述する参考記事など見ながら、何とか先に進んだ。（まだ充分な理解はしていない）

### デバッグ勘が働かない
テスト実行すると「データが保存されないなー」「エラーが出てるなー」となる。
まったく当たりが付かず、ちょこちょこと設定を変えながら実行を繰り返してみる。

あとから考えるとエラーログの内容をちゃんと見ればよかったのだが、
**エラーログ見る → エラーログでググる → 小難しい解説で思考停止**
のループだった。

結局「ダブルクォーテーションが全角だった」という問題に気づき、絶望的な気持ちになる。
こういう問題解決の経験が多く、勘が働くエンジニアは偉大だ。

## 発見など、まとめ

- VSCodeにDraw.ioの拡張機能があった
- エラーログをちゃんと読むことがデバッグの基本
- エンジニアは偉大

## 参考にした記事

https://qiita.com/foxtrackjp/items/e286b20943e99e230198

https://zenn.dev/amarelo_n24/articles/ab083b0358e902
Raspberry Pi 基本設定

# はじめに
<!-- 発端や概要を記載 -->
Raspberry piを久しぶりに使うにあたって、色々と必要なことがありましたので個人的な備忘録として投稿します。
他にも同じことが気になっている人の役に立てると嬉しいです。

# 日本語入力
日本語が入力することができなかったので、以下のコマンドを入力し、**Fcitx・Mozc**をインストールします。
Fcitxはキーボードの入力を様々な言語に切り替える機能を提供し、Mozcは日本語変換機能を提供するソフトです。この2つを組み合わせることで、WindowsやMacなどとほぼ同じ使い勝手で日本語の入力が可能になります。

~~~bash
sudo apt update
sudo apt install fcitx-mozc -y
~~~

再起動（Reboot）後に日本語入力ができるようになりました！
半角/全角のボタンで変換できますが、カタカナひらがな/ローマ字のボタンで変換できないのは残念・・・


参考文献

https://www.indoorcorgielec.com/resources/raspberry-pi/raspberry-pi-input-japanese/


<a id="#Chapter2"></a>
# スクリーンショットを撮る。
「printScreen」ボタンを押すだけで保存されます。
普段はMacユーザのため、何そのボタン！？、と驚きました笑

デフォルトでは、「/home/pi」に、日付-時間-サイズ-scrot_pngのフォーマットで保存されます。
![スクリーンショット 2024-06-16 1.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1776719/6a109c07-42b7-f86f-1c4f-e6eb1c951300.png)


これはラズパイにデフォルトで「scrot」というスクショを撮るアプリがインストールされているため使えます。

## 選択したウィンドウのみを撮る場合：
以下のコマンドを実行し，撮影したい画面を選択します．
~~~bash
scrot -sb
~~~

## 保存先を指定してスクショ
~~~bash
scrot /home/pi/Pictures/demo.png #保存したい階層を指定（今回はPicturesファイル）
~~~
今回は、picturesフォルダを指定し、demo.pngという名前で保存するようにしています。

毎回コマンド入力をするのは大変なのでデフォルトで設定できる方法をご存知の方がいましたら、ご教授願ます。

### ラズパイで撮影した写真を他のデバイスに共有
ラズパイで撮った写真を他のPC等に共有する方法は、同じグーグルアカウントにログインしてグーグルドライブにアップロードするか、Qiitaの記事に写真を載っけ、下書き保存したあとにMacでダウンロード&編集しています。
他にUSBメモリを使う方法などもありますが，効率の良い共有方法は人それぞれな気がします．（教えて）

# OSを調べる。
以下のコマンドを実行
~~~bash
lsb_release -a
~~~

出力の例↓
![スクリーンショット 2024-06-10 18.51.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1776719/5395b9d6-cd3c-4390-e7f9-c2624cbddf71.png)

つまり今回は，
OS：「Raspbian GNU/Linux 10 (buster)」
OSのコードネーム：「buster」（バスター）
だということがわかりました．

## 余談
ラズベリーパイのOSの名前は，トイストーリーのキャラクターから命名されているそうです．
今回のBusterはアンディ達が飼っていた犬の名前です．
最初はBuzzで始まり，最近のOSではトイストーリー4に出てきたforky（フォーキー）になる予定？だそうです．



参考文献：

https://plaza.rakuten.co.jp/amakaya/diary/202103060000/

https://raspida.com/raspbian-codename/

# ラズパイが固まった・反応しない時
~~~bash
Alt + SysRq(printScreen) + I #再起動

sudo shutdown -h now #shutdown（時々ボタンを押しても反応しないことがあったため）
~~~

# 終わりに
個人的な備忘録としてまとめましたが，参考になると嬉しいです．
最後までお読み頂き，ありがとうございます．
【Next.js】middleware.tsのfetch failedについて

# はじめに
Next.jsにはmiddlewareを簡単に設置することができる。決められた場所に「middleware.ts」または「middleware.js」を作成して実行したい処理を記述するだけで簡単にmiddlewareを走らせることができる。が、そのmiddlewareファイルでAPI通信を走らせたい場合にfetchを利用したが、実行できず「fetch failed」エラーが出た。これを解決するのに恥ずかしながら結構時間を費やしてしまったため、備忘録として書き留めておく。

※環境はDockerを使用しているのでDockerでの解決方法

# 環境
+ Docker
+ node.js v20
+ Next.js v14

# 前提
Next.jsのアプリケーション内では「axios」を使用している。middlewareファイルではaxiosが動作しないため、fetchを使用してAPIを走らせるところまでは辿り着いた。だがそのfetchも動かなかった。。
原因は
+ そのAPIのURLは間違っている
+ localhostに拒否されている
+ 127.0.0.1に拒否されている
+ ネットワークエラー系

みたいな意味合いのfetch failedだった。

# 解決方法
解決方法は至ってシンプルだった。
fetchのURLをコンテナ名とポート番号を指定してあげるだけだった。
```diff_javascript
- fetch("http://localhost/api/v1/check")
+ fetch("http://nginx:80/api/v1/check")
```

この場合は

+ コンテナ名 : nginx
+ ポート番号 : 80

となる。
# 終わりに
いや〜だいぶハマった・・・
Seed7 で Welcome to AtCoder を解いてみた

[Qiita Engineer Festa 2024（キータ・エンジニア・フェスタ 2024） - Qiita](https://qiita.com/official-campaigns/engineer-festa/2024)
において、約1ヶ月で38記事という大量の記事の投稿を要求されることがわかった。
そこで、あまりコストをかけずに記事数を稼ぐ方法を考えた結果、「Welcome to AtCoder を様々な言語で解く」ことを思いついた。
単に解くだけでなく、使用する言語仕様の解説を入れれば、記事として一応成立するだろう。

# Welcome to AtCoder

[PracticeA - Welcome to AtCoder](https://atcoder.jp/contests/abs/tasks/practice_1)

Welcome to AtCoder では、以下の形式で整数 $a$, $b$, $c$ および文字列 $s$ が入力として与えられる。

```text
a
b c
s
```

この入力をもとに、与えられた整数の和 $sum = a + b + c$ および文字列 $s$ を、以下の形式で出力することが求められる。

```text
sum s
```

# 今回用いる Seed7 の機能

[Seed7 Homepage](https://seed7.sourceforge.net/)
[Seed7 Manual](https://seed7.sourceforge.net/manual/index.htm)
[Seed7 Manual: Tutorial](https://seed7.sourceforge.net/manual/tutorial.htm)
[Seed7 Manual: Declarations](https://seed7.sourceforge.net/manual/decls.htm)
[Seed7 Library: Stdio](https://seed7.sourceforge.net/libraries/stdio.htm)
[Seed7 Library: Integer](https://seed7.sourceforge.net/libraries/integer.htm)

## 標準ライブラリの取り込み

以下をプログラムの最初に書くことで、標準ライブラリの宣言を取り込むことができる。

```
$ include "seed7_05.s7i";
```

## 関数定義

以下の形式で、関数の定義を行うことができる。
`seed7_05.s7i` において、`main` 関数がエントリポイントとして指定される。

```
const proc: 関数名 is func
  local
    変数宣言
  begin
    処理内容
  end func;
```

ただし、変数を用いない場合は `local` も書かない。

変数宣言は、以下の形式で行うことができる。

```
var 型名: 変数名 is 初期値;
```

型は、整数を表す `integer` や文字列を表す `string` などがある。

## 変数への代入

以下の形式で、変数に値を代入することができる。

```
変数名 := 値;
```

## 文字列の入力

以下のように `read` 関数を用いると、標準入力から空白・タブ・改行で区切られた1単位を読み込むことができる。

```
read(読み込んだ文字列を格納する変数);
```

以下のように `readln` 関数を用いると、標準入力から1行を読み込むことができる。

```
readln(読み込んだ文字列を格納する変数);
```

## データの出力

以下のように `writeln` 関数を用いると、標準出力にデータを出力し、さらに改行をすることができる。

```
wrlteln(出力するデータ);
```

データを `<&` で区切ることで、複数のデータを出力できる。

```
wrlteln(データ1 <& データ2);
```

## 文字列の数値への変換

以下のように `parse` 関数を用いると、文字列を整数に変換できる。
(これは式の中で用いる)

```
integer parse(変換する文字列)
```

# 提出コード

```
$ include "seed7_05.s7i";

const proc: main is func
  local
    var string: a is "";
    var string: b is "";
    var string: c is "";
    var string: s is "";
    var integer: sum is 0;
  begin
    read(a);
    read(b);
    read(c);
    readln(s);
    sum := integer parse(a) + integer parse(b) + integer parse(c);
    writeln(sum <& " " <& s);
  end func;
```

[提出 #54619991 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/54619991)
UbuntuでHomebrewをインストールする

# はじめに
Ubuntu環境でHomebrewをインストールする方法を作成します。


# 環境
Ubuntu 22.04 LTS

# Homebrewインストール
Homebrewのインストール手順は以下のようになります。
1. コマンドを実行してHomebrewをインストール
2. 追加コマンドを実行
3. Homebrewの実行を確認

## コマンドを実行してHomebrewをインストール
Homebrewの公式サイトにインストールのコマンドが書いています。
そのコマンドをターミナルで入力して実行します。

https://brew.sh/

公式で書いているコマンドは以下のようになっています。
```console
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

## 追加コマンドを実行
インストールが完了すると、以下のようなメッセージが表示されます。
「Next steps」の部分のコマンドを実行します。

:::note warn
`{ユーザー名}`の部分には、自分のユーザー名が入っています。
:::
```console
==> Installation successful!

==> Homebrew has enabled anonymous aggregate formulae and cask analytics.
Read the analytics documentation (and how to opt-out) here:
  https://docs.brew.sh/Analytics
No analytics data has been sent yet (nor will any be during this install run).

==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations

==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    (echo; echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"') >> /home/{ユーザー名}/.bashrc
    eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
- Install Homebrew's dependencies if you have sudo access:
    sudo apt-get install build-essential
  For more information, see:
    https://docs.brew.sh/Homebrew-on-Linux
- We recommend that you install GCC:
    brew install gcc
- Run brew help to get started
- Further documentation:
    https://docs.brew.sh
```

## Homebrewの実行を確認
Homebrewが実行できるか確認します。
```console
$ brew --version
Homebrew 4.3.5
```
オブジェクト型を支えるlookup型とkeyof型

:::note
本記事はZennに投稿している記事に加筆したものになります。
https://zenn.dev/axoloto210/articles/advent-calender-2023-day17
:::

オブジェクトはプロパティの型やオブジェクト自身の型など、複数の型が組み合わさってできていますが、このオブジェクト型を扱いやすくする機能として、`lookup`型と`keyof`型があります。
## `lookup`型
`lookup`型は主にオブジェクトのプロパティの型を得るために使用されます。オブジェクトの型`T`とオブジェクトのキーの型`K`を用いて`T[K]`のように記述します。
```ts
type Obj = {
    num: number
    str: string
}

//type T = number
type T = Obj['num']
```
`lookup`型を使用することで、`Obj`型のプロパティの型を変更するときに変更箇所の数を抑えられる利点がある一方で、型情報を知りたい場合には元のオブジェクト型を参照する必要が出てくることには注意が必要です。

また、あまり使い道はないように思いますが、`lookup`型は`123`などのリテラル型や`string`などのプリミティブ型に適用することも可能です。
その場合には`Number`型や`String`型などのラッパーオブジェクトがもつインスタンスメソッドなど、リテラル型やプリミティブ型の値でもアクセス可能なプロパティのキー文字列を渡すことで型情報を取得することができます。
```ts
//type U = () => string
type U = '123'['toString'] 

//type V = (radix?: number | undefined) => string
type V = 123['toString']
```

どのプロパティにアクセスできるかは、次に紹介する`keyof`型を使用して調べることもできます。
```ts
//type W = "toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"
type W = keyof 123
```
## `keyof`型
`keyof`型はオブジェクト型からプロパティ名のキー文字列を（複数の時はユニオン型で）取得できる機能です。
```ts
type Obj = {
    num: number
    str: string
}

type T = keyof Obj

const key: T = 'num'
const key2: T = 'str'
const key3: T = 'foo' //Type '"foo"' is not assignable to type 'keyof Obj'.(2322)
```
上のコード例では`Obj`型のプロパティ名のユニオン型である`'num' | 'str'`に適合しない値を代入しようとしてコンパイルエラーが発生しています。

この`keyof`は型に対して使用できる演算子であり、オブジェクトリテラルなどの値には直接適用することができません。
しかし、`typeof`型演算子を併せて利用することでオブジェクトリテラルのプロパティ名の型情報を取得することが可能になります。
```ts
const obj = {
    num: 123,
    str: 'one-two-three'
}

//type T = "num" | "str"
type T = keyof typeof obj
```

## `lookup`と`keyof`を組み合わせる
`lookup`型と`keyof`型を併用することで、オブジェクトからプロパティを取得したり、プロパティに値を設定する関数の方を記述しやすくなります。
```ts
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
  obj[key] = value
}

const obj = {
    num: 123,
    str: 'one-two-three'
}

console.log(getProperty(obj,'num'))//123 
setProperty(obj, 'num', 321)
console.log(getProperty(obj,'num'))//321 


//Argument of type '"foo"' is not assignable to parameter of type '"num" | "str"'.(2345)
setProperty(obj, 'foo', true)

```
`getProperty`は2つの引数`obj`と`key`を受け取りますが、`K extends keyof T`によって、`key`の型は`obj`のプロパティ名（のユニオン型）の部分型でなければならないという制約が課されています。
この制約のおかげで、オブジェクトに存在しないプロパティを取得しようとしていた場合にはコンパイルエラーが発生して、記述の誤りを検知してもらえるわけですね。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
UnityプロジェクトをGithubで管理する

# はじめに

最近PCの容量が圧迫されているので，過去に作成していたUnityプロジェクトをGithubに保存しておこうと思いました．
過去作成したものをとりあえず保存さえできればいいと思っているので`git clone`して再び編集することは考慮していません．（git cloneしたプロジェクトを編集できるかまだ試していない状態です．）

Unityプロジェクトを例に挙げていますが，Unity以外でも以下の方法でgit管理し始めることは可能だと思います．

# やったこと

まずはじめに管理用のリポジトリを作成します．
使用しているアセットを公開して問題ないかアセットページを確認しに行くことは大変なので，私はPrivateリポジトリへ保存することにしました．
リポジトリの作成が終われば，あとはコマンドを実行していくだけです．

Unityプロジェクトがある階層で以下のコマンドを実行します．
```bash
git init
```

次に以下のコマンドでリモートのリポジトリ（最初に作成したリポジトリ）への接続を可能にします．

```bash
git remote add origin https://github.com/Githubユーザー名/リポジトリ名.git
```

このままだとgitで管理する必要のないファイルまでpushすることになるので，`.gitignore`を作成しましょう．
以下，Githubでリポジトリ作成時，`Add .gitignore`の項目にUnityを選択した場合の`.gitignore`ファイルです．

```.gitignore(for Unity)
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/

# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
/[Mm]emoryCaptures/

# Recordings can get excessive in size
/[Rr]ecordings/

# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*

# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta

# Unity3D generated file on crash reports
sysinfo.txt

# Builds
*.apk
*.aab
*.unitypackage
*.app

# Crashlytics generated file
crashlytics-build.properties

# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*

# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*
```

あとはいつも通り，`git add`, `git commit`を実行すればよいです．
pushするときには，上流ブランチを紐づける必要があるので，以下を実行します．
```bash
git push --set-upstream origin master
```

以上でGithubにおいて既存Unityプロジェクトを管理できるようになりました．
macでのssh接続


最初は~/.ssh ディレクトリや ~/.ssh/config がありませんので作成します。
動画したに記載したコマンドをterminalに貼り付けてEnterを押して実行します。
コマンドは１行ずつコピー&ペーストして実行してください。

```
mkdir ~/.ssh
touch ~/.ssh/config
```

.shhフォルダは隠しフォルダになっていて見えないためターミナルを使ってファイルを移動します。
動画下に記載した以下のコマンドをターミナルに貼り付けてEnterを押して実行します。
```
mv ~/private_key.txt ~/.ssh/private_key.txt
```


今、.sshフォルダにはconfigファイルとprivate_key.txtファイルがあります。
.sshフォルダと２つのファイルのパーミッションを書き換えます。
動画下に記載した以下のコマンドをターミナルに貼り付けてEnterを押して実行します。
コマンドは１行ずつ貼り付けて実行してください。

```
sudo chown -R $(whoami):staff ~/.ssh
sudo chmod 700 ~/.ssh
sudo chmod -R 600 ~/.ssh/config
sudo chmod -R 600 ~/.ssh/private_key.txt
```


Terminalに動画下に記載した以下のコマンド貼り付け実行します。
```
vi ~/.ssh/config
```
基本知識①MVCモデルとは

## はじめに
転職活動をする中で、MVCそれぞれの役割やhttp通信についてなど、基礎的な技術知識について問われるシーンがあったので、改めて基本に立ち返って自己学習しようと思った。

## MVCについて
### 「MVCモデル」とは
システム開発の方針の一つ。
「Model」「View」「Controller」の3つに役割を分担させコードを管理する。

#### なぜ分けるのか？
1. 保守性の向上
コードを役割ごとに分けることで、システムにバグが起こった時、バグ発生箇所を特定しやすい。
また、例えばViewでバグがあったとして、ControllerやModelに影響が少なく、影響範囲を小規模で止めることができる。

2. 生産性の向上
コードが役割ごとに独立しているため、管理がしやすい。
分担作業がしやすい。

### Modelとは
**表示や入力に関連しない処理**
DBとのやりとりを担当。
データの登録・更新・削除の処理を担う。
処理したデータはControllerに送る。

### Viewとは
**表示や入力に関する処理**
HTMLなど、ユーザーが実際目にするページの表示を担う。
ページ遷移のリクエストデータをControllerに送ったり、
Controllerからレスポンスを受け取り、画面に表示したりする。

### Controllerとは
**ModelとViewの橋渡し役**
ModelとViewの制御、仲介役を担う。
Viewから受け取ったデータをModelに渡し、Modelで処理されたデータをViewに渡すなど

## 参考にさせていただいた記事
https://wa3.i-3-i.info/word11584.html
【Flutter】flip_cardパッケージを使って画像付きの回転カードを実装する

# はじめに
本記事では、`flip_card` パッケージを使用し、表面と裏面にそれぞれ画像を指定したカードを回転させる方法について記載します。


# 作るものイメージ

![flipima.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/9df3d680-9757-82cc-3e1c-c7d85c4c4e82.gif)


# 環境
- Flutter 3.22.1
- flip_card: 0.7.0
- vscode


# パッケージのインストール
次のコマンドでflip_card パッケージをインストール。
```
flutter pub add flip_card
```

https://pub.dev/packages/flip_card/install


# カードに表示させる画像の準備
`assets` ディレクトリに表示したい画像（例: FEimg.png と BEimg.png）を配置してください。
配置後に`pubspec.yaml` ファイルに画像のパスを追加します。

```yaml:pubspec.yaml
# ... 他の設定は省略 ...
flutter:
  # ... 他の設定は省略 ...

  assets:
    - assets/FEimg.png
    - assets/BEimg.png
    - 
```
次のコマンドを実施します。
```
flutter pub get
```

# ソース

表面（front）と裏面（back）にそれぞれ別々の画像を指定し、水平方向に切り替わるカードを作成します。

```dart:main.dart
import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('サンプル例')),
        body: Center(
          child: FlipCard(
            direction: FlipDirection.HORIZONTAL, // FlipCardの方向を水平に設定
            front: Container(
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(15.0),
                image: const DecorationImage(
                  image: AssetImage('assets/FEimg.png'), // カードの表面に表示する画像を設定
                  fit: BoxFit.cover, // 画像をカード全体に合わせて表示
                ),
              ),
              width: 300,
              height: 200,
            ),
            back: Container(
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(15.0),
                image: const DecorationImage(
                  image: AssetImage('assets/BEimg.png'), // カードの裏面に表示する画像を設定
                  fit: BoxFit.cover, // 画像をカード全体に合わせて表示
                ),
              ),
              width: 300,
              height: 200,
            ),
          ),
        ),
      ),
    );
  }
}
```

# 実行結果
デバッグして確認すると、次のgifのように画像付きのカードを表裏切り替えることができました。

![flipima.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/9df3d680-9757-82cc-3e1c-c7d85c4c4e82.gif)


# 参考

https://pub.dev/packages/flip_card
Professional Cloud Network Engineerに合格した

Google Cloudの認定資格であるProfessional Cloud Network Engineerに挑戦し、無事合格できたのでその体験記を書きます。  
ネットワーク周りは業務経験も薄めなのでハードルは高めでしたがなんとか合格できたという感じ。

## Professional Cloud Network Engineerについて
https://cloud.google.com/learn/certification/cloud-network-engineer?hl=ja

## 筆者について
- 社会人11年目くらいのSIer勤務
- ネットワーク周りをいじる業務経験はほぼなし
- Google Cloudはそれなりに使っている

## 受験のきっかけ
ネットワーク周りの経験がほぼないというのが実はそれなりにコンプレックスであり、とりあえず知識だけでもつけるかというのがモチベーションでした。
IPAのネットワークスペシャリストを数年前に取得していましたが、業務で使わないとほとんど忘れてしまっていて、その辺の知識を掘り起こすことも目的の一つではありました。
まさに「資格だけ持っていてもしょうがない」の典型ですが、とはいえ「知識もないよりはマシ」だと考えて今回チャレンジしました。

## 勉強方法
ネットワーク周りはほぼ触ったことがないので、とりあえず公式の模擬試験で出題傾向と自分のわかっていないところを把握しました。  
結果としてはほぼ何もわからんということと、Interconnect周りの問題も出るようだということを理解しました。  

次に、公式のトレーニングであるGoogle Cloud Skills BoostのNetwork周りのものをさらりと流しました。
特にInterconnectは個人で試せるようなものではなかなかないので、ここで設定方法などを把握しました。

ここまでがとりあえずのinputで、あとはUdemyで模擬試験を繰り返しこなしました。
inputで"なんとなく"理解したと思っていても、模擬試験では具体的な要件からどのような方式を選ぶかが問われ、なかなか正解ができず。
解説を読んで、公式ドキュメントを読んで、少しずつ理解を進めました。

また、そもそも用語がわからん、公式ドキュメント読んでもわからん、というときにはChatGPTに頼りました。
たとえば「Google Cloudにおけるロードバランサの種類・特徴・代表的な用途について、表形式でまとめて」など。
「10歳の子供にわかるように教えて」というと平易な言葉で例を交えながら教えてくれるので、そこをとっかかりとして理解を深めていきました。

## 試験
リモートで受験しました。
WEBカメラとPCがあれば、あとは部屋を片付けていれば気軽に受けられるので便利。
夜中23時くらいに受験しました。

## まとめ
ちょっとだけ自信がついた。それだけでも資格試験を受ける価値はある....と思います。
[Dify]MultiQueryRetrieverを作成してみた！

## はじめに

今回はMultiQueryRetrieverを作成してみました。
LangChainのドキュメントに実装が記載されています。ここが出典なのかは正直わからないです。
https://python.langchain.com/v0.1/docs/modules/data_connection/retrievers/MultiQueryRetriever/

ではまずMultiQueryRetrieverとは何かから解説していきます。

## MultiQueryRetrieverとは？
MultiQueryRetriever結構便利なんですよね。
普通のベクトル検索だとクエリの表現が少しでも変わったり、埋め込みがデータの意味をうまく捉えていなかったりすると、検索結果がガラッと変わってしまうんですよね。
これを手動で何とかしようとすると、プロンプトエンジニアリングやチューニングなんて面倒な作業が待っています。

MultiQueryRetrieverはユーザ入力クエリに対して色々な角度からクエリを再度生成し、各クエリに対して関連ドキュメントを取得し、それらを組み合わせることで、より幅広く関連する可能性のあるドキュメントを見つけ出すことができます。
簡単にプロンプトチューニングを自動化してくれるみたいなもんですね。

流れでいうと
1. 質問からLLMに別視点の質問を生成させる
1. 各質問からベクトル検索でコンテキストを取得する
1. 元質問と、各質問のベクトル検索で得られたコンテキストを用いてLLMに回答させる

これらをイメージ図に落とすと以下のような感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/92ac5946-9ba2-a029-ea47-a7ca11d0c2b2.png)

### 質問から生成した質問の例
イメージがつきやすいように質問から生成した質問の例を一つ載せておきます。
- 質問：ファインチューニングとは？
- 生成された質問：
    - 事前学習済みモデルのファインチューニングとは？
    - ファインチューニングの手順と注意点
    - 転移学習におけるファインチューニングの役割
    - ファインチューニングとスクラッチ学習の違い
    - ファインチューニングの成功事例と応用分野


## 全体像
では早速Difyで構築していきましょうか。
全体像はこんな感じです。
生成した質問をIterationを回してベクトル検索しています。
並列にベクトル検索できないのが残念ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/b5fb0903-d706-dad0-9527-aa849aab5147.png)

では個々のノードを解説していきます。
## 質問生成ノード
質問生成ノードでは質問から別視点の質問を生成します。
プロンプトはLangChainのドキュメントで使われているプロンプトを使用します。

#### プロンプト
```prompt
You are an AI language model assistant. 
Your task is to generate five different versions of the given user question to retrieve relevant documents from a vector database. 
By generating multiple perspectives on the user question, your goal is to help the user overcome some of the limitations of the distance-based similarity search. 
Provide these alternative questions separated by newlines.
Original question: {{#sys.query#}}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/e0670249-1766-9897-6364-37e113485be6.png)

## 質問抽出ノード
質問生成ノードから改行区切りで質問が渡されるので質問を抽出しましょう。
今回はLLMで実行していますが、コードを使用した方が確実です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/aee35580-8dfd-5095-8c9c-5469e33633b6.png)

## 知識取得 & 集約ノード
生成した質問はIterationを回してベクトル検索します。
生成が終わったら結果を全てまとめておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/bd0cf4de-e75c-3936-4e60-b5b362d2d308.png)

## 回答ノード
元質問と、各質問のベクトル検索で得られたコンテキストを用いてLLMに回答させる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/b86a461c-3693-6600-68cc-49f9c1cf1acf.png)

出力はみなさん試してみてください！結構いい感じに回答されます。

## 最後に
Xやってるので気になる方はフォローお願いします。
https://x.com/hudebakonosoto
PCの歴史と操作の変容３

# BASIC全盛期からの脱却
パソコンの普及とともに普及したのがマイクロソフトのBASICですが、パソコンメーカーにより少しづつ違いがありF社のPCで開発したBASICプログラムはN社のPCでは動かない。
等のBASICの方言という問題がありました。

それを解決したのがCP/MやMS-DOSというOSのです。
CP/MやMS-DOSのC言語やBASICで書かれたプログラムは同じOSが動作すればハードに関わらず動くようになってきました。

# DOSって何？
DOSはディスクOSの略で、CP/MやMS-DOSがディスクOSに該当します。
ディスクは、今はもうほとんど使われることがなくなったフロッピーディスクを指しています。
操作は、コマンドインタープリタ(シェルのようなもの)からコマンドを打ち込んで実行する。
BASICインタープリタとは異なり、色んなコンパイラやインタープリタが使えます。

フロッピーディスクの登場は、オーディオテープに記録していた頃に比べると高速に大きなデータの交換を可能にしたことがPCに発展に大きく関与しています。

# マウスの普及と画面の大型化
また、1984年辺りにはフロッピー搭載のPC多くなった事と8Bitから16BitCPUへの以降が進み処理が早くなった事、さらにマウスをしようするプログラムも増えCAD等も普及し始めてきました。

[前の記事](https://qiita.com/kawamo55/items/ac6c30bc789f3ddc5954)
INDEXMOV2024

https://www.imdb.com/list/ls547490072

https://www.imdb.com/list/ls547490022

https://www.imdb.com/list/ls547490507

https://www.imdb.com/list/ls547490513

https://www.imdb.com/list/ls547490353

https://www.imdb.com/list/ls547490334

https://www.imdb.com/list/ls547490349

https://www.imdb.com/list/ls547490654

https://www.imdb.com/list/ls547490483

https://www.imdb.com/list/ls547490916

https://www.imdb.com/list/ls547490962

https://www.imdb.com/list/ls547490943

https://heylink.me/greg525/
https://mez.ink/gregrivera03

https://linkr.bio/gregrivera33

https://linki.ee/gregrivera33

https://magic.ly/gregrivera33

https://bento.me/gregrivera33

https://start.me/w/brkjm1

https://www.artstation.com/gregrivera1/profile

https://muckrack.com/greg-rivera-4/bio

https://www.bitsdujour.com/profiles/fqYIRf

http://aldenfamilydentistry.com/UserProfile/tabid/57/userId/805644/Default.aspx
よく使うGitコマンド集

## はじめに
GitやGitHubはソフト開発現場で当たり前のように使われています。
ただ操作方法を忘れてしまうことも少なくありません。
毎回調べる手間を省けるように、よく使うGitコマンドをまとめます。

## ブランチを切ってコミットプッシュしてプルリクを送る

### 1. ローカルリポジトリの操作
`git branch`で現在のブランチを表示します。
```
git branch
```

`git checkout -b`でブランチを切ります。
`git checkout`と`git branch`を同時に行えます。

```
git checkout -b feature/a-001
```

`git add`して`git commit`してリモートリポジトリに`git push`します。

```
git add components/*
git commit -m '◯◯◯のために△△△'
git push origin feature/a-001
```

### 2. GitHub上の操作

GitHubリポジトリの`Pull request`をクリックします。

`base:ブランチ`と`compare:ブランチ`のブランチを選択して、`Create pull request`をクリックします。

`Title`と`description`を入力して`Create pull request`をクリックします。

以上で完了になります。

## ローカルブランチとリモートブランチを消す

`git branch`の`-d`でローカルブランチを消せます。

```
git branch -d hotfix/20240615
```

`git push` の`--detele`でリモートブランチを消せます。

```
git push --delete origin hotfix/20240615
```

## リモートからmain以外のブランチをチェックアウト

`origin/develop`を指定するとリモートの`develop`がチェックアウトされます。

```
git checkout develop origin/develop
```

リモートの`develop`が取得されない場合は`fetch`してから`checkout`します。

```
git fetch origin develop
git checkout develop
```

## コミットのログを調べる

`--oneline`は1行でログ出力します。

```bash
$ git log --oneline
843b95d (HEAD -> main) new article
a12a105 (origin/main) Initial commit
```

`--merges`でマージコミットのみ表示します。

```
$ git log --merges
```


`--no-merges`でマージコミットを除いて表示します。

```bash
$ git log --no-merges
```

`--author`でユーザーを絞れます。

```
$ git log --author="Daichi Sugiyama"
```

## 複数のコミットを１つのコミットにまとめる

### 1. リベースの実行

`git rebase`の`-i`にコミットIDを指定します。
`HEAD`でも指定できます。

```bash
$ git rebase -i HEAD^2 
```

ただし最初のコミットは`-i`では指定できないため`--root`を追加します。

```bash
$ git rebase -i HEAD^2
fatal: invalid upstream 'HEAD^2'
```

```bash
$ git rebase -i --root
```

### 2. コミットの編集

コミットを編集できるエディタが開きます。

```bash
pick a12a105 Initial commit
pick 843b95d New article
```

まとめるコミットの`pick`を`squash`（`s`）に変えます。
編集が終わったら`:wq`で閉じます。

```bash
pick a12a105 Initial commit
s 843b95d New article
```

### 3. コミットメッセージの編集

コミットメッセージを編集できるエディタが開きます。

```bash
# This is a combination of 2 commits.
# This is the 1st commit message:

Initial commit

# This is the commit message #2:

New article
```

コミットメッセージを入力します。
編集が終わったら`:wq`で閉じます。
```bash
Initial commit
```

以上で完了になります。

### a. 元に戻す

操作を誤った場合は`git rebase --abort`で元に戻せます。

```
git rebase --abort
```


## リモートのコミットを全て消してプッシュ

`--orphan`を指定してコミットを引き継がない`tmpブランチ`を切ります。

```
git checkout --orphan tmp
```

`add`して`commit`します。

```
git add .
git commit -m "Init"
```

`main`ブランチを切って元の`tmp`ブランチは消します。

```
git checkout -B main
git branch -d tmp
```

`git push`の`-f`で強制的にプッシュします。

```
git push origin main -f
```

## ブランチの差分を見てマージ

現在のブランチと`develop`ブランチの差分を表示できます。

```
git diff develop
```

現在のブランチに`develop`ブランチをマージします。

```
git merge develop
```

## バージョンタグを付けてプッシュしてリリースを作る

`git tag`でタグを作れます。
```
git tag -a v1.0.1 -m 'version 1.0.1'
```

コミットを指定した形でもタグを作れます。

```
git tag -a v1.0.0 a8b8aa -m 'version 1.0.0'
```

リモートに反映するには、コミットと同じようにプッシュします。

```
git push origin v1.0.0
```

`--tags`で全てのタグがプッシュされます。

```
git push origin --tags
```

`-d`でタグを削除できます
```
git tag -d v1.0.0
```

## おわりに

よく使うGitコマンドをまとめました。
今後も頻繁に使うコマンドや新たな情報があれば随時更新する予定です。
皆さんの開発業務に少しでもプラスになることを願っています。
【VSCode】エディタを滑らかにスクロールさせる方法

`settings.json`に以下の記述を追記するとエディタが滑らかにスクロールするようになります。

```jsonc:settings.json
"editor.smoothScrolling": true
```

リストやターミナルも滑らかにスクロールするよう設定できます。

![スクリーンショット 2024-06-15 23.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/8eb307f1-925a-845b-7286-048c095baecc.png)

```jsonc:settings.json
{
  "workbench.list.smoothScrolling": true,
  "terminal.integrated.smoothScrolling": true
}
```
[Azure]AI-900合格体験記

# はじめに
流行りの生成 AI を使いこなしたい！という想いで AI-900 を勉強し始めました。


# 前提
以下は持っています。
* SAA ([AWS Certified Solutions Architect - Associate](https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/))
* SAP ([AWS Certified Solutions Architect - Professional](https://aws.amazon.com/jp/certification/certified-solutions-architect-professional/))
* Azure Fundamentals ([AZ-900](https://learn.microsoft.com/ja-jp/credentials/certifications/exams/az-900/))
* Azure Administrator Associate ([AZ-104](https://learn.microsoft.com/ja-jp/credentials/certifications/azure-administrator/?practice-assessment-type=certification))


# AI-900 とは
詳細は飛ばします。ありふれているので。一応リンクだけ載せておきます。

https://learn.microsoft.com/ja-jp/credentials/certifications/azure-ai-fundamentals/?practice-assessment-type=certification

受かると `Azure AI Fundamentals` の認定資格を得ることができます。
※ 認定資格と認定試験(今回の場合は AZ-900) があって、認定試験に合格すると認定資格が得られるようです
※ ほとんど 1 対 1 で対応してますが、複数試験に合格しないと認定されない資格もあります


# 対策

## LinkedIn Learning
最初は動画 1 本見れば受かるかなと甘く見ていたのですが、意外と細かいことを問われます。初心者の私は気づいたら 4 本見ていました。計 4h 46m です流石にこれだけ見れば十分でした。

* Microsoft Azure AI Fundamentals（AI-900）試験対策：AIの基本と試験概要 54 m 

https://jp.linkedin.com/learning/microsoft-azure-ai-fundamentals-ai-900-ai-fundamentals-and-exam-information/4203145?autoplay=true&trk=course_preview&upsellOrderOrigin=default_guest_learning

* Microsoft Azure AI Fundamentals（AI-900）試験対策：機械学習の基本原則　1h 17m

https://jp.linkedin.com/learning/microsoft-azure-ai-fundamentals-ai-900-machine-learning-fundamentals?trk=embed_lil

* Microsoft Azure AI Fundamentals（AI-900）試験対策：自然言語処理 (NLP) 1h 28m

https://jp.linkedin.com/learning/microsoft-azure-ai-fundamentals-ai-900-natural-language-processing-nlp

* Microsoft Azure AI Fundamentals（AI-900）試験対策：Computer Vision 1h 7m

https://jp.linkedin.com/learning/microsoft-azure-ai-fundamentals-ai-900-computer-vision

## プラクティス評価
いわゆる模擬試験があります。無料なので絶対受けておくべきです。

https://learn.microsoft.com/ja-jp/credentials/certifications/azure-ai-fundamentals/practice/assessment?assessment-type=practice&assessmentId=26&practice-assessment-type=certification


# 感想
結果は 800 点越えで余裕に見えましたが、正直難しかったです。
生成 AI を使いこなすために向けた、即効性の効果があるものではないですが、 
「AI とは」から学べるので、取得してよかったと思っています。

ここで得た知識を活かして、生成 AI を活用していきます。


# 次の資格
AZ-305 -> DP-900 -> AZ-700 かなぁ。
AI 900 挟んだし、そろそろ 305 始めてみようかなと思っています。
おすすめの進め方あったら教えてください。
また合格したら体験記書きます。早く体験記の需要がある試験に受かりたい！

# おわりに
最後まで見ていただき、ありがとうございます。
よかったらチャンネル登録（フォロー）、高評価（いいね:heart_decoration:）、コメント:pen_fountain:などなど何でもお願いします:pray:

週一で投稿目指しています。もし何かリアクションをしてくれるとやる気が出るので、次週は投稿することを約束します。(震える小声)
今更Github Actionのすごさを知った話

最近、AWSの勉強をしていたり、いろんなサブスクを見直したりしている中、ふとGithubを見ているとGithub Actionというものをみつけました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/c11acb69-3730-133a-6336-30cff021eae6.png)
正直、Githubの機能を使いこなせていないこともあり、気になったので調べてみました！

# Github Actionとは？
これだけでいろいろできるすごいやつです！
具体的には
- リポジトリ上のものを自動でテストすることができる
- 様々な人が多くのアクションを公開してくれている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273072/3e4ddd67-9967-5c3c-d9fb-09e8f15c0f6a.png)
- AWSやDockerなど、主流のものと組み合わせることができる
- コードチェックができる

などなど、様々なことができます！
すべて書ききることができてないので詳しくはこちらを参照に...！
(GitHub Actions を理解する)[https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions]

これから、AWSの学習を進めるにあたり、S3とGithubを連携させたり、ゆくゆくはDocker + Github + AWS EC2みたいなことができるようにしていきます。
【Python】条件分岐文(if文)

Pythonの`if`文は条件によってコードを実行するかどうかを決定するために使用されます。基本的な構文は次のとおりです：
```python
if 条件:
    実行するコード
```
条件が真（True）の場合、`if`の下にあるインデントされたコードが実行されます。条件が偽（False）の場合、そのコードはスキップされます。
# 1. 基本的な`if`文
以下の例では、変数`x`が10以上の場合に「`x is 10 or greater`」を出力します。
```python
x = 15

if x >= 10:
    print("x is 10 or greater")
```
# 2. `if`と`else`
条件が満たされなかった場合に別のコードを実行するには、`else`を使用します。
```python
x = 5

if x >= 10:
    print("x is 10 or greater")
else:
    print("x is less than 10")
```
# 3. `if`、`elif`、`else`
複数の条件をチェックする場合は、`elif`（"else if"の略）を使います。
```python
x = 7

if x > 10:
    print("x is greater than 10")
elif x == 10:
    print("x is exactly 10")
else:
    print("x is less than 10")
```
# 4. 入れ子の`if`文
`if`文の中に`if`文を入れることもできます。
```python
x = 12
y = 8

if x > 10:
    print("x is greater than 10")
    if y < 10:
        print("y is less than 10")
```
# 5. 条件の組み合わせ
複数の条件を組み合わせてチェックすることも可能です。
```python
x = 7

if x > 5 and x < 10:
    print("x is between 5 and 10")
```
# 6. 条件の否定
条件が満たされない場合をチェックするには`not`を使います。
```python
x = 7

if not x > 10:
    print("x is not greater than 10")
```
# 実行例
以下のコードを実行してみて、どのように動作するかを確認してください。
```python
age = 20

if age < 18:
    print("You are a minor.")
elif age < 65:
    print("You are an adult.")
else:
    print("You are a senior citizen.")
```
このコードでは、`age`に応じて異なるメッセージが出力されます。`age`が18未満の場合は「未成年」、18以上65未満の場合は「大人」、65以上の場合は「高齢者」と表示されます。

`if`文は非常に強力で、条件に基づいてプログラムの流れを制御するために広く使われています。基本を理解したら、複雑な条件や入れ子の構造などにも挑戦してみてください。
######
参考)　[東京工業大学情報理工学院 Python早見表](https://chokkan.github.io/python/index.html)
【AWS】AWS 12冠が全冠目指して受けるData Engineer - Associate試験

# 概要
2022年に頑張ってAWS全冠達成していたのですが、
今年の4月から公開された[Data Engineer - Associate](https://aws.amazon.com/jp/certification/certified-data-engineer-associate/)試験によって全冠ではなく１２冠になってしまっていたので、そろそろと思い、全冠目指して受けてきました。
(AWS Summit行く予定なので、[クッキー欲しくて。。。](https://aws.amazon.com/jp/summits/japan/expo/))

普段はWebアプリやその周辺のインフラ構築をメインとしているため、試験対象の領域サービスに詳しくはないですが、全冠時のSAPやDASの知識はかすかに残っていたくらいです。

# 学習の進め方
以下を１週間で突貫工事しました。。。

1. DEA試験ガイド、Skill BulderでDEAの公式練習問題を実施
    - 目的: 試験範囲や試験対象の主要サービスの確認
1. 詳しくないサービスのリストアップ
    - 個人的に詳しくなかったサービス
        - LakeFormation
        - KDS, KDF, Amazon Managed Service for Apache Flink(旧KDA)
        - Glue
        - AppFlow
        - Athena
        - Redshift
        - DataSync
1. 詳しくないサービスの勉強
    - 対象の[Blackbelt](https://aws.amazon.com/jp/events/aws-event-resource/archive/?cards.sort-by=item.additionalFields.SortDate&cards.sort-order=desc&awsf.tech-category=*all)読んだくらいです
    - 各サービスの機能名とユースケースはこのタイミングで押さえておくと良さそう
1. 問題集で問題解く→解説読む、調べる

# 結果
800点オーバーで無事合格できました！
記憶にある限り、SAP ,DASの範囲がわかっていれば+αの勉強で取れる範囲だと思います。

また8月にはAIにまつわる以下2試験がリリースされるみたいなので、どっかで撮りたいと思います。
(ベータ試験を受けるモチベが。。。)
- [AI Practitioner](https://aws.amazon.com/jp/certification/certified-ai-practitioner/?ch=sec&sec=rmg&d=1)
- [Machine Learning Engineer - Associate](https://aws.amazon.com/jp/certification/certified-machine-learning-engineer-associate/?ch=sec&sec=rmg&d=1)
初心者から見たVue3コンポーネントの実装のしやすさについて Vision.5

# Vue3コンポーネントの実装のしやすさについて Vision.5

Vue3のコンポーネントの実装について、前回はVue3コンポーネントの概略から、
DOM内テンプレート解析の注意点について、まとめました。

前回：DOM内テンプレート解析の注意点

https://qiita.com/babel_0101/items/6713112a20778cc0423c

今回は、グローバル登録を以下にまとめます。
## Vue3のコンポーネントの詳細1

公式ページ：[コンポーネントの登録](https://ja.vuejs.org/guide/components/registration.html#component-registration)を読み進めながら、以下のように解釈。

**グローバル登録(Global Registration):** グローバルにコンポーネントを利用可能にするには<br>以下に示す`.component()`メソッドを使用します。
```typescript:main.ts
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.component(
  // 登録名
  'MyComponent',
  // 実装
  {
    /* ... */
  }
)
```
[アプリケーションの作成](https://ja.vuejs.org/guide/essentials/application)ページとチュートリアルの実装から、単一ファイル<br>コンポーネントを使用したルートコンポーネントの実装を前提とした方が、<br>今は分かりやすいと感じたので、若干、公式ページの記述から変えました。<br><br>`.component`に渡すコンポーネントが単一ファイルコンポーネントの場合は<br>インポートした.vueファイルを登録します。
```typescript:main.ts
import { createApp } from 'vue'
import App from './App.vue'
import MyComponent from './MyComponent.vue'

const app = createApp(App)
app.component('MyComponent', MyComponent)
```
`.component`はメソッドチェーンが使えます。
```typescript:
app
  .component('MyComponentA', MyComponentA)
  .component('MyComponentB', MyComponentB)
  .component('MyComponentC', MyComponentC)
```
グローバル登録したコンポーネントは、アプリケーション内の任意のコンポーネントの<br>テンプレートで使用できます。
```vuejs:anyComponent.vue
<!-- これはアプリ内のどのコンポーネントでも動作します -->
<MyComponentA/>
<MyComponentB/>
<MyComponentC/>
```
つまり、以下のように1ファイルずつimportを記述する必要が無くなるということですね。<br>どのページでも共通して利用するコンポーネントをグローバルに登録しておくと<br>記述がすっきりしますし、他にもメリットがあるかもしれません。
```vuejs:anyComponent.vue
<!-- グローバル登録済のコンポーネントは以下の記述が不要になります。 -->
<script setup>
import ComponentA from './ComponentA.vue'
</script>
```

グローバル登録のデメリットについて、次のローカル登録の節に記述がありましたので追記<br>

1. **未使用でも残り続ける**
    vue3には、**[ツリーシェイク(Tree Shaking)](https://ja.vuejs.org/guide/best-practices/performance.html#bundle-size-and-tree-shaking)** という未使用のコンポーネントを<br>削除してくれるビルドシステムが存在しています。
    
    しかし、グローバル登録では、ツリーシェイクが阻害されます。<br>グローバル登録したコンポーネントは、最後までアプリのどこにも用いなかった場合でも<br>最終的なバンドルには含まれてしまいます。
1. **依存関係が分かりづらくなる**
一度、グローバル登録してしまえば、どこからでも登録済コンポーネントを<br>呼び出せることがメリットでしたが、多数のコンポーネントを使用する<br>大規模アプリケーションの開発においては、子コンポーネントを使っている<br>親コンポーネントから、子コンポーネントの実装部分を探し出すことが難しくなります。<br>極めて多くのグローバル変数が使われている状況と同じように、これは長期的な<br>保守性に影響を与える可能性があります。

今回も目に見えたUI表現には影響しませんので、実装例はありません。<br>手元のコードは色々記述を変えたりしましたが、当然ながら見栄えに特に<br>影響はありませんでした。

次回：ローカル登録について

https://qiita.com/babel_0101/items/5dde78d187b18a96bcdb
Flutterアプリでバックグラウンド移行とフォアグラウンドに戻った際の状態変化を検知する

# はじめに
本記事ではFlutterアプリで `WidgetsBindingObserver` を使用して、アプリがバックグラウンド状態に移行したときと、フォアグラウンド状態に戻ったときの状態変化を検知し、それぞれログを出力する方法について記載します。


# 環境
- Flutter 3.22.1
- vscode


# ソース
アプリのライフサイクルが変化するたびに、`didChangeAppLifecycleState`でそれを検知します。
下記のソースではバックグラウンド状態になった時と、フォアグラウンド状態に戻った時にログをコンソールに出力します。

```dart:main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  // Widget生成時
  void initState() {
    super.initState();
    // 監視の開始を登録
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  // Widget破棄時
  void dispose() {
    // 監視の終了を登録
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // ライフサイクルの状態が変化した時に呼び出される
    if (state == AppLifecycleState.resumed) {
      // フォアグラウンド状態に戻った時の処理
      print('フォアグラウンド状態に戻りました');
    } else if (state == AppLifecycleState.paused) {
      // バックグラウンド状態に移行した時の処理
      print('バックグラウンド状態になりました');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('サンプルタイトル'),
      ),
      body: Center(
        child: Text(
          'サンプル画面',
          style: TextStyle(fontSize: 20),
        ),
      ),
    );
  }
}
```

# 参考
- https://api.flutter.dev/flutter/widgets/WidgetsBindingObserver-class.html
- https://api.flutter.dev/flutter/dart-ui/AppLifecycleState.html
- -https://zenn.dev/mukkun69n/articles/552173cb084e18
- https://qiita.com/tamappe/items/0d7033181b65ae4bd7d6
- https://zenn.dev/t_fukuyama/articles/a56746af9b4f2a
- https://zenn.dev/joo_hashi/articles/3e66715f70dc54
dockerを使って.activeなrosbagを一気にreindexする


.activeになったrosbag、手動でreindexは面倒

+ .activeなrosbagをactiveじゃないファイル名にする
+ rosbag reindexする
+ 使っているROSはnoetic
+ Host OSはubuntu 20.04ではないのでdockerを使いたい
+ .orig.bagもいらないので消したい

以下のワンライナーで一撃

```bash
for i in $(ls *.active); do BAG=$(echo $i | sed s/.active//) ; echo $BAG ; mv $i $BAG  ;docker run --rm -v $PWD:/rosbag --workdir /rosbag ros:noetic-ros-base  rosbag reindex $BAG ; sudo rm *.orig.bag; sudo chown $USER:$USER $BAG ; done
```
Bigtableのワイドテーブルとナローテーブルについて

## はじめに
Google Cloud Bigtableは、低遅延かつ高スループットを提供するNoSQLデータベースサービスであり、大量のデータ保存と分析に適しています。Bigtableの設計において重要な概念の一つに"ワイドテーブル"と"ナローテーブル"があります。本記事では、これらの概念について詳しく説明し、それぞれの利点と欠点、そしてどのような状況でどちらのテーブル設計を選択するべきかについて考察します。

## ワイドテーブル
ワイドテーブルとは、各行が大量のカラムを持つテーブルのことです。以下に例を示します。

#### ワイドテーブルの例
```plaintext
Row Key  | Col1 | Col2 | Col3 | Col4 | Col5 | ...
---------|------|------|------|------|------|------
Row1     | 10   | 20   | 30   | 40   | 50   | ...
Row2     | 15   | 25   | 35   | 45   | 55   | ...
...
```

#### 特徴
- **大量のカラム**：各行に多数のカラムが存在します。
- **スキャンの増加**：データを取得するために、広範囲のスキャンが必要になることがあります。
- **カラム指向**：カラムごとにデータを管理するため、カラムが多い場合に有効です。

#### 利点
- **時系列データの管理**：行のキーとタイムスタンプを組み合わせることで、時系列データを効率的に管理できます。
- **データの構造化**：特定のカラムに対して細かい制御が可能です。

#### 欠点
- **スキャンコストの増加**：クエリ実行時に多くのカラムをスキャンする必要があるため、スキャンコストが増加する可能性があります。
- **データの冗長性**：関連するデータが複数のカラムに分散するため、冗長性が増えることがあります。

## ナローテーブル
ナローテーブルとは、各行が少数のカラムを持つテーブルのことです。以下に例を示します。

#### ナローテーブルの例
```plaintext
Row Key          | Timestamp | Value
-----------------|-----------|------
Row1#20240101    | 2024-01-01| 10
Row1#20240201    | 2024-02-01| 20
Row2#20240101    | 2024-01-01| 15
Row2#20240201    | 2024-02-01| 25
...
```

#### 特徴
- **少数のカラム**：各行に少数のカラムしか存在しません。
- **キーに時間を組み込む**：行のキーに時間情報を組み込むことで、時間範囲のデータを直接取得できます。
- **行指向**：行ごとにデータを管理するため、行の追加や更新が簡単です。

#### 利点
- **クエリパフォーマンスの向上**：行キーに時間を組み込むことで、特定の時間範囲のデータを効率的に取得できます。
- **シンプルなデータ構造**：データ構造がシンプルで管理が容易です。

#### 欠点
- **行数の増加**：各タイムスタンプごとに行を追加するため、行数が増加する可能性があります。
- **データの分散**：同一のデータが複数の行に分散することがあります。

### どちらを選択するべきか
- **時系列データの管理**：データが時間依存の場合、ナローテーブルの方がクエリパフォーマンスが向上します。
- **カラム数が多い場合**：データが多くのカラムにまたがる場合、ワイドテーブルの方がデータの構造化に適しています。

## 結論
Bigtableにおけるワイドテーブルとナローテーブルの設計は、データの性質や利用目的に応じて使い分けることが重要です。ナローテーブルは特定の時間範囲のデータを迅速に取得したい場合に有効であり、ワイドテーブルは多くのカラムを持つ複雑なデータ構造を管理するのに適しています。
Yii2フレームワークことはじめ　その1 インストール後にやっておくべき設定　DB設定・コンタクトフォーム・ルーティング

# イントロダクション
PHPフレームワークは色々ありますが局所的に流行っている物にYii2があります。  
いっとき、Yiiシリーズはドキュメントが公式サイトのものしかなかったり記述もラフだったので覚えれば早く実装できるフレームワークにも関わらず理解するのが大変だったりしましたが、ここ最近(2024年現在)では公式ドキュメントが非常によく整備され学習しやすくなりました。


そんな中でもわかりにくかったり公式に書かれていなかったりする所、導入後にやっておくとよいところを書いていこうと思います。  

第一回は設定ファイルの記述について書いていこうと思います。

## DB設定
MVCフレームワークでは当然DB接続設定が必要ですが、この設定は以下の場所にありますので以下のように設定します（コメント行参照）

設置ディレクトリ\config\db.php  
```rb
return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=yii2_my_profile', 
    //dbname=の後に使用するDBの名前を書く
    //host=の後に使用するDBのホスト(ipやドメイン名)を書く
    'username' => 'root', //使用するDBのユーザー名を書く
    'password' => '', //使用するDBユーザーのパスワードを書く
    'charset' => 'utf8', //基本的にはこのままでOK

    // Schema cache options (for production environment)
    //'enableSchemaCache' => true,
    //'schemaCacheDuration' => 60,
    //'schemaCache' => 'cache',
];
```
## コンタクトフォームの設定(gmailを使用する)
Yii2をインストールするとデフォルトでコンタクトフォームが提供されますが詳細な設定方法が有りません。  
ここではgmailを使ってコンタクトフォームからのメールを受信するようにします。  
尚、ここで使うパスワードはgmailのパスワードではなくそのアカウントのアプリパスワードと言う物を取得してそれを使います。

### アプリパスワード発行手順
新しくgmailのアカウントを作る(ex hogehogehoge@gmail.com)  
googleのアカウント管理のページを開き、2段階認証を設定する(要スマホ)2段階認証でスマホの電話番号を登録するとSMSで認証コードが届くので認証コードを入れて2段階認証を有効にする。  
引き続きアカウント管理のページの上部に検索フォームがあるのでアプリパスワードと入力して検索。  
候補にアプリパスワード セキュリティと表示されるので選択、ログインを求められるのでログインする。  
「アプリ固有のパスワードを新規作成するには、下にアプリ名を入力してください」と表示されるのでフォームに適当な名前を入れて「作成」ボタンをクリック。
アプリパスワードが発行される※パスワードに半角スペースが入っているがこれは消す事。  
アプリパスワードを控えておく。

### site/contactの実装
以下のようにコードを書く  
config/params.php
```
<?php

return [
    'adminEmail' =>  'example@gmail.com',
    'senderEmail' => 'example@gmail.com',
    'senderName' =>  'gmail.com',
];

```  
config/web.php  
28行目辺りに  'mailer' => という配列があるので探して以下のように書き換え  
```
        'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,
            'viewPath' => '@app/mail',
            'useFileTransport' => false,
            'transport' => [
                'dsn' => 'smtp://example@gmail.com:取得したアプリパスワード@smtp.gmail.com:587',
            ],
        ],
```


## ルーティング
Yii2デフォルトのルーティングではコントローラーとアクション名をURLに記載するのは多くのフレームワークと同じですが…
**https://hostname/index.php?r=site%2Fsay**
これはsiteコントローラーのsayアクションを参照していますがちょっとURLが汚いですよね？

ここはsite/sayとスマートな記述にしたいですよね。  
この設定は以下のコードにあります。
設置ディレクトリ\config\web.phpの46行目あたりにある **urlManager**の記述を検索して参照
```
        // コメントアウトされているのでコメントアウトを解除して以下のような記述をする
        /**
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
            ],
        ],
        */
```

こうすると
**http://127.0.0.1/2ndapp/my_profile/web/site/contact**
といったURLになります。  
これはsiteコントローラーのcontactアクションを参照しています。  

OK，これで準備は整いました。  
次回はユーザー登録、ユーザーログイン、ユーザーログアウト、ユーザーアカウント更新について解説します。