OmniAICreator/Qiita-1.07M huggingface dataset:
FlutterでFirebaseのパッケージを導入する(主にIOS)

###概要
FlutterでFirebaseのパッケージを導入するための最低限の手順です。
少し厄介なIOSでの実装について書いていきます。

####1. pubspec.yamlにパッケージを入れる
使いたいパッケージを`pubspec.yaml`に入れて`Pub get`を実行する。
####2. CocoaPodsをインストールする
podのリポジトリを更新する前に`ios/Podfile`を開き、2行目にあるコードをコメントアウトから解除し、新しいバージョンに指定する。
![スクリーンショット 2021-09-02 15.11.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/f40d59f8-7c5b-781c-eb7d-bfbd2f6b0fb2.png)

また、RunnerターゲットのIOSバージョンもXcodeから変更する。
![スクリーンショット 2021-09-02 16.01.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/dc8766d7-ec63-38ce-e979-59e7c6a8fb32.png)


その後、以下のコマンドをターミナルで実行する。(数分かかる)

```
$ pod repo update
```

完了したらCocoaPodsをインストール。
`sudo get install cocoapods`だけだと`/usr/bin`配下に書き込み権限がないとのことでエラーになった。パスを指定することで権限のもとに実行できる。

```
$ sudo gem install -n /usr/local/bin cocoapods
```

####3. 起動できるか確認
エミュレータをIOSのデバイスに指定して`Run`を実行。
エラーが起きなければ完了。

(注意)
エミュのOSのバージョンを確認してください。2.で指定したバージョン以前のデバイスで起動するとアプリが開いた瞬間に強制終了します。しかもコンソールにエラー文など出力しないため、何が原因かわからずに2時間以上詰まっていたバカがいたそうです。

####(おまけ)Androidの場合
Androidで起動する際は、`android/app/build.gradle`のdefaultConfig内のminSdkVersionを23以上にすること(おそらく初期は16とかになってる)。
![スクリーンショット 2021-09-02 16.30.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/a8b231b7-5cc7-dd1c-029b-01eb514bb907.png)
Vue.jsのwatchが動かない謎を解け

# 問題

早速ですが以下のコードを見てください。
カウントアップボタンを１回クリックした際に、最初に出力される数字は何でしょう？
出力している部分は```components/Counter.vue```の①の部分です。

(A) 0
(B) 1
(C) 2
(D) 何も出ない

```typescript:pages/index.vue
<template>
  <div>
    <counter v-if="counter > 0" />
    <button type="button" @click="increment">カウントアップ</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, inject, provide } from "@nuxtjs/composition-api";
import useCounterStore, {　CounterStore,　CounterStoreKey　} from "~/stores/CounterStore";
import Counter from "~/components/Counter.vue";

export default defineComponent({
  components: { Counter },
  setup() {
    provide(CounterStoreKey, useCounterStore());

    const { counter } = inject(CounterStoreKey) as CounterStore;

　　　　　　　　const increment = () => counter.value++;

    return {
      counter,
      increment
    };
  },
});
</script>
```

```typescript:components/Counter.vue
<template>
  <div>{{ counter }}</div>
</template>

<script lang="ts">
import { defineComponent, inject, watch } from "@nuxtjs/composition-api";
import { CounterStore, CounterStoreKey } from "~/stores/CounterStore";

export default defineComponent({
  setup() {
    const { counter } = inject(CounterStoreKey) as CounterStore;

    watch(counter, () => console.log(counter.value)); // ①

    return {
      counter,
    };
  },
});
</script>
```

```typescript:stores/CounterStore.ts
import { InjectionKey, ref } from "@nuxtjs/composition-api"

const useCounterStore = () => {
  const counter = ref(0)
  return { counter }
}

export type CounterStore = ReturnType<typeof useCounterStore>
export const CounterStoreKey: InjectionKey<CounterStore> = Symbol('CounterStore')
export default useCounterStore
```

# 正解

(D)の「何も出ない」です。

# 理由

この問題のカギとなるのは、```v-if```です。
```pages/index.vue```で、```components/Counter.vue```の表示に、```v-if```を利用しています。
Vue.jsを使ったことがある人だったらわかると思いますが、```v-if```は特定の条件の場合のみ表示するためのディレクティブです。

今回の場合、```counter > 0```の場合に表示されるようになっているので、初期表示時は```counter = 0```なので表示されないようになっています。さらに、v-ifはHTMLタグ自体も出力しないため、Counterコンポーネントがページ上にない状態です。つまり、```watch```も動作しないため、0 → 1の変更の検知はできないということになります。

最初のカウントアップで、```counter```が1となり、Counterコンポーネント が表示され```watch```が設定されるようになり、以降、カウンターの変更を検知し```watch```で指定した関数が実行されます。


# どうすればよいか

```v-if``` ではなく、```v-show```を使うことで、問題を解決できます。```v-show```はHTML自体は出力され、CSSの```display```で表示切り替えを行います。Counterコンポーネント自体は出力されているので、画面上見えてなくても、```watch```は動くようになります。
【jquery】val()の使い方    ※value値を取得するだけ

#jQuery 

```javascript
<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <div class="target">
     <input  value="1">
     <input name="shain_name"  value="ABCDEFG">
     <input  value="2">
     <input  value="8888" class="pKisu" >
   </div>
    <script src="jquery-3.6.0.min.js"></script>
    <script>
      $(function(){
//////////////↓ここの部分///////////////////////////
        result_01 = $('.target').find('input[name=shain_name]').val();
        result_02 = $('.pKisu').val();
//////////////↑ここの部分///////////////////////////
        console.log(result_01);
        console.log(result_02);
      });
    </script>
```


#出力結果
```
ABCDEFG
8888
```
Expo with React-NativeでカメラロールからファイルをS3にアップロード（署名付きURL/axios）

# 概要

Expo + React-Nativeでカメラロールにある画像や動画をS3にアップロードしようとしたところ、
色々ハマったのでメモ

- expo + react-native
- カメラロールへのアクセスは `ImagePicker` を使う
- S3は署名付きURLを使ってアップロード
- axiosを使う

注）
S3署名付きURLとS3へのアップロードの部分についてはこの記事ではあまり触れません。
試している環境はあらかじめ、署名付きURLを発行するApi Gateway経由のLambdaで作成してあり、それを使っています

# ハマったところ

## ImagePickerで取得したデータがBlobじゃない

サブタイトルのとおり。

```typescript
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1
    })

```

こんな感じでファイルを取得するが、 `result` にはBlobを返してくれない

```typescript
export declare type ImagePickerResult = {
    cancelled: true;
} | ({
    cancelled: false;
} & ImageInfo);


export declare type ImageInfo = {
    uri: string;
    width: number;
    height: number;
    type?: 'image' | 'video';
    exif?: {
        [key: string]: any;
    };
    base64?: string;
};

```

`file uri` は返却されているので、これを使ってBlobに変換する。
uri -> blobは `fetch` を使うことで変換できる
(React-Native周りでblob変換してくれるいいライブラリがないのでfetchで代用した)

```typescript
const blob = await fetch(result.uri).then(r => r.blob())
```

## axiosでBlobをS3にputしたらなぜかJSONファイルがアップロードされた

変換してできたBlobをaxiosでPUTしたら、S3にアップロードはされるものの
極端にサイズが小さい・・・

ダウンロードしてみると、JSONがアップロードされていた。なぜ・・・

 試しに `fetch` でputしてみたらちゃんとアップロードされた

```typescript

// これはちゃんとアップロードされる
await fetch(signedurl, {
  method: 'PUT',
  body: blob
})

// これだとblobでなくてJSON(!?)がアップロードされる
await axios.put(signedurl, blob, {})

```

悩みに悩んだ末、axiosがrequest bodyのblobを勝手に `JSON.stringify()` で
parseしているんじゃないかと推察し、configでparseをやめさせてみたところうまくいった！

```typescript

// request bodyはそのまま使え
await axios.put(signedurl, blob, {
  transformRequest: data => data,
})

```

# 出来上がり

抜粋版のソース

```typescript

// カメラロールから選択したファイルを取得
const result = await ImagePicker.launchImageLibraryAsync({
  mediaTypes: ImagePicker.MediaTypeOptions.All,
  allowsEditing: true,
  aspect: [4, 3],
  quality: 1
})

// ファイルをblobに変換
const blob = await fetch(result.uri).then(r => r.blob())

// S3署名付きURLの取得
const signedurl = await axios.get('[s3の署名付きURLを取得するためのURL]')

// S3にアップロード
await axios.put(signedurl, blob, {
  transformRequest: data => data,
})

```
node-webrtcのサンプルを動かしてみる



# 環境

- Windows 10
- node-v16.8.0-x64.msi
- コマンドプロンプト
- Google Chrome Version 93.0.4577.63 (Official Build) (64-bit)


## 注意

- node.jsがLTS版の node-v14.17.5-x64.msi だと `npm install` Windowsのアクセス違反のエラーが出て動作しなかった
  - LTS版の方が安定していると信じこんでいて、少しはまってしまった

```
npm ERR! code 3221225477
```

# 背景

- 様々な環境で動作するWebRTCのライブラリを探している
- ブラウザなしで、気楽に通信テストを行いたい
- 候補の１つとして、`node-webrtc` を触ってみる

# node-webrtc とは

> Node.js Native Addon that provides bindings to WebRTC M87. 

- 「Node.js のネイティブのアドオンで、WebRTC M87準拠」と捉えればよいでしょうか
  - WebRTC M87は、 Nov 6, 2020にリリースされているようだ
  - node-webrtcのWebRTC M87対応は、Nov 3, 2020あたりにコミットされている

https://github.com/node-webrtc/node-webrtc

## WebRTCのRelease Note

- 2021/9/2時点、以下のリストでは、M89が最新のようだ

https://chromium.googlesource.com/external/webrtc/+/master/docs/release-notes.md

# node-webrtcサンプルを触ってみる

## サンプルファイルの場所

https://github.com/node-webrtc/node-webrtc-examples

## サンプルの全体の処理の流れ

- サンプルは、node.jsのExpressフレームワークを用いたWebアプリの形で提供される
- node.js同士でWebRTC通信をするサンプルではなく、「node.jsサーバー」と「ブラウザ」でWebRTC通信するサンプル
  - browserifyを使って、コードをブラウザで動作するコードに変換している
- RTCPeerConnection Negotiationは、REST API（HTTP）で実現している

## RTCPeerConnection Negotiationの流れ

- 以下の図は、 https://github.com/node-webrtc/node-webrtc-examples より抜粋
- Express フレームワークのHTTPサーバーを使って、LocalDescriptionとRemoteDescriptionを交換している

![ss1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083912/4d0a0cdd-c81f-aa27-4cf1-1cb20493947a.png)


## 実行したコマンド

```
git clone https://github.com/node-webrtc/node-webrtc-examples.git

npm install

npm start

> node-webrtc-examples@0.1.0 start
> node index.js

http://localhost:3000

```

## 実行結果

- ブラウザで、http://localhost:3000 を開く
- 以下は、一番、簡単そうな DataChannelを使ったテキストデータをやりとりするサンプルを実行した結果
- ブラウザ側の Consoleにログが出ることを理解するまでに時間がかかった（実は一番、難しかった）
  - node.jsを実行したターミナルをずっと眺めていた

![ping-pong.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083912/2451c7c6-dd59-cbfa-9b0a-e42b2b56bf6a.gif)



# 感想

- node.js(node-webrtc)同士で通信するサンプルではないという点を理解して、「node.js(node-webrtc)のコード」と「ブラウザ用のコード」を区別して理解する必要がある（同じjsファイルなので、これはどっちで実行されるのかな？と混乱してしまった）
- node-webrtcを使えば、ブラウザで動作するWebRTCと同じように書けそうなので、取り急ぎ動かすならば、以下のコードを見るだけでよかったかもしれない
  - https://github.com/node-webrtc/node-webrtc-examples/blob/master/lib/server/connections/webrtcconnection.js
TypeScript + webpack 個別tsconfig.jsonを使って複数の出力

###はじめに
https://qiita.com/twinemarron/items/7adca7b911caa2718823
TypeScriptとwebpackを使って、サーバーとフロントが同じ感じにかけたら素敵だなぁっと思い、調べてみるとできるみたい。すごくいい。

ただ、tsconfogが同じものを使っているがね。
フロントとサーバーサイドを切り分けるわけだし。
なんか分けることができないの？
###解決方法
webpack.config.jsonのmodule.exportsを配列に入れる。  

```webpack.config.json
const path = require('path');
const publicIndex = {
    mode: 'development',
    entry: './src/public/index/main.ts',
    devtool: 'source-map',
    output: {
        path: path.join(__dirname, "dist/public/script"),
        filename: "bundle.js"
    },
    module: {
        rules: [{
            test: /\.ts$/,
            loader: "ts-loader",
            options: {
                configFile: "src/public/index/tsconfig.json",
            }
        }]
    },
    resolve: {
        extensions: [
            '.ts'
        ],
    },
};
const server = {
    mode: 'development',
    entry: './src/server/main.ts',
    devtool: 'source-map',
    target: 'node',
    output: {
        filename: 'server.js',
        path: path.resolve(__dirname, 'dist/')
    },
    module: {
        rules: [{
            test: /\.ts$/,
            loader: 'ts-loader',
            options: {
                configFile: 'src/server/tsconfig.json',
            },
        }],
    },
    resolve: {
        extensions: ['.ts', '.js', '.json'],
    }
};
module.exports = [publicIndex, server];
```

###git
サンプルコード
https://github.com/kawamurashin/typescript_webpack_multiple_output


###参考
webpackで複数のエントリーとアウトプットの設定で引っかかったこと 
https://qiita.com/niihara_megumu/items/38b3171c6fc751f28939  
なるほど、すごくいい。これにtsconfigを足したら、うまく行った


How to create multiple output paths in Webpack config
https://stackoverflow.com/questions/35903246/how-to-create-multiple-output-paths-in-webpack-config
M5Stack Core2: タイマー割り込み

こちらのページを参考にしました。
[RepeatTimer ](https://garretlab.web.fc2.com/arduino/esp32/examples/ESP32/Timer_RepeatTimer.html)

時間設定の単位は、microseconds です。
5 秒は 5000000 になります。

## プログラム

```text:timer/timer.ino
// ---------------------------------------------------------------
/*
	timer.ino

					Sep/02/2021
*/
// ---------------------------------------------------------------
#include  <M5Core2.h>

hw_timer_t *timer1 = NULL;  

// ---------------------------------------------------------------
void IRAM_ATTR onTimer_proc()
{
  	int iix = millis() / 100;
 
	Serial.println("*** onTimer_proc *** " + String(iix));
}
 
// ---------------------------------------------------------------
void setup()
{
	M5.begin();

	timer1 = timerBegin(0, 80, true); 

	timerAttachInterrupt(timer1, &onTimer_proc, true); 

	timerAlarmWrite(timer1, 5000000, true); 

	timerAlarmEnable(timer1); 

	Serial.println("*** setup *** aaa ***");
	delay(1000);
	Serial.println("*** setup *** bbb ***");
	delay(1000);
	Serial.println("*** setup *** ccc ***");
	delay(1000);
} 

// ---------------------------------------------------------------
void loop()
{ 
  	float ffx = millis()/ 1000.0;
	Serial.println("\t*** loop *** aaa *** " + String(ffx));
	delay(3000);
  	ffx = millis()/ 1000.0;
	Serial.println("\t*** loop *** bbb ***"  + String(ffx));
	delay(3000);
  	ffx = millis()/ 1000.0;
	Serial.println("\t*** loop *** ccc ***"  + String(ffx));
	delay(3000);
}
 
// ---------------------------------------------------------------
```

## Arduino IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/234e5e6d-46a0-50b7-71bb-fa2e49cd80c6.png)


## 実行結果

```text
$ cu -s 115200 -l /dev/ttyUSB0
Connected.
	*** loop *** aaa *** 4.66
*** onTimer_proc *** 66
	*** loop *** bbb ***7.66
	*** loop *** ccc ***10.66
*** onTimer_proc *** 116
	*** loop *** aaa *** 13.66
*** onTimer_proc *** 166
	*** loop *** bbb ***16.66
	*** loop *** ccc ***19.66
*** onTimer_proc *** 216
	*** loop *** aaa *** 22.66
	*** loop *** bbb ***25.66
*** onTimer_proc *** 266
	*** loop *** ccc ***28.66
*** onTimer_proc *** 316
	*** loop *** aaa *** 31.66
	*** loop *** bbb ***34.66
```
input要素のid属性、name属性、type属性の違い

#はじめに
input要素を使って認証機能などを作る際に毎回この属性ってどういう意味だっけとなるので備忘録としてまとめます。inputタグに限ったものじゃないものもあるので注意してください。バックエンドとデータをやりとりする前提で書きます。

#id属性
対象要素をHTML内で一意に識別するための属性。input要素に限らず、ほとんどの要素につけることが可能なグローバル属性。一意である必要があるので同じidを複数つけることは出来ない（正しく動作しない）。要素同士を結びつけたい時に使われることが多い。

#name属性
バックエンドに送ったデータを識別する際の識別子。id要素とは異なり、すべての要素に存在するわけではない。特定の条件を除いて必ずしも一意である必要はないが、普通一意にする。要するにname属性をフロントエンド側で使用することは少なく、バックエンド側のための属性の意味合いが強い。

#type属性
input要素の種類を選択する属性。20種類ほどあり、初期値はtext（一行入力欄）になっている。email,password,checkbox,submit,radioあたりがよく使われる。当然自分で勝手に決めてはならず、存在する種類の中から選ぶ必要がある

#まとめ
id属性とname属性は一緒である必要はないが、一緒の方が分かりやすいので基本的に一緒にしているよう。ただバックエンド側で認識するのはname属性の値。type属性は存在するものの中から適切なものを調べて設定する。
Firebase JS SDK v9でのFirestoreの記述方法変更

前回のFirebase JS SDK v9の投稿が初投稿にしては200viewくらいあってうれしかったので、またv9関連で投稿します。

## Firestoreの記述変更方針

前回の投稿「[Firebase JS SDK v9 になってimportの記述が変わってた](https://qiita.com/dropout26/items/d37754a06057a0aa72d6)」でも書きましたが、Firebaseはv9になってimport方法を変更しています。
私はプログラミング初学者でよくわかりませんが、Composition API方式での記述らしいです。（今まではOption API方式？）

例えば、

```v8_10_0.js
import firebase from "firebase/app"

const db = firebase.firestore();
```

と記述していたのが、

```v9_0_0.js
import { getFirestore } from "firebase/firestore"

new getFirestore();
```

となります。
こうするとFirebaseのライブラリを毎回全部読み込むのではなく特定のモジュールのみを読み込めるので、高速化できるというのがv9のウリらしいです(?)。
もしv8以前の読込方式のままが良い場合は、前回の投稿にcompatライブラリについて書いていますのでそちらをご覧ください。

## Firestoreインスタンスの宣言
```getFirestore()``` は戻り値が既存のFirestoreインスタンス。
既存のFirestoreインスタンスが存在しない場合は、新しいインスタンスを生成します。
[参考: Firebase document](https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja#web-v9)

個人的な感想なので間違っているかもしれませんが、
これまでは```db = firebase.firestore()```とインスタンスの宣言をしたファイルをimportするか、各ファイルでfirebaseモジュール全体をimportして```firebase.firestore()...```としていたようです。
Vue.jsのようなフレームワークを使用していると各コンポーネント毎にfirebaseモジュール全体をimportしていて、ひょっとして1つのページを表示するのに10回くらい同じモジュールをimportしてるんじゃないかと不安になってました。
これが```getFirestore()```だけで既存のFirestoreインスタンスをどこからでも取ってこれるようになり、個人的にはすっきりしました。

この```getFirestore()```を他の関数の引数に加えるように、各関数が修正がされているようです。
以下、公式チュートリアルにある例を紹介しておきます。


## doc() ドキュメント内のリファレンス参照
```v8_10_0.js
import firebase from "firebase/app";
docRef = firebase.firestore().collection("cities").doc("SF");
```

```v9_0_0.js
import { getFirestore, doc } from "firebase/firestore";
docRef = doc( getFirestore(), "cities", "SF");
```

これだけでいいみたいです。

```v9_0_0.js
import { getFirestore, collection, doc } from "firebase/firestore";
docRef = doc( collection( getFirestore(), "cities"), "SF");
```

この書き方もアリみたいです。引数が1つ減るのでなんだか違和感ありますね。

###getDoc(): DocumentSnapshot; 単一ドキュメントの内容を取得
v8以前は```get()```で取得していたものが、```getDoc()```に代わりました。

```v8_10_0.js
import firebase from "firebase/app";
firebase.firestore().collection("cities").doc("SF").get().then((doc) => {
    if (doc.exists) {
    //...
    } else {
    //...
    }
}).catch((error) => {
//...
});
```

```v9_0_0.js
import { getFirestore, doc, getDoc } from "firebase/firestore";
async function firestore_getDoc() {
  docSnap = await getDoc(doc(getFirestore(), "cities". "SF"))
  if (docSnap.exists()) {
    //...
  } else {
    //...
  }
}
firestore_getDoc();
```

```async, await```等の非同期処理がいまいち理解できてないので間違っているかもしれませんが、こんな感じです。
```then()```で処理してはいけないのは何でだろう…？

## あとがき

v8以前の形式で書かれている他のQiita等を見ながら、自分でリファレンスを見てv9に対応させているので恐らくこの投稿にも間違いがあります。
ただ、私と同じようにv8とv9の記述形式の違いで頭ごちゃごちゃになった人が解決できる取っ掛かりになればと思い投稿していますので、もしミスがありましたらぜひご教授ください。
俺のvimrc

syntax enable
colorscheme ron
set number
set virtualedit=block
set ambiwidth=double
set ignorecase
set smartcase
set wrapscan
set incsearch
set showmatch matchtime=1
set cinoptions+=:0
hi Comment ctermfg=3
set expandtab
set shiftwidth=2
set softtabstop=2
set tabstop=2
set guioptions+=a
set smartindent
set clipboard=unnamed,autoselect
set noswapfile
Openapi Code Generatorで日本語表記のenum値を採用する場合

## これはなんですか

Java でOpenapi specを使ってコントローラーのインターフェースやクライアントを書いている人たちで、enumの値を日本語にしたいときどうしたらいいかというお話。

## ほうほう
例えばこんなかんじで、stringなvalueをenumとして扱う場合

```
  PetType:
    type: string
    enum:
      - 猫
      - 犬
```

そのままだ下記のようなとエラーになります。

```
[ERROR] Request.java:[77,5] リリース9から'_'はキーワードなので識別子として使用することはできません
```

生成されるソースコード

```
  public enum PetTypeEnum {
    _("猫"),

    _("犬");
```

## じゃあどうしようか

こうしましょう

これが

```
  PetType:
    type: string
    enum:
      - 猫
      - 犬
    x-enum-varnames:
      - Cat
      - Dog
```

こう！

```
  public enum PetTypeEnum {
    Cat("猫"),

    Dog("犬");

```

この先はかすれていて読めない。


## 参考
https://github.com/OpenAPITools/openapi-generator/issues/893
vue.js 配列をランダムに取得（シャッフル、カット）

vue.js 、 javascript側で
配列をシャッフルしてカットしたい
こんな感じ。

```hoge.vue

<script>

    export default {

        data() {
            return {

            }
        },

        methods: {

            getIkemen(){

                let dataform = new FormData();
                axios.post('/user/show/', dataform).then(e => {

                    //データをシャッフル
                    this.ikemenList = this.shuffle(e.data.res.data);
                    //配列をカットし、データを3つ取得
                    this.ikemenList = this.ikemenList.slice(0,3);

                }).catch((error) => {
                    console.log(" イケメン取得 エラー");
                });


            },

            shuffle(array) {
                for (let i = array.length - 1; i > 0; i--) {
                    let r = Math.floor(Math.random() * (i + 1))
                    let tmp = array[i]
                    array[i] = array[r]
                    array[r] = tmp
                }
                return array;
            },


        }
    };
</script>


```
AWS ElasticBeanstalkで413を吐く時の対策(ファイルサイズ上限設定変更)

AWS ElasticBeanstalkでアプリサーバを立ち上げた際、ファイルアップロードのサイズ上限はnginxのデフォルトである1MBとなっています。
ElasticBeanstalkでのこの上限変更について、検索時すぐに見つかる対策は既に使えなくなっていたことから記事を作成しました。
2021年9月1日時点の記事です。

上記の問題を調べようと関連ワードで検索した際。
出てくる対策の多くが
.ebextensionsフォルダ内にconfigファイルを作るというものですが、どうも現状それは機能しないようです。
reloadコマンドも含める場合もありますがそこまでやると機能しないどころかデプロイが失敗します。
(デプロイ直後はアクセスできても時間差でおかしくなることもありました。)

現在はアプリフォルダ直下(.ebextensionsと同階層)に
.platform/nginx/conf.d/proxy.conf
とファイルを作り。
中身は

```
client_max_body_size 20M;
```

と記載するのが良いようです。
HTTPメソッドとHTTPリクエスト

学習中のメモです。
HTTP（Hypertext Transfer Protocol）は、通信規約（プロトコル）の一種で、ユーザーが行いたい処理をサーバーに伝える役割をしている。
HTTPリクエストとは、ユーザーが行いたい処理をサーバーに伝えることである。
【WiXToolset】アンインストールしたら常駐タスクを落とす


インストーラー設計時の備忘録

# アンインストール時に、常駐タスクを落とす

生成されたwxsファイル内で、
Productの子に以下のシーケンスを追加する

```XML:installer.wxs
<CustomAction Id="TaskKillBat" Impersonate="no" Execute="deferred" Return="ignore" HideTarget="no" ExeCommand="cmd /C &quot; taskkill /im OPPyTask.exe /f &quot;" Property="UninstallProduct" />
<InstallExecuteSequence>
	<Custom Action="TaskKillBat" After="InstallInitialize">
		REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE
	</Custom>
</InstallExecuteSequence>
```

## 意味合い

- REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODEを指定することで、メジャーアップグレード以外のときのアンインストールのときに実行するように設定できる
- InstallInitializeは、**インストーラに何かの変更を及ぼすときの初期化の段階で実行される処理**を表す
- CustomActionの中にtaskkillを入れることで常駐タスクを落とす(※ここの内容を変えると、バッチファイルなども実行できると思います）


# 参考サイト

https://wixtoolset.org/documentation/manual/v3/xsd/wix/installexecutesequence.html

https://qiita.com/Yanase-Takuma/items/bf0a360c9d37ca03a272

https://qiita.com/tohshima/items/72d1e7602a48055c55f5

https://hacknote.jp/archives/16980/

https://stackoverflow.com/questions/320921/how-to-add-a-wix-custom-action-that-happens-only-on-uninstall-via-msi/731700#731700
JavaScriptの条件(三項)演算子と条件式の型変換

プログラミング初心者すぎてわからなかった事でした。
# 条件式に入れただけで型変換が自動で行われる

例えばこんなの。

```js
import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth();
onAuthStateChanged(auth, (user) => {
 user = user ? user : {};
 signin = user.uid ? true : false;
})
```

この ```?``` が条件（三項）演算子と呼ばれるもので、引数には
```condition ? exprIfTrue : exprIfFalse```
を取ります。
```condition```は条件式
```exprIfTrue```は条件式が真の時に返す値
```exprIfFalse```は条件式が偽の時に返す値
です。
[参考：JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)

上のコードはFirebase Authenticationでユーザーのログイン状態を取得するためのものですが、

```js
user = user ? user : {}
```

この```user```が3つ並んでるのを見て、私の頭の中も？？？になりました。
どうしてモジュールの```user```が条件式に入ってるんだ…？

と思って調べたら解決は簡単でして、
条件式が入るべき引数には自動的に
```Boolean(user)```
として型変換が実行されているだけでした。
なので、

```js
user = Boolean(user) ? user : {}
```

と書くと、
```Redundant Boolean call. (no-extra-boolean-cast)```（たくさんBooleanしすぎ！）
と怒られます。
そして、Boolean() は
> 一番目の引数に渡された値は、必要に応じて論理値に変換されます。値が省略された場合や、値が 0, -0, null, false, NaN, undefined あるいは空文字列 ("") であった場合、オブジェクトは false の初期値を持ちます。それ以外のあらゆる値は、オブジェクトや "false" という文字列も含めて、 true の初期値を持つオブジェクトを生成します
[参考：JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Boolean)

とあるので、文字列だろうが何だろうが0, -0 null, false, NaN, underfined以外の何かが入っていればtrueを返すんですね。簡単そうな事なのに知らなんだ。
先程の```user```が3つ並んだコードは中身がnullの場合に空のモジュールを返すという事でした。

## あとがき

どんな小さな事でも見つけたら書いていく事にします。
この辺りの執筆速度が、質問を投稿する時の速度にも影響するので早くしていきたいですね。
15分経って分からなかったら質問 → 質問文を書くのに1時間　だと話にならないですから…。
Docker Desktop なしの WSL2 で docker を動かす

Windows10 の WLS2 の構築と、WSL2 上に Docker Desktop を使わずに docker 環境を構築する手順を記載します。

## 環境
- Windows10 Home version 21H1, os build 19043.1165
- WSL2
- ubuntu 20.04 LTS
- docker 20.10.8, build 3967b7d

## WSL2の構築
PowerShell を管理者権限で起動して、以下のコマンドを実行します。

1. Windowsの「Linux実行オプション」を有効化
1. Windowsの「仮想プラットフォームオプション」を有効化
1. WSL2を既定のバージョンに設定

```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
wsl --set-default-version 2
```

### 5. Linxのセットアップ
Linxのディストリビューションを[Microsoft Store](https://aka.ms/wslstore)から`Ubuntu 20.04 LTS`を選択します。

インストール完了後、アカウントパスワードを設定し、セットアップ完了です。

## Dockerの構築
`Ubuntu`を実行し、開いたターミナルでdockerをインストールします。

### 1.必要モジュールのインストール
```bash
sudo apt-get install \
   apt-transport-https \
   ca-certificates \
   curl \
   gnupg-agent \
   software-properties-common
```

### 2. docker 公式リポジトリから docker をインストール
docker 公式の GPG キー取得し、apt のキーに設定ののち、 docker の公式 URL を apt リポジトリーに追加し、最適化します。そして docker のインストールを行います。

```bash
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose
```

### 3. docker の開始
PCを再起動するたびに必要です。

```bash
sudo /etc/init.d/docker start
```

### 4. ユーザグループ`docker`にログインユーザを追加
docker の実行に`sudo`が不要になります。

```bash
sudo usermod -aG docker ${USER}
```

### 5. docker の動作確認
ログインユーザをユーザグループ`docker`に追加済みなら`sudo`は不要です。

```bash
docker run hello-world
```

## 謝辞
@asahi13<wsp>様の記事「[WSL2でdockerの環境構築](https://qiita.com/asahi13/items/46c00f12321f68ef2015)」を参考にさせていただきました。（と言うかほとんどそのまま）
ありがとうございます！
最近Pythonを使って気づいたこと

#はじめに
どうも。
タイトルにもあるように、最近Pythonを使って気づいたことについてまとめてみました。
自分のメモ書き程度にしているため拙いですが、よければ見ていってください。
#pynputとPILの相性
pynputとPILの両方を使ってコードを書いていたとき、ちょっとトラブった話です。
pynputのmouse.Listernerでマウスのスクロール量やクリックの検知をしつつ、PILのPIL.ImageGrabで画面をキャプチャをやっていたら、カーソルの移動がとてもカクついてしまいました。
ググってもそれらしい文献が見当たらず、どうしようか悩んでしました。
その後、mssというスクリーンキャプチャを行えるライブラリを発見し、こちらは無事動きました。
もしかしたら、私の環境やコードが原因だったのかもしれませんが、まあそんなこともあるんだなという。
ちなみに、このmssは後でもう一度出てきます。
#Tesseract OCRの環境変数を通す
文字認識をやっていたときの話です。
Pythonで光学文字認識を行うとき、pyocrというライブラリを使用しますが、これを使うには先にTesseract OCRというソフトをインストールしておく必要があります。
で、インストールしたあとWindowsの環境変数にTesseract OCRを追加する必要があるわけですが、これがなぜか通らない...。
困ったなと思い調べると、pyocrを使用するコードの前に以下のコードを実装しておくだけで、勝手に環境変数に追加してくれるみたいです。

```python
import os

path='C:\\Program Files\\Tesseract-OCR'
os.environ['PATH'] = os.environ['PATH'] + path
```

もし、環境変数でお困りの方はやってみてください。
ちなみに、変数pathにはインストールしたTesseract OCRまでのパスを代入してくださいね。
#mssによるスクリーンショットは最速
先程も出てきたmssですが、実はスクリーンショットを撮ることがどのライブラリよりも"最速"らしいです。（公式が言っている）
あまり詳しい検証をしていませんが、PIL.ImageGrabを用いたスクリーンショットよりも大体30msほど速いです。
もちろん、コードや環境などによって左右されますが、少なくとも私の環境下では結構速くなりました。
また、mssで撮ったスクリーンショットを以下のコードでPILのImageが使用できる形に変換できます。

```python
import mss
from PIL import Image

sct = mss.mss()
monitor = {"top": y, "left": x, "width": width, "height": height}
sct_img = sct.grab(monitor)
pmap = Image.frombytes("RGB", sct_img.size, sct_img.bgra, "raw", "BGRX")
```

これでピクセル操作も可能になるで、画像処理を早くしたい方にはいいかもしれません。
調べていませんが、OpenCVにも置き換えはできるかもしれませんね。
#終わりに
はい、ということで最近Pythonを使って気づいたことについてでした。最後まで読んで頂き、ありがとうございました。
【Python】ホームページに更新があったらLineへ通知するbotを作ってみた


#はじめに
息子を近場の人気の幼稚園に入れたいが、かなりの激戦区。

入園までのプロセスは
(1) 息子が2歳の10月頃に3歳が通える「プレ幼稚園入園権」をゲット★１
(2) 3歳の時「プレ幼稚園」に通う
(3) 3歳の10月頃に4歳から通える「幼稚園入園権」をゲット
(4) (3)から応募してきた家族とバトルになるが、「プレ幼稚園」通っている家族が優先
(5) ライバルより優先的に入園できる

そもそも2歳からバトルが始まっているのです・・・。

そして、★１「プレ幼稚園入園権」は幼稚園のHPのブログに「案内書」の配布の詳細が記載される。
いつ更新されるかはわからない。。毎日HPを確認しなければならないのです。
ということで、
【Python】ホームページに更新があったらLineへ通知するbotを作ってみました。

#環境
・Windows10
・Python3.7

#概要
1.幼稚園のHPのHTMLファイルを抽出するために、Beautiful SoupというPythonライブラリを利用します。
2.Windowsタスクスケジューラで毎日9時ごろに以下のプログラムを実行します。
3.今日の幼稚園のHPのHTMLと昨日の幼稚園のHPのHTMLファイルを比較し、更新があればLineNotifyで自分のLineに通知します。更新がなければLineでの通知はしません。

Windowsタスクスケジューラの設定方法は以下の記事をご参考下さい。

https://qiita.com/hirockio2206/items/04a509b2aaebd3436a7a


#プログラム

```python:HP.py
import requests
from bs4 import BeautifulSoup
import datetime
import os

#windowsのどこにhtmlを保存するか指定します。
#ご自身の好きな場所にフォルダを作り、指定してください。
#今回はCドライブ直下に'Python'というフォルダを作っています。
path = 'C:/Python/'


#abc幼稚園のHPからhtmlファイルを取得します。
#'http://abc.youchien.net/'を書き換えて使ってください。
data = requests.get('http://abc.youchien.net/')
with open('abcsite.html', 'w',encoding='utf_8_sig') as file:
    file.write(data.text)

#取得したhtmlファイル名を変更_yyyymmdd_abcsite.html
#これをしないと昨日とファイルとごっちゃになりますね。
#変更不要です。
now = datetime.datetime.now()
os.rename("abcsite.html", now.strftime("%Y%m%d") + "_abcsite.html")

#昨日のファイルを呼び出す
#変更不要です。
before = now - datetime.timedelta(days = 1 )
fp1='{0:%Y%m%d}_abcsite.html'.format(before)
filepath = str(path)+fp1

with open(filepath , encoding='utf_8_sig') as f:
    html = f.read()
soup = BeautifulSoup(html, 'lxml')

#本日のファイルを呼び出す
#変更不要です。
fp2='{0:%Y%m%d}_abcsite.html'.format(now)
filepath2 = str(path)+fp2
with open(filepath2 , encoding='utf_8_sig') as f:
    html = f.read()
    soup2 = BeautifulSoup(html, 'lxml')

#昨日のファイルと本日のファイルを比較して同じかどうかで
#処理を分けています。
#変更不要です。
b =soup == soup2

#比較して違いがあるか
#違いがない場合は終了します。
#変更不要です。
def if_abc(b):
    if b == True:
        print('ありません')
        os.remove(filepath)

#違いがある場合はLine API連携します。
#"abc幼稚園のHPで"と"http://abc.youchien.net/"は適宜変えて下さい。
#line_notify_token = '************************************'も
#自分のトークンに変更して下さい。line_notify_tokenの発行方法はググればすぐ出ます。

    else:
        addmessage="abc幼稚園のHPで" "\r\n" "情報の更新がありました。" "\r\n" "内容の確認をして下さい。" "\r\n" "http://abc.youchien.net/"
        line_notify_token = '************************************'
        line_notify_api = 'https://notify-api.line.me/api/notify'
        message = addmessage
        payload = {'message':"\r\n"+ message}
        headers = {'Authorization': 'Bearer ' + line_notify_token}  # 発行したトークン
        line_notify = requests.post(line_notify_api, data=payload, headers=headers)
        os.remove(filepath)
if_abc(b)



```


#終わりに
Beautiful SoupというPythonライブラリは初めて使ったので美しくはないと思いますがやりたいことはできました。
どちらかというとWindowsタスクマネージャーが動かないことがあるかも・・・。
ご参考になれば幸いです。
【RDS】AWSのRDSについて（データーベース作成方法も記述しております）

# はじめに
今回はAWSのサービスの一つ、
RDSについて初心者の方に向けてなるべく難しくないようにまとめます。

RDSの使用方法についても記述いたします。
RDSとは何か？どうやってサービスを利用するのか？

そもそもAWSについて詳しく知りたい方は、こちらの記事をご覧いただければと思います。

https://qiita.com/kenta-nishimoto-1111/items/86ba0156c71b91dbc999


# RDSとは
AWSのクラウド上でリレーショナルデータベースを簡単にセットアップし、運用できるサービスのことです。
↪︎リレーショナルデータベースとは、下記画像のように表形式のデータベースのことです
 一般的にMySQLなどの皆様が普段使用しているデータベースをイメージするとわかりやすいかと思います。

![スクリーンショット 2021-09-01 14.57.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/4eb48d33-581f-e4fa-c3d4-36a554210fad.png)

普段、私たちはデータベース（MySQLなど）を使用する際は、
MySQLを自身のPCにインストールして使用していると思いますが、
そのデータベースをAWSのクラウド上で作成し、使用することができるサービスです。


# クラウド型のデータベースのメリット
なぜ自身のPCにデータベースをインストールするよりも
クラウド上でデータベースを作成する必要があるのか？
その理由については下記のサイトが非常にわかりやすくまとめているので、
こちらを参考にしていただければと思います！

https://it-trend.jp/database/article/89-0055

# RDSで扱えるデータベースの種類
AWSのRDSでは以下のあらゆるデータベースエンジンの選択が可能です。

・MySQL
・PostgreSQL
・AmazonAurora
・ORACLE
・SQLServer
・sMariaDB

今すでにPCにインストールしているデータベースと同じものをクラウド上に作成することが可能となっています！

# RDSの作成方法
<h4>①AWSにログインをする （ https://aws.amazon.com/jp/?nc2=h_lg ）</h4>
AWSのアカウントをまだ作成されていない方、またはログイン方法については下記の記事を参照ください。

https://qiita.com/kenta-nishimoto-1111/items/e1a5709c6efc78e00fc2


<h4>②検索欄でRDSを検索する</h4>
![スクリーンショット 2021-09-01 15.17.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/07798cae-2152-d706-d4f3-8546511c23cd.png)


<h4>③検索結果のRDSを選択</h4>
![スクリーンショット 2021-09-01 15.18.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/8ddb97ae-afc9-c508-10d9-69be4dc881b5.png)


<h4>④データベース作成を選択</h4>
![スクリーンショット 2021-09-01 15.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/e608ab1a-e2fe-99b2-9eec-f0304f306f07.png)


<h4>データベース作成画面でデータベースの設定を行う</h4>

![スクリーンショット 2021-09-02 13.52.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/83a6540f-9ff7-d276-ad42-434cb305a2df.png)

<h5>各項目の参考例</h5>
①データベースの作成方法を選択
⇨ 標準作成

②エンジンのオプション
⇨ ここでは普段使っているデータベースの種類を選択

③テンプレート
⇨ こちらは無料で使用する場合は無料利用枠を選択

④設定
DB インスタンス識別子：DB インスタンスの名前を入力します
マスターユーザー名：DB インスタンスのマスターユーザーのログイン ID を入力します。
マスターパスワード：ログイン時のパスワードを設定

⑤DB インスタンスクラス
⇨ 標準クラス

これ以降は全て初期設定のまま、自分は問題なく作成できました！
最後に一番下までスクロールしデータベース作成を実行するとデータベースができます。

# 完成形

![スクリーンショット 2021-09-02 14.08.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623096/50eeb63f-784e-8e10-7839-70dca79f7f6b.png)

上記のように、今作成したデータベースが表示されていれば完成です！
docker compose (docker-compose) で複数サービスを起動する

docker compose (docker-compose) で複数のプロジェクトの画面を同時に立ち上げたいとき、調べると「ポートが被ってるからkillしろ」とか「別なところで起動してるdockerをdownさせろ」とか、『同時に立ち上げない前提』の記事ばかり目についたのでそれとは逆の意図で書きました。

現場では2個も3個も同時に開発のプロジェクトが走っていて、いちいちdockerを立ち上げ直すのが面倒だったので。

マシン環境は以下の内容で確認しています。

macOS Catalina バージョン 10.15.7
docker desktop バージョン 3.3.3

### 結論

プロジェクト同士でポートがかぶらないようにymlファイルを編集してから ```docker-compose -p other up -d``` または ```docker compose -p other up -d``` のコマンドで起動。

### やったこと

結論から言えば上記の通り、docker-compose.yml のファイルを編集してポート番号を変更するのですが、例えばプロジェクトAとプロジェクトBを同時に起動したいとき、ymlファイルが以下のようになっているとします。

```yml:プロジェクトAのdocker-compose.yml
version: '3'

services:
  nginx:
    container_name: xxx_nginx
    image: xxx:nginx_v4
    volumes:
    - ./server:/data/www
    ports:
      - "80:80"
    depends_on:
      - php
  php:
    container_name: xxx_php
    image: xxx:php_v6
    volumes:
    - ./server:/data/www
  redis:
    container_name: xxx_redis
    image: xxx:redis_latest
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"

```

```yml:プロジェクトBのdocker-compose.yml
version: '3'

services:
  nginx:
    container_name: nginx
    image: xxx:nginx_latest
    volumes:
    - ./server:/data/www
    ports:
      - "80:80"
    depends_on:
      - php
  php:
    container_name: php
    image: xxx:php_latest
    volumes:
    - ./server:/data/www
  redis:
    container_name: redis
    image: xxx:redis_latest
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"

```

プロジェクトAを ```docker-compose up -d``` または ```docker compose up -d``` のコマンドで起動した後、ステータスを見てみると以下のようになります。

```php
% docker compose ps
NAME                      SERVICE             STATUS              PORTS
xxx_nginx   nginx         running             443/tcp, 0.0.0.0:80->80/tcp, :::80->80/tcp
xxx_php     php           running             9000/tcp
xxx_redis   redis         running             0.0.0.0:6379->6379/tcp, :::6379->6379/tcp
```

nginx　や redis のポートがプロジェクトAとBで重複しているので、プロジェクトBのymlを以下のように変更します。

```yml:プロジェクトBのdocker-compose.yml
version: '3'

services:
  nginx:
    container_name: nginx
    image: xxx:nginx_latest
    volumes:
    - ./server:/data/www
    ports:
      - "81:80" #　←ここを変更
    depends_on:
      - php
  php:
    container_name: php
    image: xxx:php_latest
    volumes:
    - ./server:/data/www
  redis:
    container_name: redis
    image: xxx:redis_latest
    ports:
      - "6380:6379" #　←ここを変更
    volumes:
      - "./data/redis:/data"

```

その後  ```docker-compose -p other up -d``` または ```docker compose -p other up -d``` のコマンドで起動すると、

プロジェクトAは http://localhost/ で、 プロジェクトBは http://localhost:81/ で繋がるようになります。

#### 参考URL
[docker-compose の ports 指定まとめ](https://qiita.com/tksugimoto/items/23fcce1b067661e8aa46)
[docker-compose.ymlの書き方について解説してみた](https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04)
[docker-compose を複数起動する](https://www.kimullaa.com/entry/2017/10/23/122016)
【jquery javascript】多次元配列を指定したキーと値にする方法

```javascript
process.stdin.resume();
process.stdin.setEncoding('utf8');

const Equipment = [
{name: "剣", value: "どうのつるぎ"},
{name: "防具", value: "かわのたて"},
{name: "防止", value: "かわのぼうし"},
{name: "ナイフ", value: "ブロンズナイフ"}
];

data = Equipment.reduce(function(p,c){
        if(p[c['name']] === undefined){
          p[c['name']] = [];
        }
        p[c['name']].push(c['value']|0);
            return p;
}, {});

console.log(data);

```

#結果  ⇛ 連想配列になる
```
{
  '剣': [ 'どうのつるぎ' ],
  '防具': [ 'かわのたて' ],
  '防止': [ 'かわのぼうし' ],
  'ナイフ': [ 'ブロンズナイフ' ]
}

```


var player ={name: "Ronaldo", team: "Juventus"};

player.uniNumber = 7;


console.log(player);
グローバル変数の整理法


# 言語

ＰＨＰ

グローバル変数と書きましたが、ローカル変数でも応用できます。

# 整理法１

こんなグローバル変数があるとします。

```php
$bara   = 1; //バラ
$kiku   = 2; //菊
$sakura = 3; //桜
$ume    = 4; //梅
$tulip  = 5; //チューリップ
```

これらを関数内で使う場合、いちいち `global $bara;` `global $kiku;` ・・・ と宣言しなければなりません。

こんな時は、関連する複数の変数を１つにまとめるとよいです

```php
$flower = array();
$flower['B'] = 1; //バラ
$flower['K'] = 2; //菊
$flower['S'] = 3; //桜
$flower['U'] = 4; //梅
$flower['T'] = 5; //チューリップ
```

関数内で使うときも `global $flower;` と１行でＯＫです

`$flower[0], $flower[1]` のような単なる連番だと保守性が落ちるので、私はアルファベット１文字の連想配列にしています。

# 整理法２

関連する複数の変数を、クラスにまとめる方法もあります。

```php
class flower {
    public $bara   = array(); //バラTBL
    public $kiku   = array(); //菊TBL
    public $sakura = array(); //桜TBL
    public $ume    = array(); //梅TBL
    public $tulip  = array(); //チューリップTBL
}

$flower = new flower();
```

メソッドも何もない、変数をまとめただけのクラスです。

このクラス方式は、複数のＤＢテーブルのデータをまとめる用に使うと便利です。
関数内で使うときも `global $flower;` と やはり１行でＯＫです。
[Salesforce]承認完了時に承認内容を含んだレコードを作成する方法

Salesforceで承認プロセス完了時に承認内容を含んだレコードを作成する方法について紹介します。

発端は、承認完了時に申請者へ承認内容をSlack通知したいという要望が挙がったことでした。
というのも、今まで承認完了しても気づかずレコードを放置してしまい、対応が遅れてしまったり漏れたりすることが起きていました。

そこで実装開始したもののなかなか一筋縄ではいかず、、でした。
そのため、今回同じ悩みを持つ人の助けになればと思い、実装方法をまとめてみました。

## 前提
今回はカスタムオブジェクト「テスト」に承認プロセスを用意し、承認完了時に商談が自動作成される機能を作ってみます(さらに商談の「Next Step」項目に承認内容を記述してみます)

次の節で大まかな実装の流れを説明します。

## 実装手順
実装の流れは以下のとおりです。

①最終承認完了時に動く「項目自動更新」を用意
②レコード変更時に発火する「プロセスビルダー」を用意
③プロセスビルダーから呼び出される自動起動「フロー」を用意

この順番にした理由は以下の３つです。
・承認プロセスから直接プロセスビルダーやフローを呼び出せない
・項目自動更新の変更をトリガに直接フローを起動できない
・プロセスインスタンス（承認の内容などを保存してあるオブジェクト）がフローからしか取得できない

次の節で一つ一つの概要を説明します。

## ①最終承認完了時に動く「項目自動更新」を用意

承認プロセスの「最終承認時のアクション」に項目自動更新を新規追加します。
今回はステータス項目を「承認完了」に変更・承認日を今日に変更するようにします。
これらが②の発火条件となります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/67d1e4be-1c23-ca72-71ce-e00d0320a52d.png)

ここで一点大切なのは、それぞれの項目自動更新の「項目変更後にワークフロールールを再評価する」にチェックを入れておく必要があります。これによりプロセスビルダーが起動するようになります。

![スクリーンショット 2021-09-02 12.43.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/b74dee48-b10d-545a-2fc4-4cc9511cc9f9.png)

## ②レコード変更時に発火する「プロセスビルダー」を用意

プロセスビルダーの新規作成をします。

まずプロセスのタイミング設定をします。
テストオブジェクトのレコード作成・編集した時を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/3e49722c-d8a7-3857-a997-c34820116272.png)

次に条件を設定します。
①の「最終承認時のアクション」で変更される項目の内容を条件にします。
「レコードに指定の変更が行われた場合にのみアクションを実行しますか?」にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/d4a2a112-3f5b-a3d8-96f2-9a4ae5a5c18e.png)

そしてアクションの設定をします。
ここでフローの起動を選択し、フローに渡す変数「TargetObjectId」を定義します。
ここには起動した対象のオブジェクトIdを渡します。

※呼び出すフローの内容は次に紹介します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/0394811c-affa-b238-1a51-b3b0e84e8219.png)


## ③プロセスビルダーから呼び出される自動起動「フロー」を用意

自動起動フローを新規作成します。

レコード取得コンポーネントでプロセスインスタンスを取得します。
条件は以下です。
・「TargetObjectId」と入力時に使用できるテキスト変数が一致すること（②の変数がここに入ります）
・「Status」がApprovedであること
つまり承認プロセスが完了したレコードの承認情報を取得しています。

そして「CompletedDate」が最新のものを一つだけ取得するように設定します。
これは対象のオブジェクトに対して複数のステップがあった場合に、最新の承認情報を得るために行っています（並び替えがないと全く違う過去の承認情報をとってしまうことがあります）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/d1549ce8-bfc0-ea7c-aaa8-e6fea527e1b1.png)

次に商談を作成します。
「NextStep」には承認内容を含めた数式を渡すことにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/d2faaa88-37a7-72e7-c600-7c7714a7b794.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/8374a36d-4e7a-1fcd-e0b4-fb72cb942aef.png)


## 結果

承認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/4ebb93aa-c055-ea79-b35a-bb7bba66b036.png)

↓↓↓↓↓↓↓↓↓

無事、承認内容が記載された商談が出来上がりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631504/d7c44661-b03b-bffc-69bb-98259561ae1f.png)

## 最後に
もっといい方法があるかもしれないですが、この方法で今は無事に承認内容をSlack通知できました。
また却下時も同様の方法で実装できました。
どこかのSalesforce管理者のお役に立てれば幸いです。
【jquery】htmlのデータを配列として取得する。※serializeArray()を使う




#jQuery 

```javascript
<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>serializeArray_01_jq</title>
   <script src="jquery-3.6.0.min.js"></script>
   <script>
    $(function () {
          var data = $("#Formdate").serializeArray();
          console.log(data);
    });
  </script>
  
  <form id="Formdate">
    <input  name="剣" value="どうのつるぎ" />
    <input  name="防具" value="かわのたて" />
    <input  name="防止" value="かわのぼうし" />
    <input  name="ナイフ" value="ブロンズナイフ" />
  </form>
```


#出力結果
```
0: {name: "剣", value: "どうのつるぎ"}
1: {name: "防具", value: "かわのたて"}
2: {name: "防止", value: "かわのぼうし"}
3: {name: "ナイフ", value: "ブロンズナイフ"}
```
GoogleAppsScriptの値を渡すときにつまった

#やってきたこと
##作ったもの
サービス費用の計算を簡単にしたくて、スプレッドシートにあるデータを用いて計算するアプリを作りました。HTMLに直書きするのではなくスプレッドシートを使用したのは、データの大きさはそれほどではないものの、定期的に計算に使用する値が変更されるためです。

##具体的なデータの流れ
　スプレッドシート(９枚)→GAS(doGet())→HTML/javascript
　GASからSpreadSheetAppを用いてスプレッドシートにある各データを取得します。その後、HTML側にデータを渡し、サービス費用を計算します。
　HTMLからGAS側にデータを戻して計算することもできますが、doPOSTがわからないこと、データ処理自体は複雑ではないことからクライアント側処理としました。

#２つのつまったところ
##1.doGetからHTML側にデータを渡そうとするとうまく渡らない。
###現象
　スプレッドシートのシート名をキーとして連想配列を作り、各シートのデータをデータとして持たせました。
　これをdoGet()を用いてHTML側に渡そうとすると、"Object object"というよくわからない値を返してしまい、詰まってしまいました。

```javascript:code.gs
function doGet() {
  let html = HtmlService.createTemplateFromFile("index");
  html.priceList=GetSpreadSheet();
  return html.evaluate();
}

function GetSpreadSheet() {
  let file = SpreadsheetApp.openById("spreadSheetId");
  let sheets = file.getSheets();
  let res = {};
  for (var i = 0; i < sheets.length; i++) {
    var sheet = sheets[i];
    let last_col = sheet.getLastColumn();
    let last_row = sheet.getLastRow();
    res[sheet.getSheetName()]=sheet.getRange(1, 1, last_row, last_col).getValues();
  }
  return res;
}
```

```html:index.html
<html>
  (略)
  <script>
    console.log(<?=priceList?>)
  </script>
　(略)
</html>
```

出力

```
[object Object]
```


###対処
　具体的なエラーがでないため、うまく検索できず…。そんな中、見つけたのが下の記事でした。
[GoogleAppsScriptでサーバー側からHTML側に値が上手く渡らない](https://qiita.com/rotelstift/items/0e2bd99eab5d06baa85a)
　内容は、"渡せるものと渡せないものがあるよ、渡せないときはJSON使おうね。"というもの。JSONを使うと解決できました。ちなみに初JSONでした…。

```javascript:code.gs
  (略)
  }
  return JSON.stringify(res)
 }
```

```html:index.html
  <script>
    console.log(JSON.parse(<?=priceList?>))
  </script>
```

##2.script.htmlでスクリプトファイルを分けると読み込めない。
###現象
　googleAppsScript調べていると、出てくるのが"cssとscriptを分けて書くとわかりやすいよ"っていう記事。cssは気持ち程度に分けていたんですが、scriptタグの中身が増えすぎたので分けてみたところ、doGet()で渡したデータが読み込めず、エラー。

```javascript:main.gs
function doGet() {
  let html = HtmlService.createTemplateFromFile("index");
  html.priceList=データ;
  return html.evaluate();
}
```

```html:index.html
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('script').getContent(); ?>
  </head>
  (略)
</html>
```

```html:script.html
<script>
  console.log(<?=priceList?>)
</script>
```

<?!= ･･･ ?>は強制出力スクリプトレットタグといわれるもので、htmlの中でjavascriptを読み込むもの(らしい)です。
作った時は、doGetからindex.htmlを読み込み、index.htmlからscript.htmlを読み込むため、データは当然読み込めるんだろうと思っていたんですが、

```
Uncaught SyntaxError: Unexpected token '<'
```

とエラーする結果に。

###対処
　これについては、正しい対処かわかりませんが、scriptタグの分割を諦めました。当初、ほかの場所も変更していたので、原因探索に時間がかかりましたが、少しずつ試すことで発覚しました。

#まとめ
　今後は、２つのエラー共に、もう少しどのような条件でエラーが発生するのか、調べてみたいと思います。
Next.js + TailwindcssでのBackgroundImage（背景画像）の設定の仕方。

# はじめに
初投稿になります。
あまりにもしょうもないことではまってしまったことが悔しくて投稿に至りました。



#本題
Next.js単体で調べると一瞬で出てくるのですが、Next.jsではpublic以下に画像を保存させます。
ここまでは公式ドキュメントを見れば誰でもわかるのですが、問題はCSS in JSではなくTailwindcssで表示させたい場合はこちらを読んでいただいて

https://tailwindcss.com/docs/background-image

tailwind.config.jsでの表記の仕方は
例: public/images/hoge.png →　/images/hoge.png
です。
publicは/←こいつで省略しないといつまで経っても画像が表示されません。

#結局何が悔しいの？
何が言いたかったのかというと、調べ方一つ変えただけで、一日もはまってしまったことに一瞬で解決できたということです。
（大体のエラー解決はそんなものかもしれませんが・・・）
あと、公式ドキュメントがすごく優秀なので、ちゃんと理解していればこんなエラーに遭遇することはなかったです。。。


#最後に
あまりにも拙い文章ですが、Twitterでも何名かはまっているみたいなので書き記しておこうかなと思います。
Flutter: Android studioでFirebaseをセットアップする最低限の手順(Android&IOS)

###この記事について
この記事はFlutterでAndroidとIOSのアプリを作る際、Firebaseを使用するときのセットアップ方法についての記事です。
実装するたびに動画の教材を見ており時間が掛かってしまうため(特にIOS)、一連の作業を箇条書きにしております。
セットアップのための最低限やることを書いた記事のため、Firebaseの機能の実装等は記載していません。また、Firebaseプロジェクトの作成は省略しております。

###開発環境

```
 % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 2.6.0-1.0.pre.150, on macOS 11.5.2 20G95 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 12.5.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.47.3)
[✓] Connected device (1 available)

• No issues found!

```

###Androidのセットアップ
1. コンソール画面からAndroidのアイコンをタップ
![スクリーンショット 2021-09-02 11.37.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/63f45961-9097-cbdd-a558-af2d18e4e412.png)



1. パッケージ名入力欄にアプリケーションIDを入力する
必須項目はこれだけなので、入力完了後は'アプリを登録ボタン'を押す。
任意の項目も後で追加、変更できるので今はスルー。
![スクリーンショット 2021-09-02 11.53.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/97963f93-a825-47ba-e1d0-1d3d880e62b8.png)
IDの記載場所はandroid/app/build.gradeファイルの中
![スクリーンショット 2021-09-02 11.47.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/74844e7a-5209-488e-613c-80f15c0bac63.png)


1. google-services-jsonのダウンロード
コンソールの説明がわかりやすいので省略。
1. FirebaseSDKの追加
google-services-jsonを使えるようにするため、build.gradle ファイルを修正する。これもコンソールの説明がわかりやすいので省略。
1. エミュレータを起動し、Runしてエラーが発生しないのを確認
コンソールを確認すると非推奨(deprecated)の警告が来ることがあるが、赤字のエラーがないのであればセットアップ完了。

###IOSのセットアップ
1.Xcodeをインストールされているか確認
インストールされてなければ、他の記事を参考にインストール作業を終わらせる。
2. IOSアイコンをタップ
コンソール画面に『アプリを追加』があるのでタップするとプラットフォーム一覧が表示されるのでIOSアイコンをタップ
![スクリーンショット 2021-09-02 12.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/88293214-f055-146a-1b37-e772de914cfd.png)
3. バンドルIDを入力
バンドルIDの場所はRunnerファイルを左クリックして画像のようにFinderで開き、Runner.xcodeproj(アイコンが青い方)をXcodeで開く。
![スクリーンショット 2021-09-02 12.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/59bcd716-5370-f302-53a2-cd352a68000a.png)
![スクリーンショット 2021-09-02 12.35.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/8df52880-7893-9c2e-2759-7648e67e92ab.png)

プロジェクトを選択し、General→Rundle Identifierという項目を見るとバンドルIDがある。
![スクリーンショット 2021-09-02 12.37.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1132605/c02a53a7-d564-cd1d-d5d9-c42e1fd3d1a1.png)

4. google-services-jsonのダウンロード
ダウンロードしたファイルをXcodeで開いたプロジェクトのRunnerファイルの直下に移動しXcodeを閉じる。

5. エミュレータをIOSのデバイスに指定してRun
エラーが発生しなければ完了。

---

以上、セットアップの方法を記載しました。
筆者の場合は特にエラーもなくできたので、エラーが起きた際はお助けできません。。。ご了承ください。
各パッケージを使う場合の実装方法については別記事で書こうと思います。
gRPCのint32 <-> int64の互換性について

以下ドキュメントにも記載のあるとおり、gRPCにおいて `int32` と `int64` は相互互換性があり、呼び出し元/先でデータ型が変わっていても通信が可能です

https://developers.google.com/protocol-buffers/docs/proto3#updating

ただ、int32の範囲をオーバーする値が設定された時に以下の変換規則が適用されるので注意

- クライアントが `int32` & サーバーが `int64` の場合
    - リクエストで `int32` をオーバーする値を設定した場合、 **クライアント側でエラーが発生** します
    - レスポンスに `int32` をオーバーする値が設定された場合、 **クライアント側にはオーバーフローした値が設定** されます
        - 例えばint32の上限値 + 1の値である `2147483648` であれば、 `-2147483648` としてクライアントにて読み取られます
- クライアントが `int64` & サーバーが `int32` の場合
    - リクエストで `int32` をオーバーする値を設定した場合、 **サーバ側にはオーバーフローした値が設定** されます
    - レスポンスに `int32` をオーバーする値が設定された場合、 **サーバー側でエラーが発生** します

ただ、これはPython実装の場合における挙動で、例えばgRPCクライアントツールとして有名な[evans](https://github.com/ktr0731/evans) だと、上記において値がオーバーフローするケースにおいてはエラー応答が返却されます

```:エラーのイメージ
$ evans --host localhost -p 14880 example.proto

  ______
 |  ____|
 | |__    __   __   __ _   _ __    ___
 |  __|   \ \ / /  / _. | | '_ \  / __|
 | |____   \ V /  | (_| | | | | | \__ \
 |______|   \_/    \__,_| |_| |_| |___/

 more expressive universal gRPC client


example.Example@localhost:14880> call getExample
id (TYPE_INT32) => 1
command call: rpc error: code = Internal desc = grpc: failed to unmarshal the received message proto: integer overflow
```

仕様はあくまで参考値に留め、実際の実装の挙動を確認するのがよさそうです

https://developers.google.com/protocol-buffers/docs/pythontutorial
Eclipse 2021-06 に relaunch (Java Applicationの再起動) ボタンを設置する

# 概要

**Eclipse 2021-06** には、デフォルトでは、 Java Application の再起動をするツールバーボタンがないので、それを設置する方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/18fa6bee-b1cb-7eaa-61db-6fc38d154886.png)
↑↑↑ **再起動(relaunch)ツールボタン**　は デフォルト↓↓↓ では無い
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/00608ff4-ed39-71f0-c573-0ab2d9b76d73.png)


## Spring (Boot) つかってるなら STS が便利

- Eclipse STS(Spring Tool Suite) を導入すると、　再起動ボタン　をつかえるようになる
- Springじゃなくても、通常の Java Application の　再起動　ももちろんできる

## Eclipse STS のインストール方法

- Eclipseの上部メニューから **Help** >　**Eclipse Marketplace** を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/1c545715-905e-bda0-ba93-04d5b9a6af82.png)

- **Find:** のところに 「**spring tool suite**」と入力して **Go**ボタン を押す
すると、 Spring Tool Suite がみつかるので、右下にある **Install** ボタンを押してインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/124bf986-89e4-f2af-c48c-d37864d5a13d.png)

- 画面に従ってインストールを終える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/5e3f2339-091e-956c-0918-8e8e76c5cdeb.png)

- これで、 再起動ボタン(**relaunch**ボタン) がつかえるようになった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170905/5dc8c9e2-1274-839b-1715-7e8b4138ce05.png)

# まとめ

- 本稿では Eclipse STS をいれると、通常の Java Application の再起動もできる、relaunchボタンを設置できることを確認しました。
[Salesforce] [Apex] 月初、月末を取得する

## はじめに

Apexで月初とか月末を出す処理、何かと使うので自分の備忘録として載せておきます。

## 月初の日付取得

DateクラスにtoStartOfMonthメソッドが用意されているのでそれを呼ぶだけです。

```
Date targetDate = Date.today();
Date startDate = targetDate.toStartOfMonth();
```


## 月末の日付取得

DateクラスにtoEndOfMonthメソッドが存在しないので自分で実装しないといけません。

```
public static date getEndOfMonth(Date targetDate) {
    Date NewTargetDate = targetDate.addMonths(1).toStartOfMonth();
    Date result = NewTargetDate - 1;   
    return result;
}
```
次月の初月を取得した後に1日引き算する方法で実現する手法です。
自分が新人だったときVB5で同じことしていました。20年前から変わっていないです。もはや伝統芸。

## 文献

Dateクラス 公式ドキュメント
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_date.htm
VerilogHDL > { } > 連接、連結演算子、連節演算、Concatenation

VerilogHDLの資料を整理していくと、用語の不統一で困る。


### 参考1
http://www.kumikomi.net/archives/2009/07/verilog_hdl_2.php?page=3

> 連接

### 参考2

トランジスタ技術 SPECIAL No.95
わかるVerilogHDL入門 by 木村真也様
p21

> 連結演算子

### 参考3

Verilog HDL デザイン・テンプレート  by 植木うてな様

>  連節演算。

### 参考4

https://ja.wikipedia.org/wiki/Verilog

> 連結

### 参考5

https://en.wikipedia.org/wiki/Verilog

> Concatenation

### 参考6

https://sutherland-hdl.com/pdfs/verilog_2001_ref_guide.pdf
p29

> { }  : concatenate m to n, creating a larger vector 


## 検索用キーワード

一箇所に情報をまとめた時にキーワードの不統一でその情報に到達できない。
「Concatenation」をキーワードにしておくと、到達はできそうかな。