OmniAICreator/Qiita-1.07M huggingface dataset:
【numpy】0除算のwarningを回避する

自分でプログラムを書いているときに迷った部分なので、メモとして書き残しておきます。
もっと良い対処法をご存知でしたら、ご指摘をお願いします。

※環境

- Python 3.7.5
- numpy 1.18.1

##numpyの0除算

Pythonで通常の0除算を行うと`ZeroDivisionError`が発生します。

```python:
try:
    divided = 1 / 0
except ZeroDivisionError as e:
    print(f'ZeroDivisionError: {e}')

# -> ZeroDivisionError: division by zero
```

一方、numpyで0除算を行うと`RuntimeWarning`が発生しますが、処理が止まることなく結果が出力されます。

```python:
import numpy as np

divided = 1 / np.array(0)
print(devided)
# -> inf
# -> RuntimeWarning: divide by zero encountered in true_divide
```

`1 / np.array(0)`の計算結果は、numpyで無限大を表すオブジェクト`numpy.inf`になります。
警告は出してくれるけど処理が止まるわけではないので、中途半端な感じです。おそらく、「一応計算できるけど、警告を出しておくよ。どうするかは任せるよ」と使用者に委ねられているのではないでしょうか。
そこで、処理を止めたい場合と、処理を許容して警告を無視する場合にどうするか考えてみます。

##warnings.simplefilterを使う

`warnings.simplefilter`を使えば、`RuntimeWarning`を例外扱いにしたり、無視扱いにすることができます。

- 例外扱いにして処理を止めたいとき

```python:
import warnings
import numpy as np
warnings.simplefilter('error', category=RuntimeWarning)  # RuntimeWarningを例外扱いに設定

a = np.array(0)  # 0 が入ることを想定していない変数
divided = 1 / a
print(divided)

# -> RuntimeWarning: divide by zero encountered in true_divide
# divided = 1 / aで処理が止まり、print(divided)が実行されない
```

- 計算を許容して警告を無視したいとき

```python:
import warnings
import numpy as np
warnings.simplefilter('ignore', category=RuntimeWarning)  # RuntimeWarningを無視扱いに設定

a = np.array(0)  # 0 が入ってもよい変数
divided = 1 / a
print(divided)

# -> inf
# 警告が出ず、処理が続行される
```

しかし、このとき0除算以外の`RuntimeWarning`にも制御が適用されるため、特に無視する場合にはバグを補足できなくなる危険性があります。そこで、別の方法を考えます

##numpy.seteerを使う
(コメントによるご指摘を受け、`numpy.seteer`を追記しました。)
`numpy.seteer`を使えば、より細かい`Warning`の制御を設定できます。

※以下、例外扱いにするときも無視扱いにするときもほぼ同様のため、無視扱いするときのソースコードのみを記載します。

```python:
import numpy as np
np.seterr(divide='ignore')  # 0除算のRuntimeWarningのみを無視扱いとする

a = np.array(0)
divided = 1 / a
print(divided)

# -> inf
```

これで、0除算のみに制御を加えることができました。`warnings`を`import`する煩雑さも解消されています。
しかし、この場合ソースコード全体にこの制御が適用されます。できれば、制御のスコープを最小限にしたいです。
除算の前後で`numpy.seterr`を書いて制御を切り替えてもいいのですが、もっとスマートな記述を考えます。

##numpy.errstateを使う
（こちらも、コメントによるご指摘から追記した部分です）

`numpy.errstate`を使うことで、コンテキストマネージャーによる制御が可能になります。

```python:
import numpy as np

a = np.array(0) 
with np.errstate(divide='ignore'):  # withスコープ内のみ制御を適用する
    divided = 1 / a
print(divided)
# -> inf

divided = 1 / a  # 無視扱いのスコープ外なので、RuntimeWarningが発生する
# -> RuntimeWarning: divide by zero encountered in true_divide
```

こうすることで制御変更のスコープを小さくし、他の箇所の（許可していない）0除算によるバグを補足できます。

例では分かりやすさのため数値の除算を考えましたが、配列の除算も同様に制御できます。

```python:
import numpy as np

a = np.array([1, 2, 0]) 
with np.errstate(divide='ignore'):  # withスコープ内のみ制御を適用する
    divided = 1 / a
print(divided)
# -> [1.  0.5 inf]
```

1つの数値を除算する場合単純にif文を書けばいいのですが、配列の場合それが難しいので、この制御方法が活躍すると思います。
※配列の要素一つ一つをif文で判定するのはナンセンスだと思っています。可能な限り避けたいです。

##おまけ
当初、`numpy.errstate`を知らず、次のような書き方を考えました。

```python:
import numpy as np

a = np.array([1, 2, 0])
divided = np.full(len(a), np.inf)  # 全ての要素がnp.infの配列を作っておく
nonzero_indices = np.where(a != 0)[0]  # aの0以外の要素を持つindexの配列
divided[nonzero_indices] = 1 / a[nonzero_indices]  # nonzero_arrayの要素だけ除算に書き換える

print(divided)
# -> [1.  0.5 inf]
```

0除算のみの警告を回避したかったのですが、冗長感ありますね。
`numpy.errstate`のような便利メソッドを覚えて使いこなせるようになりたいです。
アクセス制限　と　クラスを構造体として扱う事

```py:1
class T(object):
    pass

t1 = T()
t1.name = 'Mike'
t1.age = 20

print(t1.name, t1.age)
```

```:1の実行結果
Mike 20
```
この様に、
クラスをデータ構造体として扱う事は可能である。

しかし、
以下の様な場合は、注意が必要だ。

```py:2
class Player:
    def __init__(self, job, weapon):
        self.job = job
        self.__weapon = weapon

    def walk(self):
        print(self.job + "は荒野を歩いていた")
        self.__attack("スライム")

    def __attack(self, enemy):
        print(self.__weapon + "で" + enemy + "を攻撃")


player1 = Player("戦士", "剣")
player1.__weapon = '斧'
print(player1.__weapon)
```

```:2の実行結果
斧
```

本来、__weaponはアクセス制限がかけられていて、
クラスの外からはアクセスできない様になっている。
なので、
print(player1.__weapon)はエラーとなるはずである。

しかしながら、
player1.__weapon = '斧'　で
新たに__weaponを生成してしまっている。

バグにつながる事があるので、
注意が必要である。
2/3 授業ノート

#先週の復習
・HTMLの正式名称
　→Hyper Text Mark-up language
・HTML5のバージョン情報を完全な形で記述
　→```<!DOCTYPE HTML>```
・文字コードをメタ情報として完全な形で記述
　→```<meta charset=”utf-8”>```
・順番の無い箇条書き
　→```<ul><li></li></ul>```
・順番付きの箇条書き
　→```<ol><li></li></ol>```
・**説明型リスト**
　→```<dl><dt></dt><dd></dd></dl>```
・属性を３つ以上記述
　→**src,name,lang,href,border,charset,content...
　☆要素と属性の違い
　　　要素：特定の文字列の前後を開始タグと終了タグで囲って意味や役割を与えるもの
　　　ex:)html,h1,head,title,base,link,meta,style,body,nav,header,footer...
　　　属性：要素に対するオプション設定のような役割を持つ
　　　ex:)src,name,lang,href,border,charset,content,id,style...**
　　　※styleは要素と属性それぞれに存在するので注意
　　　参考：HTML5&CSS3リファレンス https://htmlcss.jp/index.html

・ハイパーリンク
　→```<a href=”#”>text</a>```
・コピーライトは何要素でマークアップするか
　→small要素

#今日習ったことまとめ(教科書P39、208、214、216)
header/footer/nav要素
・header/footer要素(P216)
　→セクションのヘッダー/フッターを表す。
　　header要素の中には通常h1～h6要素が入ることを想定しているがなくても間違いではない
　　footer要素の中には通常は著作権情報、連絡先などが入る
　　1ページ内に複数のheader/footer要素が存在しても良い
・nav要素(P214)
　→WEBサイトのナビゲーションを表す
　　nav要素はoutlineとして認識される

マークアップのルール
・要素の入れ子構造(教科書P39)
　→HTML文書全体はhtml要素を最上位の親要素とする入れ子構造で成立している
　　外側にある要素：親要素、内側にある要素：子要素、さらにその内側にある要素：孫要素…となる。
　　入れ子ではなく同じ階層で並列に並んでいる要素同士：兄弟要素
　ex:)````<p><a></a></p>```→pタグ：親要素、aタグ：子要素
　ex:)```<h1></h1>```
　　  ```<h2></h2><p></p><ol><li></li></ol>```
　　  h1：親要素、h2：子要素、p、ol：孫要素(pとolは兄弟要素)


#感想
各用語の定義についての理解が浅かった。
定義はきっちり覚えなきゃですな。
要素と属性の違い、なんとなく感覚でやってた。
コードについても手癖で書いてるところが多いので、改めて知識の整理整頓をしよう。
header/footer/navについて概念や使い方は理解できていると思うんだけど、
言葉で正しく定義が出来ていない。

Photoshopが出来るってすごいアドバンテージだなとつくづく感じる。
Aiはほぼ出来ないので前倒しで覚えなきゃだけど、Photoshopないだけでだいぶ楽。
Reactで手っ取り早くタブを実現する方法【react-tabs】

#Reactで手っ取り早くタブを実現する方法
多分手っ取り早く作る方法は、他にもあると思いますが、以下の２つかなと思います。
 
 - [react-tabs](https://github.com/reactjs/react-tabs)
 - [Material-UI Tabs](https://material-ui.com/components/tabs/) 

どっちも試したのですが、**react-tabsはものすごく簡単にタブを作れた**ので紹介したいと思います。

#react-tabs
何度も言いますが、**タブをものすごく簡単に**作れます。
[デモサイト](https://reactcommunity.org/react-tabs/)はこんな感じマリオのキャラクターの説明をタブとパネルで表示してます。
![スクリーンショット 2020-02-03 20.21.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337592/79a92542-1d20-03b2-9a92-7a84e51fdc1e.png)

#react-tabs使い方
[react-tabs](https://github.com/reactjs/react-tabs)
「react-tabs」を以下のコマンドでインストールします。

```
npm install --save react-tabs
```

gitの例で載っているように、こういう風に書けば、タブができます。

```React

import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';

export default () => (
  <Tabs>
    <TabList>
      <Tab>Title 1</Tab>
      <Tab>Title 2</Tab>
    </TabList>

    <TabPanel>
      <h2>Any content 1</h2>
    </TabPanel>
    <TabPanel>
      <h2>Any content 2</h2>
    </TabPanel>
  </Tabs>
);
```

#CSSの適用
以下でreact-tabsで用意されたCSSが適用されます。
***デフォルトではCSSは適用されません。***

```React
import 'react-tabs/style/react-tabs.css';
```
Railsでの新規appのdockerでの環境構築

#dockerにての環境構築手順まとめ
忘れる前にまとめておきます
##環境構築の流れ
### 0  dockerfile gemfile gemfilelock docker-compose.ymlをセットする
docker-compose.ymlの一例

```docker-compose.yml

version: '3'
services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
      - db-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
volumes:
  db-volume:

```

###1 新しいrailsprojectの作成

```
$ docker-compose run web rails new . --force --database=mysql
```


###2 database.ymlのセッティング
※DBファイルなのでインデントに注意
####database.ymlのpasswordとhostをdocker-compose.ymlでセットしたものに合わせる
```database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: password
  host: db

development:
　　　　　　　～略～
```

###3 dockerfileからビルド

```
$ docker-compose build
```
###4 コンテナの起動

```
$ docker-compose up -d
```
###5 データベースの構築
```
$ docker-compose run web rails db:create
```
####コンテナの立ち上げしてURLにhhtp://ip:3000でrailsたちあがる
###ip 検索 
```
$ docker-machine ip default
```

###コンテナOFF 
```
$ docker-compose stop
```

##おまけ　
####dockerでERROR: Encountered errors while bringing up the project.というエラーが出た時に
```
$ docker stop $(docker ps -q)

$ docker-compose up
```
とやるとうまくいった。
参考　https://remonote.jp/docker-mac-rails-postgresql
鍵を埋め込んだ  EC2 インスタンスから取得した AMI に別の鍵を指定して起動しても以前の鍵が残るので対処します。

★AWS 備忘録シリーズ

共通ミドルウェアやアプリケーションを Amazon EC2 へ事前インストールを行い、 Amazon Machine Image(AMI)を取得するという営みをしていると思います。

その際、鍵を埋め込んで EC2 インスタンスの起動をしていると、以前の鍵の情報が残り続けることはご存知でしょうか。

特に、本番や開発といった環境ごとや EC2 に割り当てている機能ごとに鍵を分けている場合に直面しやすい問題です。

※本稿では AWS 提供の AMI に何がしかの設定を入れて、いろんな機能を設定するためのもとになる AMI を**ベース AMI** と呼称します

## 鍵が複数埋め込まれる流れ

1. ベース AMI を作成する担当者は定期的に AWS 提供の AMI に AMI 作成担当者用の鍵を使って EC2 を起動(**1本目**の鍵が埋め込まれる)
2. その EC2 インスタンスに必要なミドルウェアなどをインストール
3. AMI を取得
4. 3で取得した AMI をインフラ構築担当者に伝達
5. インフラ構築担当者はその AMI の ID と 開発のインフラ構築担当者用の鍵を使って、開発環境でシステム構築を実施(**2本目**の鍵が埋め込まれる)
6. 5で作った EC2 インスタンスから AMI を取得
7. 本番環境の AWS アカウントに対して、6で取得した AMI をコピー
8. 7でコピーした AMI で本番のインフラ構築担当者用の鍵を使ってシステム構築を実施(**3本目**の鍵が埋め込まれる)

と、このようによくある構築の流れになっていますが、このステップ8までに3本の鍵が登場し、どの鍵でもログインが行える状況になっています。
とくに、本番環境の EC2 インスタンスに対して開発環境の鍵でアクセス可能な状態はあまりよろしくない状態といえます。

この問題を対処するために、格納先を確認して、不要な鍵情報は削除します。

## 鍵のありか
結論から言ってしまうと、AWS ドキュメント「共有 Linux AMI のガイドライン」記載の[パブリックキー認証情報のインストール](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/building-shared-amis.html#public-amis-install-credentials)の**注記**にある通り、**authroized_keys** というファイルで管理されています。

```sh
sh-4.2$ sudo find / -name authorized_keys
/home/ec2-user/.ssh/authorized_keys
/root/.ssh/authorized_keys
sh-4.2$
```

この環境では2か所で管理されていることがわかります。
このファイルを開くとこれまでに埋め込んだことがある鍵の情報が記録されています。

```sh
sh-4.2$ sudo cat /home/ec2-user/.ssh/authorized_keys
ssh-rsa ****************** <key-name1>
ssh-rsa ****************** <key-name2>
ssh-rsa ****************** <key-name3>
sh-4.2$
```

## そのほかにも鍵情報はあるのか
また、前述の AWS ドキュメント共有 Linux AMI のガイドライン記載の「[SSH ホストキーペアの削除](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/building-shared-amis.html
)」にも対応します。

> パブリック AMI から派生した AMI を共有する場合は、/etc/ssh にある既存の SSH ホストキーペアを削除します。これにより、他のユーザーがお客様の AMI を使用してインスタンスを起動したときに、SSH は、新しい固有の SSH キーペアを生成するように強制されるため、セキュリティが強化され、「中間者」攻撃の可能性を減らします。
>
>システムにある次のすべてのキーファイルを削除します。
>
>(中略)
>
>次のコマンドを使用して、これらのファイルをすべて確実に削除できます。

```sh
[ec2-user ~]$ sudo shred -u /etc/ssh/*_key /etc/ssh/*_key.pub
```

## 鍵情報の削除の仕方
パターンはいろいろとありますが、取得した AMI から EC2 を起動する際に以下のコマンドをユーザーデータ内で実行するのをお勧めします。
こうすることにより、起動時に指定した鍵以外を常に削除可能です。
※ AMI の取得がコード化されているとかなら取得時に該当ファイルをクリアするのでも構いません。

```sh
shred -u /etc/ssh/*_key /etc/ssh/*_key.pub
sed -i -e '$!d' /home/ec2-user/.ssh/authorized_keys
sed -i -e '$!d' /root/.ssh/authorized_keys
```
※authorized_keys が上記二つ以外にもある場合は、そこも対処する
※ユーザーデータの場合管理者権限で動作するため、sudo は不要。

## まとめ
鍵にアクセスできる人だけが EC2 インスタンスにアクセスできるのは便利です。
しかし、このように複数可能されてしまうということを知らないと知らず知らずのうちに
トラブルの元を作り出していることもあるのでご注意ください。
Ubuntu 18.04 で `visudo` が動かない問題とそのワークアラウンド

「sudo パスワード 無し」等検索すると、`visudo` を用いて `/etc/sudoers` を編集する方法がいくつが見つかるが、私の環境 (Ubuntu 18.04) では動かなかった。
その具台的な状況と解決策のメモ。

# 問題点

`visudo` で `/etc/sudoers` を編集して、特定のコマンドだけパスワードなしで `sudo` できるよう試みた。
しかし、どうもうまく行かない。

具体的には例えば

```bash
$ sudo visudo
```

```:/etc/sudoers
...

%sudo  ALL=(ALL:ALL) ALL
kobalt ALL=(ALL) NOPASSWD: /usr/bin/whoami

...
```

としても

```bash
$ sudo whoami
[sudo] password for kobalt:
```

とパスワードを要求されてしまう。

# 解決策

`visudo` は使わずに `/etc/sudoers.d/` 下にファイルを作りそこに追加したい設定を記述するとよい。

```bash
$ cd /etc/sudoers.d
$ sudo vim free_whoami
```

```:/etc/sudoers.d/free_whoami
kobalt ALL=(ALL) NOPASSWD: /usr/bin/whoami
```

すると、

```bash
$ sudo whoami
root  # パスワードが要求されない
```

# 最後に

ちなみに、[xkeysnail](https://qiita.com/miy4/items/dd0e2aec388138f803c5) というキーリマッパを起動時に自動で立ち上がるようにする作業の最中にこの問題にぶつかりました。

これで Ubuntu でもホームポジションから動かないままカーソルの移動ができそうです。
【アプリ新規作成】bundle installができない！【解決】

どうも、おささです。
エラーから始まる初投稿( ﾟ∀ﾟ)･∵. ｸﾞﾊｯ!!

事の発端は、
railsで新規アプリを作成しようと、
ターミナルから「rails new」をした後に起きたある事件。



　　　　　　「　Could not locate Gemfile　」



・・・はて？

先月プログラミングを始めた私には難易度の高い問題だった。


どうやら
「ジェムファイルがそのコマンドを実行させているフォルダにありません」
ということらしい。

元々同じアプリは作っていて、復習のために再度作り始めようとした時、
別のエラーが出たので一度全部削除をした矢先の出来事だった。

「さっき消したのがまずかったんだろうか・・・」
「もう一度ゴミ箱から復活させれば戻るだろうか・・・」

・・・

戻らない。

記事を色々調べた結果、


　　　「　Gemファイルをインストールする階層が違った　」


ターミナルで、pwdを入力し確認したつもりだった。
”つもり”だった。
きっと、そこでつまずくと思わず、気を抜いていたんだろうと思う。

階層を一つ下にしたところ、無事インストールされました！！

助かりました。これで復習ができます。

ってなわけで、初投稿は
「bundle installのエラーを解決してみた」
でした。

でわ、また！

参照：http://tacosvilledge.hatenablog.com/entry/2015/08/02/191301
初心者によるプログラミング学習ログ 228日目

#100日チャレンジの228日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

228日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>228日目<br>・架空のwebサイトコーディング<br>・udemyでcss+javascript<br>・youtubeでjavascriptアプリ模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1224060559231897601?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Azure CLIで操作する（Cognitive Search編）

## Azure CLIを利用してスケールアウトさせる。
### Azure CLIとは
Windows、MacOS、Linuxなどクロスプラットフォームで利用出来るAzureをコマンドラインで操作出来るツールです。
ダウロードは下記のページから
https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli?view=azure-cli-latest

Azure Cognitive Search は、旧称Azure Searchとなります。
https://docs.microsoft.com/ja-jp/azure/search/search-what-is-azure-search

1. Azureにログイン
az login
ログインするとサブスクリプションIDなどの情報が表示されます。
※プロキシサーバがある環境では、必要に応じてプロキシを環境変数に設定して下さい。
一時的な場合は、下記のコマンドを入力
set HTTP_PROXY=http://username:password@proxy.contoso.com:8000
set HTTPS_PROXY=http://username:password@proxy.contoso.com:800

2. Azure CLIのバージョンを確認する。
az --version
![cli2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/86d0fd67-bb3d-b67d-c0e3-7de7c4c0aed7.png)

3. 現状のプランサイズを確認する。
az search service show -g リソースグループ名 -n Searchサービス名
![search2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/853fa2b0-4cee-6941-5b61-f8ba943c839e.png)
Azure Portalでも確認してみます。
![search1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/b9e83d57-41f6-5fcc-b665-b6e569e347ee.png)
レプリカが1、パーティションが1の1の1ユニットであることが分かります。

4. Azure Cognitive Searchをスケールアウトさせる。
実行結果が返ってくるまでに30分ほどかかりました。
余計なことをしたので「ジョブを終了しますか」と問われたので「N」を選択します。
ステータスが「running」となっており正常にスケールアウト出来たことを確認出来ます。
![search3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/9b7e1f44-c699-6d45-d79c-db28cfc8ea61.png)
Azure Portalでも確認してみます。
![search4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270447/95bda00d-d456-b069-e80e-8f44168f4b56.png)

5. その他
Azure Cognitive Search は3つ以上のレプリカを指定することでSLA99.9を得ることが出来ます。
詳細は下記をご確認下さい。
https://azure.microsoft.com/ja-jp/support/legal/sla/search/v1_0/

Azure Cognitive Search のスケールアウト可能な最大サイズは価格レベルにより異なります。
詳細は下記をご確認下さい。
スケールアウトの制限は「レプリカ数」×「パーティション数」となります。
https://azure.microsoft.com/ja-jp/pricing/details/search/
headlessブラウザを利用したcui環境での結合テストの自動化（Selenium IDE＋UAとProxy指定有）

# 目標
以下の要件を満たす環境を構築しました。
- cui環境での実行（JenkinsなどのCI環境で定期実行を目指したいため）
- User Agent指定可
- Proxy指定可

# 環境構築手順
１. Chromeの拡張機能である「[Selenium IDE](https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd?hl=ja)」をインストールします。

２. Selenium IDEを起動し、適当にテストケースを作成します。この時作成するテストケースはモバイルページを検証するようなテストケースにします。

３. 適当なファイル名（例：sample.ide）でテストケースを保存します。

４. 以下のモジュールをインストールします。
・selenium-side-runner
・chromedriver

- [インストール手順参考](https://www.seleniumhq.org/selenium-ide/docs/en/introduction/command-line-runner/)

```bash
$ brew install node
$ npm install -g selenium-side-runner
$ npm install -g chromedriver
```

５. selenium-side-runnerのオプションに、Chromeの起動オプションを指定し、テストケースを実行します。

- 実行するコマンド例

```bash
selenium-side-runner -c "goog:chromeOptions.args=[--headless,--nogpu,--proxy-server=http://proxy-host:8080,--user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1] browserName=chrome" sample.side
```


- 指定したChromeの起動オプションについて

| オプション | 説明 |
|:-----------------|:-----------------|
| --headless | Chromeをヘッドレスモードで起動します |
| --nogpu | GPUの利用をOFF |
| --proxy-server | プロキシサーバを指定（例：http://proxy-host:8080） |
| --user-agent | UAを指定（例：Mozilla/5.0 (iPhone; CPU iPhone OS 11_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1） |

＊ [公式マニュアルに記載のProxy指定方法](https://www.seleniumhq.org/selenium-ide/docs/en/introduction/command-line-runner/#using-a-proxy-server)では上手くProxyを指定できなかったため、今回はChromeの起動オプションにProxyを指定して要件を実現しました。
glm で quaternion を使うときはコンポーネントの順番に気を付ける

## glm

コンポーネントの順番に気をつかないと, 4 要素配列から `glm::quat` を作ったり, その逆でハマります.

glm は以前までは wxyz 順でコンポーネントを扱っていたような気がしますが, 最近(少なくとも 0.9.9.6 から?) では xyzw になりました.

とりあえず 0.9.9.7 を使い, xyzw 順で扱うようにすればよいです.

https://github.com/g-truc/glm/releases/tag/0.9.9.7

既存コードとの互換性用などには,

`GLM_FORCE_QUAT_DATA_WXYZ` が導入されています.

Quaternion order DOES matter, can we please have a macro for the order? #983
https://github.com/g-truc/glm/issues/983

Quaternion storage order inconsistent #916
https://github.com/g-truc/glm/issues/916

Quaternion element order #942
https://github.com/g-truc/glm/issues/942

## glTF

glTF では `[x, y, z, w]` の配列で定義されています.

https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#coordinate-system-and-units

したがって glm 0.9.9.7 を使う場合は特にデータ変換は不要です.

### おまけ

glm, feature rich で便利な気はしますが(e.g. fmtlib と組み合わせて `glm::to_string(x)` で行列やらの表示とか), ドキュメントわかりずらい, API わかりずらい, 以外とバグ多めでなかなか困った子です.

代替案として, linalg

https://github.com/sgorsten/linalg

や HandmadeMath 

https://github.com/HandmadeMath/Handmade-Math

が挙げられます. ちょっとしたベクトル, quaternion と 4x4 行列まででよければこれらの利用も検討してみましょう.
【やってみた】Vottについて

#Vottとは
アノテーションツールのことである。アノテーションとは機械学習に何かを学習させるときに訓練データが必要になってくるが、その訓練データの作成を行うことである。要するに、例えば画像認識だったら、画像(x)だけを用意してもタグ(y)がなきゃ話になんない。入力xがあったとしても、吐き出すものyが最初から認知されていなかったらどうしようもないということ、なのでアノテーションを行う。

それを手助けしてくれるのがアノテーションツールである。今回は数あるうちのVottというMicrosoftから出ているアノテーションツールを試し、簡単にお纏めしてくよーん。

# 開いたらまずはプラグのマーク！
画面左のプラグのマークをクリック。ここではデータソースの指定を行う。つまりどのデータを使うかということで、そのデータのディレクトリごと指定してあげる。

詳しくは

- なんのデータソースを入れるか（さっき作ってあげたやつもある）
- ローカルファイルシステムの指定
- 画像ファイルのフォルダを選択



# 次にホームボタンで新しくプロジェクトを作ろう！
どのデータを用いるか、Vottに認識させてあげたら、今度はそのプロジェクトの作成へと移る。ホームマークを押して、一番左のフォルダプラスマークをクリ。

ここでは、

- プロジェクトの名前
- データソースの指定
- 書き出し先の登録

を決める。
TypeError: Can't mix strings and bytes in path components

#問題
```python
with open('LICENSE.txt', 'rb') as f:
  s = [os.path.join('a', line.strip()) for line in f]

#error
#TypeError: Can't mix strings and bytes in path components
```

#解決
```python
with open('LICENSE.txt', 'rb') as f:
  s = [os.path.join(b'a', line.strip()) for line in f]
```

#原因
バイト列とstrを混同させていた。バイト列にそろえた。
Goで受け取ったhttp.Requestパラメータを全て取得する

# パラメータ名を指定して取得する場合

http.RequestからGET/POSTされたパラメータを取得する際に、キー名を指定する場合は`FormValue()`を用いることができます。

```golang:main.go
package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/sample1", Sample1)
	http.ListenAndServe(":8080", nil)
}

// Sample1 ハンドラ
func Sample1(w http.ResponseWriter, r *http.Request) {
	fmt.Println("hoge", r.FormValue("hoge"))
	fmt.Println("foo", r.FormValue("foo"))
}
```

下記のようにリクエストを送信するとデータが取得できていることが分かります。

```zsh
$ curl --location --request GET 'http://localhost:8080/?hoge=aaa&foo=bbb'
```

```:標準出力
hoge aaa
foo bbb
```
# パラメータを全て取得する場合

ミドルウェア等を作成する場合、キー名によって処理を変えたいこともあります。
どのようなパラメータがリクエストされてくるのかが分からないため、事前にパラメータを指定できません。
そのため、処理を行おうとすると全てのパラメータを取得する必要があります。

その場合は`ParseForm()`を行うことでデータを`Form`から取得できるようになります。

```go:main.go
// 前略

// Sample2 ハンドラ
func Sample2(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		fmt.Println("errorだよ")
	}

	for k, v := range r.Form {
		fmt.Printf("%v : %v\n", k, v)
	}
}
```

```:標準出力
hoge : [aaa]
foo : [bbb]
```


なお、画像等を扱う際は`multipart/form-data`を扱うと思いますが、その際も`ParseForm()`を行うことで`MultipartForm`から取得が可能です。

```go:main.go
// 前略

// Sample3 ハンドラ
func Sample3(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseMultipartForm(32 << 20); err != nil {
		fmt.Println("errorだよ")
	}

	mf := r.MultipartForm

	// 通常のリクエスト
	for k, v := range mf.Value {
		fmt.Printf("%v : %v", k, v)
	}

	// ファイル等バイナリのリクエスト
	for k, v := range mf.Value {
		fmt.Printf("%v : %v", k, v)
	}
}
```

```zsh:POSTサンプル
curl --location --request POST 'http://localhost:8080/sample3' \
--header 'Content-Type: multipart/form-data; boundary=--------------------------897380512801959426741215' \
--form 'image_file=@/path/to/file/sample_image.png' \
--form 'hoge=aaa' \
--form 'foo=bbb'
```

```:標準出力
hoge : [aaa]
foo : [bbb]
image_file : 0 : sample_image.png
image_file : 0 : map[Content-Disposition:[form-data; name="image_file"; filename="sample_image.png"] Content-Type:[image/png]]
image_file : 0 : 19487
```

# サンプルコード
コードは下記にも置いておきます。
https://github.com/ayatothos/go-samples/tree/master/form_params
【bitbucket】git remote add origin git@~したのに fatal: remote origin already exists. というメッセージが出る場合の解決法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568461/35eac2f4-4140-d937-bfd5-156ada70f5df.png)
この画面から進まない。


## 作業順序

git remote rm originでoriginを削除し、再度originを登録すればOKです。


```
$ git remote rm origin
$ git remote add origin git@bitbucket.org:ユーザ名/リポジトリ名.git
$ git push -u origin master
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568461/1248bf6e-b635-0057-e651-e2f9bc5a2212.png)
この画面が表示されました。
ネストしているstruct内のすべての値を取得し、文字列連結する

# 目的
ネストしているstruct内のすべての値を取得し、文字列連結したい

# ユースケース
連結した文字列からハッシュを生成し、リクエストパラメータのチェックサムに使う

# コード
```
package main

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
)

// reflect.Value を返す関数
func toReflectValue(i interface{}) (reflect.Value, bool) {
	rv, ok := i.(reflect.Value)
	if !ok {
		rv = reflect.ValueOf(i)
	}

	switch rv.Kind() {
	case reflect.Ptr:
		// ポインタ以外になるまで reflect.Indirect する
		return toReflectValue(reflect.Indirect(rv))
	case reflect.Struct:
		return rv, true
	}
	// 構造体以外
	return rv, false
}

func recursive(depth int, rv reflect.Value, str *bytes.Buffer) {
	typ := rv.Type()

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)
		kind := field.Type.Kind()
		value := rv.FieldByName(field.Name)
		if kind != reflect.Ptr {
			if kind == reflect.Struct {
				recursive(depth+1, value, str)
			} else {
				switch kind.String() {
				case "int":
					s := value.Interface().(int)
					str.WriteString(strconv.Itoa(s))
				case "string":
					str.WriteString(value.String())
				}

			}
		}
	}
}

func main() {
	type Address struct {
		name string
	}

	type User struct {
		Name    string
		Age     int
		Address Address
	}

	user := User{"suzuki", 18, Address{"Tokyo"}}
	rv, _ := toReflectValue(user)
	str := bytes.Buffer{}
	recursive(0, rv, &str)
	fmt.Println(str.String())
}
```

# 結果

```
suzuki18Tokyo
```

# その他
他の型への対応は、`switch kind.String()`に追加する

# 参考
下記のコードに対して修正を加えました。感謝 :pray: :pray: :pray: 
https://golang.hateblo.jp/entry/2018/11/10/083000
キーボードの高さを取得する

よく使うけど変換の仕方を忘れがちなので、備忘録として残しておく。

```swift
@objc func keyboardDidChangeFrame(_ note: Notification) {
        
        guard
            let value: Any = note.userInfo?[UIResponder.keyboardFrameEndUserInfoKey],
            let frameValue: NSValue = value as? NSValue else
        { return }
        let frame: CGRect = frameValue.cgRectValue
        // https://developer.apple.com/documentation/uikit/uicoordinatespace/1622661-convert
        let convertedFrame: CGRect = view.convert(frameEnd, from: UIScreen.main.coordinateSpace)
        // https://developer.apple.com/documentation/coregraphics/cgrect/1455346-intersection
        let height: CGFloat = view.frame.intersection(convertedFrame).height
        
        // スクロールビューのインセットを調整したりなど
    }
```

# 参考
https://developer.apple.com/videos/play/wwdc2017/242/
GitHub Actions の無料枠を使いきった場合

## 使用料金

GitHub Actions の使用料金はパブリックリポジトリでは無料ですが、プライベートリポジトリは無料枠＋従量課金です。

[GitHub Actionsの支払いについて
](https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)

無料枠に関してはProアカウントかどうかで時間が異なります。

|Free  |Pro  |
|---|---|
|2000分/月  |3000分/月  |

※OSがWindowsの場合`2倍`、macOSの場合`10倍`時間が消費されます。

## 使いきった場合

プライベートリポジトリのワークフローは実行されなくなります。

![202002031848.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264159/ac2fbe92-5706-a6ee-fa37-1236dcd0da51.png)

```
The job was not started because the spending limit for Actions and Packages has been exceeded.
```

また、メール及びGitHubのBillingページで使いきった旨が通知されます。

※ワークフローでエラーをSlackに通知する設定している場合、ワークフローが実行されないためSlackへの通知はされません。

![202002031847.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264159/f5228653-fb35-ee8d-2bed-9132d7d9e4df.png)

## 追加購入
無料枠を超えた利用分はLinuxは`$0.008/分`、Windowsは`$0.016/分`、macOSは`$0.08/分`の従量課金になります。
勝手に追加購入はされないので、追加利用したい場合はGitHubのBillingページから設定します。

1. `Update spending limit ボタン` や `Cost management タブ` などから上限設定に移動
![202002031851.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264159/aca77d23-970b-6d0d-57a7-92cb66191e5c.png)

1. 上限金額を設定するか無制限に使用するかを設定

※この設定は GitHub Actions だけでなく GitHub Packages 及び Storage for Actions and Packages と共通のようです。

## Proアカウントにしたほうがお得？
Proアカウントは`$4/月`です。
FreeアカウントからProアカウントにアップグレードすることで増える無料枠は `3000分/月 - 2000分/月 = 1000分/月`
一方Freeアカウントのまま`$4`で使用できるのは `$4 / $0.008/分 = 500分` です。
したがって`500分`以上追加で使用する場合はProアカウントにしたほうがお得なようです。

## 無料枠がリセットされない場合
![limit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264159/c91145dd-4c13-49b3-c761-7eec2503ae19.png)
無料枠がリセットされない現象に一度遭遇したことがありました。
支払い方法を変更した後に発生したのでそれが原因だったのかはわかりませんが、[サポート](https://support.github.com/contact)に連絡してしばらくしたら正常に戻りました。
JavascriptでCSV出力

# 多次元配列からBOM付きUTF-8で出力

```javascript
 export const downloadCSV = (rows, fileName = 'download') => { 
     const bom = new Uint8Array([0xEF, 0xBB, 0xBF]) 
     const blob = new Blob([ bom, rows.join('\r\n') ], { type : 'text/csv' }) 
     const element = document.createElement('a') 
     const objectUrl = window.URL.createObjectURL(blob)
     element.href = objectUrl 
     element.setAttribute('download', fileName); 
     document.body.appendChild(element) 
     element.click() 
     window.URL.revokeObjectURL(objectUrl) 
     document.body.removeChild(element) 
 } 
```

## 利用例

```javascript

downloadCSV([[11, 12, 13], [21, 22, 23]], 'csvTest')
```

# APIから受け取ったCSVデータを出力

```javascript
export const downloadCSV = (csv, fileName = 'download') => {
    const blob = new Blob([csv], { type : 'text/csv' })
    const element = document.createElement('a')
    const objectUrl = window.URL.createObjectURL(blob)
    element.href = objectUrl
    element.setAttribute('download', fileName);
    document.body.appendChild(element)
    element.click()
    window.URL.revokeObjectURL(objectUrl)
    document.body.removeChild(element)
} 
```

## 利用例

```javascript
axios.get('/get/csv', { responseType: 'blob' })
    .then(resp => {
        downloadCSV(resp.data, 'csvTest')
    })
```

※ `responseType: 'blob'` を指定しない場合、文字コードが `SHIFT-JIS` などのデータの時に文字化けする。
php7.4-apacheイメージのビルド時に "No package 'oniguruma' found" エラーが発生する際の対処

### 経緯
既存のDocker+php環境を、php7.4にアップグレードすることになりました。

↓元のDockerfile

```
FROM php:7.3-apache
COPY ./etc/docker/app/conf/*.conf /etc/apache2/sites-available/

RUN apt-get update && apt-get install -y vim zip unzip

RUN set -ex apk --no-cache add postgresql-dev libpq-dev
RUN apt-get install -y libpq-dev \
    && docker-php-ext-install pdo pdo_pgsql pgsql mbstring

RUN pecl install xdebug && \
    docker-php-ext-enable xdebug
COPY ./etc/docker/app/php_conf/xdebug.ini /usr/local/etc/php/conf.d/

RUN a2enmod rewrite

EXPOSE 80

CMD ["apache2-foreground"]
```


ここからimageの部分を `php:7.4-apache` に書き換えてビルドしたところ、以下のエラーが出ました。

```
configure: error: Package requirements (oniguruma) were not met:

No package 'oniguruma' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables ONIG_CFLAGS
and ONIG_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
```

###解決方法
https://github.com/docker-library/php/issues/880
こちらによると、 `mbstring` に替わり `libonig-dev` というパッケージを追加する必要があるそう。
以下のように書き換えます。

```
FROM php:7.4-apache
COPY ./etc/docker/app/conf/*.conf /etc/apache2/sites-available/

RUN apt-get update && apt-get install -y vim zip unzip

RUN set -ex apk --no-cache add postgresql-dev libpq-dev
RUN apt-get install -y libpq-dev \
    libonig-dev \ # 追加
    && docker-php-ext-install pdo pdo_pgsql pgsql # mbstringは削除

RUN pecl install xdebug && \
    docker-php-ext-enable xdebug
COPY ./etc/docker/app/php_conf/xdebug.ini /usr/local/etc/php/conf.d/

RUN a2enmod rewrite

EXPOSE 80

CMD ["apache2-foreground"]
```

これで正常にビルドが完了しました。
【GAS】スプレッドシートに書いたイベントをカレンダーに登録させる

# 経緯
個人ごとの勤怠時間をGoogleカレンダーに登録しているが、かなりめんどくさい。
繰り返しができればいいが、シフト制なので曜日や時間に規則性がないため
ポチポチ入力するのがかなりキツイです、、、

# やること

・Googleスプレッドシートに勤怠時間を入力させる
・GoogleAppsScript（gas)で、指定された日をカレンダーに入力

# 準備

### スプレッドシート
こんなかんじのもの
![スプレッドシート.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361890/885f984e-f9be-5220-c9f3-ca0385004894.jpeg)

### カレンダーIDの確認
PC版Googleカレンダーから
歯車アイコン→「設定」→「マイカレンダーの設定」から対象のカレンダーをクリック

こんな感じのものです
![calendarID.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361890/e3ae132e-a069-cad0-f22f-6552b3896652.jpeg)

# コード

```GoogleAppsScript
//シート名
var sheetNameArray = ['ぼく','わたし','あなた'];
var DATE=new Date();
//今月
var NOW=new Date(DATE.getFullYear(), DATE.getMonth() + 1 ,0);
//来月
var NEXT=new Date(NOW.getFullYear(), NOW.getMonth() + 2 ,0);
//カレンダー
var CALENDAR = CalendarApp.getCalendarById('xxx@group.calendar.google.com');  
//「今月」の行
var NOWCOLUMN = 2;
//「来月」の行
var NEXTCOLUMN = 5;
//「日付」列の先頭
var DAYROWFIRST = 3;
var sheet = '';

//指定月のイベントをまとめて削除
function deleteEvents(dateColumn){
  var date = sheet.getRange(2, dateColumn).getValue() + '/01 00:00:00';
  var startDate = new Date(date);
  var endDate = new Date(date);
  endDate.setMonth(endDate.getMonth() + 1);
  var events = CALENDAR.getEvents(startDate, endDate, {search: sheet.getName()});

  /* イベントの数だけ繰り返し */
  for (var i = 0; i < events.length; i++){
    events[i].deleteEvent();
    Logger.log("[deleteEvent]" + events[i].getStartTime() + events[i].getTitle());
  }
}

//指定月のイベントをまとめて作成
function createEvents(dateColumn){
  var row = DAYROWFIRST;
  var dateSeed = sheet.getRange(2, dateColumn).getValue();
  
  /* 日付の数だけ繰り返し */
  while( sheet.getRange(row, dateColumn).getValue() ){
    if( !sheet.getRange(row, dateColumn + 1).getValue() ){
//      Logger.log('none');
      row++;
      continue;
    }
    var date = dateSeed + '/' + sheet.getRange(row, dateColumn).getValue();
    var startDate = new Date( date + ' ' + sheet.getRange(row, dateColumn + 1).getValue());
    var endDate = new Date( date + ' ' + sheet.getRange(row, dateColumn + 2).getValue());
    
    CALENDAR.createEvent(sheet.getName(), new Date(startDate), new Date(endDate));
    Logger.log("[createEvent]" + sheet.getName() + "," + new Date(startDate) + "," + new Date(endDate) + ")");
    row++;
  }
}

//イベントメイン処理
function setCalendar(){
  for (var i = 0; i < sheetNameArray.length; i++){
    sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetNameArray[i]);
    
    deleteEvents(NOWCOLUMN);
    deleteEvents(NEXTCOLUMN);
    createEvents(NOWCOLUMN);
    createEvents(NEXTCOLUMN);
  }
}
```

# 結果
こうなります
![ぼく.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361890/f507f6e2-f982-b7a5-612c-334584d4e7f3.jpeg)
![わたし.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361890/92f50d57-a49a-ecfb-8239-30343176bc7a.jpeg)
![あなた.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361890/44eaa46c-3b61-0033-695a-72b63021ca97.jpeg)
HTMLメールで画像を載せる [rails][初心者]

#HTMLメールに画像を載せたい

####すでにメール送信はできるけど、画像がうまく表示されない
これを記述する:point_down_tone2:

```mailer.rb
attachments.inline['画像file名'] = File.read('app/assets/images/画像file名')
```

おそらくここの部分`'app/assets/images/画像file名'`
はpublic配下とかでも大丈夫だと思います。

```mailer.rb

def send_when_creater(user)
    attachments.inline['vegetable.png'] = File.read('app/assets/images/vegetable.png')
    @user = user
    mail to: user.email,subject: "こんにちは"
  end
end
```

###mailer view
画像を表示したいところに記述しましょう:point_down_tone2:

```html.erb
省略
<body>
  <%= image_tag attachments['vegetable.png'].url, alt: 'Vegetable' %>
</body>
```

##メール結果

![こんにちは_-_ryosukedapyon_gmail_com_-_Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384804/e585c1e1-7904-a14d-c512-df98bb0884b3.png)

うまく表示できました。
いろいろな記事を参考にしましたが、railsガイドを参考にしています。
もっと綺麗な方法やhelperを使ったやり方もあるみたいなので、参考にしたいと思いました。
【Xamarin.iOS】NSInternalInconsistencyExceptionが解消しない

## はじめに
Xamarinで簡単なiOSアプリを実装中、これまで普通に起動していたのに、突然表記のエラーが発生し解消しなくなってしまった。

```
Unhandled Exception:

Foundation.MonoTouchException: Objective-C exception thrown.  Name: NSInternalInconsistencyException Reason: Application windows are expected to have a root view controller at the end of application launch
Native stack trace:
	0   CoreFoundation                      0x00000001a9bbc9a0 DA838E75-6B30-360E-9661-C4800A7E1BF6 + 1227168
	1   libobjc.A.dylib                     0x00000001a98e50a4 objc_exception_throw + 56
	2   CoreFoundation                      0x00000001a9abed1c DA838E75-6B30-360E-9661-C4800A7E1BF6 + 187676
	3   Foundation                          0x00000001a9ef48f4 0DF2911E-80CB-3289-8A1E-ED0913D55A12 + 555252
	4   UIKitCore                           0x00000001adbc8728 82C949DD-37F6-35F7-B3EF-62BA342F6BF5 + 10413864
	5   UIKitCore                           0x00000001ad3a4810 82C949DD-37F6-35F7-B3EF-62BA342F6BF5 + 1878032
(略)
```

## 動作確認環境
[開発環境]
・Windows10
・Visual Studio2019 Ver16.1.1
・Xamarin 16.1.0.542
・Xamarin.iOS and Xamarin.Mac SDK   12.10.0.153
[端末]
・iOS 13.1.2

## 対応方法
同様のエラーが発生している記事を参考に、WindowのrootViewControllerまわりの実装をチェックしてみましたが、なかなかエラー解消せず…。

（参考）[iOS9でアプリが起動直後にクラッシュする場合の回避方法](https://qiita.com/peromasamune/items/716de6da66dd31faeba8)

そもそも、Viewまわりには一切変更を加えていないタイミングで発生したのでムム？？と思い切り分けしていった結果、結局**ViewModel側の実装で、Null参照が起きていた**という超しょうもないミスが原因でした。

root view controllerうんぬん…というエラーメッセージに安易に反応して、Viewまわりばかり調査してしまいましたが、内部実装のミスでも今回のような例外が発生するケースもあるみたいです。。。
未経験者による転職（就職）メモ　#1 SES

#はじめに
最近未経験からエンジニアになりたい方が多くいますが、私がSES企業の面接を受けて感じたことをまとめましたので、頭の片隅にでも置いていただければ幸いです
ナンバリングしていますが、続く…のかなぁ？

#目次
- SES企業に面接に行った時に採用担当に聞いて欲しいこと
- さいごに


##SES企業に面接に行った時に採用担当に聞いて欲しいこと
結論から書きます

###私は未経験ですが、経歴書はどのように書かれますか？

これを聞いてください
面談に行く前とかでもいいと思います
この時に、以下のような回答が返ってきたら、一度考えて欲しいと思います
先に行っておきますが、全ての未経験採用SES企業がそうではありませんので悪しからず
私が何社か受けさせていただいた企業さんは、例えば
「自社サービスがあるから、それに半年間携わったことにする」
そうです

これは経歴詐称になるので、「詐欺」になります
これに関しての解釈はみなさんにお任せします

「未経験なんやからそんなん普通やろ」
「自社サービスだから外からはわからんし、半年の経験やったらあってないようなもんやから別にいいやろ」
「詐欺なんて許せない、ムキー！！」

ここいらの意見はご自由にどうぞ

ただ、受けさせていただいた企業さんの印象はストイックという面では非常にいいんです
あと、環境とか

だから、
「そんな小さなことはいいから、俺は早くゴリゴリコード書きたいんだ！！」
とか
「盛った分仕事せなあかんのはしんどいけど、1年くらいしたら慣れるやろ」
とか、頑張れる方はご自由にどうぞって感じです

なので、一度立ち止まって、それでいいかどうかを考えて欲しいです
「入るな」とか「やめとけ」とは言いません、あなたの人生はあなただけのものです
私がとやかく言うことではありません

その企業さん紹介して欲しい方いたら、ご連絡いただければ会社名教えますよ（嘘）

#さいごに
全ての未経験採用SES企業がそうではありません
このことはもう一度言っておきます
たまたま私の当たったSES企業のほとんどがそうだっただけの話です
[Rails<=>PHP] nl2br は simple_format

# タイトルで書きたいことはほぼ全て終わった
あとは詮方無いこと、うだうだとかいてみる。

#### `simple_format`は`nl2br`より複雑。
1. デフォルトで`<p>`が入る
2. `simple_format(text, {}, wrapper_tag: 'div')`でタグを変更することはできるが、消せない。
3. `\n`が2行以上続くと`<p>`が挿入され、文章が区切られる。

##PHPの関数`nl2br`はRailsだと`simple_format`。

```rb:hoge.rb
motoko = "根拠ですって？\nそう囁くのよ、私のゴーストが""
simple_format(motoko)
// 出力結果 =>
// <p>根拠ですって？<br />
//そう囁くのよ、私のゴーストが</p>
```

不満があるので、耳と目を閉じ、口をつぐんで孤独に暮らそうと思います。
enum属性をもつカラムの値を取得する [初心者][rails]

##enum属性をもつカラムの値を取得したい

モデルに記述するこういうのです:point_down_tone2:

```ruby
enum status: {
    error: 0,
    shipping: 1,
    completed: 2,
  }
```

errorはなんらかの不具合、shippingは配送中、completedは配送完了

ちなみにstatusカラムの `error: 0` は
errorが`key`
0が`value`

##key取得方法
上記のようなstautsカラムをもつOrderモデルで

```ruby
Order.shipping?
```

で取得可能
enumの便利なメソッドです:thumbsup_tone2:

###間違えた例

```ruby
Order.status.shipping?
```

と記述してしまいエラーになっていました
【Kotlin】KClass同士でSuperclass/Subclassを判定する

# やること
以下のような関係のクラスが有ったとき、`Impl`が`Abstract`や`Interface`を継承していることを判定します。

```kotlin
abstract class Abstract {
    abstract val hoge: Int
}

interface Interface {
    abstract val hoge: Int
}

class Impl : Abstract(), Interface {
    override val hoge: Int = 1
}
```

# やり方
以下のように、`isSubclassOf`を使えばできます。
逆方向の判定を行う`isSuperclassOf`という関数も有ります。

```kotlin
val isSubclass: Boolean = Impl::class.isSubclassOf(Interface::class)
```

## 補足
以下のように同じクラス同士で比較した場合、`isSubclassOf`/`isSuperclassOf`は両方`true`になります。

```kotlin
val isSubclass: Boolean = Impl::class.isSubclassOf(Impl::class)
```
ExcelVBAでツール開発

データ抽出・加工の際に、ExcelVBAツールを作成させていただくことがあり、その時に学習した豆知識をメモしておきたいと思います。

## １）Excelが重く、データ編集や関数計算の処理時間が長い問題
以下のサイトが結構参考になりました。
https://www.fastclassinfo.com/entry/excel_work_slow
この知識点が知らなかったです。
・VBAのセル.Selectを使うのを避けるべき。必要ない限り書かないこと。
・書式やフォントなどは設定種類が豊富であればあるほど、Excel実行が重くなる。

## ２）VBA開発中に、すぐ使えるコード
https://ateitexe.com/code-snippet/
http://www.max.hi-ho.ne.jp/happy/YNxv20002.html

## ３）ほかのVBAコード問題
■　コピーペースト
Destinationキーワードを使った方が効率よい。(※クリップボードを使わないため、メモリが食わないようです。）
```
Range("A1").CurrentRegion.Copy Destination:=Sheets("Sheet2").Range("A1")
```
■ 複数シートに対する処理（配列を使用）
```
ReDim My_SheetName(0)
For Each MySheet In ThisWorkbook.Worksheets
　　　If MySheet.Name Like "売上*" Then
　　　　　ReDim Preserve My_SheetName(i)
　　　　　My_SheetName(i) = MySheet.Name
　　　　　i = i + 1
　　　End If
Next MySheet
```
■ 複数セルに対する処理（配列を使用）
選択範囲がセルの場合,選択範囲を「Selection」のオブジェクトとして操作できる
```
Sub Sample3()
    Dim c As Range, i As Long
　　Range("A1:D10").select
    For Each c In Selection
        i = i + 1
        c.Value = i
    Next c
End Sub
```
 Selectionプロパティ
Selectionとは、選択されたセルを表します。操作対象がセルであり、ワークシートではない

###### 重複コマンド
セルA1を起点としたアクティブセル領域（CurrentRegion）の取得し、コピー
>Range("A1").Select
>Selection.CurrentRegion.Select
>Selection.Copy
結果が　Range("A1").CurrentRegion.Select.Copy　とイコールです。

##4) 間違いやすい
■　Worksheets()とWorksheet()の違い
■　ThisWorkbook.Worksheets
■　CollectionとSellection


##5) エラー調べ
■　10004エラー 
```
WbCopy.Worksheets("sh1").Range("A1").SelectでRangeクラスのSelectメソッドが失敗しました。
```
エラーの原因がSelectにある。ワークシートsh1がアクティブになっていない場合、sh1内のセルをSelectに指定してはいけない。 
以下のコードを追加すればエラーが解消される。
```
Worksheets(sh1).Activate
```
メソッド内で生成されるインスタンスのメソッドをモックするには

あるメソッドが、その中で他のクラスのインスタンスを生成してそのインスタンスメソッドが呼ばれることを確認したい。しかし、実際にそのメソッドを動かすとすごく時間がかかったりとか色々面倒なので呼ばれたことだけをテストしたい。

```ruby
def exec_service(user)
  Service.new(user).start #このコードが呼ばれることをテストしたいが、実際に動作するのは困る
end
```

そこでメソッドをモックしたインスタンスを作成し、そのクラスのnewが必ずそのインスタンスを返すようにした。

```ruby

example "exec_serviceを呼ぶとService.new(user).startが呼ばれる" do
    # 実際にstartが呼ばれないようにモックする
    @servise = Service::.new("user")                     # モックのServiceインスタンスを作成
    allow(@Service).to receive(:start)                   # モックのインスタンスのstartメソッドをモックして本来のメソッドが呼ばれないようにする
    allow(Service).to receive(:new).and_return(@servise) # Service.new がモックのインスタンスを返すようにする

    # 呼び出す
    exec_service("user")                                 

    # Service#startが呼ばれたことを確認
    expect(@servise).to have_received(:start).once
  end
end
```
jQueryの「配列内に1つでも値があればtrueを返す」でハマった

# 背景
### 「配列を受け取って、1つでも値が設定されていればtrueを返す」
という、
幾度となく書いてきた簡単な関数をjQueryで書いてみたところ、ハマった。
自己解決できたので、備忘録とQiita更新するクセをつけるために書いておく。


# TL;DR
↑毎回TL;DRって書きたいがために更新してる


PHPと同じノリで、配列をeach()で回し、条件に当てはまったら`return ture;`
して即抜けする、という書き方をしていたら、うまくいかなかった。

うまくいかない事象としては、
`trueのルートに入っているのに、関数呼び出し側で待っているとfalseが返ってくる。`

```js
  /**
   * 配列を受け取り、1つでも値が入っていればtrueを返す
   * 間違い版
   */
  "SampleArrayCheck": function(targetArray) {
    $.each(targetArray, function(index, answer){
      if(answer){
        return true;
      }
    });
    return false;
  },
```

稚拙な考えながら、
**returnしてるけど毎回のfunctionを抜けているだけで、eachは抜けていないのでは？**
と思った。（以下）

```js
  /**
   * 配列を受け取り、1つでも値が入っていればtrueを返す
   * 間違い版(自己解説)
   */
  "SampleArrayCheck": function(targetArray) {
    $.each(targetArray, function(index, answer){
      if(answer){
        // ここでeachを抜け出すように書いていたけど、
        // functionを抜けただけで、eachは引き続き回っているのでは
        return true;
      }
    });
    // 何度trueを返そうと最後に必ずここに来るのでfalseが返る
    return false;
  },
```



上記の仮設のもと、
とりあえずすぐ思いつく、変数に格納する形に変えた。
（以下）



```js
  /**
   * 配列を受け取り、1つでも値が入っていればtrueを返す
   * 修正版
   */
  "SampleArrayCheck": function(targetArray) {
    // 関数のスコープ内でステータス管理の変数を用意する
    let result = false;

    $.each(targetArray,function(index, answer){
      if(answer){
        // trueを代入するだけにする
        result = true;
      }
    });

    // trueでもfalseでもここで返る
    return result;
  },
```

上手くいった。


時間があったらちゃんと調べるけど今のところあっているぽいので今日はここまで。

指摘だらけだとは思いますが
何かあればコメントいただけますと幸いですmm
Linux or Android 向け Vulkan アプリのデバッガーのメモ

## RenderDoc

https://renderdoc.org/

一見名前からするとレンダリング関連のドキュメントかと思ってしまいますが, デバッガーです.

OSS で Linux でも使えて便利.

validation layers を入れ替える感じで, layer 入れかえでデバッグできます.
基本的には `F12` でフレームをキャプチャして, それぞれのコマンドの実行履歴や, シェーダのデータ(uniform 変数とか, 頂点データ)を確認できます.

## GAPID

https://github.com/google/gapid

RenderDoc っぽいやつ. 主に Android と Stardia 用?

## NVIDIA Nsight

NVIDI GPU の場合はこちら

https://developer.nvidia.com/nsight-graphics

VisualStudio 版あります.
https://developer.nvidia.com/nsight-visual-studio-edition

## Intel graphics performance analyzers

Intel GPU の場合はこちら

https://software.intel.com/en-us/gpa

## GPU perf studo

AMD GPU の場合はこちら

https://gpuopen.com/archive/gpu-perfstudio/gpuperfstudio-vulkan-tools/

## SwiftShader で CPU 実行してデバッグ

実 GPU でデバッグというのはなかなかしんどいので(ドライバのバージョン問題とか, GPU の世代の違いとか), CPU エミュレーションともくみあせたいですね.
RenderDoc と SwiftShader の組み合わせでいけるかな?
 
SwiftShader の Software Vulkan 実装で自前 Vulkan アプリを作る準備(Linux)
https://qiita.com/syoyo/items/17a74b6809ebf1577ce7

## まとめ

とりあえず RenderDoc がお手軽でよいかと思います.

## TODO

* [ ] RenderDoc を Android で実行する.
Chromeの拡張機能を作成してみた

####経緯
右クリック禁止ページにおいて画像の取得をしたかったのでいろいろ検索してみたら、
Googleの拡張機能を簡単に作成できるという記事を発見したので作成してみました。
実際に検索したら、同様の拡張機能はたくさんありました。（笑）

####仕様（今後の展開も含む）
1. ページを開いた瞬間にページ内のimgタグを取得し、別タブに画像とaltの内容を表示します　←今ココ
2. イベントの発火をページ開いた時ではなく、アイコンをタップした瞬間に変更する
3. 別タブに表示するのではなく、アイコンクリック時に表示するHTMLへ表示する

####フォルダ・ファイル構成
```
test/
  - manifest.json　→　設定ファイル
  - jquery.min.js
  - content_scripts.js　→　処理ファイル
```

####ファイルの中身
```json:manifest.json
{
  "name": "TakeAPicture",
  "manifest_version": 2,
  "version": "1.0.0",
  "browser_action": {
    "default_title": "TakeAPicture"
  },

  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "js": ["jquery.min.js", "content_scripts.js"]
    }
  ]
}
```

```javascript:content_scripts.js
var set_html = "";
$("img").each(function() {
	var src = ($(this).hasClass('lazyload')) ? (($(this).attr('data-src') != undefined) ? $(this).attr('data-src') : $(this).attr('src')) : $(this).attr('src');
	var img = '<img src="' + src + '" alt="' + $(this).attr('alt') + '" />';
	var cap = '<p>' + $(this).attr('alt') + '</p>';
	set_html += img + cap + "<br>";
})

var nwin = window.open("", "image_list", 'width=600,height=700,resizable=1,scrollbars=1');
nwin.document.open();
nwin.document.write(set_html);
nwin.document.close();
```
####終わり
今回初めて作成してみましたが、特に苦戦する要素は無かったと思います。
ただし、デバックがうまくいかずいい方法がないか探してみようかと思います。
デバックでいい方法をしっている方いたら教えてください。

####参考サイト
[Chromeブラウザの拡張機能を作ってみたい初心者向けに開発方法を紹介！【サンプルあり】](https://qiita.com/guru_taka/items/37a90766f4f845e963e5)

####更新履歴
20/02/10 タイトルを変更しました。
Visual Studio 2019のデフォルトエンコードをUTF-8にする方法

## 注意点
- Visual Studio 2019をC:\\Program Files (x86)等、ファイル書き換えに管理者権限が必要な場所にインストールしている場合、管理者権限が必要になります
- おそらく他のVisual Studioのエディションでもできると思いますが、Visual Studio 2019以外では検証してないため、それ以外では保証ができません
- 今時そんなのないと思いますが、BOM付きUTF-8のファイルを作成できるテキストエディターがない人は一旦ブラウザバックしてインストールしてきて下さい。ちなみにWindows標準のメモ帳は可能です

## 概要
最近C++の開発をしていて、いちいちファイルのエンコードを変更して保存ってやらないといけないのがあんまりにも煩わしいと感じていました。そもそも[@yumetodo](https://qiita.com/yumetodo)からVS2019はソースコードファイルはデフォルトでBOM付きUTF-8って聞いてたからやっとあの煩わしい作業から解放されると思ってたのに作られるファイルはShift-JIS…。なーにがBOM付きUTF-8のファイルが作られるだよ！
という怒りから方法がないか調べていた時に辿りついた記事がKTA552さんの[この記事](https://qiita.com/KTA552/items/00358eeec6a3b2afb138)でした。
ただ、実際読んでみると、まあ要するにこの画面にBOM付きUTF-8ファイルを作成するテンプレートを増やすやり方なんですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94629/b460bc01-f1a5-6b0b-246b-9ebfb0743e4a.png)
でも私は思いました。「テンプレートを作ったら負けじゃないか？」と
そもそもこの方法で作ったとして、間違っていつものを選んだら結局煩わしい作業をしないといけないんですよ
じゃあいっそこのテンプレートのソースファイルとヘッダーファイルそのものを書き換えてしまえばいいんじゃないかと考え、やりました

## 手順
やることは至ってシンプルで、テンプレートファイルがShift-JISなのでそれをBOM付きUTF-8で保存してやればいいんです
さてそのファイルはどこかというと…

__ここです！__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94629/722a473a-cbaf-c475-3a26-0bd8ad36359d.png)

私の環境ではVisual Studio 2019はC:\\Program Files (x86)\\Microsoft Visual Studio 16.0にインストールされてるので、パスはC:\\Program Files (x86)\\Microsoft Visual Studio 16.0\\Common7\\IDE\\VC\\vcprojectitemsになりますが、これは自分のVSのインストールパスに読み替えて下さい。
さて、勘のいいそこのあなたはもう分かってると思いますが、編集するファイルは
- newc++file.cpp
- hfile.h
の２つです。私はサクラエディタでこの２つのファイルをBOM付きUTF-8に書き換えました
ただ、インストール先の親ディレクトリがC:\\Program Files (x86)なので編集には管理者権限が必要でした
そしてこのファイルを書き換える時に気を付けないといけないのが「ファイル名を変えてはいけない」ということです
変えてしまうと最悪ファイル作成ができなくなります。
VSの更新の影響受けるのか？そんなもんは知らん。まだこの作業してから更新してないし

とにかく、この作業を行うことで、C++のソースファイルとヘッダーファイルはデフォルトで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94629/c4ad1de3-350f-cc77-44d6-0c0835972fb0.png)
この通りBOM付きUTF-8になります。ちなみに私はさらに行の終わりもCR+LFにしておきました。
まあそこをどうするかは作業するあなたが決めて下さい。私は知りません。
Vulkan シェーダをテストするツールのメモ


## Amber

https://github.com/google/amber

GLSL など各種シェーダ言語のテスター.
Talvos, VkRunner などを参考に作成.

## Talvos

Oclgrint(Valgrind のような感じで OpenCL をエミュレーションして実行とデバッグができるツール)の jrprice 先生謹製.

https://github.com/talvos/talvos

SPIR-V interpreter + Vulkan emulator
C++17 が必要. Vulkan-Headers と SPIRV-Tools 以外は基本全部自前実装で素晴らしい.

clspv のシェーダ(compute shader)をエミュレーションして実行できる.

## VkRunner

https://github.com/igalia/vkrunner

piglit を参考に生成

## Piglit

https://piglit.freedesktop.org/

Mesa で使われている(はず)の OpenGL テスター. 結構昔からある(2014 年ごろにはあったと記憶)
M5Stack にAmazon FreeRTOSをインストール (mac)

## 開発環境

基本的にはドキュメントにある通り以下に沿ってやっていく。
https://docs.aws.amazon.com/ja_jp/freertos/latest/userguide/getting_started_espressif.html
ツールチェーンについては以下だが、
https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/macos-setup.html
次のページ（以下）のStep2まで実行する。
Step3をやると環境変数によってコンパイルにコケるので注意。 
https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/index.html#get-started-get-esp-idf-cmake

その後でCMakeをインストール。

## Amazon FreeRTOSのダウンロード
Amazon FreeRTOS のリリース版をAWS IoT のSoftwareからダウンロードする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102681/007dcf88-fdd5-a5a8-7d49-ba18c207fbd5.png)

## ビルド＆Flash
ダウンロードしたZipを展開後以下を実行

```sh
cd AmazonFreeRTOS/
cmake -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 -GNinja -S . -B build
vendors/espressif/esp-idf/tools/idf.py flash -B build/
```

## 設定
tools/aws_config_quick_start/configure.json を編集し、CredentialやWi-Fiの設定をする。設定の仕方は同一フォルダのREADMEを参照。

```
python SetupAWS.py setup
```

## チェック

```sh
cmake -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 -S . -B build
cd build/
make all -j4
cd vendors/espressif/boards/esp32/aws_demos/
make size
make size-components
```
React.js Enterキーでsubmitされるのを阻止する

## 手軽に阻止したい
- とりあえず、イベントだけ消し去りたいメモ
- onKeyDownを書く

```js
<Form.Control type="text"  onKeyDown={e => { if (e.key == 'Enter'){e.preventDefault()} }} />
```
[macOS][Cocoa]アラートの表示

# アラートの表示

ボタンを追加するとか、ショートカットキーを設定するとか調べたのでメモ。

<img width="532" alt="alert.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37947/10cbee5e-c012-8f2d-45ed-ce71b4f6bf4a.png">

## ソース

```swift
let alert = NSAlert()

// 表示メッセージとインフォメーション
alert.messageText = "めっせーじ"
alert.informativeText = "いんふぉめーしょん"

// メッセージのスタイル
alert.alertStyle = .informational

// ボタン追加
alert.addButton(withTitle: "１つめ")
alert.addButton(withTitle: "２つめ")

// ボタンに対してショートカットキーの設定する場合
let buttons = alert.buttons
buttons[0].keyEquivalent = "\u{1b}"    // esc key
// buttons[0].tag = 1234               // runModalの戻り値を変更する場合
buttons[1].keyEquivalent = "\r"        // enter key

// 表示
let ret = alert.runModal()

switch ret {
case .alertFirstButtonReturn:
    print("１つめのボタン押されたよ。")
case .alertSecondButtonReturn:
    print("２つめのボタン押されたよ。")
default:
    print("その他:\(ret)")
}
```

## 補足

### ボタンのショートカットキー

ショートカットキーを何も設定しない場合、デフォルトで最初のボタンはエンターキー、「Cancel」タイトルのボタンにはエスケープキー、「Don't Save」タイトルのボタンはCommand-D（最初のボタンではない場合のみ）に設定されます。