OmniAICreator/Qiita-1.07M huggingface dataset:
M1 Macにデータ分析環境を作る

はじめに
==================

M1 Mac M1はCPUのアーキテクチャーが[arm64](https://urashita.com/archives/12325)ベースということで、X86ではありません。

一般的にはIntelを代表とするX86アーキテクチャーを前提で作られたパッケージが多いため、arm64にインストールできないということもよくあります。

ここではM1 Macにデータ解析基盤を作ることを目的とし、その方法を以下に示します。


M1 Macへの構築方法
====================

pyenvのインストール
--------------------------

最初にpyenvをインストールしてください。インストール方法は、[pyenvのgithub](https://github.com/pyenv/pyenv)を参考にしてください。

miniforge3-4.10.1-5 のインストール
-----------------------------------

つぎにArmアーキテクチャーに対応済みのminiforgeをインストールします。

```bash:command
pyenv install miniforge3-4.10.1-5
pyenv global miniforge3-4.10.1-5
pyenv versions
```

```bash:command
python -VV
```

```
Python 3.9.2 | packaged by conda-forge | (default, Feb 21 2021, 05:00:30) 
[Clang 11.0.1 ]
```

conda環境の構築
-----------------------

なんでcondaを使わないといけないかは、`miniforge` `conda` でググってください。

```bash:command
ENV_NAME="myenv"
conda create --name ${ENV_NAME} python=3.9.6
conda activate ${ENV_NAME}
```

以下を確認します。

- pythonが `3.9.6` であること
- condaの環境が上記で定義した `${ENV_NAME}` になっていること
- pyenvからも `${ENV_NAME}`の環境が見えること

```bash:確認
python -VV
conda info -e
pyenv versions
```

必要パッケージのインストール
-----------------------

順番変えれば、numpyとか自動的に入りますが、以下の順番は個人の好みです。

```bash:command
conda install -c conda-forge conda-forge::numpy -y
conda install -c conda-forge conda-forge::pandas -y
conda install -c conda-forge conda-forge::matplotlib -y
conda install -c conda-forge conda-forge::seaborn -y
conda install -c conda-forge conda-forge::lightgbm -y
conda install -c conda-forge conda-forge::jupyterlab -y
conda install -c conda-forge conda-forge::geopandas -y
conda install -c conda-forge conda-forge::xgboost -y
conda install -c conda-forge conda-forge::nltk -y
conda install -c conda-forge conda-forge::opencv -y
conda install -c conda-forge conda-forge::ipywidgets -y
conda install -c conda-forge conda-forge::IProgress -y
conda install -c conda-forge conda-forge::lime -y
conda install -c conda-forge conda-forge::lit-nlp -y
conda install -c conda-forge conda-forge::tfds-nightly -y
conda install -c apple tensorflow-deps
```

一部condaで入らないやつは、割り切ってpipでインストールします

```bash:command
pip install optuna
pip install tfds-nightly
pip install tensorflow-macos
pip install tensorflow-metal
pip install tensorflow_hub
pip install tensorflow_text
pip install pandas_profiling
```

tensorflowに関しては以下も参考

- https://www.alps-lab.org/?p=855

参考文献
========

https://qiita.com/c60evaporator/items/aef6cc1581d2c4676504#optuna

https://www.python.jp/install/anaconda/conda.html

https://dev.infohub.cc/conda_command/

https://medium.com/@alfarruggia/from-zero-to-transformers-on-apple-m1-chip-e5d9afa35f5

https://huang-jason.gitbook.io/anaconda/tf-nightly-cpu
R でケンドールの順位相関係数の計算が速くなりました（Pythonより速い？）

少なくとも macOS Monterey, M1 チップでのことかもしれませんが。

https://blog.goo.ne.jp/r-de-r/e/2716d7ca3c9fb3a1eb643d83d10dfecd

他の環境（OS, R のバージョン）そもそも，macOS じゃなくて，Windoze だよという人の報告もお待ちしたいところです。。
【Tableau】VIZの垢抜けスキル⑤〜ダッシュボードに囲いを付ける〜

この記事は[Advent Calendar 2021 Tableau](https://qiita.com/advent-calendar/2021/tableau2021)の18日目の記事となります。
※私の解説＆キャプチャはTableauDesktopのバージョン2020.4、PCはMacを使ってます。
バージョンが異なったりPCがWindowsの場合、操作が一部異なる場合もあるかもしれません。

本日は**ダッシュボードに囲いを付ける方法**をご紹介します。
![スクリーンショット 2021-12-19 21.37.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/ddbd1f88-a8c5-64d4-99fd-a841a5ff1b37.png)

まずオブジェクトの垂直方向もしくは水平方向をダブルクリック（もしくはドラック＆ドロップ）します。
![スクリーンショット 2021-12-19 21.35.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/4abb8f6d-138d-1211-9d61-c69edefa4406.png)
![スクリーンショット 2021-12-19 21.36.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/58290cc9-7778-7e12-9f86-96360938b72e.png)

次に縦枠を作っていきます。オブジェクトの水平方向をドラック＆ドロップします。
必要であれば枠線の幅を調整してください。
![スクリーンショット 2021-12-19 21.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/c15f3068-b830-7c64-d149-4c114a7cc49e.png)

色をつけます。
レイアウトのタブを開き、バックグラウンドで色を選択してください。
![スクリーンショット 2021-12-19 21.44.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/27c5991d-2f56-e49f-9fe0-5f769af82738.png)

反対側も同様の作業を繰り返します。
![スクリーンショット 2021-12-19 21.48.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/3e069a06-a6f2-8fd9-d608-83c10c107a81.png)

次に横枠を作っていきます。
オブジェクトの垂直方向をドラック＆ドロップします。
![スクリーンショット 2021-12-19 21.49.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/529423c5-8272-dedb-3e99-ca38151ac339.png)

同様に色をつけます。
上の横枠も作成してください。
![スクリーンショット 2021-12-19 21.51.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/0ebdae0c-4139-c1df-d33f-5ca296ab5f9c.png)

完成です。
![スクリーンショット 2021-12-19 21.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1537142/5adb7f30-344e-b21d-530d-8ee1d5abd6ab.png)
2元2次不定方程式をfind_DNでペル型方程式に変換して解く

[前回の投稿](https://qiita.com/masa0599/items/162c7e1989ae9a653a0c)でペル型方程式の解をSympyのdiop_DNで生成する方法について書きました。今回はこれを利用して以下のような2元2次不定方程式を解くプログラムを書いて行きます。

$\displaystyle \large \ \ \  ax^2+bxy+cy^2+dx+ey+f=0$</br>

手順は以下のようになります。

1. 2元2次不定方程式をペル型方程式に変換、および元の解への変換Matrixを取得
2. 前回の投稿で作った関数pelEqを使ってペル型方程式の解を生成
3. 1.で取得したA,Bで元の解に変換

例として以下の2元2次不定方程式を使います

$\displaystyle \large \ \ \  2x^2+4x-y^2-y=0$</br>

## 1. 2元2次不定方程式をペル型方程式に変換、および元の解への変換Matrixを取得
sympyのfind_DNを使うとあっけなく$X^2-DY^2=N$の$D,N$が求まります。

```python 
(D, N) = find_DN(2*x**2 + 4*x - y**2 -y)
print(D, N)
# (8, 56)
```

同時にtransformation_to_DNを使ってて$X^2-DY^2=N$の解から元の$x,y$に変換する$Matrix A, B$を取得します。

```python 
(A, B) = transformation_to_DN(2*x**2 + 4*x - y**2 -y)
print(A,B)
# Matrix([[1/8, 0], [0, 1/2]]) Matrix([[-1], [-1/2]])
```

### 2. 前回の投稿で作った関数pelEqを使ってペル型方程式の解を生成
ここは[前回の投稿](https://qiita.com/masa0599/items/162c7e1989ae9a653a0c)を参考にしてください。

## 3. 1.で取得したA,Bで元の解$x_n,y_n$に変換

1.で取得した$A,B$を使って$X_n,Yn$を元の2元2次不定方程式の解$x_n,y_n$に変換します。式は以下ようになります。

$\displaystyle \large \ \ \  \begin{pmatrix} x_n \\\ y_n\end{pmatrix}  = A \times  \begin{pmatrix} X_n \\\ Y_n\end{pmatrix}+ B$</br>

```python 
(x, y) = A*sympy.Matrix([[abs(X)], [abs(Y)]])+B
```
これらを組み合わせて2元2次不定方程式を解くプログラム**diophQuad**が以下となります。結果の最後の値が$0$になっているので正しい答えが生成されているのが確認できます。

```python 
import sympy
from sympy.solvers.diophantine.diophantine import find_DN, diop_DN, transformation_to_DN
from sympy.parsing.sympy_parser import parse_expr

def findDNAB(eqstr):
  sympy.var("x y")
  eq = parse_expr(eqstr)
  (D, N) = find_DN(eq)
  (A, B) = transformation_to_DN(eq)
  return (D, N, A, B)

# solve quadratic equation with interger solutions
def diophQuad(eq):
  (D, N, A, B) = findDNAB(eq)
  ansPelEq = pelEq(D, N)  
  while True:
    xyl = next(ansPelEq)
    for (X,Y) in xyl:
      (x, y) = A*sympy.Matrix([[abs(X)], [abs(Y)]])+B
      yield (x,y)

ansDQ = diophQuad(" 2*x**2 + 4*x - y**2 -y")
for i in range(10):
  (x,y) = next(ansDQ)
  print(x, y, 2*x**2 + 4*x - y**2 -y)
#0 0 0
#0 0 0
#1 2 0
#3 5 0
#10 15 0
#22 32 0
#63 90 0
#133 189 0
#372 527 0
#780 1104 0
```

（開発環境：Google Colab）

このアルゴリズムはProject Euler Problem 321: Swapping Countersを解くのに役に立ちます。
これから Houdini を始めるあなたへ

こちらの記事は、[Houdini Apprentice Advent Calendar2020](https://qiita.com/advent-calendar/2021/happrentice) / 19日目の記事になります。

#これから Houdini をやっていきたい人向けの講座資料まとめ
某所で短期集中・初心者向けの Houdini の講座を持たせていただいているのですが、
序盤が大事だなー と思っているので、その部分を公開します。

作例をなるべく最小単位で切り出して 頻出機能を総浚いできるように書いたつもりです。

https://sites.google.com/view/firststep-houdini/

#内容サマリ
簡単に内容をサマリしておきます。

###Day0
環境構築編です。
必要スペック、ライセンス周りなどについてざっと紹介しています。
###Day1
画面構成・基本操作紹介編です。
合わせてパラメータとは、アトリビュートとは、階層（オペレーター）とは、コンポーネントとは、など用語を揃えていく章です。
###Day2
RBD編です。
シンプルにジオメトリを Voronoi Fracture で割るやつです。
###Day3
VEX編です。
合わせて Copy Parameter & Paste Relative Reference や エクスプレッションにも触れています。
基本的な記法、変数のパラメータ化、条件分岐と反復処理について触れます。
###Day4
VOP編です。
オブジェクトのディスプレイスに加えて、マテリアル関連についても触れます。
合わせて Render View やライティングに関しても簡単に触れています。
###Day5-10
非公開部分ですが…… 日ごとに別のテーマを紹介しています。
VDB, Vellum, Pyro, FLIP, POP, Height Fieldのセットになっています。

#終わりに
Houdini の学習は最初のとっかかりがとにかく大変だと思うので これからの人の一助になれば幸いです。
お目通しいただきありがとうございました・

明日は [ryuji_shirai](https://qiita.com/ryuji_shirai)さんの"MatrixのアレをHoudiniで作ってみた" です。お楽しみに。
GASとline messaging APIで洗濯タイマーbotを作った話(その1：LINE側準備編)

# はじめに
[LIGHTzアドベントカレンダー 2021](https://qiita.com/advent-calendar/2021/lightz)の18日目の記事です。

この記事では、google apps script(GAS)を使ってサーバレスでLINEbotを作る方法をご紹介します。

 
# 用意するもの
LINEアカウント
└LINE公式アカウント（無料）を作成するのに必要。普段使っている個人アカウントで大丈夫。
googleアカウント
└Google Apps Scriptをwebアプリとしてデプロイするために必要。
こちらも普段使っているもので大丈夫ですが、心配な場合はGAS専用アカウントを作成してもよいです。


# でも、お高いんでしょう？
LINE公式アカウントは月1000通のメッセージ送信までは無料です！
個人や少人数グループで使う分には充分かと。
無料で使い倒すためにはpush APIではなくreply APIを使うなど小技がいろいろありますが、後述します。
フリープランで運用している限り勝手に課金されることはありませんので、ご安心を。

詳しくは[LINE公式のドキュメント](https://www.linebiz.com/jp/column/technique/20200204/)を見てください。

GASは[公式リファレンス](https://developers.google.com/apps-script)が英語しかないのですが、[現時点では](https://developers.google.com/apps-script/guides/services/quotas)無料版でトリガー数が20、実行時間が6分。簡単なスクリプトなら問題なさそうですね！
「毎朝〇時にその日の予定メッセージをpush」などの定期実行も無料です。Herokuの無料プランと比較しても柔軟性が高いですね。


#LINE側の準備

## まずはLINE 公式アカウントをフリープランで作成
公式のリファレンスがわかりやすい
https://www.linebiz.com/jp/column/technique/20190418-3/
大業種・小業種ともに「個人」でOK
未認証アカウントなら審査なしですぐ作れます。

## LINE Official Account Managerにログイン
https://manager.line.biz/

## 右上の「設定」→「Messaging API」からline messaging APIを初期化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160366/f9098faf-f03b-a300-61d6-5a4412d13de2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160366/0e6883a8-8154-e8e1-810f-44939a72f764.png)

## 「設定」→「応答設定」でメッセージ設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160366/02b46cb2-54e9-adcf-5c2a-0889f88baff6.png)
・応答モード→「Bot」
・あいさつメッセージ→「オフ」
・応答メッセージ→「オフ」
・Webhook→「オン」 に設定。

## アクセストークンを取得
https://developers.line.biz/ja/
LINE Developersにログイン
「コンソール」→［チャネル設定］タブでMessaging APIチャネルを選択
［Messaging API設定］タブで[長期のアクセストークン]を発行

※ここで取得したアクセストークンは**漏洩すると第三者に悪用される可能性がある**ため、扱いには気を付けましょう。
GAS内でもソースにべた書きせずにスクリプトプロパティを使います（後述）。

こちらでLINE側の準備は終了です！お疲れさまでした。
次回はGAS側の準備を紹介いたします。
一年半放置した electron アプリに Snyk を使ってみた

# Snyk

[Snyk](https://snyk.io/) はコードの脆弱性を自動で検知するツールです。

https://snyk.io/

# 登録・導入〜実行

## 1. 登録

Snyk のアカウントを作ります。

https://app.snyk.io/login?cta=sign-up&loc=nav&page=homepage

## 2. 導入

npm パッケージとして導入します。

```
npm install -g snyk
```

## 3. 認証

次を実行するとブラウザが開いて認証画面が出ます。

```
snyk auth
```

## 4. 分析

プロジェクトルートに移動して次を実行すると分析が始まります。

```
snyk monitor
```

URL が表示されるのでブラウザで開くと分析結果のダッシュボードが見られます。

# 使う対象

2020 年の 6 月頃に作って放置していた React で UI を構築している electron アプリに Snyk を使いました。

https://github.com/Kishikawa1286/electron-sidebar-test

# 出てきた脆弱性

重大性が High とされたものについてはその内容を調べました。

## Command Injection

脆弱なアプリケーションを介して OS 上で任意のコマンドを実行できる脆弱性です。

https://owasp.org/www-community/attacks/Command_Injection

## Regular Expression Denial of Service

正規表現の計算量が膨大になる入力が存在するという脆弱性です。

https://yamory.io/blog/about-redos-attack/

## Prototype pollution

Javascript のプロトタイプを汚染して、オブジェクトの初期値を操作することができる脆弱性。

https://learn.snyk.io/lessons/prototype-pollution/javascript/?loc=os

## Arbitrary File Overwrite

シンボリックリンク保護が不十分な脆弱性。

https://security.snyk.io/vuln/SNYK-JS-TAR-1536528

https://qiita.com/kusano_k/items/8763374d0dc3edc927cf

# 対応

パッケージのバージョンを上げると検知された脆弱性は解消されました。

# まとめ

1年半放置した結果、多くの脆弱性が発見できる状態になっていました。
パッケージはアップデートに伴って脆弱性を解消していっています。
可能な限り最新版に保ちましょう。
TypeScriptを書いていてちょっと困った事まとめ

TypeScriptで書いているとたまにこの時はどうするんだっけ？ってが止まることがありますよね
今回は私が普段の実装している時に？？って手が止まった時のことをまとめてみました

#### 1. Object.keys使ったループ処理
Object.keysはstring[]を返却するためstring型では列挙型のindexとは型が不一致なためエラーになります

```javascript
const obj = {
  aaa: '0',
  bbb: '1',
  ccc: '2'
}
// error 型 'string' のパラメーターを持つインデックス シグネチャが型に見つかりませんでした。
Object.keys(obj).map((key) => Number(obj[key]))
```
##### 解決策
どこかで型を明示的に変えてあげれば解決します。
###### ① 宣言しているオブジェクトの型を{ [key: string]: string }で定義する
上記の宣言だと列挙型になってしまうので列挙型ではなくインデックスシグネチャの型定義をしてあげれば参照できるようになります。

```javascript
const obj: { [key: string]: string } = {
  aaa: '0',
  bbb: '1',
  ccc: '2'
}
```
##### ② Object.keysで取得した値をアサーションする

```javascript
(Object.keys(obj) as Array<keyof typeof obj>).map((key) => Number(obj[key])) 
// or 
Object.keys(obj).map((key) => Number(obj[(key as keyof typeof obj)]));
```

何をやっているかというとobjをtypeofでいったん

```javascript
{
  aaa: string,
  bbb: string,
  ccc: string
}
```

このようなtypeにしてからkeyofで

```
  aaa | bbb | ccc
```

keyだけの型定義にして結果をObject.keysの戻り値もしくはmapの第一引数のkeyにアサーションしています。
ちなみにObject.keysはstring[]を返却するため以下のようにアサーションするのはできません。

```javascript
Object.keys(obj).map((key: keyof typeof obj) => Number(obj[key]));
```

また、アサーションをObject.keysするたびに行うのはスマートではないのでwrapperしてkeyのunion typeが返ってくるような関数を作成するのも手です。

```javascript
const wrapObjectKeys = <T>(obj: T) => Object.keys(obj) as Array<keyof T>;
wrapObjectKeys(obj).map((key) => Number(obj[key]));
```

#### 2.ライブラリの型定義にないフィールドを参照したい
 
稀によくあるのですがライブラリの関数の戻り値の型をconsole.logなどでみると型定義には存在しないフィールドがいて自分がその値を参照したいけどそのまま参照するとerrorになってしまいます。

```javascript
export type Event {
  value: string;
}
interfact Props {
  onClick: (event: Event) => void
}
export const Component: React.FC<ITextBoxProps> = (props: Props ) => {
  return <div {...props} />
}
```
こんな型定義のコンポーネントを提供しているライブラリがあるとして

```javascript
import { Component, Event } from 'Component'

const onClickEvent = (event: Event) => {
  console.log(event)
}

return (
  <Component onClick={onClickEvent} />
)
```

これでコンソールログで値を見ると { value: string, beforeValue: string }
となっていてbeforeValueを参照したいのに型定義上には存在しないため以下のようにeventからbeforeValueにアクセスするとエラーになります。

```javascript
console.log(event.beforeValue)
```

##### 解決策

渡す引数にoptionalの値を&でつないで型を拡張する

```javascript
import { Component } from 'Component'

const onClickEvent = (event: Event & { beforeValue?: string }) => {
  // アクセスできる！
  console.log(event.beforeValue)
}

return (
  <Component onClick={onClickEvent} />
)
```

optionalにしないとライブラリが提供している型定義と合致しないエラーが出てしまうのでoptionalにするのは必須です。
BigQuery日本語カラム自動変換ツールのアップデート 

https://qiita.com/yasudakn/items/2e6a69a11845a9bcdc33

以前、この記事で作ったWebアプリについて活用出来るユースケース、使い方、アップデート情報を紹介します。

## ユースケース

- 手元にあるエクセルデータのカラムが日本語で、BigQueryやAutoMLに入らない!

BigQueryやAutoMLを始めるにあたって、日本語カラムが障壁になっているも多いのではないでしょうか。
2021/12/19 現在、データセット名までは、Unicode対応が入っています。
近いうちにカラム名のUnicode対応が入ってくるとは思いますが、保守性の観点で物理名には英字を利用したい需要も多いと思います。

- 一定のルールで機械的にカラムを日本語変換したい! メンテナンスしたい!

一旦変換したスキーマをjsonスキーマとしてエクスポート出来ます。
（今後、インポート出来る機能追加する予定です)
辞書登録機能として外部のcodicに任せることも出来ます。

## 使い方
動画を見ると使い方のイメージが付くはず
![画面収録-2021-12-22-10.18.52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636318/78e502c5-d4fd-5e1e-9963-9449d4526082.gif)


## 導入方法
アプリは次の手順で実行出来ます。

#### 1. `git clone`
ソースコード一式は[こちら](https://github.com/yasudakn/column-name-auto-generator)にあります。

```
git clone https://github.com/yasudakn/column-name-auto-generator
```

#### 2. `.env`の作成
トップディレクトに`.env`ファイルを作成します。

```
FRONTEND_PORT=3000
FRONTEND_CONTAINER_NAME=column-generator-frontend

REACT_APP_CODIC_URL=https://codic.jp/
REACT_APP_CODIC_API_URL=https://api.codic.jp/
REACT_APP_CODIC_API_REQUEST_MAX_LENGTH=24
REACT_APP_CODIC_PROJECT_ID= <codic-project-id>
REACT_APP_CODIC_API_TOKEN= <codic-api-token>

BACKEND_CONTAINER_NAME=column-generator-backend
BACKEND_PORT=3001

GOOGLE_APPLICATION_CREDENTIALS= /app/keys/<gcp-service-account-credentials-json-filepath>
PROJECT_ID= <gcp-project-id>
LOCATION= <gcp-location>
DATASET_ID= <bigquery-dataset-id>
```

codicのtokenは、[free plan](https://codic.jp/plans)でsignupした後に、[apiステータス](https://codic.jp/my/api_status)のメニューで取得出来ます。
GCPで次の権限を付加したサービスアカウントを作成し、`keys`の配下にjson秘密鍵を作成して置きます。`GOOGLE_APPLICATION_CREDENTIALS`には、そのパスを配置します。

- BigQuery ジョブユーザー
- BigQuery データ編集者

#### 3. `docker-compose`で実行

```
docker-compose up --build
```


## アップデート情報

最近のアップデートの内容です。
次のようなバグ対応と機能追加が入っています。

- jsonスキーマの出力、ダウンロード（取り込みは未対応）
- データ型の自動判定(数値は一律float64、画面上でカスタマイズ可能)
- 文字コード自動判定、utf-8自動変換
- エラー時の途中リトライ
- 先頭の数字,記号の取り除き
- 記号の取り除き
- 変換不可の日本語の取り除き
- codicプロジェクトIDなしでも動くように

![スクリーンショット 2021-12-19 21.19.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636318/ac645484-7553-758a-c479-834d89b22d34.png)


## アップデート予定

- カスタム辞書
- codic以外の変換API対応(わかち書きした後に、Google翻訳にかける等)
- jsonスキーマのインポート
- BigQuery以外のRDBMSなどへの対応
Swiftでビジネスロジックを考えてみる

# Swiftで電気ケトルのロジックを作る
スクールの課題でプログラムの使用を考えるように言われた。身近なものであるエレベーターやケトルの例外処理をSwiftで考えて下さいとのこと🤔
で、やってみたこと👇

## 電気ポットのビジネスロジックを作成
- STEP1: 仕様を考えてリスト化
- STEP2: Swiftで実装する
- STEP3: 例外ケースを考えてリスト化
- STEP4: 例外ケースを考慮したコードに書き換える

## 通常使用
1. スイッチを押すとランプが点灯してお湯を沸かし始める
2. 沸かし終わると音が鳴って知らせてくれる

## 例外処理
1. 水が入ってないと空焚きになるので沸かせない
2. 最近の電気ポットは空焚き防止機能がついているそうなので電源を落とす処理を実装する

## やってみた感想

Int?をasを使ったりして型変換しようとしたり、デリゲートパターンなど機能を色々と盛り込もうとしたが、実現したいのは、電気ポットのお湯を沸かす仕組みをSwiftを使ってプログラムの使用を作るという単純なことなので、色々なパターンを考えたが、シンプルにしてみました。
こちらのサイトを参考にguart文を書いてみました。

https://www.sejuku.net/blog/32607

数値を扱う場合、letと書いて定数に引数を代入しようとしたら、エラーが出てくるので、guard storage > 0 else { といった感じで書いてみました。

```
// if文を使用した例
class DeLonghi {
    var product: String = "デロンギ社のケトル"
    
    func check(water: Int) {
        if water > 0 {
            print("0を超えているときの処理")
            print("\(water)mlの水を入れました")
            print("スイッチが押されてランプが点灯しました")
            print("お湯が沸いて「カチッ」と音がなりました\n")
        } else {
            print("0を超えていないときの処理")
            print("スイッチが押されてランプが点灯しました")
            print("空焚き防止機能が作動して電源が落ちました\n")
        }
    }
}

let dp = DeLonghi()
print("\(dp.product)\n")
// ケトルに水が入っているときに実行される処理
dp.check(water: 400)
// ケトルに水が入っていないときに実行される処理
dp.check(water: 0)

// guard文を使用した例
class Kettle {
    // 後で製品名で答えるかもしれないのでOptional型にしてみる
    var japan: String?
    
    func waterCheck(storage: Int) {
        guard storage > 0 else {
            print("スイッチが押されてランプが点灯しました")
            print("空焚き防止機能が作動して電源が落ちました\n")
            return
        }
        print("\(storage)mlの水を入れました")
        print("スイッチが押されてランプが点灯しました")
        print("お湯が沸いて「カチッ」と音がなりました\n")
    }
}

let kc = Kettle()
// デフォルトでは国産のケトルにしておく
print(kc.japan ?? "国産のケトル\n")
// ケトルに水が入っていないときに実行される処理
kc.waterCheck(storage: 0)
// ケトルに水が入っているときに実行される処理
kc.waterCheck(storage: 600)

```
コンソールのログ

```
デロンギ社のケトル

0を超えているときの処理
400mlの水を入れました
スイッチが押されてランプが点灯しました
お湯が沸いて「カチッ」と音がなりました

0を超えていないときの処理
スイッチが押されてランプが点灯しました
空焚き防止機能が作動して電源が落ちました

国産のケトル

スイッチが押されてランプが点灯しました
空焚き防止機能が作動して電源が落ちました

600mlの水を入れました
スイッチが押されてランプが点灯しました
お湯が沸いて「カチッ」と音がなりました
```

## 最後に
今まで、JavaScriptやFlutterをやっていたときはアプリを作ることしか考えておらず、現場で必要な知識であるプログラムの使用を考えることはなかった😱
プログラミングスクールに通ってみて、現役のメンターさんから貴重なご意見を教わりました。
フロントエンドエンジニアとデザイン

# はじめに
この記事は、[seya](https://qiita.com/seya)さんが立ち上げられた[エンジニアリングに興味があるデザイナー、デザインに興味があるエンジニア Advent Calendar 2021](https://qiita.com/advent-calendar/2021/design-code)の19日目の記事です。

https://qiita.com/advent-calendar/2021/design-code

参加させていただき、ありがとうございます🎄✨


# 私について
まずはじめに、簡単に自己紹介します😊
私は現在、フロントエンドエンジニアとしてWebアプリケーションの開発に携わっています。
エンジニアとしては今年1月からキャリアをスタートしたばかりの、新米エンジニアです🔰

今回は、デザインに興味があるエンジニアとして、実務開始して1年弱で感じたことをまとめてみます。
ベンチャー企業での開発の様子や、フロントエンドエンジニアとしてデザインとどのように関わったかお伝えできればと思います。


# 開発体制
いま働いている会社は、まだ立ち上がって間もないベンチャー企業です。

開発チームは、

- エンジニア（バックエンド、フロントエンド）
- デザイナー

で構成されており、計5名程度の極めて小規模のチームです。


対して開発案件は受託案件と自社開発案件含め複数件あります。

つまり・・
**大規模のチームのように、それぞれの職域がはっきり分かれているわけではなく、一人ひとりが担当する範囲は広くなります。**
個人的には、それがスタートアップや小規模チームで働く醍醐味だと感じています😃

私のように経験が浅いエンジニアでも、バックエンドエンジニアの方と一緒に要件定義やDB設計を行ったり、デザインからフロントエンド開発、さらには学生インターンの教育など幅広い業務を担当しています。

入社する前から、立ち上がったばかりのチームなので自分の成長が事業の成長に直結すると聞いていましたが、たしかにそのとおりで、毎日ハードですがチームの一員としてやりがいを感じながら開発しています！


# 実務でデザインを担当
現在主に携わっている開発は、フロントエンド（私）とバックエンドの2名体制で開発しています。
デザイナーやインフラエンジニアが別にいるわけではないので、2名で要件定義からデプロイまで担当しています。
今回の開発で、初めて実務でワイヤー設計とデザインを担当しました。

### デザインは情報設計が大事
今回はじめてデザインを担当してみて実感したのは、**Webアプリケーションにおけるデザインは情報設計が大切**ということです。

具体的には、
開発するアプリは

- 誰がどんなときに使うのか
- どこに価値があるのか

を整理し、

- 使ってもらうためにはどのような情報をどんな形で配置すべきか
- あしらいやトンマナはどうするか

を論理的に組み立て、形にする作業でした。

システム開発における要件定義は開発側と依頼側の共通認識を得るためのものであるということを、デザインから担当したことで、より実感しました。

### レビューをもらい改善していくサイクルを多く繰り返す
私の圧倒的なデザインスキル＆経験不足をカバーするため、ワイヤーからデザインカンプまで一貫して、
早く作る➔レビューもらう➔改善する
のサイクルをできるだけ多く繰り返すことを意識しました。
弊社デザイナーの方たちは、自分の好みではなくデザインの引き出しを増やすことを課題としてスキルアップに努めてますが、情報整理して提案する中でデザインパターンは多く持つべきであると思いました。


# デザイナーに代わることはできない
フロントエンドエンジニアはUIを実装するという点でデザイナーと共通しているため線引が曖昧な部分もありますが、今回デザインを担当してみて、（当然ですが）デザイナーに代わることはできないと感じました。

情報設計はできても、デザインパターンの引き出しの少なさと、どうしてもその先の実装を考えてしまい、実装しやすいようにデザインしてしまいました😓


# エンジニアがデザインすると良いこと（=デザインで考慮されていたら嬉しいこと）
他方でエンジニアがデザインを行うことのメリットもいくつか感じました。

### 実装を意識したデザイン
画面サイズやGridはもちろんのこと、使用するUIライブラリ（今回はTailwindCSSとdaisyUI）をふまえたSpacingまで考慮してデザインしたので、実装がスムーズでした。

https://tailwindcss.com/

具体的には、TailwindCSSのレスポンシブやデフォルトフォントサイズ（１６ｐｘを1remとしてrem指定）を変更せず実装できるようにしたり、1人での開発なので工数削減のため小さな積み上げを行いました。

余談ですが、今回のデザインでChromeデベロッパーツールの[ColorZilla](https://chrome.google.com/webstore/detail/colorzilla/bhlhnicpbhignbdhedgjhgdocnmhomnp?hl=ja)や[PxtoRem](https://chrome.google.com/webstore/detail/pxtorem/ldbemkmafmibhpncgagpegmhbhpolnlp)にお世話になりました🙏

### コンポーネント設計も一緒にできる
デザインする際にコンポーネント設計も一緒に行うことができるので、工数削減になります。
あるUIデザイナーの方から、デザインと併せてコンポーネント案も一緒にお渡ししますと言われたときには、ありがたや・・😭✨となりました。


# おわりに
長いポエムにお付き合いいただき、ありがとうございます。

個人的には、今回のデザイン担当を通してデザイナーの方へのリスペクトが高まりました！

デザイナーとエンジニアは仲が悪くなりがち・・・なんて話も聞きますが、結局はお互いに思いやりをもってコミュニケーションとることが大切だと思っています。
より良いプロダクトのため、協働して開発していけたら良いですね😊
【Rails】日本語化のやり方

##手順
①gem 'rails-i18n'をインストール
②デフォルトの言語を日本語に設定
③複数のロケールファイルが読み込まれるようpathを通す
④新しいファイルを作成

####①gem 'rails-i18n'をインストール

```
#Gemfile
gem 'rails-i18n', '入れたいバージョン'
→ bundle install
```


####②デフォルトの言語を日本語に設定
config/application.rbに
```config.i18n.default_locale = :ja```を追加。

```
class Application < Rails::Application

　#以下の記述を追記する
　#デフォルトのlocaleを日本語(:ja)にする
　config.i18n.default_locale = :ja

end
```

####③複数のロケールファイルが読み込まれるようpathを通す
先程の②と同様にconfig/application.rbに
```　config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]```を追加。

```
class Application < Rails::Application
　config.i18n.default_locale = :ja

#　以下の記述を追記する(設定必須)
　config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]

end
```

####④新しいファイルを作成
config/localesに２つのファイルを作成。
・```activerecord/ja.yml```　→　modelの日本語化対応のymlファイル
・```views/ja.yml```　→ view,controllerの日本語対応のymlファイル

##ja.yml内の書き方
**activerecord/ja.yml**
model全体に対応させるときはmodelsの階層を作り、
カラム名を対応させるときはattributesの階層を作って日本語化にする文字を記入。
**※追記※**
モデルの日本語を設定した場合、viewでわざわざコードを変更する必要は無い。（勝手に反映される）

```
ja:
  activerecord:
    models:
      user: 'ユーザー'
      board: '掲示板'
    attributes:
      user:
        email: 'メールアドレス'
        password: 'パスワード'
        password_confirmation: 'パスワード確認'
        last_name: '姓'
        first_name: '名'
```

**views/ja.yml**
以下の書き方でapp/views/users/new.html.erbビューテンプレート内部でnew.index.title値にアクセスできる。

```
ja:
  users:
    new:
      title: 'ユーザー登録'
      to_login_page: 'ログインページへ'
```

##ビューファイル内での書き方

```
<%= t '.title' %>  または  <%= t ('.title') %>
省略せずに書くと　→ <%= t 'posts.index.title' %>
```

**記入例**

```
<h1>ログイン</h1> → <h1><%= t '.title' %></h1>

<%= f.submit '登録', class: 'btn btn-primary' %> 
→ <%= f.submit (t 'defaults.register'), class: 'btn btn-primary' %>
```

**※form_withの場合は注意※**

```
<%= form_with model: @user, local: true do |f| %>
  <%= f.label :name, t('activerecord.attributes.user.name') %>
  <%= f.email_field :name %>
```
上記のようなform_with文があった場合、ビューファイル内での書き方によると```t('activerecord.attributes.user.name')```になるが、
form_withは```model: @user```という記述から「これはユーザーに関するフォームである」と認識してくれるので、以下の書き方でOK。

```
<%= form_with model: @user, local: true do |f| %>
  <%= f.label :name%>
  <%= f.email_field :name %>
```

##参考記事
[[初学者]Railsのi18nによる日本語化対応](https://qiita.com/shimadama/items/7e5c3d75c9a9f51abdd5#3-i18n%E3%81%AE%E8%A4%87%E6%95%B0%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%82%8B%E3%82%88%E3%81%86path%E3%82%92%E9%80%9A%E3%81%99)
[[Rails]日本語対応のためのGem 'rails-i18n'の使い方](https://qiita.com/atsushi101011/items/bd07e0dccf45a6055189)
JavaでBase64復号化（String -> byte[]）を省メモリに行う

## 概要
昨日はJavaでBase64符号化・復号化を省メモリで行う記事を書いた。

https://qiita.com/kago/items/b437928ebd58e8382e32

上記はInputStream/OutputStreamで入出力しているが、メモリ上にデータを保持する必要がある場合は別の実装になるので、今回はStringからbyte[]への復号化について考えた。

## 実装
```Base64sample.java
public class Base64sample {

    private static final int T_LEN = 16 * 1024;
    private static final int B_LEN = T_LEN * 3 / 4;

    public static byte[] decode(String src) throws IOException {

        byte[] result = new byte[getDecodedLength(src)];

        try (Reader reader = new java.io.StringReader(src)) {
            char[] buf = new char[T_LEN];
            byte[] enc = new byte[T_LEN];
            byte[] dec = new byte[B_LEN];
            int r, offset = 0;
            while ((r = reader.read(buf)) != -1) {
                copy(buf, enc, r);
                int len = Base64.getDecoder().decode((r == B_LEN) ? enc : Arrays.copyOf(enc, r), dec);
                System.arraycopy(dec, 0, result, offset, len);
                offset += len;
            }
        }

        return result;
    }

    private static int getDecodedLength(String src) {
        int len = src.length() * 3 / 4;
        for (int i = 1; i <= 2; i++) {
            if (src.charAt(src.length() - i) == '=') {
                len--;
            } else {
                break;
            }
        }
        return len;
    }

    private static void copy(char[] chars, byte[] bytes, int length) {
        for (int i = 0; i < length; i++) {
            bytes[i] = (byte) chars[i];
        }
    }

}
```
復号化対象のStringの長さおよび末尾の"="の数から復号化後のbyte数を算出し、必要な長さのbyte[]を事前に確保している。それ以降は[前回記事](https://qiita.com/kago/items/b437928ebd58e8382e32)と同様に少しずつ復号化することで、入出力となる復号化前Stringと復号化後byte[]以外には大きなオブジェクトを保持しないようにしている。
なお、入力となるStringが正しくBase64符号化されていることを前提とした実装なので、そうではない可能性がある場合には事前にチェックする必要がある。

## アンチパターン
大きなbyte[]を生成する場合、ByteArrayOutputStreamは使わない方が良い。toByteArray()は、書き込まれた内部バッファからコピーして新たなbyte[]を生成するため、メモリ消費が大きくなるためである [^1]。

[^1]: ByteArrayOutputStream#toByteArrayの内部でArrays#copyOfを呼び出している
LightGBMを触ってみた

##はじめに
LightGBM は、2016年に米マイクロソフト社が公開した決定木アルゴリズムに基づいた勾配ブースティング（Gradient Boosting）の機械学習フレームワークです。今回はLightGBM をモデルとし、中古物件のデータから住宅価格を予測しました。

予測の精度はさておき、まずはモデルをまわして予測値を出すところまでやったので、やり方を備忘録として残しておきます。


##コードの説明
###ライブラリをインポート

```
import pandas as pd
import numpy as np 
import matplotlib.pyplot as plt 
import lightgbm as lgb 
from sklearn import datasets
from sklearn.model_selection import train_test_split 
from sklearn.metrics import mean_squared_error 
from sklearn.metrics import r2_score
```

###CSVデータをPandasデータフレームへ格納
CSVデータには、住宅価格の他に位置情報、部屋数、海からの近さなどの情報が入っている。

```
df = pd.read_csv('/../input/housing.csv')
```

###データの準備
住宅価格以外の項目を全て説明変数とし、住宅価格を目的変数とした。

```
x = df_replace.drop(['house_value'],axis=1).values# 説明変数
y = df_replace['house_value'].values # 目的変数(house_value)
```

データを学習データとテストデータに分割する。テストデータは全データの20%に設定。

```
x_train, x_test, y_train, y_test = train_test_split(x, y,test_size=0.20)
```

### テストデータの予測
モデルの学習と予測値算出。

```
model = lgb.LGBMRegressor() 
model.fit(x_train, y_train) 
y_pred = model.predict(x_test)
```

###モデルの評価
RMSE（平均平方二乗誤差）とR2（決定係数）を計算。

```
mse = mean_squared_error(y_test, y_pred) 　# MSE(平均二乗誤差)
rmse = np.sqrt(mse) 　# RMSE(MSEの平方根)
print('RMSE :',rmse)

r2 = r2_score(y_test,y_pred)
print('R2 :',r2)

#出力
RMSE : 47534.167567117795
R2 : 0.8340967595740189
```

##まとめ
とりあえずLightGBM を使ってみることを目的に、中古物件のデータから住宅価格を予測し、予測結果からRMSE（平均平方二乗誤差）とR2（決定係数）を計算しました。今後はデータの前処理をしっかりし、精度を高めていきたいと思います。

参考：https://mathmatical22.xyz/2020/04/09/%E3%80%90%E5%88%9D%E5%AD%A6%E8%80%85%E5%90%91%E3%81%91%E3%80%91lightgbm-%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9-%E5%9B%9E%E5%B8%B0%E5%88%86%E6%9E%90%E7%B7%A8%E3%80%90python/
多次元配列

　プロデルで多次元配列を簡単に作れるようにした。

```プロデル
多次元配列とは
	【データ】
	【形】
	はじめ（サ）の手順
		データは，［サ］で，作ったもの
		形は，サ
	終わり
	［サイズ］で，作る手順
		【甲】は，倍浮動小数の固定配列（サイズ（1））を作ったもの。
		もし［サイズの個数］は，2以上なら
			［甲の個数］回【乙】にカウントして繰り返せ
				甲（乙）は，サイズの2番目から切り出したもので，作ったもの
			繰り返し終わり
		もし終わり
		甲を返す
	終わり
	中身を取得する手順
		データを返す
	終わり
	大きさを取得する手順
		形を返す
	終わり
終わり
```

使い方は，各次元の大きさを指定して作る。

```プロデル
甲という多次元配列（｛3，4，5｝）を作る。
甲の中身を報告
甲の大きさを報告
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150160/5e6e1246-134b-c485-c1cc-3fd3a27003e3.png)


なおこれはコンパイルすると`［サイズ］で，作る手順`の`サイズ`の型が定まらずにエラーになる。
自社のプロジェクト管理ツールにZenHubが一番あってたって話

プロジェクト管理ができるツールは色々ありますね。
みなさんは何を使っていますか？

- Confluence
- Asana
- Backlog
- Trello
- Notion
- Excel (?)

自社でもいくつか試したことがあるのですが、
今回は中でも一番使い勝手のよかった[ZenHub](https://www.zenhub.com/)を紹介します。

## ZenHub

ご存知の方も少なくないと思いますが、
ZenHubはGitHubに拡張機能として統合可能なプロジェクト管理ツールです。
主にアジャイルなプロジェクトを想定した機能が盛りだくさんです。

### Board

[Board](https://www.zenhub.com/boards)は、ZenHubの主たる機能です。
アジャイルではお馴染みのカンバンボードを提供します。
issueをカードとして扱うことができ、プロジェクトごとにパイプライン（列）の設計ができます。
また、１つのボードに複数のGitHubリポジトリを紐づけて管理することができます。
リポジトリを跨いで管理する必要があるプロジェクトにもうってつけです。

検索機能も充実しており、ラベル、スプリント、担当者等での検索もできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36105/0a985a33-f10e-e2f6-ef3e-7fa84f2ea0d8.png)


### Estimate

ZenHubをGitHubに統合すると、issueにしれっと追加される機能が幾つかあります。
そのうち一つはEstimate（見積もり）、これは「Issueにストーリーポイントを設定する機能」です。
この機能がシンプルながら強力です。

ストーリーポイントそのものの見積もり手法についてはここでは紹介しませんが、
日数や週数、時間数での見積もりではなく、相対値での見積もりとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36105/aa2c0a86-204e-fb4c-52bd-ff0d271c3715.png)

Issueの右下あたりにこのようなUIが現れています。
数字部分をクリックすることでももちろん設定できますが、
スクラム等でお馴染みの手法「プランニングポーカー」という機能を使うこともできます。
ZenHubでもプランニングポーカーの参加者全員がポイントを入力し、
全員の入力が出揃った時点でポイントが開示されます。
あとはポイントが合うように議論を重ねます。

Board上では、ポイントが設定されたパイプラインの上部で
現在そのパイプライン上に配置されているIssueに設定されている合計ポイントもわかります。


### Sprints

ZenHubではスプリントの設定も可能です。
Boardの右上の追加ボタンからスプリントの設定や編集が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36105/16b60a6a-a673-7824-116f-0119c405b57c.png)

例えば、スプリントが2週間のプロジェクトの場合、
下記のように２週間ごとに月〜金という形で設定することができます。
このスプリント機能は、期間がどれくらいでいつ始まっていつ終わるかを指定すれば、
そのサイクルで、ずっと未来のぶんのスプリントも確保してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36105/71cb4a40-67b1-8506-090a-681758271870.png)


### Burndown Report

先程のBoard、Estimate、Sprint等の機能を活用していると
それらを集計するReport機能が役立ちます。

例えばReportの画面ではアジャイルプロジェクトでのお馴染みの、
バーンダウンチャートが利用可能です。

先程までに紹介した機能を利用しているだけで、
このレポートは自動的に作成されている上、リアルタイムで計算されています。
チームの進捗把握に非常に役立っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36105/01e5be34-ea84-ae93-85bb-ec1bf4c53274.png)

右上に「Done」が設定してありますが、
これはそれぞれのIssueを完了済み扱いにするパイプラインを設定しています。
Close以外も完了として扱ってくれるのはありがたい。

チャートの青線部分が実際の消化ライン、点線がノルマラインです。
（ちょっと進捗が怪しいですね？）

---

今回は特に活用している機能をピックアップしましたが、
他にも「Epic」、「Roadmap」、「Workflows」など、便利な機能があります。

## ZenHubがイチオシな理由

エンジニアは、数あるWEBサービスの中でもGitHubを見ている時間が多く、
あまり色々なツールを行き来することを好まない人も多いかと思います。

ZenHubはGitHub拡張機能を入れる形で利用できるため、
コードとプロジェクトの管理がGitHub上で完結します。
また、Board上のカードはIssueやPullRequestそのものなので、
Issueの依存を追加したり参照したりcloseしたりするにも直感的で簡単です。
アジャイルプロジェクトに着目されているためか、必要な機能が洗練されていて、使いこなすハードルも低めな印象です。

GitHubを既に活用していて、しっくりくるプロジェクト管理ツールが見つかっていない方は
ぜひZenHubも試してみてください。
Excelでチェックボックスにチェックが入らないときに、リンクセルがエラーになっている場合がある

#ポイント
##発生するケース
チェックボックスを別のシートのセルにリンクしていたが、そのシートを削除してしまった、というときに発生する。
##チェックボックスには色々ある
ExcelのActiveXではないチェックボックス

##プロパティ名
`Shp.LinkedCell)
ではなく
`Shp.ControlFormat.LinkedCell`
である。
これがわかりにくい。

## 図形名
また名前が日本語でチェックボックスと書いていてもVBAではCheck Boxという名前で認識されている場合がある。
これは処理する場合の名前と表示が違うため。
Fomula(数式)であれば`Name`と`NameLocal`に分かれるプロパティが分かれていない。仕様とという名前のエラーだと思われる。
今回はすべて自動で`Check Box ##`(`##`は数字)名前がついているものとして処理している。

##コード
###アクティブシートのチェックボックスのすべてのリンクセルを削除するマクロ
<Font color = "Dark Red"><B>必ずバックアップをとって使うこと</B></Font>
ただのチェックボックスになってしまうためあまり使うことは推奨できない。本来は名前を指定して削除すべきである。
セレクトして起動して削除できればいいのだが、セレクトした途端エラーが発生する時もあり、どうしようもない。
手動でも削除しづらい。プロパティから削除できればよいが、プロパティを開くとエラーになる場合がある。なぜか背後の数式バーに表示されるという場合もある。
このため、エラーが発生し、大量にある場合はやむなく使わざるを得ない。
On Errorが効かないときはDebug...の行は削除すること。

```VB
Sub deletlinkedCellFromCheckBox()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim shp As Shape
On Error Resume Next
  For Each shp In ws.Shapes
    If shp.Name Like "Check Box*" Then
     Debug.Print shp.Name, shp.ControlFormat.LinkedCell ' エラーになるときは消去
     shp.ControlFormat.LinkedCell = ""
    Else
     Debug.Print shp.Name
    End If
   Next
End Sub
```
TCE構築に使うコマンド類をコンテナでくるんで次回ちょっとだけ楽したかった件

この記事は、[TUNA-JP Advent Calendar 2021](https://qiita.com/advent-calendar/2021/tuna-jp) 22日目のエントリーで、
Tanzu Community Edition(TCE)構築時の準備をちょっとだけラクにしてみようとしたときの内容です。

---

みなさん、TCE/vCenter上にマネジメントクラスタを起動するパタンでの構築はどんな環境で実行していますか?
私の場合は、おうちvSphereな環境に構築用のVM(ubuntu)を起動して、そのVM上にCLI等をインストールして、構築していました。

できるだけ、次回構築するときにラクできるようするために、tanzu等コマンドの実行環境をコンテナにまとめてみました。

当初は、コマンド類をまとめたイメージをビルドするだけでしょ? と思ってましたが
ちょっとだけ素直に起動できない箇所があったので、それも含めてリポジトリにまとめてみました。
n番煎じ感は半端ないですが、お付き合いください。

---
Dockerfile、docker-compose.yaml にまとめたので、 `docker-compose up -d` して、
コンテナ内でクラスタ構築作業ができるようになるので、次回はちょっとだけ楽してクラスタ構築環境が再現できるはず。  
コンテナを落としても(docker-compose down)、構築+構築後のクラスタのアクセスに必要なファイルは永続化してみています。

ちなみに、実行環境用の VMイメージにしておけばいいじゃん とか、他のアプローチもありそうなので、
皆さんどうしてるんですかねぇ。


## 使い方

早速ですが、以下のリポジトリに Dockerfile とdocker-compose.yaml をまとめました。

 - Dockerが起動できて,docker-compose コマンドが実行できて
 - インターネットに繋がっている

Linuxなマシンで実行できるはず。(私の実行環境は Ubuntu 20.04 LTS + Docker / Server Version: 20.10.11 + docker-compose 2.2.2)

`docker-compose up -d` すると手元でコンテナイメージをビルド(必要なコマンド類を回収ー)したあとに、
コンテナを起動します。 


```
# Git Cloneする
git clone https://github.com/make0x0/tanzuenv
cd tanzuenv

# docker-compose up する
docker-compose up -d

# イメージがビルドされたら、コンテナに潜る
docker-compose exec tanzuenv bash
```

あとはコンテナ内で、先人たちのわかりやすい記事に従って、tanzuのコマンドを打ってクラスタを構築するだけです。
これで次回は上記のリポジトリをCloneして実行するだけで、コマンド類が一式揃った環境でTCEの構築ができるはずだぞぃ!


## コンテナに包もうとしたときに躓いたところ

### どこにTCEの設定ファイルが保存されるのだろう?
- kubeconfig類
    - ~/.kube : 構築したクラスタの接続情報が格納
    - ~/.kube-tkg : マネジメントクラスタの接続情報が格納
- TCEが必要とする、設定ファイル類の保存先
    - ~/.config/tanzu : クラスタ構築時のカスタマイズに必要なファイルもここに格納されるみたい
    - ~/.cache/tanzu

この辺っぽいので、コンテナ外に保存されるように[設定](https://github.com/make0x0/tanzuenv/blob/master/docker-compose.yaml#L8)した 


### docker.sock をマウントしないといけない

Tanzuコマンドでマネジメントクラスタ構築をする際 コンテナとして小さなKubernetesクラスタ(kind)を起動される。
そのため、コンテナ内でdockerコマンドの実行と、ホスト上のDockerデーモンにアクセスできないとだめっぽい。

- コンテナ内にDockerコマンドを[追加](https://github.com/make0x0/tanzuenv/blob/master/Dockerfile#L37)した
- ホスト上のDockerデーモンにアクセスできるように docker.sock を[マウント](https://github.com/make0x0/tanzuenv/blob/master/docker-compose.yaml#L14)した

が必要でした。

### TCEインストーラーのWebUIにアクセスするためにはネットワークをHostModeにする必要があった

[ここ](https://github.com/make0x0/tanzuenv/blob/master/docker-compose.yaml#L17)


### TCEのコマンドをインストールするとき rootユーザーだと怒られる

環境変数に [ALLOW_INSTALL_AS_ROOT=ture](https://github.com/make0x0/tanzuenv/blob/master/Dockerfile#L22) を設定するとインストールできた。(とりあえず動いたけど、、、いいかなぁ。。。)

(Github上のDockerfile 2回宣言してるな。。。。)


## マネジメントクラスタの起動

あとはコンテナの中で、TCEの構築手の手順にある、tanzuコマンドを使ってインストーラーを起動、
ホストのVMのブラウザで UIにアクセスすれば、マネジメントクラスタを立ち上げられると思います。

```
tanzu management-cluster create --ui
```
(ウィザードに従ってセットアップすると･･･)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131643/c6981bc2-e9a1-f9c0-5429-7af3307534f7.png)

よしよし、できたできた。
次回 、準備作業の10分ぐらいは短縮できたんじゃないかなー と自己満足できました。ありがとうございました!

### 追記 マネジメントクラスタの削除も問題なし!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131643/c9aec7f2-5148-c118-7c8d-bb189d6e1143.png)

コンテナで設定ファイルも含めてくるんでいるので、1台の作業用マシンで、複数のマネジメントクラスタを扱いやすくなった気がします。
新人エンジニアの振り返り2

こんにちはnishioです

今週の振り返りと来週どうしたいかを記述していきたいと思います。

# 今週やったこと
* スッキリわかるJava入門の学習
     * インスタンスとクラス
        * オブジェクトを生成するためのもの金型が「クラス」、実際に活動するオブジェクトが「インスタンス」
        * クラスには属性(フィールド)と操作(メソッド)がある
        * new演算子を用いることでインスタンスを生成できる
        * 変数名.フィールド名;、変数名.メソッド名();でフィールドやメソッドにアクセスが可能
    * クラス型と参照
        * クラス型変数の中はインスタンスの情報が先頭番地に格納されている
    * コンストラクタ
        * コンストラクタはオーバーロードによって複数定義できる
        * コンストラクタはコンパイル時に自動で引数および処理なしのデフォルトコンストラクタが生成される
        * コンストラクタはクラス名と同じであること、戻り値がないこと
        * フィールドに初期値を設定できることで、インスタンス化の際にいちいち初期値を記述しなくて済む
    * 継承および高度な継承
        * 継承を用いることで既存クラスを利用でき、自クラスと合わせてオブジェクトを楽に生成できる
        * 子クラス側のメソッドで対応する
        * コンストラクタはスーパークラスから先に呼ばれる
        * 高度な継承としては継承するための材料を作れるように意識すること
    * 抽象クラス
        * 抽象クラスはメソッドの具体的な動作が決まっていないときに作る
        * オーバーライドのし忘れやインスタンスを生成できないようになっている
    * インタフェース
        * 抽象メソッドしか持たず、フィールドも定数以外持たない
        * インタフェースは多重継承できる
        * 実装する際は、implementsを用いる
    * 多態性
        * 物事をあいまいにとらえること
        * 水、お茶を飲み物として捉えること
        * is-aの関係が成立しているなら、親クラスの変数に子クラスのインスタンスを代入できる
        * どのメソッドを利用できるかは箱の型で決まる
        * メソッドが動くかは中身の型で決まる
        * あいまいに捉えることで同じ種類の動作をまとめて対応できる
        * 一つの動作で各々が適した行動をとることができる

# 来週はどうしたいか
今週は基礎をしっかり学んだつもりが、親クラスに初期値の設定ができていなかったりと応用できていなかったため、その日やった内容に関する練習問題を行ってしっかりと覚えていきたいです。
また、考えながら人に伝えたりまとめたりをできるようにつまり何を伝えたいか目的意識をもっていきたいです。
Obsidianの小技その3｜リンクをMarkdown形式に変換してペースト

### はじめに

つねに開きっぱなにしているアプリ、[Obsidian](https://obsidian.md)。使い続けて1年をこえたので、べんりにつかうための小技をご紹介してみようと思い立ちました。

### リンクをMarkdown形式でペースト

ブラウザなどからリンクをふくむテキストをコピー・ペーストすると、Markdown形式に変換してペーストしてくれます。

![dc52bd6a434d53efbc4287dc222ac021.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/540db86f-df85-1222-62c2-3ae7584188ba.gif)

ブラウザからいろいろなものをコピー・ペーストしてみると、わりとMarkdown形式に変換してくれます。`command + A`ですべてを選択して、コピー・ペーストすると、EvernoteのWebクリップみたいに使えます。わたしはやりませんけれども。

勝手にMarkdown形式に変換されてウザい！というときは、`shift + command + v`とすると、プレーンテキストでペーストになります。

### どういうときに便利か

ブラウザのブックマーク機能をつかうと、際限なくブックマークが増えていきます。ですので、ブックマーク機能はうまく使うことがむずかしいです。そこで、Obsidianのノートに、リンクをメモしておくようにすると、文脈を書き添えながらリンクを残しておけるので便利です。

たとえばこんな感じですね：

```markdown
ウィンドウフィルタがうまく使えれば早くできるのかもしれないけど……
ウィンドウフィルタ自体がどうも遅い気がする

[HotSwitch](https://oniatsu.github.io/HotSwitch/)
がよさそう。Montereyでは動かないので下記を。
[oniatsu/HotSwitch-HS](https://github.com/oniatsu/HotSwitch-HS)

すごくよくて、cmd+.のあとにキーを指定してウィンドウを変えられる
```

こういうかんじのノートをつくるときに、ブラウザからのコピー＆ペーストで`[xxx](yyy)`形式で貼り付けてくれると、けっこう助かります。

### おわりに

Obsidianはリンクに強いので、内部ノート、外部URL、PC内のファイル・フォルダなど、いろいろなものをリンクさせると、どんどん便利になります。リンクなので容量を食わないのも（PCを買い換えるときに安く済むのも😆）ありがたいです。

### ご参考

[Obsidian｜使いかたとコツ（目次）](https://qiita.com/hann-solo/items/ac8fa75394813e8adcf4)
enebular-agentを開発者モードで起動するスクリプトを書いた

enebular-agentを開発者モードで起動するスクリプトを書きました。
開発者モードとは、enebular editorでenebular-agentのフローを直接編集できるモードのことです。

[公式ドキュメント](https://docs.enebular.com/ja/EnebularAgent/Developer-Mode.html?q=)にきちんと設定方法が載っているのですが、最近は特にこの設定をするのが面倒になってきました。

そこで、1回スクリプトを呼び出すだけで、開発者モードへ切り替えられるようにしてみました。

以下の環境で動作を確認しました。

- enebular editor v1.2.0（Mac版）
- enebular-agent v2.15.5
- Device: AWS IoT

_スクリプトを実行した状態_

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/c620663e-1e2c-87d9-9a17-b512405cf543.png)


_enebular editorのリモートモードでフローを開いたとき_

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303867/b28dde14-d999-d877-327a-e7f64fb9e92f.png)


このスクリプトは、bashで実行します。

```
#!/bin/bash

CMD=`basename $0`

if [ $# -ne 1 ]; then
  echo "USAGE: bash $CMD pi" 1>&2
  exit 1
fi

PATH=/home/$1/nodejs-v12.22.5/bin:$PATH
export PATH

/home/$1/enebular-runtime-agent/ports/awsiot/bin/enebular-awsiot-agent --dev-mode
```

開発者モードでフローの編集を終えたら、忘れずにノーマルモードへ戻しましょう。
何がわからないかわからないとの付き合い方

# 何がわからないかわからないとの付き合い方

この記事は[雑食系エンジニアサロン Advent Calendar 2021](https://adventar.org/calendars/6582)の20日目の記事です。

こんにちは、ちびっこです！ 
今回は、自分が「何がわからないかわからない」に陥った時に何を意識したか、をかいていければと思います。

## わからないを書き出す

わからない事を付箋のように書き出し、一つづつ解決していく事を目指しましょう。
問題を紐付けていくと、思わぬところで知識が線で繋がることがあります。

例えば、「Railsを使っていて、コードを途中で止めたい！」と思ったとき、前提知識が足りない状況ではそのゴールに到達するのは中々難しいです。

まずは知っていることを書き出します。

![Untitled (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395131/315392c2-878d-ef9c-4dc3-03ac64c31d78.jpeg)

実際に「Rails コード 途中で止めたい」Googleで検索してみます。
debugやbinding.pryという単語が出てきました。

![Untitled (6).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395131/b1cb9e1d-1584-403f-b01c-8daab6f05b63.jpeg)

これらの単語を使って調べてみたら、もしかしたらもう少し何かわかるかもしれません。
「Rails debug binding.pry」で検索してみると、関連してそうな記事が出てきました。

https://qiita.com/AknYk416/items/6f0bec58712edaf4940e

でも、実際にRailsを使っている状態で何をどうすれば良いかわかりませんでした。
**ただ、この記事から新しい単語を見つけました。**

「Rails pry-byebug」

お、どうやらpry-byebugというのはgemらしい、Railsへの適用方法もなんとなくわかりそうです。

https://qiita.com/ryosuketter/items/da3a38d0d41c7e20a2d6

そして、binding.pryという単語はpry-byebugが提供する機能を呼び出すため書くものだ、ということもわかりました。
つまりこんな感じで付箋が繋がった状況になります。

![Untitled (10).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395131/709b930e-957d-c7bf-afec-81e09ed7684c.jpeg)

あくまで例なのでスムーズに記載しましたが、初めて調べる内容であれば上記のステップでゴールに辿り着くまで数日かかります、地道に1つづつ調べていく忍耐強さが大事です。

下記で紹介されている図が直感的にイメージしやすく、「わからない事」同士が結びつき、線の知識として解決するタイミングが訪れます。

https://twitter.com/Stakesh/status/432505262021160961

## 専門性の話

「何がわからないかわからない」状態はゴールたどり着くために必要な基本知識や単語がわからず、調べるきっかけすらも掴めない、というパターンがあります。

ただ、なぜか私生活で上記の問題で困ることはなかなかないとは思いませんか？

これは、すでにゴールまで手順が確立されていたり、それまでの道順を示したものが資料として多く存在するためです。

「何がわからないかわからない」に入り込んでいるのは、何かの「専門性」が求められる領域に入った証拠です。

「英語が学びたいけど何から始めれば良いかわからない」と「Javaが学びたいけど何から始めれば良いかわからない」では、知識に対するユーザー数と、資料の母数が異なるのです。

**つまり、「何がわからないかわからない」で凹んだり悩む必要はないのです！わかるために前進するのみ！**

## 質問の方法

地図の読めない人が、電話であなたに道案内のお願いをしてきたとします。

あなたは、まず状況を把握して目安となるものを探すと思います、いきなり目的地の話はしないでしょう。

![smartphone_map_app_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395131/46b4c674-33ae-202a-a4fc-9295eb762912.png)

これはある専門性のある質問にも適用できます。

道を聞かれている側は、あなたが今どこで迷っているか、距離感も方角もわかりません。

まず、見えている範囲の景色を正確に伝えるだけで、質問されている人がなんとなく汲み取ってくれるでしょう。

先ほどの例で「Railsを使っていて、コードを途中で止めたい！」という話がありました。

これを質問したい場合、そのまま言えばいいのです。

「Railsを使っていて、コードを途中で止めたいです！」

回答者は、「コードを途中で止める」という表現を汲み取って、いきなりdebugという表現で返すのはどうだろうか...gemの話は伝わるかな?と少し考え、いくつか認識合わせの問いかけをしてきます。

(お互い人間なので、ここで上手く噛み合わない場合もありますが、下記のような丁寧に返してくれる回答者であることを願います！)

「コードを途中で止めたい、の例がわかるサイトなどはありますか」「gemの追加方法はわかりますか？」

ここまで進めば、あとは目の前の標識を少しづつ前進すれば良いでしょう。

## 回答者の心構え

自分が同じ状態の時に、何て聞くだろう？をイメージしながら対応し、質問者の方が今見えている景色を引き出す事を最優先に考えることが大事です。

- ゴールまで導ける時間がある
- 質問に対する自分の知識レベルを相手に共有する

回答者が十分に時間を確保できず、途中で手放してしまう状況は避けた方が良いでしょう。

「XXXを調べればわかるよ」では、道の途中で投げ出され、質問者はまたその景色を他の方へ伝えるとこから始まってしまいます。

また、質問の中には回答者も即答できない、自信がないものも存在すると思いますが、それは質問者へ正直に伝えてしまいましょう。

「私も調べながらになりますが、一緒に解決しましょう」

## さいごに

最近、コード設計周りの学習を始めましたが初めの方は「何がわからないかわからない」状態でてんやわんや...

本を読む+色んな勉強会に参加する、という動きを一年ほど続けたところ、どうやら少しは話せるレベルになってきたかもしれない、という2021年でした。

何年経っても「何がわからないかわからない」から抜け出せませんが、これからも諦めずインプットを続けていこうと思います！

最後までお読みいただきありがとうございました、少しでも参考になれば嬉しいです。
バリデーションの設定

# 前回
**1. [Djangoを使ったCRUD機能実装＆Herokuデプロイ](https://qiita.com/K_Kei/items/78b566cea4fe8a14095c)**
**2. [1対多のアソシエーション実装＆確認ダイアログ](https://qiita.com/K_Kei/items/f7929929c2799711fdfa)**

## バリデーションの仕組み
バリデーションは`forms.Form`を使用した場合と`forms.ModelForm`を使用した場合とで設定方法が異なります。

### forms.Formの場合
`forms.Form`では、フォームを定義している`forms.py`の中でバリデーションを設定します。
以前の`forms.py`では以下のように記述をしていました。

[blog_app/forms.py]

```py
from django import forms


class BlogForm(forms.Form):
    title = forms.CharField(label='TITLE', max_length=100)
    content = forms.CharField(label='CONTENT', max_length=300)
```

ここの`max_length`の部分がバリデーションの設定です。
この設定により、`title`のフォームには100文字、`content`のフォームには300文字しか入力ができないよう入力制限がかかります。
バリデーションを追加してみましょう。

[blog_app/forms.py]

```py
from django import forms


class BlogForm(forms.Form):
    title = forms.CharField(label='TITLE', max_length=100, required=False)
    content = forms.CharField(label='CONTENT', max_length=300)
```

この状態で`title`と`content`を未入力のまま登録しようとすると、`content`のみバリデーションがかかります。
`forms.Form`はデフォルトで入力必須のバリデーション（`required=True`）が設定されています。
未入力でも登録を許可する場合は`required=False`を設定します。

### forms.ModelFormの場合
`forms.ModelForm`の場合は`models.py`の中でバリデーションを設定します。
現在の`forms.py`では以下のように記述をしています。

[blog_app/forms.py]

```py
from django import forms
from .models import Blog


class BlogForm(forms.ModelForm):
    class Meta:
        model = Blog
        fields = ['title', 'content']
```

ここの`max_length`の部分がバリデーションの設定です。

#### 空文字のバリデーションを表示させる

半角スペースを入力して登録しようとした場合、現時点ではバリデーションが何も表示されません。
そこで、バリデーションエラーが表示するよう`create`関数を以下のように修正します。

```py
def create(request):
    params = {
        'form': BlogForm(),
    }
    if (request.method == 'POST'):
        obj = Blog()
        form = BlogForm(request.POST, instance=obj)
        params['form'] = form
        if (form.is_valid()):   # ポイント1
            form.save()
            return redirect(to='/blog_app')
    return render(request, 'blog/create.html', params)
```

ポイント1：入力値を使って生成した`BlogForm`オブジェクトに対して`is_valid`メソッドを呼び出すことで、入力値に問題があった場合、エラーメッセージが出力されます。
STM32L010で来年(2022)のカレンダーをシリアルに表示する。5(例題の為の例題)(完成1)


目的
例題の為の例題
こんな簡単のでも「おいてけ掘」?



いろいろ　お約束　
こっちは　学習コストを払っている　だからどうだと言うが　まーいいや
まず、外国は、(教授)的には、英語圏に含まれて勝手にコピーするのは、
法が及ばないので　いいや　海外は、はっきりいってどうでもいい　言葉がわからないから
国内の場合は、法が及ぶ
あえて、実用的なプログラムを書かなくなったのは、コピーされて雑に使われるから
実用的なプログラムを書くとカウンターは、増えるけどマナーの悪いのも増える
マナーの悪いのに勝手に使われると単にむかつくから　マナーのいいのは、OK　まーいいか
アルゴリズム系でもまったりカウンターが上がるからいいや
しばらくは、アルゴリズム系でいきます。　実用系は要望があれば書き込んでください。
ある程度集計を毎日とって開発目標を決めていた　だからどうだ(教授より)

レストランで
メニュー書いてある事には、文句を言うけど
食べたいメニューは、て聞いてもわからないか？


![o_con169.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c23ec28b-0de3-a1dc-523f-0abfcf1bbbb2.jpeg)





```c++



//Ex_calendar_5

#include "mbed.h"

RawSerial pc(PA_2, PA_3); //010

int main()
{

    int hh = 1; //週のカウンター

    //開始位置
    //              1  2  3  4  5  6  7  8  9  10 11 12
    int start1[]= { 6, 2, 2, 5, 0, 3, 5, 1, 4,  6, 2, 4   ,10 ,10 ,10 };

    //月の月数
    //             1   2   3   4   5   6   7   8   9  10  11  12
    int end1[]= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 , 10 ,10 ,10 };

    // ループ 月
    for( int ii = 1 ; ii <= 12 ; ii++  ) {

        //月の出力
        pc.printf( "\r\n%d\r\n",  ii  );
        //pc.printf( "\r\n"  );




        //開始位置
        for( int jj = 1; jj <= start1[ ii-1 ] ; jj++ ) {

            //文字列出力
            pc.printf( "   " );

            
        }//for

        hh = start1[ ii-1 ]+1; //週のカウンター
        
        
        // ループ 日
        for( int kk = 1 ; kk <=  end1[ ii-1 ]  ; kk++  ) {

            //文字列出力
            pc.printf( "%2.0d ",  kk  );

            hh = hh + 1;
            if ( hh >= 8 ) {  pc.printf( "\r\n" ); hh = 1; }


        } //for jj 日

        //文字列出力
        pc.printf( "\r\n" );

    } //for ii 月

    //文字列出力
    //pc.printf( "\r\n" );

    //無限ループ マイコン的停止処理
    while(1) {};

} //main

//容量削減
void error(const char* format, ...) {}




```
unityでFirebaseのIn-App Messagingを表示する方法

こんにちは。[もぐめっと](https://mogmet.com)です。

本日はunityでin app messagingを表示する方法について共有します。

unityでは正式にはin app messagingが対応していません。
なんとか解決できないかとしらべていたら方法を見つけることができました。

方法については下記記事で紹介されている方法で解決できました。

https://www.robinryf.com/blog/2020/01/04/firebase-in-app-message-in-unity.html

## インストール設定

下記記述をしたファイル`Assets/Firebase/Editor/MessagingDependencies.xml`を作成します。

```MessagingDependencies.xml
<dependencies>
  <androidPackages>
    <androidPackage spec="com.google.firebase:firebase-inappmessaging:20.1.1">
      <repositories>
        <repository>https://maven.google.com/</repository>
      </repositories>
    </androidPackage>
    <androidPackage spec="com.google.firebase:firebase-inappmessaging-display:20.1.1">
      <repositories>
        <repository>https://maven.google.com/</repository>
      </repositories>
    </androidPackage>
  </androidPackages>

  <iosPods>
    <iosPod name="Firebase/InAppMessaging" version="8.9.1">
      <sources>
        <source>https://github.com/CocoaPods/Specs</source>
      </sources>
    </iosPod>
  </iosPods>
</dependencies>

```

--------- 2024-10-03 追記 ---------
unity6からはiosPodの書き方は下記の書き方でないとエラーになるようです。

```xml
<iosPod name="FirebaseInAppMessaging" version="11.0.0-beta">
  <sources>
    <source>https://github.com/CocoaPods/Specs</source>
  </sources>
</iosPod>
```

https://github.com/firebase/firebase-unity-sdk/issues/940

@KomoriGameDev さん、情報ありがとうございます！
--------- 追記ここまで ---------

versionに関しては導入しているfirebaseのバージョンと合わせてください。

ちなみにバージョンは下記で参照できます。

https://firebase.google.com/support/release-notes/ios?hl=ja

https://firebase.google.com/support/release-notes/android

以上のファイルを作ってビルドするだけで自動的にインストールできます。

Androidの場合、ビルドしてもライブラリが追加されなければ下記を実施してください。

Assets->Play Services Resolver->Android->Resolve

## テスト

テストする場合は下記の方法で実施することで特定端末にIn-App Messagingを表示することができます。

https://firebase.google.com/docs/in-app-messaging/get-started?hl=ja

テストのやり方でなく、普通に配信したものをテストしたい場合は1日一回しか受信することができないため、アプリを再インストールしないと表示されなかったりします。

## まとめ

In-App Messagingはライブラリ追加するだけで簡単に実装できるのでなぜかunityがちゃんとサポートされてないのは不思議ですが、無理矢理ライブラリをいれることで実現できるので、よかったら試してください。

最後に、[ワンナイト人狼オンライン](https://online.1nite-jinro.com/link/blog)というゲームを作ってます！よかったら遊んでね！

https://online.1nite-jinro.com/link/blog

他にも[Camecon](https://camecon.me/)や[Offcha](https://offcha.com/)といったサービスも作ってるのでよかったら使ってね！

https://camecon.me/

https://offcha.com/

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

https://virapture.com/