OmniAICreator/Qiita-1.07M huggingface dataset:
FirebaseとリンクされたGA4を変更したい時の注意点

「Firebaseと連携しているGA4の連携を解除して、新しいGA4と連携したい」
「リンクされたGoogleアナリティクスアカウントを変更したい」
「Firebaseを別のGA4を紐づけたい」

よくあるお問い合わせ内容になりますが、いろいろと痛みを伴うので注意が必要な操作になります。すでに今のGA4で本番運用を行っておりデータがたくさん溜まっている状態であれば、あまりオススメはしません。が、これまでのデータを捨ててでもこれから貯めるデータに全霊をかけるというのであれば止めません！


# リンク先変更方法
設定自体はFirebaseコンソールから簡単に変更することができます。
「Firebaseコンソール＞プロジェクトを設定＞統合＞Google Analytics＞管理」と進むと下記キャプチャのような画面が表示されるので、
![スクリーンショット 2020-12-02 10.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/2183cbcc-79d0-3f4d-a54c-f13f05b8930e.png)
矢印の先のアイコン（これって[ケバブメニュー](https://blog.sprobe.com/menu-icon/)って言うんですね！？）をクリックすると、
![スクリーンショット 2020-12-02 10.59.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/e5bbcaed-a76b-9a35-0b05-f7cf11042cc6.png)
「このプロジェクトからアナリティクス...(を解除する)」という表示が出てくるので、これをクリックしてください。(大事なところが表示されてないのでしっかりして欲しい。。)
するとこんな警告文が表示されます。
![スクリーンショット 2020-12-02 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/a80fe3ab-1b19-d300-3ca1-049740074ac0.png)

「Googleアナリティクスのリンクを解除する」を押すと、現在リンクされているアナリティクスは解除され、Firebaseでアナリティクス機能が無効状態になります。
分析メニュー内のダッシュボードもこの通り。連携を解除した状態ではダッシュボード以外のEventsやConversionsもFirebaseコンソールからは確認ができなくなります。
![スクリーンショット 2020-12-02 11.56.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/cdce97e4-62d5-5920-ebe0-f5d69a80d04a.png)

当たり前のことですが、この状態で送ったイベントは計測対象になりません。なので計測を再開するためには新しいアカウントを紐付ける必要があります。
「Firebaseコンソール＞プロジェクトを設定＞統合＞Google Analytics＞有効にする」と進み、連携するアカウントとプロパティを選択します。プロパティはアカウント内に新しいプロパティを作成するか、まだFirebaseとリンクしていないプロパティを選択することが可能です。すでにFirebaseと連携済みのプロパティは選択できません。
![スクリーンショット 2020-12-02 12.55.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/5c2c9a3a-501e-199c-52c8-8814686dfa92.png)
アカウントとプロパティを選択して、「Googleアナリティクスを有効にする」をクリックすると、再連携も完了です。

# Firebaseが失うもの(再設定が必要なもの)
さて、データの方は何が変わったのでしょうか？
連携解除する際に出ていた警告文に書かれていた、A/Bテストやユーザー行動の予測(Predictions)、FCMの送信ターゲットなどに影響があるのか、使ってないなぁと思って連携を解除すると泣くことになるかもしれません。

基本的には、分析配下のデータが全て消えると思ってください。
今までイベントレポートでパラメータを確認するために設定していたカスタムディメンション、カスタム指標、コンバージョン、ユーザープロパティ、オーディエンス、全部消えます。新しいプロパティと連携した後、再度各項目の設定が必要です。Firebaseから新しいGA4に設定が自動で反映されることはありません。
今まで使っていた設定は、今までリンクしていたGA4にだけ残ります。

↓再連携後全てのデータが失われたコンバージョン一覧
![スクリーンショット 2020-12-02 12.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624293/bda2af37-ebd3-3806-2579-1cf3c115822e.png)

この記事を書いている時点で、今までリンクしていたプロパティとすぐ再連携した際には解除前のデータが戻ってきました。が、Firebaseの仕様はすぐ変わりますので当てにしないでください。
同じプロパティと再連携したとしても、連携解除から時間が経っていたらデータは消えるかもしれません。試すときは別のプロジェクトで確認してから石橋を何度も叩いて実行することをお勧めします。


# 過去のデータを確認するには？
上でも少し触れましたが、過去のデータは「元々リンクしていたGA4にだけ」残ります。
カスタムディメンション、カスタム指標などの設定も含め、元々リンクしていたGA4は解除前と変わらずデータを確認することができます。
なので一度連携を解除して、別のプロパティに連携すると20XX年◯月まではこのプロパティ、20XX年△月からはこのプロパティ、というような状態になってしまいます。しかもFirebaseコンソール上では20XX年△月からのデータしか確認できません。
とっても不便な状態になります。


# まとめ
FirebaseアナリティクスとGA4(旧アプリとウェブプロパティ)の連携が開始してまだ使用感がわからないという理由で、仮のプロパティと連携し、さて正式版に切り替えよう、となるとちょっと大変な印象です。過去データは失われるとご案内すると、やっぱり「えっ！？」となるお客さんが多いです。
FirebaseとGA4をリンクする際には、計測設計を行った上で、どのプロパティと連携するかよく検討することをお勧めいたします。
既に進行中のコンソールセッションがあるため、リモートコンピューター上の他のコンソールセッションに接続できませんでした。


# 事象 : 作ったコンテナにリモートデスクトップ接続できない
- 環境
    - Windows10 Pro 64bit バージョン1909
    - Docker Desktop 2.4.0.0
        - Docker version 19.03.13
        - docker-compose version 1.27.4

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/c6964b9a-14d4-95b5-80e5-2eec807a68f5.png)

## 原因 : 自分のPCの同じポートに接続しようとしているから
以下の記事を見て「はっ！」とした・・・Windows on Dockerを使って自分のPCにコンテナ作っているんだから同じポート指定したら意味ないじゃん！
これまで、サーバ上にDockerコンテナを作って使っていたので気が付かなかった・・・。

>繋がらないIPアドレスをレジストリエディタで検索してみたところ
> なんだ、自分も接続先と同じ固定IPアドレスを持っていたのか
> 自分自身に対してリモート接続を行おうとしていたためだった。
> [リモートデスクトップ接続で - プログラまあのネタ帳](https://blog.goo.ne.jp/programaa/e/ebb7904a121d024e690eb3332bbdf0c0)


```yml
version: "3.7"
services:
  hoge:
...省略...
    ports:
      - "8080:8080" # アプリケーションサーバ用
      - "3389:3389" # リモートデスクトップ用
```

## 対応 : ポートを変える
自分のPC内同士で接続するのだから別々のポートを指定しなければおかしくなる。
よく忘れるがポートは`- "{ホストのポート}:{コンテナのポート}"`。

```yml
    ports:
      - "18080:8080"
      - "13389:3389"
```
GO言語でカプセル化

以前に書いた記事 [GO言語でクラスっぽいことをする](https://qiita.com/gramin/items/fe3b88547f6be014587b) の中で触れられなかった「カプセル化をGo言語で実現する方法」について書いていこうと思います。
ポリモフィズムに関しては今回も省略します。（いつか書きたい）

## やりたいこと

- コンストラクタでPrivate変数の初期値を設定する
- Publicメソッドを外部から参照して実行する
- Publicメソッド内でPrivate変数を利用する
- Publicの定数を参照して利用する
- Private変数の値を参照しようとするとエラーになることを確認する

全網羅じゃないけどよく使いそうな処理

## 実装例



```main.go
package main

import (
	"fmt"

	"xxx.example.com/sample/human"
)

const line = "--------------------"

func main() {

	wiz := new(human.Human)
	wiz.Init("魔法少女", 10, 10)

	fmt.Println(human.Msg)

	fmt.Println(line)
	fmt.Println(wiz.Hello())
	fmt.Println(wiz.Attack())

	fmt.Println(line)
	human.Hoge()

	// wiz.hp undefined (cannot refer to unexported field or method hp)
	// wiz.hp = 100

	// wiz.name undefined (cannot refer to unexported field or method name)
	// fmt.Println(wiz.name)
}
```

```human/human.go
package human

import "fmt"

const (
	// Msg ...
	Msg = "人類を作成してください..."
)

// Human ...
type Human struct {
	name string
	hp   int
	ap   int
}

// Init ...
func (h *Human) Init(name string, hp, ap int) {
	h.name = name
	h.hp = hp
	h.ap = ap
}

// Hello ...
func (h *Human) Hello() string {
	return fmt.Sprintf("こんにちは、私は%sです。", h.name)
}

// Attack ...
func (h *Human) Attack() string {
	return fmt.Sprintf("%sの攻撃！%dのダメージ！", h.name, h.ap)
}
```

```human.hoge.go
package human

import "fmt"

// Hoge ...
func Hoge() {
	war := new(Human)
	war.Init("+‡†狂戦士†‡+", 10, 15)
	fmt.Println(war.Hello())
	fmt.Println(war.Attack())

	fmt.Println(war.name + "はフォルムチェンジした！")

	war.name = "俺TSUEEEEEEEE"
	war.ap = 100000
	fmt.Println(war.Attack())
}
```

実行結果

```
人類を作成してください...
--------------------
こんにちは、私は魔法少女です。
魔法少女の攻撃！10のダメージ！
--------------------
こんにちは、私は+‡†狂戦士†‡+です。
+‡†狂戦士†‡+の攻撃！15のダメージ！
+‡†狂戦士†‡+はフォルムチェンジした！
俺TSUEEEEEEEEの攻撃！100000のダメージ！
```

+‡†狂戦士†‡+はチーターであることが判明しました

## 実装内容の説明

前記事 [GO言語でクラスっぽいことをする](https://qiita.com/gramin/items/fe3b88547f6be014587b) と被ってそうなところは省略します

## 外部からアクセス可能な要素

Go言語では「先頭が大文字の要素」は外部パッケージからもアクセスできます。
今回の例では `const Msg` `type Human struct` `func Hello()` などがそれに当たります。（他にもあります）
ここでは出てきませんが変数も指定可能です。

## 外部からアクセス不能な要素

Go言語では「先頭が小文字の要素」は外部パッケージからアクセスできません。
今回の例では `Human.name` などがそれに当たります。（他にもあります）
ここでは出てきませんが定数やメソッド、関数も指定可能です。

## 外部からアクセス不能な要素を指定した場合

```go
// wiz.hp undefined (cannot refer to unexported field or method hp)
wiz.hp = 100

// wiz.name undefined (cannot refer to unexported field or method name)
fmt.Println(wiz.name)
```
そんな要素は存在しないものとしてコンパイルエラーになります。

## 同パッケージのファイルからは先頭小文字でもアクセス可能

```go
war.name = "俺TSUEEEEEEEE"
war.ap = 100000
```

先頭小文字の要素であっても、同パッケージ内であれば好きに参照することができます。
+‡†狂戦士†‡+に好き勝手動かれたくない場合は別パッケージから使用するのがよいでしょう。

## まとめ：Go言語でカプセル化するには

- パッケージを分ける
- 外部から参照されたくない要素は「先頭小文字」で定義する
TIPS：CentOSの ls -l コマンドにtime-styleを添えて、年月日を揃える！

CentOSの`ls -l`コマンドだが、localeがLANG=ja_JP.utf8だと、年は表示されないし、月日の表示も情けない。

```bash
$ ls -l
drwxr-xr-x 2 root root 4096 11月 25 11:07 Desktop
drwxr-xr-x 2 root root 4096 11月 27 15:02 Documents
drwxr-xr-x 4 root root 4096 11月 30 15:29 Downloads
```
以下のようにtime-styleオプションを添えると、きれいに並ぶ。

```bash
$ ls -l --time-style=long-iso
drwxr-xr-x 2 root root 4096 2020-11-25 11:07 Desktop
drwxr-xr-x 2 root root 4096 2020-11-27 15:02 Documents
drwxr-xr-x 4 root root 4096 2020-11-30 15:29 Downloads
```
ホームの.bashrc、または、/etc/bashrc、/etc/profileのどこかにaliasを登録しておくといい。私は、/etc/profileの末尾に、以下の感じで追記してみた。

```bash
$ vi /etc/profile
alias ll="ls -l --time-style=long-iso"
alias lla="ls -la --time-style=long-iso"
$ source /etc/profile
$ ll 
drwxr-xr-x 2 root root 4096 2020-11-25 11:07 Desktop
drwxr-xr-x 2 root root 4096 2020-11-27 15:02 Documents
drwxr-xr-x 4 root root 4096 2020-11-30 15:29 Downloads
```
以上
Ruby on Rails（v6対応）をDockerで環境構築しHerokuにデプロイする

# 本記事の対象者

Railsは未経験でしたが、とりあえず学習環境つくろうと思い、備忘録のため記事化しました。
アプリケーションの開発に集中するため、Docker環境をコピペで作りたい人向けの記事です。
Rails6を対象としています。

# 自身のスキルレベル

- Railsは全くの未経験（なんにも知りません）
- Dockerはそこそこやったことあります
- 他フレームワークでWebの基本的な開発はやったことあります

# 必要なファイル

環境構築に必要なファイルは以下の通りです。
myappディレクトリを作って、以下のファイルを作成してください。

```
myapp
- Dockerfile
- Gemfile
- Gemfile.lock
- entrypoint.sh
- docker-compose.yml
```

# 1. 環境構築

## 1-1. Dockerfile

```:Dockerfile
FROM ruby:2.6.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

# yarn
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

# Node.js
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
apt-get install nodejs

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

## 1-2. docker-compose.yml

後にHerokuを使うため、dbはPostgreを指定しました。
（Postgreだと無料でHeroku環境が作れるため）


```docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    environment:
      POSTGRES_HOST_AUTH_METHOD: 'trust'
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

```

## 1-3. Gemfile

Rails用のパッケージファイルだそうです。
バージョン6を指定しています。

```:Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'
```

## 1-4. Gemfile.lock

空の```Gemfile.lock```を作成しておきます。
後にビルド時に自動的に更新されます。

## 1-5. entrypoint.sh

```entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

# 2. ビルド

Dockerのビルド。

```
$ docker-compose build
```

パッケージのインストール。

```
$ docker-compose run web yarn
```

Rails6から必須のwebpackerのインストールを行なっておきます。

```
$ docker-compose run web bundle exec rails webpacker:install
```

コンテナ起動とDBの作成を行います。

```
$ docker-compose up
$ docker-compose run web rake db:create
```

ここまで成功したらRailsが起動していることを確認します。
同時に、ローカル環境にRailsの環境一式がインストールされていることを確認してください。

http://localhost:3000


# 3. Herokuデプロイ

作った環境をインターネット経由でもみたい方は、Herokuにデプロイするところまでやってみましょう。

Herokuのアカウントが無い人は事前に作成しておいてください。
作ったローカル環境をHerokuにデプロイします。  

```
# herokuのコンテナレジストリにログイン
heroku container:login

# 新しいappを作成
heroku create

# イメージを作成してコンテナレジストリにpush
heroku container:push web

# postgresqlアドオンの無料プランを追加
heroku addons:create heroku-postgresql:hobby-dev

# DBセットアップ
heroku run rails db:migrate

# イメージをherokuへデプロイ
heroku container:release web

# 実際にアクセスして/usersを確認してみる
heroku open
```

# 4. アプリを開発

ここまでできたら、あとはアプリを開発のみです。
お疲れ様でした。
IT初心者のORACLE MASTER Bronze DBA合格までの道

#ORACLE MASTER Bronze DBA試験の概要

* 試験名：1Z0-085 Bronze DBA Oracle Database Fundamentals

* ORACLE MASTER Bronze DBA試験は2020年1月から新体系として発表された試験です。
※旧体系試験ではDBA分野とSQL分野の2種類の合格が前提でしたが、SQL分野は独立してDBA試験だけでBronze認定されるようになりました。(**嬉しい！！！**)

* 問題数：70問

* 合格基準：正答率65%以上で合格

* 受験料：29000円(税抜)　※2020年12月時点
  (11月末までは26000円だったのに12月から3000円値上がりしました....)

* 試験方式：コンピューター上で実施するCBT（Computer Based Testing）形式

#筆者について

* 2020年の春に某Sierに就職した新人エンジニア

* 学生時代は情報系の専門学校に通っていたが、特に勉強をせず自堕落な日々を送っていた

* データベースは業務で少しMySQLを触った経験あり。(環境構築経験はなし)

* Oracleについては名前だけ知ってた程度

※Oracle DBについては完全に初心者からの学習だったため、初心者向けの記事になります。

#学習期間

11月15日～12月5日までの**3週間**.

毎日平均3時間、合計**約60時間**学習しました。

#使用した参考書

**現在発売されているORACLE MASTER Bronze DBAの参考書は下記の一点になります。**※2020年12月時点


#####オラクルマスター教科書 Bronze DBA Oracle Database Fundamentals

* 出版社：翔泳社

* URL: [https://cosol.jp/techdb/2020/08/1z0-085-new-oracle-master-bronze-dba-book/](https://cosol.jp/techdb/2020/08/1z0-085-new-oracle-master-bronze-dba-book/)

* 参考書には各章末に章末問題があり理解度を確かめることが出来ます。

* 巻末にある模擬試験(70問)はネットでも受けることができて使いやすかったです。
(**問題のレベルは試験とほぼ同程度**のため、**9割**以上正答を目標にしましょう)

#学習方法

私が取り組んだ内容はこちらです。

* 参考書を3周
* 模擬試験を正答率9割を目標

具体的な手順を下記に記載します。

**試験の概要の把握**(2h)
※最近旧体系から新体系に変わったばかりで情報が少ないので、参考書を執筆している株式会社コーソルの方が書いている記事を参考にしました。

#####概要把握に使用したサイト
URL: [https://cosol.jp/techdb/2020/02/new_oracle_master_overview_2020/](https://cosol.jp/techdb/2020/02/new_oracle_master_overview_2020/)

　　　　⇩

**「オラクルマスター教科書 Bronze DBA Oracle Database Fundamentals」**(以後**黒本**)を一通り読む(15h)
※最初は単語ごとの概要をなんとなく理解できたな~ってくらいでした。
※章末問題は現状の知識を把握するのに便利なので解いておいたほういいです。

　　　　⇩

**巻末の模擬試験**を解く。(3h)
※この時点での正答率は**5割**くらいでした。
※問題を解くだけではなく、解説もしっかり読んでなんで間違えたかを確認しました。


　　　　⇩

**「黒本」をもう一度読む。**(20h)
※単語だけでなくどういう構造になっているかも覚えておくとわからない問題が出ても2択ぐらいには絞れるので、参考書にもある図をみて構造を理解しましょう。
※Oracleの無償版が配布されているので実際に構築をしながら進めることで、効率よく知識の定着が図れると思います。

　　　　⇩

**巻末の模擬試験**を解く。(10h)
※正答率が**9割**になるまで繰り返し解きました。(スマフォも活用)
※はずれの選択肢の用語の意味も理解できるようにしました。
※基本的な用語の問題は選択肢を見なくても答えが出せるくらいになりました。

　　　　⇩

**「黒本」の理解度の低い部分を重点的に見直す**(10h)
※最終確認で見直しをしましょう。

　　　　⇩

本番！

学習に取り組んでみて思ったのは**この試験は暗記で行ける！**でした。
**黒本**は試験範囲を網羅しているので、**できるだけ多く暗記**して試験に臨みましょう！

余談ですが、学習中2時間に1回は「あんきパン」が欲しいって思ってました....
#試験結果

正答率87％で**合格**:clap:

#試験を受けての感想

私はDBについての知識があまりない状態からのスタートだったので覚えるのにかなり苦労しましたが、経験者の方は簡単に合格できると思います。

これから試験を取ろうと思っている初心者の方の学習にこの記事が少しでも参考になればいいなと思います。**※正直この試験は暗記ゲーです笑**

まだSilver DBAとSilver SQLは参考書が出ていないので受験予定はないですが、参考書が出次第挑戦しようと思っています！

では！
プログラミング初心者が作るIoTRCカーの製作　1-2 ESC、サーボのハック 試作開始



##Obniz、購入しました！
![IMAG2737.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/bcded205-e372-c372-c594-27c5cd5e00b2.jpeg)

合わせてテキストも。まずは勉強から……なんですけど、そういうのすっ飛ばして電子工作出来るというのには感動の2文字しかありません。
wifi設定完了したボードにセットのサーボを付けて、web上にあるサンプルの「Test Open」をクリックするだけでもうサーボを動かせるんですよ。マイコン内にプログラムを転送する時間とかも無いですし、「うわ早っ！」というのが第一印象でしたし実際声に出てしまいました。

遅延については、多分出てるんでしょうけどラジコンを遊び的に動かす分には問題なさそうです。さすがにレースとかは無理でしょうけど、自動運転とかだと全然問題ない感じ。これにもびっくりしました。

##RCカーのサーボをハックしてみよう
スターターキットに付いているサーボはいわゆるフタバコネクタで（他にも呼び方はあるそうです）3極のメス端子になっているんですけど、それにピンヘッダを入れてオス化してObnizの端子に差し込めるようになっています。このピンヘッダを借りてTSU-03を接続し、そのままサンプルを動かした時の画面がこれです。


>io1: heavy output. output voltage is too low when driving high

という警告が出ました。Obniz側の電圧では動作出来ないようです。やはりBECか……。

![IMAG2730.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/cb135d38-1b91-db2f-7dd9-bf4834ed7d81.jpeg)

そんな訳で、RCカーのバッテリーからサーボに電源供給する必要があります。
やることはESCとサーボのフタバコネクタにあるVCCとGNDを直結して、サーボのsignalをObnizの2ピンへ、更にサーボのGNDを0ピンへ繋げる、と言うものです。この位なら自分でも何とか出来ます。

ちなみにどうして直接バッテリーからサーボに電源供給しないかというと、バッテリー電圧が7.2VでBEC電圧が6.0Vであるのに対してサーボの電圧が4.8～6.0Vであること、あとは結線のしやすさからです。RCのバッテリーはNiCdでも要警戒です。

![IMAG2735.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/2bf4a121-035e-1b76-f024-a7ad20ecb2ef.jpeg)

さて電源をESCのBECから取って、サーボ動きました！

写真のRCカーは近くにあったコミカルグラスホッパーという別のモデルですが、取り付けられているサーボのフタバコネクタからジャンパー線を挿してステアリングを作動させることが出来ました。ただやっぱり90度という角度はRCカーには大きすぎて、この辺はプログラム側から修正する必要がありそうです。あとこのシャーシもコミカルアバンテのシャーシもサーボの動きとステアリングの動きが逆になるように出来ているので、プロポでよくあるサーボリバースも考えないといけないですね。

ちなみに取り付けているサーボはTAMIYA TSU-04です。TSU-03より少しトルクが大きくて、防滴のアナログサーボです。

##ESCは少しハック出来ました
![IMAG2732.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/933473/27dda70e-3ee6-1165-9f2d-f384694daa47.jpeg)

RCカーの組み立てで時々受信機の接続を間違えてステアリングとスロットルが逆に動いてしまった、ということがあります。つまり同じ方式で動いているという訳で、同じサーボのサンプルプログラムから動かせないか試してみました。
すると一応動くには動いたのですが、一方向（軸側から見て右回転）にしかモーターが回転しなかったり、スライダーの一部でしか回らなかったりします。この辺は自分で探っていくしか無さそうです。

##現状まとめ
-Obnizでサーボ、ESCのハックそのものは可能
-TSU-03の場合サーボの電源はObniz側からではなく、RCカーのバッテリーから供給が必要
-サーボは必要な角度（60度）に修正する必要あり
-ESCでモーターを回転させるには調査が必要

まだプログラミング何もやっていないのに、ここまで分かるというのはObnizの良さなんだと思います。クラウドってすごい……。
調査については、プログラミングを学んで任意のPWMを出力できるものを用意してみる予定です。

##やりたいこと
-Obnizの電源もRCカーから供給
-リバースやトリムといったプロポの基本機能を入れたい
-本来使いたいESC、サーボを使えるようにする

電源供給は、5Vレギュレータがあれば何とかなりそうです。リバース（サーボの動き反転）やトリム（舵角調整）は最悪マシンの動きを見てプログラム側で修正してもいいかなとは思うんですが、努力目標ということで。

今からブロックプログラミングやるので、次まで時間が空きそうですね。
herokuについて何も知らなかったので調べて分かりやすく解説してみる

#<font color="blue">herokuとは？</font>

**Paas(Platform As a Service)**の１種です。

WEBサービスを公開するために必要なものをすべてまとめて予め用意してくれるサービスのようです。
１から環境を構築するとなると、サーバー用のPCを用意したり、DBをセットアップするなど色々とやることがあります。
**Paas**を入れることで以下の環境がサクっと作成できてしまうのですね。
（もちろん細かい設定は必要になると思いますが・・・）

- サーバー
- OS
- データーベース
- プログラミング言語の実行に必要な環境

これらを個別にインストール・設定することなく環境構築ができてしまうんですね。

ここまで読んで理解したとき、社内の別PJの手伝いでPHP開発のテストを行った時の環境構築、自宅でWoedPressの勉強する際に使用していた**「XAMMP」**に似ている印象を持ちました。
（すいません、見当違いなことを言っているかもしれません・・・）

**heroku**等のPaasを使用しないで１から環境を構築しようとすると下記を手作業で行わなければなりません。

### <font color="#ff00c8">herokuを使わないで環境構築を行う場合に必要なこと</font>###
- サーバPCやルータなどのハードウェアを購入 →<font color="blue">お金がかかりますね・・・</font>

- インターネットに接続し、ネットワークを構築
- サーバの仮想化環境を整備　→<font color="blue">知識が必要になりますね</font>
- LinuxやWindowsサーバなどのOSをインストール　→<font color="blue">時間がかかりますね</font>
- Oracle、MySQL、PostgreSQLなどのデータベースをセットアップ
- Java、Ruby、PHPなどのアプリケーション実行環境をセットアップ　→<font color="blue">単純にめんどいし、初心者には難しかったりする</font>


**heroku**を使うことで以上の作業が１０分ほどで完了してしまうのですね！！！すばらしい！！！
※決して私はheroku社の回し者ではありません・・・
環境構築に時間を取られずに済むので開発に集中できますね。
（環境構築に心が折れそうになり、途中で諦めかけた経験あり・・・( ﾉД`)）

### <font color="#ff00c8">herokuを使うことでのメリット</font>###
 **拡張機能が豊富**

開発を進めていくうえで「あの機能が追加で必要だ」などとなったときにharokuの拡張機能を使用すればすぐに実装できる機能も豊富にあるそうです。

例えば

- SendGrid：メール配信
- PaperTrail：ログ管理
- New Relic APM：監視
   
    などがあるそうです。
    
**②スケールアウトが簡単**
ここはAWSでも出てくる話かと思いますが（以前少し勉強しました）
例えばWEBシステムにアクセスが殺到する時間帯にはサーバーを増やしたり、システムの処理能力を上げてサーバーが落ちないように増強する必要があります。
その時にそれを感知したりせず、そのままにしておくと最適な環境が維持できなくなってしまい、最悪サービスが落ちてしまいます。
herokuではherokuのダッシュボード画面で操作したり、簡単なコマンドを実行するだけですぐにスケールアウトができるそうです。

**③運用をサポートする標準機能が揃っている**
システムを開発したらそれで終わり、ではなく正しく運用できているか監視する必要があります。
具体的に言うと、アプリの状態を確認する「ログ」や、サーバーの状態を確認する「パフォーマンスモニター」などをチェックし、状態を把握しながらアプリが正常に動いているか監視を行います。

herokuでは、ログやパフォーマンスモニターなどを確認できる機能が備わっています。
そのため、状態のチェックをするために別途用意する必要がありません。

またデータベースのデータを守るためのバックアップ機能もあるため、運用にかかる手間が減らせるだけでなく、運用にかかるコストも抑えることができるのです。



### <font color="#ff00c8">herokuの利用に必要なこと</font>###

登録に必要なのは基本的に**<font color="red">メールアドレス</font>**のみです。
個人で開発するのに使用する分には料金はかからないようですが、有料版を使用したい時には支払情報なども必要になってくると思います。

### <font color="#ff00c8">herokuの料金体系</font>####

[herokuの料金体系](https://jp.heroku.com/pricing)
で確認することができます。
個人で開発する用途でしたら無料で充分事足りそうです。


### <font color="#ff00c8">herokuのインストール方法</font>####
インストール、登録方法については前回の記事[Windows10でherokuのCLIダウンロードとアカウント作成](https://qiita.com/kotttttun/items/07bfb9c6a6124b50f8f9)で書いていますので、参考にしていただければと思います。


### <font color="#ff00c8">最後に・・・</font>####
私は今後、herokuとGit（研修は受けたけど実務で使ったことがない💦）とNode.jsで個人的に開発を進めていきます。
そちらの流れも、記事にしながらつまづきやすいところを調べつつ私のような初学者の方でも理解しやすいようにまとめていけたらと思います。
アウトプットすることで自分の理解も深まります。
文章を書くことはもともと好きなのですが、この業界に入ってからドキュメント制作などをする際に先輩からはよく「まともに日本語も使えないのか！」と怒られていました。
それだけでなく、何かの不具合が発生したときに状況を正しく伝えたり、実装方法について確認したりする際、前提知識も必要ですが、どのように伝えるとあいてにスムーズ伝わるか、を以前よりはよく考えるようになったと思います。

まだまだ不慣れでわからないことだらけですので、厳しいコメント等いただけますと励みになります。
宜しくお願いいたします。
Node.jsを改めて理解する

#前提
Node.jsを理解する前に、いくつか確認しておきます。
##そもそもJavaScriptとは
HTMLやCSSで作られたWebページをプログラム（JavaScript）で制御することができるのが特徴です。
通常、クライアントサイドで用いられ、次のような場面でJavaScriptは使われています。
・ブラウザ上で画像をクリックすると拡大する
・メールアドレスを入力フォームに入力した時に、適切な形式で入力されているかチェックをする
...etc

##クライアントサイドとサーバサイドって？
###クライアントサイド
クライアントサイドプログラムは、Webブラウザ上で動作するプログラムのことです。
代表的なものとしてはJavaScriptがあります。
クライアントサイドプログラムの仕組みとして、クライアント側（ブラウザ）がサーバにリクエストすることによって、Webサーバー上のプログラムがクライアント側に送信され、そのプログラムをWebブラウザが実行するという形です。
###サーバサイド
サーバサイドプログラムは、Webサーバー上で動作するプログラムのことです。
代表的なものにPHP、Ruby、Pythonなどがあります。
クライアントからのリクエストに対し、サーバ側でプログラムを実行し、実行結果をクライアント側へ送るという仕組みです。
###クライアントサイドとサーバサイドの違い
クライアントサイドプログラムとサーバサイドプログラムの違いは、ブラウザ上で動作するのか、それともサーバ上で動作するのかの違いです。

#本題
いよいよNode.jsの説明です。
##Node.jsとは
Node.jsとは、一言で言うと**サーバサイドのJavaScript実行環境（プラットフォーム）のこと**で、Node.jsを使用する上で使用する言語はJavaScriptです。

Node.jsとは、通常クライアントサイドで使用するJavaScriptをサーバサイドで実行できるようにしてくれるものです。
サーバサイドで動かせると言うと、PHPやRubyなどと同じように思われるかもしれませんが、厳密には少し違います。
Node.jsは単にサーバサイドでアプリケーションを動かすことができるだけでなく、Node.jsではアクセスされたURLを識別して、そのURLごとに別々の要素を表示させるなど、データベースで行う動作も実装できます。

###特徴
- 大量のデータ処理が可能
- メモリの消費が少なく動作も速い
- 処理速度が非常に速い
- サーバサイドで使える

##npmとは
npmは、Node.jsのパッケージ管理ツールです。
PHPにおけるcomposer、Rubyにおけるgemのようなものです。

##Node.jsを使う場面とは
メモリ消費量が少ないため、小さな規模の開発・運用時に、他の環境と比べるとよりパフォーマンスを出すことが可能です。同時に大量のトラフィックを捌くことができ、動画配信やチャットアプリなどで使われます。
laravelのoldを消し去る方法

## 状況
以下のようにoldをつけると、バリデーションが発生してもその時入力した値を保持してくれてまた表示してくれる。

```php:anime-suko.php
<input id="hoge" type="text" name="hoge" value="{{ old('hoge') }}">
```
この値をクリアしたくて普通にtype="clear"なinputタグを用意しても消えない。


## 解決方法
**リダイレクトする必要がある。**

```
1.ボタンを用意(名前は任意のもので、typeはclearではなくbutton)
2.そのボタンを押すとフォームの場所にリダイレクトするためだけの関数を呼んでリダイレクト
```
ここでハマったのが、ボタン側の記述。buttonタグに「type="button"」を書かないと、formタグで指定されているパスに遷移してしまって、「registerUserFormClear」パスに遷移してないのが注意点。

```php:anime-suko.php
<a href="/registerUserFormClear"><button type="button">クリア</button></a>
```

これで、oldによって再現されていた値がクリアされた。
コマンド操作でファイルを作成する方法

touchコマンドを使用します。

ターミナルでtouch 作成したいファイル名と入力し、エンターキーを押すとコマンド操作せファイルが作成できます。:relaxed::v:
例、touch file.txtとすれば左の名前のファイルが作成できます。

ファイルが素早く作成できて、とても便利です:sunny:
Oracle Multitenant 2 PDBの削除

https://docs.oracle.com/cd/E96517_01/multi/removing-a-pdb.html#GUID-75C46F1B-00D8-4FB9-A8E7-6F7FE3DE4CA0
方法としては、xml出力するか、xml+データファイル含んだ圧縮ファイルで出力するかのどちらか
今回はxml出力での切断をする

con_id確認

```
SQL> show pdbs
  CON_ID CON_NAME        OPEN MODE    RESTRICTED
       2 PDB$SEED        READ ONLY    NO
       3 ORCLPDB1$SEED   MOUNTED
       4 ORCLPDB1        READ WRITE   NO
       5 ORCLPDB2        READ WRITE   NO
```

削除対象のPDBのデータファイルパスを確認
アンプラグ時のxmlをここに置く想定

```
SQL> select name from v$datafile where con_id=5;
NAME
/opt/oracle/oradata/ORCLCDB/orclpdb3/system01.dbf
/opt/oracle/oradata/ORCLCDB/orclpdb3/sysaux01.dbf
/opt/oracle/oradata/ORCLCDB/orclpdb3/undotbs01.dbf
/opt/oracle/oradata/ORCLCDB/orclpdb3/users01.dbf
```

PDB停止

```
SQL> alter pluggable database orclpdb2 close;

Pluggable database altered.
```

xml出力して切断

```
SQL> alter pluggable database orclpdb2 unplug into '/opt/oracle/oradata/ORCLCDB/orclpdb3/orclpdb3.xml';

Pluggable database altered.
```

切断確認 > 反映されてない

```
SQL> show pdbs
  CON_ID CON_NAME        OPEN MODE    RESTRICTED
       2 PDB$SEED        READ ONLY    NO
       3 ORCLPDB1$SEED   MOUNTED
       4 ORCLPDB1        READ WRITE   NO
       5 ORCLPDB2        MOUNTED

SQL> select con_id, name, open_mode from v$pdbs;
  CON_ID NAME            OPEN_MODE
       2 PDB$SEED        READ ONLY
       3 ORCLPDB1$SEED   MOUNTED
       4 ORCLPDB1        READ WRITE
       5 ORCLPDB2        MOUNTED
```

アラートログの出力これだけ
時間も出ない

```
Completed: alter pluggable database orclpdb2 unplug into '/opt/oracle/oradata/ORCLCDB/orclpdb3/orclpdb3.xml'
```

DB名とデータファイルパスがずれてる良くないパターン
がちゃがちゃ試しててこうなったみたい

外したPDB、アプリケーションPDBだった
アプリケーションルートから切断する必要がある??
アプリケーションルートに接続し直してorclpdb2の切断を再実行

```
SQL> alter pluggable database orclpdb2 unplug into '/opt/oracle/oradata/ORCLCDB/orclpdb3/orclpdb3-2.xml';

alter pluggable database orclpdb2 unplug into '/opt/oracle/oradata/ORCLCDB/orclpdb3/orclpdb3-2.xml'
 *
ERROR at line 1:
ORA-65343: cannot unplug pluggable database ORCLPDB2
```

そういうわけではないらしい
PDBの切断はやはりCDBからしか実行できなそう

open_modeで確認するのは違った
statusで確認できる
＃再度CDBに接続

```
SQL> select PDB_ID, PDB_NAME, STATUS from dba_pdbs;
  PDB_ID PDB_NAME        STATUS
       2 PDB$SEED        NORMAL
       3 ORCLPDB1$SEED   NORMAL
       4 ORCLPDB1        NORMAL
       5 ORCLPDB2        UNPLUGGED
```

v$pdbsにstatus列欲しいところ..

切断後、削除する

```
SQL> drop pluggable database orclpdb2 keep datafiles;

Pluggable database dropped.

SQL> show pdbs
  CON_ID CON_NAME        OPEN MODE    RESTRICTED
       2 PDB$SEED        READ ONLY    NO
       3 ORCLPDB1$SEED   MOUNTED
       4 ORCLPDB1        READ WRITE   NO
```
Alpineでバージョンを指定してPythonをいれる

Dockerでflask & vueのイメージをビルドしたかったときに詰まった．

```Dockerfile:Dockerfile
RUN apk update && apk add --no-cache python3 && python3 --version
# 3.8.6
```
2020/12/07時点は自動的に`3.8.6`がインストールされた．しかし，PipでPytorchをいれるときにエラーが出てしまったのでPythonのバージョンを指定することに

また，apkでインストールされるバージョンは[こちら](https://pkgs.alpinelinux.org/packages?name=python3&branch=edge)から確認できそう

## バージョンを指定してPythonをいれる
```Dockerfile:Dockerfile
RUN apk update && apk add --no-chache --repository http://dl-cdn.alpinelinux.org/alpine/v3.10/main python3~=3.7
```
リポジトリとバージョンを指定するとできた．
リポジトリのブランチとPythonのバージョンは[先ほどのサイト](https://pkgs.alpinelinux.org/packages?name=python3&branch=v3.10)で確認できる．上の例でいうところの`v3.10`と`python3~=3.7`

## 参考文献
https://tamakiii.hatenablog.com/entry/2020/02/11/191548
Pythonのuuidモジュールを使う時の注意

Pythonで`import uuid`する時に`pip isntall uuid`してはいけないっぽい(requirements.txtに書くのも駄目)

以下のようなエラーが出たので、requiremetnts.txtからuuidを消したら動いた。

```
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'hoge/app': invalid syntax (uuid.py, line 138)
Traceback (most recent call last):
  File "/var/task/uuid.py" Line 138
                if not 0 <= time_low < 1<<32L:
```

参考にしたページ
https://github.com/Miserlou/Zappa/issues/1189
【React】Fast Refresh を有効にする

以前から `react-hot-loader` を使って、 `HMR (Hot Module Reloading)` を行ってきましたが、
`React` が `Fast Refresh`というネイティブ機能が提供されましたので、こちに移行します。
今回は `webpack` を使った場合、具体的にな設定を説明します。

## ライブラリインストール
Fast Refresh 機能は、`react-refresh` を追加でインストール必要です。
`webpack`使う場合、`babel` とプラグインもインストール必要がある

```sh:Install
yarn add react-refresh
yarn add @babel/core babel-loader @pmmmwh/react-refresh-webpack-plugin -D
```

## 設定
意外と設定する場所が少ないが、プラグインなしの場合死ぬほど難しいそうです。

```typescript:webpack.ts
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';

const configs: Configuration = {
  ...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            // *** ここから ***
            options: { plugins: ['react-refresh/babel'] },
            // *** ここまで ***
          },
          {
            loader: 'ts-loader',
            options: {
              transpileOnly: true,
            },
          },
        ],
      },
    ],
  },
  plugins: [
    ...
    // *** ここから ***
    new ReactRefreshWebpackPlugin(),
    // *** ここまで ***
  ],
  ...
};
```

## 試して見る
デモ用ソースは GitHub で公開中です。
https://github.com/wwalpha/react-refresh-typescript-example

```sh:DEMO
git clone https://github.com/wwalpha/react-refresh-typescript-example.git
cd react-refresh-typescript-example
yarn install
yarn start
```

全部５種類コンポーネントがテストできます。

- Class Default 
- Class Named
- Function Default
- Function Named
- Lazy Component
WordPressでのscreenshot.png（テーマ画像）について

ワードプレスのテーマtwentytwentyを基盤に、管理画面「外観」>「テーマ」でサイトのスクリーンショット画面を表示させる実装を行ったので、備忘録的にこの記事を残す。

# 環境情報

PHP：version 7.3.12
WordPress：version 5.5.3
WPテーマ：twentytwenty

# 作業

管理画面「外観」>「テーマ」でサイトのスクリーンショット画面を表示させるためには、「screenshot.png」が必要です。
スクリーンショット画面は、たとえば次の要領で作成・保存します。
トップページなどのスクリーンショットを取得し、画像サイズを880×660ピクセルにします。画像ファイル名は「screenshot.pmg」とします。
作成したscreenshot.pngをindex.phpやstyle.cssと同じ階層に配置します。
Class化について



# Document Links

-   [マルチスケールシミュレーション特論まとめ](https://qiita.com/evendemiaire/items/25f459daa57ab8875ba6)
-   [チャート式ruby-VI(hello class)](https://qiita.com/daddygongon/items/969ad5112878f6dab844)


# Class化


## 復習

前回の記事でClass化について少し触れたが，わかりやすいように復習がてら記述

オブジェクト指向において，鍵となる考え方が，

-   隠蔽(capsulation)
-   継承(inheritance)
-   多態(polymorphism)

の３つです．

Methodはある種の隠蔽だけど，更に言語システムとして徹底したのが， **Class** であるとのこと．

前回，その例として

```ruby:
def puts_hello name
  puts "Hello #{name}."
end

def gets_name
  name = ARGV[0] || 'world'
  return name
end

name = gets_name
puts_hello name
```

実行結果

    $ ruby hello.rb
    Hello World.
    $ ruby hello.rb Name
    Hello Name.

mainでloopがある．

こいつを消したいので，修正すると（前回から少し修正しています）

```ruby:greeter_class.rb
class Greeter
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello 
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name.capitalize #".capitalize"で先頭が大文字になる
  end
end

Greeter.new
```

実行結果は同じになる．

-   Greeter.new
-   class Greeter
-   initialize method
-   @name

なんかが鍵となる．

というところまでしました．


## MethodとClassについて

methodとclassを比べるとobject指向の書き方の流儀の違いが実感できるらしい．

-   methodでは，verb(subject,object)
-   object指向では，subject.verb(object)

とな．

よくわからんが，とりあえず書いてみる．（ついでに出力の色分けもした）

```ruby:hg_class.rb
require 'colorize'

# method
def hello(name)
  "Hello #{name}."
end

# class
class Greeter
  def initialize
    @name = gets_name
    puts_hello
  end

  def puts_hello 
    puts "Hello #{@name}."
  end

  def gets_name
    name = ARGV[0] || 'world'
    return name.capitalize
  end
end

# method call
name = ARGV[0]
puts hello(name).green

# class call
Greeter.new
```

うーん，まだよくわからん．

資料を読んで，更に加筆，修正していく．

```ruby:hg_class2.rb
require 'colorize'

# method
def hello(name)
  "Hello #{name}."
end

# inherited class
class Greeter < String
  def hello
    "Hello #{self}."
  end
end

# extend class
class String
  def hello
    "Hello #{self}."
  end
end

# method call
name = ARGV[0]
puts hello(name).green

# inherited class call
greeter = Greeter.new(ARGV[0])
puts greeter.hello.red

# extend class call, override
puts ARGV[0].hello.blue
```

上から，method，継承class，classのoverrideで書いている．

Greeter classはString classから継承することで，hello methodを扱うことが出来ている．（という認識，合ってるのか？）

まだまだ勉強が必要ですな．．．


## attr\_accessor

rubyのclassのidiomでよくあるのが，

```ruby:hg_class2.rb
require 'colorize'

# method
def hello(name)
  "Hello #{name}."
end

# inherited class
class Greeter < String
  def hello
    "Hello #{self}."
  end
end

# extend class
class String
  def hello
    "Hello #{self}."
  end
end

# method call
name = ARGV[0]
puts hello(name).green

# inherited class call
greeter = Greeter.new(ARGV[0])
puts greeter.hello.red

# extend class call, override
puts ARGV[0].hello.blue
```

のようなものらしい．

実行結果

    $ ruby hg_class_accessor.rb masa
    Hello World.
    Hello Masa.

どのように動作しているか，詳しくは講義資料に書いてくれています．


# 締め

今回はClassについて学んだ．

次回，[Thor & Rubocop](https://qiita.com/evendemiaire/items/0cd1871720fe5d0e5ce5)



------
 - **source** ~/school/multi/my_ruby/grad_members_20f/members/evendemiaire/post/class.org
[TouchDesigner] オペレータのタグとかコメントとか

TouchDesigner を使う上で必ず使用するオペレータ
1種類ごとに機能を持ち、組み合わせていくことで制作・開発を進めていくかと思います。

ただオペレータで操作するのはそれぞれの入出力とパラメータ、あとはプレビューくらいで、それ以外の機能はあまり使われているのを見たことがありません。

そこで、今回はオペレータのあまり使われていないけど便利な機能を紹介していきたいと思います。

https://docs.derivative.ca/OP_Class

## タグ
オペレータにタグ付けを行うことができます
![tags.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/89280401-2b5c-8796-c60a-97d5e0ba97b9.png)

上記の画像の赤丸のアイコンを押して、タグを追加できます
（残念ながらほかのオペレータで使っているタグが候補で出てきたりする機能は無いです、、）

```python:python
# 取得
op('').tags

# 上書き
op('').tags = ['effect', 'image filter']

# 追加
op('').tags.add('darken') 
```

ただ、タグはパラメータの上の部分に表示されるだけなのでとても見づらく、一見便利じゃなさそうですが、
COMP の`findChildren()`やOP Find DATと組み合わせることで実力を発揮します

例えば、画像で使用する`moviefileinTOP`に`image`というタグを付けたとします。
`OP Find DAT`　のLimit Max DepathをOffにして、Tagsのパラメータを`image`に変更すると、特定の階層下にある`image`タグのついたオペレータを検索することができます
![tags_opfinddat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/575df852-85a9-ed57-38f6-bf326253f72f.png)

### 使用例
起動時や特定のタイミングで初期化処理を行いたい場合

初期化を行うスクリプトの書かれたTextDATなどに`init`のタグを付加
OP Find DAT で`init`タグを検索（上記参照）

```python:init_all.py
for i in range(1, op('opfind1').numRows):
    op(op('opfind1')[i, 'path']).run()
```

これで`init_all.py`を実行するだけですべての初期化スクリプトを実行させることができます！

## コメント

オペレータにコメントを付けることができます
![comment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/c27d3dfe-f606-11f9-a318-58815c78da11.png)

タグと同様にパラメータウィンドウの上のアイコンからコメントを付けます
コメントがつくと、オペレータの右上にふきだしマークが出て、それをクリックするとミドルクリックをした時と同様にオペレータのインフォが表示されます。

コメントもタグと同様にOP Find DATなどで検索を行えます。

```python:python
# 取得
op('').comment 

# 書き込み
op('').comment  = 'コメントだよー'
```

### 使用例
https://github.com/Joe0hara/MakeDocumentFromTD

## カラー

オペレータの箱事態に色を付けることができます
![color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/65e64154-0bb4-6434-5441-897c5978c37a.png)
（左：黄色、右：デフォルト）

エディタ上で`c`を押すと左下にカラーパレットが表示されます。
色の付けたいオペレータを選択してからパレットの任意の色をクリックすることでオペレータに色を付けることができます。

```python:python
# RGB range(0.0~1.0)

# Get
op('').color # -> tuple(r, g, b)  

# Set
op('').color = tuple(r, g, b)
```

パっと見でエディタ上で分かりやすくなる

## Help Document & OP Snippets
![op_menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/a02be6d9-1078-45b6-166a-179110830cb7.png)
オペレータを右クリックして、`Help...`をクリックするとオペレータのドキュメントが開かれ、`Python Help...`をクリックするとそのオペレータのPythonのドキュメントにとびます

![para.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/08eaaf37-57d3-4b53-ca93-705141811e06.png)

パラメータウィンドウの`？`アイコンからも飛ぶことができます

# Non Default Value

パラメータウィンドウの右上の丸いアイコンをクリックすると、デフォルトでないパラメータのみが表示されます
![para_non_default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175399/7b09af7f-3929-61fb-44c6-f683456b8946.png)


## 最後に

なんか短くて申し訳ないです、、
もっと便利なのとか、これはこうやって使うといいよ！みたいなのあったら教えてください！
Go言語のエラーパッケージ aerrors をつくった

Go言語のエラーパッケージ `aerrors` をつくりました。

## モチベーション

- 型っぽく使えるエラーがほしい
- デフォルトで呼び出し元情報がほしい
- 気軽にラップしたい
- いい感じにログに書き出したい

## 使い方

基本は既存のパッケージと同じ用に使用することができます。

`errors.New` 風に

```go
err := aerrors.New("new error")

fmt.Println(err)
// Output:
// new error
```

`fmt.Errorf` 風に

```go
err := aerrors.Errorf("error: %d", 42)

fmt.Println(err)
// Output:
// error: 42
```

`aerrors` はスタンダードライブラリのエラーに加えてより詳細な情報を保持しています。
デフォルトでエラーレベルと呼び出し元の情報を保持しています。

```go
err := aerrors.New("new error")

fmt.Printf("%+v", err)
// Output:
// new error:
//     priority: Error
//     callers: main.main:example/main.go:10
```

オプションでエラーレベルを変更することができます。

```go
err := aerrors.New("new error", aerrors.Priority(aerrors.Info))

fmt.Printf("%+v", err)
// Output:
// new error:
//     priority: Info
//     callers: main.main:example/main.go:10
```

また、より詳細な情報を追加することも可能です。

```go
err := aerrors.New("new error").WithValue(
  aerrors.String("foo", "Foo"),
  aerrors.Int("number", 42)
)

fmt.Printf("%+v", err)
// Output:
// new error:
//     priority: Error
//     callers: main.main:example/main.go:10
//     foo: Foo
//     number: 42
```

さらに、エラーを拡張して新たなエラーを作成することができます。
拡張したエラーは `errors.Is` 関数で真となるため、独自のエラー型のように扱うことも可能です。

```go
appError := aerrors.New("app error")
err := appError.New("oops")

fmt.Println(err)
fmt.Printf("is parent: %v", errors.Is(err, appError))
fmt.Printf("parent: %v", err.Parent())
// Output:
// oops
// is parent: true
// parent: app error
```

`fmt.Errorf` と同様に既存のエラーをラップすることも可能です。

```go
appError := appError := aerrors.New("application error")
err := appError.Errorf("error: %w", errors.New("oops"))

fmt.Println(err)
// Output:
// error: oops:
//     priority: Error
//     parent: application error
//     origin: oops
//     callers: main.main:example/main.go:12
//   - oops
```

詳しくは [Godoc](https://godoc.org/github.com/kamiaka/aerrors) または [ソース(Github)](https://github.com/kamiaka/aerrors) をご覧ください。
railsテスト駆動する理由

railsのテスト駆動に関する参考になった記事があるので共有
https://teratail.com/questions/121833?link=qa_related_pc_sidebar


テストをする理由は今のコードと自分の認識を一致させることだったということ。




```user_test.rb


class UserTest < ActiveSupport::TestCass
  test "nameの長さは50文字以内である事" do
    # エラーを起こすために、わざと51文字を設定する
    @user.name = "a" * 51

    # もし、正しくバリデーションが設定されていたら、
    # バリデーションがfalseになるはず
    # assert_notは引数の結果がfalseに時にテストが成功する
    assert_not @user.valid?
  end

  test "emailの長さは255文字以内である事" do
    # エラーを起こすために、わざと255文字を超える文字列を設定
    # "a" * 256だけでもいいでしょう
    @user.email = "a" * 244 + "@example.com"

    assert_not @user.valid?
  end

end
```
assert_notはassert_notは引数の結果がfalseの時にテストが成功とする命令
つまり現時点でバリテーションがかかれていないため、@user.validがtrueとなるため、テストは失敗。
今のコードと自分の認識はあっていたということになる。
じゃあバリテーションを書こう。
こうなるわけなのか。。。なるほど。
テストって意味あるの？って疑問だったが、効率良く開発を進めていく上で必要不可欠なんだと理解した。

(1) 仕様を先に決める(頭の中だけでもいいし、紙に書いたりしてもいい)
(2) 仕様をテストとして記述する
(3) 仕様を満たすために実装する

このステップが大事なんですね。
めちゃめちゃ参考になりました。テストの書き方とかも勉強しないとな
UFT OneのAIベースドテストを導入・使用する

# はじめに

UFT OneにはAiベースドテストという機能があります。
これを導入するための方法を書いていきます。

## 環境

下記の環境を使用していきます。
UFT OneはすでにWindowsにインストール済みとします。

|            | Version     |
|:-----------|:-----------:|
| UFT One    | 15.0.1      |
| Windows    | 10          |

#AIベースドテスト
## 導入方法

下記のページから「UFT_One_15.0.1_DVD.zip」をダウンロードしてください。
AIベースドテストはDVD版にしか入っていないようなので、注意が必要です。
https://pdapi-web-pro.microfocus.com/mysoftware/index

UFT_One_15.0.1_DVD.zipを解凍したら、「AI\setup.exe」を実行してください。
インストールが完了したら、UFT One実行時に「Web」のアドインにチェックを入れて起動をします。

これで導入は完了です！

## 必要な設定

導入したいあとは下記の設定を行ってください。

1. ツール > オプション > GUIテスト > AIの「AIのアクティブ」にチェックを入れます
![AIアクティブ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/4ee5a43f-4e96-d9fa-2284-b8b738a08029.png)
2. Windowsの設定でディスプレイ > 拡大縮小とレイアウトの「テキスト、アプリ、その他の項目サイズを変更する」を100％に設定します
3.Webブラウザのオブジェクトリポジトリを保存していきます。
  - 記録と実行設定のメニューを開き、Webタブの中の「記録または実行時に以下を開く」にチェックを入れる
  - 「ブラウザ」で使用したいブラウザを選択する
  - 記録を実行し、オブジェクトを保存する
 ![記録と実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121319/2636c116-009e-4f4c-6ecf-17e673e73c4f.png)

##テストを実行する

テストを実行は下記の手順です。

1. テストコードの先頭に下記のコードを記述する

```VBS:sample 
AIUtil.SetContext Browser("保存したリポジトリ名")
```
2. AIメニューを選択して、AI識別ビューを開く
3. 操作したいブラウザをクリックするとオブジェクトの識別が始まり、識別が終了するとオブジェクトが枠で囲われて表示されます。
4. 操作したいオブジェクトをテストコード上にドラッグアンドドロップ
5. テストを実行する

以上でAIベースドテストの導入と使用ができます！
意外と簡単に試せちゃいます。
cypressを使ったE2Eテストを実装してみた

APIとの連携を非同期（Ajax）でたくさん行うSPAのページを制作したときに、cypressを使ったE2Eテストを導入してみました。
今回は、そのときに対応してみて、非同期（Ajax）通信周りのテストがやりやすかったので、そのことを書いてみようと思います。

# はじめに
cypressのインストール方法や使い方は、公式サイトがとてもわかりやすいので公式サイトを見てください。
実装した当時のバージョンは4系で `route` 関数を使っていますが、最新バージョンでは非推奨となり `intercept` 関数に変わっているので気を付けてください。

- [公式サイト - cypress.io](https://www.cypress.io/)
- [ドキュメント](https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshell)

# 最初に用意した設定
まず、ローカル、開発環境、テスト環境、本番環境みたいに環境が複数あったので、各環境を `npm-scripts` で引数を渡して、環境ごとに設定を変えられるようにしました。

## 設定方法
通常、基本的な設定は `cypress.json` に書きますが、cypressはデフォルトで引数を受け取れるようにしてくれてます。
さらに `plugins` に書かれた処理は、cypressが実行される前に行われるので、ここで基本設定を上書きすることにしました。

ベースとなる設定は、通常通りに `cypress.json` に書いておきます。

```json:cypress.json
{
  "baseUrl": "https://www.example.jp"
}
```

つぎに `plugins/index.js` で受け取った引数によって設定を上書きする処理を書きます。
今回は `type=環境名` みたいにする想定で書いてみます。

```js:plugins/index.js
module.exports = (on, config) => {
  switch (config.env.type) {
    'dev':
      config.baseUrl = 'https://develop.example.jp'
      break
    'local':
      config.baseUrl = 'http://localhost:3000'
      break
  }
  return config;
};
```

こんな感じ
あとは `npm-scripts` で、cypressを立ち上げるコマンド `cypress open` を追加して

```
npm run cypress:open -- --type dev
```

こんな感じで実行すれば、環境ごとに設定を変更して、cypressを実行することができるようになります。

# APIとの連携テスト

では、APIとの連携テストを書いていきます。

## 非同期（Ajax）通信のレスポンスを上書きする
たとえば、APIとの連携でエラーが起きたときのテストをする場合、エラー用のレスポンスが返ってくるように強制的に上書きして、想定通りの動きになるかを確認します。

```js
// apiのパス
const apiPath = '/api/test';

// 上書きするレスポンスのJSON
const response = {
  isSuccess: false,
  errorMessage: '〇〇が正しくないよ'
};

// ステータスを400に設定
const options = {
  status: 400
};

// routeを使って上書き
cy.route('POST', apiPath, response, options)
```

こんな感じで `route` を使うと上書きすることができます。
あとは、ちゃんとエラー処理が正しく行われたかのテストも追加すればエラーのテストが完成です。

## 非同期（Ajax）通信でリクエストしたPOST情報を確認
レスポンスもいじったら、今度は、リクエストも正しいか一緒に確認したいなと思って、POST情報も確認するようにしました。

例）
POSTのname値にhogeがあり かつ value値は文字列のfugaであるか確認する

```js
// /api/testにPOSTされる内容を確認するためrouteで設定
// この通信に対してasで名前を付けておく
cy.route('POST', '/api/test').as('apitest')

// 名前をつけたapitestの通信情報を確認
cy.wait('@apitest')
  .then((xhr) => {
    // POSTのname値にhogeがあり かつ value値は文字列のfugaであるか確認
    cy.wrap(xhr.request.body).its('hoge').should('eq', 'fuga')
  })
```

こんな感じで確認するテストコードを追加しました。
で、たとえば入力エリアがあって、その入力した値が正しくPOSTされているかを確認するときは、この処理の前に入力処理を書いて、そこで入力した値とPOSTされた内容があっているかを確認すればいいと思います。

# まとめ
SPAのページとかを制作するとき、APIの結果によってページが変わったり、エラー処理がすごく複雑だったりすることがありますが、cypressを使うとブラウザで表示されたページを見ながらテストができるので、気づかなかったミスにも気づけたりして、導入してよかったと思いました。
あと、ほかにも、画面キャプチャやテスト中の画面を動画で保存することなどもあるので、興味を持った方は、さわってみてはいかがでしょうか。

---
[:christmas_tree: FORK Advent Calendar 2020](/advent-calendar/2020/fork)
:arrow_left: 23日目 [技術書 2020](/dashimakitamago/items/9baec545c54c74ccfd5d) @dashimakitamago
:arrow_right: 25日目 [PayPay for Developersやってみた](/ono_t/items/687cab44e4f0c2d4e10e) @ono_t
Javaの "IncompatibleClassChangeError: Found class ... , but interface was expected" というエラー

大学のJavaの課題をやっていて、インターフェースを抽象クラスに書き直した際に遭遇したエラーです。

##ディレクトリ

```ディレクトリ
.
├── Main.java
├── Main.class
├── A.java
├── A.class
├── B.java
└── B.class
```

Aがインターフェース、BがAを実装したクラス、Mainが動作確認用のクラスです。
この後、Aをインターフェースではなく抽象クラスに書き直してコンパイルし、実行しようとしました。

```
$javac Main.java
$java Main
```
すると次のようなエラーが出ました。

```
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found class A, but interface was expected
```

このエラー文を和訳すると「Aというクラスは見つかったけど、それはインターフェースじゃないとダメだよ」となります。そしてIncompatibleClassChangeErrorというのは

> クラス定義に互換性のない変更があった場合にスローされます。現在実行中のメソッドが依存しているクラスの定義が、実行開始後に変更されています。
　(Java(tm) Platform, Standard Edition 8 API仕様　から引用)


##解決方法
A.class, B.class, Main.class の3つのファイルを削除しコンパイルするとうまく実行できました。
python3.5 > site-packagesを消してしまった時の対応

# python3.5>site-packagesを消してしまった時の対応

モジュールが消えてしまうので、No modue named～が出るようになる
pip3.5はそのまま残っているが、そのまま
`pip3.5 install ～`
などと実行しても

>No module named ‘pkg_resources’

と出てしまいだめ

## ■easy installを使う
`wget https://pypi.python.org/packages/source/d/distribute/distribute-0.7.3.zip`
`unzip distribute-0.7.3.zip && cd distribute-0.7.3`
`mkdir /usr/lib/python3.5/site-packages`
`python3 setup.py install`
`easy_install pip`

これでpipを使うことができる
rails マイグレーションファイルあれこれ

```rails generate model User name:string email:string```

Userのモデルをnameはstring型で、emailはstring型で作成という意味。
今までrails g model User のみをターミナルで入力してマイグレーションファイルをいじっていたので、このやり方は時短になるなあとおもった

以下マイグレーションファイル

```XXXXXXXXXXXXX_create_users.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end
```

changeメゾットはcreate_tableというrailsのメゾットを呼び出し
create_tableメソッドはブロック変数を1つ持つブロックを受け取り,ここでは（“table”の頭文字を取って）t
ブロックの最後の行t.timestampsは特別なコマンドで
created_atとupdated_atという２つの「マジックカラム（Magic Columns）」を作成

``$ rails db:migrate
``
でマイグレーションファイルが実行される。
実行されたマイグレーションファイルはいじっても更新されない
マイグレーションファイルが実行される前に戻りたいときは
``$ rails db:rollback``
このコマンドで戻すことができる
自分が使ってるパブリックIPアドレスをコマンドで一発表示

#自分が使ってるパブリックIPアドレスをコマンドで一発表示

面白くも便利な情報を見つけたので備忘録。
<br />

1. コマンドプロンプトを開いてコマンド`nslookup myip.opendns.com resolver1.opendns.com`を実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/f13b91b7-223b-8974-0d7b-aa723a494250.png)


1. 以下のように、自分のPCが現在使用しているパブリックIPアドレスが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/9d63abdf-4acd-a9c1-dd2f-e306b7f33a1e.png)



1. 確認作業。
[CMAN.JPのサイト](https://www.cman.jp/network/support/go_access.cgi) を表示してみる。
たしかに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/0376fcf3-9883-4998-d61a-8cbf8d4f0d21.png)


<br />
Firebaseでfunctionsの関数をdeploy時にasyncのエラー

#  firebaseでデプロイ時にfuncionsへ関数のデプロイに失敗

エラー文

```
Function failed on loading user code. Error message: Code in file lib/index.js can't be loaded.
Is there a syntax error in your code?
Detailed stack trace: /srv/node_modules/@google-cloud/firestore/build/src/collection-group.js:54
    async *getPartitions(desiredPartitionCount) {
          ^

SyntaxError: Unexpected token *
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:617:28)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/srv/node_modules/@google-cloud/firestore/build/src/index.js:39:28)

⚠  functions: Warning: Node.js 8 functions are deprecated and will stop running on 2021-03-15. Please upgrade to Node.js 10 or greater by adding an entry like this to your package.json:
    
    {
      "engines": {
        "node": "12"
      }
    }

The Firebase CLI will stop deploying Node.js 8 functions in new versions beginning 2020-12-15, and deploys from all CLI versions will halt on 2021-02-15. For additional information, see: https://firebase.google.com/support/faq#functions-runtime



Functions deploy had errors with the following functions:
	addDataset


To try redeploying those functions, run:
    firebase deploy --only "functions:addDataset"


To continue deploying other features (such as database), run:
    firebase deploy --except functions

Error: Functions did not deploy properly.
```

async *getPartitions(desiredPartitionCount) 
非同期通信の関数データ付近でエラーが起きているとわかった。

# エラー対処方法

functionsのpackage.jsonの中身を

```
"dependencies": {
    "firebase-admin": "^9.2.0",
    "firebase-functions": "^3.11.0"
  },
  "devDependencies": {
     "@typescript-eslint/eslint-plugin": "^3.9.1",
    "@typescript-eslint/parser": "^3.8.0",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "^2.22.0",
    "typescript": "^3.8.0",
    "firebase-functions-test": "^0.2.0"
  },
```

から

```

"dependencies": {
    "firebase-admin": "^8.6.0",
    "firebase-functions": "^3.3.0"
  },
  "devDependencies": {
    "tslint": "^5.12.0",
    "typescript": "^3.2.2",
    "firebase-functions-test": "^0.1.6"

```

へ
削除及び修正し変更。

eslintと相性があわなかったのかもっと予想・・・。
Typescriptに詳しくないので、詳しいことがわかりません。

# ヒントになった参考記事
https://stackoverflow.com/questions/64575650/firebase-functions-error-after-update-what-can-i-do


以上となります。


ここは違う、ここはこうしたほうがいいかも？
等々ございましたら、ご指摘いただけますと幸いです。

最後までみていただきありがとうございます。
コンソールでDelayed::Jobを実行する手順

ローカル開発中にたまに使うときに忘れがちなので備忘録として。


以下でキューに入ったjobを実行可能

```Ruby
Delayed::Job.find(x).invoke_job
```

実行した後はレコード削除

```Ruby
Delayed::Job.find(x).destroy
```

以上、
LINE Notifyのトークンを取得方法・備忘録

## LINE Notifyとは
APIにより連携することで、外部Webサービスやアプリケーションなどからの通知をLINEアカウントのメッセージを通じてユーザーに配信できるサービスです。

毎度取得手順を忘れるので備忘録として残します。
手順等に間違いがございましたら、ご教示よろしくお願いいたします🙇‍♀️

## 準備物
LINEアカウント

## アクセストークン取得手順
①下記にアクセス
https://notify-bot.line.me/ja/

②ログイン→マイページ
![IMG_4285.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/5e6237ca-fc38-e300-14d8-4948b401b623.png)

![IMG_4286.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/79928e12-6732-6958-3864-0ed3e65a980c.png)

③トークンを発行を押下します。
![IMG_4287.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/cf0868f1-534f-2009-461d-d7acc080088f.png)

④トークンを発行する、にてトークン名と通知を送信するトークルームを選択、発行するを押下します。
　ex: トークン名→明日の予定 通知を送信するトークルームを選択
![IMG_4289.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/50aa5678-9b37-4b43-5f1a-e2621a9d43d6.png)

⑤トークンが発行されるため、必ずコピーをします。
![IMG_4290.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/9e291332-d3b2-2efc-1a82-8d08da95b898.png)

## 本当にトークンが取得されたかの確認します。
①アクセストークンの発行(開発者向け)の下にある[LINE Nortify API Document](https://notify-bot.line.me/doc/ja/#:~:text=%24%20curl%20%2DX%20POST%20%2DH%20'Authorization%3A%20Bearer%20%3Caccess_token%3E'%20%2DF%20'message%3Dfoobar'%20%5C)にて以下、発行されたか確認ができるcurlコマンドがあります。ちゃんと発行がされていれば自分のLINEに通知が届くので、ターミナルでコマンドを入力。
![スクリーンショット 2020-12-07 15.04.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/4838ac83-e140-c1ef-b09b-2d73b72516fc.png)

```
curl -X POST -H "Authorization: Bearer 発行したアクセストークンをペースト" -F "message=ABC" https://notify-api.line.me/api/notify
```

② LINEにてアクセストークンが発行されたことを確認できます。(トークン名:テスト)
確認できたらトークンの取得成功です。
![IMG_4313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453711/aff1bab1-ecd8-4d38-6b25-366b57808e43.png)
【メモ】intellij go.modから依存関係を同期する

##　対応
ダブルクリックすると赤い電球出てくるのでそこを押して、
Sync dependencies of xxxxx をクリックすると同期してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270608/9396190c-715a-f261-2471-67a06e15bc8a.png)

## 参考
https://pleiades.io/help/go/create-a-project-with-go-modules-integration.html#working-with-go-modules
OpenCVplusUnity 画像を回転させる(アフィン変換処理)

#はじめに
この記事ではOpenCVplusUnity(無料)を使用しています。
Unityで生画像を保存する際に回転させたいなんて時があると思います。RendereTextreでこねくり回したり、ピクセル取り出して処理することもできるかと思いますが面倒です。大人しくそんな時はOpenCVを使いましょう。楽です。


今回はこの結果を目指します。Texture2Dを右回転、左回転に処理します。
![スクリーンショット 2020-12-06 13.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508103/a73e270f-4a60-155b-0f2d-a7d2b7071103.png)
といっても、することはPythonで使用する時と変わりません。
Texture2DをMatへ変換して回転変換を加えて再びTexture2Dへ返しているだけです。






#実装方法

```OpenCVManager.cs
using UnityEngine;
using OpenCvSharp;

public class OpenCVManager
{
    /// <summary>
    /// Texture2Dを90度アフィン変換処理 true:右回転 false:左回転
    /// </summary>
    public static Texture2D RotateAndResize(Texture2D tex, bool isRight)
    {
        Mat origin = OpenCvSharp.Unity.TextureToMat(tex);
        Mat dest = new Mat();

        //cpu生画像を想定。横長画像前提
        var center = new Point2f(origin.Cols / 2, origin.Cols / 2);
        Mat rMat = Cv2.GetRotationMatrix2D(center, 90, 1);
        Cv2.WarpAffine(origin, dest, rMat, new Size(origin.Rows, origin.Cols));

        if (isRight)
        {
            Cv2.Flip(dest, dest, FlipMode.XY);
        }

        return OpenCvSharp.Unity.MatToTexture(dest);
    }
}

```

#まとめ
余談ですが、iOSアーカイブの予定のある方は最初からOpenCVforUnityを購入をお勧めします。bitcodeエラーから抜けれず、ビルドできてipaはできているのにアーカイブできない理由が分からず調べ続ける羽目になり、最終的に全移行することになります。

もちろんOpenCVをネイティブプラグインで全て自分で繋込めれば問題ないですが労力が見合ってません。外部ライブラリを使用した際は、アーカイブまで確認しろと教えられた良い教訓でした。


#エラー内容について
OpenCVPlusUnityではアーキテクチャarm64が含まれていないエラーでアーカイブができません。
iPhone5s以降はarm64なので必須です。
![スクリーンショット 2020-12-13 12.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508103/4f265fe5-d1d1-b0d2-65d2-d8c69427e752.png)


staticライブラリのビルド時の簡易な設定なので対応待ち？ということは考えにくいので無償版はここまでという認識です。


Appleのアーキテクチャ、bitcodeについてわかりやすくまとめてくださっている記事【@taki4227様】
https://qiita.com/taki4227/items/db9b503e56ab25a8a375