OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaFX】Eclipseのアクセス許可をbuild.gradleに書く方法

# gradlew eclipseの度にエラーになっちゃう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/eb24a9e8-9af2-4d21-5d44-21c7382f8385.png)

**Access restriction: The type 'TransferMode' is not API (restriction on required library 'C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar')**

これは要するに以下の場所からアクセス許可を与えやればいいとの事である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/443b4e37-3ad6-6ed7-9a31-e0695c98482e.png)

上の画像右、**Edit**から編集して**javafx/\*\***をルールでAccessibleに追加して許可してやれば良いわけだが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/1b27eff5-8e6c-3508-c7a8-d87e28af46c3.png)

流石に**gradlew eclipse**なんてコマンドは依存関係を更新する度に打つので毎度毎度こんな設定をさせられるのは鬱陶しい。

誰かがgitからcloneしたときに「これエラー出てるんですけど（笑）」とか言われるのも実に腹立たしい。

というわけで、gradleに書く方法。

```build.gradle
import org.gradle.plugins.ide.eclipse.model.AccessRule

eclipse {
	classpath {
		file {
			whenMerged {
				def jre = entries.find { it.path.contains 'org.eclipse.jdt.launching.JRE_CONTAINER' }
				jre.accessRules.add(new AccessRule('accessible', 'javafx/**'))
			}
		}
	}
}
```

こんな感じ。
これでEclipseの.classpathに以下のように追加され、俺はマウスを使う量が減り、イライラが治る事で戦争が減り世界が平和になるという仕組みである。

```.classpath
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/">
		<accessrules>
			<accessrule kind="accessible" pattern="javafx/**"/>
		</accessrules>
	</classpathentry>
```

いつもありがとう、スタックオーバーフローの人。
それと、[【JavaFX】Eclipseで、アクセス制限: The type '?' is not API(? ex: JavaFX)と出た時の対処法まとめ](https://qiita.com/smk7758/items/890dff47eb272881a6b7)の@smk7758さん。

よし大体定時だ。帰るぞ俺は。
AndroidのWebViewを使うときはTCPコネクションとセッションのライフサイクルに気を付ける必要がある

ただしロードバランサーを使っていてセッションの維持にCookieを利用している場合。

## 要約すると
AndroidのWebViewが接続したTCPコネクションは、Activityのインスタンスとは独立してるから注意という話。

WebView持ってるActivityは念のため以下の実装をしておくと安心かもしれない。
※現在の開発環境がXamarin.AndroidなのでC#で書くが、JavaやKotlinでもほぼ同じだと思う。

```c#:MainActivity.cs
    protected override void OnDestroy()
    {
        base.OnDestroy();

        //WebViewの内部状態を破棄
        _webView.Destroy();
        _webView.Dispose();
    }
```

## WebViewはChomeの実装を使っている
WebViewは内部的にChromeを利用しており、そのインスタンス管理はアプリの制御外である。
.NETで言えばマネージドなコードからWin32 APIを呼び出しているイメージに近い。
そのため**WebView経由で作成されたTCPコネクションを閉じるタイミングもChromeの管理範囲**となる。

この仕様を理解しておかないと、困ったことになる場合がある。

## 困ること

サーバー側にロードバランサーを置いてラウンドロビンしているような場合、厄介なことになる場合がある。
今回自分が陥ったのは以下のようなシチュエーションだった。

1. 複数台のWebサーバーをロードバランサーでラウンドロビン
1. ロードバランサーのセッションの維持は**Cookie方式**
1. Cookieは**クライアントとの間に新しいTCPコネクションが確立したタイミング**で付与される
1. Webアプリのセッション（＝認証状態）は別のCookieで管理
1. 上記Webアプリのセッションをリセットするに、**WebView（を持つActivity）を起動するたびにCookieをクリアしている**

上記の太字部分が見事にWebViewの仕様とかち合ってしまった。
つまりこのような流れだ。

#### 1回目のWebView起動時の流れ
1. TCPコネクションが確立
2. ロードバランサーがCookie（負荷分散セッションID）を付与
3. アプリケーションセッションが確立
4. WebサーバーがCookie（アプリセッションID）を付与

#### 2回目以降のWebView起動時の流れ
1. Cookieをクリア
2. **TCPコネクションは初回の接続が生き残っているため再利用**
3. **ロードバランサーは同一Socketからのアクセス時はCookie（負荷分散セッションID）を付与しない＝ロードバランサーのセッションが維持できない**
4. アプリケーションセッションが確立
5. WebサーバーがCookie（アプリセッションID）を付与

2回目以降のリクエストでロードバランサーのセッションが維持できていないので、アプリケーションセッションを確立できていないWebサーバーにリクエストが飛ぶ可能性があり、アプリセッションが一致しないためエラーが発生してしまう。

最初エラーになった時に本当に原因がわからず、Http周りのログを徹底的に洗ってようやく突き止めることができた。
まさかWebViewの仕様に原因があったとは……

## 対応方法
先述のとおり。

Activityが破棄されるタイミングでWebViewの`Destroy`メソッドを呼び出すようにすることで、Chromeのプロセスが内部でTCPコネクションを閉じてくれるようになる。
**CookieとTCPコネクションのライフサイクルが一致するようにするのがポイント。**

実際に接続が破棄されているのかアプリ側は知る由もないが、この実装にしてからは上述の不具合は発生しなくなったので、おそらく問題ないと思われる。
ios13から日本語フォントのboldがより太くなるケース

## [19/9/25 追記2]Hiragino sansとの比較
(左がios12、右がios13.1)
<img width="793" alt="ios12とios13.1のキャプチャ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/c3bd8460-ee34-537b-475c-b9b46ff9e12b.png">

Hiragino sansでもboldが太くなっていることを確認。
ios13からは、`lang="ja"`のsans-serifは、Hiragino sansで表示されている

Hiragino sansを指定している場合 `lang="en"`でも太くなる
<img width="384" alt="43df875638061e1438c053efe53528e8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/b65973b3-dee2-150f-ad40-0989fce2558a.png">


## [19/9/25 追記]ios13.1で少しだけ細くなりました（Hiragino-sans w7?）
(ios13.1)
<img width="392" alt="ios13.1のキャプチャ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/7904f0ed-35c8-d72e-c3c8-2bdb877cfb8d.png">

-------


ios13から、`lang="ja"`のテキストに `sans-serif` が当たった場合、より太いboldで表示される（Hiragino-sans w8?）
https://output.jsbin.com/givoduv

## シミュレータのキャプチャ
(左がios12、右がios13)
<img width="812" alt="lang=jaの場合のキャプチャ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/b7d24b07-63fc-19f6-16a0-2772464e01de.png">
font-weightばboldまたは700以上の場合、ios12までのboldよりも太いboldで表示される
<img width="824" alt="lang=enの場合のキャプチャ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/78455e79-8815-c91d-614b-68b5f98f1bac.png">
`lang="en"`では起きない


### sans-serif以外を指定した場合
![-apple-system、font-face-apple-system、HelveticaNeue、ヒラギノのみを指定した場合のキャプチャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/11479a73-e7e3-68bb-ba0d-626382c58e2d.png)
`sans-serif` の指定がなければ発生しない。


### 他のフォント + sans-serifを指定した場合
![-apple-system + sans-serif、font-face-apple-system + sans-serif、HelveticaNeue + sans-serif、ヒラギノ+ sans-serifを指定した場合のキャプチャ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/959cd0ec-03e9-9d74-ca0b-957797477fe3.png)
`-apple-system` や `'Hiragino Kaku Gothic ProN'`が、`sans-serif` より前にあれば日本語フォントにはそちらがあたるため、太くならない。
`font-face-apple-system,sans-serif` は <a href="https://qiita.com/a_t/items/18693be11bd87f98d212">-apple-systemで日本語フォントが1px小さく描画されてしまう問題の対応</a>で、`@font-face` で`-apple-system` をかませているケース。
この場合、英数字のみ`-apple-system` があたり、日本語は次の`sans-serif`が当たるため、より太いboldになってしまう。

## [番外]-apple-system(SF)のfont-weightが増えてた
(左がios12、右がios13)
<img width="818" alt="003.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5323/d55880f2-dce9-f71c-a1b5-064b0a108215.png">
PyRevitでTypeのSharedParameterをGUIDから取得する方法

GUIDからパラメータの取得方法を載せております。

revit python wrapperではGUIDでパラメータを取得する方法がなく`symbol.parameters[Guid].value`では取れません。
Guidで取得する場合は、`get_Parameter()`を使います。Revit APIの書き方です。

以下が参考にしたフォーラムです。
https://forums.augi.com/showthread.php?168857-Retrieve-element-parameter-by-GUID



https://qiita.com/yishizu/items/e7ae1e47e481fa12cef4

```python:get_parameterByGuid.py
from pyrevit import revit
from System import Guid

sel = revit.get_selection()
guid = Guid('54ab4dad-8f15-4150-9aca-4b2dbafd1813')
symbol = sel.elements[0].Symbol
p = symbol.get_Parameter(guid)
print(p.AsValueString())

```

`Element.LookupParameter(string name)` は、 `Element.get_Parameter(string name)`の代わりに使用するもの、`Element.get_Parameter(string name)`は2016年以前のAPIで使用されていたようです。`Element.get_Parameter(Guid guid)`は現在あまり使われていません。Revit APIのウェブサイトからも検索しても出てきません。
https://www.revitapidocs.com/2018/4812c792-89b8-3cfa-b63b-8a63adbd535b.htm

Guidで取得する方法は、シェアードパラメータファイルを複数利用している場合、同じ名前にも関わらず異なるシェアードパラメータを使用することで、違うGuidが存在することにもなりうるので名前で取得するほうがコードのメンテナンス上は有利ということで名前で取得する方法が主流です。
Quickの非同期処理テストではactualを展開しない

# tl;dr

swiftでQuick/Nimble/BrightFuturesを使った非同期処理のテストを書いていた時にハマったののメモ


# 事象

バックエンドにRESTを投げた後、レスポンスの内容を確認するテストで下記エラーが出た。
複数のエレメントを持つJSONを取得する想定だったので、配列化された要素の中身を検証しようとしていた。

## エラー内容

```
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
2019-09-20 09:32:20.858612+0900 xxxxxxx[25589:7494225] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
```

## テストコード

```swift

it ("何かの情報を取得できる") {
               var actualPromise: [SomeSturct]!
               subject.getSomeSturct()
                   .onSuccess { success in
                       actualPromise = success
                   }
               let someSturctResponse =
                                   """
                                       [
                                           {
                                           "Key": "Value"
                                           }
                                       ]
                                   """
               expectedPromise.success(someSturctResponse.data(using: .utf8)!)

               expect(actualPromise[0].key).toEventually(equal("Value"))
           }


```

# 原因

nilのエラーなので、何かのオブジェクトがnilのはず。
非同期処理のテストなのでtoEventuallyを使っていたが、toEventuallyは成功するまでアサーションを繰り返し続けるので、
まだ値が取得できていないタイミングでactualを展開するような処理をするとnilで落ちてしまう。

なので展開せずにテストするような形で修正することで対応する。
テスト的にもこっちが正しい気がする。



```swift

// expect(actualPromise[0].key).toEventually(equal("Value"))　→
expect(actualPromise).toEventually(equal([SomeSturct(Key: "Value")]))

```


## 参考


- https://github.com/Quick/Nimble
- http://reidr.hatenablog.com/entry/2016/02/23/192614
- https://qiita.com/enomotok/items/6c3a3eef8a5a4201f645
[Rust] ベクトルが並んだ ndarray から各ベクトルのノルムをまとめて計算 [Python/numpy]

`d` 次元ベクトルが `N` 個並んだ ndarray `x` が与えられたとします. 例えば `d=3` 次元空間ならこんな感じ.

```python
>>> x = np.random.normal(size=(8,3))
>>> x
array([[-0.35165099,  0.75272535,  0.2327542 ],
[ 0.1591356 , -0.42135054, -0.47746836],
[-0.65012207,  0.42038207,  1.46586837],
[ 1.89249086, -0.9594884 ,  1.49124505],
[-2.04557264, -1.00044391, -3.70700719],
[-0.53573469, -0.91952356,  0.02255211],
[ 1.19644064,  0.13071411, -1.80561646],
[-0.68594263, -0.53059182, -0.47844146]])
>>> 
>>> x.shape
(8, 3)
```

本記事ではこの `N` 個のデータに対して一斉に Euclid ノルムを計算するといった問題を扱います. 従って欲しいものは shape `(N,)` の ndarray になります. なお以下では `x`, `y` は同じ shape `(N, d)` の 2 つのベクトルを表します.

# Python (numpy) 版

`for i in range(N)` みたいな感じで順番に処理するのはとても遅いのでやめましょう. そのための numpy です. 要点は `np.sum` または `np.max` するときに `axis=1` と指定することです.

## Euclid 距離

$$\left| x, y \right| = \left[ \sum_{i=0}^{d-1} (x_i - y_i)^2 \right]^\frac{1}{2}$$

Euclid 距離

```python
euclid = np.sqrt(np.sum( (x-y)**2, axis=1)) 
```

Euclid ノルム

```python
euclid = np.sqrt(np.sum( (x**2, axis=1)) 
```

## マンハッタン距離

$$\left| x, y \right| = \sum_{i=0}^{d-1} \left| x_i - y_i \right|$$

マンハッタン距離

```python
manhattan = np.sum(np.fabs(x-y), axis=1)) 
```

マンハッタンノルム

```python
manhattan = np.sum(np.fabs(x), axis=1)) 
```

## Chebyshev 距離

$$\left| x, y \right| = \max ( | x - y | )$$

Chebyshev 距離

```python
chebyshev = np.amax(np.fabs(x - y), axis=1)
```

Chebyshev ノルム

```python
chebyshev = np.amax(np.fabs(x), axis=1)
```

## Minkowski 距離 (<i>L<sup>p</sup></i> ノルム)

$$\left| x, y \right| = \left[ \sum_{i=0}^{d-1} \left| x_i - y_i \right|^p \right]^\frac{1}{p}$$

Minkowski 距離

```python
minkowski = (np.sum( np.fabs(x-y)**p, axis=1))**(1./p)
```

$L^p$ ノルム

```python
minkowski = (np.sum( np.fabs(x)**p, axis=1))**(1./p)
```

# Rust 版

`D: usize` をコンパイル時定数として `x: Vec<[f64;D]>` に対して同じことをしてみます. 書くのが面倒になってきたのでノルムだけ.

## Euclid 距離

```rust
let euclid = x.iter()
    .map(|v| v.iter().map(|&u| u*u).sum::<f64>().sqrt())
    .collect::<Vec<_>>();
```

## マンハッタン距離

```rust
let manhattan = x.iter()
    .map(|v| v.iter().map(|&u| u.abs()).sum::<f64>())
    .collect::<Vec<_>>();
```

## Chebyshev 距離

```rust
let chebyshev = x.iter()
    .map(|v| v.iter().map(|&u| u.abs()).fold(0.0/0.0, f64::max))
    .collect::<Vec<_>>();
```

参考: [Rustでf32やf64の配列の最大値を得る方法](https://qiita.com/lo48576/items/343ca40a03c3b86b67cb)

## Minkowski 距離

```rust
let minkowski = x.iter()
    .map(|v| v.iter().map(|&u| u.abs().powf(p)).sum::<f64>().powf(1./p))
    .collect::<Vec<_>>();
```

## Rust - ndarray 版

```rust
let euclid = (&x*&x).sum_axis(Axis(1))
    .mapv_into(|v| v.sqrt());
let manhattan = &x.mapv_into(|v| v.abs())
    .sum_axis(Axis(1));
let chebyshev = &x.mapv_into(|v| v.abs())
    .fold_axis(Axis(1), 0.0 / 0.0, |&p, &u| { f64::max(p,u)});
let minkowski = &x.mapv_into(|v| v.abs().powf(p))
    .sum_axis(Axis(1))
    .mapv_into(|v| v.powf(1./p));
```

# 関連項目

* [Rubyでミンコフスキー距離](https://qiita.com/shiroux/items/16173c1588d22e81333c)
* [ミンコフスキー距離を絵にしてみた](https://qiita.com/scivola/items/ee37b686d0b36d6e9b39)
とあるGCP SSL化のためのインデックス

[GCPで無料HTTPS化｛Compute Engine編｝](https://www.apps-gcp.com/voicekit-japanese/)
[Google Cloud Load Balancing マネージドSSL証明書の設定方法](https://blog.apar.jp/web/10750/])
[マネージド インスタンス グループの作成](https://cloud.google.com/compute/docs/instance-groups/creating-groups-of-managed-instances?hl=ja)
このaddEventListener動いているんだろうか？ そう思った時にはJavaScriptのデバッガを見ましょう

## この addEventListener は動いているんだろうか？

JavaScriptを書いたことがある人なら誰でも一回は思ったことがあると思います（多分）。
私は適用されているか分からない時には確認のために、よく内部に `console.log()` などを書いて手動でデバッグしていました。

しかし以下の方法を使えば addEventLisner が適用されているかはすぐに知ることができます。

## JavaScript のデバッガを使いましょう
Chrome の Developer Tool の Event Listeners の機能を使うと解決します。

例えば以下のようなコードを書いたのなら、clickイベントを開いてみましょう。

```javascript
    const element = document.querySelector('.js-pagetop-link');
    element.addEventListener('click', () => {
      // do something 
    });
```


![貼り付けた画像_2019_09_20_17_09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144064/66ddaa2d-b10e-fc92-884f-9f9f3bcbea27.jpeg)




## コメント
CSSを書く時にデフォルトで開いているタブの`Style`の機能を使ったことがある人は多いかもしれません。
しかし、案外その横にある`Event Listener`のタブを開いたことがある人は少ないのでは？ と思ってこの短い記事を書きました。
フォームが更新された時にどのフォームが更新されたか確認する：Googleフォーム - スプレッドシート

## 目的
### 状況
スプレッドシートにGoogleフォームを連携させていて、１つのスプレッドシート内に２つ以上のフォームが設定されている場合

### やりたいこと
GASでフォームが送信された時にどのフォームのシートが更新されたかを見分ける。

更新されたフォームによって処理を分けたい時に使います。

## 手順
### GASに記述
とりあえずフォーム名を取得するサンプルです。

```js:sample.gs
function onFormSubmit(e) {
  var range = e.range;
  var form_name = range.getSheet().getSheetName();
  Logger.log(form_name);
}
```

### トリガーを設定する

- スプレッドシートのフォーム送信時をトリガーにする
- 呼び出すfunctionはonFormSubmit() 
- 引数は勝手に渡されてました

## 追記
2019/10/23 この投稿に関連して、フォームに入力された内容を取得する方法も書きました。
⇒[フォームが更新された時に入力内容を取得する](https://qiita.com/wau/items/cf9f59ab47eab7302782)
jsonbox.ioをJavaScriptから使う

jsonを無料で読み書きできるサービス、便利そう！
ということで試してみました。

## 導入
```shell:console
% npm i -S jsonbox-node
```

## BOX_IDを準備しておく
https://jsonbox.io/ にアクセスして、`https://jsonbox.io/`より後ろの値をコピーしておきます。
~~これも生成できたら良いのに…~~

## 実装

```javascript:demo.js
const {JsonBox} = require('jsonbox-node')
const BOX_ID = 'box_id'; // コピーしたBOX_ID

(async () => {
  const jbn = await new JsonBox()

  // レコード作成
  const get = await jbn.create({name: 'Pickles', age: 18}, BOX_ID)
  console.table(get)

  // 更新
  await jbn.update({age: 43}, BOX_ID, get._id)

  // 全レコード取得
  const records = await jbn.read(BOX_ID)

  // 検索
  // const records = await jbn.read(BOX_ID, {id: get.id})
  console.table(records[0])

  // 1リクエストで全件削除
  const recordIds = await Promise.all(records.map(async el => await el._id))
  await jbn.deleteMany(BOX_ID, recordIds)

  // 1件ずつ削除
  // await Promise.all(records.map(async (el) => await jbn.delete(BOX_ID, el._id)))
})()
```

## 実行結果
更新時に `name`を指定しなかったから消えてしまった…

```shell:console
% node demo.js
┌────────────┬────────────────────────────┐
│  (index)   │           Values           │
├────────────┼────────────────────────────┤
│    _id     │ '5d84848d9d1f330017f8f2f3' │
│    name    │         'Pickles'          │
│    age     │             18             │
│ _createdOn │ '2019-09-20T07:49:33.338Z' │
└────────────┴────────────────────────────┘
┌────────────┬────────────────────────────┐
│  (index)   │           Values           │
├────────────┼────────────────────────────┤
│    _id     │ '5d84848d9d1f330017f8f2f3' │
│    age     │             43             │
│ _createdOn │ '2019-09-20T07:49:33.338Z' │
│ _updatedOn │ '2019-09-20T07:49:33.835Z' │
└────────────┴────────────────────────────┘
```

## 雑感
検索とか細かくできる必要ないと思うので、試した範囲でも結構遊べる印象です。

## 参考
- [無料JSONストレージjsonboxを試してみた！ ｜ DevelopersIO](https://dev.classmethod.jp/etc/shuntaka9576-jsonbox/)
- https://github.com/0xflotus/jsonbox-node
今までのコミット全てを１つにまとめる方法

#全てのコミットを１つにまとめる方法
　gitがよく分からなかった頃のcommitを整理したのでそのメモです。
##1. git rebaseコマンド

~~~
git rebase -i --root
~~~

##2. 編集
vimが立ち上がる。
iを押してInsertモードに変え、最初のコミット以外をf(コミットメッセージを残さない)またはs(コミットメッセージを残す)に変更する。
変更後はesc→:wq(上書き保存して閉じる）

~~~
 pick 87c9788 commitC
 f 981c917 commitB
 f 05d649c commitA
~~~

##3. 自己責任でpushする

~~~
git push -f origin
~~~
Unityで通信対戦ゲームを作った話１

せっかくやったのでその時のことを書いておく
将来の自分向けメモ

**ゲームの前提**
- 3Dゲーム
- 通信あり
- 横移動だけで縦は無し
- 対戦アクションゲーム。殴ったり殴られたり、魔法ぶっ放せたりする
- マルチプレイサーバーは他者から送られたものを流すだけで、ゲームロジックを計算はしてくれない


**座標同期**
お互いの居場所がわからないと近づけないし殴れないので同期はもちろん必要


####初期
単純に今の座標送りあえばなんとかなるでしょw

結果
残念だったな残像だ
いきなり拳が飛んできた
ありのまま今起こったことを(ry

等々散々な結果だった
読みが甘すぎた。初めて作る分野ってそんなもんだよね。

原因は各プレイヤーの通信環境の違い
このままではゲームとして成立しないのでなんとかしなければ


####やったこと
単純に座標を送り合うだけではダメなので、未来座標と到達予定時刻を送信するようにした


手元にある情報は**現在座標**・**ベクトル**・**通信時間**があるのでこれを加工していく

**相手に送る情報**
**未来座標** = 座標 + ベクトル * 時間(通信時間ではない)
と
**到達予定時刻** = サバの現在時間 + 調整時間
調整時間 = 最低制限時間 + 自分の通信遅延時間 - 調整パラメータ * 調整割合
を相手側に送る

これで受け取った相手はそのとおり動いてくれるので、
自分のところでも送った情報どおりキャラクターを動かしていく

これで通信がいい人は気持ちよく動けて、環境の悪い人は自覚できるような動きになった

実際環境を悪くして実験してみると、つるつる地面を滑って動いていたので、
今回はこれでよし


次回は攻撃関連のことを書いてみる
トピックにパブリッシュするツールをつくる

## 背景

CloudPub/Subのトピックに任意のメッセージを積む際に `gcloud pubsub topics publish` を用いれば容易に行えるが、 パターンが増えると面倒になるのと、今後使い回すことを考慮してメッセージパターンは修正しやすフォーマットで定義したかった。勉強がてらShellScriptでつくることにした。

## 概要

* オプションで該当メッセージに対応するキーを渡す
* `--message`の値はJSONファイルから読む
* `gcloud pubsub topics publish`を用いて該当トピックにパブリッシュする

gcloudのインストールや実行環境のセットアップなどは行なっておらず、トピック名をハードコーディングにしている点など、改善した方がいいところはたくさんあるが...[こちら](https://github.com/nemotoy/sh-publisher/blob/master/publish.sh)で最低限の機能を実装した。

## 参考

* [jq Manual](https://stedolan.github.io/jq/manual/)
* [gcloud pubsub topics publish](https://cloud.google.com/sdk/gcloud/reference/pubsub/topics/publish)
* [shellCheck](https://github.com/koalaman/shellcheck)
* [入門UNIXシェルプログラミング](https://www.amazon.co.jp/gp/product/4797321946/ref=ppx_yo_dt_b_asin_title_o09_s00?ie=UTF8&psc=1)
* [使いやすいシェルスクリプトを書く](https://deeeet.com/writing/2014/05/18/shell-template/)
* [bashコーディング規約](https://qiita.com/mashumashu/items/f5b5ff62fef8af0859c5)
kotlin ジェネリクスの基本構文

# ジェネリクスとは
ジェネリクスはあるクラスを作る上で、型の情報を汎用的に持たせるための仕組み。
特にリストやハッシュ等のコレクションは任意の型のインスタンスをまとめることができるが、異なる型の要素を持ってはならないという制約がある。この場合、ジェネリクスを使って型情報を汎用化することで、コンパイラが型の安全性を保証できるようになっている。

# 書き方
## kotlin
https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/generics.html
### class
```kotlin

class Box<T>(t: T) {
  var value = t
}
```
```kotlin

val box: Box<Int> = Box<Int>(1)
```
パラメータを推測することができる場合には、型引数を省略することができます。

```kotlin

val box = Box(1) 
```
### 関数
```kotlin
fun <T> singletonList(item: T): List<T> {
  // ...
}

fun <T> T.basicToString() : String {  // 拡張関数
  // ...
}
```
ジェネリック関数を呼び出すには、関数名の 後に 呼び出し箇所で型引数を指定します。

```kotlin
val l = singletonList<Int>(1)
```

## Java

```java
class Box<T>{
    private T t;
 
    public Box(T t){
        this.t = t;
    }
 
    public T getT(){
        return t;
    }
}
```
```java
Box<Integer> box = new ClassSample<Integer>(1);
```
## 例
異なる型の共通の処理を書くことができる。
下記のコードは渡されたデータを2回printする処理。

```kotlin
class MyData<T>(private val t: T) {
    fun printTwo() {
        println(t)
        println(t)
    }
}

fun main() {
    val myStrData = MyData("aaa") //引数に文字列を指定
    myStrData.printTwo()

    val myIntData = MyData(1) //引数に数値を指定
    myIntData.printTwo()
}
```
実行結果

```
aaa
aaa
1
1
```

## 型制約
パラメータに型制約を持たせることが出来ます。
以下はChildClassクラスとそのサブクラスのみ使用できます。

```kotlin
open class ParentClass
open class ChildClass : ParentClass()
class GrandchildClass : ChildClass()

class Box<T: ChildClass> (t: T) {
    var value = t
}

fun main() {
    val box1 = Box(ParentClass()) //代入できない
    val box2 = Box(ChildClass()) //代入可能
    val box3 = Box(GrandchildClass()) //サブクラスなので代入可能
    val box4 = Box("String") //型が異なるので代入できない
}
```
iOS用にOpenCVをビルドする方法(opencv2.frameworkの作り方)

#概要
iOS用にOpenCV公式サイトでopencv2.frameworkが配布されていますが
contribのmoduleを使用したい場合は自分でビルドする必要があります。
探しても古い文献しか見つからなかったので現行バージョンをまとめます。

#実行環境
- macOS Mojave 10.14.6
- Xcode 10.2.1
- CMake 3.15.3
- Python 2.7.16
- [OpenCV](https://github.com/opencv/opencv) 4.1.2
- [OpenCV contrib](https://github.com/opencv/opencv_contrib) 4.1.2

#準備
###CMake
CMakeをインストールし忘れてエラーになってる人をよく見ます。

```
brew install cmake
```
###Python
どうインストールしてもよいですが、**2系**を用意してください。
(2019/9/20段階でOpenCVのビルドスクリプトがPython3に対応していませんでした。)
###OpenCV
任意のディレクトリにOpenCVをダウンロード

```
git clone https://github.com/opencv/
```
###(必要あれば)OpenCV contrib
任意のディレクトリにダウンロード

```
git clone https://github.com/opencv/opencv_contrib.git
```

#ビルド
下記コマンドでビルドするとoutputDirにopencv2.frameworkが出来ます。

```
python opencv/platforms/ios/build_framework.py --contrib opencv_contrib outputDir
```

#サンプルプログラム
後ほど追記

#まとめ
contribを含めてframeworkを作っておくとSIFTやTrackingなどが簡単に使えるようになります。
FireBaseのStorageは存在しないパスを指定するとErrorを投げるので困る

firebaseのstorageのダウンロードURLを生成する場合、

``` javascript
const url = await storage.ref(path).getDownloadUrl();
```
と言うような感じに書きますが、このgetDownloadUrl、pathに間違ったものを渡すとエラーを投げてきます。
確かに、エラー以外に何を返して欲しいのかと言うと思いつかないんですが、
存在しない場合URLは404返すだけだろうという感覚でいると穴に落ちます。

# 対応策
エラー時用のURLを用意して以下のようにcatchで対応するのがいいかと。

``` javascript
const url = await storage.ref(path).getDownloadUrl().catch((err) => {
 //エラーのlogging等が必要な場合はこの辺りで。
 return urlForEmpty;
});
```
尺取り法による部分文字列の探索

# 概要
ある条件を満たす部分文字列を探索する場合、総当たりで探索を行うと計算量がO(n^2)になり、制限時間に間に合わない場合がほとんどです。そこで今回は、尺取り法（しゃくとり法）によって効率的に部分文字列を探索する手法を紹介します。

# 例題
## [ABC032 C - 列](https://atcoder.jp/contests/abc032/tasks/abc032_c)

### 概要
長さ $n$ の0を含む自然数からなる数列 $a_1, a_2, \dots, a_n$ と自然数 $K$ が与えられる。数列の連続する部分列で、その積が $K$ 以下となるもののうち、最大の長さを求めよ (条件を満たす区間がないときは $0$ を出力)。

### 例
　条件: $n = 7$, $K = 6$, $a = (4, 3, 1, 1, 2, 10, 2)$
　解答: $4$

条件を満たす最長の部分列は(3, 1, 1, 2) であり、その長さは4である

### 実装例
```python
import sys
n, k = map(int, input().split())
s = []
ans = 0

for i in range(n):
    s.append(int(input()))

# 0が一つでも含まれている場合、積は0になり必ず条件を満たすため、数列の長さをそのまま返す
if any(n == 0 for n in s):
    print(n)
    sys.exit()

# 全ての要素がKを超えている場合、条件を満たす部分列は存在しない
if all(n > k for n in s):
    print(0)
    sys.exit()

# 右端のindex
r = 0
# 第1項を積として持っておく
temp = s[0]

for l in range(n-1):
    if l > 0:
        temp //= s[l-1]

    while r <= n - 1:
        # 積がK以下の場合、部分列の長さを調べて最長なら更新する
        if temp <= k:
            ans = max(ans, r - l + 1)
            r += 1
            if r <= n - 1:
                temp *= s[r]
        else:
            break

print(ans)
```


## [ABC124 D - Handstand](https://atcoder.jp/contests/abc124/tasks/abc124_d)
### 概要
0と1 からなる長さ N の文字列 S と正整数 K が与えられる。連続する0の列をK回まで1の列に変換できる時、連続する1の列を最長でどれだけの長さにできるかを求めよ

### 方針
連続する0の列をK個以下含むような最長の部分列の長さを求めれば良い

### 実装例
```python
n, k = map(int, input().split())
s = input()
ans = 0

# 連続する0の列が現れる回数を数える
cnt = 0

# lを左端、rを右端とする
r = 1
for l in range(0, n):
    if l == 0 and s[l] == '0':
        cnt += 1

    # 左端が0から1に変わるタイミングで、カウントを１減らす
    if l > 0 and s[l] == '1' and s[l-1] == '0':
        cnt -= 1

    while r <= n - 1:
        # 右端が1から0に変わるタイミング
        if s[r] == '0' and s[r-1] == '1':
            # カウントがK未満の場合は、単にカウントを増やす
            if cnt < k:
                cnt += 1
            # カウントがKに達している場合、while文を抜ける(左端:lを一つ進める）
            else:
                break
        r += 1

    # 最長部分列の長さを更新
    ans = max(ans, r - l)

print(ans)

```

## 問
文字列Sの部分文字列のうち、下記の条件を満たす最長の部分文字列Tの長さを求めよ

- TはSに含まれる連続する部分文字列である
- Tは３種類以上の文字を含んではならない

### 例１
#### 入力
```
"eceba"
```


#### 出力
```
3
```
"ece"が条件を満たす最長の部分文字列となる

### 例２
#### 入力
```
"ccaabbb"
```

#### 出力
```
5
```
"aabbb"が条件を満たす最長の部分文字列となる

### 実装例
```python:条件を満たす最長の部分文字列の長さを求める
    # 条件判定のメソッドを用意しておく
    def isValid(t):
        charSet = set()
        for c in t:
            charSet.add(c)
            # 3種類以上の文字を含む場合はアウト
            if len(charSet) > 2:
                return False
        return True

    def longestSubstringLength(s):
        maxLen = 0

        for i in range(len(s)):
            l = i
            r = i + 1

            while l < r and r < len(s):
                # lからrの範囲の部分文字列を調べる
                temp = s[l:r+1]

                # 条件を満たす部分文字列が見つかったら、rを右にずらして探索範囲を広げる
                if isValid(temp):
                    if len(temp) > maxLen:
                        maxLen = len(temp)
                    r += 1
                # 部分文字列が条件を満たさない（3種類以上の文字を含む）場合、whileループから抜ける
                else:
                    break

        return maxLen

```

## 参考
[しゃくとり法 (尺取り法) の解説と、それを用いる問題のまとめ](https://qiita.com/drken/items/ecd1a472d3a0e7db8dce)
SwiftUI Property WrappersクラスのwrappedValue・projectedValue一覧表

# 環境

Swift 5.1
Xcode 11.0 (11A420a)  

2019年9月現在`SwiftUI`は変化が大きく、当記事に示した挙動もバージョンを経ると変更される可能性が十分にあるため、ご注意ください。

# 執筆動機

Swift5.1にて`Property Wrappers`という機能が追加されました。
ですが当方、`foo`、`_foo`、`$foo`、`wrappedValue`、`projectedValue`がそれぞれ何を意味しているのか...と、
それぞれの関係性が掴みあぐねておりまして...😇

ですが、先日の[こちら(YouTubeに遷移します)](https://www.youtube.com/watch?v=WYBwFj4xQWo)の発表と[その資料](https://speakerdeck.com/kumamotone/sikumikarali-jie-suruswiftui)で非常に丁寧に解説されており、自分でも手を動かすことで、理解を深めることができました。
複雑に考えすぎていたのですが、その実態はすごくシンプルだったんですね...。😅

すなわち。ほぼ引用してしまう形ですが...。

1.

```swift
@Hoge var foo: Int 
```

と書くと、

```swift
var foo: Int
var _foo: Hoge<Int>
```

に展開されるような形となる。

2.

```swift
foo は、_foo.wrappedValue と等価。
$foo は、_foo.projectedValue と等価。
```

ルールとしてはたったこれだけでした。

例えば`Hoge`クラスが、このような定義で、いま`element` に`Int`の`42` が入っていて...

```swift
// @propertyWrapperは、クラス・構造体・列挙体に付加可能
@propertyWrapper
struct Hoge<T> {
    var element: T  // 今、ここが :Int = 42 だとする
        
    // これはgetterのみ定義しているが、望むならsetterを定義することも可能
    var wrappedValue: T { element }
    // これはgetterのみ定義しているが、望むならsetterを定義することも可能
    var projectedValue: Hoge<T> { Hoge(element: element) }
}
```

このようなプロパティがあるとしたら...

```swift
// ここの型アノテーションは、移譲先の型の wrappedValueの型と一致しなければならない
// 一致しないときは、Property type '誤って指定した型名' does not match that of the 'wrappedValue' property of its wrapper type 'wrappedValueの型' というコンパイルエラーが出力される
@Hoge var foo: Int 
```

`foo` と書くと、`wrappedValue` のgetter呼び出し

```swift:print(foo)の結果
42
```

`$foo`と書くと、`projectedValue` のgetter呼び出し

```swift:print($foo)の結果
Hoge<Int>(element: 42)
```

になります。

`wrappedValue` にアクセスするには、

- `foo`
- `_foo.wrappedValue`

`projectedValue` にアクセスするには、

- `$foo`
- `_foo.projectedValue`

それぞれ2通りの方法がある、ということですね。
後者は冗長な書き方ということになると思うので、基本的に前者の書き方でアクセスしていけばいいかと思います。

# SwiftUI Property WrappersクラスのwrappedValue、projectedValue一覧表

ということで、SwiftUIで頻出するProperty Wrappersクラスの`wrappedValue`と`projectedValue`が返す値の型をまとめ、表に起こしてみました。

|propertyWrapperクラス|`wrappedValue`|`projectedValue`
|:-:|:-:|:-:|
|`State<Value>`|`Value { get nonmutating set }`|`Binding<Value> { get }`
|`Binding<Value>`|`Value { get nonmutating set }`|`Binding<Value> { get }`
|`ObservedObject<ObjectType>`|`ObjectType { get }`|`ObservedObject<ObjectType>.Wrapper { get }`
|`EnvironmentObject<ObjectType>`|`ObjectType { get }`|`EnvironmentObject<ObjectType>.Wrapper { get }`
|`Environment<Value>`|`Value { get }`| × (未定義のためコンパイルエラー)

# 参考

[Why I Can Mutate @State var? How Does @State Property Wrapper Work Inside?](https://forums.swift.org/t/why-i-can-mutate-state-var-how-does-state-property-wrapper-work-inside/27209/2)
ONNXのValueInfoProtoにinitializerで値を設定する

これの続き。自力でMLPのONNXファイルを作りたい。

https://qiita.com/natsutan/items/9233a65db4cc90fb4c3a

Reshapeのパラメータ（reshape後のshape)が、値が設定されていないのでグラフの入力につながないとエラーになる。

こちらを見ながら、initializerで値を設定する。
https://github.com/onnx/onnx/blob/master/docs/IR.md

initializerはValueInfoProtoではなく、GraphProtoに紐づくのでmake_graphの引数で指定する。値はnumpy.helperを使い、numpy arrayからTensorProtoを作る。TensorProtoにValueInfoProtoと同じ名前を付けると、make_graph時に紐づけてくれる。

```python
import numpy
from onnx import helper, numpy_helper

# numpy array から TensorProtoを作る
input_shape_init = numpy_helper.from_array(numpy.array([784], dtype=numpy.int64))
input_shape_init.name = 'input_shape'
```

これで、Graphの入力からReshapeのパラメータが消えました。

![reshape_ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/22f22517-b899-55db-ba28-034fd11a35ef.png)

全ソースはこう。次はレイヤーを書さえてMLPにする。

```python
import numpy

import onnx
from onnx import TensorProto
from onnx import helper, numpy_helper

X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [28, 28])
input_shape = helper.make_tensor_value_info('input_shape', TensorProto.INT64, [1])
reshape_out = helper.make_tensor_value_info('reshape_out', TensorProto.FLOAT, [784])

# numpy array から TensorProtoを作る
input_shape_init = numpy_helper.from_array(numpy.array([784], dtype=numpy.int64))
input_shape_init.name = 'input_shape'

flat_op = helper.make_node(
    'Reshape',
    inputs=['X', 'input_shape'],
    outputs=['reshape_out'],
    name="reshape_node"
)

graph_def = helper.make_graph(
    [flat_op],
    'my-mlp',
    [X],
    [reshape_out],
    initializer = [input_shape_init]
)

model_def = helper.make_model(
    graph_def,
    producer_name='natsutan'
)

onnx.save(model_def, 'onnx/my_mlp.onnx')
onnx.checker.check_model(model_def)
print('The model is checked!')
```
Activityが再表示されたことを簡単に知る

#はじめに
アプリの開発で画面に戻ってきた際に
トラッキングを仕込むとういう実装をした時に見つけたのでメモ。

###onRestart()
```Kotlin:sampleActivity.kt
override fun onRestart() {
    super.onRestart()
    // do something
  }
```
ActivityにonRestart()というメソッドが用意されているのでこの中に処理を実装します。
onRestart()はonStop()されたActivityがまた表示される時に呼び出されるようです。
LANとWANについて超絶簡単に説明してみた。

はい、どうも
アウトプットは大事ですね！
ってことで、今回は第２弾ネットワーク基礎！
ってことで前回の最後のほうにお話しした
WANとLANについてです！
ネットワークって？って方は前回の記事を読んでくださいね！

前回記事：https://qiita.com/sinkuro06/items/b3f9496c6eed7deecdad

では早速いってみよう！

<h1>LANとは？</h1>
まずLAN（ラン）とは何か？ですが、
これは簡単に説明しましたね。
限定した地域のみのネットワークで、わかりやすく言うと
ビル１個、部屋１個にのみネットワークを作る感じです。
そしてこの狭い範囲の中でパソコン同士、またパソコンとプリンタなどの
デバイス（端末）をつなげることですね！

そしてLAN内のデバイスはいつでも接続できるのでデータの共有が可能なんですね。
なので、LANは<b>高品質かつ、高速</b>になります！

高品質っていうのは、
例えば、電話とかで通話してる時にノイズが入ったり
聞こえにくくなったり、最悪、電話が切れたりすることってありますよね？
こういったエラーが起きにくいってことが高品質なんですね。

そして
高速っていうのは、詳しく説明すると難しくなるのですが、
一度にデータを送信できる量があって、コンピュータでは<b>ビット</b>という
単位でデータの大きさを数えています。
そのデータを運ぶのが早いってことですね。

まぁ建物の中でのみのLANだと距離も狭いので問題が起きにくいって
考えれば理解しやすいですね！




<h2>WANとは？</h2>
では、WANとは何か？なんですが、
前回の最後に簡単にお話しはしていました。
LANとLANをつなぐことができるネットワークです。

わかりやすくいうと建物と建物をつなぐことができるので
広い範囲でのネットワークということになります！
会社所有の建物が２つ以上あって関西と関東にある場合など
データやりとりが便利になりますね！
ただ、LANの場合はその建物内でケーブルをつなげればいいだけです
WANの場合はケーブルは難しいですよね？
そのため大手のケーブルを借りて接続しています。
皆さんも契約してますよね！
ADSLとかISDNとか！！
そのおかげでインターネットで世界中にアクセスできるようになっているんです！

ただし、WANの場合はWANは必ずしも常時接続とは限らないです。
そして基本的にWANはLANよりも低速になっています。


<h2>まとめ</h2>

なのでWANとLANでは共通している部分としては
両方とも<b>データを伝送</b>しているというところです
違いをまとめましょう！

<table border="1">
<thead class="bg1">
<tr><th>&nbsp;</th><th>LAN</th><th>WAN</th></tr>
</thead>
<tbody class="bg2">
<tr><td>範囲</td><td>狭い</td><td>広い</td></tr>
<tr><td>スピード</td><td class="lan">早い</td><td>遅い</td></tr>
<tr><td>品質</td><td>高い</td><td>低い</td></tr>
<tr><td>接続</td><td>常時<br></td><td>常時・間欠</td></tr>
<tr><td>ケーブル</td><td>自分で設置<br></td><td>電話会社のを借用</td></tr>
<tr><td>使用料金</td><td>タダ<br></td><td>電話代が必要</td></tr>
<tr><td>対象</td><td>パソコンとパソコンを接続<br></td><td>LANとLANを接続</td></tr>
</tbody>
</table>

ってところですね！
ではLANとWANの違いや説明は以上！
光ファイバーリフレクターをPONネットワークリンクモニタリングに適用する方法

PON（受動光ネットワーク）ネットワーク、特に複雑なポイントツーマルチポイントPON ODN（光配信ネットワーク）トポロジ環境では、ファイバー障害の迅速な監視と診断が1つになります。 やりがいのある仕事。 光時間領域反射率計（OTDR）ツールは広く使用されていますが、OTDR検出は、一部のODN分岐ファイバまたはONUファイバの端での光信号の減衰に特に敏感ではない場合があります。 ONU側に低コストの波長選択性光ファイバーリフレクターを設置することは、多くの場合、光リンクの正確なエンドツーエンド減衰を達成するために現在使用されている手法です。

光ファイバーリフレクターの動作原理は、主にOTDRによって送信されたテスト光パルスを100％近くの反射率に戻すためにファイバーグレーティングを使用することですが、通常のパッシブ光ネットワーク（PON）システムの動作波長はファイバーブラッグブラッグ条件を満たしていません。 リフレクターを少し減衰させて通過させます。 これの主な機能は、反射されたOTDRテスト信号の有無と光信号の強度を検出することにより、各ONUブランチの終わりで反射イベントのリターンロス値を正確に計算することです。 したがって、OLT側からONU側への光リンクが正常かどうかが判断されます。 これにより、障害点のリアルタイム監視と高速で正確な診断が可能になります。
![63.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/fe0155f1-516a-6f0d-aa5d-59c92b7e08f1.jpeg)

リフレクタの位置を柔軟に展開し、さまざまなODNセグメントを識別することにより、ODN障害ポイントの検出と場所の分析を迅速に実装でき、障害処理時間を短縮でき、テスト効率と回線保守の品質を向上できます。 第1レベルの分割シーンでは、ONU側に設置された光ファイバーリフレクターは、特定のファイバーブランチのリフレクターのリターンロスがヘルスファイルのリターンロス値と比較して大幅に増加した場合、このブランチのファイバーが示されることを示しています。 リンクに問題があります。光ファイバリフレクタを備えたすべてのファイバブランチに同時に明らかなリターンロスがある場合は、トランクファイバに障害が発生していることを示しています。

![62.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/52c31232-5574-51d6-435c-f5609023ce3e.jpeg)

二次分光シーンでは、リターンロスの差を比較することにより、配線ファイバセグメントまたは着信ファイバセグメントに減衰障害があるかどうかを正確に特定することもできます。 一次分光シーンか二次分光シーンかに関係なく、OTDRテスト曲線の終わりで反射ピークが急激に低下するため、ODNネットワークの最長ブランチのリターンロスを正確に測定できない場合があります。 反射レベルの変化は、障害の測定と診断の基礎となります。

たとえば、FBGをFTTH / FTTの前にインストールし、次にOTDRを使用してテストデータをベースラインデータと比較するなど、光ファイバーリフレクターを配置する必要がある場合はいつでもインストールできます。 屋内/屋外、屋内/屋外の繊維の故障を判断できます。

![61.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463940/48e72d21-67d1-36c4-59bf-3a9c3f087a1c.jpeg)

光ファイバリフレクタは、長寿命、安定した信頼性の高い、小さな温度特性、アダプタ構造の便利な接続などを備えて、ユーザエンドに便利に直列に配置でき、光ファイバリフレクタがFTTxネットワークリンクモニタリングの理想的な光端末になる理由の1つです。 Yiyuantongは、さまざまなパッケージタイプのFBG光ファイバリフレクタ、プラスチックフレームセット、金属フレームセット、ピグテールピグテールの形のSCコネクタまたはLCコネクタを提供できます。

HYC は、光通信パッシブ基本コンポーネントのR＆D、製造、販売、およびサービスを専門とする国立ハイテク企業です。 同社の主な製品は、光ファイバコネクタ（データセンター高密度光コネクタ）、波長分割マルチプレクサ、光スプリッタ、およびその他の3コアの光パッシブ基本コンポーネントです。 インターネットデータセンター、防衛通信、その他の分野。http://www.hyc-system.com
Google AIY Vision Kit：Rpiを画像認識デバイスに変える

Googleは、Raspberry Pi機器を画像認識デバイスに変えることができるAIY（AI自分）ビジョンキットを発売しました。 ビジョンキットはGoogleのTensorFlow機械学習モデルを搭載しており、まもなくデバイスを制御するためのAndroidアプリが付属します。

![vision.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/ac44d5d8-7e19-8cf9-11be-dfa4e1d239f6.jpeg)


AIY音声プロジェクトも導入しました。これにより、メーカーはGoogle Assistant SDKを使用して、Raspberry Piを音声制御アシスタントに変えることができました。


![微信截图_20181109141818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/20b294b7-e858-9e32-9fb0-54c653bd781e.png)


Vision Kit は「オンデバイスニューラルネットワークアクセラレーション」を特長としており、Raspberry Piベースのボックスでクラウドで処理せずにコンピュータービジョンを実行できます。 AIY Voice Kitは、自然言語処理をクラウドに依存しています。

キットには、最大1000種類のオブジェクトを認識できるオブジェクト認識アプリケーション、顔とその表情を認識するオブジェクト認識アプリケーション、人、猫、犬を検出する3つのアプリケーションがあります。 それだけで多くのいたずらをすることができますが、独自のニューラルネットワークを実行することもできます。


VisionBonnetボードはGoogleによって開発され、IntelのMovidius MA2450ビジョン処理チップを搭載しています。 このチップは、Vision Kitの秘密のソースです。 Raspberry Pi 3に依存する場合よりもコンピュータービジョンの実行が60倍速くなります。VisionBonnetは、キットに付属のケーブルでRaspberry Pi Zero Wに接続されます。

![微信图片_20190322105747.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/fdee3c3e-9087-1b23-c224-7cc69671612f.jpeg)

![微信图片_20190322105718.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/b92dfb7e-6ea3-a4b1-f68d-7ac42d7565ee.jpeg)
![微信图片_20190322110455.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/82ae8cf2-7193-705c-2b0b-6ef68b12d83e.jpeg)



Googleは、開発者がこれらのニューラルネットワークを構築し、猫/犬/人の検出器にウサギを認識させるなどの新しいタスクに適用することを望んでいます。 この目標を達成するために、TensorFlowでモデルを再トレーニングするためのモデルをコンパイルするツールが提供されています。

Vision Kitは、Googleディストリビュータ [Gravitylink](https://store.gravitylink.com/global/vision-kit) から89.99ドルで入手できます。
複数サイトのGoogle Analyticsを一括閲覧するブックマークレット


https://analytics.google.com/analytics/web/
にアクセスしてから、下記のブックマークレットを実行します。


```js
javascript:
    const root_path = 'https://analytics.google.com/analytics/web/#/report-home/';
    const h = window.innerHeight * 0.8;

    if(!document.location.href.match(/analytics.google.com/)){
        document.location.href = root_path;
    }

    let iframes = [
        { name: 'site_a', src: '44rw4rfsjlosk4ut4osgubsxlrutr' },
        { name: 'site_b', src: 'sw43roislfgvjslertkgvsdlguvsd'},
        { name: 'site_c', src: 'xserfswzr4wregvbdxfgvdser33gs' },
    ];

    $('body').attr('class', '').css({padding: '10px'}).empty();

    for (let i in iframes) {
        let iframe = iframes[i];

        $(`<h3>${iframe.name} <a id="${iframe.name}" name="${iframe.name}"></a></h3>`).appendTo('body');
        $('<div>').append($(`<iframe style="width:95%; height:${h}px; border:1px solid gray;">`).attr('src', root_path + iframe.src)).appendTo('body');
    }

```

srcの文字列は、アナリティクスのURLの最後につく文字列です。
こんな感じに、一括でiframe表示されますー
![gazou.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255465/d0b32b35-c6c4-efa9-9310-00e9ac23903e.jpeg)
VirtualBox+apatchでvhostがうまく動かない

# VirtualBox内のvhostがうまく動作していない気がする

## Vhostの設定を確認する
```
httpd -S

[root@loca html]# httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:80                   is a NameVirtualHost
         default server xxxx.co.jp (/etc/httpd/conf.d/_default_vhost.conf:1)
         port 80 namevhost xxxx.co.jp (/etc/httpd/conf.d/_default_vhost.conf:1)
         port 80 namevhost vmlocal.xxxx.local (/etc/httpd/conf.d/admin.conf:1)
                 alias vmlocal
         port 80 namevhost aaa.vmlocal.xxxx.local (/etc/httpd/conf.vhost.d/vhosts-aaa.conf:2)
         port 80 namevhost bbb.vmlocal.xxxx.local (/etc/httpd/conf.vhost.d/vhosts-bbb.conf:2)
         port 80 namevhost html.vmlocal.xxxx.local (/etc/httpd/conf.d/html.conf:1)
Syntax OK
```
【備忘録】DAで全角になってしまう・・・orz　仮想キーコードの入力（半角／全角キー）

DAS側の端末が全角入力になっていて、半角入力が出来ないときの対処

１．DAS端末を全角入力にしない
　┗　アプリによって強制的に全角入力にされるケースあり
２．「Set Clipbord」のステップを挟み、一度Clipbordに貼り付け、そこから値を取ってくる
　┗　入力箇所が多いと面倒・・・
３．入力値を判断するステップを設け、全角だった場合に「半角/全角キー」を押すステップを作り、再入力させる
　┗　「半角/全角」キーは通常の「Press Key」ステップの候補には出てこない　

なので、↓　の情報が必要

■通常の「Press Key」ステップで作成できないキー操作を行う
（半角／全角キーの押下、複数キーの同時押下など）

手順：
　1.「Press Key」ステップを作成して、「Standard Key」を「Calculated Key」に変更する
　2.「Key Code」に仮想キーコード（下記参照）を記載する

仮想キーコードの入力例：
　半角／全角を押す → v0x19
　半角／全角を離す → v0x19,fu
　AとBを押す → v0x41 v0x42
　AとBを離す → v0x41,fu v0x42,fu

仮想キーコードの参考URL：
http://kts.sakaiweb.com/virtualkeycodes.html

上記のサイト内の表の列で、左端の列（値の列）の丸カッコの中が仮想キーコード。
中央の列（意味の列）でキーボード上のどのキーかを判断。
Trelloのボードを縦スクロールに変えてみた

記事の訂正
同じ目的なら、こちらのchrome拡張を使うべきです
[List Layouts for Trello](https://chrome.google.com/webstore/detail/list-layouts-for-trello/aldklnbenbdgfgfbflalmlddkkndgnlc)

---

[Stylus](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?hl=ja) というchrome拡張機能を使って、Trelloのボードを縦スクロールに変えてみました。

<img width="1166" alt="trello.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/6cf26dc6-d820-8490-8a24-9c9f40dbb0a8.png">

リストの高さが画面全部必要じゃない場合には、こちらの方が見通しが良い気がします。

Stylusで上書きしたCSSはこんな感じです。

```
#board {
    overflow-y: scroll;
}
.list-wrapper {
    height: 49%;
    margin-bottom: 1%;
    float: left;
}
```
[漏洞预警]泛微e-cology OA Beanshell组件远程代码执行分析

### 漏洞描述
泛微e-cology OA系统由于某些功能引用BeanShell.jar开发,但BeanShell组件且开放未授权访问，攻击者调用BeanShell组件接口可直接在目标服务器上执行任意命令.目前漏洞的安全补丁已由泛微官方发布,可参阅文末.
### CVE编号
暂无
### 漏洞威胁等级
高危
### 影响范围
包括不限于7.0,8.0,8.1
### 漏洞复现
使用payload进行验证

![payload](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/a715c6c2-a9dd-bc13-0f02-29cdc4a49471.png)


### 简单分析
由于此次存在漏洞的jar是Beanshell,于是我研究了一下Beanshel.
参阅官方文档,下载了war包在本地搭建
![war](https://upload-images.jianshu.io/upload_images/5350990-18b0ea8494a74d46.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![war](https://upload-images.jianshu.io/upload_images/5350990-aad05e71aedcd87c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


根据官方文档说明,我直接执行一个os命令,得到了回显

![官方文档](https://upload-images.jianshu.io/upload_images/5350990-32ac14af1576548a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


![回显](https://upload-images.jianshu.io/upload_images/5350990-ee583060f10fdb65.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


接着我到泛微e-cology OA环境下复现

![泛微e-cology OA](https://upload-images.jianshu.io/upload_images/5350990-3d88464cb7fecf1b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

发现也成功了,但部分版本未成功,因为其做了全局函数过滤,需要绕过

![部分版本未成功](https://upload-images.jianshu.io/upload_images/5350990-ddfb1753cfa06608.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

随后在朋友的帮助下,成功绕过了过滤

![绕过过滤](https://upload-images.jianshu.io/upload_images/5350990-1dfacc70cdf1b6b6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

### 鸣谢(排名不分先后)
pyn3rd
thesoul(404)
lufei
### Reference
Beanshell官方指南:
[https://beanshell.github.io/](https://beanshell.github.io/)
补丁包下载:
https://www.weaver.com.cn/cs/securityDownload.asp
Unityでオンラインマルチプレイなゲームを作りたい その13 当たり判定について

[前回の記事](https://qiita.com/koyuki2007/items/5862b36a56d577e4f54c)でダンジョンの生成同期を行なえるようにしました。
これでプレイヤー, 敵, 弾, ステージがそろったので、ゲームとしての必要最低限のパーツは整いました。
ということで、当たり判定を設けて遊べるようにしていこうと思います。

# 今回の目標
当たり判定を実装します。

# プレイヤーの当たり判定
まずはプレイヤーから、[その8 プレイヤーの同期](https://qiita.com/koyuki2007/items/e7d16e020539f38c6e7c)で実装しているPlayerクラスに追加します。

## ホストで全てやるか、各クライアントでやるか
基本はホストで各クライアントの当たり判定も計算してしまうのですが、
飛んでくる弾の視認性的にホストで行った際にラグ等で起こるズレが気になるかもしれません。(FPSの銃弾ならいいんですがね...。)
ということで、今回は各プレイヤーで当たり判定を行ってもらうように実装します。

※追加するところ以外は省いてます。

```c#:Player.cs
/// <summary>プレイヤークラス</summary>
public class Player : UnityEngine.MonoBehaviour
{
    // 
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (!monobitView.isMine) { return; }

        if (other.tag.Equals("EnemyBullet"))
        {
            --m_HealthPoint;

            m_State = State.Unrivaled;

            if (m_HealthPoint <= 0){ Dead(); }
        }
    }

    /// <summary>死亡処理</summary>
    private void Dead()
    {
        m_State = State.Dead;

        m_HealthPoint = 0;

        m_FlashingColor.a = 0.5f;

        m_SpriteRender.color = m_FlashingColor;

        tag = "Player(Dead)";
    }
}
```
<code>OnTriggerEnter2D</code>内で敵弾に当たった際にHPを減らし0になったら死亡するというシンプルな内容になっています。
<code>OnTriggerEnter2D</code>の頭で<code>monobitView.isMine</code>を使い自身だけで処理を行うようにしています。
パラメータの同期については、[その8 プレイヤーの同期](https://qiita.com/koyuki2007/items/e7d16e020539f38c6e7c)で既に実装している<code>OnMonobitSerializeView</code>で行っているのでこれと言って特に同期する処理は新しく追加していません。

## 敵の当たり判定
つぎに敵の当たり判定の実装を行います。

```c#:Enemy.cs
public class Enemy : UnityEngine.MonoBehaviour
{
    // 
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (!MonobitNetwork.isHost) { return; }

        if (other.tag.Equals("PlayerBullet"))
        {
            -m_HealthPoint;

            if (m_HealthPoint <= 0)
            {
                m_HealthPoint = 0;

                MonobitNetwork.Destroy(gameObject);
            }
        }
    }
}
```
敵はホストで管理されているので当たり判定もホストで行うように<code>MonobitNetwork.isHost</code>で制限しています。
ヒット時のパラメータの同期等についてはプレイヤーと同じく<code>OnMonobitSerializeView</code>で行っているので、同期については特に新しく追加することはありません。

## 弾の判定
弾は発射のタイミング同期で生成された後、ネットワークを介した処理は行っていないため、特に実装することはありません。
強いて言うなら各クライアントでどこかしらにヒットした際に弾を消す処理を加えてあげるくらいです。


記事内容的に目新しいものはなかったですね。プレイヤーの当たり判定を行うところで、ホストでやるかクライアントでやるか、が少し重要なくらいでした。

ここでゲーム内容のネットワークの実装については最後になります。
次回はリザルト画面を作りたいと思います。
ダブルクリックやドラッグ＆ドロップでpythonを実行する (Windows)

ダブルクリックやドラッグ＆ドロップでpythonプログラムを実行できるようにしました。

# やり方

知ってる人にとっては当たり前だと思うんですが、バッチファイルを使えばダブルクリックやドラッグ＆ドロップでpythonプログラムを実行できるようになります。いちいちキーボードで処理対象のファイルPATHを入力したりする面倒な作業を簡略化できます。

# 試行環境

Windows10
python3.6

# バッチファイルとは


みんなが大好きな黒い画面、WindowsのコマンドプロンプトはOSのAPIを直接操作できる権限の強いインターフェイスです。ここに対して1行ずつコマンドを入力していく事も出来ますが、コマンドをテキストファイルにまとめて書いたバッチファイルを使っておいてまとめて処理する仕組みもあります。今回はこれを使ってpythonプログラムをダブルクリックやドラッグ＆ドロップから使えるようにしちゃいます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/3c093b17-d2eb-1ef6-1d0b-298f11b91b8c.png" width=70%>

# バッチファイルの作り方

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/4d11f74f-037b-4d23-7974-f6b021eae017.png" width=50%>
作るのは簡単でテキストファイルにコマンドを１行ずつ書くだけです。拡張子をbatにするとバッチファイルとして扱ってくれます。あとは適当なエディタ(メモ帳でも良い)で書き換えるだけです。

# ダブルクリックでpythonのコードを実行する


バッチファイルと同じフォルダに実行するpythonファイルを置いておきます。とりあえず以下のファイルを置いたものとします。

```python:test.py
print('Hello, This is test.py!')
```
python.exeにPATHが通ってる環境なら以下でtest.pyを実行できます。

```terminal:バッチファイル
python hoge.py
```
フォルダが違う場合もフルPATHを書けば実行できます。

### conda環境のpython.exeを使う場合

python.exeをフルPATH指定で呼べばOKです。

```terminal:バッチファイル
E:\Anaconda3\envs\tf\python.exe hoge.py
```
pythonの場所はconda activateしておいてwhere pythonで探せばすぐ分かります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/03cf09ee-878d-6dd9-92bc-c076c4f7f09d.png" width=70%>
### conda環境のpython.exeを使う場合 その2
conda activateもできます。

```terminal:バッチファイル
call conda activate tf
python hoge.py
```


### 黒い画面に最小化して頂く

黒い画面さまにやって頂いてるので当然黒い画面が表示されるんですが、動作をモニターする必要がないときは見た目的に圧がすごいので最小化しておいてもらいます。その場合はバッチファイルを2つ使って、1つめのバッチファイルから最小化したコマンドプロンプトを呼んで、新しいコマンドプロンプトで2つめのバッチファイルを呼ぶようにします。

```terminal:test1.bat
start /min %~dp0test2.bat %*
```
startコマンドに最小化オプション/minをつけて、最小化した状態でコマンドプロンプトを開きます。開いてから実行するコマンドを指定できますので、そこで2つめのバッチファイルを実行するように指定します。1つめのバッチファイルはそこで処理が終了しますので勝手に消えてくれます。

```terminal:test2.bat
@echo off
E:\Anaconda3\envs\tf\python.exe test.py
```
2つめのバッチファイルは先程と同様にpython.exeを実行します。

### ドラッグ＆ドロップでファイルに対して処理を行う

pythonコードに引数の受け取り処理を追加します。

```python:test2.py
import sys
print(sys.argv[-1])
```

```terminal:コマンドプロンプト
> python test2.py hoge
hoge
```
test2.pyにコマンドライン引数を渡せるようになりました。バッチファイルにドラッグ＆ドロップすると%1としてファイルPATHが受け取れるので以下のようにするとバッチファイルにドラッグ＆ドロップしたファイルをpythonから処理できるようになります。処理後にコマンドプロンプトがすぐ消えてしまうので、timeoutで待機するようにしています。

```bash:バッチファイル
python hoge.py %1
timeout 10
```
上記のバッチファイルに適当なファイルをドラッグ＆ドロップするとファイルのPATHをpythonに渡してくれます。後はpython側で好きなように処理するだけです。

```terminal:実行結果
c:\hoge\fuga.txt
```

レッツトライ！
Djangoでアプリのログインページを作る方法

こんにちは、[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている者です。
今回は、Djangoでログインページを作る方法を書いていきたいと思います。

##開発環境

まずは開発環境を整えておきます。

- Python3.7.3
- Django2.4

##構成

今回は、以下のような構成で作っていきます。

- ログイン：トップページ→ログインページ→（ログイン）→トップページ
- ログアウト：トップページ→（ログアウト）→ログアウト確認ページ→トップページ

##設定

今回の説明は、以下の設定で進めていきます。

- プロジェクトディレクトリ：```projects```
- アプリディレクトリ：```apps```
- テンプレートファイル（全て```apps/templates/apps/```内）:
    - トップページ：```index.html```
    - ログインページ：```login.html```
    - ログアウト確認ページ：```logout.html```

また、トップページは作れていることを前提に進めていきます。

##コード

新しく作成するファイルや、既存のファイルに追加するコードを紹介していきます。

###settings.py

```python:projects/settings.py
#ファイルの末尾に下の2行を追加
LOGIN_URL = 'apps:login'
LOGIN_REDIRECT_URL = 'apps:index'
```

１行目は、```login/```がログインページのURLであることを表します。
2行目は、ログインすると、```index/```（トップページ）のURLにリダイレクトすることを表します。

###urls.py

```python:apps/urls.py
#以下のインポート文を追加
from django.contrib.auth import views as auth_views

#urlpatternsに以下の2行を追加
urlpatterns = [
    path('login/', auth_views.LoginView.as_View(template_name='apps/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(templates_name='apps/logout.html'), name='logout'),
]
```

django.contrib.authからviewsをインポートします。
すでにapps/views.pyをインポートしているので、それと区別するために、auth_viewsという名前を定義してインポートします。

###index.html

```html:apps/templates/apps/index.html
<!DOCTYPE html>
<html>
  <head>
    ...
  </head>
  <body>
    ...
    {% if request.user.is_authenticated %}
    <a href="{% url 'apps:logout' %}">ログアウト</a>
    {% else %}
    <a href="{% url 'apps:login' %}">ログイン</a>
    {% endif %}
    ...
  </body>
</html>
```

トップページの、ログイン/ログアウトボタンを付けたい場所に上の5行を追加します。
ユーザー認証済であれば（1行目）、ログアウトボタンを表示し（2行目）、認証未済であれば（3行目）、ログインボタンを表示します（4行目）。
    

###login.html

```html:apps/templates/apps/login.html
<!DOCTYPE html>
<html>
  <head>
    <title>ログインページ</title>
  </head>
  <body>
    <form method="post">{% csrf_token %}
      {% if form.errors %}
      <p>ログインエラー。もう一度入力してください</p>
      {% endif %}
      <h2>ログイン</h2>
      <label>ユーザー名</label>
      <input name="username">
      <br>
      <label>パスワード</label>
      <input type="password" name="password">
      <br>
      <input type="submit" value="ログイン">
    </form>
    <hr>
    <a href="{% url 'apps:index' %}">トップページに戻る</a>
  </body>
</html>
```

ログインページには、ユーザー名とパスワードを入力するフォームが表示されます。
正しいユーザー名とパスワードを入力すると、トップページに戻ります。
もしユーザー名とパスワードの組み合わせを間違えて入力した場合、ログインエラーと表示され、再度フォームが表示されます。

###logout.html

```html:apps/templates/apps/logout.html
<!DOCTYPE html>
<html>
  <head>
    <title>ログアウトしました</title>
  </head>
  <body>
    <p>ログアウトしました。</p>
    <a href="{% url 'apps:index' %}">トップページに戻る</a>
  </body>
</html>
```

ログアウトしたことを確認するページです。
トップページに戻るボタンをクリックすると、ログアウトした状態でトップページに戻ります。

##まとめ

今回は、Djangoでログインページを作成する方法を紹介しました。
今回紹介した方法はあくまで一例であり、ログインページの作成の仕方はいくらでもあります。
もし「こんな作り方もあるよ」とか「こっちの方がいいよ」という作り方があれば、ぜひコメントをお願いします。
また、今回紹介した内容に間違いがありましたら、修正しますので、ご指摘お願いいたします。

##参考URL

DjangoBrothers（非常に分かりやすいチュートリアルで、僕のおすすめです。）：
https://djangobrothers.com/tutorials/photo_app/authentication/
root が、unix_socket 認証のとき、ansible で、db,user つくる記述

こうかけばいいだけ

```
- name: 対象データベース作成
  become: yes
  mysql_db:
    login_unix_socket: /var/run/mysqld/mysqld.sock
    login_user: root
    name: "{{ db_name }}"
    state: present

```
【Swift】"Apple Mach-O Linker Error Group"が出た時

Xcodeの新しいバージョンを入れた後、元のバージョンに戻した時に
"Apple Mach-O Linker Error Group"
エラーが出たので焦りました。

結局こちら
https://dev.classmethod.jp/smartphone/iphone/remove-xcode-derived-data/
の記事の通りにDerivedDataを削除したら、解決しました！

短いですが以上です
褒めロボットをつくろう！活動記録 - 概要

#取り組みの概要

大学の卒業研究の活動記録を記していきます。

具体的な活動内容は
**「カメラで顔を検出し、一定時間経過すると褒め、励ましてくれるロボット」**
の製作です。

思考の整理のためのアウトプット
を主な目的として記事を書いています。

勉強中の身ですので、内容に間違いなどあればご容赦ください。
加えて、ご指摘くださると幸いです。

#ロボットの機能とその実装方法


コンピュータ：Raspberry Pi 3 model B
カメラ：Logicool USB camera(研究室に転がっていたため型番不明)
顔検出ライブラリ：OpenCV
音声再生機器：Google Home Mini
主な使用言語：Python

#本日の活動
1.GitHubの導入
2.基本的な使い方（commit, push）の勉強

ということで、本記事は
**GitHub**
についてメインで書きそう。


##GitHubを使用する意義
バージョン管理。

####導入のきっかけ

GitやGitHubを知るまでは、
ファイル名_ver.→古いソースコードを残しつつ一部改変→ファイル名_Ver.+1…
と非常にスマートではない方法でバージョン管理していた。
（他ラボメンバーに笑われた）

GitHubは知っていたものの、漠然ととっつきにくさを感じ
導入には至っていなかった。

バージョン管理について他ラボメンバーに相談したところ
GitHubを勧められた。

**置いて行かれる！がんばって使わなきゃ！！**

##GitHubの使用目的


今まではRaspberry Pi にマウス、キーボード、モニタを接続し、
Raspberry Pi 上でコードを書いたり操作したりしていた。

（Qiita記事を特にに参考にさせていただいている。
ありがとうございます！）


もちろん
バージョン管理は大前提
として…

・グーグル先生にお世話になるとき（調べもの）
・コードを書くとき
は自分の使い慣れたラップトップで作業したい！

**GitHubなら、これを叶えることもできる！**

##私のGitHubの使用方法

###使用の流れ
[ラップトップ]でググりながらコードを書く。
　　　　　　　　↓
GitHub (リモートリポジトリ)にPush
**👆バージョン管理&ソースコードのバックアップが同時に行える**
　　　　　　　　↓
[Raspberry Pi :desktop:] でGitHub (リモートリポジトリ)にアクセス
　　　　　　　　↓
[ラップトップ]からPushしたコード ➡ [Raspberry Pi :desktop:] にClone
　　　　　　　　↓
[Raspberry Pi :desktop:]で動作検証

###できるようになったこと

・グーグル先生にお世話になるとき（調べもの）
・コードを書くとき
は自分の使い慣れた[ラップトップ]で作業し、

・動作検証をするとき
は[Raspberry Pi :desktop:]で作業
できるようになりました。

やったぁ～！

#今日はここまで！

Qiitaに登録してなかった頃の作業内容もまとめて記事にしたい。

それがこの先、使えるような予感がする。

Thank you for your reading:relaxed: