OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Translateを使ってGo言語で翻訳するサンプル

タイトルの通りですが、[公式ドキュメント](https://docs.aws.amazon.com/sdk-for-go/api/service/translate/)にサンプルが含まれていなかったので記事にしました。

サンプルソースはGithubにも置いてあります。
https://github.com/yuukimiyo/go-aws-translate-sample

簡単なコードですが、[73言語](https://docs.aws.amazon.com/translate/latest/dg/what-is.html#what-is-languages.html)(2021年1月現在)の双方向翻訳が可能な簡易ツールとして使えます。
Public Domainですので、コピペなどご自由に。

```golang
package main

import (
	"flag"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/translate"
)

func main() {
	sourceText := flag.String("text", "これは翻訳のテストです", "source text")
	sourceLC := flag.String("slc", "ja", "source language code [en|ja|fr]...")
	targetLC := flag.String("tlc", "en", "target language code [en|ja|fr]...")
	flag.Parse()

	sess := session.Must(session.NewSession())
	trs := translate.New(sess)

	result, err := trs.Text(&translate.TextInput{
		SourceLanguageCode: aws.String(*sourceLC),
		TargetLanguageCode: aws.String(*targetLC),
		Text:               aws.String(*sourceText),
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf(*result.TranslatedText)
}
```

上記ドキュメントを読み、Text()関数で翻訳を実施するんだ、という事さえわかれば難しいことは何もないです。

# 手元で試したい人向け

## 前提

AWSアカウントと、次のポリシーをアタッチしたユーザが必要です。

- TranslateFullAccess

無料期間もありますがAWS Translateは有料サービスです、公式サイトの料金表は必ず確認してください。
[AWS Translate](https://aws.amazon.com/jp/translate/)

Go言語の実行環境が必要です。
厳密にどのバージョンからかは把握していませんが、開発／確認には次の環境を利用しています。

Ubuntu20.04(WSL2)
go1.15.7.linux-amd64

## 環境変数の設定

他言語のAWS SDKでも同じですが、次の環境変数をセットしておきます。

- AWS_REGION
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY

### bashの場合

```sh
export AWS_REGION=ap-northeast-1
export AWS_ACCESS_KEY_ID=<access key id>
export AWS_SECRET_ACCESS_KEY=<Secret access key>
```

### fish shellの場合

```sh
set -x AWS_REGION ap-northeast-1
set -x AWS_ACCESS_KEY_ID <access key id>
set -x AWS_SECRET_ACCESS_KEY <Secret access key>
```

## Download

```sh
git clone git@github.com:yuukimiyo/go-aws-translate-example.git
```

## 動かしてみる

デフォルトでは、日本語ー＞英語の翻訳を行います。

```sh
go run main.go --text="翻訳のテストです"

> Testing the translation
```

言語を指定したい場合は次のように言語コードを指定します。
（例えば英語ー＞日本語の場合）

```sh
go run main.go --text="This is test of AWS Translate" --slc="en" --tlc="ja"

> これは AWS 翻訳のテストです
```

利用可能な言語コードの一覧は次のURLにあります。
[Supported Languages and Language Codes](https://docs.aws.amazon.com/translate/latest/dg/what-is.html#what-is-languages.html)
Webサービスにおけるダークモード対応方法

先日、携わらせていただいている[Spotlight](https://spotlight.soy)というサービスのデザインリニューアルをしました。
その際にダークモードに対応したので、それの知見共有です。

## ダークモードの対応方法
CSSでの対応です。
こんな感じで対応したい部分をメディアクエリの中に書き込みます。

```css
@media (prefers-color-scheme: dark) {
  body {
    background-color: #000;
  }
}
```

それだけ！


## ダークモード、ライトモードの切り替え方法
これが苦労しました。
Spotlightでは以下仕様でダークモードに対応しています。

未ログインのユーザー → 端末のデフォルト設定
ログイン済かつサービス内でテーマ設定していないユーザー → 端末のデフォルト設定
ログイン済かつサービス内でテーマ設定しているユーザー → 設定に合わせる

コードにするとこんな感じ。

```javascript
document.documentElement.setAttribute('theme', getTheme());

function getTheme() {
    const userTheme = localStorage.getItem('user');
    if (userTheme) {
        return userTheme;
    }
    const isDark = matchMedia('(prefers-color-scheme: dark)').matches;
    return isDark ? 'dark' : 'light';
}
```
```CSS
@media (prefers-color-scheme: light) {
  :root {
    ...
  } /* 端末設定がライトテーマ */

  :root[theme="dark"] {
    ...
  } /* 端末設定がライトテーマかつサービス設定がダークテーマ */
}

@media (prefers-color-scheme: dark) {
  :root {
    ...
  } /* 端末設定がダークテーマ */

  :root[theme="light"] {
    ...
  } /* 端末設定がダークテーマかつサービス設定がライトテーマ */
}
```

`:root`については[この記事](https://spotlight.soy/detail?article_id=ajxse9ffe)みてくれると意味がわかるかと

サービス内でテーマ設定をするとlocalStorageでデータが保持されます。
localStorageの他にも色々ありますが、今回はユーザーの使用する端末ごとに設定変更ができるよう、localStorageにしています。

HTMLに`<html theme="">`が入って、切り替わる仕組みなのでCSSではコメントアウトのように対応したい部分のCSSを書き込みます。
 
さらに、テーマ設定でテーマを切り替えなきゃいけないのでそれも実装します
SpotlightはToggleボタンをClass名切り替えで実装しているので、ちょっとややこしいため今回はボタンクリックしたら切り替わるようにします

```HTML
<button onclick ="changeTheme(event)"></button>
```
```JavaScript
function changeTheme(ev) {
  const currentTheme = document.documentElement.getAttribute('theme');
  const newTheme = currentTheme == 'dark' ? 'light' : 'dark'
  document.documentElement.setAttribute('theme', newTheme);
  localStorage.setItem('user', newTheme);
}
```

実際どんな感じで動作するかはぜひ[アカウント登録](https://spotlight.soy/register)して確かめてください。

## ダークモードの色について
最近はいろんなサービスでダークモードが採用されてるので、Spotlightはどんな感じでいこうかな〜と他サービスを調査したのでこれからダークモードを採用される方はぜひ参考にしてください。

#### iOS
```
背景: #000000
サブ背景: #1C1C1E
文字: #FFFFFF
サブ文字: #EBEBF5 60%
```

#### Android
```
背景: #121212
サブ背景: #121212 + #FFFFFF 12%
文字: #FFFFFF
サブ文字: #FFFFFF 60%
```

#### Twitter
```
ダークブルー
背景: #15202B
サブ背景: #15212B
文字: #FFFFFF
サブ文字: #8899A6

ブラック
背景: #000000
サブ背景: #15181C
文字: #D9D9D9
サブ文字: #6E767D
```

#### Facebook
```
背景: #18191A
サブ背景: #242526
文字: #E4E6EB
サブ文字: #B0B3B8
```

#### Spotlight
```
背景: #000000
サブ背景: #222222
文字: #FFFFFF
サブ文字: #999999
```

文字と背景色のコントラスト比の数値は、19〜14くらいがチラつかずに見やすい文字になると思います。

---

気になる箇所あれば連絡ください。
GraphQLをフワッと学ぶ

#はじめに
会社でGraphQLのプロジェクトに参加することになり、それまでRailsくらいしか触ったことなかったこともあり、よくわかっていなかったので、Udemyで下記動画を購入して勉強しました。

[【はむ式】フロントエンドエンジニアのためのGraphQL with React 入門](https://www.udemy.com/course/graphql-with-react/)

これで学んだことをフワッと説明したいと思います。
この動画ではフロントエンド側での使い方がメインですが、Railsでのバックエンド側の処理も解説したいと思います。

#GraphQLとは
[GraphQL公式サイト](https://graphql.org/)では「GraphQLはAPI用のクエリ言語およびクエリを実行するためのランタイム」的なことが書いてあります。

要はデータを取得するためのAPIです。
REST APIではURIに応じたデータが返ってきますが、GraphQLも同様にリクエストを送るとリクエストに応じたデータが返ってきます。

ちなみにGraphQLはFacebookが開発しました。
#GraphQLのメリット
### エンドポイントが一つ
REST APIだと、アクセスURIによって結果が変わってきます。例えばQiitaのAPIでタグの一覧（記事の件数降順）を取得するAPIのURIは`https://qiita.com/api/v2/tags?page=1&per_page=20&sort=count`です。
他のデータを取得するAPIは他のURIなので、取得するデータごとに宛先のURIが変わります。

GraphQLではエンドポイントは一つだけです。
例えばGithubのGraphQL APIのエンドポイントは`https://api.github.com/graphql`なので、URIの設計をする必要がありません。要はどんなURIにしたら分かりやすいかとかそういうことを考える必要がありません。

### 必要なデータだけ取得できる
先ほどのQiitaの例で言うと`https://qiita.com/api/v2/tags?page=1&per_page=20&sort=count`にアクセスすると、フォローしてる人の数とかidとか色々取得されますよね。

でももし必要なのがidだけだとしたら他のデータは取得するだけ無駄となってしまいます。
この程度でしたら大した差はないかもしれませんが、膨大なデータの一部だけしかいらない場合、パフォーマンスに影響が出ます。
### 実装がそのまま仕様書になる
REST APIの場合はどのURIでどのようなデータが返ってくるかのドキュメントを作成する必要があります。
そのため[Swagger](https://swagger.io/)などを使い、ドキュメントを作成（[サンプル](https://petstore.swagger.io/#/pet/findPetsByStatus)）するのですが、GraphQLの場合schema主導で開発ができ、[GraphiQL](https://github.com/graphql/graphiql)などを使用するとスキーマを見ながら開発が進められる（下記画像）ので、特にドキュメントの作成は不要になりますし、実装がそのままドキュメントになるので、ドキュメントと実装の齟齬がなくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/05e6bac4-8adf-304d-d2cf-a11d662e4d14.png)

もちろん外部に出すAPIの場合で、追加の説明が必要な場合はそれ用のドキュメントは必要になるかもしれませんが。
#フロントクエリの書き方
これは非常にシンプルでクエリ名と欲しいデータを記述するだけです。
[GraphiQLのデモ](https://lucasconstantino.github.io/graphiql-online/)で試してみます。

まずは国の名前一覧が欲しい場合、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/cdd5357d-ff6a-5853-5a88-1f0da2821e49.png)

やっぱり、首都も欲しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/081fedbd-7e10-0fdb-b098-10505f3acad7.png)
はい、素敵。
こんな感じで好きなものを取れます。
もちろん引数を指定して特定の国だけも取れます。

#サーバー側実装方法（Rails）
動画にはなかったのですが、バックエンド側の実装ももちろん必要なので簡単に解説します。
[graphql-ruby](https://github.com/rmosolgo/graphql-ruby)をインストールします。

設定はドキュメントを見ていただくとして、ここではPostモデル（titleとcontentカラムを持っている）を作成し、idを渡すと当該ポストを返すクエリを実装します。

まずは型を定義します。

```ruby
module Types
  class PostType < Types::BaseObject
    description "A post"
    field :id, ID, null: false
    field :title, String, null: false
    field :content, String, null: false
  end
end
```
これでPostの型ができました。
次にクライアントに返すクエリを作成します。

```ruby
module Queries
  module Post
    class Post < BaseQuery
      description 'post'
      type Types::PostType, null: true # 返り値の型
      argument :id, Int, required: false # 引数

      def resolve(:id)
        ::Post.find(id) # Postモデル
      end
    end
  end
end
```

これでidを引数にクライアント側でクエリを発行すると、`Types::PostType`で定義した型の返り値を取得できます。

なので、クライアントで

```json
query {
 post(id:123) {
   id
   title
 }
}
```
とクエリを発行すればidが123のポストのidとtitleが取得できます。contentも欲しかったらクエリに追加するだけです。簡単。

#まとめ
最初よく分からなかったですが、慣れてしまえば分かりやすいですし、フロントとバックエンドの開発チームが違う場合、ドキュメントを作らなくてもフロント側に何も説明することなくバックエンド側の実装だけに集中できるのでとても良いと思います。
[Tableau] 指標（メジャー）ごとにビューを切り替えたい

#こんなときに
いろいろ入れたら Viz がごちゃごちゃしてきた。すべてが見える必要もないものもあるし、うまく切り替えたい

#用意するもの
データソース : サンプル - スーパーストア (Tableau に入っているサンプルです)

#環境
Tableau Desktop : 2020.3.0

#準備
ここまで作ってみましょう

* 列に売上（合計）、利益（合計）
* 行にサブカテゴリ
* サブカテゴリごとの色もお好みで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/ba853c80-bbf9-4b26-d683-43f8e88831e4.png)

#目指すところ
売上、利益を切り替えて（右）、それをビューに反映させる
こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/5fffde96-d229-851c-df3f-166225585a8e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/6a3bf898-e4a7-a6cd-e271-55a1f29717ff.png)

では、はじめましょう

#Step0
列の売上（合計）、利益（合計）を削除  　※なんで準備で作った？

#Step1 (パラメータ作成)
* パラメータを作成する
* 名前を適当に“指標切り替え”
* データ型を整数
* 値はリストにして 1, 2 に表示名を変えて “売上”, “利益” にそれぞれセット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/ead71ee9-1557-0cf2-ce6c-c275caff2e30.png)

#Step2 (計算フィールド作成)
* 計算フィールドを作成する
* 名前は適当に”選択指標” にして、ここにさきほど作ったパラメータ [指標切り替え] を入れて、これが “1”（つまり”売上” を選択している） なら、[売上] それ以外は [利益] になるような式にする
* こんな感じで IIF を使用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/f203cca7-9493-e3f0-23d5-d028a8aef6e9.png)

#Step3 (ビュー作成)
* 選択指標を列にして合計にする
* パラメータを表示する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/5df46622-2434-66e8-eb08-d75fa24acd91.png)

* タイトルの編集で”挿入” から パラメーター “指標切り替え”を入れる
* これで切り替え時に何が選択されているのか分かりやすくなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/8a69c836-6b3c-8d0f-65b4-b27a9a5643ef.png)

#完成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177920/484acb2d-a544-7e93-c4aa-4db36915ce82.png)

わりといろいろなシチュエーションで使える小技でした
ディープラーニングまとめ（これから学習する人向け）

#はじめに
今回はディープラーニングの基本をまとめました。
※これからディープラーニングを学習する人向けの記事です。

🌟「ディープラーニングの実装及び過学習対策」
https://qiita.com/hara_tatsu/items/b7423e90574cf7730978

🌟「畳み込みニューラルネットワーク（CNN）まとめ」
https://qiita.com/hara_tatsu/items/8dcd0a339ad2f67932e7

🌟畳み込みニューラルネットワーク（CNN）の実装
https://qiita.com/hara_tatsu/items/d2c6536ae35cca5e97ab


#ニューラルネットワークについて

まずはディープラーニングの前身となるニューラルネットワークについて。

ニューラルネットワークとは、簡単にいうと人間の脳の中をマネしたアルゴリズム。
脳の中にはニューロンと呼ばれる神経細胞が何十億個とあり、それらが互いに結びつくことで神経回路という巨大なネットワークのようなものを作り上げている。



![76238686.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/06fb965a-b64c-2d67-6723-4d3751ba77f2.jpeg)


一つの情報が脳内に入ってくると、ニューロンに電気信号で伝わる。この電気信号が脳内の神経回路を駆け巡り、脳内のどの部分にどれだけの電気信号を伝えるかによって、情報を処理している。

この神経回路の仕組みを再現すれば、最高の機械学習ができるのではないか？
と考えて生まれたのがニューラルネットワークです。

##単純パーセプトロン
単純なニューラルネットワークのモデル。

※参考図
![Qiita用-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/01d79cef-1bd4-c292-b289-437e42006480.jpeg)


複数の入力を受け取り、一つの出力を行う。
入力を受け取る部分を入力層、出力する部分を出力層と言う。
入力層と出力層とのつながりは「重み」というもので調整され、どれだけの特徴を出力層に伝えるかを調整している。

※入力層と出力層のみでは回路が単純すぎるため、線形分類しか行うことしかできない。


##多層パーセプトロン

単純パーセプトロンの線形分類しかできないという弱点を解決するために、入力層と出力層の間に更に層を追加するというアプローチをとったものを多層パーセプトロンと言います。

※参考図

![Qiita用-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/f8ac30d7-091a-929a-ed12-0cc739dc1fd3.jpeg)



入力層と出力層の間の層のことを中間層（隠れ層）と言います。層が追加させただけで、単純パーセプトロンと仕組みは変わりません。
しかし、層が追加されたことでネットワーク全体の表現が向上し、非線形分類も行うことができるようになりました。

#ディープラーニング

ディープラーニングとは、多層パーセプトロンの中間層（隠れ層）をより増やしたモデルになります。（一般的に中間層2つ以上）

※層が「深い」から、ディープラーニング（深層学習）と言われている。

##ディープラーニングの学習の流れ

図で表すと以下のとおり
![Qiita用-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/408afe3c-46f5-304c-4f74-bca2868fa3e7.jpeg)



①順伝播
与えられた入力を重みで調整し、予測値を出力する。
（一般的に初期値の重みはランダムで設定される）

②誤差の計算（損失関数）
予測値と教師データである正解値の誤差を計算する。

具体的な計算方法は以下のとおり。
回帰：平均２乗誤差
分類：交差エントロピー誤差

③逆伝播（誤差逆伝播法）
損失関数（誤差）を最小化するために逆向きに学習し、パラメーター（重み等）を更新する。

④　①〜③を繰り返すことでディープラーニングの予測精度を高めていきます。


##誤差逆伝播法（バックプロパゲーション）とは
損失関数（誤差）を最小化するために逆向きに学習し、パラメーター（重み等）を更新する作業。

パラメーターの更新の際に重要なことは大きく2つ！
○パラメーターを増やすか減らすか決める。
（勾配降下法）
○どれくらい増減させるか
（学習率）

※ディープラーニングの実装の際にはオプティマイザー（optimizer）と言われる。
ADam,RMSPropなどが使われる。


#ディープラーニングの特徴まとめ

メリット
・予測精度が圧倒的に高い
・パラメーターの数が多い
・特徴エンジニアリングが不要（学習に影響を与えそうなデータを抽出する作業）

デメリット
・単純な問題の場合は単純なモデル（重回帰分析）の方が性能が良い
・計算コストが非常に高い
・大量の学習データが必要

#おわりに

以上です。
ディープラーニングの基本をまとめました。
Google Chat　で空白行を相手に送る方法

#やり方
下の空欄をコピペして、相手に送ると空白を送れます。また、その後にメッセージを書くとはじめに空白行が入ります。
︎︎

```

```
#(例)

```
おはよう。
︎︎︎
おはよう

```
**この方法では空白行は、上か下かのどちらかでしかできませんでした。（中には必ず使える）**

他に空白を送る方法があったら是非教えてください。
M5Camera にマルチクライアント接続

#　はじめに
M5CAMERA（ESP32 PSRAM OV2640）（商品紹介は例えば[こちら（スイッチサイエンスさん）](https://www.switch-science.com/catalog/5207/)）を買ってみた。wifiでカメラデータを転送できる小型のデバイスだ。SVGA（８００ｘ６００ピクセル）サイズの画像をMJPGでストリーミングできた。しかしながら、デフォルトではマルチクライアント接続できない。今回の業務では目的達成に適さないな・・・と思っていたが、調べてみるとこれをマルチクライアント対応で作動させた人がいて、方法を公開していたので真似してみた。結果、うまくいったので備忘録として記述しておく。

# 事前準備
使用するPC、MacとM5CameraをUSB接続して、ArduinoIDEでプログラミングとプログラムの転送をできるようにしておく。この方法については、先輩方が情報をいろいろ下さるから困らない。

　　M5Stack DOCs
　　https://docs.m5stack.com/#/en/quick_start/m5core/m5stack_core_quick_start

　　MacでM5stackをはじめる
　　https://qiita.com/hmmrjn/items/2b2da09eecffcbdbad85

　　初心者向けM5Stackの始め方（ArduinoIDE編）
　　https://raspberrypi.mongonta.com/howto-start-m5stack-arduinoide/


# マルチクライアント対応スケッチ（転載）
マルチクライアント対応のストリーミングについては、こちらの記事が技術参考。
https://www.hackster.io/anatoli-arkhipenko/multi-client-mjpeg-streaming-from-esp32-47768f

・・・なるほど〜、デュアルコアを活かして、コアの１つをカメラからの画像の処理に集中させ、もう一つのコアはWifiの通信処理に集中させる、という考え方なのね〜。で、こちらの方、スケッチをGithubに公開してらっしゃるのだが、使ってるブツは、M5Cameraではない。そこで、GithubでForkさせてもらったソースをM5Camera向けに編集した。M5CAMERA Bステップ向けの Camera PIN Assign を camera_pins.h に書き込んである。また、2021年1月時点でダウンロードしたOV2640ドライバをオリジナルに上書き済みだ。


　　https://github.com/tomofu74/esp32-mjpeg-multiclient-espcam-drivers

なお、スケッチを取得したらすぐ使えるか、というとそうではなくて、当該カメラを使用するWiFi環境に合わせて内容を編集した、home_wifi_multi.h というファイルをスケッチに追加しなければならない。.inoファイルを開くと50行目付近に書いてあるように、この.hファイルには2行情報を書き込む。

```
/*
  Next one is an include with wifi credentials.
  This is what you need to do:

  1. Create a file called "home_wifi_multi.h" in the same folder OR under a separate subfolder of the "libraries" folder of Arduino IDE. (You are creating a "fake" library really - I called it "MySettings").
  2. Place the following text in the file:
  #define SSID1 "replace with your wifi ssid"
  #define PWD1 "replace your wifi password"
  3. Save.

  Should work then
*/
```

さて、上述の githubにアクセスすると、3つのフォルダがある。参考情報として提示した、オリジナルの作者のページのストーリーを読むとわかることだが、それぞれ反映された機能が異なる。開発段階に応じた内容が収録されているのだ。

　　esp32-cam フォルダ　・・・　シングルクライアントで使えるシンプルなストリーミング

　　esp32-cam-rtos　・・・　マルチクライアント対応。ただし、クライアントを待たずにバッファを更新。

　　esp32-cam-rtos-allframes　・・・　マルチクライアント対応。しかも、FPS設定値を可能な限り守って全フレームをクライアントに送信しようとする。

全フレーム送信型のものは、映像の質は高いといえるが、遅延が大きい。映像の撮影サイズにもよるが、XGAサイズで１５秒程度の遅延がある。リアルタイム性は求めないストリーミング配信で有用だろう。ある程度のリアルタイム性を求めるマルチクライアントなカメラとして使うのであれば、esp32-cam-rtosのフォルダの中のスケッチが使い勝手がよいと思う。


# まとめ
M5Cameraをマルチクライアント対応のカメラ画像ストリーミングサーバーとして使うことができた。


関連情報を公開してくださった諸先輩方に敬意を表す。
tailwind2.0 + react + typescript 環境構築

tailwindとreactの環境作り、特にPostCSSに苦労したのでまとめようと思ったら本家がわかりやすくなってたのでやってみました。
公式の通りなのでぜひ公式もご覧ください。

[Install Tailwind CSS with Create React App](https://tailwindcss.com/docs/guides/create-react-app)

公式ではtypescriptやyarnは使用しません。

## 環境
```bash
$ node -v
v14.15.3

$ yarn -v
1.22.10

$ npx create-react-app --version
3.4.1
```

## Reactアプリ作成
テンプレートをTypescriptで作成します。

```bash
$ yarn create react-app app-name --template typescript
$ cd app-name
$ yarn start
```

## tailwind導入
パッケージを追加します。

```bash
$ yarn add tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
```

Create React Appで作ったままではPostCSSの設定を上書きできないのでCRACOをインストールします。

```bash
$ yarn add @craco/craco
```

package.jsonファイル内のスクリプトをreact-scriptsの代わりにcracoを使用します。ejectはそのままです。

```json
  {
    // ...
    "scripts": {
     "start": "craco start",
     "build": "craco build",
     "test": "craco test",
     "eject": "react-scripts eject"
    },
  }
```

craco.config.jsを作成します。
PostCSSのプラグインとしてtailwindcssとautoprefixerを追加します。

```js
module.exports = {
  style: {
    postcss: {
      plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
      ],
    },
  },
}
```

## tailwindの設定ファイル作成

initを実行するとtailwind.config.jsが作成されます。

```bash
$ npx tailwindcss init
```

buildしたときに未使用のスタイルを含めないようにtailwind.config.jsのpurgeオプションにすべてのコンポーネントへのパスを指定します。

```js
module.exports = {
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  // ...
}
```

## プロジェクトのCSSにtailwindを追加
デフォルトで作成される`./src/index.css`に`@tailwind`ディレクティブを使ってbase, components, utilitiesを含めます。

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## tailwindを使ってみる
簡単にボタンでも作ってみます。
`./src/Button.tsx`を追加します。

```tsx
import React from 'react';

export const Button: React.FC = ({ children }) => {
  return (
    <button className="py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75">
      {children}
    </button>
  );
};
```

`./src/App.tsx`にButtonをimportします。

```tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { Button } from './Button';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        // ...
        <Button>Click!</Button>
      </header>
    </div>
  );
}

export default App;
```

実行します。

```bash
$ yarn start
```

![yarnstart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114149/488635e4-a453-2515-b30c-0520cb39ee4c.png)

とても簡単にtailwindが導入できました。
Power Automate で ドキュメントライブラリの複数ファイルのプロパティを取得する

Power Automate でドキュメントライブラリにあるファイルに一括で処理をしたいなどの場合、ファイルのプロパティを一覧形式で取得したいこともあると思います。
単一ファイルのプロパティを取得するアクションはあるのですが、一覧で取得するアクションが見当たらなかったので、カスタムリストのプロパティを取得するもので代用ができるか試してみました。

# やり方

以下のようなライブラリを用意します。
Field01,Field02 を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/fbeb502b-2c19-b119-a122-438d9d88bff6.png)

次に以下のような Power Automate を用意します。

全体
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/2554d4e5-82db-692c-cc9f-16027b0cafc0.png)

フォルダーの一覧(追加したプロパティ取れない)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/452a861f-196c-2bd4-587b-47981122b925.png)


複数の項目を取得(追加したプロパティ取れる)
リスト名と書いてますが、取得したいライブラリ名を直接入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312282/350fdc7d-a326-e36e-378d-db727f5f13b0.png)

テスト実行してみます。

``` json:フォルダーの一覧の結果(追加したプロパティなし)
[
  {
    "Id": "%252fMyLibA1%252fMyFolderA1_1",
    "Name": "MyFolderA1_1",
    "DisplayName": "MyFolderA1_1",
    "Path": "/MyLibA1/MyFolderA1_1",
    "LastModified": "0001-01-01T00:00:00",
    "Size": 0,
    "IsFolder": true
  },
  {
    "Id": "%252fMyLibA1%252fForms",
    "Name": "Forms",
    "DisplayName": "Forms",
    "Path": "/MyLibA1/Forms",
    "LastModified": "0001-01-01T00:00:00",
    "Size": 0,
    "IsFolder": true
  },
  {
    "Id": "%252fMyLibA1%252fMyExcelA1_2.xlsx",
    "Name": "MyExcelA1_2.xlsx",
    "DisplayName": "MyExcelA1_2.xlsx",
    "Path": "/MyLibA1/MyExcelA1_2.xlsx",
    "LastModified": "2021-01-23T05:19:10Z",
    "Size": 17054,
    "MediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "IsFolder": false,
    "ETag": "\"{8EE0962C-B6A8-4B28-B918-80E016E5CEB0},8\"",
    "FileLocator": "dataset=aHR0cHM6Ly9kZXZuYW4uc2hhcmVwb2ludC5jb20vc2l0ZXMvTXlTaXRlQQ==,id=JTI1MmZNeUxpYkExJTI1MmZNeUV4Y2VsQTFfMi54bHN4"
  }
]
```

``` json:複数の項目の結果(追加したプロパティあり)
{
  "statusCode": 200,
  "headers": {
    略
  },
  "body": {
    "value": [
      {
        "@odata.etag": "\"2\"",
        "ItemInternalId": "3",
        "ID": 3,
        略
        "Field01": "a",
        "Field02": "b",
        略
      },
      {
        "@odata.etag": "\"5\"",
        "ItemInternalId": "4",
        "ID": 4,
        略
        "Field01": "c",
        "Field02": "d",
        略
      }
    ]
  }
}
```

Field01,Field02の値が取れていますので、後続の処理で使うことができます。

# まとめ
画面ではリストだけに制限されているようで、使っていいのかわかりませんが実行は可能です。
Rest API でドキュメントライブラリを指定してプロパティの取得は可能なので、おそらく問題なく使えるのが正常なのかな?
RubyonJetsをGithubActionsで自動デプロイする

## 概要
Ruby on Jetsを用いたアプリケーションをmergeやpushと同時に自動デプロイできるようにします。
GithubActionsが提供するランナーにはAWS CLIやrsync、zipなどが元からインストールされているみたいで、簡単にデプロイすることができました。

手順としては２ステップでできます！
1. AWS CredentialsをGithub Secretsに登録
2. .github/workflows/にymlファイルを記述する

## 環境
Ruby: 2.5.7
Ruby on Jet: 2.3.18

## 手順
### AWSのCredentialsをGithub Secretsに登録
[暗号化されたシークレット](https://docs.github.com/ja/actions/reference/encrypted-secrets)を参考にAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを設定してください。
結構簡単に設定できます。

### GithubActionsの設定ymlを記述
今回の例ではmainブランチにmerge(or push)した際にproductionに自動デプロイできるような設定を記述しました。

```/.github/workflows/deploy_to_production.yml

name: Deploy to production

on:
  push:
    branches: [ main ]

jobs:
  deploy:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        ruby-version: [ '2.5.7' ]

    steps:
    - uses: actions/checkout@v2

    - name: Set up Ruby
      uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
      with:
        ruby-version: ${{ matrix.ruby-version }}
        bundler-cache: false # runs 'bundle install' and caches installed gems automatically

    - name: Bundle install
      run: bundle install --path vendor/gems

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Jets deploy
      env:
        JETS_ENV: production
      run: echo y | bundle exec jets deploy

```

以下の箇所は`jets deploy`時にbundle installが走るpathと揃える目的があります。
こうしないと`jets deploy`時にgemの容量がオーバーしてうまくいきませんでした。

```yml
- name: Bundle install
  run: bundle install --path vendor/gems
```

## まとめ
stagingのデプロイは`/.github/workflows/deploy_to_staging.yml`など作成して、`JETS_ENV: staging`にするだけでOKです！
ちなみにこの記述をしたブランチをmainに反映した時点から自動デプロイが始まるので気をつけてください！

## 参考
[GitHubの新機能「GitHub Actions」で試すCI/CD](https://knowledge.sakura.ad.jp/23478/)
PHP ログイン認証の作成手順①　〜データベースと接続する〜

#使用環境（ローカル環境）
・MAMP
・phpMyAdmin

#データベース定義（使用するカラム）
・id
・name
・email
・password

#手順
##データベースとの接続

```php:env.php
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'user');
define('DB_USER', 'root');
define('DB_PASS', 'root');
?>
```

```php:dbconnect.php
<?php

require_once('env.php');

function connect()
{
    $host = DB_HOST;
    $db = DB_NAME;
    $user = DB_USER;
    $pass = DB_PASS;

    $options = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];

    $dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";

    try{
        $pdo = new PDO($dsn, $user, $pass, $options);
    }catch(PDOException $e){
        echo 'error'. $e->getMessage();
    }
}

?>
```
(UE4)Gitでのプロジェクト管理にGitLFSを使う

*＊この記事では、GitHubDesktopを使用しています。*
___
自作したゲームのプロジェクトをGithubでpushしたら、こんなエラーが起きました。

`error: RPC failed; curl 55 Send failure: Connection was aborted`

「データサイズが大きすぎて送れなかったファイルがある」ということらしいです。
Gitは元々キロバイト単位の使い方が基本の為、画像や動画、ゲームプロジェクト等の大きなデータを扱うのには不向きなもの。


##GitLFS(GitLargeFileStorage)とは
GitHubで、大サイズのデータでも扱える様にしてくれる拡張機能。
ファイルのメタ情報だけをgitで保存し、ファイルの実態はリモートサーバーで管理する仕組みです。
##導入方法
Lfsを使用する為には、各リポジトリに対してインストールを行う必要があります。
_
1.[ダウンロードページ](https://git-lfs.github.com/)からインストーラーを入手する。
![スクリーンショット 2021-01-22 14.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/12a187fc-b46d-f283-cb2a-848320be3ec5.png)
2.落とせた後、GitHubDesktopからlfsを使用したいリポジトリでコマンドプロンプトを開く。
![スクリーンショット 2021-01-22 15.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/bc3c7f6a-02dc-4502-8510-2ebd4a68833d.png)
3.コマンドラインに

`$ git lfs instal`

と入力。
リポジトリのあるディレクトリに**.gitattributes**が作成される。

これで準備は完了です。
LFSを使って、ファイルの保存が行える様になりました。
##使用方法
先ほど作成された.gitattributesを開いてみると、
![スクリーンショット 2021-01-22 19.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/ae67962c-101c-4875-fff8-e129b78c5562.png)
何も入力していないので、まだ中身は空っぽ。
この中に、次の方法でファイルを追加していきます。
___
コマンドプリンプトで、

`git lfs track ”*拡張子”`

を入力することで、
特定の拡張子データがトラックされる。
 
例えばpsdをトラックするなら、

`git lfs track "*.psd"
Tracking”*.psd”`

こうなれば成功。
.gitattributesを見てみると、
![スクリーンショット 2021-01-23 17.54.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/e677142b-6b47-7b5c-b8b2-3f95a6f72c62.png)
psdが追加されました。

こんな調子で、データサイズの大きいモノを追加していきます。
UE4のプロジェクトだと、主に以下。

.uasset
.umap
.uproject
.wav
.fbx（[引用](https://forums.unrealengine.com/development-discussion/engine-source-github/1669010-official-git-lfs-tracking-list-for-ue4)）

追加できたら、変更が反映されているかGitHubDesktopで確認。
![スクリーンショット 2021-01-23 18.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939279/fbe50df2-7dc7-4c03-6aac-7cfb4799b91f.png)
しっかり認識できてるみたいなので、comitしたらpushして完了です。
##メモ
そもそも今回LFSを使うことになったのは、プロジェクトのリポジトリをゲーム作成してから完成まで一回もコミットしてなかった為、最終的なデータサイズが大きくなりすぎた事が原因でした。
そもそもGitとしての使い方をしてなかったのが問題なので、もっと使う機会増やして覚えます…
LaradockでLaravel8の開発環境を構築する

<h2>前提</h2>
- `Mac` を使っている
- `Git` インストール済
- `Docker` インストール済


<h2>できること</h2>
- `Laravel8`の開発環境が構築できる
- `phpMyAdmin`でDBを参照できる


<h2>手順</h2>
1. `Laradock`をローカル環境に複製し、環境設定ファイルを編集する
2. `Docker`コンテナを起動し、コンテナに入る
3. `Laravel８`をローカル環境にインストールし、環境設定ファイルを編集する
4. `Laradock`の環境設定ファイルを編集し、`Docker`コンテナ再起動
5. `Laravel8`と`phpMyAdmin`の表示を確認する

※コンテナは`nginx`と`PHP-FPM`、`Mysql`そして`phpMyAdmin`を用意します

<h2>構築する</h2>

#####1. `Laradock`をローカル環境に複製し、環境設定ファイルを編集する
Laradockを複製（複製場所は"/Users/任意の名前"）

```
git clone https://github.com/LaraDock/laradock.git
```

環境設定ファイル（.env）を編集

```
cp env-example .env
vim .env
```
編集箇所と内容

>DATA_PATH_HOST=.laradock/data
COMPOSE_PROJECT_NAME=project_name
MYSQL_VERSION=5.7.31

ファイル末尾に追記
>DB_HOST=mysql

#####2. `Docker`コンテナを起動し、コンテナに入る
Dockerコンテナを起動

```
docker-compose up -d nginx mysql phpmyadmin
docker-compose ps
```

Dockerコンテナに入る

```
docker exec -it river_web_workspace_1 bash
```

#####3. `Laravel８`をローカル環境にインストールし、環境設定ファイルを編集する

Laravel８をローカル環境にインストール（ディレクトリ名はsrc）

```
composer create-project laravel/laravel src
```

環境設定ファイル（.env）を編集

```
vim .env
```
編集箇所と内容
>DB_HOST=mysql
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret

#####4. `Laradock`の環境設定ファイルを編集し、`Docker`コンテナ再起動

```
exit
vim .env
```
編集箇所と内容
>APP_CODE_PATH_HOST=../src

```
docker-compose up -d nginx
```

#####5. `Laravel8`と`phpMyAdmin`の表示を確認する
http://localhost/
http://localhost:8081/

>データベース名：mysql
ユーザー：default
パスワード：secret

※DB編集する際は、先ずはルートではいり、上記ユーザーに編集権限を付与します
>データベース名：mysql
ユーザー：root
パスワード：root

以上になります。:laughing:
Laravelでポートフォリオ　店舗管理システム作ってみた

## 初めに
バックエンドをLaravel,フロントエンドをVue.jsを用いて実装しています。
この記事ではアプリ開発の説明や工夫した点を記載したいと思います。

## アプリの概要
 実際に飲食店舗の従業員は活用することをイメージしながら作成した店舗管理システムです。

・店長の事務業務負荷
・実際に生じている店舗の問題点

を解決できるようにすることをコンセプトとして作成しました。
「Cafe de Drip」という喫茶店で活用されることを想定しています。

アプリURL：https://cafe-de-drip.herokuapp.com/
※ユーザー認証必要
ログインしてみたいと思って頂けましたらお問い合わせください。

GitHub:https://github.com/Tanaka-Kizuki/Store-management-system

↓ユーザー認証後のホーム画面
![Cafe de Drip ホーム画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639204/9d4236c6-804e-2c35-9106-c750258cc834.png)

## 実際に店舗で起きている問題点
◉勤怠管理システム(打刻式)がなくタイムカードもしくはシステム上に手打ち
　→店長がシステム上に勤怠入力もしくは実績と入力に相違がないか確認・承認作業

◉ノートを使った共有事項の伝達
　→ノートを手書きで書く作業負荷
　→全員が読んだか確認ができない

◉日々の発注業務
　→発注が出来る能力者が限られており、休みの日でも出勤もしくは遠隔発注

## 上記問題点解決策(具体的なアプリ実装・機能)
◉勤怠管理システムの導入
![スクリーンショット 2021-01-23 18.03.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639204/c7119105-e278-700f-3497-06ce900388ae.png)

◉掲示板形式の連絡ノート
![スクリーンショット 2021-01-23 18.36.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639204/5da8a23e-8ae4-6606-0f57-418017b0f344.png)

◉各投稿にいいね機能を実装

◉店舗在庫を入力することで必要数が発注される発注システム
![スクリーンショット 2021-01-23 18.38.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639204/9a84b97b-d09a-89f3-dd45-c3aa8bec7570.png)

## 機能一覧
◉ユーザー管理登録
　○管理者権限
　○新規登録(管理者のみ有効)
　○ログイン、ログアウト機能
◉勤怠管理システム
　○出退勤
　○休憩開始、終了
　○出退勤時刻、休憩時間より勤務時間の算出(15分繰り上げ)
　○ユーザーの勤怠実積照合(ログイン従業員の指定月の勤務実積表示)
　○日次勤怠照合(指定日に勤務していた従業員、勤務時間等表示)
◉コミュニケーションノート
　○新規作成
　○編集
　○削除
　○いいね機能
　　https://qiita.com/tanaka2020/items/8ec8ae0fdd3ad4409c74
　　https://qiita.com/tanaka2020/items/2f87594be2fb53b23958
　　↑実装方法は別記事でまとめています。
◉発注システム
　○アイテムの追加、編集
　○発注(データベース登録)
　○発注履歴の表示

## 使用技術
◉フロントエンド
　○HTML/CSS
　○JavaScript
　○Vue.js 4.3.1
◉バックエンド
　○PHP 7.4.9
　○Laravel　7.27.0
◉インフラ
　○mysql 8.0.21
　○heroku

## 工夫した点、苦労した点
◉ユーザー管理
　・新規ユーザー登録は管理者権限として実装
◉勤怠管理システム
　・1日に1回しか出勤出来ないように実装
　・休憩開始後、休憩終了前に退勤が出来ないように実装
◉連絡ノート
　・いいね機能はVue.jsでComponent化
　・いいねをAxiosで非同期処理
◉発注機能
　・1日に１回のみ発注可能
　・各食材の適正数量を随時変更出来るように実装することで在庫数を入力することで必要数を自動発注

## 最後に
　現場に立っている中で不便であり改善できれば良いなと普段思っていることを解決出来るように実装しました。現場の負担がすくなりお客様と向き合える時間が少しでも多くなればと思います。
PowerShell モジュールでDynamicParameterを使うときの落とし穴

# はじめに

主に`dynamicParam`キーワードを用いて、関数の引数にとる値（文字列）の種類を動的に制御することができる仕組みを、[こちらのサイト](https://stuncloud.wordpress.com/2014/12/27/powershell_dynamicparam/)でご紹介されております。

今回は、この仕組みを次の例のように`Invoke-Expression`コマンドレットと絡めてモジュールから利用しようとしたときに陥った落とし穴について述べていきます。


```PowerShell:Module/Module.psm1
function B {
    [CmdletBinding()]
    param ($array)
    dynamicParam {
        $dp = New-DynamicParameter 'Fuga' -Mandatory -Position 0 | Add-ValidateSet $array
        return New-DynamicParameterCollection $dp
    }
    process {
        $Fuga = $PSBoundParameters.Fuga
        return $Fuga
    }
}

function Piyo($command) {
    Invoke-Expression ($command -f "piyo")
}
```

# スコープの誤設定？

早速ですが、次のコードをグローバルスコープで実行すると、エラーとなります。

```PowerShell:失敗例
Import-Module "$PSScriptRoot\Module" -Force

function A($a) {
    Piyo 'B $a {0}'
}

A ("hoge", "huga", "piyo")
```

```
Add-ValidateSet: ...\Module1.psm1:5:84
Line |
   5 |  … namicParameter 'Fuga' -Mandatory -Position 0 | Add-ValidateSet $array
     |                                                                   ~~~~~~
     | Cannot bind argument to parameter 'ValidateSet' because it is null.     

New-DynamicParameterCollection: ...\Module1.psm1:6:47 
Line |
   6 |          return New-DynamicParameterCollection $dp
     |                                                ~~~
     | Cannot bind argument to parameter 'DynamicParameter' because it is null.

B: A positional parameter cannot be found that accepts argument 'piyo'.
```

これは、`function B`の`$array`引数に値[^array]が渡されておらずnullとなっていることを意味しています。
なんでこうなるのか・・・試行錯誤した結果、どうやらスコープの設定に原因があることに辿り着きました。

`function A`の`$a`引数に`script`又は`global`修飾子を添えれば、解決します。

```PowerShell:成功例
Import-Module "$PSScriptRoot\Module" -Force

function A($script:a) {
    Piyo 'B $a {0}'
}

A ("hoge", "huga", "piyo") # 出力：piyo
```

なお、`function Piyo`が同一スコープにあるときや次のコードのように一体化しているときは、このエラーは発生しません。

```PowerShell:
function A($a) {
    Invoke-Expression ('B $a {0}' -f "piyo")
}
```

`Invoke-Expression`コマンドレットが別スコープに存在するときに発生するエラーということなのでしょうか・・・？

# まとめ

今回はDynamicParameterを使ったときを題材にご紹介しましたが、もしかしたらIValidateSetValuesGeneratorインターフェースを利用したパラメータの定義でも同様の落とし穴が存在するかもしれません[^原因]。
とにかくダイナミックスコープというものが、ほぼJavaしかやったことのない人間にとってこんな苦しい概念だとは思いませんでした・・・orz

[^array]: この例で言えば、`function A`の`$a`引数にとる値`"hoge", "huga", "piyo"`です。
[^原因]: というのは、実は先にIValidateSetValuesGeneratorインターフェースを利用したパラメータの定義を行っていた時にこれと同じような現象に陥ったことがあり、思い切ってDynamicParameterを使ったやり方に切り替えたらこの現象に陥ってしまったためです。おそらく原因は同じことだと思いますが、今更改めて検証する気は特にありません。
Node.js: Let's Encrypt の証明書を使ったブローカーに接続

こちらで作成したブローカーに接続する方法です。
[Mosquitto で Let's Encrypt の証明書を使う](https://qiita.com/ekzemplaro/items/d2afb5d421c7d4d457c2)

```text:.env
HOST=abc.example.com
TOPIC=sensors/topic_1
```

```js:publish_ca.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	publish_ca.js
//
//					Jan/23/2021
//
// ---------------------------------------------------------------
'use strict'
const mqtt = require('mqtt')
const fs = require('fs')
const dotenv = require('dotenv')
// ---------------------------------------------------------------
console.error ("*** 開始 ***")
dotenv.config()
const host = `${process.env.HOST}`
const topic = `${process.env.TOPIC}`

const caFile = fs.readFileSync("/etc/ssl/certs/ca-certificates.crt")
const options = {
	rejectUnauthorized : false,
	ca:caFile 
}

const client  = mqtt.connect('mqtts://' + host + ':8883',options)

client.on('connect', function () {
	const today = new Date ()
	var ddx = (1900 + today.getYear ()) + "-" + (today.getMonth () +1)
	ddx += "-" + today.getDate () + " " + today.getHours()
	ddx += ":" + today.getMinutes () + ":" + today.getSeconds()
	client.publish(topic, ddx)
	console.log(ddx)
	client.publish(topic, 'Good Afternoon mqtts')
	client.publish(topic, 'こんにちは')
	client.end()
	console.error ("*** 終了 ***")
})

// ---------------------------------------------------------------
```

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
./publish_ca.js
```

```js:subscribe_ca.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	subscribe.js
//
//						Jan/23/2021
//
// ---------------------------------------------------------------
'use strict'
const mqtt = require('mqtt')
const fs = require('fs')
const dotenv = require('dotenv')

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
dotenv.config()
const host = `${process.env.HOST}`
const topic = `${process.env.TOPIC}`

const caFile = fs.readFileSync("/etc/ssl/certs/ca-certificates.crt")
const options = {
	rejectUnauthorized : false,
	ca:caFile
}

const client  = mqtt.connect('mqtts://www2.ekzemplaro.org:8883',options)

client.on('connect', function () {
    client.subscribe(topic)
})

client.on('message', function (topic, message) {
  // message is Buffer
    console.log(message.toString())
})

// ---------------------------------------------------------------
```

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
./subscribe_ca.js
```
Arduino から MQTT サーバーにメッセージを投げる

Arduino から MQTT サーバーにメッセージを投げます。

使用機材

|項目|設定値|
|---|---|
|使用している Arduino |arduino nano|
|書き込みブートローダ |atmega328old|
|LAN シールド|[ENC28J60](https://www.diymore.cc/products/enc28j60-ethernet-network-module-shield-v2-0-for-arduino)|

IPアドレス

|端末|IPアドレス|
|---|---|
|ルーター|192.168.0.1|
|Arduino|192.168.0.117|
|MQTT Server|192.168.0.104|

MQTT設定

|MQTT|設定値|
|---|---|
|server|192.168.0.104|
|ポート|1883|
|ルーム|test|
|クライアントID|myArduinoID|
|メッセージ|Hello World from arduino|

ソースコード

````c:mqtt_pub.ino
#include <SPI.h>
#include <UIPEthernet.h>
#include <PubSubClient.h>

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

// Function prototypes
void subscribeReceive(char* topic, byte* payload, unsigned int length);
 
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x78, 0xEE  };  
IPAddress ip(192, 168, 0, 117);
IPAddress myDns(192, 168, 0, 1);
 
// Make sure to leave out the http and slashes!
const char* server = "192.168.0.104";

void setup()
{

  // Useful for debugging purposes
  Serial.begin(9600);
  
  // Start the ethernet connection
  Ethernet.begin(mac, ip ,myDns);              
  
  // Ethernet takes some time to boot!
  delay(3000);                          
 
  // Set the MQTT server to the server stated above ^
  mqttClient.setServer(server, 1883);   
 
  if (mqttClient.connect("myArduinoID")) {
  
    Serial.println("Connection has been established, well done");
 
    // Establish the subscribe event
    mqttClient.setCallback(subscribeReceive);
  
  } else {

    Serial.println("Looks like the server connection failed...");

  }

}

void loop(){

  mqttClient.loop();
 
  mqttClient.subscribe("test");
 
  if(mqttClient.publish("test", "Hello World from arduino")){

    Serial.println("Publish message success");
  
  }else{
  
    Serial.println("Could not send message :(");

  }
 
  // Dont overload the server!
  delay(4000);

}

void subscribeReceive(char* topic, byte* payload, unsigned int length){

  Serial.print("Topic: ");
  Serial.println(topic);
 
  Serial.print("Message: ");
  for(int i = 0; i < length; i ++){
    Serial.print(char(payload[i]));
  }
  Serial.println("");

}
````

###参考リンク

- [ubuntuでMQTTブローカー「mosquitto」のインストール方法 - Qiita ](https://qiita.com/rui0930/items/40bd5a1cfd3422206ad3)
- [GitHub - 256dpi/arduino-mqtt: MQTT library for Arduino ](https://github.com/256dpi/arduino-mqtt)
- [How To Use Basic MQTT on Arduino ](https://www.digikey.com/en/maker/blogs/2018/how-to-use-basic-mqtt-on-arduino)
Entrian Source Searchを用いたUnreal Engineのソース検索を楽にするTips


#Entrian Source Search
以前、こちらの記事で膨大なUEのソースコード内部の検索には"Entrian Source Search"が安価で便利だとオススメさせていただきました。
[Entrian Source SearchでUE4内部のソースコード検索を安価で容易に！](https://qiita.com/EGJ-Nori_Shinoyama/items/9385cf73b9a75966d803)

Entrian Source Searchは簡単で安価で高速でと非常に便利なのですが、このツールでUEのソースコードを検索する際に良く起こる問題と自分が行っている解消方法についてご紹介できればと思います。

#Entrian Source SearchのUEソース検索で良く起こること
###1. .cpp.txtや.gen.cppなどUE4が自動生成する中間ファイルを参照してしまう
UE4はソースコードのビルドのためにIntermediateフォルダを生成しそこに中間ファイルを保存します。こちらのファイルを実際にユーザが見たりいじる必要はないのですが、このフォルダがEntrian Source Searchの検索対象に入っていると、検索結果の中にIntermediate内のファイルが大量に含まれてしまい検索性を下げてしまうことがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/c6acd398-539e-6412-cf39-077d5462964f.png)

###2. ThirdPartyのソースコードの検索結果が大量に参照されてしまう
また、UE4は沢山の外部ライブラリを用いてます。それらのソースなどもThirdPartyディレクトリ内に置いてある場合があります。UE内部のソースコードを検索するつもりでも、このThirdParty内のソースの結果が大量に出てしまい、こちらも検索性を下げる要因になることがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/7fb5cc8b-ffba-3930-c2e7-be0c0ecc62b7.png)

これらの解消方法についてすごく簡単なのですが2点ほどご紹介いたします。

#IntermediateやThirdPartyを省く２つの方法
###1. IntermediateやThirdPartyを常に検索対象から外す
自分はこの方法をIntermediateフォルダに対して採用しています。Entrian Source Searchのオプションを開くと、Exclusion patternsという項目があります。こちらの最後にintermediateやthirdpartyを指定することで、どんなプロジェクトでもこのフォルダが入ってるディレクトからその下は検索対象から外してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/218337b2-3294-f6ea-ae9a-48bfcfc00848.png)

###2. IntermediateやThirdPartyを都度指定して検索対象から外す
こちらは自分がthirdpartyを消したり検索対象を絞る際に使っています。 Entrianでは、検索窓で dir:~~ と指定することで特定のディレクトリ名以下を検索対象にし、逆に -dir:~~ と指定することでそのディレクトリ以下を検索対象から外します。この機能を用いて　”-dir:thirdparty" を検索時に追加することで、ThirdParty以下のディレクトリを検索対象から外しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363464/3a1a9b58-3ecb-a6af-2cd8-a424f55045da.png)
これと同様で、 ext:~~ や -ext:~~ などで、拡張子の指定もできます。こちらもシェーダコード内部などを検索するのに便利かと思うのでおすすめです。


簡単にですが、ご参考になれば幸いです。
ブラウザで .tte の外字フォントを表示確認する

## 概要

.tteの外字フォントを、ブラウザで確認したい時にやった手順をメモしておく。

## 手順

### 1. woff にコンバートする

ブラウザで確認するため、Webフォントの形式に変換する必要がある。
今回は[WOFFコンバータ](https://opentype.jp/woffconv.htm)を利用した。

### 2. 文字コードを確認する

外字に割り当てられている文字コードを確認する必要がある。
今回は[FontForge](https://fontforge.org/en-US/)を利用した。

フォントを開いたら、割り当てを見て、外字が登録されている範囲を調べてメモしておく。

### 3. 特殊文字を生成するスクリプトを作成

FontForgeで割り当てを見て、仮に外字が5,000〜6,000番目まで登録されていた場合、次のように特殊文字形式で一括出力する。

```ruby
irb(main):007:0> numbers = 5000..6000
=> 5000..6000

irb(main):016:0> numbers.each { |n| print "&##{n};" }
&#5000;&#5001;&#5002;&#5003;&#5004;…（省略）
=> 5000..6000
```

### 4. HTMLに埋め込む

外字フォントを読み込ませた上で、先ほど生成した特殊文字をコピペで貼り付ける。ブラウザで確認して、外字が無事表示されていればOK。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <style>
  @font-face {
    font-family: "sample-font";
    src: url("EUDC.eot?") format('eot'),
         url("EUDC.woff") format('woff');
  }
  .container {
    font-family: "sample-font";
  }
  </style>
</head>
<body>
  <div class="container">
    <p>&#5000;&#5001;&#5002;&#5003;&#5004;…（省略）</p>
  </div>
</body>
</html>

```
Accessのレポートで印刷時拡張設定すると思わぬレイアウト崩れ起きるかもしれないから注意ね

#印刷時拡張ってなんぞ？

枠を超える量の文字が入ったらテキストボックスが自動で下にのび～る機能。
**プロパティ** の **書式** タブのとこで設定できるん。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/d8f0f81e-e82b-3c9e-f16c-e91a574cd9de.png)

#例えばこんな使い方するとレイアウト崩れる

『text_box_expand』には印刷時拡張設定してあるます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1a002b0f-ce2b-4a08-98e0-b67b35b55cc8.png)
枠を超えない程度の文字数なら問題ナッシング。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b3920637-a952-483b-ea0c-7f35386e5d37.png)
ちょっと文字数多くなって印刷時拡張されると、右にある日付のテキストボックスが下がってイラストにかぶっちゃう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2920adcd-90b6-62f0-4944-2e932610b2c5.png)

#印刷時拡張に引っかかって位置が変わっちゃう条件
『text_box_date』の **上辺** は『text_box_expand』の **下辺よりも低い位置** にあります。
こういう子が印刷時拡張に **引っかかって位置が下がります** 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6c954387-4fc5-10c3-7e4b-8aef808062eb.png)

#テキストボックスはできる限り高さを確保しておいた方が無難です

こんなふうにある程度高さを取っておけば、印刷時拡張の副作用を受けるオブジェクトを減らせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/8ce6c31a-a60a-ad94-459e-57fa7afe6aed.png)
印刷時拡張が起きても『text_box_date』の位置はそのまま。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9839979c-0fce-e3ed-bc9c-a124ca67b148.png)

#蛇足

テストの時は『ものごっつ長い文字列にしてみる』みたくちょっとイジワルなデータにすると、こういうバグを発見しやすいです。

#バージョン

Windows10 Pro バージョン20H2 OSビルド19042.746
Access for Microsoft 365 MSO（16.0.13530.20054）32ビット
【docker build】unknown instructionでエラー

# Note
`unknown instruction: APT-GET'`のエラーが出る。
Dockerfile内におけるRUNディレクティブで、改行のバックスラッシュが抜けている可能性あり。

## NG
```dockerfile
FROM ubuntu:18.04
RUN apt-get update -qq && ←
    apt-get install -y yarn curl gnupg2 npm nodejs
```

## OK
```dockerfile
FROM ubuntu:18.04
RUN apt-get update -qq && \ ←
    apt-get install -y yarn curl gnupg2 npm nodejs
```

## 参考文献
- [Docker build で Error response from daemon: Dockerfile parse error line x: unknown instruction: &&](https://blog.keinos.com/20190527_4557)
[Firebase]Cloud Functions for Firebase で runtime を Node.js 12 にしてデプロイする方法

# はじめに
Cloud Functions for Firebase でデプロイの際にnodeのバージョン周りでエラーが出てハマったのでまとめました。
簡潔に設定の仕方を紹介した後、ハマりどころを末尾に記載しておきます。

# runtime を Node.js 12 にしてデプロイする方法
やり方は全部で２つあります。

## 1. package.jsonに記述する方法
以下のようにenginesに"node":"12"と記載する

```json
{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
   
  },
  "engines": {
    "node":"12"
  },
  "dependencies": {
    
  },
  "devDependencies": {
    
  },
  "private": true
}
```

## 2. firebase.jsonに記述する方法
firebase functions をinitするとinitしたカレントディレクトリに firebase.jsonが作成されると思います。そこに以下のような記述を足すことでランタイムを指定できます！

```json
{
  "functions": {
    "runtime": "nodejs12",
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  }
}
```
v8.6.0で変更があったみたいです。 or　と書いてあるように、package.jsonでやるやり方も使えます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/73d286cc-732f-152f-9a88-52ae9d8adeb8.png)

[公式リリースノート](https://github.com/firebase/firebase-tools/releases?after=v8.9.1)

## ランタイム指定がうまくいった時のdeployのログ
以下のように、 `creating Node.js 12 ~~~`  と出ていれば指定できています！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/1baea020-27b0-dbab-8bf1-8737bdff8dd0.png)

#大前提・要注意

### 1. FirebaseのプランをBlazeプラン(従量課金プラン)にすること
### 2. グローバルインストールされている firebase-toolsが最新のものであること！
これが古いままだと以下のようなエラーが出ます

```
Error: package.json in functions directory has an engines field which is unsupported. The only valid choices are: {"node": "8"} and {"node": "10"}.
```
### 3. 使用しているライブラリが必要とするnodeのバージョン要件をローカル環境が満たしていること!

deployなのでてっきりpackage.jsonに正しくランタイム指定されていればクラウド上で問題なくビルドしてくれると思ってましたが、どうやら自分が想像していたのとはビルドの仕組みが違うみたいで..(勉強します。)

自分は使用しているライブラリがnode v１２以上を要求していたにも関わらず、ローカルのnodeのバージョンがv10系だったため、延々と以下のエラーが出てしまいました。

```
Error: There was an unknown problem while trying to parse function triggers. Please ensure you are using Node.js v6 or greater.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/467f0cba-2f94-7f10-2cd9-d1f13e6539a5.png)

自分はnodebrewを使っていたので以下で解決しました。バージョンはご自身のライブラリの要件に合わせてしよしなに変えてください。

```shell
nodebrew use 12.20.1
```

新しく作った環境にfirebase-toolsがない場合は以下も実行

```shell
npm i -g firebase-tools
```

# 参考
[公式リリースノート](https://github.com/firebase/firebase-tools/releases?after=v8.9.1)
[Cloud Functions for FirebaseでNode.js 12を利用する方法](https://qiita.com/y-temp4/items/98d75ccfc3383b4ff40f)
Node.jsがとっつきにくいと思ったら ～非同期処理とは？～【初心者向け】

##背景
JavaやらPythonやらの言語でエンジニア人生を送っていると、Node.jsでバックエンド処理を作っていると「何か違う～！！」と感じたのでこの記事を書いていく:runner_tone5::thought_balloon:
なお、node.jsはjavascriptをサーバーサイドでも動かせるようにした実行環境や処理系のことを指す。

##Node.jsってどんな言語？
Node.jsは他の言語と比べて決定的に異なる点がある。「ノンブロッキングI/O」という処理方式を採用している点だ。ブロッキングとは、Node.jsのプログラムを実行する際に、ファイル呼び出しやネットワークリクエストなどNode.js以外の操作が完了するまで待たなければならない状態だ。ブロッキングが発生すると、プログラムの次の処理に進むことができない。Node.jsでは、このブロッキングを避けるため「ノンブロッキングI/O」という非同期処理を採用している。ファイル呼び出しやネットワークリクエストの処理の結果を待たずに次のプログラムコードが実行される。

```
const fs = require('fs'); // ファイル読込ライブラリ

// ファイル内容をコンソールに出力するコールバック関数
const fileoutput = (err, txt) => {
  console.log(txt); 
};

console.log('前');
fs.readFile('./readme.txt', 'utf8', fileoutput);
console.log('後');
```

上記のプログラムを実行すると、前、後、ファイルの中身という順番でコンソールに出力される。ファイル読込の処理結果を待たず、次のプログラムコードが実行されていることが分かるだろう。

##なぜ非同期？
非同期的にプログラムを実行して、ブロッキングをなぜ避けなければいけないのかというと、Node.jsはシングルスレッドで動く処理だからだ。スレッドとは、プログラムを実行する実行単位のことだ。例えばWebサーバーにリクエストがきて、プログラムを実行する際に並列で実行できないとすると、シングルスレッドのためプログラムを実行する場所が他になく、大幅に処理が滞ってしまう。そのため、非同期で次の処理を実行できるようにしているのだ。そのため、メモリを効率的に利用できたり、プロセスのデッドロックが起こりにくいというメリットがある。

##まとめ
Node.jsのほとんどの関数はこのように非同期で実施されるため、実行される順番には留意してコードを書こう:raised_hand:
macでpythonの仮想環境作成

# macでpythonの仮想環境を構築する

## 前提
・macOSでpythonの仮想環境を構築する
・今までanacondaで仮想環境を作っていたが、ふとターミナルで仮想環境を作るには？と思い調べた

## 手順
### 1.仮想環境の作成
1-1.仮想環境を作りたいディレクトリまで移動
お馴染みの`cd`で
1-2.ターミナルに以下のコードを入力

`python3 -m venv 環境名(例：.venv)`

### 2.仮想環境の起動
`. .venv/bin/activate`

### 3.終了

`deactivate`

##最後に
今までpythonの実行をanacondaのspyderというIDEを使っていたため、急にターミナルやVScodeで実行するのに少し抵抗があったが、少しずつ慣れていきたい
[自分用メモ]Reactのstateとpropsの関係

自分用のメモです。
本記事ではReactの概念について解説しています。

#Reactとは

Reactとはフレームワークではなく、あくまでもUIの作成に特化したJavascriptのライブラリです。

ライブラリは部品で、フレームワークは既に決められたテンプレートと例えることができます。
プログラマはライブラリの機能を呼び出すタイミングと場所を指定できますが、フレームワークはフローの中で、プログラマが介入できる場所がいくつか用意され、フレームワークは必要に応じてそれらを呼び出します。

>ライブラリとフレームワークの違いについてはこちらの記事をどうぞ
[「ライブラリ」と「フレームワーク」は何が違うのか](https://qiita.com/baby-degu/items/7dc4548bf7befc2671f4#opinionated%E3%81%A8un-opinionated)

Reactではコンポーネントと呼ばれる構成要素を用いて開発します。部分ごとにコンポーネントを分けることで、カスタマイズしやすく変えたい部分だけを変えることができます。

#なぜReactを使うのか

- 仮想DOMが高速

Reactには、仮想DOM(Virtual Document Object Model)というレンダリング機構が備わっています。
(DOMとは```document.getElementById(id);```のようにjavascriptから自由に文字色などを操作することができる操作を指す。)

仮装DOMはページの差分検出の比較対象に使われ、従来のDOMと違い、必要な部分しか更新されないため非常に高速に動作します。

>[DOM操作についてはこちらをどうぞ](https://eng-entrance.com/what-is-dom)
>[仮想DOMについてはこちらをどうぞ](https://watablogtravel.com/react-virtual-dom/)


- SPA（Single Page Application）が作りやすい
SPAは、ページすべてを毎回読み込む必要がなく、単一のWebページでコンテンツの切り替えを行うことができる。効率的かつ高速で動かすことができる設計構造のことです。
ReactはSPAに必要な高速な動作速度を完全に再現できるので、非常に相性のいいライブラリといえます。

#　Reactの構成要素

Reactは主にComponent、state、propsの3つで構成されており、データが変更された時に、適切なコンポーネントだけを効率的に更新してレンダリングすることができます。

- Component

コンポーネント単位でUIの部品を作り、コンポーネントを組み合わせてアプリケーションを構築します。
コンポーネントのおかげで、UI を独立した再利用できる部品に分割し、部品それぞれを分離して開発することができます。
コンポーネントは関数と似ており（props）任意の入力を受け取り、画面上に表示すべきものを記述する React 要素を返します。　
ComponentにはClass ComponentとFunctional Componentの2種類あります。

1.関数(Functional Component)
``` const App = (props) => {
  return (
    <div>
      <h1>Hello World</h1>
    </div>
  );
}; ```

2.ClassComponent

```class App extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello World</h1>
      </div>
    );
  }
}
```

- state

　Componentでは内部で状態(state)を持つことができます。stateはコンポーネント毎に持っており、コンポーネントの状態を管理します。
状態の変化によってstateの値を変えることができます。

- props

　親コンポーネントから子コンポーネントへ値を渡し、コンポーネント間でデータの受け渡しができます。(propsは子供が持っており、子から親へは渡せない)

#処理の流れ

・コンポーネントにはコンポーネントを利用する側である「親コンポーネント」とコンポーネントを利用される側である「子コンポーネント」に分けられます

・親コンポーネントが子コンポーネントを呼び出すとき、子コンポーネントに値が渡されますが、この時に渡されるのが「props」になります。

・親から渡された値を取り出して画面に描画します。


#stateの使い方
・stateを使うことで画面を動的に変更させることができます。

stateを使う際には、初期値を設定して変化させる処理を書いて使います。
stateの値が更新されることで画面を動的に変えることができます。

#まとめ
・各コンポーネントはstateを持っており、自身のstateしか更新できない
・stateが更新されると再描画される
・親から子にのみpropsを渡せる

[propsとstateの説明はこちらの記事が分かりやすいです](https://qiita.com/rio_threehouse/items/7632f5a593cf218b9504)

実際にこうしてアウトプットしてみるとReactの概念しか理解できていないと痛感させられますね。。
アウトプット大事です。