OmniAICreator/Qiita-1.07M huggingface dataset:
Gitツールまとめ（メモ書き。素人目線）

# 概要

Git～うんちゃら、ってキーワードは様々あるけど何が何なの？って自分メモ。
Git、Sourcetree、GitHub、、、ごちゃごちゃ、のまとめ。


## 「Git」と「Gitサービス」とそれ以外（クライアント）

「Git」とは「履歴管理システム」の一つ（特徴などは他の両記事を参照のこと）。

利用するには、「リモートリポジトリの置き場」をどこかに構築する必要がある。その「置き場」をあらかじめ作っておいて貸し出してくれるのが「Git（ホスティング）サービス」。

**Github**、**GitLab**、**Bitbucket**、**Assembla**、、、は「Gitサービス」の名称。これらサービスを利用して取得したリモートリポジトリへのPush/Pull（Commit/Checkout）は、**Gitクライアント**を利用する。


## Gitクライアント

Gitシステム／サービスを利用するためのクライアントツール。

### Git for Windows
  - **Git本家**のクライアント。
  - 「Git GUI」と「**Git Bash**（こっちがコマンドライン）」の提供がある。
    - Gitのコマンドラインと言ったら、通常はこれに含まれる**Git Bash**のことか？
  - 「Git for Windows Portabl」という「Notインストール型」の提供もある。
    - このPortable版でも、VSCodeとの連携はできると思われる（後述の参考サイトを参照）。

### Github Desktop
  - **GitHub**のクライアント。
  - もちろん、GitHub以外のGitサービスに対しても利用可能。
  - Ver.1系とVer.2系がある。
    - Ver.1系は、Gitコマンドライン（Git Bash？）同梱だったが、Ver.2系はコマンドラインは無くなったっぽい。
  - シンプルで使いやすい。（最低限のことは）直観的に使える。
  - 応用的な操作をしようとすると、GUIの範囲では出来ないことも多い？

### Sourcetree
  - **Bitbucket**のクライアント。
  - もちろん、Bitbucket以外のGitサービスに対しても利用可能。
  - GUIのクライアントとしては、**一番人気**？
  - 「GUIから出来ない操作は無い」が売り（だったと思う）。


# 参考サイト


- Git公式サイト
 - https://git-scm.com/
 - 「Dowdload＞Win」のページに行くと、自動でGit for WindowsのDLが始まる。
 - この↑DLを無視して、「Other Git for Windows downloads」でPortableを取得できる。

- Git for Windows の公開リポジトリ。現時点の最新「Git for Windows 2.17.1(2)」
 -  https://github.com/git-for-windows/git/releases/tag/v2.17.1.windows.2
 - Git for Windows Portable を取得するなら、こっちのGithubリポジトリから取得した方が容易（勝手にDLしないので）。

- PortableGit for Windows 64bit の インストール 
 - https://azriton.github.io/2017/08/21/PortableGit-for-Windows%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
- Visual Studio Code で git.exe が 見つからないと言われた場合の対処 
 - https://azriton.github.io/2017/12/18/Visual-Studio-Code%E3%81%A7git%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A8%E8%A8%80%E3%82%8F%E3%82%8C%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6/
- 自分用 Git For Windowsのインストール手順 
 - https://qiita.com/toshi-click/items/dcf3dd48fdc74c91b409
- 【初心者向け】Gitのインストール方法をわかり易く解説（画面付き） 
 - https://eng-entrance.com/git-install
- GitをWindowsで使うためのGit for Windowsのインストールと初期設定 
 - https://haniwaman.com/git-for-windows/
- Windows10でgit環境を作るまでのメモ 
 - https://qiita.com/neko_the_shadow/items/207f77b43c92e7f9c026
iOS ライセンスと配布方法

# ライセンスと配布方法
業務でEnterpriseでの配布があって、前にも詰まったので主にライセンスとそれぞれの配布についてまとめます。

## ライセンス
- Developer Program
- EnterPrise Program
- University Program

*Universityについては今回は書かない。必要になったら追記します
## 特徴・違い
基本的には以下の通り
Enterprise(adep)プログラムでも実機ビルドはできるのでEnterprise持っておくと便利そう
adep持っておけば課金周りが必要じゃない限りDeveloper(adp)プログラムはリリース時を除いて不要そう
### Developer Program
- 配布方法：appstore/ Ad Hoc
- Certificate(証明書)期限： 作成から1年
- プロビジョニングプロファイル有効期限： 作成から1年
- 年間費用：99米ドル


### EnterPrise Program
- 配布方法： Ad Hoc/ in-house(OTA可)
- Certificate(証明書)期限： <font color = red>作成から3年</font color>
- プロビジョニングプロファイル期限： 作成から1年
- 年間費用：299米ドル



![スクリーンショット 2018-06-12 16.09.25.png](https://qiita-image-store.s3.amazonaws.com/0/261386/ba8c95be-12dd-f7a1-b00f-95d218daa4f2.png)
参照:https://dev.classmethod.jp/smartphone/difference-between-developer-and-enterprise-program/

## Ad Hoc/ EnterPrise 違い
### Ad Hoc
- インストール台数： AppStoreを介さずに最大100台まで同一アプリ配布が可能
- デバイス登録：必要。デバイス追加の都度、UDID登録、プロビジョニングファイル更新、リビルド等の作業が必要



### EnterPrise
- インストール台数：AppStoreを介さずに無制限でアプリ配布が可能
- デバイス登録：<font color = red>不要。UDID管理等が一切不要</font color>
- OTA形式での配布可能：EnterPriseではOTA形式での配布が可能。
その際は「Include manifest for over-the-air installation」にチェックを入れる
＊ その後配布用webサーバーの情報を入力する必要あり。チェックを言れない場合はOTAでの配布でないためサーバー情報入力の必要なし。

<img width="747" alt="スクリーンショット 2018-06-13 11.46.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/261386/6b4e5f87-994e-f732-09ee-b9a5affcde71.png">


EnterPriseは企業向けに強力な機能を備えている一方、配布にあたって厳格な管理が求められているそうで
故意か否かに関わらず、利用規約に反して契約主体法人以外にアプリ配布があった場合はEnterPrise Programライセンス取り消し等のペナルティが課されることもあり得るようなので注意が必要です。

## 参考
https://dev.classmethod.jp/smartphone/difference-between-developer-and-enterprise-program/
https://qiita.com/isaac-otao/items/126bced83d9af86c7ce5
【PR】を出す前にきれいにしよう

# 主旨

広告記事ではありません。

プロジェクトの運営でgithubを使っている方も多いかなと思います。

修正内容をPR（プルリクエスト）をする際に、レビュアーが確認しやすいようにするために
変更内容を一まとめにして出したほうが、後々のレビューなどが楽になると感じました。

検索してみるとざくざく出てくるので、いろんな現場で課題になっているような気がします。

本稿では、git marge --squash で、PRする際に細かいコミットを一まとめにする例を扱います。

# 担当者レベルでは、細かくコミットした方が良い

失敗しやすいところでは、細かくセーブしてやり直せるようにしとけ。という考えは
個人レベルでは正しいと思います。

1. イニシャルコミット
2. 新しいビジネスロジックの追加
3. 固定値の変更が必要になった
4. 3のリバート（取り消し）
5. 仕様変更に伴い、ビューを改修
6. テストケースを追加
7. 6で見つかった問題の改修

極端な話、個人のローカル開発環境ではこのくらい細かくても良いかも。
個人の範囲では。レビューする側にとっては面倒くさいことこの上ないけど。

レビューを行い、問題なければマージする段階では一まとめコミットの方が良い。
ましてや個人レベルのリバートがふくまれているようなものは･･･。

# 作業手順

仮に
ブランチは、以下の名前とします

* stem:開発用ブランチの分岐元かつ、PRを出す対象（チーム内で共有）
* edit:実装作業を行うブランチ
* prrq:PR用にコミットをまとめるブランチ

同一リポジトリ内で作業するとします。


プライベートリポジトリに、最新のstem（分岐元）ブランチが存在すると仮定し

## ブランチを用意する

```bash:作業用ブランチと、PR用ブランチを作る
# stemブランチを選択する
$ git checkout stem

# 作業用ブランチを作成
$ git checkout edit

# PRに出す用のブランチを作成
$ git checkout prrq
```

注：状態をそろえるために作業用ブランチと同時に、PR用のブランチも作成してください！

## PR出す直前に、ブランチをまとめる

```bash:prrqに対しスクウォッシュ
# pr用ブランチに切り替えて
$ git checkout prrq

# merge --squash で、一まとめにする
$ git merge --squash edit

#一つのコミットとみなされていればOK
```

後はこの、 prrqブランチを使ってPRを出せばOK。

実務ではedit,prrqブランチは各メンバー用のリモートリポジトリにpushすることが多いと思いますが、
説明を簡単にするため同一リポジトリを使うと仮定しています。

# 余談

githubのPR機能には merge and squash いうものがあるので、それを使っても良い。
特に、開発用のブランチになら。
Rで日本の人口Treemapプロット

<h1>概要</h1>
Rでデータの可視化を試してみたんだけど、ggplot2のTreemapがうまくいかない人のための記事。使用するデータは2015年度の政府統計です。

(ゼミでコードをシェアしたものの、コードだけでは伝わらないのでは、という懸念を解消するための記事でもある。)

#解説
#ライブラリとデータのセット
```R
#set libraries
print(search())
library(gdata) #to read xls data
library(treemap) #to use treemap plot
library(dplyr) #to use great data modify function, like group_by

#load data

population <- read.xls("2015_population.xls")
#delete useless columns
population <- population[c("X.5","X.6","X.7")] #dataframe of 3 factors
c_name <- c("state","city","population") #to set columns name
names(population) <- c_name
print(names(population))

```
ライブラリはinstall.packages() を使ってインストールします。
読み込んだデータには X.数字 というカラムがあるので、必要なもののみ取り出して、populationに入れておきます。
今回は、都道府県、市町村、人口の順でデータを抜き取ったので、カラムの名前をstate, city, populationの順に変えておきます。
##文字から数値へ変換する
```R
#modify population column
population <- population[11:length(population[[2]]),] #delete useless values
population$population <- sapply(gsub(',','',population$population),function(x) x[1]) # to eliminate comma on population column
population$population <- as.numeric(population$population)#to change character d-type into numeric d-type

```
populationカラムには人口が入っていますが、データの型がcharacterであったので、このままでは平均の計算や、プロットしにくいので、numに変換します。
populationカラムのカンマによる数値の区切り (ex. 123,456)を削除し、as.numeric()を使うことで、数値に変換させます。

#Treemap

```R
#make treemap
states <- population$state #to reshape population dataframe
population_without_allState <- subset(population, !(city %in% states)) # delete rows where state and city have a same name
rainbow_color <- rainbow(47,s=0.4) #set colors
treemap(population_without_allState,
        index=c("state","city"),vSize = "population", title = "Distribution of the population in Japan",type = "index",fontsize.labels = c(12,8),
        fontcolor.labels = c("white","orange"),fontface.labels = c(2,1),bg.labels =c("transparent"),align.labels = list(c("center","center"),c("right","bottom")),
        overlap.labels = 0.5,inflate.labels = F, fontfamily.title ="HiraKakuPro-W3", fontfamily.labels = "HiraKakuPro-W3",
        fontfamily.legend = "HiraKakuPro-W3",palette = rainbow_color, border.lwds=c(1,1))
 
```
populationの中には、県毎の合計が含まれているので、これを削除して、population_without_allStateに入れておきます。
treemapの引数はそれぞれ;

```
index: treemapで使用するグループの区分
vSize: treemapの面積を何の指標で表すかの設定
bg.labels: 大きい方のグループの文字のバックグラウンドの色の設定。※これを設定しないとかっこ悪いグラフになる
fontface.labels: 文字の形式。1がノーマル, 2が太字,3がイタリック,4が太字イタリック
inflate.labels: Tに設定すると、面積に応じてラベルサイズが大きくなる
fontfamily: これを設定しないと、日本語が〼(マス、豆腐)表示になる
palette: treemapの色設定
border.lwds: グループの堺の太さの設定

```
<img width="471" alt="treemap.png" src="https://qiita-image-store.s3.amazonaws.com/0/193147/6d768f4d-2fb5-e377-7cff-333fed080512.png">


#まとめ
関東人おおい。県庁所在地つよい。
参考資料: https://www.r-graph-gallery.com/236-custom-your-treemap/
コードはgithubにあります。https://github.com/genkioffice/subsemi_analysis/blob/master/first/chap1_hw.R
ラズパイに初めて接続しようにもIPアドレスが分からないときどうするか

Raspberry Pi 3を購入して、初期セットアップを行おうとした際に一番最初に問題になるのは、「はて？どうやってログインするん？」ということではないでしょうか？　とりあえず、ラズパイとMacもしくはWindows PCを有線LANで直結してください。Macに有線LANのポートがない場合、USB-有線LANのアダプタを買ってきましょう。

Macの場合もWindowsの場合も、Raspbianのイメージを書き込んだSDカードの/boot領域にsshという空ファイルを作っておいてください。これがないとラズパイ起動時にsshサーバーが起動されません。Macの場合は以下のようにターミナルで操作します。Windowsの場合はエクスプロラーでよしなにお願いします。

```shell
cd /Volumes/boot
sudo touch ssh
```

#Macからの場合#
以下のコマンドでRaspberry Piにsshで接続します。Macを使っている場合、IPアドレスが分からなくても、以下のようにラズパイのデフォルトホスト名を指定して接続できます。Bonjour素敵！

```shell
ssh pi@raspberrypi.local
#デフォルトのパスワードは raspberry 
```

#Windowsからの場合#
Raspberry Piにログインするためには、以下のように現在のIPアドレスを知りputtyなどでログインする必要があります。

```shell
#DOS窓で以下のコマンドを実行。
arp –a
#現在接続されている機器のIPアドレスとMACアドレスが一覧表示されます。
#見慣れないIPアドレスの機器を見つける。

#Windows PCのIPアドレスを、該当IPアドレスのネットワーク体系に合わせます。
#例えば、見慣れないIPアドレスが169.254.148.167の場合169.254.148.1に設定します。

#以下のコマンドでRaspberry Piにsshで接続する
ssh pi@169.254.148.167
#デフォルトのパスワードは raspberry 
```

やはりエンジニアは、Macで開発した方が幸せになれる気がする今日この頃です^^;
Firebase ML Kit で不適切画像の検出を試した話

少し遅くなりましたが、Google I/O 2018 で発表された Firebase ML Kit が面白そうだったので触ってみました。今回は不適切な画像の検出を試してみました。結論から言うと、Firebase ML Kit ではまだ出来なかったのですが、せっかくなので備忘録として残しておきたいと思います。

# 概要

Firebase ML Kit は Google 機械学習の専門知識を Android や iOS アプリに簡単にもたらせる事ができます。現在は主に画像認識機能が提供されています。

# 機能

利用できるのは下記の機能です

- テキスト認識
- 顔検出
- バーコードスキャン
- ラベリング
- ランドマーク認識

これに加え「不適切画像検出」があると最高だったのですが、無いので「ラベリング」機能を使って試してみました。

# 方法

画像の認識の方法は、端末内のモデルを使う方法と Google のサーバ内のモデルを使う方法が用意されていて、それぞれの利点は下記の通りです。

- 端末モデル
    - 無料
    - 400種類のラベリング
    - Knowledge Graph entity ID support
- クラウドモデル
    - 最初の10000ユーザーまで無料
    - 10000種類以上のラベリング
    - Knowledge Graph entity ID support

`Knowledge Graph entity ID` は Google の [Google Knowledge Graph Search API](https://developers.google.com/knowledge-graph/) で使われている entity ID の事だと思います。

# 試してみた

今回は、無料という理由から、端末モデルを使う方法を試してみました。

[ゾンビ画像](https://pixabay.com/p-949916/?no_redirect)を用意してドキュメントに沿って実装してみると、下記のラベルが得られました。

```swift
let labelDetector = Vision.vision().labelDetector()
let image = #imageLiteral(resourceName: "zombie")
let visionImage = VisionImage(image: image)
labelDetector.detect(in: visionImage) { (labels, error) in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Error. You should also check the console for error messages.
        // ...
        return
    }

    // Labeled image
    // ...
    for label in labels {
        let labelText = label.label
        let entityId = label.entityID
        let confidence = label.confidence
        print(labelText)
        print(entityId)
        print(confidence)
    }
}
```


```
Skin
/m/06z04
0.942024
Hand
/m/0k65p
0.933021
Flesh
/m/02p16m6
0.748568
Beard
/m/015h_t
0.724764
Dog
/m/0bt9lr
0.558683
Event
/m/081pkj
0.53936
Jacket
/m/032b3c
0.531936
Sitting
/m/015c4z
0.525712
Fun
/m/0ds99lh
0.514916
Nail
/m/023j4r
0.502204
```

# 終わりに

`VisionLabelDetector` から取得したラベルから、不適切画像と判断するのは難しそうですが、Google Cloud Vision API を利用すると今回やりたかった事が実現出来るようです([チュートリアル](https://cloud.google.com/functions/docs/tutorials/imagemagick?hl=ja))。今後、ML Kit でも出来るようになることを期待しています！
GitリポジトリをCloneしたら何もしていないのに変更が…

# GitリポジトリをCloneしただけで変更ありになってしまう
## 犯人はお前だ！
```
git status
```
変更を確認すると、変更されたファイルと、Untrackedになるファイルがある模様。
該当のファイルを確認するとなるほど…そういうことか。

## 日本語のファイル名
日本語のファイル名があると、文字化けしてしまいUntrackedになってしまう。
CentOSでは問題なかったが…。ファイル名に使われている文字コードが変なのだろうか。
英数字に変更した。

```
hoge コピー.png
 ↓
hoge_copy.png
```

## 大文字、小文字
AbcとABCのような大文字と小文字の違いだけのファイルがいくつかあった。
これらのファイルは、どちらか一方のみしか存在できないため、変更されたという扱いになってしまう。
どちらかのファイルをリネームした。

```
Abc.png
ABC.png
 ↓
Abc.png
ABC_.png
```

## まとめ
今回の事件は、FTPサーバのファイルを一気にリポジトリへ移行した際に
過去に作成された膨大なファイルの中で上記のような問題が起きたようだ。

過去の遺産にはいろいろとカオスなことになっている。
DBには姓・名を別で登録しているのに、検索はフルーネーム部分一致で行いたいときの実装（一部）


Laravelで実装したもの。
サブクエリを使い、フルネーム項目をつくって対応。

### 検索ワードを配列につっこむ

```
        if ($conditions->user_name) {
            $whereInfo["user_name"] = $conditions->user_name;
        }
```

### 配列に入ってる検索ワードで検索

```
        if (isset($infoWhere["user_name"])) {
            $name = $infoWhere["user_name"];
            $ids = $this->getUserIdsByName($name);
            $query->whereIn("id", $ids);
            unset($infoWhere["user_name"]);
        }
```

#### SQLのサブクエリを使ってうまいこと検索する

```
    protected function getUserIdsByName($name)
    {
        $name = "%$name%";
        $sql = <<<SQL
select
  *
from (
  select
    *,
    last_name || first_name as full_name
  from m_user_info
) mui
where first_name LIKE ?
OR last_name LIKE ?
OR full_name LIKE ?
SQL;

        $result = DB::select($sql, [$name, $name, $name]);
        $rtn = [];
        foreach ($result as $row) {
            $rtn[] = $row->id;
        }
        return $rtn;
    }
```
Swift 4 排他処理

Swift4で排他制御が必要だった為、実装を行った。

## 方法
```swift:
let lockObj = NSObject()

objc_sync_enter(lockObj) // ロック開始

... 排他処理

objc_sync_exit(lockObj)  // ロック終了
```

## 検証用コード
```swift:UnitTest
func testSynchronized() {
    let ex = expectation(description: "test")
    let lockObj = NSObject()
    var count = 0
    func work(_ i: Int) {
        objc_sync_enter(lockObj)
        print("[START] \(i)")
        usleep(arc4random() % 1000)
        print("[END  ] \(i)")
        objc_sync_exit(lockObj)
    }
    DispatchQueue.global().async {
        for i in 1...5 {
            work(i)
        }
        count += 1
    }
    DispatchQueue.global().async {
        for i in 6...10 {
            work(i)
        }
        count += 1
    }
    DispatchQueue.global().async {
        while count != 2 { }
        ex.fulfill()
    }
    waitForExpectations(timeout: 60, handler: nil)
}
```

## 実行結果
<font color="Red">排他制御なし</font>

```console
[START] 1
[START] 6
[END  ] 1
[START] 2
[END  ] 6
[START] 7
[END  ] 2
[START] 3
[END  ] 7
[START] 8
[END  ] 3
[START] 4
[END  ] 8
[START] 9
[END  ] 4
[START] 5
[END  ] 9
[START] 10
[END  ] 5
[END  ] 10
```

<font color="Blue">排他制御あり</font>

```console
[START] 6
[END  ] 6
[START] 1
[END  ] 1
[START] 7
[END  ] 7
[START] 2
[END  ] 2
[START] 8
[END  ] 8
[START] 3
[END  ] 3
[START] 9
[END  ] 9
[START] 4
[END  ] 4
[START] 10
[END  ] 10
[START] 5
[END  ] 5
```
開始と終了が順番になっている事を確認。
【EC-CUBE】EC-CUBE 3.n α5を構築してみた。

2018/06/13現在、EC-CUBEの最新バージョンは3.0.16ですが
次期バージョン3.nのα版（α5）が公開されています。
https://www.ec-cube.net/news/detail.php?news_id=297

次期のEC-CUBEがどんなものかと構築してみましたので手順をまとめておきます。
※筆者の構築時点での内容となるため、最新の状況は変わっている可能性があります。

## 環境について
初めはXAMPPに突っ込んで適当に動くだろう、と
気軽に構築を始めると、**動きませんでした。**

どうやら開発中の為、一部コマンドやパス等がWindows環境に対応していないようです。

ならVagrantでやればいいじゃん、と構築を始めました。

## Vagrantの設定
先駆者がたくさんいらっしゃいますのでVagrantのインストール等については省略します。
https://qiita.com/ozawan/items/160728f7c6b10c73b97e
あたりを参考にインストールを行いました。
使用するOSはcenteOS7です。

ブラウザで確認するため、Vagrantfileの
`config.vm.network "private_network", ip: "192.168.33.10"`
のコメントアウトを外しておきます。
その後`vagrant up`でOSを立ち上げ順に下記の設定を行います。

- locale, timezoneの設定
- apacheのインストール
- mod_rewriteの有効化
- mysql(5.6を使用)のインストール
- php(7.1を使用)のインストール
- ファイヤーウォールの停止
- gitのインストール
- composerのインストール
- apache, mysqlのサービス登録


ここまで終わった段階でブラウザから
http://192.168.33.10
にアクセスし、apacheのスタートページが見えれば下準備が完了です。

## EC-CUBEのインストール
インストール直後のapacheのDocument_Rootは`/var/www/html`となるため、ここに直接構築してしまいます。
EC-CUBEのTOPをドメインルートにしたい場合はバーチャルホストを設定してください。

下記の順でコマンドを実行します。

```
cd /var/www/html
git clone -b experimental/sf https://github.com/EC-CUBE/ec-cube.git
cd ec-cube
composer install
bin/console eccube:install
```

Database Urlを聞かれるため、下記の形式で入力してください。
`mysql://<user>:<password>@<host>/<database name>`

その他の設定はひとまずエンター連打で進んで大丈夫です。

エラーなく終われば
http://192.168.33.10/ec-cube
へアクセスすればEC-CUBEのTOPが見えるはずです。
AzureのLinux VMをテンプレートで自動化しよう

<p>この投稿は東京渋谷ヒカリエ 8 階にある <a href="http://aka.ms/aajp" target="_blank">Azure Antenna</a> で実施された「AzureのLinux VMをテンプレートで自動化しよう」で使われた資料のご案内です。</p>

- <strong> ARM Template for Linux</strong>
https://www.slideshare.net/AkiraKoike1/azure-antenna-arm-template-for-linux


- <strong>Hands on ARM template</strong>
https://www.slideshare.net/AkiraKoike1/hands-on-arm-template

<p>:satellite:&nbsp;&nbsp;新しいイベントの情報は、Connpass の <a href="http://aka.ms/aajp" target="_blank">Azure Antenna サイト</a>よりご確認いただけます。</p>

<p>:arrow_backward:&nbsp;<a href="https://qiita.com/AzureAntenna/items/71f394c100fbfa8ddcc8">「Azure Antenna 実施イベント資料（カテゴリ別）」に戻る</a></p>
漢数字を算用数字に変換するコード

python3系です。

仕事上で、漢数字を算用数字に変換する必要が生じたので、作ってみました。
ネット上で、同目的のプログラムもありましたが、自分に理解しにくい部分もあったので、自作してみようという試みです。

「二十万三百五十四」
というように、「十」なども入れる正式な記述だけに対応しています。

現時点ではバリデーションを付けていないため、変な文字列を投入しても一応数字がかえってしまいます。
正規表現を用いてバリデーションするのが王道でしょうか。

非エンジニアでずっと独学のため、他人に指導してもらった経験がありません。

- 全体的な構成
- アルゴリズムの適否
- クラスの使い方
- 変数の使い方
- 変数名の付け方
- より適切orスマートな書き方

などなど、お気づきの点について遠慮なくご意見をいただけると嬉しいです。


#構成
二十八兆　一億　三百二十万　六千十八
という風に、４桁単位で区切ります。

そして、
**二十八**兆　**一**億　**三百二十**万　**六千十八**
という風に、兆・億・万につく部分を1000以下の数字として捉え、数値に変換します（→`_change_num_under1000`）。
これに兆・億・万を数値として掛け算します。

たとえば二十八兆の場合は、
28 ×　1000000000000
という風に計算します(→`_change_num_over1000`)。

最後に合計します。

# コード
```
import re

class Kansuuji():
    def __init__(self,text=""):
        #不正な文字列に対するバリデーションがあるとよい。
        self.kan=text


    def _convert_single_KAN(self,one):
        chars={
		"一":1,
        "二":2,
        "三":3,
        "四":4,
        "五":5,
        "六":6,
        "七":7,
        "八":8,
        "九":9,
        "十":10,
        "百":100,
        "千":1000
        }
        return chars.get(one,1)    #十三など、一のつかないものに対応するため、getで1を返させている。

    def _change_num_under1000(self,text):

        C=self._convert_single_KAN
        val=0

        kans=(    
            ("千",1000),
            ("百",100),
            ("十",10)
        )    #処理順を保つためディクショナリは回避。

        for kan,num in kans:
            pat="([二三四五六七八九])?{}(.*)".format(kan)
            matobj=re.match(pat,text)
            if matobj:
                val+=C(matobj.group(1))*num
                text=matobj.group(2)

        if text:    #一の位を処理
            val +=C(text)

        return val

    def _change_num_over1000(self,text):
        val=0
        C2=self._change_num_under1000

        kans=(
            ("垓",100000000000000000000),
            ("京",10000000000000000),
            ("兆",1000000000000),
            ("億",100000000),
            ("万",10000)
        )    #現時点は垓までだが、ここに追加していけば全ての文字に対応可能。

        for kan,num in kans:
            pat="([一二三四五六七八九十百千]+){}(.*)".format(kan)
            matobj=re.match(pat,text)
            if matobj:
                val+=C2(matobj.group(1))*num
                text=matobj.group(2)

        return text,val


    def get_arabic(self,text=None):
        text=text if text else self.kan    #インスタンス作成時に引数を与えなくても動くようにしてみた。（こういうのはよくない？？）
        text,val=self._change_num_over1000(text)
        return val+self._change_num_under1000(text)
```
依存のテストの書き方


「"試験A"から生成された"結果R"に対して"試験B"及び"試験C"を実施する」といった場合、テストを分けて書くことができる。
「データプロバイダ　テスト」とググれば、複数の郵便番号まとめてテストしたりする方法とかも出てくる。

## メリット

- 一つの `testHogehoge`が膨らみすぎるのを防げるほか、"試験A"がこけた場合に自動で"試験B/C"をスキップしてくれたりとっても便利


## 書き方

- `@depends` で依存するテストを指定する
- 依存される"試験A"の方ではreturnを記述する
	- そのreturnを `@depends` を記述した"試験B/C"の引数で受け取る
- `@depends` が依存を示すので、`@param` は書かなくてもOK。

```
<?php
namespace Tests\API;

use App\Model\Postalcode;
use Tests\TestCase;

class PostalcodeTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function test郵便番号から都道府県・市区町村を取得(){
        //ランダムな郵便番号をEloquentでとってきて、都道府県・市区町村を取得
        $postalcode = Postalcode::inRandomOrder()->first();
        $response = $this->get("/api/master/postalcode?postalCode=$postalcode->postal_code");
        $content = json_decode($response->baseResponse->content());
        $this->assertTrue(true);
        return [$postalcode, $content];
    }

    /**
     * @param $rtn
     * @depends test郵便番号から都道府県・市区町村を取得
     */
    public function test都道府県から絞った郵便番号との一致($rtn)
    {
        $postalcode = $rtn[0];
        $content = $rtn[1];
        //都道府県からとってきた郵便番号リストに存在するか
        $postalcodefindByPref = Postalcode::where('pref_name', $content->pref)->get(['postal_code']);
        $postalcodeList1 = [];
        foreach ($postalcodefindByPref as $line) {
            $postalcodeList1[] = $line["postal_code"];
        }
        $this->assertTrue(in_array($postalcode->postal_code, $postalcodeList1));
    }

    /**
     * @param $rtn
     * @depends test郵便番号から都道府県・市区町村を取得
     */
    public function test市区町村から絞った郵便番号との一致($rtn)
    {
        $postalcode = $rtn[0];
        $content = $rtn[1];
        //市区町村からとってきた郵便番号リストに存在するか
        $postalcodefindByCity = Postalcode::where('city_name', $content->city)->get(['postal_code']);
        $postalcodeList2 = [];
        foreach ($postalcodefindByCity as $line) {
            $postalcodeList2[] = $line["postal_code"];
        }
        $this->assertTrue(in_array($postalcode->postal_code, $postalcodeList2));
    }

}
```
React NativeでAndroidをリリースビルド

iOSばかりやっていて忘れてしまうのでメモ

# **リリースビルドのコマンド**

```bash
cd android
./gradlew assembleRelease
```

実際にビルドする際のコマンドは以上。
gradleのバージョンがどうのこうのというエラーが出ることが多い。（対策は別記事でまとめる予定）

# **コマンドを叩くまでの準備**
いろいろと準備が必要

## signing keyを作成

```bash
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
```

これを叩いていろいろと質問に答えると、カレントディレクトリで「release-key.keystore」というファイルが生成されるので、これを`android/app`フォルダへ移動。

## gradle.propertiesを編集
PC全体の設定とする場合は`~/.gradle/gradle.properties`、プロジェクトの設定とする場合は`android/gradle.properties`に以下を追加。
(先ほど答えたパスワードに*****を置き換える。)

```
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
```

## build.gradleを編集
`android/app/build.gradle`を以下のように編集。
...のところにはもともとのコードが入るので丸コピはできません。

```java
...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...
```

## 最初のコマンドを叩く
改めて、最初のコマンドを叩くとリリースビルドできます。
ネイティブといろいろlinkしている場合はここから戦いが始まりますので、一度休憩してHP全快の状態で臨みましょう。

```bash
cd android
./gradlew assembleRelease
```
「動的コンテンツ」の基本理解（1）

#「動的コンテンツ」とは 
Webサーバ上でプログラムが実行されるページ。
「静的コンテンツ」と対比される。
dynamic=「動的な」。

#「静的コンテンツ」とは
index.html などのように、要求のパスに指定されたhtmlなどのデータがそのまま応答のデータとして送信される方式のWebページのこと。
static =「静的な」

#自分の理解
Webサーバにデータを要求する際、データベースなどを使って都度情報を生成するのが動的コンテンツ。
誰が見ても同一の内容が表示されるのが静的コンテンツ。


##引用
上越教育大学「WWWの基本技術 - 静的コンテンツと動的コンテンツ」
http://juen-cs.dl.juen.ac.jp/html/www/005/
DOMElement拡張




- ロジック層から切り離されている（例: モデル層, ゲームのロジック層）
- 入れ子にしても問題ない（依存性注入）

クラス

- idは持たない
- できればコンポーネント化しておく（Angular4のように）
- 汎用的なHTML
- 汎用的なCSS
- 必要最低限の小さなメソッド群（Js）
    - render: 挿入先は引数からとる
    - など

これらをDOMElementに拡張し、どこからでも操作できるようにしておく

- Q. 設定値は与えてもまだ描画したくない時がある。new時にまだ描画しないほうがいいのでは？
- A. その設定値とは？それはロジック層に分類できるのでは？ "newしたら描画している"、"destructorが呼ばれたら消えている"、といった *完全に同期している* ことが望ましい。

note

- `$0.__proto__` を拡張すると全DOMが拡張される
- `$0` を拡張するとそのDOMのみが拡張される
- Q: あるコンポーネント（同じ種類のDOMら）のみが拡張されるにはどうしたらいいのだろう？
    - クラスの外にオブジェクトを定義して参照渡しするのかな？
        - →[やってみた](https://gist.github.com/candyrobot/d2fc0fa5d2009b836d38fbbc93ecd0d1)
[Swift] Simulatorでの表示に嵌った話

#はじめに
私がSwift学習中に嵌った内容を忘れない為に記載する。
この内容で半日4時間近く悩んで、いろんな事を検索していたなんて恥ずかしくて言えない。。。。
アプリ開発などでは殆ど関係ないと思います。
また同じ内容で嵌った人がいてすぐに解決できれば嬉しい。

#実施環境
- Xcode 9.4

#内容
**String型の変数をLabel.textに代入し、正常な文字列(想定した文字列)が格納されているがSimulatorでは正常に表示されない。**

今回は文字列をLabel.textに格納し、表示を行いたかったのだが、正常に表示されなかった。
正常に表示されている数字があるため、余計になぜ表示されないのか解らず嵌ってしまった。
理由はおそらく同じフォントでも表示するために必要なViewのサイズが異なるため
実際は画面に表示できていないだけで正しい文字列が格納されているため、**表示するためのViewサイズを変更してやれば正しく表示される**。

#実行結果

![表示不具合.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/60616/baf4b94a-3f1f-ba4c-d976-49275b554909.gif)


#参考
[【Mac】自分の画面を録画して、即gif動画化する方法](https://qiita.com/YosukeItabashi/items/5722395218e6e592fd39)
[Macでキャプチャして作ったGifアニメーションをQiita記事に貼り付ける方法](https://qiita.com/ryosukes/items/b5dd0fac1a059caffbf0)
Swift TableViewデータソース



TableViewデータソース

```
  
  enum xxSection: Int {
    case XXX = 0
  }
  
  var tableView: UITableView!
  
  func setupDataSource() {
    self.tableView.register(UINib(nibName: "", bundle: nil), forCellReuseIdentifier: "")
  }
  
  func numberOfSections(in tableView: UITableView) -> Int {
    return 0
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
  }
  
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 44
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "") as! ClassName
    return cell
  }
  
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
  }

```
[Kotlin]イニシャライザ、エクステンション


イニシャライザ

```
   class Ratioal(val numerator:Int, val dominator:Int = 1) {
        init {
            require(dominator != 0)
        }
    }
```
    
    

エクステンション

レシーバーとなるクラス(正確には型)の名前と関数名の間に「.」記号をおくだけです。


    fun String.countWords() : Int {
        this.split("""\s+""".toRegex()).size
    }
[Kotlin]インライン関数について


* インライン関数の正体

　Kotlinのラムダ式は無名クラスを生成します。つまりラムダ式を使えば使うほど無名クラスが増えていくということになります。簡単な処理のためだけにどんどん無名クラスを増やしてしまうのは避けたいところです。そこでインライン関数を使います。
　
　
* inline修飾子とは

inline修飾子は主に関数を引数に持つ関数に使われる修飾子です。
Fragmentのベストプラクティス


https://academy.realm.io/jp/posts/360andev-david-hope-fragments-activities-android-beginner/


- アクティビティひとつに対して、使用するフラグメントは最大3つにしましょう。これにより、トランザクションの管理が楽になります（それは後々悩まされる頭痛を軽減してくれるでしょう）。

タブレイアウトのフラグメントは、最大5つにするのが良いでしょう。それ以上になると、ユーザーインターフェイスが乱雑になります。
[Kotlin]開発Tips


- Data Class
    - dataアノテーションを使ってシンプルにかける

```
data class User(val id:String, val name:String)
```


importであるパッケージにあるすべてのクラスを使えるようにする

```
import android.app.*;
```

##Adapter

文字列や画像などの複数データと、(AdapterViewから派生した)ListView等との中間に存在し、両者の橋渡しをする役割を担います。、


###データクラス

クラス宣言にdataをつけるとAnyクラスが持つメソッドの適切な実装が行われる。 これにより、toStringでデータを表示したり、equalsでの中身が同じかどうかの比較、 copyでJavaのcloneと同じように、ディープコピーが可能。


###DP->SP変換
val progressBaseViewDpWidht:Int = header_view.progress_base_view.width
//        progressBaseViewWidht = (progressBaseViewDpWidht / applicationContext.resources.displayMetrics.density).toInt()


###View動的追加

            var view = View(context)
            view.setBackgroundColor(Color.GRAY)
            val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 30)
            lp.weight = 1.0f
            lp.leftMargin = margin
            lp.rightMargin = margin
Rで同じIDごとに連番をふる方法

Rで、同じidに連番をふっていく方法（idが変わったら番号を1から振り直す方法）がわからず困っています。。

id no
1  1
1  2
1  3
1  4
1  5
1  6
2  1
2  2
2  3
2  4
2  5
2  6
2  7

エクセルでのやり方はわかるのですが、データが膨大なため、途中でエクセルがクラッシュしてしまい、Rで挑戦しております。

何卒よろしくお願い申し上げます。
matter.jsで特定のbodyに対してマウスイベントを設定する

なかなか見つからなかったので取り急ぎメモ。

# やりたいこと
* Matter.MouseConstraintを使って簡単にマウスイベント実装したいけど、デフォルトですべてのbodyがドラッグで動かせるようになるので不便

# 対処１：動かしたくないbodyのoptionにstaticを付ける
* 完全に動かなくなるのでドラッグだけさせないとかできない

# 対処２：mouseConstraitと動かしたいbodyに同じcollisionFilterを設定する

``` javascript

// モジュールへのエイリアス
    var MouseConstraint = Matter.MouseConstraint;

…

// マウスイベントを有効にしたいbodyにはfilterを設定
    var targetOptions= {
        render: { fillStyle:  "rgba(0, 0, 0, 1)" },
        collisionFilter: { // 一意のフィルタ
            category: 0x0001,
            mask: 0xFFFFCC,
            group: 1
        }
    };
    var Target = Bodies.polygon(170, 350, 20, 200, targetOptions);

// マウスイベント不要なbodyはfilterを設定しない/別に設定
    var otherOptions= {
        render: { fillStyle:  "rgba(0, 0, 0, 1)" }
    };
    var Other= Bodies.polygon(170, 450, 20, 200, otherOptions);

// mouseConstraintの設定
    var mousedrag = MouseConstraint.create(engine, {
        element: canvas.childNodes[0], //マウス操作を感知する要素を指定
        constraint: {
            render: {
                strokeStyle: "rgba(0, 0, 0, 0)" //マウス操作の表示を隠す
            },
        },
        collisionFilter: { // 一意のフィルタ
            category: 0x0001,
            mask: 0xFFFFCC,
            group: 1
        }
    });

    World.add(engine.world, mousedrag);
    World.add(engine.world, [Target , Other]);

…


```

♯ 参考リンク
https://github.com/liabru/matter-js/issues/48
【サルが書く】直前のcommit メッセージを最速で修正するため見た方が良い記事


```bash
git commit --amend -m "正しいコミットメッセージを入れる"
```

```bash
#　変更されているか確認
git log
```

コーナーで差をつけろ！

これで一発で修正できる！
バレる前に修正しよう！
タスクランナー note


## **オールインワン** ES6 x CommonJS -> concat x minify(map付き)✨

例: 

```javascript
var gulp = require("gulp");
var browserify = require("browserify");
var source = require("vinyl-source-stream");
var buffer = require("vinyl-buffer");
var uglify = require("gulp-uglify");
var sourcemaps = require("gulp-sourcemaps");
var minimist = require('minimist'); // 引数を使うための

var SITE_ID = minimist(process.argv.slice(2)).f; // 第一引数 `gulp [taskName] -f param1Value`

gulp.task("compile", function() {
  browserify({
    entries: `./src/${SITE_ID}.js`  // ビルド対象のファイル
    // debug: true  // trueにすると、//# sourceMappingURL=data:application/json;charset:utf-8;base64,～でsourcemapが出力される
  })
  .transform("babelify", {presets: ["env", "react"]})
  .bundle()
  .pipe(source("out.min.js"))  // ビルド後のファイル名
  .pipe(buffer())
  .pipe(sourcemaps.init({loadMaps: true}))  // sourcemap作成
  .pipe(uglify())  // minify
  .pipe(sourcemaps.write("./"))
  .pipe(gulp.dest("./"));  // 生成先の指定
});

gulp.task("default", ["compile"]);
```

参考: http://d.hatena.ne.jp/Kazuhira/20150921/1442822827

### 本当はこうしたかった:

- 直接コマンドで叩けばuglifyでもgoogle-closure-compilerでも上手く動作する 
- が、nodeでファイル内に書かれた`require('child_process').exec` から実行すると、どう頑張っても、1KBのファイルが出力される。（怒）
- 結論、素直にgulpを使った。

## ES6

ES6のクラスはプロパティをメソッド外で定義できません（JavaやC++みたいに）。
それを出来るようにしてくれるやつ

- https://marunouchi-tech.i-studio.co.jp/2665/


ビルドシステム（タスクランナー？）

* Rollup
* Webpack
* Browserify


requireを解決したり、es6->es5にしてくれるやつ

* buble
* babel
* rollup

パッケージインストーラー

* yarn
* gulp
* npm

## yarn

* `$ yarn build` は `$ npm run build` と同じ。
Gorm+MySQLでUNIQUE制約と論理削除を両立させる方法

# UNIQUE制約
DBの特定の列に重複した値が入力されないように制限を掛けることができます。
複数列に1つのUNIQUE制約を掛けることも可能です。(複合UNIQUE制約)

# 論理削除 (Soft Delete)
DB上の値を実際には削除せずに、`deleted_at` などの「削除フラグ」を立てることで擬似的に削除を実現することを**論理削除**といいます。

# UNIQUE制約と論理削除の両立
例えば、`username` カラムに対してUNIQUE制約を掛ける場合、論理削除と併用して使うと、ユーザを削除してもDB上では実際に削除されず残っているので、制約に引っかかってしまい、新しく同じ`username`のユーザを作成できなくなってしまいます。

`deleted_at`と`username`に複合UNIQUE制約を掛けても、`deleted_at`が `NULL` の場合、NULL ≠ NULL と見なされ、制約に引っかからず思ったように動いてくれません。

この場合は、`deleted_at` などの削除フラグにdefault値を入れ、`username` と `deleted_at` に複合UNIQUE制約を掛けることで解決することができます。

# **Gorm**でのUNIQUE制約と論理削除の両立
Gormは、`Find` や `Scan` をする際に、自動で `WHERE deleted_at IS NULL` を追加してくれるため、論理削除をあまり意識しなくとも利用することができます。
しかし、UNIQUE制約と論理削除を両立させたい場合、`WHERE deleted_at = default value`の条件で値を取得してほしいので、これはあまり嬉しくありません。
DBにUNIQUE制約を書けずに、コード側で対処することもできますが、どこかで破綻しそうで好ましくない気がします。
論理削除をやめて物理削除にすれば解決しますが、削除されたデータを追いたい場合もあるので、これも今回の場合は好ましくありません。

# Gormのカスタマイズ
GormでUNIQUE制約と論理削除の両立は厳しいのか...? と思いましたが、カスタマイズするための機能が存在しました。([Write Plugins]("http://doc.gorm.io/development.html#write-plugins"))

`deleted_at` に default値として、`'1970-01-01 00:00:01'` を与え、
`Find` や `Scan`が実行されたときに走るCallbackの前に、`WHERE deleted_at = '1970-01-01 00:00:01'` などの独自のロジックを追加して、通常の`WHERE deleted_at IS NULL` が走らないようにすれば、UNIQUE制約と論理削除を両立させられそうです。

以下、それを実装したものです。（一部省略しています）

```go

package main

import (
    "fmt"
    "time"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
)

type User struct {
  Username  string    `json:"username"   gorm:"unique_index:unique_username"`
  DeletedAt time.Time `json:"deleted_at" gorm:"default:'1970-01-01 00:00:01';unique_index:unique_username"`
}

var DB *gorm.DB

func main() {
  DB = newDB
  DB.Callback().Query().Before("gorm:query").Register("new_before_query_callback", newBeforeQueryFunction)
}

func newBeforeQueryFunction(scope *gorm.Scope) {
	var (
		quotedTableName                   = scope.QuotedTableName()
		deletedAtField, hasDeletedAtField = scope.FieldByName("DeletedAt")
		defaultTimeStamp                  = "1970-01-01 00:00:01"
	)

	if !scope.Search.Unscoped && hasDeletedAtField {
		scope.Search.Unscoped = true
		sql := fmt.Sprintf("%v.%v = '%v'", quotedTableName, scope.Quote(deletedAtField.DBName), defaultTimeStamp)
		scope.Search.Where(sql)
	}
}

```
後は、通常どおり使うことができます。

# 最後に
間違っている箇所や、もっといい方法などがあれば是非教えてください。
PyTest - Python Test Framework

#<b>INTRODUCTION</b>
Previous Article We have discuss about IOS Testing Framework which we are using the IOS build in Unit test and Third Party Testing Library which is <b>Quick&Numble</b>. But this time we are going to discuss about Python Test Framework which is <b>Pytest </b>. 


#<b>GETTING STARTED</b>
##<b>1. Installation</b>
you can install pytest by using pip

```terminal
pip install pytest
```
##<b>2. Create Test File</b>
so with pytest , it is expect <b>test</b> to be located in the file which its name start with <b>test_</b> or end with <b>_test.py</b>
Ok, Now let create sample .py file. let's name it "test _SampleApp.py"

```python
# our function
def capital_case(x):
    return x.capitalize()

# our test function
def test_capital_case():
    assert capital_case('semaphore') == 'Semaphore'
```
Ok, Now I will explain example above. As you can see in above example we have two functions.
1. <b>capital_case</b> : This function take string as parameter and it will return those string into uppercase letter.
2. <b>test_capital_Case</b> : This function is a test function, as you can see the prefix is test and the prefix must be test because it is a rule of pytest , all test function must start by <b>test_</b>. We use this function is test our capital_case function by using <b>assert statement</b>.

##<b>3. Run Test</b>
to run the test, you can just type 

```terminal
pytest
```
<b></b>
AngularJS 全watch数カウント

2000以下にする。

抜粋　https://medium.com/@kentcdodds/counting-angularjs-watchers-11c5134dc2ef

       //Call
       WatchCountService.getWatchers().length
 
       //Service
       main.service('WatchCountService', [
        function () {
            this.getWatchers = function (root) {
                root = angular.element(root || document.documentElement);
                var watcherCount = 0;

                function getElemWatchers(element) {
                    var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
                    var scopeWatchers = getWatchersFromScope(element.data().$scope);
                    var watchers = scopeWatchers.concat(isolateWatchers);
                    angular.forEach(element.children(), function (childElement) {
                        watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
                    });
                    return watchers;
                }

                function getWatchersFromScope(scope) {
                    if (scope) {
                        return scope.$$watchers || [];
                    } else {
                        return [];
                    }
                }

                return getElemWatchers(root);
            }
        }]);
メモ：Mac OSでMemory Analyzerが動かない件

### 何故かJava 6を使おうとする問題
/Applications/mat.app/Contents/Info.plist の下の方にそれっぽい指定があるので、それを書き換える。

```xml
<key>Eclipse</key>
<array>
	<string>-vm</string><string>/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java</string>
	<!-- to use a specific Java version (instead of the platform's default) uncomment one of the following options,
			or add a VM found via $/usr/libexec/java_home -V
		<string>-vm</string><string>/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Commands/java</string>
		<string>-vm</string><string>/Library/Java/JavaVirtualMachines/1.8.0.jdk/Contents/Home/bin/java</string>
	-->
	<string>-keyring</string>
	<string>~/.eclipse_keyring</string>
	<string>-showlocation</string>
</array>
```

### GUIが操作を受け付けない問題
https://www.eclipse.org/forums/index.php/t/1090889/ によるとSWTのバージョンの問題らしい。

https://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops4/R-4.7.1a-201710090410/swt-4.7.1a-cocoa-macosx-x86_64.zip からSWTをダウンロードして置き換えれば良いとのこと。

```sh
mv swt.jar /XXXXXXXXXXXXXXXX/mat.app/Contents/Eclipse/plugins/org.eclipse.swt.cocoa.macosx.XXXXXXXXXXXXXXXX.jar
```
xUnitのテストを環境によってスキップする

xUnitでは``[Fact(Skip="ここはスキップするよ"]``のように書けばテストを一時的にスキップできる。
しかし、例えば、ローカルの環境ではテストを実行したいけど、ビルドサーバーではやりたくないとか、OSなどの要因によってあるメソッドが未実装の時には失敗しては欲しくない時もある。

そんなときには、[SkippableFact](https://github.com/AArnott/Xunit.SkippableFact)を使うとよい。
NuGetでインストールして、次のように書くだけで、指定したExceptionが発生したときにはスキップ扱いにしてくれる。

```
[SkippableFact(typeof(NotImplementedException))]
public void DoTest()
{
    // do some tests
}

```

複数ある場合はExceptionクラスを複数書けばよい。

```
[SkippableFact(typeof(NotImplementedException), typeof(NotSupportedException))]
public void DoTest()
{
    // do some tests
}

```

``Theory``の場合は同じように``SkippableTheory``を使うだけ。

```
[SkippableTheory(typeof(NotImplementedException), typeof(NotSupportedException))]
public void DoTest()
{
    // do some tests
}
```

ただ、残念なことに``DisplayName``などと混在できないのが難点。。。まぁ、いっか。
スタートアップで学んだ、最短のエラー解決フロー

## TL;DR
* なにか問題が発生したとき、人によって解決フローはことなる
* 人によっては、非効率なフローを回していることがある。
* `最短の解決フロー`を知っておくことで、解決にかかる時間を最小化する

## はじめに
チームにいる **問題の解決が早い人**。

その人に聞いたり、観察すること数ヶ月…

**早い解決フローみたいなものが見えてきました**。

それを実践してみると、

`よくわからんバグ踏んで調べてたら、数時間を無駄にしてしまった…`

みたいなことが、以前より少なくなったのでまとめました。

※`問題 = プログラミング時のエラー`として書いてます

## ①人に聞く
`チームメンバーに迷惑かかるやん！リソース奪い良くない！`なんて思っていたのですが、
知っている人に聞くほうが、チーム全体でみるとコストが低いことが多いです。

**自分が何時間も頭を悩ますより、チーム全体の1時間で解決するほうがベター**です。

おすすめ：とりあえずSlack。

<img width="926" alt="times_tsubuku___Ulysses_Slack.png" src="https://qiita-image-store.s3.amazonaws.com/0/99874/66a678a5-d7d8-e913-fe3d-aaecfb5d7e6a.png">

## ②エラー内容を確認する
* エラーメッセージをよく読む
  * わからない英語だったら調べる。次に出会った時に調べなくて良くなるので。
* どこでエラーが起きているのかを明確にする

このあたりは、大体皆さん実践されていると思いますので割愛。

## ③そのエラーを本当に解決する必要があるのか考える
ここが個人的には目から鱗でした。

`よっしゃ。エラー内容もわかったしらべるぞ〜！`

と、エラーを前にすると解決したくなるのがエンジニアですが…

**このエラー、そもそも解決する必要あったっけ…？**

例えば、

* なんか処理に時間かかってる。データが大きくなったらやばいかもしれないから、早めに原因を突き止めよう
  * 実際に大きなテストデータでテストしてみる
  * 実用的な範囲内で速度が出れば、そもそも問題ではないのでは？
* エレガントに書こうとしたら、なんかハマった…。
  * 少し冗長でも、まずは正しく動くものを正にしましょう。
  * テストを書いておいて、リファクタできるようにしておけばOK

## ④ドキュメントを読む
解決する必要がある場合、ドキュメントを参照して、正しい使い方をしているかを確認しましょう。
もしかすると、間違った使い方や開発者が意図していない使い方をしている可能性があります。

## ⑤Githubレポジトリのissueに上がっていないかを探す
ドキュメントをよく読み、正しく使用していても、なぜかエラーが出てしまう場合があります。
それ、もしかすると既知のissueかも…

そんなときはレポジトリのissueで検索をかけましょう。

例えば、以下のようにライブラリの実装上むずかしいことがあったりもします。

<img width="775" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f39393837342f34623838316166662d373136322d343934612d626166622d6166366335616236653066652e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/99874/acc7c2d8-e751-ae63-873e-d6be47e45b2a.png">


参考: ［GoでHTMLをPDFに出力する］（https://qiita.com/kurkuru/items/65614fd3524fefccf576#four-%E8%A4%87%E6%95%B0%E3%81%AEhtml%E6%96%87%E5%AD%97%E5%88%97%E3%81%AE%E5%A0%B4%E5%90%88）

## ⑥ソースを読む
それでも原因がわからなければ、ソースを読みましょう。

ソースを読むことで、**最も正しい情報が得られます**。

ライブラリ自体への理解も深まるし、実装面で参考になることも多いです。

## 適宜：Qiita / Stack Overflow でさっと解決
狭い範囲での問題だと、エラー内容でとりあえずググりましょう。
Qiita, Stack Overflow を見た方が早いことがままあります。
これらは、順番的にはどこに入れても良さそうなので、適宜としました。

## 終わりに
いかがでしたでしょうか。
解決フローがチーム全体に共有されていると、
「お、フローはどこまでやったん？」みたいな話もすっとできてよさそうです。

また、[@y_tsubuku](https://twitter.com/y_tsubuku)が開発する[yaritori - メール共有システム](https://yaritori.jp/)も、良ければご覧ください :tada:
メモ：ShoeBoxでスプライトシーツを作る

openFrameworksでスプライトシートを使ってアニメーションしたのでそのメモ

##プラットフォームとAddonとツール
- openFrameworks
- [ofxTexturePacker](https://github.com/danoli3/ofxTexturePacker) (アニメーションの再生に使用
- [ShoeBox](http://renderhjs.net/shoebox/) (スプライトシートの作成ツール

##TexturePackerでいいじゃないか
その通りですが無償でやりたかった
できればTexturePackerほしいですが・・・

##出力してみる
ShoeBoxからスプライトシートを出力してみると.pngと.xmlが出力される
当然だけどofxTexturePackerはTexturePackerというツールのAddonなのでXMLは読み込めない

##XMLのフォーマットが違う
ShoeBoxが出力するxmlのフォーマットを変更することにした

ShoeBoxはSprite Sheet SettingのAdvancedでxmlの出力フォーマットをいじれるようです
以下のような変更をした

File Format Loop
```\t<sprite n="@id" x="@x" y="@y" w="@w" h="@h" pX="0.0" pY="0.0"/>\n```
File Format Outer
```<TextureAtlas imagePath="@TexName" width="@W" height="@H">\n@loop</TextureAtlas>```

これで最低限だけどスプライトシートが読み込めるようになった

![2018-06-13_095820.png](https://qiita-image-store.s3.amazonaws.com/0/121137/d80f5cbf-cd04-ac52-e1a6-9913f29ad5e4.png)
仕事ではじめる人工知能（AI）

会社の偉い人（例：社長、事業部長）から

- AIを使って何かできないのかという依頼や相談
- （挙句の果てには、）会社の宣伝のためにAIを使って何かしろという業務命令

を受けた方は、エンジニアや研究者の中にいらっしゃると思います。
そのような状況で、参考にして頂ければと思う注意点を幾つか纏めました。

## AIの定義を明確化する
世の中には `AI = ディープラーニング（深層学習）` と思い込んでいる人達がいます。
例えば、AIを作る側の人が説明のしやすさという観点から決定木などのルールベースのアルゴリズムを選択しても、会社の偉い人から「そんなものはAIとは言わない」「ディープラーニングを使わないと会社の宣伝にならない」と言われる事があります。

そのような事態を避けるために、まずは関係者でAIの定義を明確化しましょう。
AIの定義や歴史については、東大の松尾先生の『[人工知能は人間を超えるか ディープラーニングの先にあるもの](https://www.amazon.co.jp/dp/4040800206/)』という本に詳しく書かれています。

## AI以外の手段がないのか検討する
AIを使う事はあくまでも手段であって目的ではありません。
そのため、AI以外の手段がないのか検討し、もしAI以外の手段があればそちらを使いましょう。
その方が開発コストだけでなく運用コストも安く済む場合が多いです。

例えば、スーパーのレジ打ちの場合を考えてみましょう。
AI、この場合は画像認識を使って買い物カゴの中に入っている商品を認識しレジ打ちを自動化しようと言う人がいますが、商品に事前に電子チップを埋め込んでおき、レジでその電子チップを読み込めば買い物カゴの中の商品は認識できます。さらに、電子チップであれば、画像認識のように認識誤りが発生する事はほぼあり得ません。
もちろん電子チップを埋め込むコストを考慮しなければなりませんが、このようにAIを使わずに単純なシステム化だけでも十分に解決できる事例は数多く存在します。

## AIの費用対効果を意識する
AIの機能を自社で開発するにしろ外部ベンダーに依頼して開発するにしろ、多くの費用と時間が掛かります。
例えば、AIを使ったレコメンドエンジンを開発する場合、

- ビジネス要件定義
- アルゴリズム開発
    - データ取得
    - データ前処理
    - 各種アルゴリズムの比較検討
- 既存システムへの組み込み

といったタスクが少なくとも必要です。
これらを全て一人で対応することはまず無理で、複数のプロジェクトメンバーが数ヶ月掛けて作ることが多いです。
1人月100万円で見積もっても、最低でも数百万円の費用になります。
レコメンドエンジンを開発することで売上げがこれ以上に伸びるのであれば問題ありませんが、売上げアップがあまり見込めない場合はレコメンドエンジンの開発そのものを諦める方がビジネス上は正しい判断となります。

また、最近ではBRP(Business Process Re-engineering)の中でAIを使って業務改善ができないか？という事例も多く見聞します。
その場合、AIによる業務改善の恩恵を受ける人が数万人、もしくは数千人であれば効果が費用を上回る可能性が高いですが、恩恵を受ける人が数十人であれば効果が費用を上回る可能性は低くなります。
レコメンドエンジンの開発と同様、何もしない方がビジネス上は正しい判断となる事があります。

## AIが誤ることを許容するサービス設計にする
AIは間違うことが必ずあります。100％の精度はあり得ません。
例えば、画像認識では丸まった猫をクッションと判断したり、翻訳でも正反対の意味の文章に訳してしまう事があります。

そのため、最初からAIが誤ることを許容するサービス設計にすることが重要です。
よく採り入れられる対応策の一つとして、完全自動にはせずに半自動にするという方法があります。
例えば、HRTechでの新卒採用やキャリア採用におけるAIを使った書類審査では、

- AIが優秀と思われる候補者を抽出し、抽出した候補者だけを人がチェックする
    - 本当に優秀な人を取りこぼさないように、絞り込み過ぎないことが大切
    - AIは全然ダメな候補者を弾くのに使うイメージ
- AIが各候補者をスコア付けし、人がチェックする際の参考情報とする
    - 100点満点で付けるのではなく、三段階評価ぐらいで十分

という方法がよく採られます。
前者は人がチェックするレジュメの数を減らすことでコスト削減、後者は人がチェックするレジュメの数は減りませんが候補者一人当たりに掛かる審査時間の軽減に加えて審査結果の公平性の担保に寄与します。
文字コードの基本

## 1. はじめに
文字コードについて基本的なことをまとめます。

## 2. 概要
英数字、記号、ひらがな、漢字…等の文字は、コンピュータはそのまま理解することができないため、コンピュータが理解できる数値(16進数)に置き換えたものを**文字コード**という。
**文字集合**と**符号化方式**という2つの概念が存在し、これらが組み合わさってコンピュータの文字を表している。

## 3. 文字集合
「文字」と「文字に割り当てた番号」の対応表のこと。
 Unicode、JIS(ISO-2022-JP)等がある。

## 4. 符号化方式
文字集合で定義されている一つ一つの文字を、どのように符号化するかという方式(エンコーディング)。
例えば、Unicodeという一つの文字集合に対して、異なる文字符号化方式(UTF-8、UTF-16)が存在する。

### 4-1. ASCIIコード
 * 最も基礎となる文字コード。
 * 「数字」「アルファベット」「記号」は1バイトで表す。

ASCIIコード表 (10進数ASCIIコード、16進数ASCIIコード、ASCII文字)

|10進|16進|文字|    |10進|16進|文字|   |10進|16進|文字|   |10進|16進|文字|
|----|----|----|----|----|----|----|---|----|----|----|---|----|----|----|
| 0|00|NULL||32|20|SP||64|40|@|| 96|60|`  |
| 1|01|SOH ||33|21|! ||65|41|A|| 97|61|a  |
| 2|02|STX ||34|22|" ||66|42|B|| 98|62|b  |
| 3|03|ETX ||35|23|# ||67|43|C|| 99|63|c  |
| 4|04|EOT ||36|24|$ ||68|44|D||100|64|d  |
| 5|05|ENQ ||37|25|% ||69|45|E||101|65|e  |
| 6|06|ACK ||38|26|& ||70|46|F||102|66|f  |
| 7|07|BEL ||39|27|' ||71|47|G||103|67|g  |
| 8|08|BS  ||40|28|( ||72|48|H||104|68|h  |
| 9|09|HT  ||41|29|) ||73|49|I||105|69|i  |
|10|0A|LF  ||42|2A|* ||74|4A|J||106|6A|j  |
|11|0B|VT  ||43|2B|+ ||75|4B|K||107|6B|k  |
|12|0C|FF  ||44|2C|, ||76|4C|L||108|6C|l  |
|13|0D|CR  ||45|2D|- ||77|4D|M||109|6D|m  |
|14|0E|SO  ||46|2E|. ||78|4E|N||110|6E|n  |
|15|0F|SI  ||47|2F|/ ||79|4F|O||111|6F|o  |
|16|10|DLE ||48|30|0 ||80|50|P||112|70|p  |
|17|11|DC1 ||49|31|1 ||81|51|Q||113|71|q  |
|18|12|DC2 ||50|32|2 ||82|52|R||114|72|r  |
|19|13|DC3 ||51|33|3 ||83|53|S||115|73|s  |
|20|14|DC4 ||52|34|4 ||84|54|T||116|74|t  |
|21|15|NAK ||53|35|5 ||85|55|U||117|75|u  |
|22|16|SYN ||54|36|6 ||86|56|V||118|76|v  |
|23|17|ETB ||55|37|7 ||87|57|W||119|77|w  |
|24|18|CAN ||56|38|8 ||88|58|X||120|78|x  |
|25|19|EM  ||57|39|9 ||89|59|Y||121|79|y  |
|26|1A|SUB ||58|3A|: ||90|5A|Z||122|7A|z  |
|27|1B|ESC ||59|3B|; ||91|5B|[||123|7B|{  |
|28|1C|FS  ||60|3C|< ||92|5C|\||124|7C||  |
|29|1D|GS  ||61|3D|= ||93|5D|]||125|7D|}  |
|30|1E|RS  ||62|3E|> ||94|5E|^||126|7E|~  |
|31|1F|US  ||63|3F|? ||95|5F|_||127|7F|DEL|


### 4-2. Shift_JIS
 * ASCIIコードの文字に加え、日本語の文字を加えたもの。
 * 半角カタカナは1バイトで表現し、それ以外の全角文字は、2バイトで表現する。
 * Windows、Macでも採用しており、PC上のファイルで広く用いられている。

### 4-3. UTF-8
 * ASCIIコードの文字に加え、世界中の文字を加えたもの。
 * ASCIIコード以外の文字は、2～6バイトで表現され、日本語の文字は、基本的に3バイトで表現する。
 * ASCIIコードとの互換性が良いため、パソコンで扱いやすく、世界中の多くのソフトウェアは、UTF-8に対応しています。

### 4-4. UTF-16
 * ASCIIコードは使わず、基本的な世界中の文字(基本多言語)の全てを2バイトで表現し、残りのマイナーな文字を4バイトで表現した文字コード。
 * 半角アルファベット、半角数字、日本語のほとんどが2バイトで表現されます。
 * 多くの文字を対応しており、様々な場面で使われているが、UTF-8より対応するシフトウェアは少ない。

### 4-5. EUC
 * Extended UNIX Codeの略。
 * UNIX環境でよく使われるコード体系。
 * EUCには日本語EUC、中国語EUC、韓国語EUCなどがある。

## 5. おわりに
他にも追加情報等ありましたら随時更新致します。
開発中のRailsプロジェクトを新しい環境で再開するときのメモ

お仕事ではなく趣味レベルで個人でやっている中での手順・注意点

* リポジトリのクローン 
* Rubyのバージョン合わせ
  * rbenv local
* Gemのインストール
  * bundle install --path vendor/bundle (--without production)
* development環境のDB準備
  * rails db:create
  * rails db:migrate
* **バージョン管理から除外されているが、必要になるファイルの、作成ないしコピー**
  * Encrypted Credentialsをdevelopmentでも有効にしているのに、master.keyのことを忘れており、railsコマンドが動かなくなりパニクった
* .git/configを編集してremoteのURLを書き換え、sshを有効にする
  * デフォルトがhttpになっていて、pushしようとするとログインを促され、面倒
  * Clone with SSHしてれば不要
GPSの研究　その4

#概要
GPSを理解したい。
RINEXから、現在地を算出したい。
RINEXをパースして見た。

#OBSのパース

##サンプルコード

```
from pathlib import Path
import pyrinex as pr

fn = Path('gisa116x.18o')
obs, nav = pr.readrinex(fn, use = 'G')
print (obs.isel(sv=2).isel(time=1))

```
##結果

```
<xarray.Dataset>
Dimensions:  ()
Coordinates:
    sv       <U3 'G24'
    time     datetime64[ns] 2018-04-26T23:01:00
Data variables:
    C1       float64 2.182e+07
    C1ssi    float64 8.0
    L1       float64 1.147e+08
    L1lli    float64 nan
    L1ssi    float64 8.0
    S1       float64 46.9
    P1       float64 nan
    P1ssi    float64 nan
    C2       float64 2.182e+07
    C2ssi    float64 8.0
    L2       float64 8.935e+07
    L2lli    float64 4.0
    L2ssi    float64 9.0
    S2       float64 34.6
    P2       float64 2.182e+07
    P2ssi    float64 9.0
    C5       float64 2.182e+07
    C5ssi    float64 9.0
    L5       float64 8.562e+07
    L5ssi    float64 9.0
    S5       float64 52.0
    S5ssi    float64 nan
Attributes:
    toffset:    -.000000002
    filename:  gisa116x.18o
    version:   2.11


```



#NAVのパース

##サンプルコード

```
from pathlib import Path
import pyrinex as pr

fn = Path('gisa116x.18n')
obs, nav = pr.readrinex(fn, use = 'G')
print (nav.isel(sv=2).isel(time=1))

```
##結果

```
<xarray.Dataset>
Dimensions:           ()
Coordinates:
    sv                <U3 'G12'
    time              datetime64[ns] 2018-04-27
Data variables:
    SVclockBias       float64 0.0003372
    SVclockDrift      float64 -2.274e-12
    SVclockDriftRate  float64 0.0
    IODE              float64 31.0
    Crs               float64 -71.69
    DeltaN            float64 4.055e-09
    M0                float64 0.4623
    Cuc               float64 -3.941e-06
    Eccentricity      float64 0.007202
    Cus               float64 8.57e-06
    sqrtA             float64 5.154e+03
    Toe               float64 4.32e+05
    Cic               float64 -1.118e-07
    Omega0            float64 2.123
    Cis               float64 6.892e-08
    Io                float64 0.9867
    Crc               float64 231.8
    omega             float64 0.9658
    OmegaDot          float64 -7.936e-09
    IDOT              float64 -3.879e-10
    CodesL2           float64 1.0
    GPSWeek           float64 1.998e+03
    L2Pflag           float64 0.0
    SVacc             float64 2.4
    health            float64 0.0
    TGD               float64 -1.257e-08
    IODC              float64 31.0
    TransTime         float64 4.269e+05
    FitIntvl          float64 4.0
Attributes:
    version:   2.11
    filename:  gisa116x.18n
```



以上。