OmniAICreator/Qiita-1.07M huggingface dataset:
【Google Cloud Next Tokyo ’23レポート】DAY2 基調講演

# 講演概要
2 日目の基調講演では、米国の Next で発表された最新の Google Cloud プロダクトとソリューションをお届けします。
さらに、多岐にわたる業種のビジネス リーダーの方々に、ビジネス課題を Google Cloud でどう解決しているのか、インフラストラクチャ、データの利活用、コラボレーションといった側面にフォーカスを当てお話しいただきます。

https://cloudonair.withgoogle.com/events/next-tokyo?talk=d2-keynote

# 所感

CAPCOM、TBSともにDXやAIの導入によって創出された時間やお金をおもしろさのために使っていきたいと言っていたことが胸に刺さりました。自分達もおもしろさのため、パートナー様のためにそういった再投資ができるようにしていきたいと改めて決意しました。　

テクノロジーの発表内容としては個人的にはあまり刺さらず・・・
ただ、BiqQueryやAppSheetのように非エンジニアでも分析や開発ができるのが当たり前になっていく世界で自分達がどうDXを進めていくかということをもっと真剣に考えていかないとあっというまに置いていかれてしまうのではという危機感は感じました。

# セッションメモ

DAY2では生成AIだけの話じゃないみたい

## インフラ

AI-optimized infrastructure
AIの学習において費用対効果の高い環境を提供
来年6月には東京リージョンでも利用可能になる
 
Modern and enterprise workloads
Cloud Runサイドカー
GKE Enterprise Edition（マルチチーム、安全なワークロード）
デモあり（フリート単位、チーム単位で管理可能、脆弱性のチェックをフリートを跨って確認、ポリシーにgoogleが用意したβストプラクティスを適用・作成できる、サービスメッシュではマイクロサービス間の接続をモニタリングできる）

Reliable and scalable infrastructure
前世代より2-7倍のパフォーマンス向上
ストレージプールMAX40%のコスト低減効果
Cross-Cloud Network（オープン、安全、最適の３つのポリシーを元に複雑化したクラウド/オンプレ間のネットワーク構成をシンプルに。脅威防御効果20倍）

### CAPCOM

SF6のお話
コアファン層向け作品からさまざまな人に楽しんでもらえるコンテンツにすることを目指した
発売１ヶ月で200万ユーザー
クロスプラットフォームを実現するためにGoogle Cloudを使った
ゲームはデータベースへの書き込みが多い
マネージドサービスを利用することで開発にかかる人件費を大きく削減できた
テストやQAにはAIを活用
品質を上げてコストを最適化することで「おもしろさ」への再投資ができる
テクノロジーはおもしろさのためにある

### 北國FDH

デジタルバンクを４年前にローンチ
ノルマ影響を廃止
ATMの社内開発、銀行システムのクラウド化
勘定系システムをフルクラウド化（日本初）
次世代地域デジタルプラットフォーム
AzureとGoogle Cloudでマルチクラウド化

## AI ecosystem

画像、音声、ドキュメントなどの非構造化データを組み合わせてビジネスに活かす
BiqQueryで管理されているコールセンターの音声データを使ったデモ
BiqQueryで音声をテキスト化できる、これをAIに渡してサマリを作成できる（これもBiqQueryでできる）
構造化データと非構造化データを掛けわせて可視化することで新しいビジネス価値を提供
Colablarory
Colab Enterprise
BiqQuery Studio（パブリックプレビュー）
Duet AIでクエリを解説させる、自然言語で提案、レポートを自動作成
ナレッジストア（構造化データと非構造化データを一元管理する）

## Google Workspace

### TBS
利用状況 9250アカウント、3.64PB
ファイル共有をする目的で2015年から導入開始、2018年にG Suiteを導入、２0２１年にはGoogleWorkspaceへ移行
JNNでも展開、残り１社もまもなく導入
AppSheetをJNN系列で活用できるようにてDXを推進していきたい
Duet AIに期待、そこで生み出された時間をコンテンツの制作に充てていきたい

## Google Startup

ダイバーシティの推進
ビシネス面でのサポート

### LUUP
電動マイクロモビリティのシェアリングサービス
街中を駅前化するインフラをつくる

## クロージング
次回は2023 8/1,2 パシフィコ横浜

# 資料リンク
例外処理の概要

## はじめに
例外処理の説明と、それに必要なエラーに言及した内容である。

## 例外とは？
　エラーは大別すると構文エラーと実行時エラーの２つである。

**・構文エラー**
　文法や構文の間違いによって発生するエラーのこと。

:::note info
例：
 　インデントミス、スペルミス、存在しない命令呼び出し、変数の参照ミスなど
:::

**・実行時エラー**
　プログラム実行中に発生する予期しないエラーのこと。
　実行時エラーにはプログラムが対処できるものとできないものがあり、
　<font color="red">**プログラムが対処できるエラーが例外**</font>と呼ばれるものである。

:::note info
プログラムが対処できるエラー例：
　ネットワーク通信障害、データアクセス障害、データベースのデッドロック、
　ファイル読み込み失敗、整数を0で除算するなど
:::
:::note info
対処できないエラー例：
　ハードウェアの故障、メモリ不足、OSの異常など
:::

## 例外処理とは？
　つまり例外処理とはプログラム実行中に発生するエラーの内、
　対処できるエラー(例外)に対する処理のこと。

## 例外処理の目的
　例外が発生すると実行中のプログラムの処理が中断してしまう。

```Python:Pythonコード
alphabets = ['a','b','c','d']

print('処理開始')
print(alphabets[5])  #存在しないインデックスにアクセス
print('処理終了')
```
　`print(alphabets[5])`でエラーが発生したことで処理が中断されるため、
 　`print('処理終了')`の処理が実行されない。
```Python:実行結果
処理開始
```
　例外処理を行うことで<font color="red">**エラーが発生してもプログラムの処理を中断せず、
　発生したエラーは例外処理で対処しそれ以降の処理は続行させる**</font>ことができる。

 ## 例外処理の仕組み
　例外が発生しそうな箇所をブロック(try)で囲む。
　別ブロック(except)でエラー時の処理を記述する。
 
```Python:Pythonコード
alphabets = ['a','b','c','d']

print('処理開始')

try:
    print(alphabets[5])              # 存在しないインデックスにアクセスによりエラー発生
    print('エラー発生のためこの命令は処理されない')
except IndexError:
    print('インデックスエラーの発生')  # 例外処理

print('処理終了')
```
　ブロック(try)内で例外が発生するとブロック(try)内の処理は中断され、
　発生した例外に対応するブロック(except)に処理が切り替わる。
　その際、エラー情報が格納されたオブジェクトがブロック(except)に渡される。
　ブロック(except)内の処理が終わったら、そのブロック以降の処理が実行される。

```Python:実行結果
処理開始
インデックスエラー発生
処理終了
```
　`print(alphabets[5])`で例外が発生したことでブロック(try)内の処理が中断され、
　`print('エラー発生のためこの命令は処理されない')`は実行されていない。
　しかし、例外処理によってプログラムの実行は継続されているため、
　例外処理以降の`print('終了')`が中断されることなく実行され出力されている。
devcontainer事始め

# devcontainer とは

VSCodeで利用できる開発用コンテナ

https://code.visualstudio.com/docs/devcontainers/containers

コンテナの構成や設定をファイルで定義しておくことで、
2回のクリックだけで開発環境を構築できるようになる

1. 左下の `><` マーク
1. `コンテナーで再度開く`

![Nov-16-2023 10-28-56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1666407/b5a7ae45-65c0-0182-bfb7-6aa0cc784b4d.gif)

ホストマシンでは実行できなかった `go` コマンドが、
開発用コンテナに入ったことで実行可能になった

# 嬉しいこと

- 開発作業がコンテナ内で完結できる
    - 他の作業と衝突しない
    - 手軽に環境を復元できる
    - 気兼ねなく削除できる
- 開発者間で環境を統一できる
    - シェル
    - プログラミング言語
    - 依存パッケージ
    - ツール
    - 環境変数
    - VSCode拡張機能、など
- 開発環境自体をバージョン管理できる
- 個別の環境構築マニュアルが不要になる
    - 手作業によるミスも減らせる

# 前提

- VSCode
    - 拡張機能 [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
- Docker

# チュートリアル

https://code.visualstudio.com/docs/devcontainers/tutorial

:::note
`New Dev Container (新しい開発コンテナー)`のところは
`Open Folder in Container (コンテナーで再度開く)` を選択したほうが分かりやすい
(devcontainerの設定ファイルが現在開いているリポジトリに作成されるため)
:::

# 設定ファイル

`.devcontainer/devcontainer.json` に各種設定が記載されている
設定項目は以下を参考

https://containers.dev/implementors/json_reference/

## Dockerfileを利用したい場合

`build.dockerfile` で相対パスを指定する

```json:devcontainer.json
{
    ・・・   
	"build": {
		"dockerfile": "../Dockerfile"
	},
    ・・・
}
```

## VSCode 拡張機能を利用したい場合

```json:devcontainer.json
{
    ・・・   
	"customizations": {
		"vscode": {
			"extensions": [
				"MS-CEINTL.vscode-language-pack-ja"
			]
		}
    }
    ・・・
}
```

拡張機能の歯車マークから`devcontainer.jsonに追加`も可能

![Nov-16-2023 11-04-31.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1666407/2c30edc0-b3f0-6460-24c5-04b4a9a91237.gif)
Vue.jsの小技。propsでヒアドキュメント風

:::note
小ネタです
:::

propsを呼び出すときに、タイトルなどを改行したい場合は、
```demmo.css
elm {
    white-space: pre-wrap
  }
```
を使うとヒアドキュメントのように書ける。

```demo.vue
<layout-visual
  style="white-space: pre-wrap"
  title="
  N
  U
  X
  T
  Information"
  :height="40"
  visual="visual-information"
/>
```
![スクリーンショット 2022-09-21 13.33.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587300/b2e4d9f2-ae25-6b71-bc4a-500796e10215.png)
PythonでAzure Blob Storage上の画像をメモリに直接読み込む

Blobに配置した画像をNotebooksで触る必要があったので備忘録として。

```python
import os
import matplotlib.pyplot as plt
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, __version__
from PIL import Image
from io import BytesIO

container_name = "container"
target_image_folder = "hoge/fuga"

STORAGE_ACCOUNT_CONNECTION_STRING = ""

blob_service_client = BlobServiceClient.from_connection_string(STORAGE_ACCOUNT_CONNECTION_STRING)

with blob_service_client:
    container_client = blob_service_client.get_container_client(container_name)
    blobs_list = []
    img_list = []
    for blob in container_client.list_blobs():
        blobs_list.append(blob)

    for blob in blobs_list:
        if os.path.dirname(blob.name) != target_image_folder:
            continue
        print("Downloading blob: ",blob.name)
        blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob.name)
        stream = blob_client.download_blob()
        data = stream.readall()
        img = Image.open(BytesIO(data))
        img_list.append(img)

print(len(img_list))
for img in img_list:
    plt.imshow(img)
    plt.show
```
1115

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>アカウント登録</title>

    <!-- 引入jQuery -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>

    <!-- 引入Bootstrap的CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

    <!-- 引入Bootstrap的JavaScript -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>
    <!-- ... 其他HTML内容 ... -->

    <!-- 你的表单和脚本代码 ... -->

</body>
</html>
PythonでPandas DataFrameをAzure Table Storageに書き込む

PandasのDataFrameをそのままAzure Table Storageに書き込むサンプルコードです。
対象のDataFrameにTable Storageで必須となるカラム「PartitionKey」「RowKey」を含めます。これらはTable Storageの制限として2つの組み合わせで一意になる必要があります。詳しくは公式ドキュメント参照。サンプルではめんどくさいのでramdomにしていますが、検索パフォーマンスに大きく影響するので実際に利用する場合はちゃんと設計しましょう。
※テーブルはすでに作成されている前提です。

```python
import random
import pandas as pd

from azure.cosmosdb.table.models import Entity
from azure.cosmosdb.table.tableservice import TableService

CONNECTION_STRING = ""
table_name = ""

# 適当にDataFrameを作成
cols = ["PartitionKey", "RowKey", "val3", "val4"]
df = pd.DataFrame(index=[], columns=cols)
for i in range(50, 100):
    row = pd.Series([str(i).zfill(4), str(0), random.random() * 100, random.random() * 1000], index=["PartitionKey", "RowKey", "val3", "val4"])
    df = df.append(row, ignore_index=True)

# 書き込み
table_service = TableService(connection_string=CONNECTION_STRING)
for index, row in df.iterrows():
    table_service.insert_entity(table_name, row.to_dict())
```
reviveでカスタムLintルールを設定する方法

### **はじめに**

Go言語のプロジェクトにおいて、コードの一貫性と品質を保つことは非常に重要です。標準のlintツールは多くの基本的なニーズを満たしますが、特定の命名規則やスタイルガイドに完全に準拠するためには、追加の設定やツールが必要になることがあります。この記事では、特に**`revive`**を使用してGoのコードに対するより厳格なlintチェックを行う方法について解説します。

### `revive`の導入

`revive`は`golint`の代替として推奨される、柔軟で高速なlintツールです。これは、Goのコードに対するスタイルと品質のチェックを提供し、カスタマイズ可能なルールと高速な実行が特徴です。

### `revive`の設定例

`revive`をプロジェクトに組み込む基本的な手順と、特定の命名規則をチェックするための設定例を以下に示します。

まず、`revive`を有効にするために、lint設定ファイル（例えば`.golangci.yml`）に以下のように追加します。

```yaml
linters:
  enable:
    - revive
```

次に、`revive`の設定ファイル（通常は`.revive.toml`または`revive.toml`）を作成し、特定のルールを有効にします。例えば、略語を大文字で表記するルールを設定するには、以下のようにします。

```toml
[rule.var-naming]
  arguments = [["ID", "URL", "HTTP", "TLS", "XML", "JSON", "SQL"]]
```

この設定により、`revive`はこれらの略語がコード内で一貫して大文字で使用されているかをチェックします。

### 3. その他のlintツールとの組み合わせ

`revive`は他のlintツール（例：`staticcheck`、`errcheck`）と組み合わせて使用することができ、プロジェクトの品質をさらに向上させることが可能です。

### **おわりに**

`revive`を使用することで、Goのコードに対するより詳細なスタイルと品質のチェックが可能になります。特に、命名規則に関するカスタムルールを設定することで、コードの読みやすさとメンテナンスの容易さが向上します。lintツールのカスタマイズは、チームやプロジェクトの特定のニーズに応じて調整することが重要です。
PythonでAzure Blob Storageのファイル一覧をPandas DataFrameに出力する

Blobに適当にアップロードしたファイルを一覧化し、ファイル名とか作成日時とかで集計・フィルターする必要があったので備忘録として。

```python
import os
from concurrent.futures import ThreadPoolExecutor
import pandas as pd
from azure.storage.blob import BlobServiceClient, __version__

CONNECTION_STRING = ""
container_name = ""

# blob接続
blob_service_client = BlobServiceClient.from_connection_string(CONNECTION_STRING)
container_client = blob_service_client.get_container_client(container_name)

# df作成
cols = ["file_name", "folder", "basename", "creation_time", "last_modified"]
df = pd.DataFrame(columns=cols)

# blob情報をdictに突っ込む関数
def create_row_dict(blob):
    row_dict = {}
    row_dict["file_path"] = blob.name
    row_dict["directory"] = os.path.dirname(blob.name)
    row_dict["file_name"] = os.path.basename(blob.name)
    row_dict["creation_time"] = blob.creation_time
    row_dict["last_modified"] = blob.last_modified
    return row_dict

# blob情報取得
blob_list = container_client.list_blobs()

# めっちゃ時間かかるので並列化
with ThreadPoolExecutor(12) as e:
    ret = e.map(create_row_dict, blob_list)

tmp_dict = {}
for i, r in enumerate(ret):
    tmp_dict[i] = r

# dictをdf化
df = pd.DataFrame.from_dict(tmp_dict, orient="index")

# csvファイルのみ抽出
only_csv_df = df.query("file_name.str.contains('.csv')").reset_index(drop=True)

# 特定期間内に作成されたファイルのみ抽出
only_csv_df["creation_time"] = pd.to_datetime(only_csv_df["creation_time"], utc=True, errors='coerce').dropna()
only_csv_df = only_csv_df.sort_values("creation_time")
filterd_df = only_csv_df.query("creation_time >= '2023-02-01 00:00:00+00:00' & creation_time <= '2023-05-01 00:00:00+00:00'")
```
Javaってオワコン？？ーJavaでご飯を食べていけるようになりたいエンジニア

# Javaを覚えれば食べていけると言われて
自分が学生の頃にC言語をやりつつ、先生にはこれからはJava時代だ！！
Javaを覚えれば食うに困る事態にはならない！！　と言われてはや数十年......
現在はプログラミングの「Vivienne Westwood」いや「焚き火台」かな
はたまた「マリオカート」的な......

例えがわからなくなってきましたが、最先端！！！！　という形ではないものの、常に前線にいる存在。
そんな形でさまざまなシステムが今日もJavaで動いております。
でも、ここ最近Javaってオワコン？？？？　という話を聞くこともちらほら......
（まぁ、有償化のときが一番ひやっとしましたが......) 

そんなJavaの将来についてどうなんだ？　と見ていきたいと思います。

# そもそもJavaでできることって？？
Javaって色々言われているけど、現状どんな特徴あるっけ？　何が作れる？　をまとめてみよう！

* Javaの特徴
    1. オブジェクト指向
    オブジェクティブ指向言語の筆頭に数えられるJava。そこは今も昔も変わっていません。
    最近人気のPython、JavaScript、昔ながらのC++、Swiftもお仲間です。
    1. 環境に依存しない
    Javaはプログラムを実装すればコンピューターやOSに依存せず動作するという特徴があります。
    MacOSやWindowsといったOS間での互換性は言わずもがな。
    最近ではスマーフォンなどでもJavaによるアプリケーションが使われています。
    1. セキュリティ面の堅牢さ
    当初からセキュリティを考慮された設計になっているので、ハッキングされにくく、安定性が高いとされてきています。

* Javaで作られているものは？
    1. Webアプリ・Webサービス
    実行スピードが速い・堅牢性の高さなどから大規模なWebサービスやアプリ開発に好まれる傾向にあります。YouTube・Amazon・X（旧Twitter）などが挙げられます。
特にXはTwitter時代にRuby on RailsからJavaに切り替えてアメリカ大統領選の情報量を乗り切ったそうです。
    1. デスクトップアプリ（PCソフト）
    OS問わず利用できることから、PC向けデスクトップアプリケーションの開発によく利用されます。
    一太郎、ゲームのMinecraft、OpenOfficeなどになります。
    1. 基幹システム開発
    堅牢性のおかげで、商用の基幹システムへの採用例も多いです。代表的なものに銀行の基幹システムなどがあります。
    1. 組込みシステム・IoT開発
    某メガネの少年が「IoTテロだ！！！！」と叫んでおり、こんなに簡単にやられてたまるかｗｗと思ったシーンでしたがｗｗ近年、家電製品の組込みシステムにJavaが登場することが多くなりました。
また、IoT化分野でスマートスピーカーや、紛失防止の電子タグなどの通信モジュールに使用されています。

# Javaってニーズありそうやん？？
何ができるのか？　という点で考えると結構ニーズありそう......ってなってきました。
一応ちゃんとニーズがあるぞという理由も考えてみましょ！！
1. Javaで作ったシステムの保守・改修案件
    Javaで作られているシステムは結構多いため、保守、改修の需要が多いです。
銀行の基幹システムや企業や官公庁の大規模システム、大手ECサイトなど、信頼性が重視されるものが数多くあるため、保守・点検が重要になってきます。そのため、この辺りの需要は現状絶えることはないでしょう。
完全になくなると思われていたCOBOLの案件も、なくなることはなかったので尚更Javaが絶えることは万が一がない限りないと思います！！！！
1. Javaの需要は減っていない！！
    プラットフォームを選ばない応用力の高さ、信頼性によって未だ幅広い分野で使用されていること。
    また、新しくIoT分野でもJavaが使用されることが多くなり、スマート家電やウェアラブルデバイスは今後さらに伸びていく分野のため、まだまだ需要は減っていく様子はないと言っていいでしょう。

# Java覚えれば食べていけるはうそじゃなかった！！

ニーズなくならない!!!!　なら今から頑張っても無駄にはならない！
じゃあすぐなろう！
と頑張りたいところですが。Javaの習得はそれなりにコストが高いです。
また、実務を行うにあたってネットワークやハードウェアも含めた知識や企業などの基幹システムの構築では、将来を見据えた設計の経験を積んでいく必要があります。
それを踏まえた上でも、将来性は十二分にあると思います。
時間がかかっても頑張り甲斐があるかと思います。

# 最後に
簡単にJavaエンジニアは育たないことから、多くの企業がJavaエンジニアを求めています。Javaは、これまでもこれからも、学習する価値の非常に高い言語といえます。
そう、Javaを覚えればご飯を食べていけるエンジニアにはなれるということです！！！！

というわけで、Javaはまだまだオワコンじゃないよ！
Android　Studioでビルドができない問題

## ビルドできない
Androidアプリを作ろうと思い、早速ビルドを行うと問題が発生した。
以下のようなエラーが発生。

```
Dependency 'androidx.activity:activity:1.8.0' requires libraries and applications that
      depend on it to compile against version 34 or later of the
      Android APIs.

      :app is currently compiled against android-33.
```
翻訳すると、
```
androidx.activity:activity:1.8.0'に依存するライブラリとアプリケーションは、
バージョン34以降でコンパイルする必要があります。
依存するライブラリとアプリケーションは、バージョン34以降でコンパイルする必要があります。
に対してコンパイルする必要があります。

 現在、アプリはandroid-33に対してコンパイルされています。
```
## 言うことを聞いてみる

app配下にあるbuild.gradle.ktの数値を変えて、バージョンを変えてみる。
`compileSdk = 34`
`targetSdk = 34`
に変更。

## sdkのバージョン変更後
コードを確認すると、targetSdkの方に赤い波線がでてしまう。
エラーの内容は以下の画像の通り。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2302298/98b63b37-df29-1035-f64b-5819ffdea998.png)

ドキュメントを参照すると、仮想デバイスのAPIレベルが足りていないと書かれていた。
[ドキュメントはこちら](https://developer.android.com/guide/topics/manifest/uses-sdk-element?hl=ja)

そこで、APIレベルが34以上の仮想デバイスをインストールした。

## それぞれ変更した変数の役割について
そもそも何を変更したのかわからない。なんでうまくいったのかを調べるためにまずは変更した変数の意味を調べた。


### **compileSDK** 
> compileSdkVersion specifies the Android API level Gradle should use to compile your app. This means your app can use the API features included in this API level and lower.
> 
> 
> compileSdkVersionは、Gradleがアプリをコンパイルする際に使用するAndroid APIレベルを指定します。これは、アプリがこのAPIレベル以下に含まれるAPI機能を使用できることを意味します。


コンパイルに使うSDKのバージョン。新しい機能を使えるようにするため、基本的には現時点での最新を指定する。

---

### **minSdk** 
> Defines the minimum API level required to run the app.
> 
> 
> アプリの実行に必要な最低限のAPIレベルを定義します
> 

アプリの最低OSバージョン。
古いOSをサポートする場合、この値を小さくする。

---

### **targetSdk**
> Specifies the API level used to test the app.
> 
> 
> アプリのテストに使用するAPIレベルを指定します。

問題のやつ。翻訳してもよくわからなかったので、調べたところわかりやすい説明があったため引用しました。

***アプリを動作させるAPIレベルを指定します。compileSdkと同じく基本的には現時点での最新を指定すればいいですが、例えばAndroid 12（APIレベル31）対応が完了していない場合、targetSdkを30に指定すればAndroid 12でも11のように振る舞う、ということです。***

参考：https://qiita.com/uhooi/items/0f2ad61d83b96d9166c8

## targetSdkを33にする

これは、実行時にどのOSバージョンの互換モードで動かすかの指定。
だからここは最新ではなくてもよい。

バージョンを以下のように修正し

`compileSdk = 34`
`targetSdk = 33`

ビルドをし直すと、うまく動作した！

---

内容についての指摘や追加情報等ございましたら、コメントで教えていただけますと幸いです。
Azure AutomationでSet-AzKeyVaultAccessPolicyを実行できないときの対処法

# はじめに
めちゃくちゃニッチですが、システム割り当てマネージドIDでAzureと接続したAutomation Accountにて、Key Vaultに対してアクセスポリシーを付与するコマンド「Set-AzKeyVaultAccessPolicy」をサービスプリンシパルIDで実行する際、所有者ロールを付与しても登録できない場合の対象法になります。
よく読めばMSDocsのノートに書かれていましたが、非常に苦労したので備忘録として、、、

# 解決策
MSDocsに示されている通り、「-BypassObjectIdValidation」パラメータを指定する必要があります。
https://docs.microsoft.com/en-us/powershell/module/az.keyvault/set-azkeyvaultaccesspolicy?view=azps-8.1.0#description

```powershell
$servicePrincipalId = "XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
$KEY_VAULT_NAME = "<your key vault name>"
 
# セッション情報の保持を無効化
Disable-AzContextAutosave -Scope Process
 
# システム割り当てマネージドIDを利用して接続
$AzureContext = (Connect-AzAccount -Identity).context
# コンテキストをセット
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
 
# アクセスポリシー付与
Set-AzKeyVaultAccessPolicy `
    -VaultName $KEY_VAULT_NAME `
    -ObjectId $servicePrincipalId `
    -PermissionsToSecrets Get,List `
    -BypassObjectIdValidation
```
Azure Custom Visionのプロジェクトをコピーする

Custom Visionに作成したプロジェクトをコピーする方法です。
REST APIを持ってるのでcurlでもほかの言語でも行けますが

```python
import requests
import json

# Exports param
export_endpoint = ""
export_project_id = ""
export_training_key = ""

export_url = f"{export_endpoint}/customvision/v3.3/Training/projects/{export_project_id}/export"

export_headers = {
    "Training-Key": export_training_key
}

response = requests.get(export_url, headers=export_headers)

res_body = json.loads(response.text)
token = res_body["token"]
print(token)

# Import params
import_endpoint = ""
import_project_name = ""
import_training_key = ""

import_url = f"{import_endpoint}/customvision/v3.3/Training/projects/import"

import_headers = {
    "Training-key": import_training_key,
    "Content-Length": "0"
}

params = {
    "token": token,
    "name": import_project_name
}

response = requests.post(import_url, headers=import_headers, params=params)
```
Azure Custom Visionにアップロードした教師データをダウンロードしなおす

Custom Visionにアップロード済みの教師データをタグごとにフォルダ分けしてダウンロードするサンプルです。

```python
import os
import requests
import json
import collections
from tqdm.notebook import tqdm as tqdm

headers = {
    "Training-Key": ""
}

params = {
    "take": "256",
    "skip": "256"
}

project_id = ""
endpoint = ""
url = f"https://{endpoint}/customvision/v3.0/training/projects/{project_id}/images/tagged"

r = requests.get(url, params=params, headers=headers)
data = json.loads(r.text)

# タグ名の一覧取得
tag_name_list = []
for item in data:
    tag_name_list.append(item["tags"][0]["tagName"])
tag_name_list = [k for k, v in collections.Counter(tag_name_list).items() if v > 1]

# タグ名に応じたフォルダを作成
for tag_name in tag_name_list:
    folder = "output/" + tag_name
    if not os.path.exists(folder):
        os.makedirs(folder)

# ダウンロードしてタグ名に一致するフォルダに格納
for item in tqdm(data):
    original_image_uri = item["originalImageUri"]
    tag_name = item["tags"][0]["tagName"]
    id = item["id"]
    folder_path = "output/" + tag_name
    file_name = os.path.join(folder_path, f"{id}") + ".png"
    if os.path.exists(file_name):
        print(f"{file_name} is exists.")
        continue
    image = requests.get(original_image_uri).content
    with open(file_name, "wb") as file:
        file.write(image)
```
未経験エンジニアが2年目の業務で学んだこと

# はじめに
オークファン開発部の @Soogle_1729 です。
2021年の11月に製造業から当社へ中途入社しました。いわゆる未経験エンジニアに該当すると思います。
この記事では、**未経験エンジニアが2年目の業務で学んだことや身につけたスキル**についてまとめます。

IT業界へキャリアチェンジを考えている方や、実際の業務でどのようなスキルセットが必要になるか気になっている新人エンジニアの方などの参考になればと思います。

ちなみにですが、これまでは未経験エンジニアの視点で下記のような記事を書いています。
- [業界未経験から転職して1年間で学んだこと](https://qiita.com/Soogle_1729/items/9b650a73016ecb39fb5d)
- [製造業からIT業界へ転職して感じたギャップ](https://qiita.com/Soogle_1729/items/74c2d8c1a9f163946f76)

# 自己紹介
- 大学の専門： 材料系
    - コンピュータサイエンスやプログラミングについては、ほとんど学んでいませんでした。
- 前職：新卒で製造業に入社し、品質管理など担当
    - データ分析などはやるが、プログラミングやITとはほぼ無縁
- 転職するまでのプログラミング歴：独学とスクールで合計1年ほど。
    - Swift　や　Ruby on Rails　などを学習。プログラミングスクールを決める際に、どの言語を学ぶか迷いましたが、いま振り返ると最初に学ぶ言語は何でも良かったと感じます。

転職してから1年目の間は、主にバックエンドとフロントエンドについて担当しました。詳細については、[過去の記事](https://qiita.com/Soogle_1729/items/9b650a73016ecb39fb5d)を参照していただければと思います。

# 2年目で担当した業務と技術
担当した業務ごとに使用した技術をまとめます。

## Web システムの新規開発 その1
4 ~ 6 名程度のプロジェクトで、バックエンドの一部とフロントエンドについて担当しました。

### 使用した技術
- バックエンド
    - [Spring Boot](https://spring.io/projects/spring-boot)
    - [Kotlin](https://kotlinlang.org/)

- フロントエンド
    - [Nuxt.js](https://nuxt.com/)
    - [TypeScript](https://www.typescriptlang.org/)
    - [Vuetify](https://vuetifyjs.com/en/)

これまで使ってきた技術でしたが、規模が大きめのプロジェクトだったので、複雑さに苦戦しました。


## Web システムの新規開発 その2
3名程度のプロジェクトで、PM として参画しました。上流から下流まで一貫して対応したので、良い経験ができました。

### 使用した技術
- WordPress
    - PHP

小さめの案件であることと、時間的制約から WordPress を採用することになりました。
WordPress のどのディレクトリを Git 管理するのが良いか悩んだ記憶があります。

## モバイルアプリの機能改修
運用されているモバイルアプリの機能改修を担当しました。

### 使用した技術
- [iOS](https://developer.apple.com/jp/ios/)
    - Objective-C
    - [Swift](https://www.swift.org/)
    - [Swift UI](https://developer.apple.com/jp/xcode/swiftui/)

- [Android](https://www.android.com/intl/ja_jp/)
    - [Kotlin](https://kotlinlang.org/)

初めてモバイルアプリを担当することになりました。既存アプリの仕様の把握や各技術のキャッチアップなど大変でしたが、念願のモバイルアプリを担当できたので、非常に良かったです。

## モバイルアプリの新規開発
上記の経験もあって、モバイルアプリの新規開発を担当しました。

### 使用した技術
- [Flutter](https://flutter.dev/)
    - [Dart](https://dart.dev/)

開発工数を削減するためマルチプラットフォームに対応している Flutter を採用しました。
まだまだキャッチアップ中で、知見を深めようとしています。

# 2年目の感想

## 良かったこと
- プログラムを書く仕事が継続できている
    - 要件定義や設計などもありますが、メインの業務としてプログラムを書くことができています。
    - 自分の書いたものが動くという体験が楽しいので、継続できて良かったと感じています。
- モバイルアプリに携わることができた
    - 入社当時は、モバイルアプリの業務がありませんでした。
    - モバイルアプリの事業が開始したタイミングで担当させてもらえたのは非常に良かったです。
    - やりたいと言っていた業務ができるのは良い環境だと感じます。
- リモートワークが継続できている
    - 去年もほぼフルリモートでしたが、現在も継続できています。
    - オフィスを縮小したこともあり、今後もリモートワークが続きそうなので安心しています。
    - 物理的に会わないので、人の顔と名前が一致しないという弊害も生じています。

## 想定とのギャップ
- ルーティーン業務が少ない
    - 所属部署の関係上、新規開発の割合が高く、運用などにあまり携わっていません。毎回新しいことを進めていくような感じなので、ルーティーン業務がほとんどありません。
    - 新鮮な気持ちで業務に取り組めるのは良いですが、1つの技術やシステムなどに精通しづらいということもあるので、一長一短ですね。
- 自然と身に付くと思っていたことは、身につかない
    - わからないことがたくさんあるので、深堀りする知識は自分の中で取捨選択をするようにしています。
    - 業務を進めていれば自然と身に付くだろうと後回しにした知識も多くあるのですが、そういったものは結局身に付かないままになってしまっています。
    - 業務を調整して、しっかりとキャッチアップする必要があると感じます。
- 人の流動性が激しい
    - 気がついたら担当者が変わっているような印象があります。
    - ロストテクノロジーとならないように、組織として知見を溜めていく必要がありそうです。

## 今後の抱負
- モバイルアプリの担当者は少ないので、この技術を自分の得意分野にできるようにスキルアップしたいです。
- 上流工程をやることが増えてきたので、プロジェクトを円滑に進めるようにプロジェクト管理に慣れていきたいです。
- 主担当として自分のやった案件だと言えるような結果を残したいです。

オークファングループでは、未経験者を含めてエンジニアを募集しています！興味のある方は、[コチラ](https://aucfan.co.jp/recruit/)をご覧ください。
M5StackのAtomMotionをM5Unifiedと共に使うClass

# はじめに

[M5StackのAtomMotion](https://shop.m5stack.com/products/atom-motion-kit-with-motor-and-servo-driver-stm32f0)を、いつも利用しているM5Unifiedと連携して使いやすくしたライブラリを作りました。[Unit Encoder用のClassを作った話](https://qiita.com/8ga3/items/50fd5c0691ea8f025d9d)と動機は同じです。

メンバ関数はM5Stack公式のスケッチ例にあるAtomMotion.(cpp|h)を継承しています。

https://qiita.com/8ga3/items/50fd5c0691ea8f025d9d

# ライブラリ共有

GitHubにリポジトリを作りました。`lib/AtomMotion_Class/AtomMotion_Class.cpp`が該当します。platformioのプロジェクトの形になってます。

https://github.com/8ga3/AtomMotion_Class_M5Unified

# 初期化

特に宣言はありません。M5Stack系・M5Stick系はサイド、M5Atom系は底のピンのI2Cにつながるものとして初期化されます。M5Unifiedによって自動判別で適切に設定されます。
変更する場合は、コンストラクタの引数で指定できます。

```cpp:main.cpp
#include <M5Unified.h>
#include <AtomMotion_Class.hpp>

m5::AtomMotion Motion;

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  Motion.SetServoAngle(1, 90);
}
```

# メンバ関数

## コンストラクタ

```cpp
  AtomMotion(std::uint8_t i2c_addr = DEFAULT_ADDRESS, std::uint32_t freq = 400000, I2C_Class* i2c = &In_I2C);
```

**パラメータ**
* *i2c_addr* : アドレス値。AtomMotionは0x38です。
* *freq* : クロック数
* *i2c* : I2C_ClassでSCL/SDAの番号を設定しています。

## SetServoAngle

```cpp
  std::uint8_t SetServoAngle(std::uint8_t Servo_CH, std::uint8_t angle);
```

サーボモーターを指定した角度にします。[Servo Kit 180‘](https://shop.m5stack.com/products/servo-kit-180) を使用することが前提となっていると思います。angleの値とサーボモーターの角は機種ごとに確認したほうが良いです。

**パラメータ**
* *Servo_CH* : サーボ番号(1~4)
* *angle* : 角度(0~180)

**戻り値**
* 0 : 成功
* 1 : 引数が範囲外

## SetServoPulse

```cpp
  std::uint8_t SetServoPulse(std::uint8_t Servo_CH, std::uint16_t width);
```

サーボモーターのパルス幅を設定します。1500が中央値です。360度連続回転サーボを使う場合、1500で停止するようにプラスドライバーを使ってモーター本体を調整しましょう。

**パラメータ**
* *Servo_CH* : サーボ番号(1~4)
* *width* : パルス幅(500~2500)

**戻り値**
* 0 : 成功
* 1 : 引数が範囲外

## SetMotorSpeed

```cpp
  std::uint8_t SetMotorSpeed(std::uint8_t Motor_CH, std::int8_t speed);
```

Atom Motionの２ポートあるブラシモーターの速度を設定します。０で停止、プラス・マイナスで回転方向が変わります。

**パラメータ**
* *Servo_CH* : モーター番号(1~2)
* *speed* : -127~127

**戻り値**
* 0 : 成功
* 1 : 引数が範囲外

## ReadServoAngle

```cpp
  std::uint8_t ReadServoAngle(std::uint8_t Servo_CH);
```

サーボモーターの角度を取得します。

**パラメータ**
* *Servo_CH* : サーボ番号(1~4)

**戻り値**
* 角度

## ReadServoPulse

```cpp
  std::uint16_t ReadServoPulse(std::uint8_t Servo_CH);
```

サーボモーターのパルス幅を取得します。

**パラメータ**
* *Servo_CH* : サーボ番号(1~4)

**戻り値**
* パルス幅

## ReadMotorSpeed

```cpp
  std::int8_t ReadMotorSpeed(std::uint8_t Motor_CH);
```

ブラシモーターの速度を取得します。

**パラメータ**
* *Servo_CH* : ブラシモーター番号(1~2)

**戻り値**
* 速度
で、数学的帰納法って結局何に使うん？（´｡｀)　⇒　例えば、ヴァンデルモンドのたたみ込みの証明とか　⇒「非」復元抽出の公式の導出

普段より、自分のプログラミング等に関する質問に答えて下さっている皆様ありがとうございます。m( _ _)m　よろしければ統計検定の学習等にご利用ください。マークダウンは雑ですみません。これから勉強します。 m( _ _)m

<h1>「ヴァンデルモンドのたたみ込み」の証明（のメイン部分）※省いてあるところはチャートとかの定型文でいけます。

https://drive.google.com/drive/u/0/folders/12X9Vzw4cETT1RiBv_vPfYLLg5jNkXSQ4

Githubリンクバージョン（※中身は同じです）

https://github.com/thinking-weed/analysis-statics-memo/tree/main/Vandermonde's_convolution


　最近たまたま以前計算していたノートを見つけました。（前職で、もしかしたら使うかもとおそらく休みとかに計算したものの、使う気配全くなく存在すら忘れていたノート）
 　この謎公式が何の役に立つのかは、また時間を見てQiita化しますが、数学的帰納法はこういうパターンもあるんだよ、
<h3>つまり一口に数学的帰納法といっても


「数列 ①$n = 1$の場合の証明　② $n=k$ のときの場合を仮定して、$n=k+1$ の場合を考える。そして、①・②より全ての自然数に対して～」**意外のパターンも結構ある**」

という例です。（※チャートとかにも実は後半少し載っている）
____
なお、ヴァンデルモンドは線形代数とか勉強してると時々行列式とかに出てくる、変態的な公式を作りまくって死んでいったおじさんの名前で、リンク先の画像ファイル名の英語は
convolution　⇒　たたみ込み、fomula　⇒　公式、combination　⇒　組み合わせ（${}_n C_r$のやつ）、proof ⇒　証明　です。
恒等式というのは、右と左が実は同じですよってやつです。
中身は日本語で書いています。生粋の日本人ですので。

____
実はこれは、**「非」復元抽出の標本平均** 

$E(\bar{X})$

**の公式を出すのにどうも使う**みたいです。
（以前たぶんかなり時間かけて調べたり計算したりして確かめたのであろう本人も忘れている・・(ﾟДﾟ)）※Python学習の合間にそのノートもQiita化します。




<h1>よくお世話になった参考資料一覧（※全部の内容を自分も理解できているわけではないです。）

・統計検定1級公式問題集　実務教育出版　
　※過去問のページもありました。　https://www.toukei-kentei.jp/prepare/kakomon/
・青チャートI＋A、Ⅱ＋B　数研出版
・理工系の微分積分学　吹田信之、新保経彦　共著　学術図書出版書
・線形代数入門　齋藤正彦　著　東京大学出版会
・定本　解析概論　高木貞治　著　岩波書店　
・数学シリーズ　数理統計学　改訂版　稲垣萱生　著　裳華房
・数学シリーズ　集合と位相　内田伏一　著　裳華房
・one point 推定と検定　鷲尾泰俊　著　共立出版
・電磁場とベクトル解析　深谷賢治　著　岩波書店
・シリーズ物理数学1　フーリエ解析　江沢　洋　著　朝倉書店
（※一見、統計とは全く関係なさそうですが、実は中に統計・確率に関する章があります。しかも結構詳しく書いてくれてある。江沢さんの本は難しいけど丁寧だから基本オススメ）
Ruby on Rails チュートリアル 第11章演習解答（第7版）

# 概要
11.3.3の演習問題が難しく、ネット上に解答が見つからなかったので忘備録として記載してます。
rails tでGREENでしたが間違っていたらすみません。
ご指摘いただけると大変助かります。
# 解答
## リスト 11.42
```ruby:test/integration/users_index_test.rb
.
.
.
  test "should display only activated users" do
    # ページにいる最初のユーザーを無効化する。
    # 無効なユーザーを作成するだけでは、
    # Railsで最初のページに表示される保証がないので不十分
    User.paginate(page: 1).first.toggle!(:activated)
    # /usersを再度取得して、無効化済みのユーザーが表示されていないことを確かめる
    get users_path
    # 表示されているすべてのユーザーが有効化済みであることを確かめる
    assigns(:users).each do |user|
      assert user.activated?
    end
  end
end
.
.
.
```

## リスト 11.43
テンプレート通りのため省略

## リスト 11.44

```ruby:test/integration/user_show_test.rb
require "test_helper"

class UserShowTest < ActionDispatch::IntegrationTest

  def setup
    @inactive_user  = users(:inactive)
    @activated_user = users(:archer)
  end

  test "should redirect when user not activated" do
    get user_path(@inactive_user)
    assert_response :redirect
    assert_redirected_to root_url
  end

  test "should display user when activated" do
    get user_path(@activated_user)
    assert_response :success
    assert_template 'users/show'
  end
end
```
【Power Apps】コレクションに含まれる要素の判定を行う

# はじめに
　Power Appsにて、普通のプログラミングのように配列内の要素をforeachでぶん回して判定処理をさせたいと思ったことがあるかと思います。（カンマで区切られた文字列に対して、それぞれの要素があるフォーマットに従っているか など・・・）
　が、悲しいことにPower Appsではforeachにあたる「ForAll」関数内では変数を更新する「Set」「UpdateContext」関数を利用することができません。
　「Collect」関数を用いて判定OK要素を格納するコレクションとNG要素を格納するコレクションを用意することで代替できます。気持ち悪いことこの上無いですが、仕方がないのでこうするしかありません。別の良い案をご存じの方居たらコメントください。

 # 実現方法
 以下のような画面で、「TextInput」にカンマ区切りで入力されたメールアドレスが正しいかを判定しています。ボタンのOnSelect()に以下の処理を入れて、カンマ区切りした値が正しいか正しくないかに応じて別のコレクションに格納します。

 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551355/f1079a59-f055-70b4-f923-734ec4496eaa.png)

```
Clear(ValidCollection);
Clear(NotValidCollection);
ForAll(
    Split(
        TextInput1.Text,
        ","
    ),
    If(
        IsMatch(
            Value,
            Match.Email
        ),
        Collect(
            ValidCollection,
            Value
        ),
        Collect(
            NotValidCollection,
            Value
        )
    )
)
```

以下のようにエラーメッセージ用ラベルも用意することでそれっぽいエラー判定ができるようになります。


![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551355/1170267f-33e6-84bb-1c3f-d276518a5a43.png)

```
If(
    CountRows(NotValidCollection) > 0,
    "エラーがあります"
)
```
【Power Apps】SharePointリストの参照列に対してキーワード検索する

データソースに対してキーワード検索を行う関数は「Search()」ですが、この関数はSharePointリストの参照列に対しては実行できません。（ゴミ）
出来ないくせに「Filter()」関数と「in」を組み合わせることで同じような動きを再現できます。

 ```
Filter(
    TestCollection,
    "example" in 'テストリスト:参照列1'.Value
)
 ```
【Power Apps】SharePointリストのユーザ型にOffice 365 Usersから取得したユーザを格納する際の注意点

# はじめに
Power Appsに用意されているデーターソースの内、テナント内のユーザー情報を取得できるデータソース「Office 365 Users」があります。このデータからユーザーを検索してSPリストのユーザ型列にデータを入れたい！となったとき、新規登録なら問題ありませんが更新する際は以下のような工夫が必要です。

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551355/a6eac3b3-3217-544c-4d1b-9a37afe78e44.png)

# 対処法
編集フォームのユーザ型カードのUpdate部に以下のようなコードを入れることで、Office 365 Usersから指定した値があればOffice 365 UsersのデータをSPリストのユーザ型に変換したデータを、なければ元のデータ（フォームに表示されているSPリストのユーザ型データ）を指定するコードです。
※冗長になるので、選択した365ユーザをWith句で変数化してます。

```
If(
  IsBlank(cmbO365Users.Selected.Mail),
  ThisItem.User,
  With(
    {_user365: cmbO365Users.Selected},
    {
        Claims: "i:0#.f|membership|" & Lower(_user365.Mail),
        Department: "",
        DisplayName: _user365.DisplayName,
        Email: _user365.Mail,
        JobTitle: ".",
        Picture: "."
    }
  )
)
```
SQL Serverで日付を加算

備忘録
```sql
update
	data
set
	Time = (
		SELECT
			FORMAT( DATEADD(month, 6, t2.Time), 'yyyy/MM/dd HH:mm:ss.fff')
		FROM
			data t2
		WHERE
			t2.Time = data.Time
	),
	TimeStr = (
		SELECT
			FORMAT( DATEADD(month, 6,CONVERT(datetime , stuff(stuff(stuff(stuff(data.TimeStr, 9, 0, ' '), 12, 0, ':'), 15, 0, ':'), 18, 0, '.'))), 'yyyyMMddHHmmssfff')
		FROM
			data t2
		WHERE
			t2.Time = data.Time
	)
```
Pandasで忘れがちな処理メモ

加筆修正していきます。
最近Pandas使ってませんが・・・

### Seriesから値を取り出す
column1がfooに一致したcolumn2の値を取り出す。

```python
df.query("column1 = 'foo'")["column2"].item()
```

### GroupByして上位n件を抽出
column1に対してGroubByし、column2の値が上位n件であるレコードのみ抽出する。

```python
sorted_df = df.sort_values(by="column2", ascending=False) # 降順
groupby_df = sorted_df.groupby("column1").head(n)
```
Azure AI Search(旧: Cognitive Search)のチャンク分割＋ベクトル化が簡単になったので試す！(1/2)

# はじめに
2023年11月Microsoft IgniteでAzure AI Search(旧：Cognitive Search)の大幅なアップデートがありました。Azure AI Searchでチャンキング＋ベクトル化を行うには、Azure OpenAI on your data経由で作ったり、公式が用意したPythonのデータ準備ツールなどを利用する必要がありました。今回、ようやくこの機能がプレビュー版としてAzure AI Searchに統合されたので使ってみたいと思います！

こちらが公式の記事となります。

https://learn.microsoft.com/en-us/azure/search/vector-search-integrated-vectorization

# 試してみる
Azure AI Searchのリソースにいくと「概要」に「データのインポートとベクター化」という項目が追加されました。クリックしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/7ac3f7dd-98a1-02bc-40e6-f83a3683ad67.png)

現状データソースは「Azure Blob Storage」もしくは「Azure Data Lake Storage Gen2」のみの対応のようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/e5d1e0cb-fb5a-6107-1e24-095d98307383.png)


データのフォーマットはPDFを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/61ea8cce-73c7-5029-e94f-a01f5521c35f.png)

Azure OpenAIのEmbeddingsモデルをあらかじめデプロイしておき、こちらで指定します。ここで言語アナライザーの指定ができないことに絶望します。。少しでも日本語の検索精度を上げたいので、セマンティックランカーを有効にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/35d57a7a-45f4-0da0-e037-03f63a256e21.png)

最後にプレフィックスを入力して、作成をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/515ec933-776b-f405-4d32-cca7cd767b56.png)

10秒ほどでインデックスが作成されていました。ドキュメント数に関しても、5件のドキュメントに対して、チャンク分割後20レコード作成されたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/ec9b11b9-ffef-5280-6da7-19b346b3766c.png)

検索を実行してみると確かにインデックスが作成されていることが確認できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/d08f5dfe-30e6-9b37-75e8-8678a1a22819.png)

言語アナライザーはデフォルトの英語(泣)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/a0c01fdd-4221-e119-ae9b-347f8a2ea7c5.png)

## 23年12月1日追記
言語アナライザーを日本語にする方法について解説しました！簡単にできるので、希望を捨てずお試しください！

https://qiita.com/tmiyata25/items/3e9644b4e8346c13f619

# 考察
今回GUIからチャンク分割＋ベクトル化ができるようになったのでとても便利になりました。個人的に今回の大きなアップデートは1ドキュメントに対して複数レコードをインデックスとして登録できるようになった事です。今までは1ドキュメントに対して原則1レコードしか登録できませんでした。従って、インデクサーを2回使って裏技みたいな形でチャンク分割＋ベクトル化を行っていました。

https://qiita.com/tmiyata25/items/875f563ba7a91f3da823

それが、今回「Index projections」機能の登場により、チャンキング後のテキスト情報を複数のレコードにマッピングすることが可能になりました。また、「Azure OpenAI Embedding skill」がネイティブにサポートされたことによりカスタムスキルを自分で作成する必要がなくなりました。「Text Split skill」もチャンク分割ようにアップデートされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/ce8ab803-33a2-e891-ea92-0bb0c6442be6.png)

https://learn.microsoft.com/en-us/azure/search/whats-new

これらのスキルセットを上手く設定してあげれば、言語アナライザー日本語＋チャンク分割＋ベクトル化を比較的簡単に実現することが可能です。こちらのやり方に関しては次回の記事で紹介したいと思います！

->23年12月1日に記事書きました！

https://qiita.com/tmiyata25/items/3e9644b4e8346c13f619
Vue + Typescript環境でeslint --initで生成されたコンフィグが動かない時

この記事は [ここのえ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/99no_exit) Day 12 の記事です。

# 要約

- `eslint --init` に設定を全部任せるのはやめておいたほうが良い
- ネットの知見を参考にして自分で書いた方がいい


# eslint --initで生成されたコンフィグが動かない

まさにこのAdvent Calendarを書いていた時の事だったのですが、どうも `eslint --init` した時にVue向けに設定を選択していくと、エラーになってしまいました。

原因の究明と、解決策について示します。

# 再現までの手順

`Vue` + `Vite` + `Typescript` + `ESLint` の環境を整えます。
`yarn`を使います。

`ESLint`のバージョンは `v8.53.0` です。

```bash
# Vite + Vue + Typescript
$ yarn create vite
✔ Project name: … eslint-test
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript

$ cd eslint-test
$ yarn
$ yarn dev     # Viteの起動確認

# ESLint
$ yarn add -D eslint
$ yarn eslint --init

? How would you like to use ESLint? …
▸ To check syntax, find problems, and enforce code style

? What type of modules does your project use? …
▸ JavaScript modules (import/export)

? Which framework does your project use? …
▸ Vue.js

? Does your project use TypeScript? 
‣ Yes

? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser

? How would you like to define a style for your project? …
▸ Use a popular style guide

? Which style guide do you want to follow? …
▸ Standard: https://github.com/standard/eslint-config-standard-with-typescript

? What format do you want your config file to be in? …
▸ JavaScript

? Would you like to install them now? 
‣ Yes

? Which package manager do you want to use? …
▸ yarn
```

eslintを走らせると、こんなエラーが出ます。

> Error: Error while loading rule '@typescript-eslint/dot-notation': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.

言われた通り、`parserOptions.project` を追加して再度ESLintを走らせます。

```.eslintrc.cjs
"parserOptions": {
  ...
  project: ['./tsconfig.json']
},
```

> Error: Error while loading rule '@typescript-eslint/dot- ...

何の成果も得られませんでした。どうも原因は他の所にありそうです。

# 調査

試しにこんなスクリプトを作って、ESLintを走らせてみます。

```src/test.ts
const str: string = "test string"
console.log(str)
```

```bash
/home/username/eslint-test/src/test.ts
  1:10  error  Parsing error: Unexpected token :

✖ 1 problem (1 error, 0 warnings)
```

もうめちゃくちゃです。Typescriptの構文すら理解できていません。
どうやらParserがまともに動いてなさそうです。

# 解決法

実はよく見てみると、`parser`がそもそも指定されていません……
`@typescript-eslint/parser`を追加すると解決します。

```.eslintrc.cjs
...

"parserOptions": {
  "ecmaVersion": "latest",
  "sourceType": "module",
  parser: "@typescript-eslint/parser"
},

...
```

# まとめ

この問題について、確実に言い切れはしませんが `eslint --init` で `Vue` を選択した時の特有の問題 だと思われます。つい数日前Nodeのバックエンド向けに `eslint --init` した時はこの問題に引っ掛かりませんでした。

普段はちゃんとESLintの設定をしたいので `eslint --init` は使っておらず、気が付きませんでした。記事書く用のテスト環境だし適当でいいや、と思ったら見事にやられてしまいましたね…

落ちてくるのも `plugin:vue/vue3-essential` なので、ちゃんと環境を整えるのなら `plugin:vue/vue3-recommended` の方がいいと思います。横着はしないほうがいいですね。
typescriptの可変長引数は0個を許容している

## typescriptにおける可変長引数
- 可変長引数とは、長さの決まっていない関数の引数のことで、typescriptでは残余引数(rest parameter)とも呼ばれる
- **0個を許容している**


### 例） 関数exampleの引数hogeは、可変長引数
```typescript
function example (...hoges[]: Hoge) {
    for( const hoge of hoges ) {
        // 処理を書く
    }
    return result;
}
```

### 例2） hogeが0個だと都合が悪いときは、firstHogeを引数に用意する
```typescript
function example (firstHoge: Hoge, ...hoges[]: Hoge) {
    let result = firstHoge;
    for( const hoge of hoges ) {
        result = result + hoge;
    }
    return result;
}
```


## 参考記事
https://typescriptbook.jp/reference/functions/rest-parameters

## この記事は
実務で教えていただいたことに加えて、記事を読んで勉強したことの覚書です。
あくまでtypescriptの挙動を記載しているだけであり、typescript以外の言語での可変長引数の扱いについては勉強不足のため比較できていません。
rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その５）画像の学習

[rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その４）](https://qiita.com/rex0220/items/c56084cdaccdd749800d)の続きです。
画像の学習を試してみます。

# 概要

画像ファイルも扱えそうなので、プラグイン設定画面をアップロードして試してみます。
.doc ファイルと .png ファイルで試してみました。
.doc ファイルだけでは、動作が不安定になり、 .png ファイルを追加すると応答内容が安定しました。

![2023-11-16_08h47_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2e3606ca-b023-246f-e4c8-9f66a93f75b3.png)


# 画像学習前

以前に学習させた Qiita のページには、プラグイン設定画面もありますが、それだけではダメなようです。

![2023-11-16_08h20_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/772d8c6c-fde4-4591-00c2-c5bc56b6cff0.png)

# .doc ファイルをアップロード

.doc ファイル内に、設定画面の画像を入れています。

![2023-11-16_08h48_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/76ed8e77-3571-8fcf-62c8-e04deb88b629.png)

# .doc ファイル学習後の応答
「プラグインの設定画面の画像をみせて」の問合せを何回か行うと、エラーや画像自体の情報を表示したり、画像を表示したりと動作が不安定となります。

- 応答例1
![2023-11-16_08h19_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c12ce371-c145-98e7-e63f-bed1ad0e9578.png)

- 応答例2
![2023-11-16_08h54_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c05e984d-a110-1dd1-f896-17f95d963262.png)

- 応答例3
![2023-11-16_08h56_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f8d5482e-303a-19ae-4129-fc68cb4d21fc.png)

# .png ファイルをアップロード
「計算式プラグインの設定画面.png」をアップロード
![計算式プラグインの設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/39edba76-3bd7-e0dd-1d82-817f4290d74e.png)

# .png ファイル学習後の応答
「プラグインの設定画面の画像をみせて」の問合せを何回か行っても、画像付きで .doc の説明を入れて応答してくれる。

![2023-11-16_08h59_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ca12b563-3bcc-8696-d232-6eddf6c1eb25.png)

# 使用上限オーバー

画像処理は、負荷が高いようで使用上限オーバーのメッセージが表示されて、利用できなくなった。
GPT Builder も利用できません。

![2023-11-16_09h22_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1e76780c-007c-83c6-55bb-b731be47310f.png)

![2023-11-16_09h25_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/59955050-22a9-166d-b3f2-c30f1dde25c5.png)

# まとめ

画像の扱いには、なんかコツが必要で、いろいろ試してみる必要があります。
ただ画像の処理は、負荷が高いようで使用上限オーバーになりやすいので気を付けましょう。
DVCの指南書

[公式ドキュメント](dvc.org/doc)

## 一番簡単な使い方

- `dvc.yaml`を編集
- `dvc repro`で再生成
- `dvc push`でリモートにアップロード
- `dvc pull`でリモートのダウンロード

## よく使う順

- repro <プロセス名>
    - dvc.yamlに登録したデータ生成プロセスを実行する。ただし、生成プロセスが依存するソースのハッシュに変化がなければ無視される
    - `--dry`で実行はせず、何が実行される予定かの確認だけできる。まずはこれを付けて使うと便利(dvc statusも似た感じ)
- push
    - リモートストレージにdvcのキャッシュを送る。バックアップのほか、他ユーザが自分の生成したデータをダウンロードできるようになる
- pull
    - リモートストレージから他ユーザーがpushした結果を取得する
- dag
    - プロセスの可視化。見づらい
- checkout
    - 現在のgit commitの状態で生成されていたデータに更新する
- add
    - 外部データの追加。ハッシュ値を計算して<file_name>.dvcとして保存する
- remove    
    - addしたデータを削除・変更したい場合。.dvcと.gitignoreも変更する
- gc
    - ローカルやリモートのキャッシュを削除する
- init
    - 最初に一回だけ行う。.dvcを生成する
- remote
    - `dvc remote add -d <remote_name> /path/to/remote` でリモートストレージを指定する。(-dでデフォルトに指定)。.dvc/configに保存される
    - パスだけでなく、SSH/S3など多様な保存先が指定可能
コンストラクターについて

# コンストラクターの書き方
## オブジェクトを生成する関数はコンストラクターと呼ばれる
通常の関数は、処理部分を何も書かずに、**new演算子で実行**すると、空のオブジェクトを返却する。

```javascript
function hoge(){};
let obj = new hoge();
```
この関数内での、thisは、返却されるオブジェクトを表し、関数定義部分で、プロパティを定義できる。
```javascript
function hoge(name){

    this.name = name;
    
}

let a = new hoge("taro");
console.log(a);

```

一例として、ベクトルを定義するコンストラクターを書く。
```javascript
function Vector(x,y){

  this.x = x;
  this.y = y;

}
```
これは、ベクトルのx成分と、y成分を与えるコードだ。
```javascript

let v = new Vector(1,1);
console.log(v)

```

このようにして、javascriptでは簡単に、必要なオブジェクトを定義できる。
エンジニアは、考える力とチャレンジする力を磨くべき！

現代社会は、情報の民主化によって大きく変化しました。インターネットやスマートフォンの普及により、誰もが簡単に膨大な量の情報にアクセスできるようになりました。これは、これまで特定の人にしか与えられていなかった情報へのアクセス権を、すべての人に平等に与える画期的な変化です。

しかし、情報の民主化は、単に情報へのアクセスが容易になっただけではありません。それにより、人々は自分で情報を取捨選択し、自らの判断で行動する必要性が高まりました。これは、個人の思考力と判断力の重要性を高めるものです。

特に、エンジニアにとって、考える力とチャレンジする力は、今後ますます重要になるスキルです。エンジニアは、常に新しい技術や知識を学び、新しいことに挑戦していく必要があります。そのためには、自らの思考力と判断力を磨き、自立した存在になることが不可欠です。

本記事では、情報の民主化がもたらす社会の変化と、エンジニアが考える力とチャレンジする力を磨くために必要なことについて、解説します。

# イントロダクション
- 情報アクセスの民主化とその背景
- ネットとスマホの普及による社会の変化
- AIの普及によるさらなる社会の変化

# 情報アクセスの変化
- 昔の情報アクセス: 書籍、新聞など限定された情報源
- 現代の情報アクセス: インターネットとスマートフォンによる広範なアクセス
- 情報の偏りと民主化の影響

昔は、書籍や新聞等がメインで特定の人しか情報を持ってなく、偏った人による社会形成がありました。
ネットとスマホの普及で全ての人が同じ情報にアクセスでき、自らジャッジを行える時代、これが民主化の時代です。

# 自由と個人の責任
- 民主化がもたらす自由の概念
- 個人の判断力と情報の取捨選択
- 自らの道を選択し、未来を決定する能力

民主化とは自由。

自由の時代は、一層、個人個人の考える力が必要とされる時代になります。
自由なので自ら考えて情報を取捨選択し、道を選択して未来を決める事が出来ます。

# AIの役割と限界
- AIの普及と自動的な情報収集
- 生成AIの機能と限界: 過去データを基にした情報生成
- 人間とAIの判断力: 100%正確な答えを出すことの困難性

更にAIの普及で自動的に情報収集が行なえます。生成AIは、様々な過去データを収集し最適な確からしき情報を並べて、文章やソースコード等を生成します。
そのAIのアウトプットを使うのは人間です。人間も100%の答えを出すことは苦手でしたが、AIも同じく100%の答えを出す事は苦手です。
最後は、自分で判断する必要があります。

# 持続的なチャレンジの重要性
- 完璧な方法の不在と多様な試行の価値
- ピカソの事例: 1万点以上の作品制作と独特なスタイルの確立
- VUCAの時代は、変数が多すぎる
- 継続的な思考とチャレンジの重要性

情報の民主化とAIの普及により、人々は自分で情報を取捨選択し、自らの判断で行動する必要性が高まりました。これは、個人の思考力と判断力の重要性を高めるものです。

特に、エンジニアにとって、考える力とチャレンジする力は、今後ますます重要になるスキルです。エンジニアは、常に新しい技術や知識を学び、新しいことに挑戦していく必要があります。そのためには、自らの思考力と判断力を磨き、自立した存在になることが不可欠です。

ピカソは、1万点以上の作品を制作し、独特な抽象画を確立した芸術家です。ピカソは、常に新しい表現方法を追求し、失敗を恐れずにチャレンジし続けました。その結果、独特なスタイルを確立し、世界的な芸術家になりました。

エンジニアにとっても、ピカソのような持続的なチャレンジ精神が重要です。完璧な方法は存在しません。時には、100点満点の手法はないかもしれません。しかし、30点の手法を数多く試すことで、100点満点に近づくことができます。
更にの今VUCA時代では、考える必要がある変数が多すぎるのです。この多い変数をコントロールするのは、非常に難しく、フォーカスを絞りながら変数を減らし、色々な施策を繰り返す事が必要となります。

# 結論
- 今後の時代における重要なスキルとしての自己判断とチャレンジ精神
- 個々の責任と社会への影響

しっかり考え、チャレンジする。これを何度も繰り返す。
これからの時代は、これがとても重要なスキルとなります

# 最後に
エンジニアの皆さん、エンジニア未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
AI-102試験対策のまとめ「インターネットから切断されたコンテナにおけるAzure AIサービスのAPI利用」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
### インターネットから切断されたコンテナにおけるAzure AIサービスのAPI利用
* 切断されたコンテナを使用することで、独自の環境でAzure AIサービスのAPIを実行可能  
⇒セキュリティとデータガバナンスの固有の要件に対応可能
* 現時点では下記のコンテナをこの方法で実行可能
    - 音声テキスト変換
    - カスタム音声テキスト変換
    - ニューラルテキスト読み上げ
    - テキスト翻訳(標準)
    - Azure AI Language
        - 感情分析
        - キーフレーズ抽出
        - 言語検出
        - 概要
    - Azure AI Vision(読み取り)
    - Document Intelligence

1. インターネットから切断されたオンプレミスのKubernetesクラスタをプロビジョニング
1. 切断された環境でコンテナへのアクセスを要求するために、要求フォームに記入して送信
1. 承認後、Microsoft Container Registry(MCR)からイメージをプル
1. コンテナを実行し、対象リソースの「エンドポイントURL(Billing)」と「APIキー」を指定

* 参考
    - https://learn.microsoft.com/ja-jp/azure/ai-services/containers/disconnected-containers


## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「Speech SDKでMicrosoft Entra認証を使用する方法」**

https://qiita.com/fsd-jume/items/53137d655cc0424ba6a0

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

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d
FizzBuzzEnterpriseEditionが何をやっているのか超ざっくりと


## FizzBuzzEnterpriseEdition

https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition

## 大体こんな感じ（多分）

実際はFactoryだとかがあったり（水増し用の）クラス、インターフェースが大量に作られているのでかなりカオス

```java
import java.util.ArrayList;
import java.util.List;

interface IsEvenlyDivisibleStrategy {
    boolean isEvenlyDivisible(int i);
}

class FizzStrategy implements IsEvenlyDivisibleStrategy {
    public boolean isEvenlyDivisible(int i) {
        return i % 3 == 0;
    }
}

class BuzzStrategy implements IsEvenlyDivisibleStrategy {
    public boolean isEvenlyDivisible(int i) {
        return i % 5 == 0;
    }
}

class NoFizzNoBuzzStrategy implements IsEvenlyDivisibleStrategy {
    public boolean isEvenlyDivisible(int i) {
        return i % 3 != 0 && i % 5 != 0;
    }
}

interface DataPrinter {
    public void printValue(Object value);
}

class FizzStringPrinter implements DataPrinter {
    public void printValue(Object value) {
        System.out.print("Fizz");
    }
}

class BuzzStringPrinter implements DataPrinter {
    public void printValue(Object value) {
        System.out.print("Buzz");
    }
}

class IntegerPrinter implements DataPrinter {
    public void printValue(Object value) {
        System.out.print(value);
    }
}

class FizzBuzzOutputGenerationContext {
    public IsEvenlyDivisibleStrategy strategy;
    public DataPrinter printer;
    public FizzBuzzOutputGenerationContext(IsEvenlyDivisibleStrategy strategy, DataPrinter printer) {
		this.strategy = strategy;
		this.printer = printer;
	}
}

public class Main {
    public static void main(String[] args) {
        var contexts = new ArrayList<FizzBuzzOutputGenerationContext>();
        contexts.add(new FizzBuzzOutputGenerationContext(new FizzStrategy(), new FizzStringPrinter()));
        contexts.add(new FizzBuzzOutputGenerationContext(new BuzzStrategy(), new BuzzStringPrinter()));
        contexts.add(new FizzBuzzOutputGenerationContext(new NoFizzNoBuzzStrategy(), new IntegerPrinter()));
        fizzBuzz(contexts);
    }

    private static void fizzBuzz(List<FizzBuzzOutputGenerationContext> contexts) {
        for (int i = 1; i <= 100; i++) {
            for (FizzBuzzOutputGenerationContext context : contexts) {
                if (context.strategy.isEvenlyDivisible(i)) {
                    context.printer.printValue(i);
                }
            }
            System.out.println();
        }
    }
}
```

## チラ裏

Javaの開発環境がローカルにないのでpaiza.ioでコーディングしました。
sklearn.SequentialFeatureSelector内でGroupKFoldを行う

# SequentialFeatureSelector内でGroupKFoldを行う

パラメータの"cv"には、list()化したスプリットを入れましょう。
"An iterable yielding (train, test) splits as arrays of indices."

例：
from sklearn.model_selection import GroupKFold
gkf = GroupKFold(n_splits=3)
gkf_split = list(gkf.split(X, y, groups=groups))
selector = SequentialFeatureSelector(model, n_features_to_select=nb_feat, direction=direction, scoring="r2", cv=gkf_split)
selector.fit(X, y)

# 参考
sklearn.feature_selection.SequentialFeatureSelectorの公式は↓
https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SequentialFeatureSelector.html#sklearn.feature_selection.SequentialFeatureSelector.set_params