OmniAICreator/Qiita-1.07M huggingface dataset:
眺めて覚えるGo言語 その4 Windows10 GUI

# GO は、サーバー用言語だからGUIは、HTMLで十分言う考え方がある。
###だけどGUI作りたい。
WALKを使えば簡単に作れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/06362c0c-7334-7ebc-df4c-ca96c19a22cb.png)
こんな感じのGUI
ライブラリのありか!
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/92fbbc49-68f0-1661-9e17-5166edc52701.png)]
(https://github.com/lxn/walk)
#インストール
```
C:\Users\hirat\go-work\gui> go get github.com/lxn/walk
```
つぎにテストソース

```test.go
package main

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
	"strings"
)

func main() {
	var inTE, outTE *walk.TextEdit

	MainWindow{
		Title:   "Hello Golang GUI",
		MinSize: Size{320, 240},
		Layout:  VBox{},
		Children: []Widget{
			HSplitter{
				Children: []Widget{
					TextEdit{AssignTo: &inTE},
					TextEdit{AssignTo: &outTE, ReadOnly: true},
				},
			},
			PushButton{
				Text: "クリック",
				OnClicked: func() {
					outTE.SetText(strings.ToUpper(inTE.Text()))
				},
			},
		},
	}.Run()
}
```
つぎにマニフェスト(適当なWindows manifest)

```test.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="HelloWord" type="win32"/>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
        </dependentAssembly>
    </dependency>
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
            <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
        </windowsSettings>
    </application>
</assembly>
```
次に、次のようにrsrcツールを使用してマニフェストをコンパイルします。

```
go get github.com/akavel/rsrc

rsrc -manifest test.manifest -o rsrc.syso
```

この時に

```
    rsrc.syso
    test.go
    test.manifest
```
ファイルがありります。

```
go build
go build -ldflags="-H windowsgui"
```
```
C:\Users\hirat\go-work\gui>tree /f
C:.
    gui.exe
    rsrc.syso
    test.go
    test.manifest
```
gui.exeは、C:\Users\hirat\go-work\gui作成されダブルクリックで実行できます。
Amazonの領収書の合計をshellでちょっと見る。

#Amazonの領収書の合計をshellでちょっと見る。
##条件
* pdfgrep がインストールされている。
* 一つのフォルダにpdfでAmazonの領収書がある。
* 複数発送は確認していない。（とりあえず今急いでるのであとでやる）


### 使い方
領収書が保存されているディレクトリに移動して貼り付ける

```sh
pdfgrep -m 1 -P "請求額.*(\d|,)+" * | cut -d "額" -f2 | tr -d " " | tr -d ","| sed "s/^/+/g" | tr -d "\n" | sed "s/^+//g" | bc
```
WindowsのAMIからの起動時のアクティベートエラー

WindowsインスタンスからAMIを作成して、別のVPCで立ち上げたらアクティベートエラーに！

スナップショットからの作成だとライセンス認証用のコードがなくなってしまうと言うのは聞いたことが有ったので、イメージ作成からAMIを作成したのに...

と途方にくれていても仕方ないので調べてみると、以下に解決方法がありました。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/common-messages.html#activate-windows

これ、スナップショット作成時とかAMI作成時にこういう事象が起こるよっていうポップアップを出すとかして、わかりやすくしてほしいなぁ。

これも誰かの助けになれば幸いです！
ノートPCにCentOSを入れた話

#はじめに

全く使っていなかったノートPCを勉強用に使おうと思いCentOSを入れてみることにした。
思ったより時間がかかったので記録に残しておく。
今回はUSBメモリを使った方法で、元環境はWindows7を使用。

#必要なソフトやファイル
+ [CentOS](https://www.centos.org/download/)
+ [Rufus](https://Rufus.ie)

#手順
CentOS Linux DVD ISOをクリック
ダウンロードするisoのファイルが複数出てくるが一番上でいいと思う。
（回線速度次第ではかなり時間がかかるのでなにかしているついでにダウンロードしておくと良い）

Rufusはページの真ん中少し上にダウンロードファイルのリンクが貼ってあるので、
最新版をダウンロードする。


![Rufus_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545843/c8eba06e-59a8-2c04-0458-86ce84360ebe.png)

Rufusの画面を開いて、ブートの種類を選択する。
（黒矢印の選択から、ダウンロードしたisoファイルを選べばOK）

クリックフォーマットと拡張機能うんたらって書かれているところに
チェックが入っているかを確認してスタート！！

isoイメージかDDイメージのどっちで作るか聞かれるのでisoで作成する。
何かエラーでたらDDで作成するとできるらしい（エラー出てないので不明）

####これにも時間がかかるので、ながら作業推奨

緑ゲージがいっぱいになったらいざ再起動してBIOSを立ち上げる。
（電源ON後にF12を押すとBIOSが立ち上がる）

あとはUSBから起動するようにすれば、OSのインストール画面が出てきます！
【Metabaseチュートリアル】Collectionを作ってみよう

[< 前(Question・Collection・Dashboardを理解する)](https://qiita.com/k_0120/items/9979ec82cbdff7c67185)
[次 >(Questionを作ってみよう)](https://qiita.com/k_0120/items/2c4e5300ef63c514cb69)

# このチュートリアルで理解できること

- Collectionの仕様と作り方について


# パーソナルCollectionへ移動

- 本チュートリアルでは、ログインしているユーザーしか参照できないパーソナルCollectionの中で作業していきます。
- Metabaseトップページにある下記画像の赤枠をクリックしてください。


![Collection1_censored.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/94edf172-8f20-17e5-74c5-3d0b56660057.jpeg)

- 下記画像の赤枠がパーソナルCollectionに該当します。
- 赤枠をクリックしてください。

![Collection2_censored.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/bf702b1e-7ec9-6983-2ffb-8cde567a8034.jpeg)


# Collectionを作成

- 下記画像の赤枠をクリックすると、新規Collection作成メニューが表示されます。


![Collection3_censored.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/4b4a07be-6439-eee1-a879-c342f6c64105.jpeg)


### 実践

- `SampleCollection1` `SampleCollection2` `SampleCollection3`の3つのCollectionを、パーソナルCollectionの中に作ってみましょう。

  - ※パーソナルCollectionの中身が空の場合、新規Collection作成のリンクが表示されません。1つ前の階層に戻り、「SampleCollection1」を作成し、パーソナルCollectionにSampleCollection1をD&Dしてください。

- `SampleCollection2`の中に、`SampleCollection2-1`を作ってみましょう。


### 確認

- 下記画像と同じ階層構造が作れていれば正解です。

![tutorial2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311026/7727b8ce-8505-fe72-7574-765aec946ce6.png)
docker-composeで環境構築する際、railsサーバーのコンテナが起動しないときの対処法

##記事の目的
railsのコンテナをdocker-composeで立ち上げる際に発生したコンテナが起動しない問題に対しての対処法を共有すること。

## 状況
```$ docker-compose up -d```でコンテナを立ち上げる。


```
$ docker-compose up -d
rails_db_1 is up-to-date
Starting rails_web_1 ... done
```
```$ docker-compose  ps ```で現在のコンテナの中身を確認したところ、

 ```
$ docker-compose  ps 
   Name         Command     State       Ports   
------------------------------------------------
rails_db_1    docker-entr   Up       3306/tcp,  
              ypoint.sh              33060/tcp  
              mysqld                            
rails_web_1   bundle exec   Exit 1              
              rails s -p                        
              300 ...   
```
## 対処法


```$ docker logs rails_web_1```でlogを確認。

 ```
$ docker logs rails_web_1
=> Booting Puma
=> Rails 5.0.0.1 application starting in development 
=> Run `rails server -h` for more startup options
A server is already running. Check /app/tmp/pids/server.pid.
Exiting
```
すると、「もうすでにサーバーは起動しているよ、
/app/tmp/pids/server.pid.を確認してね。」と言っている。

###server.pid.について
これは、サーバを起動するときに書き込まれ、
```$ docker-compose down```などのコマンドでサーバを停止した際に残ってしまっていることがあるファイル。

これがあるともう一度起動したくても、起動状態と判断されサーバが立ち上がらなくなる。

よってこのファイルを削除すると起動ができる。

```
$ rm tmp/pids/server.pid
```

で削除。

もう一度立ち上げてコンテナを確認

```
$ docker-compose up -d
rails_db_1 is up-to-date
Starting rails_web_1 ... done
```
```
$ docker-compose  ps 
   Name         Command      State      Ports   
------------------------------------------------
rails_db_1    docker-entry   Up      3306/tcp,  
              point.sh               33060/tcp  
              mysqld                            
rails_web_1   bundle exec    Up      0.0.0.0:300
              rails s -p             0->3000/tcp
              300 ...                       
```
Stateを確認すると起動していることが確認できる。


## 終わりに
コンテナを削除する際にserver.pid.が残ってしまう時は、 ```rm tmp/pids/server.pid```で削除すればコンテナを起動することができる。
dockerを使いたての初心者がよく陥りやすいミスなので覚えておくと得。
強化学習44　windows10で開発環境を作るときのTips

中学生から大学生のAI初学者を対象にしています。
chokozainerは、ubuntuを使っています。子供たちはwindows10とmacを使っています。
colaboratoryを使用しないでGPU機械学習環境を構築するならば、ubuntuは圧倒的に便利なのですが、Colaboratoryを使用するならば、windowsでもmacでも大差ありません。

windowsの設定は、面倒なので放置していたのですが、そろそろ手を付けることにしました。

#　うるさい日々のバックグラウンドサービスを減らす方法
そもそも、windowsが面倒な理由の一つは、起動するたびにバックグランドでやっているサービスです。
これの止め方ですが、
CompatTelRunnerの止め方
https://aprico-media.com/posts/2554
こちらに詳しく書いてあります。
よほどの理由がなければ止めるのが吉です。

#　Anaconda3のターミナルを、Alt+Ctl+Tで出す。
要は、ショートカットキーの作り方です。
こちらに詳しく書いてあります。
https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=017810
不思議と、qiitaでは見つからず。当たり前すぎるのだろうか。。。

# Anaconda環境で、jupyter　Notebookを実行する。
これって何のこっちゃですが、windows特有の話です。
スタートボタンから選択して実行するjupyter　notebookは常にbaseのようです。
anacondaで環境を切り分けて使用する場合は、その環境に以下のようにしてから、jupyternotebookを起動しないとだめです。
結構はまるところです。

```bash
conda activate chainer
jupyter notebook
```
chainer環境で、実行できます。次のように、ショートリンクつけていると、大切な話になります。


#anaconda環境にショートカットリンクする。
windowsのショートカットの作り方は、こちらに詳しく書いてあります。
https://121ware.com/qasearch/1007/app/servlet/relatedqa?QID=017742

windowsのanaconda環境は、C:\Users\UserName\Anaconda3\envs\　以下に作られます
C:\Users\UserName\Anaconda3\envs\chainer\Lib\site-packages　の中にショートカットキーを置きましょう。

anaconda3は、2019年のupdateで大幅に使いやすくなっている印象です。おかしいなと思ったら、アップデートしましょう。
FlexBox でスクロールさせたいアイテムが潰れちゃうやつ

FlexBox で横並びリストを作った時に以下のようにアイテムが潰れて、しばらく手こずってたメモ

![こんな](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525849/8dc0cc37-609b-6a6c-ce9d-47bb1f5927aa.png)

## 解決方法
flex-shrink が原因
0 を指定すれば潰れなくなる

[**`flex-shrink`**](https://developer.mozilla.org/ja/docs/Web/CSS/flex-shrink)
アイテムの縮小度を設定するプロパティ
アイテムの寸法がコンテナより大きい場合このプロパティに従って縮小される

## サンプル
<p class="codepen" data-height="400" data-theme-id="32227" data-default-tab="result" data-user="canoypa" data-slug-hash="rENjjR" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="flex-shrink">
  <span>See the Pen <a href="https://codepen.io/canoypa/pen/rENjjR">
  flex-shrink</a> by cano (<a href="https://codepen.io/canoypa">@canoypa</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
[Python3]チームのために簡単なコーディングルールをまとめる

ある小さなチームのPython3での開発のコーディングルールをまとめる。
タイトルにある「簡単な」の意味は、あまりプログラミングスキルが高くないチーム向けに基本的なことをざっくりとまとめているということ。
チームの進行度やスキルレベルの成長に合わせて進化させられたらいいな。

詳しい方からみると、Pythonコーディング規約のPEP8の抜粋にすぎませんので、そのようなものと思って読んでください。

# 環境
- Python 3.7.4
- pytest 5.2.2

# フォルダ構成
- フォルダ構成を一定にしてプログラム開発する習慣をつける
- プログラムとセットでテストも作成する習慣をつける

```
(project name)
├── (project name) ............ プログラムのソースコード
│  ├── logs ................... ログ出力先フォルダ
│  ├── data ................... 連携ファイル格納先フォルダ
│  └── *.py
└── tests ..................... 単体テストのソースコード
   └── test_*.py
```

# 命名規則
- Pythonの標準的な考え方やルールに則るのが原則

## モジュール名、関数名、変数名
- 小文字のみ、単語間をアンダーバー(_)で区切る
- 例 sample_module.py, sample_function

## 非公開にしたい関数名、変数名
- 先頭にアンダーバー(_)をつける
- 非公開指定の関数や変数を呼び出さないこと(呼び出そうと思えばできてしまう)

## 定数名
- 大文字のみ、単語間をアンダーバー(_)で区切る
- 例 SAMPLE_CONSTANT

## クラス名
- 単語の先頭を大文字にし、それ以外は小文字とし、アンダーバーで区切らない(Pascal記法という)
- 例 SampleClass

# クォーテーション
- ダブルクォーテーション(")で統一
- Pyhonはシングルクォーテーション(')もOKだが、チームでは統一する

# スペースの入れ方
- 余分なスペースは入れない方針で統一
- 何が余分かについては好みもあるかもしれないがプロジェクトの統一感を出したい
- 例

```
# 好ましくない例
family( parents[ 1 ] , children[ 1 ] )
sample_function ( x )

# 好ましい例
family(parents[1], children[1])
sample_function(x)
```

#空行の入れ方
- 関数やクラスの区切りは2行分の空行を入れる。
- 例

```
# トップレベルの区切りの空行は2行
def sample_function_1()
    pass


def sample_function_2()
    pass


def sample_function_3()
    pass
```

# import文の書き方
- 複数をインポートする際は、ライブラリ毎に一行ずつ分けて書く
- 標準ライブラリ、サードパーティ製ライブラリ、プロジェクトで作成したモジュールでカテゴライズし、その順に並べる(カテゴリは1行分の空行で区切り、カテゴリの中はアルファベット順に並べる)
- 標準ライブラリは、pythonに用意されているライブラリのこと(例 datetime, logging)
- サードパーティ製ライブラリは、pythonが用意しているもの以外で企業や個人が配布しているライブラリのこと
- `from <モジュール名> import <オブジェクト名>`でオブジェクトを明示的にインポートすることを推奨
- 例

```
from datetime import datetime, timedelta
from logging import getLogger

from third_party_liblary import sample_object

from project_module import sample_function
```

# コメントのつけ方
- 何を目的としたプログラムなのか、コメントがないと理解しにくいのでコメントを書く習慣をつける
- 公開する関数の説明は必ずコメントをつけること。
- 関数の説明にはdocstring(開始と終了をダブルクォート3個で囲んで書くやり方)を推奨


# 参考
- [[Pythonコーディング規約]PEP8を読み解く](https://qiita.com/simonritchie/items/bb06a7521ae6560738a7)
- [Python, importの使い方（from, as, PEP8の推奨スタイル, 注意点など）](https://note.nkmk.me/python-import-usage/)
- [[Python]可読性を上げるための、docstringの書き方を学ぶ（NumPyスタイル）](https://qiita.com/simonritchie/items/49e0813508cad4876b5a)
- [PEP8(Python コードのスタイルガイド)](https://pep8-ja.readthedocs.io/ja/latest/#)


## 追記2021/1/10
内容を再確認し、冒頭に注意書きを追加「詳しい方からみると、Pythonコーディング規約のPEP8の抜粋にすぎませんので、そのようなものと思って読んでください。」
firebase データ取得にfor文を使いつつ、その中で非同期処理する方法

この記事は、どっかからAPIをとってきたデータを、firebaseのデータ群と比較参照する場合、
非同期処理とfor文をどうやって組み合わせれば良いかというところにいつも引っかかっていてしまっていたので、その備忘録です。

## 環境
- Node.js
- Cloud firestore

## どんな問題なのか
firestore にあるcollection からデータを全てとってくる場合、下記の例のように、`forEach`を使ってとってくるのが普通です。


```js
var query = db.collection('contents').get();
query
  .then(function(snapshot) {
    snapshot.forEach(function(childSnapshot) {
     ... // childsnapshot の処理
 });
});
```


しかし、この`forEach`文の中、つまり、`childsnapshot`の処理の中に、時間がかかる関数を呼び出していて非同期処理をする必要があるとなった場合、
**`forEach` は非同期処理に対応していない**ため、一筋縄でいかないのが問題でした。

具体的に、下記のような重い処理を`childSnapshot`の処理内で行うと、

```js
var query = db.collection('contents').get();
query
  .then(function(snapshot) {
    snapshot.forEach(async function(childSnapshot) {
     console.log('before_func');
     await heavyfunc(childSnapshot); //重い処理
     console.log('after_func');
 });
});

const heavyfunc = function(data){
   ... // API をとってくるなどの重い処理
   console.log('inside_func');
}
```

```js
// snapshot が2つのdataを持っている場合
before_func
after_func
before_func
after_func
inside_func
inside_func
```
このような結果が得られ、`heavyfunc`の処理が`forEach` の処理に追いついていない状態になります。


## どうやったか


```js
var query = db.collection('contents').get();
query
  .then(async function(snapshot) {
    for await(let childSnapshot of snpashot.docs){
     console.log('before_func');
     await heavyfunc(childSnapshot); //重い処理
     console.log('after_func');
   }
});

const heavyfunc = function(data){
   ... // API をとってくるなどの重い処理
   console.log('inside_func');
}
```

`forEach` ではなく、**`for ~ of`を使ってループ内での非同期処理を実現**しました。




### 具体的に
- `for ~ of` を使う際、そのループにも`await`を付けたす必要がありました。
- `snapshot`のデータを一つずつ取ってくる時に、**`snapshot.docs`のように`docs`を呼び出さないと、データを取得することが出来ませんでした。**
Goのfor文のまわりの変数スコープ

Goでの変数のスコープについてはすでにあちこちで語られているとは思いますが、再確認。

以下のプログラムは i を何度も定義していますが動作します。

```go
package main

import (
	"log"
)

func main() {
	log.SetFlags(log.Lshortfile)

	i := 123
	log.Println(i)
	for i := 0; i < 3; i++ {
		log.Println(i)
		i := 9999
		log.Println(i)
	}
	log.Println(i)
}
```
https://play.golang.org/p/eSlHO5tlhBH

playground での結果

```
prog.go:11: 123
prog.go:13: 0
prog.go:15: 9999
prog.go:13: 1
prog.go:15: 9999
prog.go:13: 2
prog.go:15: 9999
prog.go:17: 123
```


こちらで解説されているものもほぼ同じですね。
https://dave.cheney.net/2016/12/15/declaration-scopes-in-go
機械学習学び始めて1ヶ月で取り組んだこと

Advent Calendarに初参加します。

機械学習をどう学んだか by 日経 xTECH ビジネスAI② Advent Calendar 2019のカレンダーが埋まっていると思っていたんですが、空いていたので急遽書くことにしました。

## 経緯
今後の案件に備えて2019年12月から本格的に勉強始めました。理系の大学出ているので数式見てもウッとはなりません。

## 学習の流れ
以下の順に学習しました。

1. 統計
2. 機械学習
3. DeepLearning
4. TensorFlow ← 最近

統計を予め理解しておいたほうが、ML/DeepLearningを簡単に理解できそうかなーと後々Kaggleやりたいなーというところから統計を始めに学習しました。
実際に、回帰あたりの最小二乗法とかの話を理解しておけば、DeepLearningで損失コストを最小にしていく流れもスッと理解できるのではないかなーと思っています

## 統計
統計WEBを利用しました。リンクは下記参照
大学で確率の期待値・分散・分布あたりの証明はやった記憶があるんですが、実際にどういうことに利用されているかの認識はなかったので、結構楽しかったです。（もっと早めに学習しておけばよかった、、、）

一通りやったあと、`scipy`を利用しつつpythonで問題解きつつ、pythonの使い方とかもざっくり覚えました。基本的にはGoogle Colaboratory使ってました。便利 :smile: 

## 機械学習
『Python機械学習プログラミング 達人データサイエンティストによる理論と実践』から入りました。
機械学習全般の知識を身につける目的でした。写経しつつ取り組みましたが、かなりいい本だと思います。

## DeepLearning
『ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装』を読みました。
実際にゼロから作るので

- 活性化関数
- 損失関数
- 誤差逆伝播法

あたりはかなりわかりやすいと思いました。



## TensorFlow
DeepLearningがかなり面白そうなので、TensorFlow使ってみよう！みたいになりました。
簡単にtutorialやった後は、CycleGANのチュートリアルから自前で用意した画像に合わせて学習させて遊んでます

## 今後
今後はKaggleのコンペに参加を目標にやろうと思ってます :thumbsup: 


## 参考
### WEB

- [統計WEB](https://bellcurve.jp/statistics/course/)
- [TensorFlow tutorials](https://www.tensorflow.org/tutorials)
- [TensorFlow tutorials CycleGAN](https://www.tensorflow.org/tutorials/generative/cyclegan)

### 書籍
amazonのリンクです

- [Python機械学習プログラミング 達人データサイエンティストによる理論と実践](https://www.amazon.co.jp/dp/4844380605/ref=cm_sw_em_r_mt_dp_U_Q1vbEbGK13BKQ)
- [ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装](https://www.amazon.co.jp/dp/4873117585/ref=cm_sw_em_r_mt_dp_U_l4vbEbC3W8QN2)
PHP/Psyshによる対話型デバッグ時の使い方

一旦個人的にメモ、後ほどちゃんとした記事形式に修正予定

####ブレークポイントの設定
eval(\Psy\sh());

####対話を終了してプログラム続行
exit

####プログラムの実行ごと中止
Ctrl + C
簡単なiOSアプリの開発費相場の意識調査結果

最近Twitter経由で個人での簡単なiOSアプリの受託開発の打診を受け、費用を伝えると連絡が途絶えました。具体的な内容は書けないのですが、以下のような案件です。

- 実装期間は2日（かなりシンプルな機能でこれ以上はかかりそうにない）
- 実装可能か要検証な機能有り
- アイコン画像等のリソースは発注元が作成
- App Store申請作業込み（シンプルな為リジェクト対応が必要になる可能性あり）

見積もりとしては合計20万円と出しました。

そこで以下のようにツイートでアンケートをとってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Twitter経由でちょっと検証は必要だけど2日程度でできそうなiOSアプリの開発を打診されて、申請関係も込みで20万円って返したんだけど、音沙汰がなくなった。20万って高いかな？</p>&mdash; りず (r.izumita) (@rizumita) <a href="https://twitter.com/rizumita/status/1209978871937814529?ref_src=twsrc%5Etfw">December 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

選択肢は

- 高い
- 安い
- 丁度良い

です。

## 調査結果

投票数: 236票

- 高い: 8%
- 安い: 46%
- 丁度良い: 46%

## 感想

- 投票数からアプリ開発費への興味がうかがわれる
- 意外に「安い」が多い

まず投票数がこれだけ伸びるとは思いませんでした。投票期間は1日だけです。これまで様々なアンケートを投稿しましたが、最も多い投票数です。おそらく投票してくださったのはアプリ開発者の方々で、皆さん開発費に強い興味があるのではないかと思いました。

途中経過では「安い」が「丁度よい」より常にリードしていましたが最終的には同値になりました。私が行った見積もりは私が副業で提示している単価に照らして丁度良いように見積もったつもりでした。アンケートへ以下のコメントがありました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">時給1万で2日稼働で16万、申請やリジェクト時あたりのセルフサポート対応に4万くらいで妥当で良さそうかなーと計算した。 <a href="https://t.co/dgvQVkEZoO">https://t.co/dgvQVkEZoO</a></p>&mdash; 🧖🏻 (@a_aryzae) <a href="https://twitter.com/a_aryzae/status/1210040845518307329?ref_src=twsrc%5Etfw">December 26, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

まさに私が見積もった計算と同じ計算です。私の副業での単価は少し高めかもしれないと思っているので「安い」はある程度票は集めはするが「丁度良い」の方が支持されると思っていましたし、「高い」も20%くらいは集めると思っていました。しかし「安い」が、最終的に「丁度よい」と同値とは言え、常にリードしてこれだけの支持を集め、「高い」が一桁台ということは、開発費が私の感覚よりも高騰しているのではないかと思われます。以下のコメントがまさにそうです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ちょうど良いで答えたけど、安いと言う人もいた。たしかにスポット20万で1アプリ作るには安いような気もする。今ってエンジニア探すだけでお金かかる時代だと思うので。あとは開発中とリリース後の仕様変更と瑕疵担保責任で作業が発生する見込みがあるなら、40,50万くらいでも良いような気もしてきた。 <a href="https://t.co/CFXQ0ZMycB">https://t.co/CFXQ0ZMycB</a></p>&mdash; koishi (@mego_) <a href="https://twitter.com/mego_/status/1209982647193108480?ref_src=twsrc%5Etfw">December 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

私の感覚からすると結構高いように思いますが、そんな時代なんでしょうか。発注側からすると2日でできるアプリが40〜50万というのは、かなり高いと感じられるのではないでしょうか。すごい時代です。私の副業の単価ももっとあげるべきなのではと思えてきました…

---

投票してくださった皆様、ありがとうございました。

この投稿を読んでくださった皆さんはどのように感じられましたでしょうか？もしよかったらコメントをお願いします。
content_tag

`content_tag`はのちに消える説あるけどコードが冗長だったので修正しました。

##修正前
```html
<% if @provider.key == "noe-jx-group" %>
  <div class="e__saving"><span class="e__tag">割引額</span><span class="e__number e__deals"><%= service['discount'].to_f %></span>円<% if SetPlan.is_discount_from_energy?(service) %>/kWh<% elsif SetPlan.monthly?(service) %>/月<% elsif SetPlan.yearly?(service) %>/年<% end %></div>
<% end %>
```

##修正後

```html

<%= discount_text(service, @provider) %>
```

```try_helper.rb
  def discount_text(service, provider)
    content_tag(:div, class: "e__saving") do
      discount_text = content_tag(:span, "割引額", class: "e__tag")
      discount_value = content_tag(:span, provider.key == "noe-jx-group" ? service['discount'].to_f : service['discount'].to_i, class: "e__number e__deals" ) + "円"
      discount_from_energy = if SetPlan.is_discount_from_energy?(service)
        "/kWh"
      elsif SetPlan.yearly?(service)
        "/年"
      elsif SetPlan.monthly?(service)
        "/月"
      end
      discount_text + discount_value + discount_from_energy
    end
  end

```
【Angular】DBのデータを元にテーマカラーを動的に変更したい

## はじめに
DBのデータ(カラーコード)を元にAngularのテーマカラーを変更する方法を共有していく。

## 環境
- Angular 8.2.11
- Angular Material 8.2.3

## `global.css`にテーマカラーを適用するための変数を宣言
ちなみに環境によっては`global.css`という名前ではなく、`style.css`かもしれない。(自分は`style.css`だった。)
`global.css`の確認方法としては、`angular.json`のこの箇所↓

```json:angular.json
{
  "projects": {
    "hoge-project": {
      ...
      "architect": {
        "build": {
          ...
          "options": {
            ...
            "styles": [
              "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
              "src/styles.css"
            ],
          },
        }
      }
    }
  }
}
```

ここに指定されている`src/style.css`というのが`global.css`にあたるものだ。

この`style.css`に以下の設定を追加。
※ここのデフォルトカラーに関しては、ネットワークの速度によってはどうしても色の反映が遅れてしまい、ちらついたように見えてしまうため背景色と合わせたほうが無難。

```css:style.css
:root {
    --main-color: #FFF;
    --sub-color: #FFF;
    --accent-color: #FFF;
}
```

## テーマカラーを適用したい箇所に、先ほど設定した変数を当てる
以下は設定例

```scss:example.scss
.example-main {
  &__item {
    &__button {
      background-color: var(--main-color);
    }
  }
}
```

## カスタムテーマカラー用のServiceクラスを作成
```typescript:theme-color.service.ts
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';

interface ThemeColor {
    mainColor: string;
    subColor?: string;
    accentColor?: string;
}

@Injectable({
    providedIn: 'root',
})
export class ThemeColorService {
    constructor(private http: HttpClient) {}

    public async initialize() {
        const { mainColor } = await this.http
            .get<ThemeColor>('theme-color')
            .toPromise();
        document.documentElement.style.setProperty('--main-color', mainColor);
    }
}
```

重要なのはこの部分。

```typescript
document.documentElement.style.setProperty('--main-color', mainColor);
```

これを`app.component.ts`の`ngOnInit()`とかで呼んであげることでテーマカラーが適用される。

## 参考
- [Theming Angular apps with CSS Custom Properties](https://coryrylan.com/blog/theming-angular-apps-with-css-custom-properties)
MNISTのデータベースをJSONで得る

MNISTのWebサイトで配布されている手書き数字のデータは、バイナリ形式です。これを、JSONデータに変換する方法をメモしました。

http://yann.lecun.com/exdb/mnist/

DBをダウンロードして、解凍します。

```js:mnistdb2json.js
// MNIST手書きデータをJSONに変換する for Node.js

const CONV_LIMIT = 5000 // 小さなJSONを作成する場合

// サンプルファイルの保存先を指定
var DIR_IMAGE   = __dirname + "/image";

// モジュールの取り込み
var fs = require('fs');

// 変換処理
convertToJSON("train");
convertToJSON("t10k");

function convertToJSON(basename) {
  console.log("convert: " + basename);
  // 各種ファイル名を決定
  var file_images = basename + "-images-idx3-ubyte";
  var file_labels = basename + "-labels-idx1-ubyte";
  var file_csv = basename + ".json";

  // ファイルを開く
  var f_img = fs.openSync(file_images, "r");
  var f_lbl = fs.openSync(file_labels, "r");
  // var f_out = fs.openSync(file_csv, "w+");

  if (!fs.existsSync(DIR_IMAGE)) {
    fs.mkdirSync(DIR_IMAGE);
  }

  // ヘッダを読む
  var buf_i = new Buffer(16);
  fs.readSync(f_img, buf_i, 0, buf_i.length);
  var buf_l = new Buffer(8);
  fs.readSync(f_lbl, buf_l, 0, buf_l.length);

  // ヘッダをチェック
  var magic      = buf_i.readUInt32BE(0);
  var num_images = buf_i.readUInt32BE(4);
  var num_rows   = buf_i.readUInt32BE(8);
  var num_cols   = buf_i.readUInt32BE(12);
  var num_size   = num_rows * num_cols;
  if (magic != 0x803) {
    console.error("[ERROR] Broken file=", magic.toString(16));
    process.exit();
  }
  console.log("num_of_images=" + num_images);
  console.log("num_of_rows=" + num_rows);
  console.log("num_of_cols=" + num_cols);
  console.log("num_of_pixel_size=" + num_size);

  // 画像を取り出す
  var buf_img = new Buffer(num_size);
  var buf_lbl = new Buffer(1);
  var mini_csv = "";
  var labels = [];
  var datas = [];
  for (var i = 0; i < num_images; i++) {
    // 経過を表示
    if (i % 1000 == 0) console.log( i + "/" + num_images );
    if (i > CONV_LIMIT) break;
    // 画像を読む
    var pos_i = i * num_size + 16;
    fs.readSync(f_img, buf_img, 0, num_size, pos_i);

    // ラベルを読む
    var pos_l = i * 1 + 8;
    fs.readSync(f_lbl, buf_lbl, 0, 1, pos_l);
    var no = buf_lbl[0];

    // PGM形式として保存 (テスト用)
    if (i < 30) {
      var s = "P2 28 28 255\n";
      for (var j = 0; j < 28 * 28; j++) {
        s += buf_img[j] + " ";
        s += (j % 28 == 27) ? "\n" : "";
      }
      var img_file = 
        DIR_IMAGE + "/" + basename + 
        "-" + i + "-" + no + ".pgm";
      fs.writeFileSync(img_file, s, "utf-8");
    }

    // CSVとして保存
    var cells = [];
    for (var j = 0; j < 28 * 28; j++) {
      const v = Math.floor(buf_img[j] / 255 * 100) / 100
      cells.push(v);
    }
    labels.push(no)
    datas.push(cells)
  }
  var obj = {"label":labels, "data":datas}
  fs.writeFileSync(file_csv, JSON.stringify(obj), "utf-8")
  console.log("ok:" + basename);
}
```
Railsでsqlite3からpsglに乗り換えてみた！(途中から)

## 今回やること
#### (psglはインストールされている前提で話を進めます！)
- gem "pg"
- config/database.ymlを変更
- エラーにどのように対応したか


##　gem "pg"を入れる
sqlite３はコメントアウトするか、削除

```
gem 'pg', '~> 0.18.4'
```
bundle installをし、すんなり行けばおっけー！ちなみに僕はすんなりいきませんでした。それはエラーにどのように対応したかの項目で紹介します！

## config/database.ymlを変更
```rb

default: &default
  adapter: postgresql　#変更
  encoding: unicode
  pool: 5
  host: localhost　#追加
development:
  <<: *default
  database: appname_development # appnameのところは、db/development.sqliteになっているはずなので、変更
test:
  <<: *default
  database: appname_test　#上記と同様
```

## エラーにどのように対応したか
gem "pg"の時にめちゃめちゃ長いエラー
#### 解消方法　ターミナルもしくはテキストエディターの再起動

```

`
省略
`
An error occurred while installing pg (1.2.0), and Bundler cannot continue.
Make sure that `gem install pg -v '1.2.0' --source 'https://rubygems.org/'` succeeds before bundling.
```

bundle exec rails db:createしようとしたら、すでにあると言われてしまったのでconfig/database.ymlのappnnameをrenameしたらうまくいきました！
## 参考
https://qiita.com/taKassi/items/8e43171aeda300b67213
OTLT

# 参考
ジョー・セルコ

# メリット
テーブルが少なくて済む
マルチテナントアーキテクチャではなしじゃない

# デメリット
型変換が起きるとインデックスが使えない
https://dev.mysql.com/doc/refman/5.6/ja/type-conversion.html

不要なレコードを読み込むことになる
SCSSでより簡単でスタイリング

SCSSに@mixinを使えば、クラスを定義することができます。

```scss:@mixin定義
@mixin themable($theme-name,container-bg,$left-bg,$right-bg,$innertext,$button-bg){
	.#{$theme-name}{
		.container{
			background-color:$container-bg;
			border:1px solid #000;
			display:flex;
			justify-content:space-between;
			margin:0 auto;
			width:50%;
		}

		*{
			color:$innertext;
			font-size:1rem;
		}

		.left {
			background-color: $left-bg;
			height: 100%;
			width: 69%;
		}

		.right {
			background-color: $right-bg;
			height: 100%;
			position: relative;
			width: 29%;
		}

		.button {
			background-color: $button-bg;
			border: 0;
			border-radius: 10px;
			bottom: 10px;
			cursor: pointer;
			font-size: 1rem;
			font-weight: bold;
			padding: 1em 2em;
			position: absolute;
			right: 10px;
		}

		input{
			outline:none;
			background:none;
			border:none;
			border-bottom:1px solid white;
			box-shadow:none;
		}
	}
}
```

これでthemableというクラスが定義できました。

それでは、@includeで実際にthemableを定義してみます。

```scss:@includeでmixinを継承
@include themable(dark-theme,#898989,#454545,#252525,#ffffff,#e5e5e5);
@include themable(light-theme,#ffffff,#ffa3a3,#ffa3d1,#000000,#ffd1a3);
```

```html:dark-theme
<body class="dark-theme">
  <div class="container ">
    <div class="left d-flex justify-content-center align-items-center">
      <span>LEFT</span>
    </div>
    <div class="right d-flex flex-column justify-content-center ">
      <span class="align-self-center">RIGHT</span>
      <button class="button">BUTTON</button>
    </div>
  </div>
</body>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557787/10f85465-2af4-8cfa-0f17-418f2d111d60.png)

```html:light-theme
<body class="light-theme">
  <div class="container ">
    <div class="left d-flex justify-content-center align-items-center">
      <span>LEFT</span>
    </div>
    <div class="right d-flex flex-column justify-content-center ">
      <span class="align-self-center">RIGHT</span>
      <button class="button">BUTTON</button>
    </div>
  </div>
</body>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557787/b177be22-b378-5f75-f096-57c1e1b98876.png)
dark-themeとlight-themeで宣言するだけで、簡単でスタイリングできようになりました。

これによってデサイントレンドのダークモードも手軽に実装できます。
皆さんもぜひ日常のフロント設計やコーディングの中にSCSS（またはSASS）を使ってみてください！
ilasmでstack machine その4

#概要

ilasmでstack machineやってみた。
先人に、教えを乞うた。

#参考にしたページ

http://home.a00.itscom.net/hatada/lp/ci/minicinterpreter00.html

#テストコード

```
int add(int a, int b) {
    return (a+b);
}

void main() {
    int sum, n = 1;
    int wa;

    wa = add(12, 23);

    sum = 0;
    while (n <= 10) { 
        sum = sum + n;
        n = n + 1;
    }
    printf("add(12,23)=%d sum=%d", wa, sum);
}
```

#結果


```
C:\mh\mcc>ci0 test.c -code
0: func str add
1: label int 1
2: entry
3: addsp int 0
4: push stack-val 2
5: push stack-val 3
6: add
7: ret
8: func str main
9: label int 2
10: entry
11: addsp int -3
12: push stack-ref -2
13: push int 1
14: mov
15: push stack-ref -3
16: push int 23
17: push int 12
18: call int 1
19: addsp int 2
20: mov
21: push stack-ref -1
22: push int 0
23: mov
24: label int 3
25: push stack-val -2
26: push int 10
27: le
28: jz int 4
29: push stack-ref -1
30: push stack-val -1
31: push stack-val -2
32: add
33: mov
34: push stack-ref -2
35: push stack-val -2
36: push int 1
37: add
38: mov
39: jmp int 3
40: label int 4
41: push stack-val -1
42: push stack-val -3
43: push str "add(12,23)=%d sum=%d"
44: call str printf
45: addsp int 3
46: ret
add(12,23)=35 sum=55
```

#ニーモニック

|ニーモニック|	意味|	stackの状態|
|:--|:--|:--|
|push|stackに積む。|	１個増える|
|entry|エントリー|	変化無し|
|pop|stackから、取り出す。|	１個減る|
|mov|ファンクションに飛ぶ。|	変化無し|
|add|stack-1,stackの加算を求める。|	１個減る|
|addsp|stackの操作。|	１個減る|
|sub|stack-1,stackの減算を求める。|	１個減る|
|mul|stack-1,stackの乗算を求める。|	１個減る|
|div|stack-1,stackの除算を求める。|	１個減る|
|mod|stack-1,stackの剰余を求める。|	１個減る|
|ret|サブルーチンから戻る。|	１個減る|
|call|サブルーチンに行く。|	１個増える|
|jz|stack-1,stackが真ならtugiへ飛ぶ。|	１個減る|
|jmp|無条件でtugiへ飛ぶ。|	変化無し|
|cmp|stack-1,stackを比較する。|	１個減る|
|lt|stack-1,stackが大ならtugiへ飛ぶ。|	１個減る|
|gt|stack-1,stackが小ならtugiへ飛ぶ。|	１個減る|
|le|stack-1,stackが真ならtugiへ飛ぶ。|	１個減る|
|ge|stack-1,stackが偽ならtugiへ飛ぶ。|	１個減る|
|eq|stack-1,stackが同じならtugiへ飛ぶ。|	１個減る|
|ne|stack-1,stackが違うならtugiへ飛ぶ。|	１個減る|
|func|ファンクション|	変化無し|
|label|ラベル|	変化無し|

#書き直し


```
   func "add"
label1:
   entry
   addsp 0
   push stack-val 2
   push stack-val 3
   add
   ret

   func "main"
label2:
   entry
   addsp -3
   push stack-ref -2
   push 1
   mov
   push stack-ref -3
   push 23
   push 12
   call label1
   addsp 2
   mov
   push stack-ref -1
   push 0
   mov
label3:
   push stack-val -2
   push 10
   le
   jz label4

   push stack-ref -1
   push stack-val -1
   push stack-val -2
   add
   mov
   push stack-ref -2
   push stack-val -2
   push 1
   add
   mov
   jmp label3

label4:
   push stack-val -1
   push stack-val -3
   push "add(12,23)=%d sum=%d"
   call "printf"
   addsp 3
   ret


```


以上。
SSR(Self Service Restore)ではローカルクラスタ上のスナップショットからのみ戻せます

SSRについて質問があったので、一応動作を確認しました。

# はじめに。SSR(Self Service Restore)とは  
ゲストOSの管理者（Prsim管理者ではない）が、任意のファイルをリストアできる機能で、
Prism管理者の工数を削減し、ゲストOSの管理者も、お手軽にファイルをリストアできる、みんなにやさしいサービスです。


# 今回の質問
```
Async DRでリモート先に取得したスナップショットを用いてSSRが可能か？
Async DRで下記のように保護している  
- ローカルクラスタ：3世代
- リモートクラスタ：7世代

一番古いデータのリモートクラスタ上のスナップショットディスクをSSRでマウントしたいとのことでした

```

# 回答
結論としてはNoです。  
ゲストOSの管理者さんの操作だけではマウントできません。

# 画面イメージを取ってみました。
- ローカルクラスタ：1世代
- リモートクラスタ：3世代

### ローカルクラスタのスナップショット取得状況  
1世代だけ取得しています  
![img020_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543420/c9042ff5-4fae-555a-b72b-4a56e51e4607.jpeg)

### リモートクラスタのスナップショット取得状況
3世代取得しています。  
![img021.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543420/6120e0af-9ac1-147e-ea5e-fcc6a4d626a5.jpeg)


### SSRで確認できるスナップショット
ローカルクラスタの1世代分のみマウント可能です  
![img022.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543420/fa956aa7-b83e-1b08-03b4-17be7412f400.jpeg)


# 技術的には
SSRはローカルクラスタのIPアドレスに向けてスナップショットを確認していますので
マウントする場合は、ローカルクラスタにあるスナップショットをのみマウントすることができます

### リモートから戻せないの？
いや、戻せます。Prismの管理者さんの操作が必要ですが

リモートクラスタのスナップショットをローカルに転送した後は
当然SSRでディスクをマウントしファイルリストアをすることができます。


### まとめ
- SSRは便利！！
- SSRはローカルクラスタにあるスナップショットからのみ戻すことができます
- SSR以前のデータはもしかしたらクラスタの管理者さんに相談すると取ってることもありますので相談しましょう。そんなこともあろうかと、それ以前のデータが出てくるかもしれません  
- 設計時にはこういったことを踏まえてバックアップ設計（各クラスタの世代数やディスクサイジング）をする必要がありますね。
Rook/Cephの/metricsにアクセスし、Prometheusで監視してみた

# はじめに

自前のKubernetes(K8s)クラスターでRook/Cephを利用していますが、K8sクラスターの外にPrometheusを導入しています。Rookの公式ドキュメントでは、metricsを取得する方法が記載されていますが、coreos/prometheus-operatorを前提にした設定になっているので、簡単なメモを残すことにしました。


# Rook/CephのServiceを調べてみる

```bash:kubectlコマンドでrook/cephのservice定義を確認する
$ kubectl -n rook-ceph get svc
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
rook-ceph-mgr             ClusterIP   10.233.12.211   <none>        9283/TCP            214d
rook-ceph-mon-ah          ClusterIP   10.233.1.1      <none>        6789/TCP,3300/TCP   36d
rook-ceph-mon-ak          ClusterIP   10.233.27.34    <none>        6789/TCP,3300/TCP   6d20h
rook-ceph-mon-al          ClusterIP   10.233.25.114   <none>        6789/TCP,3300/TCP   6d20h
```

先頭のrook-ceph-mgrの/metricsにアクセスしてみます。

```bash:curlで/metricsを取得した結果
$ curl http://10.233.12.211:9283/metrics | grep -v '#' | head

ceph_mds_mem_dir_minus{ceph_daemon="mds.myfs-b"} 0.0
ceph_mds_mem_dir_minus{ceph_daemon="mds.myfs-a"} 43227.0
ceph_paxos_store_state_latency_sum{ceph_daemon="mon.ak"} 13650.276728195
ceph_paxos_store_state_latency_sum{ceph_daemon="mon.al"} 11494.469300331
ceph_paxos_store_state_latency_sum{ceph_daemon="mon.ah"} 30.680001772
ceph_mds_cache_recovery_completed{ceph_daemon="mds.myfs-b"} 0.0
ceph_mds_cache_recovery_completed{ceph_daemon="mds.myfs-a"} 0.0
ceph_osd_op_out_bytes{ceph_daemon="osd.3"} 1192672815.0
ceph_osd_op_out_bytes{ceph_daemon="osd.1"} 893430742.0
```

あとは、この/metricsをどうやって取得するかを検討します。

# 方法1: Rook/Cephのmetricsを外部にexportする

既存のrook-ceph-mgr定義を参考にして、80番ポートで稼動させてみたりします。

```bash
$ kubectl -n rook-ceph get svc rook-ceph-mgr -o yaml > metrics.service.yaml
$ vi metrics.service.yaml
$ kubectl -n rook-ceph apply -f metrics.service.yaml
```

viでは不要な.metadataの要素や.statusなどを削除しています。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: rook-ceph-metrics
  namespace: rook-ceph
spec:
  ports:
  - name: http-metrics
    port: 80
    protocol: TCP
    targetPort: 9283
  selector:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
  type: LoadBalancer
  loadBalancerIP: 192.168.1.46
```

# 方法2: rook-ceph-mgr/metricsにproxyするIngressを利用する

方法については省略。

# まとめ

前提として、K8sが稼動するネットワークは外部から切り離されていて、外部に公開するサービスは別にnginxを境界に立ち上げて管理している点と、rook-ceph-mgrの9283ポートはPrometheus用なので、そのままLoadBalancerに登録して公開しています。

/metricsが他のサービスと同じIP:Portで公開されている場合には、セキュリティ上の懸念がないか慎重に考慮するべきかなとは思いました。（この場合には限られたpathをexportするようingressを利用すると思います）

Grafana Labsには、Ceph用のJSONが登録されているので、これをDashboardにして様子をみています。

* https://grafana.com/grafana/dashboards/7056

見た目も大事ですが、この定義を確認すると、alert_rules.yamlに追加するべき監視項目が分かるので、公開されているDashboardの定義情報は監視項目の設定の参考になると思います。

以上
Noodl 2.0β版が公開されたので使ってみた！ ～チュートリアル：Mars Rover Gallery～

#概要
　2019年 Noodl Advent Calender 25日目で、**Noodl 2.0β版**が公開されました！！！
詳細はこちら。
[【Noodl開発者からクリスマスプレゼント!?】 Noodl 2.0ベータ版に参加しよう！](https://qiita.com/noodl-tokyo/items/e8d9e945c60433019026)

#特徴
 元記事から引用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/fa7d0edf-cb29-52c5-2caa-5a635652484d.png)

　Reactは使ったことないので、これから勉強していこう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7e339c50-bca8-783f-aaf9-0f6cb76867b7.png)

 今までレイアウトを変えるために別々のノードを使う必要がありましたが、Groupノードに統合されたことでノードの使い方を覚える量が減ったかも。
　imageノードにgif追加！！嬉しい！！　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7465ddbe-ae3b-538b-6eff-0649b6fe905a.png)

　Reactベースになった弊害。今後のハンズオンはこちらで行うのかな。
今までのプロジェクトを継続開発するとしたら大変だ...。新規でプロジェクト作るならver2.0がいいかも。
　
#使ってみた
###サインイン後の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/4a04c59c-8c05-460a-0086-4ba6c8edfe13.png)

###チュートリアルのMars Rover Gallery
　火星探査機の管理画面のサンプルです。

###Textノードのプロパティに変更が！！
　Paddingの設定方法が分かりやすくなっている。
今まで数値しかなかったので初見だと不明なプロパティでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7ab87213-206d-b6cf-e2da-6e8ce24c0532.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/47c17309-2a3e-038f-f804-90fc5bc43303.png)
CSSが記述できるようになっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/8c852d40-949c-9043-1605-965dcf33055e.png)

###コンポーネントの追加がしやすくなった！
　画面左上のボタンから追加できるようになっていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/544eb25a-b7ff-4c3f-e742-defa44ef02e3.png)
　追加したいコンポーネントのあるプロジェクトを選択し、その中からコンポーネントを選ぶようです。次の図では、ver1.3.1で作成したプロジェクトを選択した時の画面です。画像ファイルやフォントファイルも読み込めるみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/480efc7e-5959-6e10-d43a-3bfc41ba8667.png)

#おわりに
　次は新規プロジェクト作成からIoT連携まで試してみようと思います。
Macのunzipで "illegal byte sequence "

客先から送られてきたzipファイルが何故か展開できない。ファイル名の文字コードの問題らしい。自分の環境はMac、客先はおそらくWindows。

```
$unzip 基本設計_20191226.zip
Archive:  基本設計_20191226.zip
checkdir error:  cannot create ???{???v_20191226
                 Illegal byte sequence
                 unable to process ???{???v_20191226/???-????????_20191226_01.xlsx.
checkdir error:  cannot create ???{???v_20191226
                 Illegal byte sequence
                 unable to process ???{???v_20191226/?Q?l?_?+?+/.
checkdir error:  cannot create ???{???v_20191226
                 Illegal byte sequence
                 unable to process ???{???v_20191226/?Q?l?_?+?+/?+???T?u?V?X?e??_?T?v????.xlsx.
checkdir error:  cannot create ???{???v_20191226
                 Illegal byte sequence
                 unable to process ???{???v_20191226/?Q?l?_?+?+/?????+???Z??.xlsx.
checkdir error:  cannot create ???{???v_20191226
                 Illegal byte sequence
                 unable to process ???{???v_20191226/?+???T?u?V?X?e??_?y???{???v?z???-?C???[?W?Q20191225.xlsx.
```

ちなみにFinderからzipファイルのアイコンをダブルクリックするとこうなる。
<img width="490" alt="スクリーンショット 2019-12-27 10.03.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66940/515105ed-c958-b675-d3d9-284d0f6ad40d.png" alt="アーカイブユーティリティ エラー22 - 引数が無効です。">


unzipでなくdittoを使ったらうまく行った。dittoはMacOSX固有のコマンド。

```
$mkdir DESTINATIONDIRECTORY
$ditto -V -x -k --sequesterRsrc --rsrc 基本設計_20191226.zip DESTINATIONDIRECTORY
```

参考
https://github.com/CocoaPods/CocoaPods/issues/7711#issuecomment-386942543

dittoコマンドの説明
http://www.openspc2.org/reibun/bash/basic/018/index.html
IBM CloudアカウントでCaseを管理できる権限を付ける

# はじめに
IBM Cloudでは、質問や障害報告等のticketのことをCaseと呼びます。
アカウントのオーナーは最初からCaseを起票できますが、そうでない人に対して権限を付けるための手順をメモします。

(参照リンク) [Assigning user access for working with support cases](https://cloud.ibm.com/docs/get-support?topic=get-support-access#access)

# 手順の概要
権限は個人につけることもできますが、いったんグループを定義した方が、2人目以降の対応が楽です。
そこで、グループを定義する手順を説明します。

# グループ「case」の設定
IBM Cloudのダッシュボードから「管理」->「アクセス(IAM)」

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/6ab0e0b2-be32-8939-549a-0335f639bd4e.png' width=70%>

下の画面で
①　左のメニューから「アクセス/グループ」をクリック
②　画面右の「作成」ボタンをクリック

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/92fa3444-a3ef-bb2a-5da3-bd975ac160d6.png' width=100%>

下の「アクセス・グループの作成」パネルで、名前に「case」を入れて「作成」ボタンをクリック

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/074d55fd-fb65-b9a7-6a5c-a87c485a9f2f.png' width=50%>

「caseの管理」パネルで
①　「アクセス・ポリシー」タブをクリック
②　「アクセス権限の割り当て」ボタンをクリック
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/d5058ee6-1377-eeac-8859-76ba7a8bb7bb.png' width=90%>

下の画面で
①「アカウント管理」をクリック
②　アクセス権限は画面を下にスクロールして「Support Center」を選択

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/9896021e-ed84-fb30-818f-190f4bdf9416.png' width=80%>

「プラットフォーム・アクセス」の画面では、「Editor」にチェックを入れて「追加」ボタンをクリック

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/f6e86260-33b9-3d91-b116-5d8031d58ce0.png' width=90%>

下の画面が表示されるので、画面右の「割り当て」ボタンをクリック

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/5179179b-6e10-b15b-6a83-3e237e027f0e.png' width=90%>


下の画面になれば、アクセス権の登録に成功しています。

# グループ「case」へのユーザー割り当て
この画面で、一番左の「ユーザー」タブをクリックします。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/4760c084-ffca-0164-46c5-286164e0d0e7.png' width=90%>

下の画面になるので、「ユーザーの追加」ボタンをクリック

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/e840371a-3655-12d4-2a3b-987bc79c71c6.png' width=90%>

次の画面になるので、
①登録したいユーザーにチェックをつけ
②「グループに追加」のリンクをクリックします。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/0406294a-20b1-0971-a6a6-e1ba6a35fd4f.png' width=90%>

お疲れ様でした。これで、Case発行権の追加が完了しました。
🐘【PHP】mkdirでディレクトリ作成に失敗したのは再帰的に作成してないから

## やりたいこと

mkdirでディレクトリを新規作成したいのにできない
その上にあるディレクトリ（/test/）のパーミッションも問題なし

```hoge.php
        // /test/は作成済み

        // これは作成できる
        $saveDir = /test/hoge/;
        // なぜか作成できない！？
        $saveDir = /test/hoge/fuga;

        // 存在確認しディレクトリ作成
        if (!file_exists($saveDir)) {
            if (mkdir($saveDir, 0777)) {
                chmod($saveDir, 0777);
            }
        }
```

## やったこと

第三引数がtrueでディレクトリ再帰的作成であった
単純すぎることにつまってた...

```hoge.php
        mkdir($saveDir, 0777, true)
```
「チラ裏ですよ」@IBDesignable で UIButton の グラデーション

```swift
import UIKit

@IBDesignable class GradientButton: UIButton {
	
	@IBInspectable var firstColor: UIColor = UIColor.clear
	@IBInspectable var secondColor: UIColor = UIColor.clear
	@IBInspectable var startPoint:CGPoint = CGPoint(x: 0.0, y: 1.0)
	@IBInspectable var endPoint:CGPoint = CGPoint(x: 1.0, y:0.0)
	
	@IBInspectable var borderColor: UIColor = UIColor.clear
	@IBInspectable var borderWidth: CGFloat = 0.0
	@IBInspectable var cornerRadius: CGFloat = 0.0
	
	override func draw(_ rect: CGRect) {
		let gradient: CAGradientLayer = CAGradientLayer()
		gradient.frame = self.bounds
		let colors: [UIColor] = [firstColor, secondColor]
		gradient.colors = colors.map { $0.cgColor }
		gradient.startPoint = self.startPoint
		gradient.endPoint = self.endPoint
		self.layer.insertSublayer(gradient, at: 0)
		self.layer.cornerRadius = cornerRadius
		self.clipsToBounds = (cornerRadius > 0)
		self.layer.borderColor = borderColor.cgColor
		self.layer.borderWidth = borderWidth
		super.draw(rect)
	}
}
```
[iOS]CocoapodsでもCarthageでもない、Firebaseライブラリの導入方法

## はじめに

iOSアプリにFirebaseを導入する際、選択肢として主に`Cocoapods`と`Carthage`の２通りがありますが、それぞれ一長一短があります。
Firebaseをよく利用する私としては、どちらも使いにくいなと感じました。色々調べていく中で、公式ドキュメントにあるような第３の方法がシンプルで早かったので、その方法をまとめました。

### Cocoapods
導入が簡単だが、ビルド時間がかかる(特にFirestore)。Xcodeのビルドキャッシュもあるので、ある程度は全体的なビルド時間の短縮はありますが、それでも長いと感じます。

### Carthage
[Firebaseのリポジトリ](https://github.com/firebase/firebase-ios-sdk/blob/master/Carthage.md)をみてみるとCarthageはまだベータ版だそうです。ビルドはバイナリを使っていますが、依存関係が複雑でXcodeに導入するときに注意を払わないとなりません。


## 第３の方法
この２つ以外の方法としては、直接githubからバイナリをダウンロードして使用する方法です。[公式ページ](https://firebase.google.com/docs/ios/setup?hl=ja#frameworks)にも記載がありますが、「ダウンロードしてくれ」だけだったのでスクリプトを組むことにしました。
最新のリリースは[こちら](https://github.com/firebase/firebase-ios-sdk/releases)からダウンロードできます。スクリプトを組むことで、ダウンロードが簡単になります。

### メリット
- スクリプトを動かすだけで指定のバージョンをダウンロード
- ダウンロードしたバイナリは、それぞれのプロダクトごとにフォルダ分けされているので、Xcodeにバイナリを追加する際に迷わない
- Carthage用の追加Build Phaseはない

### デメリット
- ダウンロード時のサイズは約1GB
    - MLを使わない場合は、ダウンロード後に削除することで、ディスク上でのサイズは300MB以下
- バージョンは手動で管理する

## 導入方法
導入方法としては、ダウンロードスクリプトを作成し、プロジェクトをgithubなどからチェックアウト後に実行します。gitにスクリプトを追加しておくのが良いでしょう。

### 環境
- ターミナルが使える
- `wget`が使える(Homebrewでインストール)
- プロジェクトのトップディレクトリに`Firebase/`のディレクトリを作成するので、`.gitignore`に`/Firebase/`を追加している
    - 最初に`/`が入っていることに注意

### スクリプト
以下のスクリプトを作成し、実行します。

```
#!/bin/sh
# Firebaseをダウンロード

if [ -d "Firebase" ]; then
echo "directory Firebase/ is not empty";
exit 0;
fi

wget https://github.com/firebase/firebase-ios-sdk/releases/download/[version]/Firebase-[version].zip -O Firebase.zip
unzip Firebase.zip
rm -f Firebase.zip
rm -rf Firebase/ML*
```

`[version]`については、Firebaseの[github](https://github.com/firebase/firebase-ios-sdk/releases)から必要なバージョンを指定します。
個人的にですが、ファイル名は`firebase.sh`とし`scripts/`ディレクトリに配置しております。さらに実行権限を付加して実行しやすくしています。

### Xcodeに追加
必要なフレームワークをFirebaseに追加していきます。FirestoreやStorageなど、プロダクトごとにディレクトリに分かれているので、選びやすいかと思います。

- 必要なフレームワークを追加
    - Xcode11以降については、`Embed`を`Do not embed`に変更します。
- ターゲットのビルド設定で、Other Linker Settings に`ObjC`リンカーフラグを追加します。

（2020/04/28 追記）
最近ではFirebaseでも`xcframework`に対応しているものが増えてきました。
必要なフレームワークをを追加する際は、プロジェクトの`Frameworks`フォルダに`Drag&Drop`すると`Do not embed`やパスの設定を自動でしてくれます。Project > General > Frameworks, Librariesから追加すると、Info.plistが見つからないなどのエラーが出ていました。

### 注意点
特にチーム開発における注意点ですが、この方法ではバージョン管理はしてくれません。なので、バージョンを変更した際にはチームに通知し、それぞれで`Firebase`ディレクトリを一度削除してから上記スクリプトを実行してもらう必要があります。

## 終わりに
出来るだけシンプルにかつ早く導入できる方法を書きました。もちろんデメリットはありますが、運用でカバーできると考えております。
M5StackでAmazon FreeRTOSを使用する　３

# はじめに

[前々回](https://qiita.com/fukuebiz/items/54f765d12c084ceea392)、前回と、M5StackでAmazon FreeRTOSが動作して、アプリケーションが作れそうな気がしてきました。といっても、せっかくの画面が使えないとM5Stackを使っている意味がなくなってしまいます。

仕事で関わっている[Record Meeting](https://www.recordmeeting.jp/)という自動議事メモ作成サービスでも、操作メニューやQRコードを表示させるなど、スマートスピーカーの補助としてM5Stackが大活躍しています。

![COET Record Meeting](https://www.tis.co.jp/images/jp/news/2019/tis_news/0725_1/20190725_1_01.png)

TFTのライブラリーは、[Boris Lovosevic の ESP32_TFT_Library](https://github.com/loboris/ESP32_TFT_library) を使わせていただきましょう。

Git bashから、任意の場所にデモアプリをダウンロードします

```bash:
git clone https://github.com/fukuen/m5stack-freertos-tft --recursive
```

[前々回](https://qiita.com/fukuebiz/items/54f765d12c084ceea392)と同じモノの名前や証明書を使う場合は、証明書やヘッダーファイルを前回使用したamazon-freertosフォルダーから、今回のamazon-freertosフォルダーにコピーしてください。新しく登録する場合は、/tools/aws_config_quick_start/configure.json を修正して SetupAWS.py を実行してください。

ダウンロードしたディレクトリーに移動して、アプリケーションをビルドします。

```bash:
cd m5stack-freertos-tft
cmake -DCMAKE_TOOLCHAIN_FILE=amazon-freertos/tools/cmake/toolchains/xtensa-esp32.cmake -GNinja -S . -B build
cd build
ninja
```

ビルドが完了したら、フラッシュします。

```bash:
cd ..
idf.py flash
```

画面にはデモが表示されます。

シリアルコンソールでモニターしてみます。

```bash:
idf.py monitor
```


# 最後に

画面が使えるようになって、少しM5Stackらしくなってきました。
[Boris Lovosevic の ESP32_TFT_Library](https://github.com/loboris/ESP32_TFT_library) のサンプルでは、SNTPに接続して時刻を取得するロジックがありますが、現在のESP32用Amazon FreeRTOSはLWIPに対応していないため、SNTPのロジックをそのまま使うことができませんでした。SPIFFSの箇所も一部コメントにしてしまいました。今後書き換える予定です。
リバーシbitboard備忘録:全ての着手可能位置に対する処理を行うループ

# 概要
リバーシのbitboardを操作する際に使った処理について、備忘録のつもりで書いていきます。
「コード」「コメント」のセットだけ書きます。
実装例はJavaScriptです。
今回は着手可能位置一つ一つに対して処理をしたい場合のループの書き方です。

# コードとコメント

```JavaScript:ex.js

var bit;
/* for文におけるiのようなもの, 32bitのうち1か所のみビットが立っている
ex:0b 00000000
      00000000
      00000010
      00000000 */

var pattern0, pattern1;
/* 32bit整数, 着手可能位置にビットが立っているものとする
64bit整数が利用できる環境の場合は変数一つで良い
ex:0b 00000001
      00001000
      00000010
      00011000 */


while (pattern0) {
  bit = pattern0 & -pattern0;
  /* 動作:pattern0の立っているビットのうち、LSBを抽出する
入力例
pattern0:0b 00000001
            00001000
            00000010
            00011000
出力例
bit:     0b 00000001
            00000000
            00000000
            00000000 */

  /* bitで表現されるマスに対して処理を実行
     使用例:ソルバー(完全読みAI)に着手位置として送ると、
     各空きマスの評価値を算出できる*/

  pattern0 &= ~bit;
  /* 動作:pattern0のうち、bitと同じ位置に立っているビットを0にする
     for文におけるインクリメントに相当します
入力例
pattern0:0b 00000001
            00001000
            00000010
            00011000

bit:     0b 00000001
            00000000
            00000000
            00000000 
出力例
pattern0:0b 00000000
            00001000
            00000010
            00011000

*/


}//end of while(pattern0)

while (pattern1) {
  //pattern0と同様の処理を記述する
}//end of while(pattern1)

```
Swift の enum を拡張、複数に適用。

特定の enum に対して拡張したい場合は、それに対して extension を書けばいいです。
ただ、複数の enum に対して **使い回せる** 拡張をしたい場合の書き方がわからなくなりがちだったので、記事にしました。

例で書いているコードは実用性のない適当なものなので、流し読みで。

# 様々な enum に適応する拡張

`RawRepresentable` の extension を作成すれば良いです。
**※ RawValue が存在する enum をでなければ使用できません！**

```swift
extension RawRepresentable {

    init?(_ rawValue: RawValue?) {
        guard let rawValue = rawValue else { return nil }
        guard let value = Self.init(rawValue: rawValue) else { return nil }
        self = value
    }

    var rawValueClassName: String {
        return String(describing: type(of: self.rawValue))
    }
}
```

# 特定の RawValue の enum に適応する拡張

特定の `RawValue` 型のすべての enum に適応されます。
上記の extension に where を指定します。

```Swift
extension RawRepresentable where RawValue == Int {
    var twice: Int {
        return self.rawValue * 2
    }
}

// 下記のような enum に使用できます
enum Example: Int {}
```

# 自ら指定した enum のみ拡張させる

前述までのものでは、新たに enum を作成したとき、条件が一致すればそれも適応されてしまいます。
能動的に適応させるために protocol を用意します。

### A. RawRepresentable に準拠させる

ただ protocol を用意しただけでは色々なものに適応できてしまうので、制限をかけます。
下記 protocol を `RawValue = Int の enum` 以外に適用させるとエラーが発生します。

```swift
// RawRepresentable に準拠させることで enum(RawValueあり) のみに使用できるように (from Swift5)
// where 句で RawValue の型を制限 (変えたりとったりご自由に)
protocol EnumProtocol: RawRepresentable where RawValue == Int {}
extension EnumProtocol {
    var twice: Int {
        return self.rawValue * 2
    }
}

// 下記のように使用します
enum Example: Int, EnumProtocol {}
```

### B. extension に型制限をかける

下記のようにすることで、`EnumProtocol` 自体は class や struct など何にでも適用できますが、
`.twice` プロパティが使用できるのは `RawValue が Int か String の enum` のみです。

```swift
protocol EnumProtocol {}
extension EnumProtocol where Self: RawRepresentable, Self.RawValue == Int {
    var twice: Int {
        return self.rawValue * 2
    }
}
extension EnumProtocol where Self: RawRepresentable, Self.RawValue == String {
    var twice: String {
        return String(repeating: self.rawValue, count: 2)
    }
}
```

この辺は enum というより protocol の話なので、色々調べてみてください。

# 参考
- https://qiita.com/abouch/items/67f9def6dc2feec3e183#特定の型が準拠することができるprotocol

# 環境
- Swift 5.0