OmniAICreator/Qiita-1.07M huggingface dataset:
How to use a dot env file when building the container with docker-compose

# docker-composeでコンテナを構築する際に.envファイルを使用する方法

`docker-compose build`で`git config --global user.email`とか`name`とかを指定したいの。でも個人情報を`Dockerfile`に書くのは死んでも嫌！

そうだ！`.env`を使えばなんとかなるんでは……？

で、こうなりました。

```docker-compose.yml
version: '3'

services:
  web:
    build:
      context: .

      args:
        - GIT_USER_EMAIL=$GIT_USER_EMAIL # ココ
        - GIT_USER_NAME=$GIT_USER_NAME   # ココ

    volumes:
      - ./src:/app

    ports:
      - "80:8080"
```

```Dockerfile
FROM bash

WORKDIR /app

ARG GIT_USER_EMAIL
ARG GIT_USER_NAME

RUN \
  apk add git &&\
  git config --global user.email "${GIT_USER_EMAIL}" && \
  git config --global user.name "${GIT_USER_NAME}"
```

```.env
GIT_USER_EMAIL="foobar@example.com"
GIT_USER_NAME="Foo Bar"
```


`Dockerfile`内で`ARG`として変数を宣言しなければならないのが盲点でした。

なお、`docker-compose.yml`で以下のように変数を波カッコで囲むと動作しないようです。

```
- GIT_USER_EMAIL=${GIT_USER_EMAIL}
- GIT_USER_NAME=${GIT_USER_NAME}
```

##### 参考にしたページ

- [environment variables - Multiple Docker build args from docker-compose .env file - Stack Overflow](https://stackoverflow.com/questions/47451060/multiple-docker-build-args-from-docker-compose-env-file)
- [Environment variables in Compose | Docker Documentation](https://docs.docker.com/compose/environment-variables/)
「バグをたくさん見つける人の頭の中」を言語化してみた

# バグ発見にはセンスがあるらしい？
*「よくそのバグ見つけたね！」*
と言われる人が周囲にいませんか？

実は私も言われます

ただ、「なんで見つけられるの？と言われても...」と思うくらい無自覚だったりします
そんな自分を知るためにも今回は、**バグを見つけるセンスの言語化**に取り組んでみようと思います

# 注意書き
大前提、体系化も裏付けもできておりません
本来の品質保証やテスティングは、センスでバグを見つける活動ではないとも考えています
よくバグを見つける人の頭はこうなっているのかもな、という一例としてお読みください

また、この記事では用語の解説は行いません
気になる言葉があればぜひ調べてみてください！

では、「バグをたくさん見つける人の頭の中」を解体していきましょう！

# 分類1: 視点を広げる
## ✅ 無数のユーザーになりきってみる
- ユーザー面: 中高生だったら？ビジネスマンだったら？高齢者だったら？日本語話せなかったら？操作者が複数人数いたら？
- 心理面: どんな気分、どんな欲求、仕様理解度は？、高揚してる場合は？、最悪の心理の場合は？
- 状況面: どんな使用頻度、どんな時間帯、1人か複数人数か？、並列操作してる？
- 身体面: 視力、障がい、けが、ネイル、どんな姿勢、疲労困憊、飲酒状態
- 時系列: どんな流れで？、どれくらいの周期で？、操作は断続的？連続的？、操作途中に時差が変わったら？
- 環境面: どんな場所、どんな天気、ネット接続状態、機種、OS、ブラウザ、バージョン
- 制限面: セキュリティ規制があったら？、APIだけ操作してたら？、海外から操作、VPN...etc
- 開発チームメンバーの不安: エンジニア、PdM、デザイナーetcに、不安があるか聞いて試す

## ✅ 全部自分で理解するまで信じない・納得しない
- 仕様書・テストケース・説明書を信じない: 見たもの、触れたものが全て
- 作った人を信じない: すごいエンジニアが作っていてもバグは出る(人は信頼し、システムは信頼しない)
- 自分を信じない: 全てを理解し切った気持ちにならない。分からないことを探し続ける
- 労力を信じない: バグを探した時間や労力に関わらず、気になる部分があるならいくらでも操作する

## ✅ プログラムの欠陥(Defect)だけがバグではないという視点
- 仕様に定義できていない挙動を探す
- 仕様通りでもユーザーが困る挙動を探す
- こうだったらもっといいな、という視点を探す

# 分類2: テスト技法で観点を広げる
## ✅ 目的からテストを描く
- 開発で実現したいことを保証するためにどんなテストが必要か考える
- 開発で実現したいことを阻害する要因を見つけていく
- 必要なテストを明らかにしたら、全体像を俯瞰して漏れがないか確認する

## ✅ インプット・アウトプットの種類を考える
- 正常系、準正常系、異常系それぞれにどんなパターンがあるか考える
- 挙動に冪等性がない場合は、インプットとアウトプットの変化幅の限界を試す
- 同値分割法・境界値分析法で仕様が正確に実装されているか試す
- 準正常系ではじくことができず、予期せぬエラーや文字化けになる入力値がないか探す

## ✅ ソフトウェアの状態や制御パスを考え尽くす
- ソフトウェアがイベントやデータにより取りうるパターンを全て網羅する(状態遷移的思考)
- 状態の掛け合わせをひたすら試し、設計時点で想定していなかった状態を作れないか試す
- 存在しない状態を実現できないか試す
- 状態遷移をすごい速さ・並列実行で切り替える
- 制御パスの流れや掛け合わせの中に想定しないパターンがないか試す
- 想定していないデータパターン・データフローが発生しないか探す

## ✅ 操作して得られた情報をたどってみる(探索テスト的思考)
- テストケースを事前に決めないで操作してみる
- 操作中に感じた違和感を解消し続けてみる

## ✅ 将来のリスクを想像する(品質特性の観点)
- 環境変化: ユーザーが急に増えたら？海外展開したら？
- インシデントが起きたとしたら？インシデントが止まらなかったとしたら？
- インシデントの原因が分からなかったとしたら？
- 移植が必要になったとしたら？
- その機能をクローズすることになったら？
- 内外から攻撃を受けたとしたら？
- またその機能をテストする必要が出てきたら、テストしやすいか？
- その他の品質特性を眺めながら、紐づくリスクがないか考える

## ✅ 経験からリスクの傾向を考える
- リスクの大小を定義する: リスクが大きい部分から絞って探しにいく(リスクベースドテスト的思考)
- 過去の傾向: 過去のバグやインシデントの傾向・経験から、水平的に発生するものがないか考える
- 不確実性の高い機能や領域がないか考える
- バグが偏在していそうな機能・領域がないか考える
- 改修の途中でデグレする(しそうな)観点がないか考える
- 起こしたいバグをどうにか再現できないか試す
- 最悪のケースが実現してしまう方法がないか探す
- どのプロセスでどんなバグがよく混入しているか調べる・考える

# 分類3: 技術的知識がある・内側がわかる
## ✅ 機能面でのリスクがわかる
- バックエンド、フロントエンド、繋ぎこみなどの内部構造からリスクがないか考える
- アーキテクチャ、DBなどのインフラ面にリスクがないか考える
- 外部サービスとの連携や、サービスダウン時に問題がないか考える
- ユーザーの操作だけでなく、外部システムや定期実行処理がバグを起こさないか考える

## ✅ 非機能面でのリスクがわかる
- セキュリティ面: システムや外部サービスにリスクがないかわかる
- 性能面: 操作に対するレスポンスタイムや表示時間が適切か
- 負荷面: 大量のトラフィックや大きな処理が走るリクエストにリスクがないか考える
- 非機能要件の品質特性を眺めながら、紐づくリスクがないか考える

## ✅ 専門知識がわかる
- ドメイン特有の専門知識: 業界特性、ユーザー特性、商習慣など
- 技術的な専門知識: 認証技術、機械学習、外部サービスAPIなど

# おわりに
何十項目と書き出してみましたが、開発には時間や工数の制限があります
全ての項目を完璧に考えられるわけではありません
常にデリバリと品質の両立と戦うことになります

となると、得られた情報に対して常に観点を使い分けることが重要です
- 価値を届けるためにはどんなバグを見つけるべきなのか
- どこまで保証できればリリースできると言えるのか
といった観点を通して、皆さんが良いバグ発見ライフを過ごせたら幸いです


この記事は[モチベーションクラウドシリーズ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mcs)の投稿です
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect date value: '1988' for column 'created_at' at row 1

SQLが悪そうなので、

試したこと

SQLの　「created_at　」のタイプを「date」　→「timestamp」へ変更

「date」　とは
”1000-01-01 00:00:00″から”9999-12-31 23:59:59″
・年、月、日、時、分、秒を持ちます。ミリ秒がありません。
・文字列をDate型にするには、TO_DATE関数を使用します。
・Date型を文字列にするには、TO_CHAR関数を使用します。


「timestamp」とは
・”1970-01-01 00:00:01″UTC から”2038-01-19 03:14:07″UTC
・年、月、日、時、分、秒、秒の小数部を持ちます。
・文字列をTIMESTAMP型にするには、TO_TIMESTAMP関数を使用します。
・TIMESTAMP型を文字列にするには、TO_CHAR関数を使用します。
・TIMESTAMP(6)の6は、小数部の桁を意味します。



画面上
mysqlのタイプを「date」にすると「　2000-04-18　」となります

mysqlのタイプを「timestamp」にすると「　1988-04-18 00:00:00　」となります
solidityで存在しないメソッドをcallした時のエラーは2パターンある！

これは[no plan inc.の Advent Calendar 2022](https://qiita.com/advent-calendar/2022/noplan_inc)の13日目の記事です。

コントラクトに存在しないメソッドをcallしようとした時にノードが返すエラーメッセージは実は二種類あります！

* `invalid opcode: INVALID`
* `execution reverted`

前者は0.4系、後者は0.6系以降で使われているようです。

詳しい境目は分りませんでした！
いかがでしたか？

# no plan株式会社について
- no plan株式会社は、ブロックチェーン技術、Webサイト開発、ネイティブアプリ開発、チーム育成、などWebサービス全般の開発から運用や教育、支援などを行っています。よくわからない、ふわふわしたノープラン状態でも大丈夫！ご一緒にプランを立てていきましょう！
- [no plan株式会社について](https://noplan-inc.com)
- [no plan株式会社 | ブロックチェーン実績](https://noplan-inc.com/blockchain)
- [no plan株式会社 | ブログ一覧](https://noplan-inc.com/blog)
インスタグラムの投稿に自動コメント

初投稿です。

インスタグラムのPOSTに対してコメント（宣伝文）を書き込むアルバイト。
自動化しないと、あまりにも給料が安すぎて。

というわけで、ググって調べてみると、サンプルコードみたいなのはあまりいいのが見つからなかったけど、大体のやり方は把握できた。

SELENIUMという、PYTHONから操作できるブラウザみたいなのを立ち上げて、それに対してあれこれ命令する。ブラウザ立ち上げ、ログイン、業者からもらったアカウントリストの上から順にアクセスして、投稿があればその投稿ページに行き、コメントする。そして次のアカウントへ。

投稿ページに行くまではスムーズに進む、が、投稿を書き込むところで詰まった。

find_elementで投稿書き込み用のテキストエリアを探すのだけれど、「そんなものは無い」とエラーを返される。

いや、無いはずない。あるよ！

探す方法を色々変えてみたけれど、結局どれも効果なくて。

これで解決。
```
while True:
    try:
        elem = driver.find_element(By.XPATH,full_xpath)
        elem.send_keys(com)
        print('comment wrote')
        time.sleep(1)
        break
    except:
        print('comment : failed to write')
        time.sleep(1)
        pass
```

つまり、そこに有るんだから、何度でも探しなさい、というこちらの信念が通った形。

実際は、一回目は必ずエラーになって、二回目でちゃんとコメント成功する。

なぜだろう。。。なぜ一回で成功してくれないのか。ブラウザの読み込み時間は十分に取っているはず。
そしてなぜ二回目は必ず成功するのか。そんな微妙なタイミングを求められているのですか。ブラウザの中では一体何が蠢いているのでしょうか。

わかる方教えてください。
ブラウザしか使わないから低スペックのパソコンで十分

といわれた時代があったなぁー。
いまは最重量級のソフトウェアのひとつがウェブブラウザ。
ということで、「ブラウザしか使わないから低スペックで！」っていう年配の方に出会って、ココロの中で
`「ちがう、ちがう、そうじゃ、そうじゃなーいー♪」`
と念仏の様に唱えて我慢する今日このごろです。
Rubyで数字を1行になるまで掛け算する

# 前提
引数のintegerの値を一桁になるまで掛け続けて、何回掛け算を行ったかを返り値にする。

```
ex
39 --> 3 (because 3*9 = 27, 2*7 = 14, 1*4 = 4 and 4 has only one digit)
```


# 判定メソッド
```ruby
def persistence(number)
  count = 0

  while number > 9 do
    num = 1
    number.to_s.split('').each do |i|
      num = num * i.to_i
    end

    number = num
    count += 1
  end

  count
end
```

```ruby
def persistence(n)
  k = 0
   while n > 9 do
    n = n.to_s.split(//).map{|x| x.to_i}.inject(:*)
    k+=1
   end
  k 
end
```

```ruby
def persistence(n)
  n < 10 ? 0 : 1 + persistence(n.to_s.chars.map(&:to_i).reduce(:*))
end
```
チェインされないコードを無理矢理チェインさせる方法

<h1>
チェインされないコードを無理矢理チェインさせる方法
</h1>

最近ラムダ式やチェインの為に自身を返すコードが流行となっている。

その中で自身を返さない文があると、チェインや三項演算子が使えない。

その場合に無理矢理自身を返すようにする方法

先に完成形
````完成形
const name = 'hello taro';
const address = 'tokyo';
const age = [ 1900, 2000 ];

console.log(
    { 'name' : name, 'address' : address, ...age
        .reduce((a, c) => !a ? { startAge : c } : (() => { a['endAge'] = c; return a; }).call(), null)
    }
);
````

このコードで問題なのが、
````
a['endAge'] = c; return a;
````
の部分

aを返したいのだが、a['endAge'] = cの部分でaを返してくれないのでchainできない。

その為aを返すように明示的に指定しないといけない。
しかし2文にすると、{}で囲まないと行けなくなる。

しかし一部を{}で囲むと、全部を{}で囲みreturn文が必要になる。

```冗長文
.reduce((a, c) => {
    if (!a) {
        return { startAge : c };
    } else {
        a['endAge'] = c;
        return a;
    }
});
````

処理内容自体は単純なので、すべて{}とreturnを付けると、なんかイヤだ。

すると、次に考えるのは
「匿名関数で囲めば出来るのではないか」

````匿名関数にした場合
.reduce((a, c) => !a ? { startAge : c } : function() { a['endAge'] = c; return a; }, null);
````

「匿名関数ではfunction文字が邪魔なのでラムダ式にする」
この考え方で、コードを組むとこのようになる。

````ラムダ式
.reduce((a, c) => !a ? { startAge : c } : () => { a['endAge'] = c; return a; }, null);
````

ここまで短くなると「return」文字でさえ邪魔だが、これはどうしようもない。(よね?)
これで「解決」と思いきや、この文は正常に動作しない。

なぜなら、!aの時のreturnは、aではなく、
````
() => { a['endAge'] = c; return a; }
````
というfunctionがreturnになってしまうためだ。
functionそのものではなくfunctionの結果が欲しいのだ。

なにで発見したのか忘れてしまったが、functionの結果を返すようにするには、

````
(...).call()
````
で更に囲むと実現できる。
これで正しく動作する。

改めて、完成形の文は以下のようになる。

````
.reduce((a, c) => !a ? { startAge : c } : (() => { a['endAge'] = c; return a; }).call(), null);
````

まあ、あまりやりすぎると1行のコードが長くなり醜くなるので、
その辺は臨機応変に。

動作コードはこちら
https://paiza.io/projects/mzd7qmHD-y34IXNglb10Ow
VScodeでGoのデバッグを行う際にエラーが発生した

## 概要
起動したいファイルを指定してVScodeからデバッグを実行すると以下のエラーが発生した。

```terminal
Failed to launch: could not launch process: can not run under Rosetta, check that the installed build of Go is right for your CPU architecture
```

備忘録として解決方法を投稿する。

## 環境
■ PC
macOS Monterey
バージョン 12.5.1
■ チップ
Apple M1 Pro
■ CPUアーキテクチャ
```
e2e % uname -m
arm64
```

## 原因
自身のPCのCPUアーキテクチャが`arm64`にも関わらず、[Goの公式](https://go.dev/dl/)よりインストールしたファイルが`amd64`であっためエラーになっていた。

```
Go version
go version go1.19.3 darwin/amd64
```

よって、現在のGoを削除して、`arm64`のファイルを再度ダウンロードした。

## 解決手順
Goを削除する。
```
% sudo rm -rf /etc/paths.d/go
% rm -fr /Users/[各々のユーザー名]/go
```

[Goの公式](https://go.dev/dl/)より`arm64`のファイルをダウンロードする。
```
% go version
go version go1.19.4 darwin/arm64
```

再度vscodeでデバックを行うと成功した。

## 環境変数を読み込まない
`.envrc`ファイルを使用して環境変数を読み込んでいたが、VScodeからデバックを実行すると環境変数を参照しない現象が起きた。

`.vscode/launch.json`ファイルに環境変数を追加することで解決した。

```.vscode/launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid: 830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Package",
            "type": "go",
            "request": "launch",
            "mode": "auto",
            "program": "${fileDirname}",
            // 追加
            "env": {
                "ENV": "local",
            },
        }
    ]
}
```

以上の設定でVScodeからGoのコードをデバッグすることができた。
ViteでFirebaseのGoogle認証したらunauthorized-domainでエラーになる

## 現象

Vite（3.0以降）、かつ、Node.js（17未満）の環境で開発サーバを起動し、
Firebase AuthenticationのGoogle認証を実行したら以下のエラーが発生します。

```
FirebaseError: Firebase: Error (auth/unauthorized-domain).
    at createErrorInternal (assert.ts:136:55)
    at _fail (assert.ts:65:9)
    at _validateOrigin (validate_origin.ts:46:3)
```

## 原因

Vite（3.0以降）、かつ、Node.js（17未満）の場合、
開発サーバのホストが`localhost`ではなく`127.0.0.1`で起動されるようになったことが原因です。

Firebase Authenticationはデフォルトで`localhost`が承認済みドメインとして設定されていますが、
`127.0.0.1`は設定されていないため、`unauthorized-domain`と判定されてしまいます。

## 対処方法

以下のいずれかを実施することでGoogle認証が正常に動作するようになります。

- `vite.config.ts` or `vite.config.js`ファイルに以下の設定を追加する

    ```typescript
    // vite.config.ts or vite.config.js
      import { defineConfig } from 'vite'
    + import dns from 'dns'
    
    + dns.setDefaultResultOrder('verbatim')
    
      export default defineConfig({
        // 省略
      })
    ```
- Node.jsのバージョンを17以降にアップグレードする

- Firebase Authenticationの承認済みドメインに`127.0.0.1`を追加する

    ![CleanShot 2022-12-09 at 11.47.24@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989440/06e7ab12-376b-0f70-321a-d58910756c50.png)

## 参考

https://ja.vitejs.dev/config/server-options.html#server-host

## おわりに

以下の書籍を執筆した後にViteの動作が変わってしまったため、
ご購入いただいた読者の方も困っている可能性があるかもということで記事を投稿させていただきました。

https://www.amazon.co.jp/gp/product/B0BMQ1BYLS/

本記事の内容以外にも、執筆時とは動作が変わってしまう箇所が出てくると思います。
気づいた点は、都度、書籍に記載しているリポジトリのサンプルアプリを更新したり、
今回のようにQiitaに記事を投稿したりしていこうと思ってますのでぜひウォッチしてください。

Firebaserのみなさん、よいFirebaseライフを :thumbsup:
Fun Done Learnによるふりかえりをアニメ鑑賞に適用してわかったこと〜チェンソーマン１話〜

KDDIアジャイル開発センターの中島です。
本記事は、KDDIアジャイル開発センター Engineer & Designer Advent Calendar 2022の10日目の記事です。

スクラム開発のふりかえり手法のひとつである「Fun Done Learn」をアニメ鑑賞に適用してみました。
意外な気づきがあったので、本日はそちらをご紹介しつつ、
Fun Done Learnがスクラム開発現場だけでなく、***様々なコミュニケーションを活性化させたい場で活用できそう***という話をしてみます。

## Fun Done Learn とは

アジャイル開発のふりかえり手法のひとつで、
2018年[Scrum Coaches Retreat in Okinawa](https://www.scrumalliance.org/events/coaching)にて提唱されたふりかえりのフレームワークです。

・Fun(楽しかったこと) 
・Done(終わったこと)
・Learn(学んだこと)
が重なり合った図を使ってふりかえりを行います。

参考文献：　[ファン・ダン・ラーン(FDL)ふりかえりボード
](https://qiita.com/yattom/items/90ac533d993d3a2d2d0f)

## 具体例

あくまで例ですが、以下はFun Done Learnでふりかえった例です。
１枚１枚付箋の内容を書いた人が説明し、チーム全員でFun Done Learnの輪のどこに当てはまるか議論します。
例えば、「祝リリース！」や「とりあえずできた！」などはFunでありDoneでありLearnであったため、３つの輪が重なり合ったところに付箋を置いています。
どこに置くかは、チームメンバー同士で話し合い決定します。

![スクリーンショット 2022-12-09 11.27.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149986/0d3f337d-bdbc-1fad-1718-7d4691ef6f7b.png)



## Fun Done Learn を使って得られる効果

アジャイル開発を行い、さまざまなふりかえりを試している中で、Fun Done Learnによるふりかえりは以下のような特徴があると（個人的に）考えています。

- ルールがシンプルなので始めやすい
- 「今の業務を改善しなければいけない」というやらされ感が生まれにくい
- 起きた出来事における「楽しさ」が可視化されるので、ふりかえっていて楽しい
- 楽しい結果会話が活性化するため、カイゼンしたいことも自然と話題に上がってくる（上がらないこともある） 

普段Fun Done Learnを行っているメンバーからは以下のような感想が出ています。

- 楽しい雰囲気になるため、立場にとらわれず思うことを言い合える
- 楽しい雰囲気になるため、初めて参加するフルリモート環境下のチームだったが受け入れてもらえる感があった
- ルールがシンプルなため、スクラム開発、アジャイル開発に知見が浅い人でも、参加しやすい
- 同じ出来事であっても自分以外の他人の視点が見えやすい

## ソフトウェア開発と全く関係のない現場でもFun Done Learnをすると話題が活性化するのでは？

日々Fun Done Learnでふりかえりを行っている中で、「スクラム開発と全く関係のない現場でもFun Done Learnをすると話題が活性化するのではないか」と考えました。
そこで、有志メンバーで集まり、話題のアニメ、チェンソーマンの１話を皆で再生し、ふりかえってみました。

### 事前準備・条件

- チェンソーマン１話再生環境（amazon primeを契約していれば[ウォッチパーティ](https://www.amazon.co.jp/adlp/watchparty)がおすすめ）
- 原作やアニメを観たか否かは不問。ただし、2話以降のネタバレは禁止。
- 今回参加者は全員リモート環境。（可能であれば現地でも問題なさそう。）

### やった手順

- ふりかえりの流れを説明する
- チェンソーマン１話を再生する。（今回は再生中テキストチャットは書かないようにした。）（３０分程度）
- 観終わった後、ふりかえりボードに集まる（今回はふりかえりツール[anycommu](https://anycommu.web.app/)を使用）
- anycommuに従い、タイマーを２分回す
- ふせんが出てくるため、メンバーに観て感じたこと、思ったことなどを自由に書いてもらう
- タイマーが満了したタイミングで、１枚ずつふせんを紹介する。ふせんを書いた人はふせんの内容について説明する

### ふりかえりボードはこうなった

![スクリーンショット 2022-12-09 13.35.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149986/35b68ba4-5b29-06e1-0ddb-964c9a08b0f9.png)



## ふりかえってわかったこと

作品そのものだけでなく、チェンソーマンのアニメ制作環境や、原作との違い、魅力的に感じる作品の特徴など、様々な視点での意見が飛び出しました。中でも、マネーリテラシーに関する考察が飛び交い、***私自身「今年のふるさと納税を決める」というTRYを決めることができました。***

また、ふりかえり後合流した人からも ***「参加していないのにふりかえり結果をみただけで雰囲気が伝わってくる」*** との意見がありました。

また、これはふりかえり全般に言えることですが、***「ふせんに書いて順番に発表する」ことで、参加者全員が万遍なく話ができる***という特徴があるように思っています。

## Fun Done Learnはチームで集まったらやってみたいふりかえり手法

Fun Done Learnはソフトウェア開発やアジャイル開発の現場のみならず、***チームで集まってコミュニケーションを活性化させたい時、新たな気づきを得たい時に活かせる*** 手法ではないかと思いました。是非、まだやったことがない人には試していただきたいです。
Azure Administrator(AZ-104)：Azure管理者向けの前提条件「PowerShellの変数とスクリプト」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「PowerShellの変数とスクリプト」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure 管理者向けの前提条件](https://learn.microsoft.com/ja-jp/training/paths/az-104-administrator-prerequisites/)
◇対応するモジュール
[Azure PowerShell でスクリプトを使用して Azure リソースを作成する](https://learn.microsoft.com/ja-jp/training/modules/automate-azure-tasks-with-powershell/5-create-resource-interactively?pivots=windows)
[Azure PowerShell でスクリプトを作成して保存する](https://learn.microsoft.com/ja-jp/training/modules/automate-azure-tasks-with-powershell/7-create-resource-using-script)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure管理者向けの前提条件「PowerShellによるAzureリソースの作成」](https://qiita.com/fsd-jume/items/3d5953d8bef8e1007bf6)

## PowerShellの変数
・変数を作成し、すべての種類の値を格納可能(コマンドの結果も格納可能)
・変数名では大文字と小文字は区別されず、スペースや特殊文字を使用可能
・作成した変数はPowerShellウィンドウを閉じると削除される
・変数内で作成した変数を使用可能

**◆変数を使用したコマンド結果の格納例**
・リソースグループ名を変数`$RSGName`に格納
・「Get-AzVM」の出力結果を変数`$vm`に格納
・`$vm`を使用してVMの停止を実行
```:PowerShell
$RSGName = [ResourceGroup名]
$vm = Get-AzVM -Name testvm-eus-01 -ResourceGroupName $RSGName
Stop-AzVM -ResourceGroupName $RSGName -Name $vm.Name
```
**※コマンドの意味**
**・$`変数名` = `格納したい値`**
変数名に$をつけることで変数として使用可能
**・$vm**
Get-AzVMの出力結果を格納しているため、$vmだけを入力すると格納した結果を表示
**・Stop-AzVM**
指定したVMを停止
**・$vm.Name**
格納したGet-AzVMの結果のNameプロパティを取得
　今回の場合は「testvm-eus-01」を取得

## PowerShellスクリプト
・コマンドと制御コンストラクトを含むテキストファイル
　-コマンド：コマンドレットの呼び出し
　-制御コンストラクト(制御構文)：ループや変数、パラメーター、コメントなどの機能
・拡張子は「.ps1」
・Windowsの場合は「Windows PowerShell Integrated Scripting Environment(ISE)」を使用可能
・PowerShellコマンドラインから実行可能
例)ファイル名「myScript.ps1」を実行したい場合　→ ファイル名の前に`.\`をつけて入力
```powershell:PowerShell
.\myScript.ps1
```

## 次の学習内容
**◆PowerShellスクリプト(ループ：For)**

https://qiita.com/fsd-jume/items/62f907ab1dc2506dee69

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

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
LinearLayoutで固定サイズの子ビューの残りを別の子供ビューに割り当てる

layout_heightに0dp、layout_weightを1にするだけ。
```
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <View
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="10dp">

    <View
        android:id="@+id/main"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    <View
        android:id="@+id/footer"
        android:layout_width="match_parent"
        android:layout_height="10dp">
</LinearLayout>
```
QCサークル、はじめました

# はじめに
今から2年ほど前、社内でQCサークルを立ち上げることになりました。
個人的にソフトウェア品質を考える上で良い活動ができているなーと感じているので、活動内容について紹介しようと思います。

# QCサークルって何？
私も立ち上げるまで知りませんでしたが、[Wikipedia](https://ja.wikipedia.org/wiki/QC%E3%82%B5%E3%83%BC%E3%82%AF%E3%83%AB)には

>同じ職場内で品質管理活動を自発的に小グループで行う活動

と書かれています。…なんとなく良い活動に聞こえますね。

しかし、こんなことも書かれています。[問題点](https://ja.wikipedia.org/wiki/QC%E3%82%B5%E3%83%BC%E3%82%AF%E3%83%AB#%E5%95%8F%E9%A1%8C%E7%82%B9)より一部抜粋
>* 「予防よりは、失敗して起こしたトラブルの後始末の活動」を担当することになり、「予防なしのもぐら叩き」に陥った
>* 「自主的」（Independent）活動として出発したが、このことが給料の対象とならない非正規業務として過労死などの人間性の尊重に反する事態を導いた
>* 本来、相互啓蒙のために他のサークルを聴衆とし行うべきなのに、審査員に対して発表するという習慣が出来上がり、審査員の評価を高くする競走を招き、ほとんどがデータの改ざんや虚偽した発表が多く見られる

…なんとなく維持するのが難しい、つまらなそうな活動に聞こえますね。

これを読んでいると、私たちの活動はQCサークルではないのかも知れない…と感じつつも、「同じ職場内で品質管理活動を自発的に小グループで行う活動」であることに間違いはないので、自信を持って良いQCサークルが維持継続できていると考えます。

# メンバ紹介
活動内容を紹介していこうと思いますが、メンバプロファイルがあった方が良いかなと思うので簡単に紹介します。
※立ち上げ当初は10名ほどいましたが、現在は6名で活動しています。QCサークル専門の方はもちろんいません。
・開発エンジニア、ラインマネージャ
・開発エンジニア、若手
・QA（Quality Assurance）エンジニア、ベテラン
・製品検査エンジニア、中堅
・カスタマーサポートエンジニア、中堅

全員開発には携わっているものの、役割、ポジション、年齢はバラバラです。
（最初は意図的に複数部門から集めましたが、今はみんな自発的に活動しています）


# QCサークルって何するの？
特に決まりはないと思うので、私たちの活動を紹介していきます。
まず、活動は毎週金曜の午後30分間と決めています（週末の午後はテンションも上がりやすい）。


### 障害共有会
「障害を共有し、原因を追究して知見を得る」活動
通常、本番環境で障害が起きると、経緯・経過報告、原因分析、再発防止など大変な緊張感の中、相応の役職者が出てきて、堅苦しくなりますよね。
※障害でご迷惑をかけているので当たり前ですが…（誤解のないように先にお伝えしますが、もちろん本気の障害分析や再発防止は本業の方でしっかりとやっています）

QCサークルでは、何かしらの障害を取り上げ、「障害あるある」や「どうやれば防げたか」などを気楽に話していきます。
障害は過去発生したものならなんでも良く、中には15年以上前の障害を対象にすることもあります。ベテランの方からこんなのが昔あったんだけど…という感じで出されます。
フランクな雰囲気を作り、自由な発言を行うことから障害に対する意識を変えることを目的としています。なぜなぜ分析など体系だった分析はしません。
・障害は「誰かのせい」ではなく、「誰しも起こしうるもの」「誰もが見落としていたもの」
・対策は「誰かがする」ではなく、「自分が防ぐにはどうするか」


### プロジェクト振り返りシェア
これはその名の通り「プロジェクトの振り返り結果を、全体へシェアする活動」で、QCサークルは運営側という感じです。
シェアは担当プロジェクトリーダーの方にお願いします。

振り返り形式は主にKPTを採用していますが、シェア会では下記のことをQCサークル外の方にも考えてもらうようにしています。最後に聞いてもらった方からランダムで指名して感想を述べてもらうようにすることで、相互に意見交換ができるような仕組みも取り込んでいます。(「指名されるかも知れないから考えなきゃ…」みたいな仕掛けにもなります)

* Problem（悪かったこと）やTry（次に挑戦すること）を聞いて自分ならどうするか
* Keep（良かったこと）を聞いて自分のプロジェクトで取り入れるにはどうするか

### 有識者マッピング
多くの会社や開発で、プロセスってありますよね。市場調査、分析、企画、要件定義、開発、テスト、リリース…
プロセスってその会社の重要なナレッジだと思うんですが、「何をするか」が継承され「なぜ必要なのか」が継承されないために、形骸化しちゃったってあるあるだと思います（個人的所感）。
じゃあナレッジとして残そう！と頑張っても、手順書があるだけで経緯は薄い…みたいな。

ということで、「困った時誰に聞けば分かるんだっけ？」というのをマッピング＆可視化して、新しく入った方や分からなくなった時にはこの人に聞いてみようとすることで、そのナレッジをしっかりと継承していこう！という活動です。これまたQCサークルは運営的な立ち位置です。


### 品質の日
年に2回（半年に1回）、品質の日を設けて、過去起きた重大障害などを思い出す機会にしています。新入社員の方も、品質の日ってなんだ？過去そんなことがあったのかと知る機会にもなりますし、全員が定期的にリマインドするための日です。
しかし、これをイベントとして運営するのは結構大変だったりするので、社内記事書いたり、半年間のQCサークルの活動を共有をしたりしています。（運営大変になると負荷かかっちゃいますからね）


# やってみて
2年間やってきました。成果は？と聞かれても定量的なものはありません。強いて挙げるとすれば何回障害共有会をやったかとか。しかし、ここに定量的な目標や成果、報告を求めてしまうと辛くなっていきます。自由に、気軽にやっていくことで、継続性を持たせ、参加した本人や周りの人が「タメになっている！」「良い気付きを得られた！」って感じてくれていることがこのような活動には最重要だと思います。


# さいごに
ソフトウェアのバグは人が作りこみます。品質向上のためにテストはもちろん必要ですが、極論バグを埋め込まなければ品質は良くなります。
* 「どうやったらバグを検出できるようになるのか」を考えることも必要ですが、
* 「どうやったらバグを作りこまなくなるのか」という視点から、エンジニアの失敗を共有して、疑似的に経験値を爆増させて、ナレッジを強化する
ということに対して、QCサークルの活動は非常に効果的なんじゃないかなと感じます。

ソフトウェア品質で悩まれている方の、何かしらのお役に立てたら幸いです。
docker-composeで建ってるgrowiのmongoをmongodb-awesome-backupを使ってwasabiにバックアップする

タイトルの通りのことをやりたかったので備忘録的なただのメモです。

基本的な手順は以下の通りです。
https://docs.growi.org/ja/admin-guide/admin-cookbook/mongodb-backup.html


## --linkオプションのコンテナ名を調べる

`docker ps`してmongoのNAMESを調べる。今回は`growi3_mongo_1`なので`--link growi3_mongo_1:mongo`が追加すべきオプション

```
# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED        STATUS                          PORTS                               NAMES
236373f1aaa4   growi3_hackmd           "/usr/local/bin/dock…"   18 hours ago   Up 18 hours                     0.0.0.0:3100->3000/tcp              growi3_hackmd_1
9270ea5af81e   growi3_app              "/sbin/tini -e 143 -…"   18 hours ago   Up 18 hours                     0.0.0.0:30000->3000/tcp             growi3_app_1
b17a6a0c7a0f   growi3_elasticsearch    "/usr/local/bin/dock…"   18 hours ago   Up 18 hours                     9200/tcp, 9300/tcp                  growi3_elasticsearch_1
abf5b89acace   mariadb:10.3            "docker-entrypoint.s…"   18 hours ago   Up 18 hours                     3306/tcp                            growi3_mariadb_1
7072563cd83b   mongo:3.6               "docker-entrypoint.s…"   18 hours ago   Up 18 hours                     27017/tcp                           growi3_mongo_1
```

## --netオプションのネットワーク名を調べる

`docker network list`をしてNAMEを調べる。今回は`growi3_default`なので`--net=growi3_default`が追加すべきオプション

```
# docker network list

NETWORK ID     NAME               DRIVER    SCOPE
14922bcf2b5c   growi3_default     bridge    local
```

## AccessKeyとAccessSecretを調べる

wasabiのコンソールのAccess Keysの箇所からAccess KeyをCREATEする。secretは生成時にしか参照できないのでメモるかcsvを落としておく。
今回は`Access Key Id = aaa`, `Secret Access Key = bbb`とする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124712/5bb1ddd1-887f-001b-925d-0a7d449c3e15.png)

## Bucket URLを調べる。

これはそのままBucket NameがURLになる。例えばBucket Nameが`hogehoge-bucket`であれば`s3://hogehoge-bucket/`。階層にしたいなら`/dir/`など適時追加する。

## Endpoint URLを調べる。

mongodb-awesome-backupのデフォルトはAWSなので、wasabiのendpointを調べる。
Regionに応じて以下から参照。今回は`ap-northeast-1`なので`https://s3.ap-northeast-1.wasabisys.com`。

https://wasabi-support.zendesk.com/hc/ja/articles/360015106031-Wasabi-%E3%81%AE%E5%90%84%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%83%AA%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9-URL-%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84-


## mongodb-awesome-backupを起動する

以下のリポジトリをcloneする。
https://github.com/weseek/mongodb-awesome-backup

```
# git clone https://github.com/weseek/mongodb-awesome-backup.git
# cd mongodb-awesome-backup
```

オプションつけて`docker run`する。

```
docker run --rm \
  -e AWS_ACCESS_KEY_ID=aaa \
  -e AWS_SECRET_ACCESS_KEY=bbb \
  -e TARGET_BUCKET_URL=s3://hogehoge-bucket/ \
  -e AWSCLI_ENDPOINT_OPT=https://s3.ap-northeast-1.wasabisys.com \
  --link growi3_mongo_1:mongo \
  --net=growi3_default \
  weseek/mongodb-awesome-backup
```

以上です。
Aurora Serverless(MySQL)メジャーアップグレード手順について

# はじめに
Auroraのメジャーアップグレード(Aurora mysql v1(mysql 5.6互換のEOL)について、
AWSから通知があり、Aurora mysql v1(mysql 5.6互換)から、
Aurora mysql v2(mysql 5.7互換)にメジャーアップグレードを行う必要がありました。
備忘として、コンソールでの作業手順をまとめてみました。

# アップグレード対象の確認
AWSコンソールにログインし、データベース一覧画面から該当のAuroraのエンジンバージョンが、
5.6.mysql_aurora.1.22.3(EOLバージョン)であることを確認します。
（画面に表示されない場合、設定で「エンジンバージョン」の表示を有効にしてください。）
![aurora_serverless_major_vup_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/736b13f4-5e17-e150-3ce8-7baaacf5c034.png)

# 事前作業
- スナップショット取得
   クラスター構成の場合、アップグレード時に自動でスナップショットを取得してくれません。
    もしロールバックすることになった場合、困ってしまうので、
    事前にスナップショットを手動で取得しておく必要があります。

- パラメータグループの作成
    カスタムパラメータを使用している場合、メジャーアップグレード時にカスタムパラメータを指定する必要があります。
    その為、事前にアップグレード先に対応したカスタムパラメータを作成しておく必要があります。

# アップグレード作業
アップグレード対象を選択し、データベース一覧画面右上の「変更」ボタンを押下します。
![aurora_serverless_major_vup_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/78f51554-ea72-e985-cfe7-632a3251450c.png)

設定変更画面にて、設定欄の「バージョン」のリストからアップグレード先のバージョン(MySQL5.7互換)を選択します。
![aurora_serverless_major_vup_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/ed5e328b-2f5a-1476-9547-82a8b28285f2.png)

最下部にスクロールし、追加設定欄の「DBクラスターのパラメータグループ」のリストから、
事前に作成しておいたパラメータグループを選択します。
さらに画面右下の「続行」ボタンを押下します。
![aurora_serverless_major_vup_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/62dc3ef0-beb4-e9d0-7f1e-206bab772571.png)

変更のサマリーを参照し、現新の値を確認します。
又、変更のスケジューリング欄のタイミングを「すぐに適用」のラジオボタンを選択します。
問題なければ、「クラスターの変更」ボタンを押下します。
![aurora_serverless_major_vup_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/343b9bf9-cd3e-2e0b-023c-79ebec4b23d0.png)

アップグレード処理が実行されます。
20分程のダウンタイムが発生した後、アップグレードが完了しました。
![aurora_serverless_major_vup_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740559/e1992aca-0224-f2eb-5589-0dcbe780126b.png)

# 考慮事項など
・ダウンタイムが発生する為、システムが稼働していない時間帯を見計って作業する必要があります。
WSL2のubuntuをgatsbyの開発環境にする（他のフレームワークでも使える）

## ubuntu on wsl2を準備

1. WSL2を有効化してubuntuをインストールする（参照：[WSL2+ubuntu20.04: GUI化して使う方法](https://qiita.com/atomyah/items/887a5185ec9a8206c7c4)）※ 特にGUI化する必要はないので「ubuntuにXRDPをインストール」以降の作業は必要ない。
1. すでにubuntu on WSL2があって、それを初期化したい場合は、Windowsの設定→アプリ→アプリと機能→***ubuntu 20.04 on Windows***の詳細オプションをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/5691804a-2fff-6d9f-f2d7-7e9ab382ab1b.png)
3.そしてリセットボタンをクリックすればあっという間に初期化される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/447bc3c3-80a9-f7f3-b72f-36fa3f8866d1.png)

## nodeのインストール
- aptでnodeとnpmをインストール
```bash
$ sudo apt update
$ sudo apt install nodejs npm
```
- nodeバージョン管理のために一応npmでnをインストール
```
$ sudo npm install -g n
```
- nodeの最新安定版（LTS）バージョンを確認
```bash
$ n --lts
18.12.1
```
- nでlts版のNode.jsをインストール
```bash
$ sudo n lts
```
- nでnodeバージョンを確認
```
$ n ls
node/18.12.1
```
- 最後にaptで入れたnodejsとnpmをアンインストール
```bash
$ sudo apt remove nodejs
$ sudo apt autoremove
```

## Gatsbyをインストール
- gatsby-cliをインストール
```bash
$ sudo npm install -g gatsby-cli
```

## Gatsbyプロジェクトを作成してみる
- userホームディレクトリの下にtempspaceフォルダを作成。そこに移動して`gatsby new test-sample`コマンド（test-sampleはプロジェクト名）
```bash
$ mkdir /home/atom/tempspace
$ cd /home/atom/tempspace
$ gatsby new test-sample
```
- 完了したらtest-sampleプロジェクトフォルダに移動し一応Gatsbyのバージョン確認
```bash
$ gatsby -v
Gatsby CLI version: 5.2.0
Gatsby version: 5.2.0
  Note: this is the Gatsby version for the site at: /home/atom/tempspace1/test-sample
```
- そして`gatsby develop`
```bash
$ gatsby develop
```
- Windows上でクロームなりFirefoxなりでhttp://localhost:8000 を開いてみる。WSLで`gatsby develop`によって立ち上がったGatsbyデフォルトスターターのページがWindows上のブラウザで表示できるはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/6fc66b59-984a-874a-32b2-b61515e3c9e4.png)

## VS Codeでプロジェクトフォルダを開く
- まず新しいVS Codeのウインドを開く
- 拡張機能で、***WSL***をインストールする（以前はRemote WSLという名前だったかと…）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/3e5db474-ad1d-faba-1d55-263db2eb1a22.png)
- 左下の緑の><アイコンをクリックして、「新しいWSLウインドウ」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/47979ee3-c841-76cd-d55e-f91895c78906.png)
- 新しいウインドが開く。左下の緑の枠に接続先のWSL上のOS(ubuntu-20.04)が表示されているはず
- 「フォルダを開く」ボタンをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/831e3a5b-74dc-1f40-9998-3c839a3dfe2e.png)

- Gatsbyプロジェクトファイルのパスを選んでOKボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/bc3a4b95-758f-d6fd-98a3-d25dcd2d3139.png)

開けました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/884a9a56-d1bb-53ad-50b5-779a1ba49b86.png)

<br />
以上です。
AWSとGoogle Cloud 認定資格をコンプリートしました

# はじめに

この度、AWSとGoogle Cloud の認定資格を全て取得しました。
AWS 12冠、Google Cloud 11冠。合わせると、計23個となります。

資格取得をする中で考えていたことを振り返ってみます。

### AWS 認定資格 取得記録
![AWS 認定資格.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/1af91400-98af-2fdc-fb00-3703bb25f7cb.png)

### Google Cloud 認定資格 取得記録
![Google Cloud 認定資格.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/44af1587-783b-4cec-47f6-983709a68a4a.png)

# 意識していたこと

## 1. 心構え

AWSは3年、Google Cloudは2年と、いずれも一定期間が経つと有効期限が切れます。そのため、期限切れのたびに更新（再受験）が必要です。

このこともあって、私は「資格取得は、短距離走ではなくマラソンに近い」と捉えていました。
いかに早く取得するかではなく、自分のペースで走り続けることが大事なのだと。

そのため単に取得するだけでなく、今後も維持することを意識して学習に努めていました。

例えば、学習にあたって参考にした教材や大事なポイント、受験後の所感などをなるべく記録に残しておくようにするなど。

マラソンには途中で給水ポイントが設けられているように、疲れを感じたときには無理せず休憩を挟んで構わないと自分でペースコントロールも行なっていました。

## 2. モチベーションの維持

長く資格勉強を続けている途中で、「なぜ資格を取る必要があるのか？」と迷いが出てくるタイミングが私には何度かありました。

これがモチベーションの維持の難しさかと痛感していたのですが、そのたびにいちいち同じ問いを自分に向けているとキリがない。

そう思い、ある時「なぜ資格を取るのか」を箇条書きで書き出してみたところ、私には効果的でした。

冷静に資格を取ることのメリットを見つめることができ、資格取得への努力を肯定できるようになりました。目的意識が明確になったことで、それ以降はモチベーションが減退して前に進めないことは少なくなったように思います。

書き出す際には、自分の素直な思いを可視化しておくことが大切だと感じています。

(例)

- 学ぶことがたのしいから。
- キャリアアップに繋がるから。
- 昔の自分を驚かせたいから。

## 3. 習慣化するために
自分のペースで資格取得を続けられそうな頻度を模索していたところ、1ヶ月か2ヶ月に1度の頻度で受験することに落ち着きました。

学習にあたっては他の人の合格記や体験話を参考にする機会もありましたが、あくまで参考に留めるだけで丸っきり真似をしようとは考えていなかったです。人によって学習の仕方は千差万別だからです。

真似することよりも自分にとって続けやすいやり方は何かと考えることの方を重要視していました。気乗りしない時は勉強しない時期があっていいなど、ストイックになりすぎないように意識しました。

私は資格勉強に近道はないと思っています。突き詰めると、仕事しながら普段の生活の中で学習時間をいかに確保するか、という時間捻出の問題になってくると考えています。

それは自分と、自分の生活に向き合うことであり、さらにはその各要素に優先順位をつけること。

最初はバランスが難しいですが、徐々に結果が付いてくると楽しい/嬉しいのようなポジティブな感情が後押ししてくれて、良い循環が生まれていきます。

# なぜコンプリート達成できたのか

1つ1つ目の前の資格を取ることに集中していたときには深く考えていなかったですが、改めて私がなぜコンプリート達成できたのかを考えてみました。

- 会社からの手厚い制度

会社から受験費補助と資格手当という形でサポートしてくれる制度があったことは外せません。お金のことを気にかける必要がなく、学習に集中できる環境が整っていたのはとても有難かったです。こうした制度がもしなかったら、そもそも全ての資格を取ろうとすら思わなかったはずなので。

- コロナ禍での生活の変化

私はコロナ禍に入ってから自宅勤務となり通勤時間がなくなったことで、1日のうちで使える時間が以前よりも増えました。「今が資格取得に打ってつけな期間ではないか！？」と気がついてからは、段々とエンジンがかかり始めました。コツコツと目標に向かって日々努力を続けるのが割と得意な自分の性格も相まって、良い結果が出たのだと今になって思います。

- RPGのように楽しむこと

「資格取得の過程はRPGのようなゲームに近い」と考えると、夢中になれた理由が自分の中でしっくりきました。レベルを上げて（問題集を解く）、装備を整えて（知識を得る）、ボス戦に挑む（本試験を受ける）。それを何度か繰り返す。さらにゲーム内だけではなく、実生活にも良い効果をもたらす（スキル向上など）。単純作業、仕事のための勉強と思っていたらここまで続いていなかったです。

# おわりに

こうして振り返って言語化してみると、自分が思っているよりも多くのことを意識しており、その努力の末に全資格の取得が達成できたのだなと改めて感じました。

自分の体験ベースで書いてしまいましたが、何か参考になる部分が1つでもあれば幸いです。
画像データが多すぎてPCの容量を逼迫した話

# はじめに

これは自分の身に起きた本当の話...

同じことが起きないように備忘録として書いておく

# 起きたこと

私 < さぁてファイルの整理するためにフォルダでも作るか！

PC < 空き容量が無いので新規フォルダを作れません

私 < ...

# 原因は？

**画像データが多すぎた！**

機械学習をする上で画像とannotationデータを同じフォルダに置いておく必要があったため、annotationの条件を変えるたびに画像フォルダとannotationデータのフォルダを複製していた

...そりゃデータ食うよね

# というわけで

データセット用のフォルダを用意して、そこにSymbolic linkを通すことで容量の圧迫を防ぐことに

```bash
ln -s <参照path> <Symbolic link path>
```

> これまでSymbolic linkをほとんど使ったことがなかったのでイチから調べました...
> 参照pathは相対pathでもいいとのことだったけど絶対pathじゃないと通せなかった...なぜ？

# さいごに

PCの容量は無限では無いのでいい感じに整理をしないとだめですね。

当たり前のことながら再認識した出来事でした...
Google Cloud に Datadog を導入してみよう - 全体説明編

こんにちは、京セラコミュニケーションシステム 井筒 (@kccs_naoto-izutsu) です。

みなさんは「Datadog」をご存じでしょうか？
Datadog は、システム、アプリケーション、サービスを横断して監視することができる SaaS 型のモニタリングプラットフォームです。

Google Cloud をはじめとしたパブリッククラウド や オンプレミスサーバ、その中で動作しているアプリケーション、データベースなど、あらゆるものを一元的にモニタリングできる優れモノです。

京セラコミュニケーションシステムは、2021 年に Datadog 社と マネージド・サービス・パートナー契約を締結し、MSP サービスとして Datadog を提供しております。

https://www.datadoghq.com/ja/

本記事では、Datadog シリーズの第1回目として、Datadog で Google Cloud をモニタリングする際の全体像を整理したいと思います。

## この記事の対象者

- Datadog に興味がある人
- これから Datadog を使って Google Cloud をモニタリングしてみようと思っている人

## モニタリングのステップ

モニタリングをステップに分けると、ざっくり

1. データの収集
2. データの利用

に分けられます。

これらを Datadog で行う場合、どのようになるか見ていきます。

## データの収集

### 全体構成

Datadog で Google Cloud からデータを収集する際の全体構成を見てみましょう。
こんなイメージになります。

![Datadog_データ収集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989018/2903b04e-1685-9ee2-53a6-d8c97f9ad4a6.png)

Datadog が Google Cloud から各種情報(メトリクス、トレース、ログなど)を集める方法として、大きく分けて 2 つあることが分かります。
イメージの左側にある赤い箱の部分です。

具他的には、

1. API クローラー
2. REST API

の2つです。
順番に見ていきましょう。

### API クローラー

Datadog が、データ収集対象側に用意されている API をコールして、各種データを収集します。
この仕組みを、Datadog では「Integration(インテグレーション)」と呼んでいます。

Datadog は、たくさんの種類を Integration を標準で提供しています。
その中には Google Cloud をはじめ、AWS や Azure といった主要なパブリッククラウドに対応したものなどが用意されています。
Datadog で何かデータを収集したいと思ったら、まずは Integration が用意されているかを確認するとよいと思います。

https://docs.datadoghq.com/ja/integrations/

#### Google Cloud の場合

Google Cloud をモニタリングする場合は、**GCP Integration** を使用します。
GCP Integration は、Cloud Monitoring API をコールして Cloud Monitoring が保持しているメトリクスを収集します。

https://docs.datadoghq.com/ja/integrations/google_cloud_platform/

### REST API

Datadog は、データを受け取るための REST API を用意しています。
何らかのアプリケーションなどから、必要なデータを REST API 経由で Datadog に送信します。

Datadog が提供している Agent プログラム(Datadog Agent)は、REST API を利用してデータを送信します。

#### Google Cloud の場合

Google Compute Engine などは、OS に対して Datadog Agent をインストールしてメトリクスやログを収集します。
GKE に対しては、DaemonSet として Datadog Agent のコンテナを起動させて、メトリクスやログを収集します。

Cloud Logging に蓄積されているログを収集する場合は、Pub/Sub を経由して Datadog の REST API へログを送信します。

## データの利用

API クローラーや REST API で収集したデータは、Datadog のさまざまな機能で利用できます。
データ活用の全体イメージは、以下の図のようになります。

![Datadog_データ利用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989018/df7d40fb-4674-6af6-1f21-1763bc3465be.png)

Datadog の主要な機能については、今後の記事で解説できればと思いますが、今回はDatadog 公式ドキュメントを参照してください。

https://docs.datadoghq.com/ja/dashboards/

https://docs.datadoghq.com/ja/getting_started/monitors/

https://docs.datadoghq.com/ja/logs/explorer/

https://docs.datadoghq.com/ja/tracing/trace_explorer/

## まとめ

本記事では、Datadog で Google Cloud をモニタリングする際の全体像を、イメージ図を交えてご紹介しました。

具体的な設定方法や使い方には触れませんでしたが、Datadog と Google Cloud との関係性や、Datadog の仕組みについて大まかなイメージを持っていただけたら幸いです。

次回以降で、各仕組みや機能について、より具体的にご紹介したいと思います。

## 免責事項

本記事に記載している内容は、2022年12月時点の情報となります。
記事中の図表は筆者の理解をベースに作成したものとなり、実際の構成とは異なる可能性があります。
[Salesforce]問い合わせページにWeb-to-リードを設定する

## はじめに
[株式会社ピーアールオー（あったらいいな！を作ります） Advent Calendar 2022](https://qiita.com/advent-calendar/2022/pro-japan1) の9日目になります。

今回はQiitaに記事の少ないSalesforceで、最初にやることが多い「Web-to-リード」を題材とします。

## 前提
利用が多いと思われるWordPressで作成されたLPページ等の問い合わせページに対して
Web-to-リードのフォームを追加していく流れを紹介します。

## 素直に作ろうとすると
Salesforceの「web-to-リード」機能で発行したHTMLを利用します。
以下のようになります。
| 媒体 | 処理の流れ | 対応すること |
|:-|:-|:-|
| LPページ | SalesforceにPOSTする | Salesforceで発行したHTMLを埋め込む、JSで入力チェック |
| Salesforce | reCAPTHAキーペアチェック、リード登録、メール送信 | リード・メール設定  |
| Thanksページ  | 設定登録しているURLへリダイレクト  | Thanksページの作成  |

:::note warn
ここで考えたいこと
・web-to-リードのメールは商談（行動履歴）のように残したいものでない、Salesforceに寄せる必要がない
・Thanksページを余計に作る必要がない
・SalesforceのWeb-to-リード要求は制限数（500/日）がある
・HTMLから直接SalesforceへPOSTは避けたい(JSの入力チェック作成やHTMLに載せたくない項目（**組織ID**）がある)
・PHP等でサーバーサイド処理を１から作成するのも大変
:::

## 解決はプラグイン
なるべく楽な解決として、WordPressのプラグインを選択します。
プラグインの選定基準は「無料・更新日（サポート）が新しい・分かり易い」の３点

以下のプラグインを利用させて貰いました。
| プラグイン名 | プラグインの内容 |
|:-:|:-:|
| ContractForm7 | メジャー、確認画面なし、reCAPTCHA（v3）あり、日本語:flag_jp:がうれしいです |
| Code Snippets | codeの差し込みが可能。(PHP、スタイル)  |

※最近はWordPressで子テーマを利用したノーコード・ローコードの記事を目にしますが
　子テーマのことを考えるのが手間なので、コードを差し込むSnippetsプラグインを選択

だいたいはこのようになります。
| 媒体 | 処理の流れ | 対応すること |
|:-|:-|:-|
| LPページ | 自サーバーにPOSTする | ContractForm設定（フォーム、チェック、メール） |
| 自サーバー | ContractFormの処理＋Snippetsの処理 | Snippetsでコード追加（SalesforceAPIアクセス、その他追加可能） |
| LPページ | 送信完了メッセージを表示 | ContractForm設定のもの |

## 設定手順とポイント
１\.  reCAPTCHA発行
- [Google v3 Admin Console](https://www.google.com/recaptcha/about/)で発行します。

２\.  Salesforceの設定
- 設定＞マーケティングにある「Web-to-リード」の設定をする
有効化とフォームの払い出し
- 設定＞マーケティングにある「リードの設定」の設定をする
デフォルト作成者やレコードタイプ設定等を必要に応じて

３\.  WordPressプラグインインストール
- ContractForm7、Code Snippetsをインストール

４\. ContractFormの設定
- インテグレーションにあるreCAPTCHAのセットアップをする
Googleで発行したキーを設定する
- 問い合わせフォームを作成する
Salesforceで払い出したHTMLの項目（nameなど）に併せて作成する
hiddenのoidはSnippets側で設定するので含めない
- メールのテンプレートを設定する

５\. Snippetsの設定
- reCAPTCHAの制御追加
WordPressのプラグインでreCAPTCHAは見かけますが「更新が古い、有料」など見つける手間の方が高く付くのでコード追加としてます。
<details><summary>対象画面を絞る（除外する）サンプルコード</summary>

```
add_action( 'wp_enqueue_scripts', function() {
    if(is_page(array('LPページ1','LPページ2'))) return;
    wp_deregister_script( 'google-recaptcha' );
}, 100, 0);
```
</details>

- Salesforceへの登録
こちらは参考サイトさまのリンクを載せさせて頂き、ポイントの記載とさせていただきます。
APIエラーによる機会減少を考える場合は、フックするアクションの選択を「wpcf7_mail_sent」にする、非同期処理にするといった対応を検討されるとよいかもしれません。

:::note alert
HTML（問い合わせForm）にSalesforceの組織IDを載せず、追加するアクション内に記載することをオススメします。
:::
:::note info
チェック処理の追加用途だけではなく、HTTPClientの処理でslack通知を入れるといったカスタマイズを入れることもよいと思います。
:::

###### 参考サイトさま
https://qiita.com/emegane/items/957c5db4e41d11454430

## 纏め
ケースにより確認画面が必要な場合はMW WPFormを使用など対応の選択は様々と思われます。
組織IDをhiddenで設定するのは避けた方がよいと思われます。（ごくまれに見かけます:cry:）
Salesforceの考え同様に、出来るだけ在るものを利用していきましょう。
という記事でした。
参考になれば幸いです。
【Unity】初学者は絶対つまずくであろうGameObgect型の不明を解決する

# はじめに
GameObgectを何となく使っていたが、自分でゲームを作ろうとするとGameObgectの使い所が曖昧だったので深く調べることにしました。
GameObgectとコンポーネントの関係がかなり密接なので、コンポーネントについても触れなから解説していきたいと思います。

# GameObgectとは
ゲームオブジェクトは空の箱でる。
ゲームオブジェクトは箱である為、自身では何もしない。動かす為には、その動作をさせるパーツであるコンポーネントが必要。

![スクリーンショット 2022-12-09 11.02.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2958170/1a460d04-8284-4815-b2e2-dff671318473.png)

上記の写真のように、 __Boardというゲームオブジェクト__ の中には、__Transform__　と　__Board(Script)__ というコンポーネントがある。

TransformとBoardという動きができる素材がBoardという箱の中にあることで、Boardという箱すなわちBoardというゲームオブジェクトを動作させることが出来るのです。

# GameObgect型はどのような時に使うのか

一例としての使い型では以下のような使い方がある。

__GameObjectを検索（取得）したい時__
GameObject.Find("取得したいオブジェクトの名前")

__(インスペクタから直接選択可能)ゲームオブジェクトに格納したい時__
    [SerializeField]
    private GameObject 格納したい変数;

__タグ名でゲームオブジェクトを取得したい時__
GameObject object1 = GameObject.FindGameObjectWithTag("取得したいオブジェクト名前");

__スクリプトから消去したい時__
Destroy("消去したいオブジェクト名前");
    
# 最後に
ゲームオブジェクト型はコンポーネントを敷き詰めた箱のようなものである。
ゲームオブジェクトを取得、消去、格納などをしたい時にゲームオブジェクト型(クラス)を指定した上で指定のオブジェクトを書くことで取得できる。
Windowsローカルフォルダードライブのマウント

## .reg
```
REGEDIT4 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices] 
"M:"="\\??\\C:\\Users\\me\\Box\\_myboxfolder"
```

マウント (再起動後消える）
```
subst M: D:\Folder
```

アンマウント
```
subst M: /D
```

net drive
```
ipconfig /flushdns

::NET USE M: /DELETE

NET USE M: \\mynetdrive\general /persistent:yes
```


```
REGEDIT4 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices] 
"Z:"="\\??\\E:\\sda"
```

### unmount
```
REGEDIT4 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices] 
"Z:"=-
```
GitHubのサイトを指定したGo Installのやり方に手間取ったのでメモ

# まえがき
Goでプログラミングをしてみたいと思い、環境整備したときモジュールのインストールにかなり手間取った。
その時の忘備録。
GitHub以外のリポジトリからインストールするときはまた話が変わってくるので注意。

# 環境
OS：Windows 10(64bit)
プロセッサ：AMD Ryzen 5 3450U with Radeon Vega Mobile Gfx     2.10 GHz
RAM：16 GB
Goのバージョン：go1.19.3 windows/amd64

# 結論
こうすればOK。
```:書き方
go install github.com/<リポジトリのパス>@HEAD
```

# 経緯
Teftifyをインストールしたいと思い、公式のインストール方法を見てみた。

https://github.com/stretchr/testify#installation


```:サイトに書いてあったやり方
go get github.com/stretchr/testify
```
なんだこれなら簡単じゃないか、と思いきや、以下のエラーが出てしまった。
```:エラーメッセージ1
> go get github.com/stretchr/testify
go: go.mod file not found in current directory or any parent directory.
        'go get' is no longer supported outside a module.
        To build and install a command, use 'go install' with a version,
        like 'go install example.com/cmd@latest'
        For more information, see https://golang.org/doc/go-get-install-deprecation
        or run 'go help get' or 'go help install'.
```

メッセージを見てみると、どうやら「go get」はこの書き方をもうサポートしていないらしい。
代わりに「go install example.com/cmd@latest」としろ、と書いてある。

つまり、「go install github.com/stretchr/testify@lastest」と書けば良さそうか。
```:エラーメッセージ2
> go install github.com/stretchr/testify@lastest
go: github.com/stretchr/testify@lastest: github.com/stretchr/testify@lastest: invalid version: unknown revision lastest
```
「lastestというリビジョンは存在しない」と返ってきた。

調べてみると、GitではlastestではなくHEADらしい。(実は人生で一度もGitを使ったことがなかったので分からなかった。)

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%83%AA%E3%83%93%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AE%E9%81%B8%E6%8A%9E

lasestをHEADにしてみたところ、通った。
```
> go install github.com/stretchr/testify@HEAD
package github.com/stretchr/testify is not a main package
```

インストールもできているようだ。
```
> ls


    ディレクトリ: C:\Users\XXXXXXX\go\pkg\mod\github.com\stretchr\testify@v1.8.2-0.20221102114659-1333b5d3bda8


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-r---        2022/12/09     12:33                .github
d-r---        2022/12/09     12:33                assert
d-r---        2022/12/09     12:33                http
d-r---        2022/12/09     12:33                mock
d-r---        2022/12/09     12:33                require
d-r---        2022/12/09     12:33                suite
-ar---        2022/12/09     12:33            278 .ci.gofmt.sh
-ar---        2022/12/09     12:33            455 .ci.gogenerate.sh
-ar---        2022/12/09     12:33             34 .ci.govet.sh
-ar---        2022/12/09     12:33            263 .gitignore
-ar---        2022/12/09     12:33           2566 CONTRIBUTING.md
-ar---        2022/12/09     12:33           1075 doc.go
-ar---        2022/12/09     12:33            188 go.mod
-ar---        2022/12/09     12:33           1425 go.sum
-ar---        2022/12/09     12:33           1103 LICENSE
-ar---        2022/12/09     12:33            186 MAINTAINERS.md
-ar---        2022/12/09     12:33            186 package_test.go
-ar---        2022/12/09     12:33          11667 README.md
```

# あとがき
複数のツールが絡んだり、バージョン更新で変更が入ったりすると、こういうところで苦労させられるなぁ、と思う。
一番助かるのは公式サイトの情報が更新されることなのだけども。
【備忘録】業務で実際使用したcurlコマンドメモ①（疎通確認）

# 1.curlコマンドとは
任意のサーバーやWebサイトへhttpリクエストを送って、そのレスポンスをチェックすることができるコマンド
curlの後に-Xオプションを指定することでデータの送受信を指定することができる。
(-Xオプション無しだとデフォルトでGET(受信）となる。)

# 2.よく使用するオプション表
|オプション|説明|
|:---:|:---|
|-o,-O|取得したコンテンツをファイル出力する|
|-s|コンテンツ取得時の進捗状況を非表示にする|
|-x|プロキシサーバ経由でアクセスする|
|-X|メソッド(GET,POST等)の指定([メソッド一覧](https://qiita.com/matsumotojanai/items/9d992077dce7b096464a))|
|-v|コンテンツを取得した際の詳細なログを表示する|
|-I,--head|コンテンツを取得した際のHTTPレスポンスヘッダの内容を表示する|
|-L|リダイレクトがあったらリダイレクト先の情報を取る|
|-d(--data)|POSTメソッドで使用。送信する文字列データを指定する|
|–data-urlencode|日本語文字列などをエンコードして送信する必要がある場合|
|-H|リクエストヘッダを追加する。POSTのフォーマットがJSONの場合は -H "Content-Type: application/json" という指定をする|






# 3.具体的な使い方（疎通確認）
**curl -v [接続先IPアドレス]:[接続先ポート番号]**
このコマンドは「コマンドを実行したサーバから、接続先サーバの指定したポートに向けて接続を試みている。
→接続成功の場合の結果
```
  *About to conenct() to [接続先IPアドレス] port [接続先ポート番号](#0)
  * Trying [接続先IPアドレス]...
  * Connected to [接続先IPアドレス] port [接続先ポート番号](#0)

```
　→ ***接続先サーバの接続先ポート番号が空いているということがわかる。***

→接続失敗の場合の結果
```
  *About to conenct() to [接続先IPアドレス] port [接続先ポート番号](#0)
  * Trying [接続先IPアドレス]...
  * couldn't connect to host *Closing connection #0 curl:(7) could'nt connect to host
```
とか
```
  *About to conenct() to [接続先IPアドレス] port [接続先ポート番号](#0)
  * Trying [接続先IPアドレス]...
  * couldn't connect to host *Closing connection #0 curl:(7) Failed to connect to [接続先IPアドレス] port [接続先ポート番号]:接続を拒否されました
```
等の表示がされる。
　→この場合、***接続先サーバの接続先ポートが空いていない可能性がある。***

# 4. 3のコマンドを使用して実際あったこと
①Aサーバで以下のコマンドを実行し、失敗
```
curl -v BサーバのIPアドレス:9100

  *About to conenct() to BサーバのIPアドレス port 9100(#0)
  * Trying BサーバのIPアドレス...
  * couldn't connect to host *Closing connection #0 curl:(7) Failed to connect to BサーバのIPアドレス port 9100:接続を拒否されました
```
→Bサーバの9100ポートが空いていないことがわかる

②Bサーバで同様のコマンドを実行し、成功
```
curl -v AサーバのIPアドレス:9100

  *About to conenct() to AサーバのIPアドレス port 9100(#0)
  * Trying AサーバのIPアドレス...
  * Connected to AサーバのIPアドレス port 9100(#0)
```
→Aサーバの9100ポートが空いていることがわかる。

③Bサーバから自分自身の同様ポートを指定しコマンドを実行すると、失敗
```
curl -v localhost:9100

  *About to conenct() to BサーバのIPアドレス port 9100(#0)
  * Trying BサーバのIPアドレス...
  * couldn't connect to host *Closing connection #0 curl:(7) Failed to connect to BサーバのIPアドレス port 9100:接続を拒否されました
```
→Bサーバの9100ポートが空いていないことがわかる
 ***ここで成功していた場合、A-Bサーバ間のfirewallではじかれている可能性がある。***

***双方のサーバで通信の疎通を確認したい場合、それぞれのサーバで接続したい先の疎通を試みた後に、自分自身のサーバでも通信を確認した方が切り分けができる。***
Streamlitのラジオボタンの選択状態に応じて整数値を引き渡す方法

珍しくDatabricksに関係のない話題、単に詰まったので。

https://docs.streamlit.io/library/api-reference/widgets/st.radio

こちらで、ラジオボタンを作成することはできたのですが、戻り値はラジオボタンのテキストです。これに整数値を割り当てて、後段の処理に渡そうと思ったのですがやり方がわからず。

結局のところ、以下の方法で行けました。

```py:Python
is_red = st.radio("", ("赤ワイン", "白ワイン"), horizontal=True, args=[1, 0])

if is_red == "赤ワイン":
  is_red = 1
else:
  is_red = 0
```

もしかしたら、もっとスマートな方法があるのかもしれませんが。

:::note
スマートな方法、[@iizukak09](https://qiita.com/iizukak09)さんに教えてもらいました。`Enum`を使ってラベルと数値を紐づけるという方法。なるほど。
:::

```py:Python
import streamlit as st
from enum import Enum

class Choice(Enum):
  def __str__(cls):
    return cls.name

  赤ワイン = 1
  白ワイン = 0

is_red = st.radio("どちらのワインがお好みですか？", Choice, horizontal=True)

st.write(f'選択：{is_red}')

if is_red.value == 1:
  st.write("ではピノ・ノワールにしましょう")
elif is_red.value == 0:
  st.write("ではリースリングにしましょう")
```
cv::UMatがいまいちだった件(グラボなしGPU利用)

# はじめに

近年、人工知能などで莫大な計算量や情報量が要求されるソフトウェアが増えている。
これを処理するために、「CPUだけ」での能力では役不足になってきている。
そこで注目されるのは、以前は映像処理専門だったグラフィックボード(GPU)である。
これは、映像処理はもちろんの事、大容量の専用メモリーがあり、処理能力もCPUに引けを取らいないものであれば、データをGPUにアップロードして、処理をGPUに投げて、処理完了後にダウンロードして結果を受け取れば、CPUはその空き時間で別の処理を行うことが可能である。また、GPUは専用メモリーを使うので、メインメモリの圧迫が軽減されることが期待される。
OpenCVでは「GpuMat」と言う、GPUで処理させるMatが存在するが、これを利用するにはN社製のグラフィックボードとCUDAのインストールがあって、初めて利用可能となる。
逆に言えば、初めからマザーボードに張り付いている、I社製などのGPUでは利用することは出来ない。
そこで登場するのが「UMat」である。UMatはGpuMatが使えない環境でも、OpenCVからGPUを利用することが出来る。これを使用することでソフトウェアの動作速度の向上などが期待されるのである。

# UMatの簡単な使い方

UMatは概念的には仮想のデバイスであり、直接そのメモリ空間にアクセスする事は出来ない。これはGpuMatでも同様である。
そこで一旦Matにデータをセットして、それをCopyTo()関数でアップロードする。
処理が終わったらCopyTo()関数でダウンロードする。

``` C++:test.cpp

int main()
{
    cv::Mat  img;
    cv::Mat  gray;
    cv::UMat u_img;
    cv::UMat u_gray;
    //画像読み込み
    img = cv::imread("apple.jpg");

    //UMatへアップロード
    img.copyTo(u_img);

    //Gpuで処理する内容を記述(この場合はカラーからグレイスケール変換)
    cv::cvtColor(u_img,u_gray,cv::COLOR_BGR2GRAY);

    //Matへダウンロード
    u_gray.copyTo(gray);

    //表示
    cv::imshow("gray",gray);
    //u_grayを直接表示する事も可能
    cv::imshow("u_gray",u_gray);

    cv::waitKey();
}
```

![apple.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883019/e4bfa4ea-8cb3-125d-7949-3dca3e75ca63.jpeg)

![u_gray.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883019/6aa7e500-849b-ff05-235f-092487303d56.jpeg)

# UMatの簡単なベンチマーク

以下のようなコードを記述して、実行時間を計測した。

``` C++:u_time.cpp

#include <opencv2/opencv.hpp>
#include <windows.h>
#include <stdio.h>



int main(int argc, char* argv[])
{
	const int LOOP_NUM = 100;

	cv::Mat src = cv::imread("apple.jpg");

	cv::Mat gray;
	DWORD   st;
	//UMat時間計測開始
	st = GetTickCount();
	//アップロード
	cv::UMat u_src;
	cv::UMat u_gray;
	src.copyTo(u_src);
	//時間稼ぎループ
	for(int cnt=0;cnt < LOOP_NUM;cnt++)
	{
		//グレイスケール画像に変換
		cv::cvtColor(u_src,u_gray,cv::COLOR_BGR2GRAY);
	}
	//ダウンロード
	u_gray.copyTo(gray);
	//UMat時間計測完了
	std::cout << "UMat時間" << GetTickCount() -  st << "[ms]" << std::endl;
	//UMat画像表示
	cv::imshow("u_gray",gray);
	cv::waitKey(30);

	//Mat時間計測開始
	st = GetTickCount();
	//時間稼ぎループ
	for(int cnt=0;cnt < LOOP_NUM;cnt++)
	{
		//グレイスケール画像に変換
		cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
	}
	//Mat時間計測完了
	std::cout << "Mat時間" << GetTickCount() -  st << "[ms]" << std::endl;
	//Mat画像表示
	cv::imshow("Mat",gray);
	cv::waitKey();

	return 0;
}
```
実行時間

UMat時間 7719[ms]
Mat時間 78[ms]

以上からUMatの方が著しく遅い結果となった。

# おわりに

Umatの実行時間はよろしくなかったが、実際別件でUmatを組み込んで使って見ても、
速度性能向上は見られず、かえってメモリ違反などが出ていたので、
ある意味予想通りだった。
C/C＋＋プログラマであれば、ポインタやC言語の標準関数などを駆使するのが、
現実的と考える。
Windowsであれば、Direct3D/2Dの利用を検討するのもありかと思います。