OmniAICreator/Qiita-1.07M huggingface dataset:
Colab上でTensorFlow Object Detection APIを用いて作成したモデルをtfliteに変換する

# はじめに
この記事は [NCC Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ncc)の9日目の記事です

Google Colaboratory上でTensorFlow Object Detection APIを用いて学習したモデルをtfliteに変換するまでの手順を見つけ出せたので共有します。
###前提条件
アノテーションや学習をすでに済ませており、手元に.pdファイルがあることを前提としています。モデルを作成するまでの手順は下記の記事を参考にしてください。

[Tensorflow Object Detection API : Google Colaboratory環境で学習を実行する（環境構築）](https://qiita.com/hirokikmr/items/f89d5405aa7e385dff7e)
[TensorFlowの「Object Detection API」で物体検出の自前データを学習する方法](https://qiita.com/karaage0703/items/76ef6b774e3cd69028bb)

###実行環境
学習まではColabで行っています
以下、ローカルPCでの実行環境です
OS: macOS Catalina 10.15.1
CPU: Intel Core i5 2.3GHz
GPU: Intel Iris Plus Graphics 655 1536 MB
メモリ: 16 GB 2133 MHz LPDDR3
Bazel: v0.29.1

#学習の際に用いたConfigファイルを確認する
TensorFlow Liteのモデルは、量子化されている必要があります。デフォルトではその設定がされていないはずので、まず最初に自分が学習の際に用いたConfigファイルに以下のような内容が含まれているかどうか確認してください。含まれていない場合、変換できても意味不明な認識結果になるだけなので含めてから学習をやり直してください。頑張ってね。

```xxx.config
graph_rewriter {
  quantization {
    delay: 1800
    activation_bits: 8
    weight_bits: 8
  }
}
```

#tfliteに変換
ここからはColab上ではなくPC上で作業を行います。ColabでGoogleドライブをマウントさせる際のディレクトリ名 `/content/drive/My Drive/`にスペースが含まれており、その下で変換の際に用いるBazelというビルドツールを実行することができない問題があるためPC上での作業が必要となります。.pdファイルをドライブからPC上の任意のディレクトリに置いておいてください。　
###TensorFlowをインストール
下記二つのコマンドを実行
`pip install tensorflow`
`git clone https://github.com/tensorflow/tensorflow.git`

###Bazelをインストール
以下のページを参考にしてBazelをインストールしてください。
https://docs.bazel.build/versions/master/install-os-x.html#install-with-installer-mac-os-x
###ついに変換！
`tensorflow`ディレクトリに移動し、下記のコマンドで必要な箇所を変更して実行してください。

```
bazel run -c opt tensorflow/lite/toco:toco -- --input_file=[入力ディレクトリ]/graph.pb --output_file=[出力ディレクトリ]/detect.tflite --input_shapes=1,300,300,3 --input_arrays=normalized_input_image_tensor --output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3'  --inference_type=QUANTIZED_UINT8 --mean_values=128 --std_values=128 --change_concat_input_ranges=false --default_ranges_min=0 --default_ranges_max=6 --allow_custom_ops
```
detect.tfliteというファイルが出てきたら大成功です！

#終わりに
かなりかっ飛ばした感ありますけどできました？書いてみると意外とあっさりとできる感じがしますが、この方法探し当てるまでに二ヶ月かかってるんですよねー...　まあそんなもんですよね (^^)b

#参考ページ
[Tensorflow Object Detection API : Google Colaboratory環境で学習を実行する（環境構築）](https://qiita.com/hirokikmr/items/f89d5405aa7e385dff7e)
[TensorFlowの「Object Detection API」で物体検出の自前データを学習する方法](https://qiita.com/karaage0703/items/76ef6b774e3cd69028bb)
[Training and serving a realtime mobile object detector in 30 minutes with Cloud TPUs](https://medium.com/tensorflow/training-and-serving-a-realtime-mobile-object-detector-in-30-minutes-with-cloud-tpus-b78971cf1193)
オンラインサロンを活用した複業のススメ

はじめまして、シャンディです。便利屋Guildというオンラインを得意とした現代版なんでも屋の代表をしています。

現在、便利屋Guildの事業としては以下のことに注力して取り組んでいます。

- 地方創生コンサルティング
- シェアハウス/ゲストハウスコンサルティング
- オンラインサロンサポート運用
- 各種代行業務（ライター/動画編集/データ入力）
- 複業サポート
- 旅人育成などなど

特に今回はサポートとして入らせていただいているデータラーニングギルドを含む、オンラインサロンの有用性について書かせていただきます。


<h3>なぜオンラインサロンがいいのか</h3>
日常生活が楽しくないとか、なんか面白いことがないかなぁとか、そんなことを考える人にはオンラインサロンはとても魅力的なサービスだと僕は考えています。

僕自身、「旅」が好きなこともあり少し偏った意見にはなりますが、現在の日常に不満があり、それを変えるための方法としてオンラインサロンが一般化されるまでは以下の3つを提案していました。
- 旅に出る
- 転職する
- 引越しをする

ただ、この3つどれも簡単にできるものではなく、色々なコストがかかってしまうというのも正直なところではありました。精神的なコストもリアルマネー的なコストも含めて。

そこに登場してきたのが最近のオンラインサロンの流れです。

環境を変えずに、月額の定額料金で自分と同じ想いの人たちと、世界のどこにいても繋がれるのです。

mixiのコミュニティやFacebookの趣味ページと似たような性質を持っている感じもすると思いますが、「有料」であることがかなりポイントになります。

無料のコミュニティは荒らしがでてきたり、入っているメンバーから反応がなくなったりということが多々あります。

それもそのはずで、熱量にバラツキがあるのでそうなっても仕方がないです。

一方でオンラインサロンは基本的にどこも月額定額であり、お金を払ってでも繋がりたい、情報を得たいという人たちが集まります。

主催者側も無料のコミュニティとは違い、金銭というバックを得て運用を行うので双方にメリットがあります。

<h3>オンラインサロンで複業？</h3>
ここ1-2年でオンラインサロンは劇的に増えました。色々なタイプのオンラインサロンがありますが、データラーニングギルドを含む、スキル習得系のオンラインサロンは複業にとても向いています。

先にも述べた通り、低コストでかつ、場所も時間も問わず始めることができるからです。

従来は資格の勉強だったり、スキルの取得のためには専門学校やスクールに通う必要がありました。

サラリーマンの場合は平日の仕事終わりに決められた時間に決められた場所に行く必要があるこれらの行為はかなり心理的にも肉体的にも負担があったのではないでしょうか。

それがオンラインサロンの登場で、好きな場所で好きな時間にスキルを習得できるようになりました。

データサイエンティスト向けの当サロンを筆頭に、YouTuber向けや、ブロガー向け、英語学習やフリーランス向けなどなど。

そして月額のため、少し興味のある分野に入ってみて、違うなと感じたら辞めればいいのです。

資格の専門学校のように入学金や、高額な年額での支払いもないため一歩目のハードルが格段に下がりました。

さらに最近のオンラインサロンの傾向として、サロン内で真摯に活動していれば、優先して仕事をもらえたり、サロンメンバー同士でチームを組み仕事を作るということも増えてきました。

言い換えるとサラリーマンとして平日の昼間に働き定額を稼ぎながら、残りの時間で徐々にオンラインサロンを活用して副収入を育てていくということができるようになったのです。


ただし自己管理ができ、努力をしている場合には限りますが。カリキュラム的なものが必要だったり、管理されていないと勉強できないというような人には従来の専門学校や、オンラインスクールのほうが向いてるとは思います。



<h3>なぜオンラインサロンのサポートが必要か</h3>
そんな流れもあり最近ではオンラインサロンを開設する方が増えてきました。

が、オンラインサロンを作る方々は何かしら本業を持っている方々がほとんどです。

そしてほとんどの場合がオンラインサロンの入退会管理や懇親会といった運用に段々と時間をとられ、本業の時間を大幅に割くカタチになったり、最悪の場合はオンラインサロン運用に疲れ閉鎖するといった事例をたくさん見てきました。

そういった本業とは関係のない部分や、定期的に発生するイベントをサポートすることで、サロン運営者の負担を減らし、かつサロンを活発化させることで参加者の満足度も高めるということを便利屋ギルドではさせていただいております。

特にパソコン関係にあまり詳しくないお客様がコミュニティ運営をしたいけどどうしていいかわからないという声をよくいただき、お手伝いさせていただいております。


<h3>さいごに</h3>
はじめてのアドベントカレンダー参加となりましたが、いかがでしたでしょうか。

オンラインサロンにより何かをはじめる一歩目が格段にハードルが下がりました。まだまだ可能性がある仕組みだと思っていますので、一緒にコミュニティを盛り上げていけたらなと思っております。
CentOSにchromeを入れる

#はじめに
CentOS入れてブラウザーのchromeを導入します。

#実行するコマンド
以下のコマンドをコピーペースとしてterminalで実行します。ヒアドキュメントにしておきました。

```
cat << EOS > /etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/\$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
EOS
yum -y install google-chrome-stable
```

#おわり
情報をさがすのに好きなブラウザを使いたいので、すぐに入れたくなります。
この2019年12月に初学者がRかPythonを学ぶなら、どっち？

#RとPythonどっちが良い？？
最近はだいぶPythonから入って、Rは別に、、みたいな人も増えましたが、よくある疑問が「RとPythonどちらを覚えるべきか？」ですね！

個人的な答えは「両方覚えれば？」です笑
どちらか一つしか選べない、というものでもないですし、求人とか見ても「RやPyhonを用いて分析した経験」のように両方書いてあることも多いので。
何より、どちらかしかわからない人より、両方わかるほうが市場価値は高いんじゃないでしょうか。（もちろん、これだけで市場価値は決まらないですけどね）



#とはいうものの初心者が始めるにはどっちが。。。
ただ、初学者がいきなり両方勉強するのはなかなか大変かと思いますので、まずどちらか入るべきか？という視点でいくと下記のようになるかなと。。



R

・プログラミングがそもそも初心者

・記述統計寄りのバックグラウンドで、そちら寄りの分析がしたい



Python

・機械学習寄りのことがしたい

・画像認識などをやりたい



#だいたいどちらでも同じことができる
階層ベイズモデルなり、状態空間モデルなり、MCMC推定なり、クラスターなり、判別モデルなり、勾配Boostingなり、このあたりはRでもPythonでもどちらでもできます。

ただ、個人的には変数加工する際にRStudioを用いれば列数・行数を確認しながら行えるので、Rのほうがおすすめです。（PythonならSpyderがおすすめです）

一方、画像解析系はPythonのほうがおすすめです。これは圧倒的にPythonでの事例が多いので、困ったときにググって解決できるからです。



#時代はPython?
なんとなくPyhonから入る人が増えているように思えますし、会社に入社してくる学生や、インターン生もPython使いの比率が増えてきているように思えます。

ならば、Rの時代は終わるのか？というとわかりません笑

ただ、完全に需要がなくなるのはまだ先かなと。そのときにPython使いだらけの中、Rが使えれば市場価値は高そうですよね。なので、個人的には両方覚えちゃえば？と思ってます。

またJuliaなんて言語が次に流行る！とも言われているので、学び続ける姿勢が何より大事かなと。。
Rubyで競プロする上で避けたい2つの遅いメソッド

*注意: この記事はRuby2.3系の頃の話で、現在(2021/05)のAtCoderはruby 2.7系のため、同じ挙動ではないかもしれません。*

## 競プロで避けたい2つのメソッド
ABC 147Dで痛い目を見たのでまとめておきます。
https://atcoder.jp/contests/abc147/tasks/abc147_d

### [each_with_index](https://ref.xaio.jp/ruby/classes/enumerable/each_with_index)  
ブロックの外で変数を宣言し、自分でインクリメントしたほうが早い。
`596.8 i/s`(each_with_index) vs `704.4 i/s`(ブロック外変数をインクリメント)
(秒間何回処理を実行できるかの比較)

### to_s(2)
[Integer#to_s](https://docs.ruby-lang.org/ja/latest/class/Integer.html#I_INSPECT) は引数の進数展開してくれますが、これが遅かった。
全bitを確認する場合でも、bit shiftしながら確認していったほうが早いです。
`1783.4 i/s`(while loop) vs `704.4 i/s`(to_s(2))

<details><summary>実行コード</summary>
<div>

```ruby
require 'benchmark/ips'

cons = 100.times.with_object([]) { |_i, obj| obj << rand(1 << 60) }
ary_to_s1 = Array.new(60, 0)
ary_to_s2 = Array.new(60, 0)
ary_while = Array.new(60, 0)
ONE = '1'.freeze
Benchmark.ips do |x|
  x.config(:time => 20, :warmup => 0)

  x.report("each_with_index") {
    cons.each do |num|
      num.to_s(2).chars.reverse.each_with_index do |x, i|
        ary_to_s1[i] += 1 if x == ONE
      end
    end
  }
  x.report("index") {
    cons.each do |num|
      index = 0
      num.to_s(2).chars.reverse.each do |x|
        ary_to_s2[index] += 1 if x == ONE
        index += 1
      end
    end
  }
  x.report("while") {
    cons.each do |num|
      tmp = num
      ind = 0
      while tmp > 0
        ary_while[ind] += tmp%2
        tmp = tmp >> 1
        ind += 1
      end
    end
  }

  x.compare!
end
```

</div>
</details>

```
Comparison:
               while:     1783.4 i/s
               index:      704.4 i/s - 2.53x  slower
     each_with_index:      596.8 i/s - 2.99x  slower
````

`Ruby 2.3.3` で確認
Roslynは怖くない

#これについて
自分用のメモがてらさっくり書く

#Roslynってなんぞ
正直このサイトがしっくりきた
[Visual Studio 2015の新機能“Roslyn”とは](https://www.buildinsider.net/enterprise/roslyn/01)

そんなの読みたくないよーって人向けにざっくりいうと
Visual StudioでC#書いてるとき、エディタが構文を解析して、ここエラーだよとか教えてくれるじゃないですか。
その、構文解析データを使えるようにもなったしコンパイラ側も使ってるよって話。

#なにに使えるの
拡張機能だとか、C#のファイル投げたらメソッド名を全部ランダムな文字列に変えるソフトだとか。
Microsoftが例として提供してるのは[const fix](https://docs.microsoft.com/ja-jp/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix)です。
こいつは定数化しても問題ない変数なのに定数化されてないものを定数化する拡張機能です。
コード自体は、Visual Studioで[新しいプロジェクト]からRoslynと検索すると出てくるものを作成するとテンプレートで生成される。

#拡張機能の作成に必要なもの
* SyntaxVisualizer [.NET Compiler Platform SDK](https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.NETCompilerPlatformSDK)
これで構文木が見えるようになる。
* [Microsoft提供のドキュメント](https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.csharp.syntax?view=roslyn-dotnet)を読む体力
* 根気

#ほかの人の参考になればいいな
僕の作ったすべてのノードの中身を吐き出すやつ
https://github.com/A1g0/RosConvertTex

SyntaxWalkerっていう与えられたノードの子ノードをすべて巡回するやつを使ったりしてる。
名前の通りC#をtexに変換しようとしたけど(見栄えを良くするために)、どうにかなったのでやらなかった。
組織内で記事・文章作成する時は早めにレビューしてもらう

これは [記事・文章作成は流れに沿ってやればいい](https://qiita.com/ymatsukawa/items/edb894d674b88a7b5e4c) の補足的記事である。

# 記事・文章作成の流れをおさらいする

```
* (1) ターゲットを絞る
* (2) テーマ(= ターゲットに一番何を伝えたいか)を決める
* (3) 枠組み(見出し・流れ)を決める
* (4) 各見出しについて、伝えたいことを 3 つ箇条書きする
* (5) 箇条書きを文書にする
* (6) 改めて、上から下に読める流れかを確認する
* (7) 少し時間をおいて全体を見直す
```

# 大体の形が出来たらレビューしてもらう

上の流れに記された (1) - (4) まで出来たら、つまり **大体の形が出来たらレビューしてもらう**。

これで

* (1) ターゲットに漏れがある
* (2) テーマ(伝えたいこと = やるべきこと) がややズレている
* (3) 枠組みが誤っている
* (4) 枠組みはおおよそ合っているが、伝えたいこと(= 書く内容) がズレている

といった**「マズいこと」を早めに検知**できる。

もし全部やった後にレビューしてもらうと「手戻り」になるリスクが非常に高い。

**「大体の形」が出来た時にレビューしてもらおう。**

もちろん、これは記事・文書作成 以外の場面でも役に立つ。

次の場面以外にないか、よく考えてみよう。


* プルリクエスト
* マージリクエスト
* 企画書・提案書を作る時
* 仕事の進め方を決めるとき
* etc.
チェリー本を読んだまとめ(一部)

[チェリー本(プロを目指す人のためのRuby入門)](https://www.amazon.co.jp/dp/4774193976/ref=cm_sw_r_tw_dp_U_x_yPq7DbN1RXP1P)を改めて読んだ際の気づきや発見の一部まとめです。

###ブロック引数について
```
menus = [
  ["ハム", 100],
  ["パスタ", 200],
  ["ピザ", 300]
]

menus.each do |menu,price|
  puts "#{menu} #{price}円" 
end

//下記のように書ける
menus.each do |menu,price|
  puts "#{menu} #{price}円" 
end

//each_with_indexも
menus.each_with_index do |menu,i|
  puts "#{i}番 #{menu[0]} #{menu[1]}円" 
end

//下記のように書ける
menus.each_with_index do |(menu,price),i|
  puts "#{i}番 #{menu} #{price}円" 
end
```
###ブロックローカル関数
```
//「; sum」でブロック内でのみ有効なローカル変数を定義できる
menus.each do |menu,price; sum|
  sum = 0
  puts "#{menu} #{price}円" 
  sum += price
  puts sum
end
```
###ブロックを渡すと、ブロックの戻り値が要素が見つからないときの戻り値になる
```
menus.delete(100) 
→nil

menus.delete(100) {'not_found'}
→not_found
```
###Arrayクラス
https://docs.ruby-lang.org/ja/latest/class/Array.html
###Enumerableモジュール
https://docs.ruby-lang.org/ja/latest/class/Enumerable.html

###while文
```
//条件が偽のため実行されない
while false
  puts "NG"
end

//最低1回は実行される
begin
  puts "OK"
end while false
```

###breakの戻り値
```
i = rand(3)
ans =
loop do
  break 0 if i == 0
  break 1 if i == 1
  break 2 if i == 2
end
puts ans // 0〜2のランダムな数字
```
###ループからの脱出
```
catch タグ do
  throw タグ
end
```
###redo
```
//処理を繰り返す
menus = ["ハム", "パスタ", "ピザ"]
count = 0
menus.each do |menu|
  puts "それは和食ですか？(#{menu})" 
  ans = "違います"
  puts ans

  count += 1
  redo if ans != "そうです" && count < 2

  count = 0
end
```
###ハッシュの展開
```
menus = {
  ハム: 100,
  パスタ: 200,
  ピザ: 300
}

new_menus =  {コーヒー: 100, **menus}　//または{コーヒー: 100}.merge(menus)でも同じ
p new_menus //{:コーヒー=>100, :ハム=>100, :パスタ=>200, :ピザ=>300}
```
###**引数
```
def menu_output(menu, **others)
  puts others
end

menu_output('パスタ', dessert:'ケーキ') //{:dessert=>"ケーキ"}
```
###ハッシュの初期値設定
```
h = Hash.new{ 'def' } //Hash.new('def')としてしまうと同一オブジェクトとなってしまうので注意
a = h[:hoge] //"def"
b = h[:fuge] //"def"
h // {}

h = Hash.new{ |h, k| h[k] = 'def' }
a = h[:hoge] //"def"
b = h[:fuge] //"def"
h // {:hoge=>"def, :fuge=>"def}
```
###シンボルの式展開
```
menus = {
  pizza: 300
}

menu = 'pizza'
p menus[:"#{menu}"] // 300
```

###文字列からシンボルへの変換
```
p 'abc'.to_sym // :abc
```

###||=を使った自己代入
```
count ||= 0 //countがnilまたはflaseであれば0を代入する。それ以外はcountをそのまま使用する
```
### !!を使った型変換
```
!!find_pizza //先頭に「!!」を付与して、trueかfalseに変換する
//上記のようにメソッドの返り値で存在判定できる。falseとnilはfalse、それ以外はtrueとなる
```
###アクセサメソッド
```
//読み書き
attr_accessor :name
//読み取り専用
attr_reader :name
//書き込み専用
attr_writer :name
```
###メソッドの存在確認
```
name = "yamada"

name.respond_to?(:upcase) //true upcaseはStringクラス
name.respond_to?(:join) //false joinはArrayクラス
```
###クラスの親クラスを配列にして返すancestorsメソッド
```
Array.ancestors
=> [Array, Enumerable, Object, Kernel, BasicObject]
```
###メソッドの定義場所を確認
```
//rails console
name = "yamada"
=> "yamada"
name.method(:present?).source_location
=> ["/usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/core_ext/object/blank.rb", 26]
```

以上です。
いいねやQiitaやTwitterのフォローいただけると励みになります！
お気軽にどうぞ〜

お疲れ様でした！！！
SwiftでUILabelのテキストを中央に表示する。(複数行)

タイトル通りです。
しかし、意外と一つにまとまっているものがなかったので書いてみます。
ついでにlabelで複数行記述しています。　　
　　


```swift
let label = UILabel()

// widthは適当に設定。画面幅を取得しlabelが中央に配置されるようにする。
let screenwidth = Float(UIScreen.main.bounds.size.width)
let width = 300
let widthGap = (screenwidth - Float(width)) / 2
label.frame = CGRect(x: Int(widthGap),
                             y: 100,
                             width: Int(width),
                             height: 60)
// textAlignmentで文字を中央揃えに。
label.textAlignment = NSTextAlignment.center

// numberOfLinesで行数を規定、これを設定しないと\nが意味をなさない
label.numberOfLines = 2;
label.text = "一行目\n二行目"
self.view.addSubview(label) //labelを表示
```
 　　
　　

実行結果はこんな感じ。
<img width="350" alt="スクリーンショット 2019-12-08 23.17.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540869/55927f9b-8887-8067-bd11-b89a6a8baf6c.png">

　　
ほぼ備忘録ですし、もっといい方法があるかもしれません。
サクラエディタ 設定メモ

# 使っているバージョン
Ver. 2.2.0.1


# ツールバー
## ツールバー設定方法
メニュー ＞ 設定 ＞ 共通設定 ＞ ツールバー

## ツールバー設定
### ファイルを開く、保存、印刷
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| 新規作成 | ファイル操作系 |  |
| 開く(ドロップダウン) | ファイル操作系 |  |
| 上書き保存 | ファイル操作系 |  |
| 名前を付けて保存 | ファイル操作系 |  |
| 印刷プレビュー | ファイル操作系 |  |

### 編集(Undo、Redo)
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| 元に戻す | 編集系 |  |
| やり直し | 編集系 |  |

### 設定内容の確認、変更
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| タイプ別設定一覧 | 設定系 |  |
| タイプ別設定 | 設定系 |  |
| 共通設定 | 設定系 |  |

### 便利系(高頻度)
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| 常に手前に表示 | ウィンドウ系 |  |
| 開き直す | ファイル操作系 | ファイルの読み取り専用属性の変更を反映する |
| ビューモード | ファイル操作系 | 編集できなくする |
| 同名のC/C++ヘッダ(ソース)を開く | ファイル操作系 |  |
| アウトライン解析 | 検索系 |  |

### 画面表示の変更
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| 折り返さない | 設定系 |  |
| 右端で折り返す | 設定系 |  |
| 指定桁で折り返す | 設定系 |  |
| 折り返し桁数 | 設定系 | 現在のウィンドウ表示幅を折り返し桁数に設定する |
| ステータスバーの表示／非表示 | 設定系 |  |
| ミニマップの表示／非表示 | 設定系 |  |
| ブックマークの全解除 | 検索系 | ブックマーク(行番号のハイライト)を全解除する |

### ファイルを開き直す(文字コード指定)
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| SJISで開き直す | ファイル操作系 |  |
| EUCで開き直す | ファイル操作系 |  |
| UTF-8で開き直す | ファイル操作系 |  |

### 編集(整形)
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| 左(先頭)の空白を削除 | 編集系 |  |
| 右(末尾)の空白を削除 | 編集系 |  |
| 選択行の昇順ソート | 編集系 |  |
| 選択行の降順ソート | 編集系 |  |
| 連続した重複行の削除(uniq) | 編集系 |  |

### 情報コピー
| 機能 | 種別 | メモ |
|:-----|:-----|:-----|
| このファイルのパス名をコピー | クリップボード系 |  |
| このファイル名をコピー | クリップボード系 |  |


# ショートカットキー
## ショートカットキー設定方法
メニュー ＞ 設定 ＞ 共通設定 ＞ キー割り当て

## ショートカットキー設定設定
（準備中）
vagrant環境のseleniumで、chromeブラウザをGUIで動作させる

## はじめに
CentOSは基本CUIのため、seleniumを実行するときはheadlessモードで動かしていましたが
画面確認の度にスクリーンショットを撮っていて開発効率が落ちていました。
そこで開発時は非headlessモード、運用時はheadlessモードと分けたいと思いました。

以下のような方には当てはまるかと思います。

・ホストOSに開発環境を構築して汚したくない
・開発環境は統一しておきたい
・スクレイピングをする際、スクリーンショットでちまちま画面確認するのが面倒

## 環境
・macOS Catalina（ホスト）
・vagrant + CentOS7（ゲスト)
・python + selenium（chromedriver）

## X11サーバーをインストール

X11サーバーをMacOSにインストールします。
現在は同梱していないそうなのでXQuartzプロジェクトから入手します。

XQuartz
https://www.xquartz.org/

## Vagrantfile

以下の1行を追加することで、Linux側のDISPLAY環境変数が設定されます。


```ruby:Vagrantfile
config.ssh.forward_x11 = true
```
X11 ForwardingでChrome（Xクライアント）は、DISPLAY環境変数で指示されたXサーバーと通信して画面を出します。
既に`vagrant up`で起動済みの場合は、`vagrant reload`で読み込み直して下さい。

## ソースを修正する

headlessモードのオプションをコメントアウトします。

```python:main.py

# coding:utf-8
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep


def main():
    try:
        options = Options()
        # ヘッドレスモード
        #options.add_argument('--headless')
        # ユーザーエージェント
        options.add_argument('--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36')
        # 日本語
        options.add_argument('--lang=ja')
        # 起動
        driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver', chrome_options=options)
        # 10秒待機
        sleep(10)
    finally:
        # 終了
        driver.quit()


if __name__ == '__main__':
    main()
```

## 実行

実行し、mac側にブラウザが表示されれば成功です。

```
$ python main.py
```

<img width="1078" alt="chrome.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547737/af692746-772d-4698-f162-983018f29b5b.png">

## 終わりに

文字化けする場合はフォントのインストール等行なってください。
X11 forwardingすると`send_keys`で一部の文字が入力できなくなる現象はなぜだろう？
Nefry Cloud Appつくってみた

こんにちは、わみです。

2年前につくったNefryクラウド(仮)のアップデートをしてみたので、記事をまとめてみようと思います。

[![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97208/3f6eeb50-d57a-d25a-6a41-3beaa5b89d4b.png)](https://qiita.com/wamisnet/items/38d6a5ac8332b090d0c2)

https://qiita.com/wamisnet/items/38d6a5ac8332b090d0c2


# なにを作ったか

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Nefry Cloud Appなるものをつくってみた <a href="https://t.co/rl1OsulYWm">pic.twitter.com/rl1OsulYWm</a></p>&mdash; わみ@NefryとかFlutter本とか (@wamisnet) <a href="https://twitter.com/wamisnet/status/1203677894599303168?ref_src=twsrc%5Etfw">December 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こんな感じのコードでNefryを動かせるようにしました。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Nefry Cloud App</title>
    <script src="NefryCloudApp.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <!-- UIkit CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.3/dist/css/uikit.min.css" />
</head>
<body>
    <H1>Nefry Cloud App</H1>

    <button class="uk-button uk-button-default" id="red">LED Red</button>
    <button class="uk-button uk-button-default" id="blue">LED Blue</button>

    <script>
        let nefry = new NefryCloudApp("NefryCloud user","NefryCloud Key","Device ID");

        $("#red").on("click", function(){
            nefry.setLed(255,0,0);
        });

        $("#blue").on("click", function(){
            nefry.setLed(0,0,255);
        });
    </script>
</body>
</html>
```

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97208/8ea96d81-a96d-73b0-aad9-651d3135d31a.png)

# どうしてつくったのか

Nefryを専門学校の授業で使用するにあたって授業の難易度的にC言語から始めるのは難しくそのつなぎとして始めるのがJavaScriptでできると非常に導入しやすい。

開発環境を整えなくても使えるのは非常に便利。

# 技術構成

Nefry <--> Nefry Cloud <--> JavaScript

基本的な構成はNefry Cloudの拡張になります。

Nefry Cloudの仕組みを拡張して、データにそれぞれのLEDの制御だったりを入れてやり取りするようにしています。

ハードウエア側はディスプレイにDeviceIDを表示するようにして、一意に扱えるようにしています。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97208/cafdbf06-b55e-50ec-fd0c-4228999b8e84.jpeg)

# まとめ

簡単にNefryCloudAppの紹介をしてみました。

もし使ってみたい方がいたら、私のTwitterにでもメッセージを送ってもらえれば、コードの本体を渡そうかと思いますので、ぜひ！

簡単にIoTの環境を作れるようになったのはいい世の中だなあと思います
DRONE HUBの構成管理をAnsibleで運用している話

DRONE HUBの構成管理をAnsibleで運用している話

# はじめに

[SENSYN Robotics](https://www.sensyn-robotics.com/)(センシンロボティクス)の中山です。
Webアプリやそのインフラ周りと、Web側とドローンの接続を行うデバイスドライバ的な部分を担当しています。

今回はDRONE HUB内部の構成管理をAnsibleで行う話です。

# Ansible on DRONE HUB

Ansibleはサーバ管理で使うイメージが強いツールですが、開発環境の作成等でも使うことがあり、同様にLinuxやWindowsが載ったドローンでも利用できます。

DRONE HUBの内部ではUbuntu Linuxが動いており、[データをクラウドと同期する機能](https://qiita.com/nakayamaatsushi/14d4b56c8be76ceb0b14)や[通信を秘匿化するSSH port forwarding](https://qiita.com/nakayamaatsushi/8721f90c0b4ad9025527)等、様々なソフトウェアが走っています。このソフトウェア群のデプロイや設定変更を機体ごとに行うのはそれなりに手間なので、Ansibleを使って実行しています。

sshで機体に入って手で一機ずつ設定するのに比べると、

* 操作ミスや漏れによる設定の差異をなくせる
* デプロイする対象や方法をGitで管理できるので、レビュープロセスを通せる
* 機体ごとに設定する値(公開鍵やAPI Key)を集中管理できる
* Playbookを実行するだけなので、同時に複数機体へのデプロイができる
* 出荷時の手間を減らせる

といったメリットがあります。

# 具体的なデプロイ対象

機体へのデプロイでは、下記の機能をAnsibleで自動化しています。

* [撮影データをクラウドと同期する機能](https://qiita.com/nakayamaatsushi/14d4b56c8be76ceb0b14)
* [MQTTをSSH port forwarding経由で秘匿化する設定](https://qiita.com/nakayamaatsushi/8721f90c0b4ad9025527)
* LTEモジュールの設定

他にも、連携するシステムとしてw離着陸時に警告するためにパトランプがあるのですが、そのソフトウェアのデプロイにも使っています。パトランプを回すかどうかの判定をRaspberryPiで実装しています。

# 実装

AnsibleはPythonで実装されており、Pythonといえば[本体やライブラリのバージョン管理が複雑](https://qiita.com/ganariya/items/1bf870275bad7b5ab506)なことで有名です。Pythonの環境管理で煩わされたくなかったので、素直にDokcer HubのAnsibleイメージを使いました。

```shell
docker pull cytopia/ansible:2.8-tools
```

実行するときはMakefileを使っています。

## Makefileの中身

```
deploy/lte:
	cd lte \
	&& docker run \
		--rm \
		-it \
		-v $$(pwd):/opt/scripts \
		-v $$(pwd)/../settings:/opt/settings \
		-v $$(pwd)/../settings/ansible.cfg:/etc/ansible/ansible.cfg \
		cytopia/ansible:2.8-tools \
		sh -c "ansible-playbook \
				-i /opt/settings/host.ini \
				playbook.yml"
```

## Makeの実行

```shell
make deploy/lte
```

Playbookはいくつかのロールに分けています。

## Playbook

```yaml
- hosts:
    - vehicle
  become: yes
  vars_files:
    - vars/common.yml
  roles:
    - device
    - ppp
    - boot
```

`device`ロールでLTEモジュールをUSBモデムとして認識させ、`ppp`ロールでUSBモデムを使ったPPP通信の設定を行います。これらの設定をブート時に有効にするのが`boot`ロールで、systemdのUnitをデプロイするようになっています。

他の機能のデプロイでも、同じようにソフトウェアのレイヤーをロールに割り当てるイメージで管理しています。他にいい方法があったら、コメント欄でヒントを頂けると嬉しいです。

# まとめ

* Ansibleはサーバ管理だけではなく、ドローン内部のソフトウェアを管理するのにも便利
* ソフトウェアのレイヤーをAnsibleのロールに割り当てるイメージで管理している
【Rails Tutorial】8章まとめ

```
$ rails g controller Sessions new
```

`rails g` で`new`アクションを生成すると、それに対応ビューも生成されてる
`create`や`destroy`には対応するビューが必要ないので、無駄なビューを作成しないためにここではnewだけを指定する


# 8.1.3 ユーザーの検索と認証
ログインでセッションを作成するときに最初に行うのは、入力が無効な場合の処理
次にログインが失敗した場合に表示されるエラーメッセージを配置
次にログインが成功した場合に使う土台を作==
SORACOM LTE-M Button(powered by AWS)でAWS LambdaのFunctionを呼び出すときのevent

SORACOM LTE-M Button(powered by AWS)でAWS LambdaのFunctionを呼び出すときに、
eventとして渡ってくる内容について整理する

<img width="400" alt="SORACOM LTE-M Button powered by AWS" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19870/182638d5-d993-1fe9-8596-18dfb6e95e7f.jpeg">


# 前準備
- SORACOM LTE-M Button powered by AWSをSORACOMコンソールに登録する
    - https://dev.soracom.io/jp/start/aws_button_registration/
- AWS IoT 1-Clickに紐付けする
    - https://dev.soracom.io/jp/start/aws_button_slack/

# AWS LambdaのFunctionを呼び出す設定
AWS IoT 1-Clickのテンプレート設定で、
アクションに「Lambda 関数の選択」を選択し、実際に動かすLambda関数を指定します。
<img width="972" alt="AWS IoT 1-Click テンプレート" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19870/f45e19c6-8815-2fb7-bab7-a7639600f484.png">



# 実際に渡ってくる内容
eventとして連携されてくるjson内容を出力してみた。
これがわかっていると、実機がなくてもLambdaでテスト実装することができる。

```json
{
  "deviceInfo": {
    "deviceId": "****************",
    "type": "button",
    "remainingLife": 76.69762,
    "attributes": {
      "projectRegion": "us-west-2",
      "projectName": "iotbutton_yesno",
      "placementName": "iotbutton_yesno",
      "deviceTemplateName": "iotbutton_yesno"
    }
  },
  "deviceEvent": {
    "buttonClicked": {
      "clickType": "DOUBLE",
      "reportedTime": "2019-12-08T12:34:56.789Z" 
    }
  },
  "placementInfo": {
    "projectName": "iotbutton_yesno",
    "placementName": "iotbutton_yesno",
    "attributes": {}, 
    "devices": {
      "iotbutton_yesno": "****************" 
    }
  }
}
```

イベント情報を噛み砕いてみる

 - ```deviceEvent.buttonClicked``` : ボタン側で起きたイベントの情報
    - ```clickType``` : SORACOM LTE-M Buttonがどう押されたか
        - SINGLE : 1回押し
        - DOUBLE : 2回押し
        - LONG : 長押し
    - ```reportedTime``` : ボタンが押された時間
- ```placementInfo``` : AWS IoT 1-Clickで登録されているプレイスメントの情報
    - ```projectName``` : AWS IoT 1-Clickで紐づけられているプロジェクト
    - ```placementName``` : AWS IoT 1-Clickで紐づけられているプレイスメント
    - ```attributes``` : AWS IoT 1-Clickのプレイスメントに指定した属性情報（上記の例では設定なし）
    - ```devices``` : SORACOM LTE-M Buttonのシリアル番号（※）

上記のイベントを受け取っている設定周りは以下の通り

■SORACOMのコンソール
<img width="859" alt="SORACOMコンソール" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19870/7961e1ee-5ae9-a46a-6085-d0a6bc38cedb.png">

■AWS IoT 1-Clickのプレイスメント
<img width="1097" alt="AWS IoT 1-Click プレイスメント" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19870/1e32711a-a1e7-f423-a52f-336633480859.png">
CentOS7 - Install - MySQL8.0

# 環境と対象
- 環境
    - CentOS7
    - MariaDB（インストール済み）
- 対象
    - MySQL 8.0.19

# MariaDBのアンインストール
- MariaDBのインストール状態を確認
- CentOSに標準で乗っかっている可能性あり

```
// インストール状態の確認
$ yum list installed | grep maria
mariadb-libs.x86_64
```

- このように表示されたらインストール済みのため、アンインストール実行

```
// アンインストール
$ yum uninstall mariadb-libs.x86_64
```

# MySQLのインストール

## MySQLパッケージの追加
- yumコマンドを用いてインストール
- yumリポジトリにはMySQLパッケージがないため、手動で追加
- MySQL公式サイトより、Community Edition の [ダウンロードページ](https://dev.mysql.com/downloads/repo/yum/) へ遷移
    1. MySQL公式から製品タブを押下
    2. 左ペインにある MySQL Community Edition を押下
    3. Download MySQL Community Edition を押下
    4. MySQL Yum Repository を押下

- 任意のバージョン（今回は Red Hat Enterprise Linux 7 / Oracle Linux 7）を選択
- ページ下部の No thanks, just start my download. をからパスを取得
![pic_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340394/16d83c31-ebc0-1021-28a8-89011b992ee5.jpeg)

- 取得したパスを用いて、パッケージをダウンロードとインストール

```
// ***** の部分には、選択したバージョンに応じた値が入る
$ yum install https://dev.mysql.com/get/*****
```

- インストールしたパッケージの確認

```
$ yum info mysql-community-server
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
利用可能なパッケージ
名前                : mysql-community-server
アーキテクチャー    : x86_64
バージョン          : 8.0.19
（以下省略）
```


## インストール

- yumコマンドを用いてインストール

```
// インストール
$ yum install mysql-community-server
```

- インストールしたMySQLの確認

```
$ mysql --version
mysql  Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)
```


## 起動と確認

```
// 起動
$ systemctl start mysqld.service
```

```
// 停止
$ systemctl start mysqld.service
```

```
// 自動起動設定（オフにする場合はdisable）
$ systemctl enable mysqld.service
```

```
// 状態確認
$ systemctl status mysqld.service
```

# MySQLの初期設定

## rootパスワードの確認

- 格納場所：/var/log/mysqld.log

```
// rootパスワード確認
$ cat /var/log/mysqld.log | grep Note
（省略）A temporary password is generated for root@localhost: (pass-phrase)

```

## rootパスワードの変更

```
// MySQL起動
$ mysql -u root -p
Enter password: （確認したrootパスワードを入力）
```

```
// 一旦、任意のパスワードに変更
mysql> ALTER USER 'root'@'localhost' identified BY '（任意のパスワード）'
Query OK, 0 rows affected (0.01 sec)

// パスワードポリシー変更のおまじない
mysql> set global validate_password.length=4;
Query OK, 0 rows affected (0.00 sec)

// パスワードポリシー変更のおまじない
mysql> set global validate_password.policy=LOW;
Query OK, 0 rows affected (0.00 sec)

// rootパスワードを'Password'に変更
mysql> ALTER USER 'root'@'localhost' identified BY 'Password';
Query OK, 0 rows affected (0.01 sec)

```

- rootパスワードをPasswordに変更することができた。
初学者が関数型コンポーネントを使って困ったこと

# はじめに
今までクラス型でコンポーネントを書いていた私が関数型のコンポーネントを書く際に困ったことを書きたいと思います。
今回は「3秒たった後に数字が0から1に変わる」という機能を実装する中で僕が出会った問題を紹介したいと思います。
# 問題点
関数型コンポーネントを使って書いてみます。

```react:index.js
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1);
  };
  useEffect(() => {
    setTimeout(increment, 3000);
  });
  return (
    <div>
      <h1>Sample Counter</h1>
      <p>{count}</p>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

これで実行すると3秒おきに延々とカウントが進むようになります。

# 解決策
以下のように書くと、実行後に3秒後に1回だけカウントが進むようになります。

```react:index.js
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function App() {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1);
  };
  useEffect(() => {
    setTimeout(increment, 3000);
  },[]);
  return (
    <div>
      <h1>Sample Counter</h1>
      <p>{count}</p>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

ほとんど変更していないように見えるがuseEffectの第2引数に[]を渡しています。
第2引数に値を渡すと、再レンダー時、その値が変わっていなければ副作用の適用をスキップするようになります。
今回空の配列を渡しているので、useEffect内部の式は最初に一回だけ実行され、その後再実行されることはありません。
今回のような場合、第2引数に空の配列を渡し、明示的に再実行の必要がないことをReact側に伝える必要があるようです。

# 最後に
このようなことは、以下のReactのドキュメントにも書いてあるので、もう少ししっかりドキュメントを読まないとなと思いました。

https://ja.reactjs.org/docs/hooks-effect.html
Zバッファだけ更新するシェーダーでオクルージョンの実装

# 今日の目的

ARでのなんちゃってオクルージョンをやってみる。

# シェーダー

Zバッファのみに書き込むシェーダーです。これをマテリアルに当てます。

```
Shader "Unlit/DepthOnly"
{
	SubShader{
		// Render the mask after regular geometry, but before masked geometry and
		// transparent things.
		Tags {"Queue" = "Background+10" }

		// Don't draw in the RGBA channels; just the depth buffer
		ColorMask 0
		ZWrite On

		// Do nothing specific in the pass:
		Pass {}
	}
}
```

出典を忘れて申し訳ないのですけど、どこかで紹介されてたものです。

# テスト

まずは、テストでEditor上で動かしてみます。
![20191208_fig_occu.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30257/341257ae-2c36-bbbe-500b-bf02184f8cb3.png)

Clear Flagsは、ARを前提として#000000でSolid Colorになっています。周辺の直方体が通常のマテリアル。真ん中の球にZバッファのみ書き込みShaderを当ててあります。うまくいきそうですね。

# HoloLensで実装

実際にHoloLensで実装してみました。
我が家にあった、箱ティッシュの箱を採寸して、同じ大きさのCubeを抜いています。
そのまわりに緑の帯を回してみました。
Cubeの位置合わせは、Bluetoothキーボードをつけて、手動で合わせました。

![20191208_231207_HoloLens.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30257/a31a9a93-c7f0-a011-1aea-f4c0c04b58d9.jpeg)

ちなみに、HoloLensのキャプチャや録画だと、目の位置とカメラの位置が違うので、それなりにずれて写ってしまうようで、目で見ているときは結構きれいにオクルージョンしていたのが、キャプチャした画像や録画だと、いまいちということがあり、キャプチャの方でうまく見えるように、動かしたりもしています。
また、若干のずれはやはり発生するので、オクルージョン用のオブジェクトは、一回り大きめに作っておくのがよいのでしょう。

# おわり

ぎりぎりになりましたが、今日の分は以上です。
LED バッジを enebular から操作してみた。(技術書典 7 編)

# はじめに
こんにちは。野良ハックチーム ざっきー と申します。
2019 年 9 月 22 日に開催された技術書典 7 で野良ハック本 2 冊目となる「<A HREF="https://norahack.booth.pm/items/1565529">光りモノをハックする</A>」という技術本を頒布しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/68c8daa1-a7ca-8958-1d04-5048b334cb8c.png" width="25%">
私はその本の中で「LEDバッジ（熱闘甲子園2019）」という記事を書きました。
ページ数の都合で詳細について触れることができなかった「Raspberry Pi に USB-HID 版 LED バッジ (S1144) を接続して enebular から操作する方法」について説明します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4403541f-d201-c898-6303-d292f4375949.png" width="50%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/029f66d4-3750-116b-42ab-2adbe827f8ce.png" width="50%">

# 材料
- Raspberry Pi 2 Model B / 3 Model B / 3 Model B+ のいずれか  
※ Raspberry Pi Model B、Raspberry Pi Zero / Zero W は USB 電源の制御ができないため使用不可
- USB-HID 版 LED バッジ (S1144)  
※ 購入先は<A HREF="https://www.aliexpress.com/store/all-wholesale-products/5120167.html">こちら</A>。
- 超小型 MicroUSB OTG 変換アダプター USB-A オス → MicroUSB オス変換  
※ 購入先は<A HREF="https://www.amazon.co.jp/KAUMO-極小アダプタ-USBオスをmicro-USBオスに変換-KM-158/dp/B01I1TD6J8">こちら</A>。通常の USB-A オス → MicroUSB オス変換ケーブルでもOK。

# 構成
Raspberry Pi へ enebular agent をインストールして enebular から Node-RED フローをデプロイします。
Node-RED のダッシュボード機能を利用してブラウザから LED バッジの表示メッセージを変更することができます。
<img width="1176" alt="スクリーンショット 2019-12-08 19.33.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d47f163f-3785-a4a2-7046-1857ed8eb17f.png">

## Raspberry Pi の USB 電源の仕様
ポイントは LED バッジの表示メッセージを変更した後に USB 電源を OFF にすることです。
USB 電源を ON にしたままだと LED バッジに充電中マークが表示されるためです。
Raspberry Pi はポート番号 2 の USB 電源を ON / OFF 制御することで、その他のポート番号 3 〜 5 の USB 電源も同時に制御されます。
フローの流れとしては、ブラウザのフォームからメッセージを入力 → USB 電源を ON → LED バッジのメッセージを書き換え → USB 電源を OFF になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a88678a1-763e-1393-49aa-b2dc0855a7e3.jpeg" width="25%">

# プログラム
プログラムの仕様や使い方の詳細については野良ハック本に掲載していますので、Qiitaでの説明は割愛します。
興味がある方は是非本をご覧ください！

- LED バッジのメッセージを書き換えるプログラム  
https://github.com/jnweiger/led-name-badge-ls32
- USB 電源を制御するプログラム  
http://www.gniibe.org/oitoite/ac-power-control-by-USB-hub/hub-ctrl.c
- 日本語メッセージを表示するプログラム  
https://github.com/kitazaki/LED_Badge

## フロー
ダッシュボードのボタンノードを配置して、ボタンが押下されたら exec ノードで hub-ctrl プログラムを実行して USB 電源を ON / OFF 操作しています。
また、ダッシュボードのフォームノードを配置して、フォームから入力されたメッセージを led-badge-11x44.py プログラムや message.sh スクリプトを実行して LED バッジに表示するメッセージを書き換えています。
ボタンノードで固定のメッセージ (フローでは「野良ハック」という文字列を横、または、縦に表示する例) に書き換えることも可能です。
<img width="1200" alt="enebular.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6e732f99-c136-c28c-586f-507a86cdef98.png">
※ フローは<A HREF="https://enebular.com/discover/flow/e0cd4b98-a710-4c0a-b83d-80a16d1ab56b">こちら</A>で公開しています。

# まとめ
LED バッジを Raspberry Pi へ接続してデジタルサイネージのように使用してみました。
Raspberry Pi の USB から充電されるので電池切れの心配もありません。また、enebular (Node-RED) を使用してリモートから簡単に表示するメッセージを書き換えることも可能です。

良き enebular & LED バッジライフを！
学園祭周りのシステムにLaravelを導入した話

学園祭アドベントカレンダー8日目を担当します、@sirogane1013です!

私は東京工業大学の学園祭『工大祭』の実行委員会で、Webサイト周りのいろいろをやる仕事に3年間従事してきました。

書こうと思ったネタはいろいろあったのですが、フレームワーク**Laravel**を導入した話を書こうと思います!

結論としては世にあふれるLaravel布教記事になります。ですが、学園祭の実行委員という「小規模」「初心者多」な環境におけるLaravelの利用という点で見てもらえればいいかと思います。

はっきり言って自分自身、1年ちょっとLaravelを触った程度の初心者なので、間違い等あればご指摘お願いします。

## 導入に至るまで

Laravelを導入するまで、当委員会では**FuelPHP**というフレームワークを使っていました。

FuelPHP自体はいいところもいろいろあります。しかし、メジャーリリースがなかなか行われなかったり、単純に流行りではないので情報が少なかったりで運用が難しくなってきました。

そこで移行先を考えて、(多分)今一番熱いPHPフレームワークなLaravelが選ばれました。

## Laravelを導入してよかったこと

### 実装がしやすい

Laravelといえばサービスコンテナというイメージがありますが、このサービスコンテナをしっかり利用していくことで、自然に保守性の高いアプリケーションを構築していけます。

サービスコンテナとは何かを説明すると長くなってしまうので、サービスコンテナによって得られる利点の例を挙げようと思います。

例えばあるWebアプリケーションで、リクエストの内容をもとにいろいろな処理をしたいとします。この時、Laravelでは次のような記述でリクエストの内容を取得できます。

```php
/*引数に指定したインスタンスがサービスコンテナにより注入される*/
public function index(Request $request)
    {
/*ここに処理を書く*/
    }
```

このように、リクエストの内容が入った`Request`インスタンスが欲しいなら、`Request`インスタンスを利用したいメソッドで引数に`Request`を指定します。
この際のインスタンス生成の手続きは隠蔽されているため、よくわからなくても利用できるのが素晴らしいです。

ほかにも、自分で実装したクラスをサービスコンテナで管理することにより、クラス同士の疎結合が保たれ、保守性が上がります。

### セキュリティ周りがしっかりしている

Webサイトの構築にあたってフレームワークを利用するメリットの1つは、セキュリティ面のサポートを得ることではないでしょうか。
Laravelはセキュリティ周りの対策がしっかりしているので、そこまで知識がなくても自然と安全なサイトが構築できます。

たとえば、Laravelはデフォルトでcsrfトークンチェックが必須となっています。一方で、たった1行追記するだけでcsrf保護を有効にできるという手軽さも持ち合わせています。

```php
<form method="POST" action="/profile">
    @csrf
    ...
</form>
```

↑の記述だけでcsrfへの対策になります!

ほかにも、データベースへのクエリの発行などで様々な対策が施されています。しかし、利用する上で、それらの実装は隠蔽されているので初心者にも大変扱いやすいです!

### ググれば大体わかる

正直これが一番の利点、大正義です。ググれば大体のことが書いてあります。

FuelPHPを使っていた時は全然探したい情報を見つけられず、苦労した覚えがあります...

Laravelは非常にコミュニティや情報交換が盛んで、その点で困ることはほとんどなかったです。

## Laravelの導入でつまずいたこと

Laravel導入の利点の話はほかにもごまんとあると思うので、こっちが本題になります。
Laravelを知っている人がほとんどいない中で困った点の話です。

### 体系的に学びづらい

これがだいぶしんどかったです...
1から学ぼうと思うと、Laravelは初心者には結構厳しめだと思います。

比較対象としてわかりやすいのはRuby on Railsだと思います。
Railsは公式のチュートリアルがすごくしっかりしていて、初めてWebサイトを構築するような場合でも手厚くサポートしてくれるところがあります。

一方Laravelは、公式ドキュメントにデザインパターンとかWebとかの用語が説明なしにバンバン出てくるので、初めての時にはすごく読みづらいです。(最終的には何度もお世話になるのですが...)

最低限、MVCパターンの知識とWebの基本知識は別で仕入れるのがいいと思います。

## まとめ

やはり学園祭の実行委員のような小規模な集団には学習コストの高さがネックかなと思います。

しかし、それを補ってなお得られる利点が大きいので、PHPを使った開発でフレームワークを導入するならLaravelがいいのではないかなと思います。

ここには書いていませんが、フロントエンドフレームワークとの連携とかもできるので、Vueみたいなのをやってみたいという際にもお勧めできます。
【Vue.js】よく使いそうなディレクティブまとめ【初心者】

## はじめに
Vue.jsを触り始めたので、よく使いそうなディレクティブを自分用にまとめました。

※HTML側の表記のみサンプルで記載しています。

[公式ドキュメントはこちら]()

## 環境
```
- OS: macOS Catalina 10.15.1
- Vue.js: 2.6.10
```

## 各ディレクティブの意味と使用例

### 1.`v-bind`データバインディング
[公式ドキュメント](https://jp.vuejs.org/v2/guide/class-and-style.html)
####【意味】
データバインディングを作成する。
HTMLの各タグにJavaScriptのデータを紐付ける。

####【使用例】
```vue
<a v-bind:href="url">Click here</a>
```

```vue
<a :href="url">Click here</a>
```
短縮形が用意されていて、通常は下側の表記を使う。

その他、以下のタグと連携する活用例が多い。

- `href`
- `src`
- `id`
- `class`
- `checked`

---
### 2.`v-on`イベント発火
[公式ドキュメント](https://jp.vuejs.org/v2/guide/events.html)
####【意味】
HTMLタグに紐付け、イベント発火時に指定したJavaScriptを実行する。

####【使用例】
```vue
<div id="example-1">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
```

例では、ボタンをクリックすると変数`counter`に1加えられ、`p`タグ内に反映される。

```vue
<div id="example-1">
  <button @click="counter += 1">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
```
短縮系が用意されていて、通常は`@click`のように使用する。

その他活用の幅が広く、様々な修飾子が用意されている。
詳細は[公式ドキュメント](https://jp.vuejs.org/v2/guide/events.html)参照。

---
### 3.`v-model`双方向データバインディング
[公式ドキュメント](https://jp.vuejs.org/v2/guide/forms.html)
####【意味】
双方向データバインディングを作成する。
フォームなどと連携し、リアルタイムで値を反映させたいときに使用する。

####【使用例】
```vue
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
```
例では、`input`タグで作成されたフォームに入力された文字が`p`タグ内の`{{message}}`にリアルタイムで表示される。

その他チェックボックス、セレクトボックスなどにも応用出来る。

---
### 4.`v-if`条件分岐
[公式ドキュメント](https://jp.vuejs.org/v2/guide/conditional.html)
####【意味】
trueなら表示、falseなら表示されない。

####【使用例】

```vue
<div v-if="hoge">
  fuga
</div>
<div v-if="foo">
  bar
</div>
```

例では

- `hoge`がtrue => `fuga`が表示
- `foo`がtrue => `bar`が表示

また、もう少し複雑な処理であれば
`v-else-if`
`v-else`
も組み合わせて条件分岐させることが出来る。

---
### 5.`v-show`表示/非表示
####【意味】
`v-if`と記法・使用用途は近い。

ただし、実態はCSSで`display: none`を付与して**非表示にしているだけ**ので`false`の場合も要素自体は存在する。

####【使用例】※`v-if`と同様

```vue
<div v-show="hoge">
  fuga
</div>
<div v-show="foo">
  bar
</div>
```
例では

- `hoge`がtrue => `fuga`が表示
- `foo`がtrue => `bar`が表示

---
### 6.`v-for`繰り返し処理
[公式ドキュメント](https://jp.vuejs.org/v2/guide/list.html)

####【意味】
配列の要素を１つずつ取り出し、取り出す要素が無くなるまで繰り返す。

####【使用例】
```vue
<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
```
この例では、個数分だけ`li`タグが繰り返し表示される。

`vfor`の後にある`item in items`の意味は

- `item` => htmlにある`{{item.message}}`の中にある`item`
- `items` => JavaScriptの`data`に入っている`items`配列

表やリストに対して使用する例が多い。
## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

これからガンガン使って慣れていきます！:fist:

## 参考にさせて頂いたサイト（いつもありがとうございます）
[ディレクティブ - vue.js](https://012-jp.vuejs.org/api/directives.html)
Google App Engineに作成したインスタンスにSSHで接続するメモ

GAEに作成したインスタンスにSSH接続した後に実際にアップロードしたデータ操作するまでの手順メモ。

インスタンス中でDockerが動作しているので、要はそこにアクセスすれば良いらしい。

詰まるところ、GAEインスタンスにSSH接続した後に`sudo docker exec -it gaeapp /bin/bash`で接続出来る。

GAEに作成したインスタンスに大して直接SSH接続するためには、作成時にフレキシブル環境（app.yamlでenv: flexで指定）を指定する必要がある。

以下、もうちょっとだけ丁寧に記載した手順です。

## 手順

- App Engineのインスタンスを開く。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198321/0ca555ad-a206-89e4-accb-cc880e03b26d.png)

- SSHをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198321/e8fedbb0-8481-4ab7-f317-bdec5c62dc99.png)


- `sudo docker ps`で稼働してるコンテナ一覧を表示する。
- [gaeapp]という名前が見つかったら、そこに`sudo docker exec -it gaeapp /bin/bash`で接続する。
- あとはやりたい事を実行するだけ。うーん、便利。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198321/20b84a6f-2c33-dd5f-d0b2-7227661963e5.png)

## 参考

[インスタンスのデバッグ](https://cloud.google.com/appengine/docs/flexible/php/debugging-an-instance?hl=ja)
ojichatグラフシェル芸

# ojichatグラフシェル芸とは？
![o.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/25370942-bed8-70c2-cb88-ad9265d63bcf.png)
こういう画像を作るシェル芸です。
# コマンド
以下のコマンドで目的の画像が出力できます。

```bash
$ echo "digraph{👴[fontsize=100]👴🏻[fontsize=100]👴🏼[fontsize=100]👴->👴🏻[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏻->👴🏼[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏼->👴[label=\"`ojichat|grep -Eo '.{1,14}'`\"]}"|dot -Tpng>/images/o.png
```
ojichatの出力がランダムであるため、エッジのキャプションは実行するたびに変わります。
# 前提条件
[``` graphviz ```](https://www.graphviz.org/)と[``` ojichat ```](https://github.com/greymd/ojichat)がインストールされていること。

# コマンド解説
3つのノードをエッジでつないだグラフを描きます。

```bash
$ echo "digraph{A->B B->C C->A}"|dot -Tpng>/images/0.png
```
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/67773bbd-5e43-b0f9-0c63-77b1bed1ef26.png "/images/0.png")
エッジにキャプションを添えます。

```bash
$ echo "digraph{A->B[label=\"from A to B\"] B->C[label=\"from B to C\"] C->A[label=\"from C to A\"]}"|dot -Tpng>/images/1.png
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/b55afc34-7554-a6c9-ce82-7a5b46fa6aff.png "/images/1.png")

ノードに👴(OLDER MAN)を入れます。

```bash
$ echo "digraph{👴->👴🏻[label=\"from 👴 to 👴🏻\"] 👴🏻->👴 🏼[label=\"from 👴🏻 to 👴🏼\"] 👴🏼->👴[label=\"from 👴🏼 to 👴\"]}"|dot -Tpng>/images/2.png
```
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/ded51744-f2f5-ff50-767f-46c4807a5d14.png "/images/2.png")
👴🏻と👴🏼は👴に [skin tone modifier](https://emojipedia.org/modifiers/) を付けたものです。

エッジのキャプションを``` ojichat ```の出力にします。

```bash
$ echo "digraph{👴->👴🏻[label=\"`ojichat`\"]👴🏻->👴🏼[label=\"`ojichat`\"]👴🏼->👴[label=\"`ojichat`\"]}"|dot -Tpng>/images/3.png
```
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/043ed126-a7da-5819-e142-a1cb2b21b772.png)

``` ojichat ```の出力が長すぎるので改行します。``` grep -Eo '.{1,14}' ```として、14文字で改行します。

```bash
$ echo "digraph{👴->👴🏻[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏻->👴🏼[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏼->👴[label=\"`ojichat|grep -Eo '.{1,14}'`\"]}"|dot -Tpng>/images/4.png
```
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/61780ac5-dda7-30a9-f240-2ace6d0a521d.png "/images/4.png")

👴のサイズを調整します。
``` graphviz ```で``` fontsize ```を指定します。

```bash
$ echo "digraph{👴[fontsize=100]👴🏻[fontsize=100]👴🏼[fontsize=100]👴->👴🏻[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏻->👴🏼[label=\"`ojichat|grep -Eo '.{1,14}'`\"]👴🏼->👴[label=\"`ojichat|grep -Eo '.{1,14}'`\"]}"|dot -Tpng>/images/o.png
```
![o.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143996/59924cfd-88b0-fd61-d8b2-96bbb91272b8.png "/images/o.png")
完成です。
# 所感
これをシェル芸botに投げたとき、「地獄」という反応が多かったんですけど、僕としては「優しい世界」のつもりでやっていました。
以上です。
ShellScriptで環境構築を自動化

[なんか布教したいエンジニア Advent Calendar 2019](https://qiita.com/advent-calendar/2019/engineer_tail)の9日目の記事です。

# はじめに
会社のサーバーをバックアップするスクリプトを触り、自分でも何か作りたいと思い作りました。
また、初学者が環境構築で躓いてしまうのはとてももったいないと思うので良ければこれを使ってみてほしいです。
[ソース](https://github.com/sayuprc/Setup)

ソースと一緒にこの記事を読んでいただけるとより理解できると思います。

# 環境
OS: Windows10
[Vagrant](https://www.vagrantup.com/)と[VirtualBox](https://www.virtualbox.org/)、[Cmder](https://cmder.net/)を使うのでダウンロードとインストールをしておいてください。

# スクリプトの説明
このスクリプトはvagrantとvirtualboxを用いて仮想環境を構築する一連の作業を自動化したものです。
流れとしては
1. ディレクトリの作成
2. vagrant init の実行
3. Vagranfileの書き換え
4. vagrant provisionに必要なスクリプトの作成
5. vagrant up の実行
です。

スクリプトの実行には引数が2つ必要です。
1つはディレクトリの名前
もう1つは仮想マシンの種類です。

## 1.ディレクトリの作成
まず初めにVagrantfileを置いておくファイルを作成します。
自分の場合は`C:\Users\username\VM`というディレクトリをROOTディレクトリとして作成し、その中に引数で受け取ったディレクトリを作成しています。

```setup.sh
DIR_NAME=$1

cd $ROOT_DIR
if [ ! -d "$DIR_NAME" ]; then
  mkdir $ROOT_DIR/$DIR_NAME
fi
```

### 解説
`ROOT_DIR`という変数には`$HOME/VM`が代入されています。
この`$HOME/VM`は`C:\Users\username\VM`を表しています。

```
DIR_NAME=$1
```
この`$1`は第一引数のことです。
`sh setup.sh aaa`とコマンド実行した場合`$1`には`aaa`が入ります。
また、後で出てくるのですが、`$2`や`$3`などもありそれぞれ第二引数、第三引数を表しています。

```
if [ ! -d "$DIR_NAME" ]; then
	// 処理
fi
```
ここのif文は引数で受け取ったディレクトリ名が無い場合、そのディレクトリを作成するというものです。
`-d`はディレクトリの有無を調べます。

## 2.vagrant initの実行とVagrantfileの書き換え
先ほど作成したディレクトリで`vagrant init`を実行してVagrantfileを作成します。
init時にBoxも指定しています。
利用しているboxはbento/CentOS7.5です。(ここは適宜変更してください。)

```setup.sh
count_dir

cd $ROOT_DIR/$DIR_NAME

vagrant init bento/centos-7.5

if [ -f Vagrantfile ]; then
  sed -i '31a \  config.vm.network "forwarded_port" ,guest: 80, host: 8080, host_ip: "127.0.0.1"' Vagrantfile
  sed -i '35a \  config.vm.network "private_network", ip: "192.168.33.10"\n  config.vm.network :public_network, ip: "192.168.11.'$((100+$COUNT))'", bridged: "en1: Wi-Fi(AirPort)"' Vagrantfile
  sed -i '69a \  config.vm.provision "shell", :path => "provision.sh", :privileged => false' Vagrantfile
fi
```

### 解説
if文の中ではVagranfileの書き換えを行っています。
一番上はフォワードポートを指定しています。
真ん中はパブリックネットワーク用のIPアドレスを指定しています。
`count_dir`関数で取得したディレクトリの数に応じてIPアドレスが変わるようになっています。(この機能は作成当初必要かと思っていましたがよく考えたらいりませんでした。)
最後に`vagrant provision`を利用する行を追加しています。

## 3.provision.shの準備
最後にprovision.shを作成します。
provision.shにはvagrant up時に実行させたいものを記述しておきます。
スクリプト内ではどのマシンでも行う共通のコマンドを記したcommon.shとそれぞれの環境で実行するコマンドを記したスクリプトがあります。
このcommon.shと各環境で実行するスクリプトを組み合わせてprovision.shを作成します。

```setup.sh
case "$ENV_TYPE" in
    "dev") cp -p $DEV/development.sh provision.sh.org ;;
    *) ERROR_NUM=5
        get_errormessages
        exit ;;
esac

if [ -f provision.sh.org ]; then
	cp -p $COMMON/common.sh common.sh
	cp -p $COMMON/end.sh end.sh
	cat common.sh provision.sh.org end.sh > provision.sh
	rm common.sh provision.sh.org end.sh
fi
```

### 解説
\$ENV_TYPEには第二引数で指定された仮想マシンの種類が入っています。(現状devのみ)
\$ENV_TYPEがdevだったら指定したフォルダからスクリプトをコピーしてきます。

## 5. vagrant upの実行
あとはvagrant up を実行するだけです。
vagrant upした際に先ほど作成したprovision.shに記述されたコマンドを実行し、仮想マシンのセットアップを行います。

# 最後に
以上が今回作成した環境構築自動化スクリプトの大体の流れです。
私は楽するためと勉強を兼ねてこのスクリプトを作成しましたが、環境構築に躓く初心者の方がこれを使ってプログラミングを楽しくできたらいいなと思います。

稚拙な文で分かりづらいかと思います。何か質問等あればコメントにお願いします。
Unityでカメラアプリを作った時に買ったAsset

[MEISAIというiOS用ARカメラアプリ](https://kitasenjudesign.com/meisai/)をUnityで作ってます。
swiftとかiOSのことが何も分からないので、アセットを買って凌ぎました。

## ビデオ録画

[NatCorder](
https://assetstore.unity.com/packages/tools/integration/natcorder-video-recording-api-102645)
有料


## ビデオでマイク録音

[NatMic](
https://assetstore.unity.com/packages/tools/integration/natmic-microphone-api-123358)
有料
NatCorder一緒に利用


## SNSシェア

[NatShare](
https://assetstore.unity.com/packages/tools/integration/natshare-mobile-sharing-api-117705)
無料
NatCorder一緒に利用。でもうまく動かなかったので動画を保存する時しか使ってない。


## LEDライトをつける

[iOS Native Flashlight](
https://assetstore.unity.com/packages/tools/integration/ios-native-flashlight-129556)
有料
フラッシュ用

## インスタストーリーにシェア

[Cross Platform Instagram Story Kit](https://assetstore.unity.com/packages/tools/integration/cross-platform-instagram-story-kit-136064)
有料
UiPath Community Editionで、GitHubに繋がらない問題の、（暫定）解決法

# UiPath Studio (Community Edition)でも、GitHubを使ってみたい
使ってみたいですよね。
![接続.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/44a0f607-73d1-d5cf-e8c4-b51a05f0785b.png)
やってみます。

# でも、エラーが出ます
GitHubに繋ごうとすると、Exceptionが出ます。

![エラー画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/a1fe1c67-8aab-127d-1963-5cb6a6a5b567.png)

例外の、メッセージを読むと、
DllNotFoundException: 'git2-572e4d8'
が、原因のようです。

Community Editionの、フォルダを見ても、git2-572e4d8.dllは、確かに、入っていません。

# ファイルを探してきました

Community Editionの、2019.11.0-bata2に、付属している、libgit2sharpという、Gitに接続するライブラリが、git2-572e4d8.dllに、静的にリンクされているのが、原因のようです。（ほかのバージョンの、UiPath Studioだと、git2-xxxxxxx.dllの、xxxxxxx部分は、別のバージョンかもしれません）

今回、このファイル、どこにあるのかな、と、探して回ったのですが、LibGit2Sharp.NativeBinariesに、同梱されていました。

問題は、その、バージョンです。最新版には、同梱されていません。
上記の、git2-572e4d8.dllだと、LibGit2Sharpの、0.22.2のnupkgの中に、入っていました。

https://www.nuget.org/packages/LibGit2Sharp.NativeBinaries/0.22.2
![nupkg.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/4d797c6e-0fa7-12af-c7bb-213b3f4d6841.png)
nupkgを、NuGet Package Explorerで（なければ、拡張子を、.zipに変えれば、Explorerでも開けます）git2-572e4d8.dllと、git2-572e4d8.pdbを、取り出します。
取り出し元は、win-x86のフォルダです。win-x64だと、おそらく、エラーになります。

![コピーしました.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/0ac69f10-fb1e-820f-e3fc-a150047a820d.png)
これを、UiPath Community Editionの、app-xx.xx.xxのフォルダ（最新バージョンの、フォルダ）に、コピーします。

あと、手軽にGitHubでの接続を、試すのであれば、

- 最初に、GitHubのWebページで、リポジトリを作ります
- 次に、Main.xamlと、project.jsonを、アップロードします
- 最後に、UiPath Studio画面で、Clone Repositoryから、作成したリポジトリのURLと、GitHubのユーザーアカウントで、接続します

![clone.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/8f17ed12-60de-d919-5930-e23261069713.png)

 
これで、UiPath Community Editionでも、手軽に、GitHubでの差分管理を、できるようになります。
![繋がりました.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545754/115d381f-2caf-2aa1-64f7-e9fc4b11481c.png)

# 探し方
上で、git2-xxxxxxx.dllを、探したと、書きました。
これは、NuGet.orgの、LibGit2Sharp.NativeBinariesの、過去バージョンを、順番にダウンロードして、dllのファイルを探す、ワークフローを、UiPathで作りました。
もうちょっと、スマートな方法があれば、良いと思うのですが・・・。