OmniAICreator/Qiita-1.07M huggingface dataset:
実際のブラウザーのプロファイルをWebDriverで使う

普段使っているブラウザーのプロファイルをWebDriverで使いたい。

#Chromeの場合

```csharp
            var options = new ChromeOptions();
            options.AddArguments(@"--user-data-dir=C:\Users\Taro\AppData\Local\Google\Chrome\User Data");
            options.AddArguments(@"--profile-directory=プロファイル名");
            ChromeDriver driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), options);
            try
            {
                // Navigate to Url
                driver.Navigate().GoToUrl("https://www.google.co.jp/");

            }finally
            {
                Console.ReadKey();
                driver.Quit();
            }
```
#Firefoxの場合

使いにくい。

```csharp
            FirefoxOptions options = new FirefoxOptions();
            FirefoxProfile profile = new FirefoxProfile(@"Firefoxのプロファイル");
            options.Profile = profile;
            FirefoxDriver driver = new FirefoxDriver(options);
            
            try
            {
                // Navigate to Url
                driver.Navigate().GoToUrl("https://www.google.co.jp/");

            }finally
            {
                Console.ReadKey();
                driver.Quit();
            }
```

#注意

ChromeもFirefoxも普段使っているプロファイルを想定している。

Chromeはコンソールでエラー表示が出るが、一応　動いてるっぽい。

Firefoxはブラウザーをいつものように使っていると、そのプロセスがロックファイルを使って、C#プログラムを起動できないセキュリティの高い仕様のようだ。プロセスを使っていない場合(ブラウザーを普段使いしていない場合)、プログラムは起動するがプロファイルが一時ファルダにコピーされるうえ、オーバーヘッドが大きく、やたら起動に時間がかかる。

解決方法は今の時点で見つからず。
lodash の debounce で多重クリックを回避する

# はじめに
どうもはるうさぎです。今回は案件内で、問題があったのでそれを解決したよ〜っていう話です。
備忘録です。

## 背景

最近では、スマホだとボタンが消えるまで何回もタップしてしまったり、
マウスでもボタンが押せなくなるまでクリックしたりなど、ユーザーが予期しないクリックをすることがあります。
今回は多重クリックが問題だったので、クリックを無視してくれる関数が欲しい！
それが [debounce](https://lodash.com/docs/4.17.15#debounce) です。

## どうやった？
こんな感じ

```index.vue
<Button
　　:text="投稿する"
　　@click="submitDebounce"
/>


import { Component, Vue, Watch } from '@/node_modules/nuxt-property-decorator';
import Button from '@/components/buttons/Button.vue';
import { debounce } from 'lodash';

@Component({
  components: { Button },
})

export default {

　　async submit(): Promise<void> {
 　　　//省略
  }

　　　submitDebounce = debounce(this.submit, 500);　←ここ！

}

```
注意していただきたいのが、debounceは関数を返す関数です。
今回は既に投稿ボタンがあったので、そのsubmitの中でごちょごちょとしてます。
これで何回クリックしようが、0.５秒遅延して1回しかクリックできなくなっています。

※[vue-property-decorator](https://qiita.com/simochee/items/e5b77af4aa36bd0f32e5#watch)が導入されています。
whereとorderByを同時に実行(React + firebase)


## この記事を書いた理由
Reactを学習し始めて２ヶ月程度。
なんとなくでしかまだわかっていないのですが、とにかく実践あるのみかと思い、家計簿アプリを作成しました。

結果つまずいたところがたくさんあったので、備忘録がてら記事にしたいと思います。
また、私と同じくReactの学習を始めたての方の参考になれば嬉しいです。


## 本題：表示しているデータが月ごと、ユーザーごとでソートできない

家計簿アプリなので、例えば2021年7月に入力したデータは7月のページで表示させたいし
2021年6月に入力したデータなら、2021年6月に表示させたい。


これは下記のソースコードで、ログインしているユーザーが入力したデータ(uidを取得)と、
入力した日付(date)でソートをかけているのですが

```Home.js
const getIncomeData = () => {
    const incomeData = db.collection('incomeItems');
    incomeData
      .where('uid', '==', currentUser.uid)
      .orderBy('date')
      .startAt(startOfMonth(date))
      .endAt(endOfMonth(date))
      .onSnapshot((query) => {
        const incomeItems = [];
        query.forEach((doc) =>
          incomeItems.push({ ...doc.data(), docId: doc.id })
        );
        setIncomeItems(incomeItems);
      });
  };
```
なぜか入力していたデータが一つも表示されません。
色々調べていると、whereとorderByを同時に実行したい場合は
firebase側で設定をしないといけないようでした、

参考記事：[Flutter: FirestoreでwhereとorderByを同時に実行したい](https://moimoiblog.com/programing/firebase-execute-where-orderby/#toc3)

これに気づかず、whereとorderByの組み合わせがダメなのか？と色々試行錯誤して
かなり沼にハマりました・・・泣

要は、「uid」を取得してなおかつ、「date」を取得して並び替えるのであれば、
firebase側でデータを取得してソートするのであれば、複合インデックスを作らないといけないようです。
コンソールのエラーにも出ていました。。
コンソールのエラーにはURLが出ていて、それをクリックすると自動で必要なインデックスを作成してくれるようなのですが、なぜか私のアプリではURLなんて出てくれなかったので、自分でインデックス作りました◎

インデックスを設定したら、無事データが出てくれるようになりました〜！
QEMU Guest Agent for Windows をビルドする

# これはなに？

Windows 用 QEMU ゲストエージェントをビルドすることに関する個人的なメモです。
ぜんぜんまとまっていませんので、スルーしてください。


おおまかな手順は https://github.com/rbld/rebuild/wiki/QEMU-Guest-Agent-for-Windows-Build-Environment にあるとおりです。

Dockerを扱いやすくしてくれる [Rebuild](https://github.com/rbld/rebuild) を使って、手元の環境を汚さずに作業します。

# Rebuild環境構築

## コンテナ作成

```
rbld create -b fedora:rawhide qemu-ga
rbld modify qemu-ga
```


## 必要なパッケージ

ビルドに必要なパッケージです。Wikiにある手順より少し多いです。

コンテナ内での作業です。

```bash
sudo dnf install -y git \
glib2-devel libfdt-devel pixman-devel zlib-devel \
python gcc gcc-c++ ninja-build findutils make \
mingw*-glib2 mingw*-pixman mingw*-gmp mingw*-SDL2 mingw*-pkg-config \
mingw*-glib2-static mingw*-zlib-static \
mingw*-winpthreads-static mingw*-pcre-static \
mingw*-pixman-static \
flex bison bzip2
```

# ビルド手順

コンテナ内での作業です。

VSS SDKをダウンロードします。

```console
curl -o VSS_SDK_7.2_setup.exe https://download.microsoft.com/download/9/4/c/94c588cf-8176-4bdb-9d55-2597c76043c6/setup.exe
```

ソースを取得します。

```console
wget https://download.qemu.org/qemu-6.0.0.tar.xz
tar Jxf qemu-6.0.0.tar.xz
cd qemu-6.0.0
```

VSS SDKを展開します。

```console
./scripts/extract-vsssdk-headers ../VSS_SDK_7.2_setup.exe
```

ビルドします。x64版の場合です。

```console
mkdir build
cd build
../configure --disable-docs --target-list=x86_64-softmmu --cross-prefix=x86_64-w64-mingw32- --static --enable-guest-agent-msi --with-vss-sdk
make qemu-ga
```

`build/qga`の下にmsiファイルが出来上がります。

# バージョン番号

バージョン番号はルートにある `VERSION` ファイルにあります。

virtio-guest-tools を使って qemu gaを入れると、バージョン番号が100.0.0.0とかなっているので、上書きインストールするmsiを作りたいときはより大きいバージョン番号にします。

# インストールに失敗する(1)

このようなメッセージが出て、インストーラがコケます。

**The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2613.**

MSITOOLSの不具合のようです。 https://gitlab.gnome.org/GNOME/msitools/-/issues/37


# インストールに失敗する(2)

このようなメッセージが出て、インストーラがこけます。

**Service `QEMU Guest Agent' (QEMU_GA) failed to start. Verify that you have sufficient privileges to start system services.**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59475/e1980c68-491a-b958-dc88-aacef5aa3425.png)

virtio guest toolsに入っている qemu ga は大丈夫なのに。。。

# そもそもなんで、自前でビルドしているのか

Windows 10では動くのに、Windows Server (2012/2016/2019)では動かないのをどうにかしたかったのです。

イベントビューアにこのようなメッセージが記録されます。

```
Faulting application name: qemu-ga.exe, version: 100.0.0.0, time stamp: 0x5c473543
Faulting module name: msvcrt.dll, version: 7.0.17763.475, time stamp: 0xf362c2f9
Exception code: 0xc0000005
Fault offset: 0x000000000005d700
Faulting process id: 0x77c
Faulting application start time: 0x01d7787041c4b0c0
Faulting application path: C:\Program Files\Qemu-ga\qemu-ga.exe
Faulting module path: C:\Windows\System32\msvcrt.dll
Report Id: bf4178f2-396d-4fa9-a537-ebfeec0caf10
Faulting package full name: 
Faulting package-relative application ID: 
```

いろいろ試してみると、`--daemonize` オプションをつけて起動すると落ちる様子です。
Error: "prettier/@typescript-eslint" has been merged into "prettier" in eslint-config-prettier 8.0.0.

# エラー

```
Cannot read config file: /hoge/fuga/node_modules/eslint-config-prettier/@typescript-eslint.js
Error: "prettier/@typescript-eslint" has been merged into "prettier" in eslint-config-prettier 8.0.0. See: https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md#version-800-2021-02-21
Referenced from: /hoge/fuga/.eslintrc.json
```

# コメント
素直に[リンク先](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md#version-800-2021-02-21)を参照。どうやら2021-02-21のFixで"prettier/@typescript-eslint"の記述が不要になったらしい。

> The "prettier" config now includes not just ESLint core rules, but also rules from all plugins. Much simpler!

## 解決策
```.eslintrc.json
{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier",
    "prettier/@typescript-eslint" // この行をコメントアウト
  ],~~~
}

```

:::note warn
至らない部分がある場合は、是非お気軽にコメントいただけると幸いです。
:::
ログイン後、リロードすると一瞬ログイン画面が表示される(React + firebase)

## この記事を書いた理由
Reactを学習し始めて２ヶ月程度。
なんとなくでしかまだわかっていないのですが、とにかく実践あるのみかと思い、家計簿アプリを作成しました。

結果つまずいたところがたくさんあったので、備忘録がてら記事にしたいと思います。
また、私と同じくReactの学習を始めたての方の参考になれば嬉しいです。


## 本題：ログイン後、リロードすると一瞬ログイン画面が表示される
ログインをしているかどうかを判別し、
ログインしているのであれば**Homeコンポーネント**を表示
そうでなければ**Loginコンポーネント**を表示する　といった挙動にしていました。

```App.js
function App() {
  return (
    <AuthProvider>
      <Router>
        <div>
          <PrivateRoute exact path="/" component={Home} />
          <Route exact path="/Signup" component={Signup} />
          <Route exact path="/Login" component={Login} />
        </div>
      </Router>
    </AuthProvider>
  );
}

export default App;
```

これが、ログインしているはずなのに、ほんの一瞬ですがLoginコンポーネントが表示されていました。

これは、firebaseのデータベースに登録されているユーザーなのかどうかを取得するまでの間に
先にログインしていない認識の状態のLoginコンポーネントが出てしまっていたようです。

これは一旦、ログインをしているかしていないかの判断を待っている間の
ローディング画面を作ってあげる必要があります。

まずuseStateで下記内容を作成。

```AuthProvider.js
  const [loading, setLoading] = useState(true);
```
初期値はtrue（ローディング画面の状態）にしておきます。
その後、ログイン認証済かどうか確認する前に下記useEffectの記述を追加。

```AuthProvider.js
useEffect(() => {
    const unsubscribed = auth.onAuthStateChanged((user) => {
      setCurrentUser(user);
      setLoading(false);
    });
    return () => {
      unsubscribed();
    };
  }, []);
```

userがログインしていると無事判別できたら、
ローディングをfalseにすることで、Homeコンポーネントが表示されるようになりました！！
未経験からCCNA取得までの道のり　ver10

OSPFマルチアクセスの場合の挙動についてアウトプットします！！

マルチアクセスの場合、大量のルータ間がfullステートになると、トポロジの変更などで各ルータが個々にLSUを送信するとトラフィックが増えてしまうため、完全な隣接関係を全ルータではなく、限定した一部のルータにすることでLSUのトラフィック量を減らすことができる。
この時複数のルータのうちどの部分を完全な隣接関係にするかを決定する必要がある！！

その部分を決定するためにDR(Designated Router)とそのバックアップとなるBDR(BackupDesignatedRouter)を選びDRおよびBDRとだけ完全な隣接関係を結ぶ！

DRは全ルータと完全な隣接関係を築いてそれぞれのルータのLSAを収集し、集めた情報を全ルータへと送信することによって各ルータがそれぞれ1対1で完全な隣接関係を築かなくても、DRから全てのLSAの情報を得ることができるため、効率がアップします。
BDRはDRがダウンした際の予備で、DRがダウンするとBDRが代わりにDRとして動作をします。

他のDRとBDRに選出されなかったルータをDROtherという！
。DROtherのルータは、お互いをネイバーとして認識してはいるものの、DBDパケットやLSUパケットを直接交換することはありません。そのため、DROther同士は2Wayステートで止まったままになる！！

🚩DRとBDRの選択方法

・ルータプライオリティ

ルータプライオリティは、ルータのインターフェイスごとに決定できる値です。Helloパケットに含まれるため、Helloパケットを送受信することでお互いのルータプライオリティを知ることができます。マルチアクセス環境では、ルータプライオリティの値が最も大きいルータがDR、2番目に大きいルータがBDRに選出されます。ルータプライオリティのデフォルト値は1です。0に設定すると、DRおよびBDRに選出されません。

・ルータID

ルータプライオリティが同じである場合、次にルータIDを比較します。ルータIDは、各ルータを識別する一意の値でIPアドレスと同じ書式となります。ルータIDの値が最も大きいルータがDR、2番目に大きいルータがBDRに選出されます。

・・・ルータIDの設定方法

1.コマンドによって手動で設定する2.ルータの有効なループバックインターフェイスのIPアドレスの中で最も大きなIPアドレスが選択される3.有効な物理インターフェイスのIPアドレスの中で最も大きなIPアドレスが選択される
【Junit5備忘録】SpringBoot

#Junit5備忘録
##概要
SpringBootのテストをJunit5で書いてみました
備忘録としてまとめようと思います

##目次

- テストするアプリケーション
- Junit5
    - コード
    - めも
- 終わり
- 参考サイト

##テストするアプリケーション
まずテストしたいアプリケーションについてざっくりと

tsvファイルの内容を読み込み、DBに登録
※重複チェックあり

↓こんな感じになってます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1733797/f1a999cf-5c25-e856-6039-4062b882f869.png)

##JUnit5
###コード
早速書いていきます
テストしたいクラス→新規→JUnitテストケースで作成できます

毎回ダミーのデータを入れるのが面倒だったので
@BeforeEachと@AfterEachを使って
各テスト前にダミーの登録、テスト後にダミーデータ削除します
（削除もしないとデータが重複してしまいます）

```
//java
@Autowired
private NamedParameterJdbcTemplate template;

@BeforeEach
void setUp() throws Exception {
	//SQLでDBに情報を入れる
	//一回実行したら消さないと重複のエラーがでる→@AfterEachで削除実行
	String sql = "INSERT INTO items";
        sql += " (name,condition,category,brand,price,shipping,description)";
        sql += "  VALUES('dummyName',1,1,'dummyBrand',1,1,'dummyDescription');";
		
	SqlParameterSource param = new MapSqlParameterSource();
	template.update(sql, param);		
}

@AfterEach
void tearDown() throws Exception {
	//テスト用のダミーコード削除
	String sql = "DELETE FROM items WHERE name='dummyName' OR name='dummyName2';";
	SqlParameterSource param = new MapSqlParameterSource();
	template.update(sql, param);
}
```

↓↓　テストの一部です

```
//java
@DisplayName("tsvCountメソッドのテスト：DBに何件あるか取得する")
@ParameterizedTest
@CsvSource({
	"dummyName, 1, 1" 
	, "dummyName, 2, 0"
})
void testTsvCount(String name, Integer category, int result) {
	itemRepository.tsvCount(name, category);
	assertEquals(result, itemRepository.tsvCount(name, category));
}
```
@DisplayNameに分かりやすいように記載して、
@CsvSourceを使って複数パターンのテストをまとめて動かしています。

最初@CsvSourceの書き方が把握できていませんでしたが、
好きでよく使いがちです。

"dummyName, 1, 1" がtestTsvCountメソッドの引数の
(String name, Integer category, int result)に対応した形になります
（dummyNameがnameに、1がcategoryに、1がresultに入る）


###めも
@SpringBootTestのつけ忘れをよくやります

カバレッジがみたいときは
右クリック→カバレッジ→JUnitテストで

##終わり
なんだかんだと毎回調べ物をしている気がしたので備忘録として
書いてみました


##参考サイト
https://www.ne.jp/asahi/hishidama/home/tech/java/junit/5/index.html
【React】Identifier 'Hoge' has already been  declaredの対処法【javascript】

<h2>症状</h2>
Reactで画面作成時に以下のエラーが発生しました。
翻訳すると、「識別子 'Hoge'はすでに宣言されています」でした。
シンプルに、変数が二重に宣言されていると言われているようです。

```terminal:エラー
Identifier 'Hoge' has already been declared 
```

以下が該当のソースです。

```react:HogeHome.jsx
import React,{useState} from "react";
import Hoge from "../Hoge";
import Hoge from "../Hoge";

export const HogeHome = () => {
  
  const [value, setValue] = useState(Hoge);
  
  return (
    {value}
  )
}
```

<h2>解決策</h2>
imortが2重に書かれていた箇所を１つに直したら、解決しました。
importした値やオブジェクトが2重にimportされているため、既に宣言されているというエラーが出ていたようです。

```react:HogeHome.jsx
import React,{useState} from "react";
import Hoge from "../Hoge";
import Hoge from "../Hoge";

export const HogeHome = () => {
  
   const [value, setValue] = useState(Hoge);
  return (
    {value}
  )
}
```

<h2>参考</h2>

https://qiita.com/TRyota/items/d5a7a39da551612dbfd9
useContextを使っていて、Cannot destructure property 'pause' of 'Object(...)(...)' as it is undefined.のエラーがでたとき

useContextを使っているときにこんなエラーが出ました。

```
Cannot destructure property 'pause' of 'Object(...)(...)' as it is undefined.
```
オブジェクトでのpauseが未定義だと言われてしまいました。解決するには本当にエラー文そのままで、pauseの型を考えて上げればいいと思います。
そこで、pauseがあるところまで戻ってみました。

```javascript
\\import React,{createContext} from 'react'
export const Store = createContext()

const App = () => {
   const [pause, setPause] = useState(false)
   return(
  ...

     <Store.Provider value={{pause, setPause}}>
        ..........
     </Store.Provider>

  ...
  )

}
```

そこまで問題がないように見えます。

実は、ここではなくて、importするときにpauseの型が適切ではありませんでした。

```
import Store from './App'
```

これを

```
import {Store} from './App'
```

にしてあげる解決しました。初歩的過ぎますね。オブジェクトの形でStoreに保存しているのにimportする形はオブジェクトでなかったため怒られていたようです。

日本語の記事がなかったため、書いてみました。
Git で commit 間の差分を確認する

たまに使うことがあって、そのたびに「何するんだっけ…？」と言いながらググっている気がするのでメモ。

# 実際の事例１

こんなことがたまにあります。

```
$ git log --oneline
...（長いコミット履歴）
8cc2ae4 プログラムを高速化した
0ad5cb8 ○○機能を追加した
```

**この時の「高速化」って何をどう変更して高速化したんや…？**
そんな時は diff を見ます。

```
$ git diff [変更前のコミットID] [変更後のコミットID]
```

というわけで、この場合は、

```
$ git diff 0ad5cb8 8cc2ae4
```

とコマンドを叩けば、端末に「高速化」の変更箇所が表示されます。

ちなみに、現在のブランチの状態からの差分を見たければ、

```
$ git diff [コミットID]
```

のみで差分が表示されます。

# 実際の事例２

こんなこともたまにあります。

```
$ git log --oneline
...（長いコミット履歴）
8cc2ae4 プログラムを高速化した
0ad5cb8 ○○機能を追加した
```

**この「高速化」を実現するために、どのファイルをいじったんや…？**
そんな時も diff を見ます。

```
$ git diff --name-only [変更前のコミットID] [変更後のコミットID]
```

というわけで、この場合は、

```
$ git diff --name-only 0ad5cb8 8cc2ae4
```

とコマンドを叩けば、端末に「高速化」した時にいじったファイルの名前が一覧表示されます。
PHPunitを使用しテストを行う際のエラー




##課題
 phpunitを使いテストを行う際に下記のエラーが発生。


/usr/bin/php declares an invalid value for PHP_VERSION.
This breaks fundamental functionality such as version_compare().
Please use a different PHP interpreter.



##考えたこと


エラー文にて

```
invalid value for PHP_VERSION.
```


PHPのバージョンが無効な値
→phpのバージョンが原因ではないかと推測。

phpのバージョンを確認


```
php -v

WARNING: PHP is not recommended
PHP is included in macOS for compatibility with legacy software.
Future versions of macOS will not include PHP.
PHP 7.3.24-(to be removed in future macOS) 
```

PHP 7.3.24は将来的にmacOSで削除されるという警告が出ます。
→phpのバージョンをアップデートすれば解消されるのではないか？


##対処法

PHPのバージョンがいけなかったようなのでアップデートします。

###homebrewのインストール

※すでにhomebrewをインストールしている方は飛ばしてください。

インストールする際に以下の記事を参考にさせていただきました。
>https://qiita.com/zaburo/items/29fe23c1ceb6056109fd


###php 7.4をインストール
```
brew search php7
```

インストールできるバージョンを確認
php@7.4があるので

```
brew install php@7.4
```

インストールは以上になります。



###パスを通す

シェルの確認を行う

```
cd ~
echo $SHELL
```

/bin/zshと表示された場合

```
echo 'export PATH=/usr/local/opt/php@7.4/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
```


/bin/bashと表示された場合

```
echo 'export PATH="/usr/local/opt/php@7.4/sbin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
```


を実行しパスを反映させます。



###バージョンの確認
```
php -v
```



バージョンがアップされているかどうか確認を行います。
バージョンが変わっていれば成功です。




##まとめ
PHP 7.3.24に原因があると思い調査しましたが、根本的な原因を解明することはできませんでした。
おそらくですが、macOSでPHP 7.3.24を使用している場合起こるエラーになります。
PHPのバージョンの問題であると推測し、バージョンを変更することによってエラーを解決しました。


##参考

https://blog-and-destroy.com/29755
https://qiita.com/kuroro_ru/items/046cba8e23d32599ee4a
https://qiita.com/zaburo/items/29fe23c1ceb6056109fd
AppDistributionでAPKの代わりにAABを使う

# TL;DR

- 既にfirebase-appdistribution-gradleでAppDistributionに対してAPKをアップロードしている人の変更点です
- いまからプロジェクトを作るなら[CodeLabo](https://firebase.google.com/codelabs/appdistribution-app-bundles)やったほうが良いと思います

## artifactTypeにABBを指定する

artifactType には AAB と APK が指定できます。AABを指定しましょう。
詳しくは[ここ](https://firebase.google.com/docs/app-distribution/android/distribute-gradle?apptype=aab)を参照してください。

```gradle
    firebaseAppDistribution {
        artifactType = "AAB"
    }
```

## Firebase プロジェクトを Google Play アカウントに接続する

AABはデバイスに応じたAPKを配布する仕組みなので、GooglePlayStore経由でインストールすることになるようです。なので、FirebaseとGooglePlayStoreをリンクさせる必要があります。これをしないと `This project is not linked to a Google Play account` というエラーが表示されて失敗します。
詳しくは[ここ](https://firebase.google.com/docs/app-distribution/android/distribute-console?apptype=aab#before_you_begin)を参照してください

> a. 自分が Firebase プロジェクトのオーナーであること、および Google Play アカウントの管理者アカウントまたはオーナーであることを確認します。
b. Firebase プロジェクトで settings（設定）に移動し、[プロジェクト設定] > [統合] の順にクリックします。
c. まだ行っていない場合は、Google アナリティクス カードを使用して Google アナリティクスを有効にします。これは、プロジェクトを Google Play にリンクするために必要です。
d. Google Play カードの [リンク] をクリックします。

# 終わり

上記を行った状態でAABを作成した後にAppDistributionに配布するtaskを起動すればアップロードされます。GooglePlayStore経由で更新されるので初回だけダイアログが出ますが、手順に沿って内部アプリ共有をONにすれば次回からは問題なくダウンロードできるようになります。
GooglePlayStore経由でダウンロードするなら内部テスト版のリリースと一緒じゃないかなと感じましたが、自由にダウングレードすることができるのは便利ですね。ただGooglePlayStoreに登録していない開発環境のアプリの配布などは難しいのかなと感じました。
iframe>シャドウDOMの先にある要素の取得、操作  --メモ--

MDNのHTMLのリファレンスで
https://developer.mozilla.org/ja/docs/Web/HTML/Element/select
のselectタグにアクセスしたかったが、Seleniumでエラーが出て取得できなかった。
調べたら、取得したいタグは iframeの中にあり、さらにShadow DOMがあってその中にあった。
通常のシンプルなロケータではうまくいかなかったので、一工夫してみたら上手くいった。

```csharp
           ChromeDriver driver = new ChromeDriver();

            try
            {
                driver.Manage().Window.Maximize();
                driver.Navigate().GoToUrl("https://developer.mozilla.org/ja/docs/Web/HTML/Element/select");
                var iframe = driver.FindElement(By.CssSelector(".interactive"));
                driver.SwitchTo().Frame(iframe);
                IWebElement shadow_output = driver.FindElement(By.TagName("shadow-output"));
                IWebElement shadow_root = (IWebElement)driver.ExecuteScript("return arguments[0].shadowRoot", shadow_output);
                IWebElement select_pet = shadow_root.FindElement(By.Id("pet-select"));
                var selectObject = new SelectElement(select_pet);
                selectObject.SelectByIndex(2);
            }
            finally
            {
                Console.ReadKey();
                driver.Quit();
            }
```
AndroidのWorkManagerでWorkerにデータが渡らない？

Androidはころころ変わるし、ユーザ的にもUpdateはよくない。そこで、Androidの深いところは使わず、なるべくWebに処理を持ちたい。しかし一方で、普及したハードは利用したい。そこで、AndroidのAPIは最低限だけ使おうと思う。で、KotlinのCoroutineでは書けないことがあって、Background処理のため、WorkManagerを使おうとして。

そこで3日以上はまったので、似たようなことで困っている方のために首記Titleで、残しておきます。

Androidの開発者向けの解説Sample通りに書いても、Workerにデータが渡せない。
何度コードを見直して、ドキュメントを見て、同じことをやるいろいろな書き方を試しても、うまくデータが渡らない。
WorkerにわたったデータをPrintして、ようやく気付いた。
昔書きかけで実行したみたWorkerプロセスが、延々と再試行されていて、その時の結果をDumpさせていた。
今起動した処理は、Queueの後ろにあるのか、まだ実行されていない模様。

新しくQueueにデバッグ済みのWorkerを入れる前に、以前のWorker再試行を全部キャンセルする処理を入れたら、データがちゃんとわたっていましたよ。
[Swift]for文とforEachのどちらを使うか

※この記事は[Swift by Sundell](https://www.swiftbysundell.com/tips/picking-between-for-and-for-each/)の内容を日本語に翻訳したものです。

`Array`や`Set`などのコレクションを反復処理する場合、最初は、従来の`for`ループを使用するか、クロージャーベースの`forEach`メソッドを使用するかは、好みとスタイルの問題のように思われるかもしれません。これらの2つのメカニズムが非常に類似していることは確かですが、いくつかの点で異なります。

これらの違いの1つは、`for`ループの反復がコードの制御フロー内で直接実行されることです。これにより、これらの反復をより正確に制御できます。たとえば、`continue`キーワードを使用して任意の時点で次の要素にスキップするか、`break`を使用して反復を完全に中断するかを選択できます。

```.swift
func recentArticles(among articles: [Article]) -> [Article] {
    var results = [Article]()
    
    for article in articles {
        guard !article.isDraft else {
            // すぐに次の要素にスキップします。
            continue
        }
    
        results.append(article)
        
        guard results.count < 5 else {
            // 反復を中断します。この場合、ここに直接戻ることもできます。
            break
        }
    }
    
    return results
}
```

`for`ループの反復が（上記のように）フィルタリングに使用される`guard`（または`if`）ステートメントで始まる場合、代わりに`where`ベースのパターンマッチングを使用してそのロジックを実装することもできます—次のように：

```.swift
for article in articles where !article.isDraft {
    results.append(article)
    
    guard results.count < 5 else {
        break
    }
}
```

上記の種類の制御フロー関連の機能は、forループを非常に強力にする大きな部分ですが、そのレベルの制御が必要ない場合は、`forEach`の呼び出しを使用すると、コードが少し単純に見える可能性があります。たとえば、ここでは、配列の要素ごとに新しいビューを追加しています。これは、`forEach`を使用して非常にエレガントに実行できます。

```.swift
func addArticleViews(for articles: [Article]) {
    articles.forEach { article in
        let articleView = ArticleView()
        
        // クロージャーの article を使用して新しいビューを設定します。
        ...
        
        view.addSubview(articleView)
    }
}
```

ただし、Swiftのファーストクラス関数機能を使用する方がおそらくさらにエレガントです。上記のメソッドをリファクタリングして単一の`Article`のみを受け入れ、そのメソッドを`forEach`の呼び出しに直接挿入します。

```.swift
class ArticleGroupViewController: UIViewController {
    private let articles: [Article]
    
    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        articles.forEach(addArticleView)
    }

    private func addArticleView(for article: Article) {
        let articleView = ArticleView()
        ...
        view.addSubview(articleView)
    }
}
```

要約すると、`for`ループを使用すると、反復をより高度に制御できます。一方、`forEach`を使用すると、一度開始すると反復を停止することはできませんが、クロージャとファーストクラス関数の機能を利用できます（エラーをスローすることは別として）。

### 元の記事
[Picking between a for loop and forEach](https://www.swiftbysundell.com/tips/picking-between-for-and-for-each/) Swift by Sundell
React - 学ぶべきポイントまとめ【フロントエンド開発入門者向け】

こんにちは！

本記事は React を始める方向けに、必要な学習ポイント、および、参考になるページを紹介します！

本記事では、詳細の解説はしていませんが、以降の連載で解説してきたいと思いますので、良ければ閲覧ください。

## 学習ポイント、参考ページの紹介

### React 公式チュートリアル

https://ja.reactjs.org/tutorial/tutorial.html

### JSX

https://ja.reactjs.org/docs/introducing-jsx.html

https://ja.reactjs.org/docs/jsx-in-depth.html

### State

https://ja.reactjs.org/docs/state-and-lifecycle.html

### Props

https://ja.reactjs.org/docs/components-and-props.html

#### State と Props の違い


https://ja.reactjs.org/docs/faq-state.html#what-is-the-difference-between-state-and-props


###  関数コンポーネントとクラスコンポーネント

https://ja.reactjs.org/docs/components-and-props.html#function-and-class-components

### フック

https://ja.reactjs.org/docs/hooks-overview.html

https://ja.reactjs.org/docs/hooks-intro.html



### Redux

https://redux.js.org/


### バリデーション

https://react-hook-form.com/jp/


### テスト

https://ja.reactjs.org/docs/testing.html



## Ignite UI for React トライアル版を利用するには

Ignite UI for React はトライアル板での試用が可能です。
<a href="https://jp.infragistics.com/products/ignite-ui-react/download" target="_blank">トライアルのダウンロードはこちら</a>

また、<a href="https://iam.infragistics.com/Account/Register" target="_blank">こちらのページ</a> よりアカウントの作成を行っていただければ、実際にサブスクリプションをお持ちの場合と同じ内容のテクニカルサポートをご利用いただくことが出来ますのでぜひご利用ください。（初回利用より30日間）

また、製品をご購入をご検討のお客様は <a href="https://jp.infragistics.com/about-us/contact-us" target="_blank">こちらのページ</a> よりお気軽にお問い合わせください。そのほか、<a href="https://jp.infragistics.com/request-demo" target="_blank">製品デモ</a>や、弊社製品そのものに関するご相談だけでなく、システム開発における様々なご相談も実施可能な<a href="https://jp.infragistics.com/free-consultation" target="_blank">無料相談会</a>も随時受け付けています。


## 開発全般に関するご相談はお任せください！

インフラジスティックス・ジャパンでは、各開発プラットフォームの技術トレーニング、コンサルテーションの提供、開発全般のご支援を行っています。

https://jp.infragistics.com/service-and-support/professional-service


「古い技術やサポート終了のプラットフォームから脱却する必要があるが、その移行先のプラットフォームやフレームワークの検討が進まない、知見がない。」

「新しい開発テクノロジーを採用したいが、自社内にエキスパートがいない。日本語リソースも少ないし、開発を進められるか不安。」

「自社のメンバーで開発を進めたいが、これまで開発フェーズを外部ベンダーに頼ってきたため、ツールや技術に対する理解が乏しい。」

「UIを刷新したい。UIデザインやUI/UXに関する検討の進め方が分からない。外部のデザイン会社に頼むと、開発が難しくなるのではないか、危惧している。」

といったご相談を承っています。

お問い合せは<a href="https://jp.infragistics.com/about-us/contact-us#contactform" target="_blank">こちら</a>からお気軽にご相談ください。


## 技術サポート・無料オンライン相談会をご利用ください

インフラジスティックスのUI製品は多くの機能を備えているためドキュメントの情報量も多く、なかなかお探しの情報に辿り着けない場合もあります。そういった際はお気軽に技術サポートや、製品導入支援担当との無料オンライン相談会をご予約いただくことで検証時間を節約可能ですので、ぜひご活用ください。<br>
<a href="https://jp.infragistics.com/support/dev-support" target="_blank">技術サポートへの問い合わせ方法を確認する</a><br>
<a href="https://jp.infragistics.com/free-consultation" target="_blank">無料オンライン相談会を予約する</a>
毎回ログインするの面倒だから自動でログインをできるようにした

# はじめに
こんにちは。
この前行った美容室、会員カードとか作らない感じのお店で、個人的にいいなと思いました。増えるんすよね、あれって :thinking: 

さて、今回は1日経つとログアウトされちゃうような会員サイトで毎度ログインページに行って、ログインボタン押してが面倒に感じたので自動化しました。

日々の煩わしさから来るストレスを減らしていきましょう :smile:

# 使用するもの
以下拡張機能です。
こちらは、**任意のJavaScript**を実行できる拡張機能です。
ドメインなどのフィルタもできるがいいところ！

https://chrome.google.com/webstore/detail/scriptautorunner/gpgjofmpmjjopcogjgdldidobhmjmdbm?hl=ja

## 使い方
以下記事が参考になりました :bow:

https://qiita.com/itaya/items/36ed8b890c87ac47d9d3

# 実践
今回は**Contentful**のログインを自動化します

https://www.contentful.com/

**ScriptAutoRunner**にスクリプト追加します。
私の場合は**GitHubの**アカウントを使用して**Contentful**にログインします :v:

GitHubでログインするボタンのセレクタはDevtoolsから取得しました。

```js
(() => {
  // Contentfulトップページにアクセスしたらログインページに飛ばす.
  if (location.href == 'https://www.contentful.com/') {
    location.href = 'https://be.contentful.com/login'
  }
  // ログインページのときは、GitHubでログインするボタンをクリックする.
  if (location.href == 'https://be.contentful.com/login') {
    document.querySelector("body > div.row > div > div.account__box.box > div > div.row.row--lessgutter > div:nth-child(1) > a").click()
  }
})()
```

これで、**Contentful**にアクセスした際に自動でログインするようになりました！

# おわりに
いやー、**Vimium**を使用していつもキーボード操作だけでログインしてまして、どのキーを押して行けばログインできるか、複数のサイトで頭に焼き付いてました :innocent:
それでもいいんですが、こんなのさっさと自動化すべきですね、ほかのサイトにもどんどん追加していこうと思います:bow:

それでは！
Local Storageを使ってみる

# Local Storageとは
Local StorageとはHTHL5から導入されたWEB APIの一種で、Javascriptでブラウザにデータを記録する仕組みです。

# 利点
**ブラウザにデータを保存できる**
cookieのようにWEBサーバーにデータを保存するのではなくブラウザに保存するので、
ブラウザを閉じてもユーザーの入力情報などを保持し続けることができます。

**保存容量が大きい**
主要なブラウザなら5MBまでデータを保存できます。

# 注意点
**データは永続的に保存される**
こちらでLocal Storageのデータを削除する処理を書かないと、データは永続的に残り続けるので削除する処理を書きましょう。

**Javascriptから自由にアクセスできる**
セキュリティ上非常に大きな注意点です。
ユーザーの個人情報など、機密性の高い情報には使わないようにしましょう。

# 構文
**保存**
`localStorage.setItem('key', 'value')`あるいは`localStorage.saveKey = 'value'`と書くだけで保存ができます。

```test.js
localStorage.setItem('key', 'value1');
localStorage.saveKey = 'value2';
```

**取得**
`localStorage.getItem('Key')`あるいは`localStorage.saveKey`でvalueを取得することができます。

```test.js
var value1 = localStorage.getItem('Key')
var value2 = localStorage.saveKey;
```

**削除**
`localStorage.removeItem('key')`で指定したキーのデータを削除するか、`localStorage.clear()`ですべてのデータを削除します。

```test.js
localStorage.removeItem('key');
localStorage.clear();
```

# 実装
この記事を読んだ日時を記録する機能を作成しました。
`この記事を見た日を記録`を押すと現在の日時を記録し、`この記事を見た日を表示`で記事を見た日時を表示します。
`クリア`を押すことでLocal Storageのデータを消去します。
日時を記録してからブラウザを閉じ、もう一度この記事を開いて日時が記録されているか実験してみてください。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="dyWvMGr" data-user="sankomasuda" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sankomasuda/pen/dyWvMGr">
  </a> by masuda (<a href="https://codepen.io/sankomasuda">@sankomasuda</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
[Swift]同じ名前の変数に式を割り当てる

※この記事は[Swift by Sundell](https://www.swiftbysundell.com/tips/same-name-assignments/)の内容を日本語に翻訳したものです。

##### Swift 5.4の新機能：
`self`を使って手動で明確にすることなく、同じ名前の式に割り当てられるローカル変数を作成できるようになりました。

たとえば、次の`ItemListViewController`には、単に`item（at :)`を呼び出すように選択した特定の`IndexPath`のアイテムを取得できるメソッドがあります。

```.swift
class ItemListViewController: UIViewController {
    ...

    private func item(at indexPath: IndexPath) -> Item {
        ...
    }
}
```

Swift 5.3以前を使用しているときに、上記のメソッドを呼び出して、その結果を`item`とも呼ばれるローカルの`let`または`var`に割り当てる場合、コンパイラーが使用できるようにするには、メソッド呼び出しの前に`self`を付ける必要があります。 2つを分けるには—次のように：

```.swift
class ItemListViewController: UIViewController {
    ...

    private func showDetailViewForItem(at indexPath: IndexPath) {
        let item = self.item(at: indexPath)
        ...
    }
}
```

ただし、Swift 5.4以降、これは不要になり、コンパイラは、`self`を使用して参照するかどうかに関係なく、右側のアイテムシンボルがメソッドの呼び出しを参照していることを自動的に認識します。

```.swift
class ItemListViewController: UIViewController {
    ...

    private func showDetailViewForItem(at indexPath: IndexPath) {
        let item = item(at: indexPath)
        ...
    }
}
```

おそらく、この新しい構文機能を使用する私のお気に入りの方法は、非同期コードの単体テストを作成するときです。これには通常、組み込みの`expectation`APIを使用して`XCTestExpectation`インスタンスを作成することが含まれます。このような期待の最も自然な名前は単に`expectation`であることが多いため、次のことができるようになったのは本当に素晴らしいことです。

```.swift
class ItemLoaderTests: XCTestCase {
    ...

    func testLoadingItem() {
        let expectation = expectation(description: "Loading item")
        ...
    }
}
```

上記の機能が役立つもう1つのタイプの状況は、プロパティのローカルで変更可能なコピーを作成する場合です。これは、コピーするプロパティを参照するときに`self`を使用せずに実行できるようになりました。たとえば、次のようになります。


```.swift
struct Item {
    var title: String
    var prefix: String?
    var suffix: String?
    
    func fullTitle() -> String {
        var title = title  // 従来は var title = self.title

        if let prefix = prefix {
            title = prefix + title
        }

        if let suffix = suffix {
            title += suffix
        }

        return title
    }
}
```

確かに、これはSwiftコードの記述方法を完全に変える革新的な新しい構文機能ではないかもしれませんが、すべての機能や変更が必要なわけではありません。個人的には、このような「生活の質」の向上は非常に歓迎されており、特定の種類のコードをかなり軽量に感じさせることができると思います。

### 元の記事
[Assigning an expression to a variable with the same name](https://www.swiftbysundell.com/tips/same-name-assignments/) Swift by Sundell
PostgreSQLでカウンターを作る

Webで連番のカウンターが必要な用件があったので実装を検討しました。普段使っているPostgreSQLの上にテーブルを作り、カウンターを実装しました。１追加してUPDATEした値が返ってきます。

# テーブル実装

## Create

テーブルを作成します。

```sql
create table mycounter(
 count_key varchar(16) PRIMARY KEY,
 count int8
);
```

## Count

以下のようなQueryで一致するcount_keyが無い場合は1をセット、存在する場合はカウントアップをして、resultを返します。

```sql
INSERT INTO mycounter (count_key, count) VALUES ('MYCOUNTERKEY', 1)
ON CONFLICT ON CONSTRAINT mycounter_pkey
DO UPDATE SET count = mycounter.count + 1 RETURNING *;
```

# シーケンスを使う

シーケンスを使っても連番を取得する事ができます。こちらの方がIDなどに使えるので応用がきくかもしれません。

## Create

```sql
CREATE SEQUENCE my_seq; -- 指定無しで1 
```

## Count等
```sql
select nextval('my_seq');  --次の値
select currval('my_seq');  --現在の値 
select setval('my_seq', 1);  --1に設定 
```
https://www.postgresql.jp/document/11/html/functions-sequence.html

# むにゃむにゃ

count_keyを変更する事で複数のカウンターを実装したり、日付別や月別での連番を生成する事ができるので、何かと役に立つかと思います。
MySQLでPDO接続時のエラーの出力設定について


###PDO::ERRMODE_SILENT

**デフォルトのエラー設定。**エラーメッセージを出力しない。エラー内容は保持している。 
エラ−を取得するにはPDO::errorCode()かPDO::errorInfo()を使います。


###PDO::ERRMODE_WARNING
いつもの**ブラウザに表示されるエラーを出力させる**にはこの設定がいいと思います。この設定が返すのはE_WARNINGなので、スクリプトは停止されません。

さきほどのPDO::ERRMODE_SILENTと同じくPDO::errorCode()およびPDO::errorInfo()でエラーコード等を取得することも可能です。

開発中はこの設定が便利でいいかもしれません。

###PDO::ERRMODE_EXCEPTION

最後の設定は**例外を投げます**。もっともエラーハンドリングに向いている設定かもしてれません。

この設定をしているとPDOExceptionがスローされます。ですからtrycatch構文でキャッチすれば処理を分岐させることが可能です。

例外オブジェクトからも取得できますが、PDO::errorCode()およびPDO::errorInfo()でエラーコード等を取得することも可能です。


####参考サイト

https://unskilled.site/pdo%E3%81%AF%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%A7%E3%81%AF%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%BA%E5%8A%9B%E3%82%92%E3%81%97%E3%81%AA%E3%81%84%E3%81%A7%E3%81%99/

https://teratail.com/questions/56396
カテゴリカッター＠バケツコレクション

#これは何か
現実を触っていると非常にめんどくさい表現をしてきた歴史があります。
過去、現実ARを書いてきた数多の歴戦達はいろんなこと現代の知見から見ると知りません。
現代に至って、ITの隆興によっていろんな知見は集約されて集められました。

#難点
昔からの人々は癒着を好みます。
単純に速いからですが、癒着によって色々な境界はゆがめられ領域が立たなくなっていきます。
これを切る方法を探すための人生がある人もいますが、単純にナンセンスなのです。
この癒着を切る一つの方法を描いておきます。

#code
```cpp:code.cpp
#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <cstdint>

#define interface struct

interface IUnknown
{
public:
	virtual bool Say() = 0;
	typedef std::shared_ptr<IUnknown> spUnknown;
};

class IOne :public IUnknown {
public: bool Say() { std::cout << "One" << std::endl; return true; }
};
class ITow :public IUnknown {
public: bool Say() { std::cout << "Tow" << std::endl;  return true;}
};
class IThree :public IUnknown {
public: bool Say() { std::cout << "Three" << std::endl; return true; }
};
class IFour :public IUnknown {
public: bool Say() { std::cout << "Four" << std::endl;  return true;}
};

typedef std::vector<IUnknown::spUnknown> Unknowns;
typedef std::map<std::uint16_t, Unknowns> M;

int main() {
	M M = { {1,{std::make_shared<IOne>()}} };

	M[2].push_back(std::make_shared<ITow>());

	M[1].push_back(std::make_shared<IThree>());

	M[1].push_back(std::make_shared<IFour>());

	for (auto& oo: M) {
		for (auto& o: oo.second) {
			o->Say();
		}
		std::cout << std::endl;
	}

}
```
#終わりに
世界にたゆたう数多のモノが狂っています。誰かこれを止めてくれ。
AWSCLI で S3 オブジェクトをダウンロードしようとしたら AccessDenied で困った

# 目的
S3の特定オブジェクトをAWSCLIでEC2のローカルにダウンロードしたい。

# 発生事象
以下ローカルへのダウンロードコマンドを実行するとAccessDeniedエラー

```
$ aws s3 cp s3://sourcebucket/object.jpg ./
download failed: s3://sourcebucket/object.jpg to ./object.jpg An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
```

バケットポリシーとIAMロールの権限周りを確認するが、実行可能な権限設定に見える。
事実、GetObjectと同様に設定したListBucket権限の以下コマンドを実行すると正常に機能
する。

```
$ aws s3 ls s3://sourcebucket/
2021-07-13 10:56:40    8574 object.jpg
```

# 原因と対処
S3バケットのデフォルト暗号化の有効（KMS）に起因していた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363093/a5a84ca9-f02f-88b4-f3ca-a04cfc852c7d.png)

そのため、S3バケットで使用しているKMSの「キーユーザー」にユーザーまたはロールを追加して解決した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363093/b9a1b218-1ba6-d434-d34f-942272c26c52.png)

# 参考
以下のおかげで解決に至りました。
https://base64.work/so/amazon-web-services/1209321
みんながよく使うawsリソースとは？【2021年上半期】

webエンジニアならAWSは必須ですね。
最近は、サーバーレスも定着してきて、これまでのEC2メインでもなくなってきたので、勝手ランキングを発表！
（2021年上半期版）

これからのwebサービス開発の参考にしてください。

# 人気awsリソースランキング　4位～10位

第 **4** 位 **Lambda**

軽いちょっとした処理は、lambdaにして呼び出すのが便利ですね。
もう自前ライブラリを構築する必要はなくなりました。
[AWS Lambda 料金](https://aws.amazon.com/jp/lambda/pricing/)

第 **5** 位 **DyanmoDB**

NoSQL便利！しかも、速い！スケーラビリティ！
RDB思想からの脱却に苦労するかもしれませんが、価値はかなり高いです。
[Amazon DynamoDB 料金](https://aws.amazon.com/jp/dynamodb/pricing/)

第 **6** 位 **API Gateway**

サーバーを立てて、APIキー認証をしっかり作って、バージョンを管理して、から脱却できます。
トラフィックスピードも制御できるので、もう自前API構築は、きっとしないです。
[Amazon API Gateway の料金](https://aws.amazon.com/jp/api-gateway/pricing/)

第 **7** 位 **Step Functions**

サーバーレスでは絶対に欠かせません。ロジックを構築できます。
Lambdaでロジックを組む必要がなくなった上、図表示できるのでとても理解しやすくなりました。
[AWS Step Functions の料金](https://aws.amazon.com/jp/step-functions/pricing/)

第 **8** 位 **EC2**

やっぱり必要ですね。Linux。
一通りをLinuxで組む場面ではまだまだ現役です。でも最近は、単用途ばかりな気がします。
[Amazon EC2 の料金](https://aws.amazon.com/jp/ec2/pricing/)

第 **9** 位 **CodeBuild**

これがないと何も進みません。devもprodもデプロイするのに大活躍です。
かなり自由度が高いので、複雑でカオスになりそうでヤバイです。
[AWS CodeBuild の料金](https://aws.amazon.com/jp/codebuild/pricing/)

第 **10** 位 **RDS**

リレーショナルDBは、当然必要です。歴史もありますし構築しやすいです。
どんなに複雑に組んでも、学習コストが少なくてすむのは素晴らしいです。
[Amazon RDS の料金](https://aws.amazon.com/jp/rds/pricing/)

---
では、第3位から第1位までの発表です！
---

# 人気awsリソースランキング　3位　CloudShell

ご存じですよね！めちゃ便利！
linuxコマンド（aws/cli）を叩くのにEC2を起動する必要はありません！
[AWS CloudShell pricing](https://aws.amazon.com/jp/cloudshell/pricing/)

# 人気awsリソースランキング　2位　S3

もはや不動のポジション。awsの超初期からあるリソースです。
今だに機能拡張されていて、ファイルを簡単に安全安心に操作できるのはこの上ないメリットです。
[Amazon S3 の料金](https://aws.amazon.com/jp/s3/pricing/)

# 人気awsリソースランキング　1位　CloudFormation

まさかポチポチしてawsリソースをつくっていませんか？作成も更新もコードで管理できます。
インフラをバージョン管理できるのは、セキュリティ観点からもアクシデント観点からもメリットばかりです。
[AWS CloudFormation の料金](https://aws.amazon.com/jp/cloudformation/pricing/)

- ハードウェアを管理しなくてよいのは、とてもありがたいです。
- これまでは、かなり余裕を見込んだハードウェアを選定してデータセンターに設置、もしくは、同じくスペックを選定してレンタルサーバーを契約。
- でオーバースペックや不足が出てしまったら、切り替えるためだけのシステム障害リスクや、精神的負担、段取り、過渡期の無駄費用の発生など大きなデメリットがありました。

でも、ポチポチとクリックしてリソース作成するのは、ドキュメント整備の苦労や属人性などから、実質の再現性が低くなる場面があるため、コード管理できるCloudFormationは重宝します。

---
以上、2021年上半期ランキングでした。

:::note warn
筆者の見識による勝手な推測ですので、ぜひコメントください。
:::

**次に、関心があるのは・・・**

1. 買う側サービスは、とても便利に進化しましたが、売る側は、まだまだなのが現実です
1. なので、今、売る側に注力しています。（と、言ってもかなり前からですが・・・）
1. 一緒に「売り方コミュニケーション」を進化させませんか？
1. エンジニア募集中です。採用エリアは【日本全国】
1. 【完全リモートワーク】でみんな働いています
1. 学生アルバイト、一般アルバイト、副業、中途社員、新卒社員、業務委託があります
1. エントリーは、https://www.combz.jp/recruit へ
Windows Terminal でビープ音を消す方法

# 概要
Windows Terminal を使用していると、
コマンド履歴を呼び出す際やTab補完をする際に鬱陶しいビープ音が鳴る。
そのビープ音を消す方法を紹介する。



# 1. Windows Terminal を実行し、`Ctrl + ,` で設定画面を開く



# 2. ビープ音を消したいプロファイルを選択

![setup_windows_terminal_beep_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645714/4e35c7af-c54d-07a0-844b-228ce6c1656f.png)


# 3. `詳細設定` をクリック

![setup_windows_terminal_beep_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645714/390c4931-2cc2-e23a-f3c6-e859c991a2a9.png)


# 4. 1番下の設定項目 `ベル通知スタイル` を `なし` に変更

![setup_windows_terminal_beep_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/645714/13b7309d-f313-a42f-8319-8a886d9b2e57.png)


# 5. 右下 `保存` をクリック



以上。
とても簡単。
[GAS] URLがわからない他者開発ライブラリを解析する必要がある場合の対処方法

## はじめに

クラウドソーシングの案件では、ＧＡＳが動かなくなったから修正してほしい、というものがそこそこあります。その中でも外注先の開発者（クラウドワーカー）と連絡がつかなくなった、というものがかなりの割合を占めているように思えます[^1]。

その中には、稀ですが自作のライブラリを使用しているものがあります。挙動や処理内容を確認したいのに、そのような案件に限って、ライブラリのドキュメントが記述されていません（あくまでも個人的な感想です）。クライアント様もライブラリの存在は知らない、もちろんGitHub等で管理されているわけでもない。ライブラリ本体を解析する必要があるがどうしたものか、というときの小ネタです。

## 利用場面

他者開発プロジェクトのリファクタリングでライブラリ本体の解析が必要になった、ライブラリのスクリプトＩＤがわからないといったケースが考えられます。

まず、**ライブラリが生存している**ことが大前提となります。

### スクリプトＩＤを調べる

1. 当該プロジェクトのスクリプトエディタを開きます。
1. 左側の歯車ののようなアイコンで設定画面を開きます。
1. 「appsscript.json」マニフェスト ファイルをエディタで表示する　にチェック。

![library01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111613/2027834d-e790-a569-8b91-764eb2d81a0c.png)

4．「＜＞」アイコンをクリックし、コード編集画面に戻ります。
5. 「ファイル」からappsscript.jsonをクリックします。

![library02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111613/fb1e410b-7e67-bcec-b02c-16f3073130f7.gif)

### ライブラリを開く

以下ＵＲＬの{SCRIPT ID}を先程調べたスクリプトＩＤと差し替えると、ライブラリ本体を開くことができます。

`https://script.google.com/home/projects/{SCRIPT ID}/`

当然のことですが、コピーを作成した上で解析しましょう。

誰かの役に立てれば幸いです。
AWS CloudTrailとは？

エンタメ系企業の社内もろもろを担当しているakibinです。

最近はレノン・ステラって人の[Summer Feelings](https://open.spotify.com/track/49dFIRQCQxPWgoH0m38XQ5?si=4eee8ccee91e4f96)にハマってます。夏だよね〜

# やったこと
CloudTrailとは？の備忘録です。

# CloudTrailとは
CloudTrailはAWSの管理コンソールやCLI、SDKなどでどのような操作が行われたか記録するサービスです。
いつ、誰が、何をしたかを記録、確認ができます。

# ログの種類
取得されるログは大別すると以下3つです。
#### 管理イベント
EC2インスタンスの作成・操作や、S3バケットの作成、IAMの操作などAWSリソース操作全般
デフォルトで有効で、90日間まで無料で記録される。

#### データイベント
S3バケットのデータ操作、Lambda関数の実行などデータ関連のイベント。
データイベント記録は有料。イベントが発生した分だけ料金が発生。

#### インサイトイベント
管理イベントを分析、異常なアクティビティを検出。
分析は有料。分析した分だけ料金が発生。

# CloudTrailのメニュー
#### ダッシュボード
イベント履歴、証跡、インサイトがまとめてダッシュボードで確認できます。
![スクリーンショット 2021-07-15 11.42.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/f45874d7-2777-de41-5fd3-b5d2ead114d3.png)

#### イベント履歴
過去90日間の管理イベントを確認可能。
イベントソースで検索するとわかりやすいかもと思いました。
![スクリーンショット 2021-07-15 11.48.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/c688e55b-bdc8-f6ce-9b74-126dfa4a6b89.png)

#### Insights（インサイト）
私はまだ使用したことがないのですが、後述する証跡でインサイトイベントを有効にすると、分析の結果、異常なアクティビティがこのメニューで確認できるようです。

#### 証跡
以下用途で証跡は使用します。証跡を作成すると、ログはS3に保管されます。
![スクリーンショット 2021-07-15 13.06.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/e1b20094-b7ec-6639-3a59-dc86f3839843.png)

* 管理イベントを90日以上保管する場合（S3の保管費用が発生）
* データイベントを有効にする（S3の保管費用 + イベントが発生した分だけ料金が発生）
* インサイトイベントを有効にする（S3の保管費用 + 分析した分だけ料金が発生）

有効にするイベントは証跡作成中に選択できます。
![スクリーンショット 2021-07-15 13.19.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/389c0177-e016-5e03-36d9-9f7a5c628aa2.png)

よし、これでとりあえずはCloudTrailが何なのかは理解できました。

これを踏まえて、次回はCloudTrailとCloudWatch Logsを使用して、IAM関連の管理イベントが発生した場合の通知設定方法をやってみようと思います。
↓↓↓やってみました。
[CloudTrailとCloudWatchLogsを使用してIAM関連イベントの通知](https://qiita.com/akibin/items/af88e49ccc27bb72c4ed)

# こちらもチェックお願いします！
[Twitterアカウント](https://twitter.com/akibinmusic)
[Youtubeチャンネル](https://www.youtube.com/channel/UC-JOpwEnJn3gCrUA4NdCYgg)
PHP ローカルスコープ内で変数名を使い回すのはなるべくやめようと先輩から教わった

# 目的

- 先輩から教わったことをメモ的にまとめる

# ご注意

- 本ソースは他のエンジニアの方が書いてくださったものです。
- ソースの設計思想はいくつか存在し、正解はいくつもあります。
- 本記事は筆者個人の意見であり、登場人物である先輩の考えも実際とは異なる可能性があります。
- 例として記載するソースは元のものからかなり修正をしております。

# 情報

- 下記の様なソースが記載されていた。

    ```php
    public function foo()
    {
        $adminUserInfos = $this->userService->getAllAdminUserInfo();
        foreach($adminUserInfos as $adminUserInfo) {
            $user_id = $adminUserInfo->id;
            $user_name = $adminUserInfo->name;
            $this->mailService->sendMail($user_id, $user_name);
        }

        $userInfos = $this->userService->getAllUserInfo();
        foreach($userInfos as $userInfo) {
            $user_id = $userInfo->id;
            $user_name = $userInfo->name;
            $this->mailService->sendMail($user_id, $user_name);
        }
    }
    ```

# 先輩が言っていたことと筆者の初見の所感

- 「ローカルスコープ内で変数は使い回さないほうが良いかもしれない」
- どういうことかというと、上記のソースは１つ目のforeachで`$user_id`と`$user_name`を定義して他メソッドの引数として使っている。
- 更に2つ目のforeachで`$user_id`と`$user_name`を更に定義している。
- 筆者は問題ないと思ってしまった。何なら処理に一貫性があって良いソースだと思った。
- 先輩曰く「1つ目のforeachが終わった後に`$userInfos = $this->userService->getAllUserInfo();`エラーかなにかでスルーされてしまったら事故になる可能性がある」ということだ。
- 上記のソースに限っては$userInfosがnullなどだった場合、foreachが動作することは無い。
- しかしながら、先輩はこのソースに限った話ではなく、そもそも「ローカルスコープ内で変数名を使い回すと事故につながる可能性になるのでやめたほうが良い」と言っていると筆者は受け取った。
- 個人的に非常に学びになった。

# どのように記載すると事故は防げるのか

- 今回のソースで言うと2個回避策があると思う。
- 下記に先輩が提案されていた回避策を記載する。

    ```php
    public function foo()
    {
        $adminUserInfos = $this->userService->getAllAdminUserInfo();
        foreach($adminUserInfos as $adminUserInfo) {
            $this->mailService->sendMail($adminUserInfo->id, $adminUserInfo->name);
        }

        $userInfos = $this->userService->getAllUserInfo();
        foreach($userInfos as $userInfo) {
            $this->mailService->sendMail($userInfo->id, $userInfo->name);
        }
    }
    ```

- 先輩は変数に入れずにそのまま直接引数として使用する方法を挙げられていた。その後使う予定の無い変数を増やすより事故は減りそうである。
- 下記に筆者が考えた回避策を記載する。

    ```php
    public function foo()
    {
        $adminUserInfos = $this->userService->getAllAdminUserInfo();
        foreach($adminUserInfos as $adminUserInfo) {
            $admin_user_id = $adminUserInfo->id;
            $admin_user_name = $adminUserInfo->name;
            $this->mailService->sendMail($admin_user_id, $admin_user_name);
        }

        $userInfos = $this->userService->getAllUserInfo();
        foreach($userInfos as $userInfo) {
            $user_id = $userInfo->id;
            $user_name = $userInfo->name;
            $this->mailService->sendMail($user_id, $user_name);
        }
    }
    ```

- 筆者は単純に変数を使い回さないようにした。ただそれだけ。

# 感想

- 先輩とソースを一緒に読むと非常に学びになることがわかった。
- どうにかして一緒にソースを読んで意見を出し合う時間を作りたいのだけれど、、、なかなか難しい。
GitLabでユーザーごとにpushの許可制御を行う

#書いてあること
GitLabでサーバサイドhookでpush時にスクリプトを実行して許可／拒絶を制御する方法。

#きっかけ
パートナーさんと１つのリポジトリを使って協業するプロジェクトで、パートナーさんにはdevelopとfeature以外は触ってほしくなかった。注意喚起だけでは弱いのでできたら機械的にできないかと考えた。

#要約
GitLabにはpush等のアクションに応じてイベント検知しスクリプトを走らせることができる。

|イベント名（スクリプトファイル名）  |説明  |
|---|---|
|pre-receive  |クライアントからのプッシュを処理するときに最初に実行されるスクリプトが pre-receive です。  |
|update  |update スクリプトは pre-receive スクリプトと似ていますが、プッシュしてきた人が更新しようとしているブランチごとに実行されるという点が異なります。 複数のブランチへのプッシュがあったときに pre-receive が実行されるのは一度だけですが、update はブランチ単位でそれぞれ一度ずつ実行されます。   |
|post-receive  |post-receive フックは処理が終了した後で実行されるもので、他のサービスの更新やユーザーへの通知などに使えます。  |


今回はブランチごとに制御を行いたいので、upateスクリプトで対応しました。

#やったこと
GitLabサーバ上に以下のシェルスクリプトを新規作成。配置場所は決まっている模様。

```sh:[/srv/gitlab/data/git-data/repositories/(リポジトリグループ名)/(プロジェクト名).git/custom_hooks/update]
#!/bin/sh
#
# Git's update hook for submit control [2011-07-12]
#

# User setting file
readonly AUTH_USERS_FILE='authorized_users'

# Branch name the user is about to push to.
target_branch="$1"

# Fullpath of hooks dir.
self_dir=$(cd $(dirname $0); pwd)

# 1 if the target branch name can be found in the $AUTH_USERS_FILE.
is_restricted=0

# Parenthetic section which represents a branch name in the $AUTH_USERS_FILE.
current_section=''

echo "user-id:"$GL_ID
echo "user-name:"$GL_USERNAME

# Search user names.
while read line
do
    # Remove comment.
    line=${line%%#*}

    # Remove trailing spaces.
    line=$(echo $line | sed -e 's/ *$//')

    # Empty line.
    if [ -z "$line" ]; then
        continue
    fi

    # ここのブロックでpushしようとしているブランチを特定
    # Parse section name. e.g. 'refs/heads/master'.
    section=$(echo $line | sed -n -e 's/\[\(.\+\)\]/\1/p')
    if [ -n "$section" ]; then
        if [ "$section" = "$target_branch" ]; then
            is_restricted=1
        fi
        current_section="$section"
        continue
    fi

    # 後術するホワイトリストにユーザー名があるかで許可判断
    # Check if the user is listed.
    if [ "$current_section" = "$target_branch" ]; then
        if [ "$GL_USERNAME" = "$line" ]; then
            # The user can push to the branch.
            exit 0
        fi
    fi
done < "$self_dir/$AUTH_USERS_FILE"

if [ $is_restricted = 0 ]; then
    # No restriction. The user can push to the branch.
    exit 0
fi

echo ""
echo "----------------------------------------------"
echo "[$target_branch] is in submit control."
echo "You do not have access to this branch."
echo "Please wait until the submit control finishes."
echo "----------------------------------------------"
echo ""

# The user cannot push to the branch.
echo "GL-HOOK-ERR: You aren't allow push to $target_branch branche."
exit 1

```

同じ場所にブランチごとに許可するユーザー名をファイルで記述します。ホワイトリスト形式です。

```sh:[/srv/gitlab/data/git-data/repositories/(リポジトリグループ名)/(プロジェクト名).git/custom_hooks/authorized_users]
[refs/heads/master]
userA

[refs/heads/develop]
userA
userB

[refs/heads/release]
userA

[refs/heads/hotfix]
userA

[refs/heads/feature]
userA
userB
userC
```

上記の例だと、userAが開発～リリースまで全てを行う人、userBが開発～マージまでの人、userCが開発のみと、
役割に応じてpushできるブランチが制御できる。
Pyflow使ってDjangoが使える環境を作る

# はじめに
Pyflowを使いながらDjango環境構築方法が探してもなかったので、どうやってやったのかここにメモします。

# Pyflowとは

> ***引用***
Pyflow はおそらく一番新参のパッケージ管理ツールです。Rust で書かれており、Poetry で導入された PEP 518 に加え、PEP 582 で提案された、プロジェクト内で扱える仮想環境を複数の Python バージョンに対応させることができます。Pyenv + venv で 1 つの Python のパージョンの 1 つの仮想環境を扱う Pipenv/Poetry に対して、Pyflow は単体で Python のバージョンを複数管理して任意のバージョンで仮想環境を作ることができます。現環境で大きな恩恵は無い気もしますが、今後 Python にメジャーアップデートがあった場合などに重宝されるかもしれません。個人的な懸念は Rust で書かれていることで、速度等で恩恵がありそうな一方で、Rust にある程度の理解がないとエラーメッセージに対応しづらい点と、開発コミュニティが伸びにくいということです。
> [@sk217さん - 2020 年の Python パッケージ管理ベストプラクティス](https://qiita.com/sk217/items/43c994640f4843a18dbe)

# Pyflowのインストール

```zsh
$ brew install pyflow
```

# PyflowでProjectを作成
```zsh
$ pyflow new プロジェクト名
```

## プロジェクト作成手順
```zsh
$ pyflow new sample

#使いたいPythonのバージョン書いてください
Please enter the Python version for this project: (eg: 3.8)
Default [2.7.16]: 3.9
Created a new Python project named sample
```

# Djangoをインストール
```zsh
# 作ったプロジェクトファイルに移動
$ cd プロジェクト名
# Djangoをインストール
$ pyflow install django
```

###　インストール手順
```
HEKUTA sample % pyflow install django
Found multiple compatible Python versions. Please enter the number associated with the one you'd like to use:
1: python3.9: 3.9.6
2: python3: 3.9.6
1
🐍 Setting up Python...
⬇ Installing pytz 2017.2 ...
⬇ Installing django 3.2.5 ...
Added a console script: django-admin
⬇ Installing sqlparse 0.4.1 ...
Added a console script: sqlformat
⬇ Installing asgiref 3.4.1 ...
Installation complete
```
### なぞのエラー
わかる方がいれば教えてください
これが出たりするんですが、一様djangoは動きました。細かいこと試してないので、心配な方はファイルを消して、最初からやり直してみてください

```zsh
HEKUTA sample % pyflow install django
Found multiple compatible Python versions. Please enter the number associated with the one you'd like to use:
1: python3.9: 3.9.6
2: python3: 3.9.6
2
....　省略
        ],
        extra: None,
        sys_platform: None,
        python_version: None,
        install_with_extras: None,
        path: None,
        git: None,
    },
]
             It's taking a long time to get dependency data - this usually suggests that the dependency tree is being newly built. Please try again in a few minutes, and if the error still occurs, consider opening an issue on github.
HEKUTA sample % 
```

# パッケージのビルド
インストールが終わったらパッケージをビルドします

```zsh
$ pyflow package
```

#Djangoの起動
djangoのプロジェクトを作ってください。

`プロジェクト名/プロジェクト名/djangoproject`の中に作りました。
`プロジェクト名/djangoproject`ていう感じでも動いたんですけど、どっちが正解かわからないので、私は`プロジェクト名/プロジェクト名/djangoproject`にしました

# 起動！
```
$ cd djangoproject
$ pyflow manage.py runserver
```


# 参考にした記事
https://qiita.com/sk217/items/43c994640f4843a18dbe