OmniAICreator/Qiita-1.07M huggingface dataset:
RailsのtransactionメソッドとSQL

よく忘れるので、ここにメモします。

### 戻り値

ブロックの戻り値が`transaction`メソッドの戻り値になります。

```ruby
val = ActiveRecord::Base.transaction do  # BEGIN
  user.save!
  true
end # COMMIT

val #=> true
```

### 例外でROLLBACK

ブロック中で例外が発生すると、ROLLBACKが行われ、例外が再送出されます。

```ruby
ActiveRecord::Base.transaction do # BEGIN
  user1.save!  # 実行される（ROLLBACKで戻る）
  raise "foo"  # ROLLBACK
  user2.save!  # 実行されない
end
do_something # 実行されない
```

### 例外 ActiveRecord::Rollback

ただし、例外が`ActiveRecord::Rollback`の場合は、ROLLBACKが行われたあとで、例外は再送出されず、`transaction`メソッドが完了します。この場合の戻り値は`nil`になります。

```ruby
ActiveRecord::Base.transaction do # BEGIN
  user1.save!  # 実行される（ROLLBACKで戻る）
  raise ActiveRecord::Rollback # ROLLBACK
  user2.save!  # 実行されない
end
do_something # 実行される
```

### 行ロックを使う

行ロック（SELECT FOR UPDATE）を使いたい場合は、ブロック中で`lock`メソッドを使ってレコードを取り出します。前に実行中のトランザクションがあれば、`lock`メソッドのところで待ち状態になります。COMMITまたはROLLBACKでロックが解除され、待ち状態だったトランザクションが再開されます。

```ruby
ActiveRecord::Base.transaction do # BEGIN
  # SELECT ... FOR UPDATE
  # 前に実行中のトランザクションがあればロック解除待ち、
  # なければクエリー実行
  user = User.lock.find(123) 
  user.save!
end  # COMMIT、ロック解除
```

### 行ロックを使い、ほかの読み込みを待たせる

SELECT FOR UPDATEはトランザクションの外でも使えます。あるレコードの保存作業中にはそのレコードを読み込みさせたくない、というときに使えます。Aの開始直後にBが実行されると、AがコミットされるまでBのfindは待ち続けます（PostgreSQLとMySQLで確認済み）。

```ruby:A.レコードを保存しようとしているタスク
ActiveRecord::Base.transaction do # BEGIN
  user = User.lock.find(123) # SELECT ... FOR UPDATE
  user.save!
end  # COMMIT、ロック解除
```

```ruby:B.レコードを読もうとしているタスク
user = User.lock.find(123) # SELECT ... FOR UPDATE
```

（ただし、この挙動はautocommitフラグなど条件によって変わるもよう。いつか調べたい。）
ブロックレベル要素とインライン要素の復習

# 投稿の経緯

```haml
.header
  .header__logo
    SNS
.contents
  .contents__message
    follow me!
  .contents__btn
    Facebook
  .contents__btn
    Twitter
  .contents__btn
    Instagram

```
ブラウザ上の表示
https://gyazo.com/53414efdd750bf9a52eb1817659c0cb7

それぞれのsnsページにアクセスできるようにするため、link_toメソッドでリンクを記述した。

```haml
.header
  .header__logo
    SNS
.contents
  .contents__message
    follow me!
  =link_to "https://www.facebook.com/", class: "contents__btn" do
    Facebook
  =link_to "https://twitter.com/", class: "contents__btn" do
    Twitter
  =link_to "https://www.instagram.com/", class: "contents__btn" do
    Instagram
```
ブラウザ上の表示
https://gyazo.com/3f15a37d10b8714942d450193a8de4b7

この時、なぜ、縦に並んでいたSNSへのリンクが横並びになったのかが分からなかった。
そのため、ブロックレベル要素とインライン要素について調べてみた。

#ブロックレベル要素とインライン要素について
##ブロックレベル要素とは
　一つの**ブロック（かたまり）**としての要素のこと(ex. divタグ、h1~h2タグ、pタグ、liタグ、ulタグなど)。ブラウザ上では**前後に改行が入るため、縦から順番に要素が並ぶ。また、cssで高さや横幅の指定を自由にすることができる。もしも指定をしていなければ、画面の幅と同じ幅になる。**

##インライン要素とは
　ブロックレベル要素の中の**一部分**として認識される要素のことをいう(ex. aタグ、imgタグ、brタグなど)。ブラウザでは**前後に改行は入らず、ブロックの一部として表示される。また、インライン要素の横幅は、文字の記述量や画像の大きさなどで、要素の高さや幅が変化するため、cssで自由に要素の高さや幅の指定をすることができない。
テキストとして要素を表示させたい時は、spanタグを使うと前後に改行が入らない。

#解決

今回、縦に並んでいたSNSへのリンクが横並びになった理由は、それぞれのブロック要素をlink_toメソッドに書き換えたからである。link_toメソッドを使うと、ブラウザ上では、インライン要素であるaタグ変換される。


＜参考文献＞
・http://www.htmq.com/htmlkihon/005.shtml
・https://webst8.com/blog/css-display/#liinline-block
[Swift]UITextViewにplaceholderを簡単に導入するKMPlaceholderTextViewについて

#はじめに

デフォルトではUITextViewにplaceholderを設定できないのですが、それを簡単に設定できるライブラリの
KMPlaceholderTextViewを使ってみたところ、一部詰まったところがあったので
記事にまとめました。


#完成品

<img width="382" alt="スクリーンショット 2019-08-06 14.15.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303227/b7749baa-1cfe-f9c5-37bb-d7b0e125f78e.png">
このようになります。

#ライブラリのインストール

今回インストールするのは[KMPlaceholderTextView](https://github.com/MoZhouqi/KMPlaceholderTextView)になります。
ライブラリの導入方法がわからない方は[こちら](https://codezine.jp/article/detail/10677
)がわかりやすいかと思います。

#詰まったところ

[KMPlaceholderTextView](https://github.com/MoZhouqi/KMPlaceholderTextView)
こちらのリンク先にあるgifでのやり方で導入しようとすると、ストーリーボードに設置したUITextViewのCustom ClassのClassにKMPlaceholderTextViewを入れてもmoduleのところにKMPlaceholderTextViewが自動で入らず、またplaceholderを入力する画面もでてきません。

#解決策

まずストーリーボードにUITextViewを配置する。
↓
UITextViewのCustom ClassのClassとmoduleのところに手動でKMPlaceholderTextViewと入力する。
↓
UITextViewをIBOutletでファイルにつなぎ、`UITextView.placeholder="ここにplaceholderのテキストを書く"`のように記述する。


#例

```
import UIKit
import KMPlaceholderTextView

class ViewController: UIViewController {
    
    @IBOutlet weak var textView: KMPlaceholderTextView!

    override func viewDidLoad() {
        super.viewDidLoad()
        textView.placeholder = "ここにplaceholderのテキストを書く"
       
    }
    }
```



#最後に

最後まで読んでくださりありがとうございました。
もしどなたかの為になれれば、幸いです！！
Tensorflow Liteを使ってAndroidで物体検出するメモ

###AndroidでTensorflowLiteを実行するAPKの作成手順

####Tendsorflowのexamplesをダウンロード
git clone https://github.com/tensorflow/examples.git

####以下フォルダをAndroidProjectのフォルダにコピー
examples-master\lite\examples\object_detection\android

####AndroidStudioで上記フォルダを開き、ビルドする
　※表示される項目への対処を実施していけばエラーなくビルドできる

####アプリをインストールする
apkファイルをスマホへインストール

####・独自のモデルを使う場合
以下にモデルとラベルデータを保存
app\src\main\assets

以下を修正
app\build.gradle
40行目：apply from:'download_model.gradle'をコメントアウトする

####・表示されるアプリ名を変更する場合
以下を修正
app\src\main\res\values\base-strings.xml
2行目：<string name="activity_name_detection">TFL Detect</string>
pythonのmax関数

codewars 8kyuのExpression matterを解いた時に重要だったmax関数について解説していきたいと思います。

この問題は、expressionsMatterという関数を作り、
a,b,cにどの数字が入ってもその数値が最大になるような式を考えないといけない問題です。
例えば、a、b、c全てに１が代入されたとします。
この場合a+b+cだと３、a*b*cだと１ですよね？
そのため、足し算の式がアウトプットされるようにします。
しかし、a,b,cに１０が入ると、掛け算の方が数値が大きくなりますよね。
数値によって最大値が変わってしまいます。
では、どのようなcodeを書けば最大値だけを求められるのでしょうか？



##max関数
```
def expressionsMatter(a,b,c)
    return　max(a+b+c,a*b*c,a*(b+c),(a+b)*c)
```

このようにcodeを書けば、どの数値がa,b,cに入っても最大値が求められます。
ここで重要なのが、max関数でカッコの中に全ての式のパターンを書くことです。

ここで注意なのが、returnを何回も使わないということです。
returnは関数内の処理を終了させる性質を持っているので、１番最初のreturn文しか機能しません.
そのため、いくつもカッコ内の式があるからといって、

```
return(a+b+c)
return(a*b*c)
...
```
といくつもreturn文を書かないようにしましょう。

以上になります。
processing で画像や動画を読み込むときいつもデータをスケッチに入れなくてもいい

画像や動画などをprocessingでいじるのが面白くていろいろ作ってたらPCの容量がパンクしました。


loadImage("ファイルの名前");

で読み込むのだけれど、この指定するファイルをスケッチに追加しないといけないと思っていたけど、いちいち追加しなくても好きな位置にあるファイルを持ってこれることがわかった


"ファイル名"のところを絶対パスにすればよかった。


Macならばターミナル開いて絶対パス調べたいファイルを放り投げるとすぐにパスがわかり、いちいち動画を追加する必要がなくなった。



いろいろprocessingの本を買いあさっているがProcessing3による画像処理とグラフィックスが画像特化で持ってて損はない感じだった
Djangoでプロジェクトを作ってみた



##まずは仮想環境の準備
Djangoをインストールし、プロジェクトを立ち上げるために、まずはDjangoをインストールする仮想環境を準備します。

仮想環境を準備するために、まずはAnacondaというPythonのディストリビューション、簡単言うとPythonとそのパッケージを簡単に利用できるソフトをインストールします。

###Anacondaのインストール
Anaconodaインストールは、非常に簡単で、Anacondaのホームページからインストールできます。
Anacondaをインストールしたら、Anaconda Navigatorというものを開きます。
その後、Anaconda　Navigatorのホーム画面にある、「Environment」をクリックし、その下に出てくる「Create」をクリックします。
「Create」は、仮想環境を立ち上げるためのアイコンです。
必要事項を入力して、仮想環境を立ち上げたら、その仮想環境上でDjangoをインストールします。

##仮想環境上でプロジェクトを立ち上げる

###Djangoのインストール
Djangoのインストールをするためには、まずターミナルを立ち上げます。
Windowsの場合は、コマンドプロンプトかPower Shellです。

・Djangoのインストール

```
pip install django
```

###Spyderのインストール
Spyderは、Anaconda Navigatorのホーム画面にあるので、そこで「Install」→「Launch」をクリックします。
Spyderは、コードが書かれたテキストファイルなどのたくさんのファイルをまとめて管理するためのアプリです。

###Spyderで新規プロジェクトを作り、ファイルを追加する
Spyderを開いたら、ウィンドウにある「プロジェクト」メニューから、「新規作成」をクリックします。
するとプロジェクトが作成されるので、そこで「新規ファイル」をクリックしてファイルを作成してそのファイルを保存します。
これで、プロジェクトができ、その中にファイルを追加することができました。
Excel便利add-inの作り方

# Excelアドインについて


####アドインは、一般的にはプログラムに拡張した機能を追加するもの
エクセルに独自の機能追加するものがエクセルアドインになります。

Excelのアドインファイルは、拡張子が.xlam（2003までは.xla）のファイルです。
このアドインファイルをエクセルに登録することでアドインの機能が使えるようになります。

# アドインファイルのフォルダ

Excelアドインの既定のフォルダは、
C:\Users\ユーザー\AppData\Roaming\Microsoft\AddIns
まぁ基本的にはエクセルからアクセスできればなんでもいい。


# add-inを作ろう。
プロシージャーでのVBAの記述について
最初は通常の「Excel マクロ有効ブック(*.xlsm」で作成します。
アドインとして呼び出すプロシージャーは、外部で使える必要がありますので、
Sub
Public Sub
Function
Public Function
このように、スコープがPublicになるようにします。

アドインの機能を呼び出す方法は何通りもあります。

・リボン「開発」→「マクロ」→「実行」
・リボンのアイコンをクリック
・ユーザー定義関数


https://excel-ubara.com/excelvba4/EXCEL297.html
【新人向け】Gitはじめの一歩

- 新人教育の際に突貫で作った記事です。
- 超ざっくり概念とセットアップだけ。

## Gitとは

- version管理のツール
  - versionとは:
    - ソースコードの変更の履歴。ある状態からの変更した内容をベースに履歴を残す。
    - 個人開発でも自分のした変更履歴が残るのは便利だし、チーム開発でも誰のソースコードが反映されているのか、最新はなにかがわかって便利
      - 現在の開発ではほぼ必須

- プロジェクト単位でgit管理する
  - なので最初にプロジェクトを建てるときに `git init` コマンドを実行する

### 参考

- [【Git】オレならこう説明する！Git初心者への用語説明 - Qiita](https://qiita.com/nnahito/items/e546b27f73e7be131d4e)

## GitHubとは

- https://github.com/
- チームでソースコードを管理するためのメジャーなWebサービス。
  - gitだけでも管理はできるみたいだけれど、チーム開発をするときはGitHubを使うのがデファクトスタンダード。
  - この人の変更を許可する、とか 変更しようとしている箇所にコメントを入れて議論したりできる。

### 参考

- [今日からはじめるGitHub 〜 初心者がGitをインストールして、プルリクできるようになるまでを解説 - エンジニアHub｜若手Webエンジニアのキャリアを考える！](https://employment.en-japan.com/engineerhub/entry/2017/01/31/110000)


## set-up

### 1. git configに基本情報を入力

- itermを開く (もしiterm入れてなければターミナルで)
- gitの初期設定のため以下のコマンドを入力
  - globalのオプションがついてるのでPC全体に反映される

```
$ git config --global user.name "your_name"
$ git config --global user.email your_email_address@example.com
```

- 参考：この記事通りにやれば会社用と自分用を楽に分けられるらしい
- [[git] gitconfigで会社用アカウントと個人用アカウントを楽に使い分けする - Qiita](https://qiita.com/SugarShootingStar/items/64f239f89d25a3b9f520)

### 2. GitHub

- 以下記事の 「1.5 登録完了メール」のところまでやる

- [GitHubアカウント作成とリポジトリの作成手順 - Qiita](https://qiita.com/kooohei/items/361da3c9dbb6e0c7946b)

### 3. 使い方デモ

#### 1. GitHubでリポジトリを作成 (リポジトリ = ソースコードを格納するフォルダ, プロジェクト作成と同義)

- GitHubにアクセス、ログイン
- `+ New repository` をクリック
- 好きなリポジトリ名(例: `git_trial`)で作成
- public(誰でもソースコードを見れる,公開設定)を選択, Create repository

#### 2. ローカル(使ってるmac上)にリポジトリを持ってくる

- clone(GitHubのリポジトリのコピー)します。
  - ＊通信方式はhttpsとsshを選べて、簡単なのはhttps, よりセキュアなのはssh
  - 業務ではssh使うけれど間瀬が個人で練習とかするときはhttps使ってます

- httpsの場合
  - ローカル環境で、ターミナルを開く
    - `mkdir develop` 名前はなんでもいい
    - `cd develop`
    - `git clone https://github.com/YuichiMase/git_trial.git`
  - 上記コマンドで`top > develop > git_trial` になるはず
    - `cd git_trial`
    - `echo "#Hello Git!!" >> README.md`
    - `git init` このリポジトリをgit管理する
    - `git add`
    - `git commit -m "my first commit"`
    - `git push -u origin master`
    - 再度 https://github.com/YuichiMase/git_trial.git にアクセス, READMEが表示されればOK
- sshの場合
  - [今日からはじめるGitHub 〜 初心者がGitをインストールして、プルリクできるようになるまでを解説 - エンジニアHub｜若手Webエンジニアのキャリアを考える！](https://employment.en-japan.com/engineerhub/entry/2017/01/31/110000)
  - 上の「環境の構築（2） SSHの鍵を取得する」を見ればいいと思う

- 上記完了したら以下をテストしてみると理解深まるかも
  - 何度かローカルで変更 -> コミット -> push を繰り返して、GitHubのコミットログがどうなるか。ローカルで`git log`とやるとどうなるかを見る
  - 他人のリポジトリをフォークして自分のGitHubアカウントに持ってくる。
    - それをcloneして、ローカルで新しくブランチを切ってREADME.mdを好きなように変更して Pull Requestを作成してみる。
    - 上記のPRにコメントをいれて会話してから、マージする。
    - 最新版になったmasterブランチをpullする、どういうログが流れるかチェック
【C#】【WPF】別アセンブリのクラスをWPF上で使用する


例えばDataModel.dllというモジュールがあって、
その中のHogeというnamespace内の『HogeClass』クラスを参照したい場合。
＃当然、プロジェクト参照でDataModel.dllは参照しておく

自身のプロジェクト内と同様に以下のように記載すると参照エラーになります。

```C#
xmlns:data="clr-namespace:DataModel.Hoge"
～～中略～～
<Window.Resources>
  <data:HogeClass x:Key="HogeClass"/>
</Window.Resources>
```
その名前空間にそんなもんは無い！とお叱りを受けます。
確かに参照にも追加しているし、namespaceも間違っていないのに…と思っていたら、
名前空間の宣言が間違っていました。
正しくは以下のようにアセンブリ名を記載する必要があります。

```C#
xmlns:data="clr-namespace:DataModel.Hoge;assembly=DataModel"
```

地味にハマったのでメモ。
「Creately」でAWSの構成図を超簡単に作成

「Creately」というサービスがあり、AWSの構成図をWebブラウザ上で作れます。
AWSの新しいアイコンにも対応しており、非常に便利です。

# 1.「Creately」アクセス方法
以下URLからアクセスできます。
https://app.creately.com/manage/project/home

# 2. 利用方法
1. まず「ドキュメントの追加」を押します。
2. 「何を描きたいですか？」の画面で「Amazon Web Services」を押します。
3. 左側にいっぱいアイコンがあるので、右側のスペースにドラッグ&ドロップします。
4. こんな感じで構成図が書けます。(キャプションも付いてきます。必要に応じてキャプションをサーバ名等任意の文字列に変えられます)
![creately.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211986/c1f32a32-76e9-7de2-51d6-7faf0262639c.png)
5. PNGやJPEGでエクスポートして、設計書や提案書に貼り付けます。

# 3. まとめ
これは便利でした！生産性が上がります。こういう便利なツールは使わない手はありませんね！
ファイル名リストに書かれた名前のファイルを別のフォルダにコピーしたい（bash）

###ファイル名の書かれたリストとフォルダを対応付けながら、データをコピーしたり、動かしたりしたい時の書き方。

こういうリスト

```name.list
ねこ　　脊椎動物
いぬ　　脊椎動物
かめ　　脊椎動物
たこ　　軟体動物
ちょう　 節足動物
しじみ  軟体動物
・・・
```
と
こういうフォルダ

```animals.dir
ねこ　いぬ　かめ　ふくろう　いるか
たこ　ちょう　しじみ　せんちゅう　くも　かに
```

があるとする。

name.listの1列目に名前のある動物の名前がついたファイルのみをanimals.dirからコピーしたい。
そんなときは以下のコードでできる。

```bash
#!/bin/bash

cat name.list | while read line
do
  name=`echo $line| awk '{print $1}'`
  filename=animals.dir/${name}
  cp ${filename} ./コピー先ディレクトリ名
done
```


###解説

- テキストを1行ずつ読み込み、処理を行う

```bash
cat name.list| while read line
do
(なにかの処理)
done
```
catでname.listを返し、それをそのままwhileに入れている

- 処理の返り値を変数に代入する

```bash
name=`(なにか処理)`
```
【C#】【WPF】依存プロパティ(DependencyProperty)定義時にエラー

依存プロパティを実装したコントロールのコンストラクタで
以下のような例外が出た場合のメモ。
__『指定されたバインディング制約に一致する型 '○○○.MainWindow' のコンストラクターの呼び出しで例外がスローされました。』__

何のことだろう、と思っていましたがチェックポイントとしては依存プロパティの宣言内容を確認する。

- プロパティ、親の型が間違っていないか
- 初期値の型がプロパティと一致しているか

実際のケースではdouble型のプロパティに対して
『200』と指定していたのでintと判断されて不一致扱いになっていました。
初期化の際は注意…。
MATLABで株価データ自動取得　その１　データ取得

# MATLABで株価データを取得してみた

Yahooファイナンスの時系列データを自動的に取得して解析したい！
ということで、MATLABのText Analytics Toolboxで試しにやってみた。今回はとりあえずデータ取得するところまで。

# 1. RESTful-API
Yahooファイナンスの時系列データのURLは以下のような構造になっている。

```matlab:
baseURLTimeseries = "https://info.finance.yahoo.co.jp/history/?code=";
getURL = baseURLTimeseries+num2str(stockCode)+"&sy="+string(year(sDateTmp))+...
        "&sm="+string(month(sDateTmp))+"&sd="+string(day(sDateTmp))+...
        "&ey="+string(year(eDateTmp))+"&em="+string(month(eDateTmp))+...
        "&ed="+string(day(eDateTmp))+"&tm=d";
```


# 2. HTMLの取得
MATLABではwebreadだけでHTMLデータを取得できる。上のURLをwebreadに放り込むとHTMLのテキストデータが取得できる。

```matlab:
str = webread(getURL);
tree = htmlTree(str);
stockName = eraseTags(string(findElement(tree,"h1")));  % H1タグ（会社名）を見つけてHTMLタグを削除
```

# 3. テキストデータの加工

HTMLファイルからタグや不要な文字列を削除して、時系列データだけを抽出する。

```matlab:
startTag = "調整後終値*";
stopTag = "VIP倶楽部限定";
str = eraseTags(str);   % HTML Tagを削除
str = extractBetween(str, startTag, stopTag);   % 不要部分文字列を削除
splitStr = split(str, "  ");    % 1つのセルをセル配列に分割
splitStr = splitStr(2:end-2);           % 最後の2つは不要のため削除
splitStr = reshape(splitStr, [verNum+1, length(splitStr)/(verNum+1)])';
splitStr = erase(splitStr, ",");   % 数値の, を削除
```
こんなセル配列になった。
![stockDataCell.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/1c40423c-8c6f-28b9-eaea-b62127deb7d8.jpeg)

# 4. Time Talbeデータの作成
ここはもうちょっと賢いやり方がありそうだけど、とりあえずこんな感じでセル配列をTime Tableに変換した。

```matlab:
temp = timetable(datetime(splitStr(:,1)));
for n = 2:numel(varNames)+1
    temp = addvars(temp, cellfun(funcStr2num, splitStr(:,n)));
end
stockData = [stockData; flipud(temp)];
```

# 5. MATLAB関数化
引数に株価コード、開始・終了日を設定できるようにして関数化した。

```matlab:
function stockData = dataAcqFromYahoo(stockCode, startDate, endDate)
```

# 6. 実行結果
実行すると株価データをtime tableにして返してくれる。（トヨタ自動車の2019/6/1~8/5までの株価）
![commandWindowStockData.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/1114b656-6500-833c-2844-2d633735b176.jpeg)

変数エディタで見るとTime Tableはこのように。
![timeTableStock.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/18a6da7c-85d0-4a60-2cf2-22860df8a202.jpeg)

次はプロットする予定。
【C#】アプリケーションの見た目をOS依存ではなく固定する

WindowsでGUIアプリケーションを作成する際に、
OSによってコントロールの見た目が変わることがあります。
例えばフォントにしても以下のようにデフォルトが異なります。

|OS|システムフォント|
|---|---|
|Windows XP|MS UI Gothic|
|Windows 7|Meiryo|
|Windows 10|Yu Gothic UI|

これによって、各OSによってレイアウトが崩れることが良くあります。
最近はWindow7から10へのリプレースをする機会が増えてきているかと思いますが、
その際には注意が必要です。

実際あったケースとしては、
開発環境はWindows7のまま、本番環境はWindows10という状況で、
検証に回すと挙動が異なる、という報告がありました。
『コンボボックスが特定の項目を選択している場合のみ色替えを行う』という仕様でしたが、
色が変化しない、という報告。
確かに確認すると色が変化しないけど、開発環境では問題なく動作する。

で、色々と調べてみると本題であるOSの問題。
コンボボックスの見た目も7と10で異なります。
・Windows7の場合![win7Combo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373724/654eaae5-366e-0d16-f726-290bb0375563.jpeg)
・windows10の場合![win10Combo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373724/06f32a29-f772-adf6-ca88-08ed2b6f41ea.jpeg)
この影響で色替えが正しく動いていませんでした。
で、ようやく今回書きたかったこと。
Windows7上では正しく動作していたのでWindows10でも同様のレイアウトにしたい。
その場合は以下のように指定することで解決します。

```C#:指定方法
<Application x:Class="WPFTest.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfTest"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary Source="/PresentationFramework.Aero;component/themes/aero.normalcolor.xaml" />
    </Application.Resources>
</Application>
```
上記の例ではApp.xamlに記載しています。
そうすることでアプリケーションの規定値として指定することが出来ます。
Windows7以外のOS準拠にしたい場合はそれぞれ以下を指定すればOKです。

|OS|指定するテーマ|
|---|---|
|Windows XP|presentationframework.Aero|
|Windows 7|presentationframework.Aero|
|Windows 10|presentationframework.Aero2|

ちなみに指定する為には対応するテーマをプロジェクト参照に追加する必要があるので注意。

で、大抵はこれで解決すると思いますが、
私の場合はまだ解決しませんでした。
上記指定しても問題のコンボボックスはWindows10の見た目のまま…。
更に調べていくと該当コントロールにStyleを指定していたことが原因でした。
Styleを継承する場合は、BasedOnプロパティで、以下のように継承元を指定します。 

```C#
<Style TargetType="ComboBox" BasedOn="{StaticResource ResourceKey={x:Type ComboBox}}">
```
継承定義しないとデフォルト＝各OSの基本テーマが適用されてしまうので反映されません。
いやぁハマってしまった…。
ワンライナーでGitLab-CIの環境変数を取り出すシェル(Ruby)スクリプト



```shell
ruby -e 'require "yaml"; yaml = YAML.load_file(".gitlab-ci.yml"); variables = yaml["variables"]; variables.each { |key, value| cmd = "export #{key}=\"#{value}\""; system("echo #{cmd}"); }'
```
VeraCryptでWindows内に暗号化領域を作ってみた

# 概要
VeraCryptという暗号化用のオープンソースソフトウェアがあります。（ご存知の方もいるかもしれませんが、TrueCryptの後継ソフトのようです）

今回はそれをWindowsのPCにインストールして、さらにバッチファイルでちょこっと使い勝手を良くしましたので、その情報共有です。
　

※ソフトウェアの内容については省かせていただきますが、検索したら沢山出てきますし、下の[「インストール」](https://qiita.com/TwDaiki/items/4abfb1ee5a6aa3ebee91#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)のWEB記事でも色々と説明されています。

※実際にやってみる人は自己責任でお願いします
（特にシステムボリューム全体を暗号化して失敗すると、最悪起動しなくなることもありそうです）

# インストール

以下のWEB記事を参考にしてインストールしました。VeraCryptについての説明も色々参考になります。

 + 【SSS】VeraCryptをダウンロードして暗号化領域を作る　※Windows向けの記事 
  + https://excesssecurity.com/veracrypt/

 + 死んだ後も安心！？VeraCryptで秘密のファイル置き場を作る方法　※Linux向けの記事
  + https://linuxfan.info/veracrypt

※（参考）インストールしたPC 
　　  OS：Windows7 Pro 64bit
　　  RAM：8GB
　　  CPU：Intel Core i5-3340M
　　  SSD：1TB

# 使い方（ざっくり紹介）

暗号化領域（ファイル）を作り、それをボリュームとしてマウント/アンマウントして使います。
※以下の手順では、細かい操作を省略しています

### 暗号化領域（ファイル）を作る
1. 「ボリュームの作成」ボタンを押し、作成する暗号化領域のファイルパスを指定する
![CreateVolume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/7649c601-9ebc-bacc-321a-4245ac241185.png)
 ※上のファイルパス(C:￥test￥testVolume.ogv)は適当に指定しています（実際には、暗号化ファイルだとわかりにくい名前にした方が良いと思います）  
 　　

1. 続いてパスワードを入力する
![InputPassword.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/b53f4d27-3279-dace-8efa-e186cfd7d18f.png)

1. 暗号化領域（ファイル）が出来る
![testFolder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/25e185f9-bb21-cca1-ea76-bdaced9fe3ce.png)
　

※上記ではファイルを暗号化領域としていますが、パーティションやシステムボリューム全体を暗号化領域とすることもできるようです

### マウント/アンマウントして使う

1. マウントする
　①「ファイルの選択」で暗号化領域のファイルを指定する（上記で作成したファイル）
　② パスワードを入力する
　③「マウント」ボタンを押下する
![mount.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/230e41f5-7a86-2262-16a5-d7dc3aea94a4.png)
 ※アンマウントする場合は「マウント」ボタンが「アンマウント」に変わっているのでそれを押します  

1. Windowsのファイルシステム上にボリュームが表れて、他のボリュームと同じ様にエクスプローラーなどでファイルの操作（作成、コピペ、削除など）が出来る
![drive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/192a1737-1bc1-812c-633a-44225f54f754.png)

※PCの電源をOFFすると自動でアンマウントされました

# バッチファイル

以下にバッチファイルのサンプルを載せます。

これを実行すると、VeraCriptのパスワードの入力画面がでてきます。
そして、パスワードを正しく入力すると暗号化領域が「I:」ボリュームとしてマウントされて、
「explorer」で指定したフォルダ（I:\temp\001）をエクスプローラーで開きます。

```open_volume.bat
"C:\Program Files\VeraCrypt\VeraCrypt.exe" /q /v "<暗号化領域(ファイル)のパス>" /l I
explorer "I:\temp\001"
```

※ 1つ目のコマンドの「/l I」というのはボリューム「I:」としてマウントする事を指しています
※ あらかじめ「\temp\001」というフォルダを暗号化領域に作っているという前提です

（参考）実際に使用したVeracryptのバージョン：　1.23 hotfix 2(64bit)
（参考）WEB記事：[VeraCryptのWindows版でコマンドラインでマウント/アンマウントするには](https://denor.jp/veracrypt%e3%81%aewindows%e7%89%88%e3%81%a7%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%a9%e3%82%a4%e3%83%b3%e3%81%a7%e3%83%9e%e3%82%a6%e3%83%b3%e3%83%88-%e3%82%a2%e3%83%b3%e3%83%9e%e3%82%a6%e3%83%b3)


			
# 更新履歴
* 2019-08-06：新規作成
【信号処理】Pythonを使って正弦波をフーリエ変換してみた！

#概要
フーリエ変換を離散化したものが離散フーリエ変換(DFT)であり、
計算機ではこのDFTを高速化した高速フーリエ変換(FFT)を用いて、
フーリエ変換をしています。

DFTの練習問題としてよく出てくるのが，
(1)方形波
(2)正弦波
の2つです．
正直フーリ変換と違ってDFTは手計算できるものがかなり限られてくるので
この2つを押さえておくだけでもだいぶ違うかなと思います．

前回は(1)方形波を扱ったので，今回は(2)正弦波を扱おうと思います．

[【信号処理】Pythonを使って方形波をフーリエ変換してみた！]
(https://qiita.com/trami/items/2d893d781eaeb75025b1)

DFTを実際に手計算で計算し，それをPythonでFFTしたものと一致するかを確かめてみたいと思います．

#動作環境
- Windows10(64bit)
- Python 3.7.2

# DFTの復習
入力信号をx(n)とすると，そのDFTであるX(k)は以下のようになります．ただし，$W_N = exp(-j\frac{2\pi}{N})$.

```math

X(k) = \sum_{n=0}^{N-1}{x(n)W_{N}^{kn}}
```

#問題

```math

x(n) = cos(2\pi ft)
```

のDFTを求めなさい．ただし，サンプル数$N=8$，周波数$f=1000$，$t=nT=n\times\frac{1}{1000N}$とする．

#解答
それでは上記の問題を,まずは手計算で計算していきます．

まずは，回転子を導入する．

```math

W_8 = exp(-j\frac{2\pi}{8})
```

回転子を用いると，入力信号は以下のように表される．

```math

x(n) = \frac{1}{2}(W_8^{-2n}+W_8^{2n})
```

DFTの定義より

```math
\begin{align}
X(k) & = \sum_{n=0}^{7}x(n)W_8^{kn}\\
& = \frac{1}{2}\sum_{n=0}^{7}(W_8^{-2n}+W_8^{2n})W_8^{kn}\\
& = \frac{1}{2}\sum_{n=0}^{7}W_8^{(k-2)n}+\frac{1}{2}\sum_{n=0}^{7}W_8^{(k+2)n}\\
& =\begin{cases}
& 4 & (k = 2, 6)\\
& 0 & (otherwise)
\end{cases}
\end{align}
```

#実装
では，早速実装していきましょう．

```py:sine_wave.py

import numpy as np
import matplotlib.pyplot as plt
pi = np.pi

N = 64
f = 1000
n = np.array(range(0,N))
t = n/(1000*N)
f = np.cos(2*pi*f*t)
F = np.fft.fft(f)

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

ax1.stem(n, f)
ax2.stem(n, np.abs(F))
ax1.set_xlabel('t')
ax2.set_xlabel('k')
ax1.set_ylabel('f')
ax2.set_ylabel('abs(F)')
fig.tight_layout()
plt.show()
```

#解説
特に難しいところはないと思います．
高速フーリエ変換はnp.fft.fft()でできます．
グラフ描画は離散データなので，stemで描画するためnp.stem()となります．

#実行結果
以上のプログラムを実行すると以下のような画像が得られます．

![cos(N=8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433790/5b8f87ef-9d41-3527-9932-8359002de6f7.png)

$k = 7$の成分は$k = -1$の成分と解釈することもできますね．
今回は入力信号の角周波数が単一なので，プラスとマイナスの所に2つインパルスが立っていますね．
サンプル数を増やして$N=64$として実行した結果が以下になります．

![cos(N=64).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433790/9154ede9-63ff-ca39-d244-c9c4f69aa426.png)

#まとめ
今回は，DFTで頻出の正弦波のDFTに挑戦してみました．いかがだったでしょうか？
計算に関してはほぼお決まりのパターンなので，たくさん練習をして慣れていくといいと思います．
サンプル数を変えたり，入力信号を変えたりして遊んでみると面白いのではないかなと思います．
今回のプログラムに関して何か改善点や建設的な意見等あればコメントしてもらえると助かります！
phpコマンドがとても便利

# はじめに

phpのテストを行う時、通常は

1. DocumentRoot配下にtest.phpを作成する
2. test.phpにテストをしたいコードを記述する
3. test.phpを保存する
4. ブラウザからtest.phpにアクセスする
5. 出力内容を確認する
6. test.phpを削除する

のように多くのプロセスが必要。php.iniの設定によってはエラーが出ているはずなのに表示されなかったり…本番環境の場合はtest.phpを消すの忘れたら大変だ…考慮しなければならないことが沢山あってテストだけでも一苦労。

そんな時に大活躍するのがphpコマンドだ。

# お勧めのphpコマンド

```php
# PHPのバージョンを確認する
php -v

# 読み込んでいるモジュールを表示する
php -m

# phpinfoを表示する※ボリュームがあるので、php -vやphp -mを積極的に使いたい
php -i

# 実行はしないでシンタックスチェックだけする
php -l test.php

```

# 必殺コマンドphp -a

ログのファイル名を作るのに、今の**年-月-日-時-分-秒-マイクロ秒**を取得したい。`date_format(new DateTime(), 'Y-m-d-H-i-s-v')`あたりで取得されるはずなんだけど、さくっと動作確認したいな。

```bash
## 対話シェルを立ち上げる
user@host:~$ php -a
Interactive mode enabled

# 上述のコードをechoしてみる
php > echo date_format(new DateTime(), 'Y-m-d-H-i-s-v');
2019-08-06-12-19-20-357

# あ、末尾のvってマイクロ秒じゃなくてミリ秒だった！修正修正…
php > echo date_format(new DateTime(), 'Y-m-d-H-i-s-u');
2019-08-06-12-22-27-214692

# よし！うまく動いたぞ！！

# 対話シェルから抜ける
php > exit
user@host:~$
```

…

テストがとっても簡単になりました。
この対話シェルでは変数や関数も扱えるので、もっと本格的なテストもできそうです。
SAS ViyaのFetchオブジェクトのパラメータ操作について

SAS ViyaはAIプラットフォームです。PythonやJava、Rなどの言語を通して利用できます。そのSAS Viyaの中で使われているのがCASTableというテーブルオブジェクトです（CASはCloud Analytic Servicesの略です）。CASTableからデータを取得する際のパラメータをネストして与える方法について紹介します。

## SAS Viyaに接続する

まずはSAS Viyaに接続します。

```python
from swat import *

cashost='localhost'
casport=5570
useremail='dev@sas.com'
userpassword='password'
casauth='~/.authinfo'
conn = CAS(cashost, casport, useremail, userpassword, caslib="casuser")
```

## データをアップロードする

CSVファイルのデータをアップロードします。今回は有名なIRISのデータです。

```python
out = conn.upload('./iris.csv')
```

## Fetchオブジェクトを取得する

Fetchオブジェクトをconnから取得します。初期値としてテーブルなどを指定できます。

```python
fa = conn.Fetch(to=5, table=dict(name='IRIS', caslib='casuser'))
```

## パラメータの取得

パラメータを取得する際には `get_param` を使います。

```python
fa.get_param('to')

# -> 5
```

複数の引数を指定することで複数の値を取得できます。

```python
fa.get_params('to', 'table.name')

# -> {'table.name': 'IRIS', 'to': 5}
```

## パラメータの削除

パラメータの削除は del_params を使います。

```python
fa.del_params('to', 'table.caslib')
```

## パラメータの確認

パラメータの存在確認は has_param を使います。

```python
fa.has_param('table.caslib')

# -> False
```

複数指定した場合は、すべての項目がある場合のみTrueが返ってきます。

```python
fa.has_param('table.name', 'to')

# -> False
```

## プロパティを使ったアクセス

プロパティを指定して値を取得することもできます。

```python
fa.table.name

# -> 'IRIS'
```

同じようにデータの削除もできます。

```python
fa.table

# -> {'caslib': 'casuser', 'name': 'IRIS'}
```

データを削除します。

```python
del fa.table.caslib
```

確認します。

```python
fa.table

# -> {'name': 'IRIS'}
```

## まとめ

SAS ViyaのFetchオブジェクトは柔軟にデータ指定ができます。プログラマブルに条件を変更するのも簡単でしょう。ぜひお試しください。

[Python Programming for SAS Viya | SAS](https://developer.sas.com/guides/python.html)
Rasberry Pi の標準プレーヤ（omxplayer）で、音楽を鳴らす

##最初に
もうすぐ子供が生まれ、とうとう父になるようです。
夜泣きとかすごいと思うので、赤ちゃんが泣いた時に、一時対応として、
「泣き声がすごかったら、ア●パ●マ●とかの曲を流す」ということをさせようと思っています。
（**要件：センサーで音を検知したら、音楽をランダムで再生する**）

この仕組みを作るためには、以下のことができなければなりません。
**1.Rasberry Piで音楽を鳴らす**
**2.音センサーで検知させる**
**3.センサー検知後に、ランダムな曲を選択する**
などなど

**今回は、「1.Rasberry Piで音楽を鳴らす」ということを主眼に**記事を書いていきます。

##環境
Python
Rasberry Pi
USBミニスピーカ（DAISO製）


##音楽を再生させてみる
■参考にさせていただいたURL
https://qiita.com/goowaSystemTeam/items/95525dae25dee270087b

基本的に、上記のURLを参考にすると、Pythonでの音楽の再生方法と停止の方法がわかります。

参考にしたURLだと、10秒で音楽を停止するようにしているので、
「音楽の長さを取得して、音楽の終了時に停止する」という処理に変えてみたいと思います。

ここで、mutagenというモジュールをインストールします。
以下の公式サイトに記載がありますが、オーディオのメタデータを操れるモジュールのようです。
https://mutagen.readthedocs.io/en/latest/

・mutagenのインストール

```
pip install mutagen
```

##コード
```playOmxplayer.py
# -*- coding: utf-8 -*-

import subprocess
import time

from mutagen.mp3 import MP3

#以下の音楽ファイルのパスは、環境に応じて変更してください
audio = MP3('/path/to/music/music_test.mp3')
print (audio.info.length)

#動画を再生する
#以下の音楽ファイルのパスは、環境に応じて変更してください
command = 'omxplayer /path/to/music/music_test.mp3'
proc = subprocess.Popen(command,shell=True,stdin=subprocess.PIPE)

#-- なんからの処理(音声の長さ分の停止)  --
#time.sleep(10)
time.sleep(audio.info.length)
#-------------------------------------

#終了処理
print("Fiininish")
proc.stdin.write("q")
```
これで、音楽終了時に、プレーヤーを停止させる、というロジックができました。

##実行

```
python playOmxplayer.py
```

##実行結果
```
192.574693878    #←再生する音楽の長さ（秒表示）
Audio codec mp3 channels 2 samplerate 44100 bitspersample 16
Subtitle count: 0, state: off, index: 1, delay: 0
Fininish
Stopped at: 00:03:12
```

無事にスピーカーからも音声が出力されました

![IMG_0091.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167745/8acfc2fc-4b2d-645a-c0dd-0cb2ef9fd38f.jpeg)
※DAISOさんのスピーカは、USBで給電して、イヤホンジャック部分にプラグを挿すようです。


さて、次回はRaspiの配線の先にある、音センサーとの接続をやっていきたいと思います。
SAS ViyaのFetchオブジェクトに条件をプロパティとして与える

SAS ViyaはAIプラットフォームです。PythonやJava、Rなどの言語を通して利用できます。そのSAS Viyaの中で使われているのがCASTableというテーブルオブジェクトです（CASはCloud Analytic Servicesの略です）。CASTableからデータを取得する際のパラメータをネストして与える方法について紹介します。

## SAS Viyaに接続する

まずはSAS Viyaに接続します。

```python
from swat import *

cashost='localhost'
casport=5570
useremail='dev@sas.com'
userpassword='password'
casauth='~/.authinfo'
conn = CAS(cashost, casport, useremail, userpassword, caslib="casuser")
```

## データをアップロードする

CSVファイルのデータをアップロードします。今回は有名なIRISのデータです。

```python
out = conn.upload('./iris.csv')
```

## Fetchオブジェクトを取得する

Fetchオブジェクトをconnから取得します。

```python
fa = conn.Fetch()
```

初期状態ではテーブルなども設定されていませんので、パラメータで設定するのですが、この際にプロパティを使ってみます。

```python
fa.params.table.name = 'IRIS'
fa.params.table.caslib = 'casuser'
```

この時の `fa` の内容は次の通りです。

```python
?.table.Fetch(table=dict(caslib='casuser', name='IRIS'))
```

ソート条件も同様にプロパティとして適用します。

```python
fa.params.sortby[0].name = 'PetalLength'
fa.params.sortby[0].formatted = 'raw'
fa.params.sortby[1].name = 'PetalWidth'
fa.params.sortby[1].formatted = 'raw'
```

paramsを変更することも、別途取り出して変更もできます。

```python
sortby = fa.params.table.sortby
sortby[0].name = 'PetalWidth'
sortby[0].formatted = 'raw'
sortby[1].name = 'PetalLength'
sortby[1].formatted = 'raw'
sortby
```

結果は次のようになります。

```python
{0: {'formatted': 'raw', 'name': 'PetalWidth'},
 1: {'formatted': 'raw', 'name': 'PetalLength'}}
```

## 任意のパラメータを追加した場合

もし、popという要素を追加したとします。

```python
fa.params.pop = 'corn'
```

この値は自動的にディクショナリ型になります。

```python
fa.params.pop

<bound method xdict.pop of {'table': {'name': 'data.IRIS', 'caslib': 'casuser', 'sortby': {0: {'name': 'PetalWidth', 'formatted': 'raw'}, 1: {'name': 'PetalLength', 'formatted': 'raw'}}}, 'sortby': {0: {'name': 'PetalLength', 'formatted': 'raw'}, 1: {'name': 'PetalWidth', 'formatted': 'raw'}}, 'pop': 'corn'}>
```

ただし、キーでアクセスすると元の文字列が返ってきます。

```python
fa.params['pop']

'corn'
```

このようにアクセス方法によって返ってくる値が異なるので注意してください。

## まとめ

Fetchオブジェクトにはパラメータとしてアクセスする方法も用意されています。使いやすい方を選択してください。

[Python Programming for SAS Viya | SAS](https://developer.sas.com/guides/python.html)
Fetchオブジェクトのパラメータ指定について

SAS ViyaはAIプラットフォームです。PythonやJava、Rなどの言語を通して利用できます。そのSAS Viyaの中で使われているのがCASTableというテーブルオブジェクトです（CASはCloud Analytic Servicesの略です）。CASTableからデータを取得する際のパラメータをネストして与える方法について紹介します。

## SAS Viyaに接続する

まずはSAS Viyaに接続します。

```python
from swat import *

cashost='localhost'
casport=5570
useremail='dev@sas.com'
userpassword='password'
casauth='~/.authinfo'
conn = CAS(cashost, casport, useremail, userpassword, caslib="casuser")
```

## データをアップロードする

CSVファイルのデータをアップロードします。今回は有名なIRISのデータです。

```python
out = conn.upload('./iris.csv')
```

## Fetchオブジェクトを取得する

Fetchオブジェクトをconnから取得します。

```python
fa = conn.Fetch()
```

初期状態ではテーブルなども設定されていませんので、パラメータで指定します。

```python
fa.set_params('table.name', 'IRIS',
              'table.caslib', 'casuser')
```

この時の `fa` の内容は次の通りです。

```python
?.table.Fetch(sortby=dict(0=dict(formatted='raw', name='PetalLength'), 1=dict(formatted='raw', name='PetalWidth')), table=dict(caslib='casuser', name='IRIS'))
```

そしてソート条件を指定します。

```python
fa.set_params('sortby.0.name', 'PetalLength',
              'sortby.0.formatted', 'raw',
              'sortby.1.name', 'PetalWidth',
              'sortby.1.formatted', 'raw')
```

そして出力します。

```python
fa(to=5)
```

**§ Fetch**

Selected Rows from Table IRIS

|SepalLength|SepalWidth|PetalLength|PetalWidth | Name
|---|---|---|---|---|---|
| 0 | 4.6 | 3.6 | 1.0 | 0.2 | Iris-setosa
| 1 | 4.3 | 3.0 | 1.1 | 0.1 | Iris-setosa
| 2 | 5.0 | 3.2 | 1.2 | 0.2 | Iris-setosa
| 3 | 5.8 | 4.0 | 1.2 | 0.2 | Iris-setosa
| 4 | 4.7 | 3.2 | 1.3 | 0.2 | Iris-setosa

elapsed 0.00106s · user 0.000999s · mem 2.84MB


## まとめ

Fetchオブジェクトは set_params を使って取得するデータの指定、絞り込みが簡単に行えます。ぜひ試してみてください。

[Python Programming for SAS Viya | SAS](https://developer.sas.com/guides/python.html)
Azureアーキテクチャガイドまとめ 8 【ビッグコンピューティングアーキテクチャ】

## はじめに
[**Azureクラウドアプリケーションアーキテクチャガイド**](https://azure.microsoft.com/ja-jp/campaigns/cloud-application-architecture-guide/)より、7つあるスタイルの最後の1つ、**ビッグコンピューティングアーキテクチャ**に関してまとめます。

#### 連載目次
[Azureアーキテクチャガイドまとめ 1 【はじめに】](https://qiita.com/Catetin0310/items/74249f333d9fbfccd543)
[Azureアーキテクチャガイドまとめ 2【N層】](https://qiita.com/Catetin0310/items/1ab0ae1130f767d770d3)
[Azureアーキテクチャガイドまとめ 3 【Webキューワーカー】](https://qiita.com/Catetin0310/items/fe0729549faeee843e8a)
[Azureアーキテクチャガイドまとめ 4 【マイクロサービス】](https://qiita.com/Catetin0310/items/06ab890a04baa161cac6)
[Azureアーキテクチャガイドまとめ 5 【CQRS】](https://qiita.com/Catetin0310/items/d0e8b489f6501e4da90b)
[Azureアーキテクチャガイドまとめ 6 【イベントドリブンアーキテクチャ】](https://qiita.com/Catetin0310/items/58f65242a7b71620825b)
[Azureアーキテクチャガイドまとめ 7 【ビッグデータアーキテクチャ】](https://qiita.com/Catetin0310/items/d515fc3fdff68b54f408)
Azureアーキテクチャガイドまとめ 8 【ビッグコンピューティングアーキテクチャ】 → 本記事



## 概要
作業を個別のタスクに分割し、**多数のコアを使って同時に処理**するアーキテクチャスタイル。大量のコアを一気にプロビジョニングし、アプリケーションが完了すると、プロビジョニングを解除します。

以下のような特徴を持つアプリケーションに適します。

- **計算負荷が高く**、複数へのコンピュータのCPUへの分割が必要なシミュレーションや数値演算
- 一台のコンピュータでは時間がかかりすぎる**処理時間の長い**計算
- **小さな計算処理を数百万回から数千回実行**する必要がある場合

以下のようなケースで活用します

- 画像のレンダリング
- 流体力学
- 金融リスクモデリング
- 石油探査
- 新薬開発
- 応力解析


## 対応するAzureコンポーネント
大規模なパイパフォーマンスコンピューティングアプリケーションを実行するためのマネージドサービスである、**Azure Batch**が主要なサービスです。

**Azure Batch**はワークロードに合わせて、**Virtual Machine**を自動的にスケールアウトします。

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/995261f1-13b0-aead-f63e-a6172270f961.jpeg)


## 利点
- 単純並列処理による**ハイパフォーマンス**
- **大規模な問題を迅速に解決**
- 専用の高速ネットワークを備えた専用HWにアクセスできる
- 作業に必要な数だけVMをプロビジョニング可能



## 課題
- マシンリソースの管理
- 数値演算ボリュームの管理
- 数千のコアのタイムリーなプロビジョニング


## 参考リンク
[Azure でのハイ パフォーマンス コンピューティング (HPC)](https://docs.microsoft.com/ja-jp/azure/architecture/topics/high-performance-computing)
[ビッグ コンピューティング アーキテクチャ スタイル](https://docs.microsoft.com/ja-jp/azure/architecture/guide/architecture-styles/big-compute)
コマンドでWindowsのDNSレコード(Aレコード)を変更する

#序文
DNSレコードを変更するにあたり、以下のコマンドを作成する。
　・ゾーン情報を一覧出力
　・レコード変更

※1
DNSCMDを利用するので、DNSサーバ上で実行する必要がある。

※2
もちろん、数件であればDNSレコードを直接ダブルクリックして変更した方が早い。
ただし操作ミスが起こりうる事、事前レビューがあまり意味をなさない事から、コマンド化することを強く推奨する。


##ゾーン情報の出力
###Syntax
```
dnscmd <DNSサーバ> /ZonePrint <Zone名>
```


例えば次のケースの場合、以下のコマンドで出力が出来る。
　DNSサーバ ：contosoDNS
　Zone名　　：stage.contoso.co.jp

```
dnscmd contosodns /ZonePrint stage.contoso.co.jp
```

#レコード追加
###Syntax
```
dnscmd <ServName> /recordadd <ZoneName> <Node> <RecordType> <IP>
```
※/fオプションを付けると、確認無しで実行する事が出来る。バッチ化する際は/fコマンド推奨。

###例
以下のケースの場合
　DNSサーバ：contosoDNS
　ホスト名:Serv02
　IP Address：192.168.10.2
　ゾーン名：stage.contoso.co.jp

```
dnscmd contosoDNS /recordadd stage.contoso.co.jp Serv02 A 192.168.10.2
```

#レコード削除
###Syntax
```
dnscmd <ServName> /recorddelete <ZoneName> <Node> <RecordType> <IP>
```

###例
以下のケースの場合
　DNSサーバ：contosoDNS
　ホスト名:Serv02
　IP Address：192.168.10.1
　ゾーン名：stage.contoso.co.jp

```
dnscmd contosoDNS /recorddelete stage.contoso.co.jp Serv02 A 192.168.10.1
```


#DNSレコードを変更する場合
削除と追加を、それぞれ実行すればOK。
(追加では古い情報は削除されない為、削除が必須。)

###例
以下のケースの場合
　DNSサーバ：contosoDNS
　ホスト名：Serv02
　旧IP Address：192.168.10.1
　新IP Address：192.168.10.2
　ゾーン名：stage.contoso.co.jp

```
dnscmd contosoDNS /recorddelete stage.contoso.co.jp Serv02 A 192.168.10.1 /f
dnscmd contosoDNS /recordadd stage.contoso.co.jp Serv02 A 192.168.10.2 /f
```
※/fコマンドは無くてもOK。

#参考
Microsoft Docs 「DNSCMD」
https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/dnscmd
システム運用自動化プラットフォーム"Kompira Enterprise"のインストール手順（Ver.1.6編）

# はじめに
みなさん、こんにちは。
Kompiraエバンジェリストの冨です。

本記事は「運用自動化プラットフォーム Kompira Enterprise」をインストールして実行するまでの手順を解説します。

# "Kompira Enterprise"とは？
システム運用の自動化を実現するための、手順書の自動実行やシステム間の情報連携などを行うソフトウェアです。
RBA(Run Book Automation)やRPA(Robotics Process Automation)などのカテゴリ―に属するもので、作業担当者の操作手順をスクリプト化して自動実行させたり、運用監視システムなどからの通知情報を元に、調査作業／対応作業／通知／記録などを自動で行う事で、システム管理者、運用者の業務負荷を軽減します。

# 稼働環境
本稿を記載している時点(2023-09-28)の情報となります。
Red Hat Enterprise Linux (RHEL): 8系（推奨）または 7.6 以上（代替）
CentOS:  7.6 ～7.9（代替）（※8系はCent OSサポート終了に伴い、サポート外）
CentOS Stream: 8（代替）
Amazon Linux 2（代替）
がインストールされたサーバーが必要になります。オンプレ、クラウド環境のいずれでも大丈夫ですが、パッケージのダウンロードが必要になりますので、インターネットへの接続が必要になります。
アプリケーションの機能の性質上、管理対象の業務用サーバーに対して、IP reachableな環境に設置する必要があります。
またPython3.6が必要です。

最近の稼働環境に関しては、以下の製品仕様情報をご参照ください。
https://support.kompira.jp/enterprisespecificationinfo/

# ソフトウェアのダウンロード
KompiraをインストールするURLをご案内いたしますので、下記フォーム「Kompira評価版お申込み」より「ご希望の評価版」にKompira Enterpriseを選択して、申請をお願いいたします。

https://www.kompira.jp/trial/
![2021-09-10_12h31_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94326/b39117fe-e6c0-07fd-4683-f2397a2f6ce8.png)
※利用規約は、https://www.kompira.jp/Kompira_terms.pdf
をご参照ください。

# tar ballの展開～インストーラーの起動
以下の例ではバージョン1.5.4 post5 での例です。ダウンロードされたバージョンによってファイル名、ディレクトリ名は読み替えてください。

```
$ tar xvfz kompira-1.5.4.post5-bin.tar.gz
$ cd kompira-1.5.4.post5-bin
$ sudo ./install.sh
```

"Finish"メッセージが表示されれば終了です。

```
 ****: Finish: Install the Kompira (status=0)
```

# ブラウザでのアクセス～認証

サーバーのアドレスに対してブラウザでアクセスします。(httpsのプライバシー警告が表示された場合は、適当な証明書をインストールするか、ブラウザ側での例外対応などを設定してください。）
以下のようなログイン画面が表示されれば成功です。
![2019-08-06_11h10_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94326/c8cd0f0a-e15b-3fcd-42fd-b3aea6c78f5c.png)

初期ID,パスワードは"root", "root"になっています。

ログインが完了しましたら、自動化ジョブフローを書く準備が整いました。

# ライセンスの登録

Kompira Enterpriseの利用はライセンス登録が必要となります。
license@kompira.jp
にタイトルを「Kompira評価版申請【お客様会社名】」としてご請求ください。

1. 会社名
2. ご担当者様
3. ご希望の利用期間: YYYY/MM/DD ～ YYYY/MM/DD
4. ハードウェアID：「NODE:*******」

※「ハードウェアID」は下記の「設定＞ライセンス登録」画面の「ライセンス情報」に記載の内容を転記してください。

ライセンスファイル（*.lic）を入手しましたら、以下の手順で登録を行います。

1. 設定＞ライセンス登録　

![2019-08-06_11h18_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94326/17db6bcf-ee89-1f8a-efce-ad2dbd76f004.png)

2. 「編集」をクリック
3. ライセンスファイルの「ファイルを選択」ボタンより、*.licファイルを選択します。
4. 「保存」をクリック
5. 以下の様に登録が出来ましたら完了です。

![2019-08-06_11h30_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94326/5aa61d0b-278e-babf-dce3-7f03c601ebe3.png)

---
# Kompira Enterpriseの製品情報

https://www.kompira.jp/
サーバーやネットワーク機器などの運用を自動化するための連携処理基盤ソフトウェアです。
運用手順書の操作作業の自動化、監視ツールやメールなどをトリガーにした保守作業の自動実行など、独自のKompiraジョブフロー言語を用いたスクリプトを用意する事で、個々の機器やワークフローにきめ細かく対応する事が可能です。
npm installに失敗した時の対処方法

`npm install`に引っかかった時の対処方法についてまとめます。

# nodeのバージョンを変える

nodeの最新バージョンなら基本的にはできるはずなので、最新バージョンにアップデートしましょう。

逆にダウングレードしないとできない場合もあるかもしれないので、チーム内でできている人にnodeバージョンを聞いて、合わせてみましょう。

laradockでnodeのバージョンを変更する場合、

`.env`ファイルの`NODE_VERSION`を`node`から変更したいバージョンにします。

```
docker-compose stop workspace

docker-compose up -d --build workspace
```
でコンテナを再作成してあげればworkspaceコンテナに指定したnodeバージョンが入ります。

# --unsafe-permオプションをつける

今回、このオプションによってエラーが解消したのですが、情報がほとんどなくて困りました。

docker環境の場合、rootユーザでworkspaceコンテナに入っていたので、エラーになったようです。

rootユーザで`npm install`を実行するのは推奨されていないようなので、`--unsafe-perm`オプションをつける必要がありました。

`npm install --unsafe-perm`

お試しください。
AmazonLinuxからRDSへの接続、コマンドまとめ

コマンドをなかなか覚えられず、調べなおすのが大変なので、覚書。

#PostgreSQL(9.6.11) Port 5432

|||
|:-----------------|:-----------------------------------------------------:|
|パッケージ　　　　　|postgresql96.x86_64                                    |
|接続コマンド　　　　|psql –h \<endpoint\> -U \<username\> -d \<database\>   |
|データベース作成　　|CREATE DATABASE \<databasename\>                       |
|テーブル一覧取得　　|\dt                                                    |
|切断　　　　　　　　|\q                                                     |
|ロール(ユーザ作成)　|CREATE　ROLE \<username\> WITH LOGIN PASSWORD ‘pass’;  |
|ロール一覧取得　　　|CREATE　ROLE \<username\> WITH LOGIN PASSWORD ‘pass’;  |
|権限の追加　　　　　|GRANT SELECT, UPDATE ON \<tablename\> TO \<username\>; |

#MySQL(5.7．25)  Port 3306
|||
|:-----------------|:-----------------------------------------------------------------:|
|パッケージ　　　　　|mysql57-server.x86_64                                              |
|接続コマンド　　　　|mysql -h \<endpoint\> -u \<username\> -p \<database name\>         |
|データベース作成　　|CREATE DATABASE \<databasename\>                                   |
|テーブル一覧取得　　|SHOW TABLES;　                                                     |
|切断　　　　　　　　|exit　　　　　　　　　　　　　　　　　　　　　　　　　　　　            |
|ロール(ユーザ作成)　|CREATE USER '\<username\>'@'%' IDENTIFIED BY 'pass';               |
|ロール一覧取得　　　|SELECT * FROM mysql.user;                                          |
|権限の追加　　　　　|GRANT INSERT,UPDATE,SELECT ON \<dbname\>.\<tablename\> TO 'app'@'%'|

#MariaDB 10.2.21 Port 3306
###MariaDB 10.2.21 Port 3306

#Oracle Standard Editon One エンジンバージョン11.2.0.4.v20　Port 1521
|||
|:-----------------|:-----------------------------------------------------------------:|
|パッケージ　　　　　|下記参照                                                            |
|接続コマンド　　　　|sqlplus64 '\<username\>@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=\<endpoint\>) (PORT=1521))(CONNECT_DATA=(SID=ORCL)))'|
|データベース作成　　|Oracleは1インスタンスにデータバースは1つみたい                        |
|テーブル一覧取得　　|SELECT * FROM DBA_TABLES ORDER BY OWNER,TABLE_NAME;                |
|切断　　　　　　　　|exit　　　　　　　　　　　　　　　　　　　　　　　　　　　　            |
|ロール(ユーザ作成)　|CREATE \<username\> SATOU IDENTIFIED BY \<pass\> DEFAULT TABLESPACE TABSP1 TEMPORARY TABLESPACE TEMP QUOTA UNLIMITED ON TABSP1;|
|ロール一覧取得　　　|select username from dba_users;                                    |
|権限の追加　　　　　|GRANT SELECT ON \<tablename\>TO \<username\>; |

##パッケージのインストールについて
Instant Client Downloads 
oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm
oracle-instantclient11.2-sqlplus-11.2.0.4.0-1.x86_64.rpm をローカルPCにインストール
sudo rpm -ivh oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64.rpm
sudo rpm -ivh oracle-instantclient11.2-sqlplus-11.2.0.4.0-1.x86_64.rpm
##パスの設定をしないといけないよ
export LD_LIBRARY_PATH=/usr/lib/oracle/11.2/client64/lib
【C#】【WPF】カレンダーコントロールで選択不可日を指定する

UIとしてカレンダーで日付を選択させる際に
選択可能な範囲を制限したいケースがあると思います。
＃過去日付は選択不可とか

で、その場合にどうするかというと
選択できない日付を設定するためにBlackoutDatesプロパティを使用します。

単純に過去日付を選択不可にする場合は以下でOK。

```C#:現在日より過去を選択不可にする
    // 過去を選択不可能にする
    calendar.BlackoutDates.AddDatesInPast();
```

選択不可にする日付を具体的に指定したい場合は以下のように指定します。

```C#:選択不可日付を指定する場合
    // 2019年8月1日～8月31日を選択不可能にする
    calendar.BlackoutDates.Add(new DateTime(2019, 8, 1), new DateTime(2019, 8, 31));

    // 2019年9月1日を選択不可能にする
    calendar.BlackoutDates.Add(new DateTime(2019, 9, 1));
```

で、実際使用した際に起きた問題についても記載しておきます。
日付が変わったタイミングで動的に選択範囲を切り替えるような処理を組んでいたのですが、
その際にOutOfRangeException（範囲外エラー）が発生してしまうことがありました。
何故だ…と思っていましたが、原因がわかると実にシンプルでした。

例えば上記の例で、2019年8月1日～8月31日を選択不可能にする処理を実行した際に
カレンダーコントロールが指定している値が
『2019年7月31日』になっているとエラーになります。
つまり、範囲設定を行った際に現在の値が指定範囲外になっているとエラー。
確かに範囲外だわ…。

なので範囲指定を行う際は現在値もチェックしてあげると安全です。

```C#:範囲チェックしてから選択
var inputRange = new CalendarDateRange( new DateTime(2019, 8, 1), new DateTime(2019, 8, 31) );
if (inputRange.End < calendar.SelectedDate)
{
	// 選択不可範囲を指定しているとエラーになるので補正
	// (範囲終端を超えているので終端の日付に補正)
	calendar.SelectedDate = inputRange.End;
}
else if (calendar.SelectedDate < inputRange.Start)
{
	// 選択不可範囲を指定しているとエラーになるので補正
	// (範囲先端をより過去なので先端の日付に補正)
	calendar.SelectedDate = inputRange.Start;
}
// 2019年8月1日～8月31日を選択不可能にする
calendar.BlackoutDates.Add(inputRange);
```
IBM Cloud(旧SoftLayer)にVPNでアクセスする方法 2019年版

## IBM CloudガイドのVPN接続に関する説明が古い件

IBM CloudのIaaSにVPNで接続する必要があり、方法について調べました。
ところが、本家のガイドも、ネット上で出てくる有志のガイドも **Java applet**で接続する話になっていました。

なので、ガイド通りに操作しても、VPN接続できません。

Java appletってイマドキのブラウザでは動かないねんけど、、、、
これだけのために古いブラウザを入れたくないし。

本家のガイド　https://www.ibm.com/cloud/vpn-access



## VPNソフト

以下のサイトで配布されているVPNソフトを使えば、アクセスできるとのこと

Array Networks "Motion Pro Client"
https://support.arraynetworks.net/prx/001/http/supportportal.arraynetworks.net/downloads/downloads.html

Windows10用に、64bitのクライアントをダウンロードして入れてみました。

ところが、「VPNを確立できません」エラーで接続できず。あるぇー？

試行錯誤の結果、導入後、**「PCを再起動」** することで、接続できました。良かった!



## 愚痴
インストーラが、導入完了後自動的に再起動するダイアログをだしてくれたら、はまらずに済んだのに……

自分同様　ここで　はまる人がいるかもしれないので、記事をPostしておきます。



## 補記・英語版のガイド(19/8/7)
コメント欄にて、英語版のガイドだとVPN Clientの情報が載っていると情報頂きました。(@derao さん、ありがとうございます)

[Virtual Private Networks (VPN) / Standalone VPN clients - Windows, Linux, and Mac OS X]
(https://cloud.ibm.com/docs/infrastructure/iaas-vpn?topic=VPN-standalone-vpn-clients&locale=en)

* ガイドには記載ないですが、導入後、最後にPCを再起動させる必要があります。皆さんはお忘れなく。。


ググったらこのURLがまず出てほしいところですが、さすがに他力本願すぎですネ。

IBM も せっかく Watson Language Transratorなんてのあるんだから 古い日本語ページを放置せず、自力でリアルタイム翻訳すればいいのに、、、

ドッグフードを食べましょう精神です。
Oracle_Clientインストール/バージョン・32bit64bit確認

①install
--
自動インストール(管理者として実行)
"\\server\Oracle_12c_Client\setup.exe" -responseFile "\\server\Oracle_12c_Client\client.rsp" -silent

ODBCドライブをインストールする時、下記の3つだけを選択してインストールしていいです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381112/bcf4d1ec-1692-adce-9faa-26615febb91d.png)

②uninstall
--
自動uninstall
```
 (管理者として実行)
cd C:\app\client\product\12.2.0\client_1\deinstall
deinstall.bat -checkonly -o C:\Users\Oracle
deinstall.bat -paramfile "C:\Users\Oracle\deinstall_OraClient12Home1_32bit.rsp" -silent
```
C:\app\UserID\product\11.2.0\client_1\deinstall\deinstall.bat
右クリックして管理者として実行
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381112/c20a9de1-b679-f61b-fc43-afc2504f3584.png)

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381112/bce5670a-4d45-f83d-fab2-63bd1d5ce6d3.png)

アンインストールしても残る以下の2つのフォルダを削除します。
　「C:\app」
　「C:\Program Files\Oracle」
最後にレジストリを削除します。
.「HKEY_LOCALMACHINE\SOFTWARE\ORACLE」を探し、キーごと削除します。
https://www.projectgroup.info/documents/Oracle/ORA-110006.html

ORACLEクライアントのバージョンを確認
--
ORACLEクライアントのバージョンを確認するには、コマンドプロンプトで次のコマンドを実行します。
sqlplus -v


インストールされている Oracle が 32 ビット版 か 64 ビット版かを調べる方法
--
https://www.projectgroup.info/tips/Oracle/Oracle_000023.html
1.C:\app\product\11.2.0\client_1\cfgtoollogs\oui\installActions･･･.log
2.ログファイルをメモ帳で開き、'oracle_install_architecture'という文字列を検索します。
情報: 変数'oracle_install_architecture'を'64'に設定しています。コマンドラインから値を受け取りました。


tnsping
--
64bitと32bit両方インストールされています。
環境変数のpathに64bitが前にある場合、64bitで優先を利用してtnsping実行します。

```
C:\Users\admin>tnsping testdb

TNS Ping Utility for 64-bit Windows: Version 11.2.0.1.0 - Production on 06-7月 -
2021 11:19:15

Copyright (c) 1997, 2010, Oracle.  All rights reserved.

パラメータ・ファイルを使用しました:
F:\app\admin\product\11.2.0\client_64bit\network\admin\sqlnet.ora


エイリアスを解決するためにTNSNAMESアダプタを使用しました。
(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = server)(PORT =
 1521))) (CONNECT_DATA = (SERVICE_NAME = testdb.japan.makino.biz)))に接続の試行中
OK (0ミリ秒)
```
ログインシェルを変える (bash ←→ fish) [忘備録]

普段はfishを使っているのだが、bashを使いたくなるときもあるので、切り替えの方法をメモしておく。



まずはbashが使えるか確認。

```console
$ cat /etc/shells 

# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/usr/local/bin/fish
```
`/bin/bash`とあるので使えますね。

切り替え実行。

```console
$ chsh -s /bin/bash
```
これでおけ。


fishに戻すときは

```console
$ chsh -s /usr/local/bin/fish
```


🐟
postgresql　コマンドの備忘録

## テーブル
- テーブルの中身を確認
```select * from <table名>```


## rubyでgem pgを読み込んで使う時、rubyで扱えるように接続を行う必要がある。その時、dbnameを作成して指定してあげないとサーバを立ち上げた時にエラーを起こす。
`` client = PG::connect(
  :host => "localhost",
  :user => '', :password => '',
  :dbname => "myapp2") ``
【C#】イベントハンドラの処理をラムダ式で書く

C#でイベント関連の処理を書く場合に、
簡単な処理を行うだけなのにわざわざ関数を用意するのが手間だったので
ラムダ式で書いてみたのでその際の覚書。

```C#:ラムダ式でイベント処理
btnOK.Click += (sender, e) => { MessageBox.Show("OKボタンを押下！"); };
```

この記述の問題点としてはイベント解除が出来ないこと。
まぁ実際はボタン押下イベントとかは動的に登録/解除することはあんまりないと思うんだけど。

で、その場合にどうするかというと、以下のように書けばOK。

```C#:ラムダ式でイベント登録と解除
EventHandler handler = null;
handler = (sender, e) => { MessageBox.Show("OKボタンを押下！"); };
// 登録
btnOK.Click += handler;

// 解除
btnOK.Click -= handler;
```
要するにイベント解除する時は登録時と同じものを指定する必要があるので
EventHandlerを用意しておこう、ということ。

個人的にこの手法で便利だったのは、
ローカル変数をイベント処理内で参照出来る点。

具体的には元々ファイル検索みたいな処理を別スレッドで実行して、
処理が終わったらイベントが発行されるクラスがあって、
それを流用する際に同期的に使用する必要があったケース。
処理が終わったイベントで終了フラグをOnにして、
メインスレッド側ではその終了フラグがOnになるまで待機、みたいな処理を組む場合に
関数内て定義した情報だけで完結出来る。

```C#:別スレッドの処理待ち
bool isFinished = false;       // 処理完了フラグ
EventHandler finish = null;
finish = (object sender, EventArgs e) => { isFinished = true; };// 検索完了フラグを立てるだけ
var searcher = new Searcher(); // 検索用クラス
searcher.Finished += finish;   // 検索用クラスに完了イベントを登録
searcher.Start();              // 検索開始

// 検索が終わるまでここで待つ
while(false == isFinished)
{
    Task.Delay( 100 ).Wait();
}

// イベントハンドラ破棄
searcher.Finished -= finish;
```
従来通りに関数を用意していた場合は処理完了フラグをクラスのメンバとして持つ必要がある。
でもこの処理でしか使わないのであればローカルに留めておきたいので
この書き方は有りだと思います。
２４歳、エンジニア歴２年目がAR開発したい

AR技術は進んでいる
ポケモンGOであったり最近はハリーポッター、ドラクエなんかもAR技術を使用したゲームがリリースしている（される予定）


#　AR開発するにあたってタイプがある

ロケーションベース型、マーカー型、マーカーレス型のどれを使うか、または組み合わせるかを選びます。
ロケーションベース型は、GPSなどで位置情報を取得する機能が必要になります。また、位置認識の誤差に対する対処方法も考える必要があります。
マーカー型は、マーカーをスマートフォンなどで撮影するだけのシンプルなものであり、多くのARアプリで使われています。マーカーは実際に現実世界またはWeb上に存在している必要があるため見栄えなどの問題があり、管理をどのようにするのかを考える必要があります。
マーカーレス型は、スマートフォンなどに写っている映像から物体を検出する機能が必要になります。画像認識ライブラリなどのサポートが必要になってきます。
（未来技術推進協会さん参照、ありがとうございます）



**今回はマーカーレス型でやりたい**

今回見つけたマーカーレスできそうなライブラリをピックアップした

***ARToolkit(ARツールキット)*** と ***Vuforia(ビューフォリア)***

ビューフォリアはUnityと一緒に使って開発していくのがベターらしい
（unity版やとタダやからね、金は大切だ）

だから僕は今回ARツールキットの方でマーカーレス進めていくよ

##　マーカーありではできた ##

```html:index.html
<head>
  <!-- A-Frame ????? -->
  <script src="https://aframe.io/releases/0.8.2/aframe.min.js"></script>
  <!-- AR.js ????? -->
  <script src="https://cdn.rawgit.com/jeromeetienne/AR.js/1.6.2/aframe/build/aframe-ar.js"></script>
</head>

<body style='margin: 0; overflow: hidden;'>
  <!-- ?????? -->
  <a-scene embedded arjs="debugUIEnabled:false;">

    <!-- 3DCG???????? -->
    <a-assets>
      <a-asset-item id="vroid" src="marker/model.gltf"></a-asset-item>
    </a-assets>

    <!-- ?????????  -->
    <a-marker type='pattern' url='marker/pattern-frame.patt'>

      <!-- 3DCG???????? -->
      <a-gltf-model src="#vroid"></a-gltf-model>

    </a-marker>

    <!-- ?????? -->
    <a-entity camera></a-entity>
  </a-scene>
</body>

</html>

```
a-frameとAR.js使ってこんなかんじ、ほぼコピペだけどね





そしてついに見つけた
https://www.toyship.org/2018/06/05/193435
（記事書いてくれたTOYSHIP兄貴と記事見つけてくれたもぐ姉貴(@mgmgOmO )に感謝）

ARToolkit必要ないみたいなんで
この記事見ながらUSDZファイルつかってios12でAR表示やってきます＾ー＾

```:USDZとは
3Dオブジェクトを表示するための新しいファイルフォーマットです。
```



進捗状況次第でどんどん追記していきます！！！！！！！！みてね！！！！！