OmniAICreator/Qiita-1.07M huggingface dataset:
ラズパイ、JetsonNanoなどのSDへのイメージ書き込み

よくやるけど、よく忘れるんでメモ


## GUI

* Etcherを利用するのが楽
※ただしCatalinaになってからFlashするとエラーするようになっている。(2019/10/15現在)
  その場合はコマンドを利用する



## コマンド

Macでの書き込み方法メモ

1: diskutilコマンドでSDを認識しているデバイスファイルを確認する

```
$ diskutil list external | fgrep '/dev/disk'
```

2: パーティションの再作成 (ここでは/dev/disk2にマウントされていることとする)

```
$ sudo diskutil partitionDisk /dev/disk2 1 GPT "Free Space" "%noformat%" 100%
```


3: 書き込み (zipは落としてきたimageに応じて変える)

```
$ /usr/bin/unzip -p "Image.zip" | sudo /bin/dd of=/dev/rdisk2 bs=1m
```

Jetson Nanoとラズパイはこれでいけた
ansible playbook実行時にGathering FactsでTimeoutErrorが出るときの対処

ansible playbook実行時に下記のエラーがでたときの対処

```
TASK [Gathering Facts] *********************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: TimeoutError: Timer expired after 10 seconds
fatal: [10.193.xx.xx]: FAILED! => {"changed": false, "cmd": "/usr/bin/udevadm info --query property --name /dev/sdn1", "msg": "Timer expired after 10 seconds", "rc": 257}
```

##対処方法
udevadmコマンドがこけてるように見えるが、実際はansible.cfgに設定されているtimeout時間を超えてしまったためにでるエラー。
なので、このtimeout時間を伸ばしてやれば良い。

```:ansible.cfg
gather_timeout=20
```

##参考
https://github.com/ansible/ansible/issues/43884
【たぶん個人用】vim環境設定 ~/.vimrc

[こちらの記事](https://qiita.com/morikooooo/items/9fd41bcd8d1ce9170301)を参考にさせていただきました。~~(絶賛でパクリました。)~~


すべての機能は必要なかったのでコメントアウトで消しています。参考になれば幸いです。

```~/.vimrc

" setting
"文字コードをUFT-8に設定
set fenc=utf-8
" バックアップファイルを作らない
set nobackup
" スワップファイルを作らない
set noswapfile
" 編集中のファイルが変更されたら自動で読み直す
set autoread
" バッファが編集中でもその他のファイルを開けるように
set hidden
" 入力中のコマンドをステータスに表示する
set showcmd


" 見た目系
" 行番号を表示
"set number
" 現在の行を強調表示
set cursorline
" 現在の行を強調表示（縦）
"set cursorcolumn
" 行末の1文字先までカーソルを移動できるように
set virtualedit=onemore
" インデントはスマートインデント
set smartindent
" ビープ音を可視化
set visualbell
" 括弧入力時の対応する括弧を表示
set showmatch
" ステータスラインを常に表示
set laststatus=2
" コマンドラインの補完
set wildmode=list:longest
" 折り返し時に表示行単位での移動できるようにする
nnoremap j gj
nnoremap k gk
" シンタックスハイライトの有効化
syntax enable


" Tab系
" 不可視文字を可視化(タブが「▸-」と表示される)
set list listchars=tab:\▸\-
" Tab文字を半角スペースにする
set expandtab
" 行頭以外のTab文字の表示幅（スペースいくつ分）
set tabstop=2
" 行頭でのTab文字の表示幅
set shiftwidth=2


" 検索系
" 検索文字列が小文字の場合は大文字小文字を区別なく検索する
set ignorecase
" 検索文字列に大文字が含まれている場合は区別して検索する
set smartcase
" 検索文字列入力時に順次対象文字列にヒットさせる
set incsearch
" 検索時に最後まで行ったら最初に戻る
set wrapscan
" 検索語をハイライト表示
set hlsearch
" ESC連打でハイライト解除
nmap <Esc><Esc> :nohlsearch<CR><Esc>


```
vue.js webpack ビルド を遅いので早く

laravel と vue.js を使っている場合の設定。
hard-source-webpack-pluginを使ってビルドを早くしよう。


# ソースをインストール

```

npm install --save hard-source-webpack-plugin

```

以下のファイルに2点追記。

```node_modules/laravel-mix/src/builder/webpack-plugins.js

var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');//追記

module.exports = function() {
    let plugins = [];

    if (!Mix.bundlingJavaScript) {
        plugins.push(new MockEntryPlugin());
    }

    plugins.push(new HardSourceWebpackPlugin());//追記



```


これでビルドが早くなる。






# キャッシュがおかしい場合は

```

rm -rf ./node_modules/.cache
```

でキャッシュを削除。
会社でSlack導入にあたってミスったと思ったこと

# 概要

会社でSlackを導入する際にガイドラインを作成したり、チャンネルの運用ルールを作ったりすると思いますが、その策定において失敗したなと思ったことです。

コミュニティ等で利用する際にも参考になるかもしれないのでこの記事を書きました。もっとも全従業員が利用するゆえのリテラシーの幅による問題も多分に含まれるので、あくまでも個社・個人的に感じたことです。

# 結論

- `#general` は **管理者（システムや総務部門）からの告知** に限ったほうが良い。

- お知らせはその他の初期参加チャンネルを作成して全員参加必須とする
    - ただし、このチャンネルから抜けることをシステムでは制限できない

# 説明

当初、当社では、周知について下記の２つのチャンネルを作成しました

- 重要周知
    - 半日に一度の目安で閲覧すること
- お知らせ
    - 業務外を含めたお知らせを可とする。一日に一度の目安で閲覧すること
    - 必須チャンネルのひとつで、抜けてはならない

## 起こってしまった問題

概ね、オオカミ少年を減らしたかった...というところに尽きます。

重要周知に書いたのに、お知らせに書いたのに見てもらえないなどの問題により、重要な周知については従来のように同じような内容をメールで再配布したりという手間が発生してしまいました。

### お知らせと重要周知の区別がつかない

事前に危惧はしていたのですが、情報は **発信する人が** 重要かどうかを決めてしまいます。重要というほどではないからお知らせにしよう・・・という力学が働くかなと思いましたが、想定外に重要周知への投稿が発生してしまいました。

特にここはエンジニアとそれ以外で **共有スペースに関する考え方が違うのかな** という気がしていますが、気のせいかもしれません。
※ master ブランチには直接pushしない、とかそういう考え

### here, channel が使われてしまう

ガイドライン上もできるだけ禁止していたのですが、こちらも上記同様、発信する側の都合でメンションしてしまいたくなるという状況でした。こちらは発生都度緊急性の高いものに絞るように自治警察を発動させて絞るようにしました。

### 共有チャンネルとして general は使えない

[Slackのヘルプ：共有チャンネルを作成する](https://slack.com/intl/ja-jp/help/articles/360035092414) に記載があるのですが、`#general チャンネルは共有できません` となっています。

まあそりゃそうだよね、という気はしますが、関係会社間でワークスペースをまたいでチャンネルを共有する運用をしていた当社では、案外これは困った事態になりました。

## 上記の問題への解決策

- 重要な周知はそもそも重要な周知をコントロールできる部門や管理職からの発信に限定する
    - [Slackのヘルプ：#general チャンネルについて](https://slack.com/intl/ja-jp/help/articles/220105027) にて、**#general へ投稿できるメンバーを制限する** を設定する。
        - その他のメンバーが投稿したい場合は投稿を該当メンバーに依頼する
            - これはアプリにしたいですね...[Reacji Channeler](https://reacji-channeler.builtbyslack.com/) なんかが使えそうですが
        - ワークスペース管理者グループという概念で [ユーザグループ](https://slack.com/intl/ja-jp/help/articles/212906697) を作って、有料版であればグループメンションできるようにしておくと良いと思います。
    - 重要な周知とはどのようなものなのかを事前にできるだけ定義する。
        - 建物停電、必須提出物etc
- 緊急性の高いものだけ here, channel を利用する。あとは定期的に読んでいる前提とみなす
- 複数ワークスペースへの重要周知は各スペースごとの管理者がコントロールする

# しかしそれでも悩みは続く...

- お知らせチャンネルから抜けるのを止められない
    - まあそういうアプリを作ればいいといえばいいのですが...
- ユーザグループは誰がメンテナンスするのか問題
    - 部署ごとにメンテナンスとしていると、漏れるリスクとの戦いです
- 新規チャンネル作成等のお知らせをお知らせチャンネルに送るべきなのかどうか
    - 現時点ではZapierを使ってお知らせ投稿しています
    - 特にSlackのUIが悪いために、チャンネルの誤作成がよく発生するのです...

これなんとかなりませんかね...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13879/bc41c2d0-3e3c-54a1-5e11-1ec09cd15ef0.png)


# その他

here, channel の区別がいまいちついていない という問題もありましたね。オフラインの人でも後から通知を送れるので、より通知を確実に届けたい場合channelという説明をしていますが、緊急との兼ね合いが難しくなってしまってもいます。

もしウチではこんな感じにして解決しているよ！な事例がありましたら教えて下さい！
【Rails】RSpecによるテスト　4.統合テスト

##RSpecによる統合テスト

今までは単体のテストを行いましたが、次は統合テストを行います。
統合テストでは、「ログインしてから記事を投稿する」といった一連の動作をテストします。
統合テストには`Capybara` gemを追加して行います。

####Capybaraを追加
```Ruby:Gemfile
group :development, :test do
#下記を追記
  gem 'capybara'
end
```
```Ruby:ターミナル
$ bundle install
```
```Ruby:spec/rails_helper.rb
#下記を追記
require 'capybara/rspec'
```

続いて実際に統合テストを行います。

```Ruby:spec/features/post_spec.rb
require 'rails_helper'

feature 'post', type: :feature do
  let(:user) { create(:user) }

  scenario 'log_in and post_tweet' do
    # ログイン前は投稿するボタンが表示されない
    visit root_path
    expect(page).to have_no_content('new post')

    # ログインすると投稿ボタンが表示される
    visit new_user_session_path
    fill_in 'user_email', with: user.email
    fill_in 'user_password', with: user.password
    click_on("Log in")
    expect(current_path).to eq root_path
    expect(page).to have_content('new post')

    # 投稿ボタンから記事を投稿する
    expect {
      click_on("new post")
      expect(current_path).to eq new_post_path
      fill_in 'post_title', with: "記事のタイトル"
      fill_in 'post_text', with: "記事の本文"
      click_on("投稿")
    }.to change{ Post.count }.by(1)
  end
end
```
統合テストの中では複数のテストを行いますので、後から見て分かりやすいようコメントアウトでテストの内容を書いておきます。

`fill_in`での指定はidの値を、`click_on`での指定はvalueの値を参照するようです。

入力できたらテストを実行します。

```Ruby:ターミナル
＄ bundle exec rspec spec/features/post_spec.rb
```

```ターミナル
post
  log_in and post_tweet

Finished in 0.53377 seconds (files took 2.36 seconds to load)
1 example, 0 failures
```
テスト結果は問題ないようです。
Youtube Data api を用いて、動画のタイトルを取得する

webapi,jsonファイルについて少し勉強したので、YoutubeAPIを使ってみようと思い簡単なコードを書いてみました。
jqueryのgetJSONメソッドを使っています。

```get.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript" src="jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="get.js"></script>
  </head>
  <body>
<div id="player"></div>
    <div class="">
      <input id="inputText" type="text" name="" value="">
      //各種ボタンの設置
      <button id="searchButton" type="button" name="button">検索</button>
      <button id="nextButton" type="button" name="button">次へ</button>
      <button id="prevButton" type="button" name="button">戻る</button>
      <ul>

      </ul>
</div>

  </body>
</html>
```

```get.js
$(function(){
  //ページトークンの初期化
  var pageToken = "";
  var nextPageToken = "";
  var prevPageToken = "";
  //Youtube data api をjsonファイルで取得
  function getJsonFile(){
  $.getJSON(
    'https://www.googleapis.com/youtube/v3/search?key={API Key}&part=id,snippet',
    {q:$('#inputText').val(),
     type:'video',
     maxResults:50,
     pageToken:pageToken
  },
    function(data){
    $.each(data['items'],function(i,item){
      $('ul').append('<li>' + item.snippet.title);

    });
    nextPageToken = data.nextPageToken;
    prevPageToken = data.prevPageToken;
  });
  }
  $('#searchButton').on('click',function(){
    $('li').remove();
    pageToken = "";
    getJsonFile();
  })
  $('#nextButton').on('click',function(){
    $('li').remove();
    pageToken = nextPageToken;
    getJsonFile();
  })
  $('#prevButton').on('click',function(){
    $('li').remove();
    pageToken = prevPageToken;
    getJsonFile();
  })
});
```
macOS CatalinaにしたらGitコマンドが動かなくなった


さっそくCatalinaにアップデートしてみましたが、恒例のやつです。
Gitコマンドが動かなくなったのでまたメモです。内容は全く同じ。

* [macOS MojaveにしたらGitコマンドが動かなくなった](https://qiita.com/n0bisuke/items/1c60084c8c07b690d693)
* [macOS SierraにしたらGitコマンドが動かなくなった](https://qiita.com/n0bisuke/items/0ad33fa466c3de5ac763)

毎年やってる（笑）けど、ハマったときの検索ワードがOSアップデートによっても変わってくるのでまた残しておきます。

```
$ git
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

## 以下のコマンドで直ります

```
$ xcode-select --install
```

インストーラーが立ち上がるのでインストールしましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/52e53c2b-87cc-265b-b888-140fc0d9d531.png" width="500px">


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/9596982a-4020-905d-ddbf-61d6bed4b56f.png" width="500px">


> ちなみにこのコマンドを実行と、今回はこんな感じのエラーも同時に出てましたが気にせず大丈夫です。
>
>```
>xcode-select: note: install requested for command line developer tools
>```

無事にインストールできました。

```
$ git version
git version 2.21.0 (Apple Git-122)
```
JavaScriptでの文字列・整数の変換方法に関して

# 文字列から整数型への変換
```JS
Number('123456');
parseInt('123456', 10) //10は10進数という意味
```

Numberだと不適格な文字列が与えられた場合、```NaaN```を返却するのに対し、
parseIntだと数字以外を無視した状態（123abcとかだと123とかになる）で返却されるっぽい。

Javaに慣れているせいか（parseIntというメソッドがJavaにはあるから）後者が個人的に好み。

# 整数型から文字列への変換
```JS
String('123456');
"" + 123456;
```
後者の方はJavaっぽく記述できて個人的に好み。
Smartyよく使うもの

ほとんど使われなくなったSmartyですが、
自身会社のシステムで使っているもあり忘れないようにメモ
※追加があったら改変していきます


## 配列のダンプ

変数内の配列の中身を確認する際によく使います

```
{$hoge|@debug_print_var}
```
または

```
{$hoge|@var_dump}
```

$hoge ・・・ 表示したい変数


## 代入
変数名を短くしたいときや、ループ時内部でよく使います。

```
{assign var="name" value="Bob"}
```
value ・・・ セットする値
var ・・・ 代入する変数名


## ループ
####配列をループ
```
{foreach from=$myArray key=key item=data name=foo}
    <li>{$data}</li>
{/foreach}
```

from ・・・ ループされる配列変数
key ・・・ ループ時配列のkey値は代入される変数
item ・・・ ループ時配列のvalue値は代入される変数
name ・・・　foreachのプロパティを使用するときに設定する名前。ループ名
>name foreachのプロパティ
>
>```
{foreach from=$myArray item=i name=foo}
    {$smarty.foreach.foo.index} 
    {$smarty.foreach.foo.iteration}
    {if $smarty.foreach.foo.first}最初のループ時反応{/if}
    {$smarty.foreach.foo.last}最後のループ時反応{/if}
{/foreach}
```
>index ・・・配列のインデックスを0から数えた値が代入される
>iteration ・・・配列のインデックスを１から数えた値が代入される
>first ・・・ループ時、最初のものであるときに TRUE
> last ・・・ループ時、最後のものであるときに TRUE


####シンプルなループ
配列に依存せずphpのforのようなループも必要になることがある

```
{section name=bar loop=21 max=6 step=-2}
  {$smarty.section.bar.index}
{/section}
```
loop ・・・ ループ回数を決定する値
start ・・・ ループを開始するインデックス位置
max ・・・ セクションがループする最大の回数
step ・・・ループインデックスを進めるために使われるステップ値
name ・・・　foreachのプロパティを使用するときに設定する名前。ループ名
Route53 初心者　要点まとめ

#DNS関連メモ(Route53含めて)

・**エイリアスレコード**とは、DNS拡張機能であり、AWSリソースにルーティングするための別名を付けることができる。ELB、S3、API GatewayなどDNS名を持つリソースに対して、直接ドメインを登録することができます。Route 53のエイリアスレコードを使用することで、外部からのアクセスにAレコードとして振る舞います。CNAMEとエイリアスレコードで名前解決を行う際、CNAMEの場合だと、ルートDNSサーバからアクセスを行うが、エイリアスレコードであれば瞬時に名前解決が行われる。


・**FQDN**とはFully Qualified Domain Name（フリー・クオリファイド・ドメイン・ネーム）のことで、ドメイン名を省略せずに記載していること。
・**ホストゾーン**とは、レコードのコンテナのこと。パブリックとプライベートがある。
・**リゾルバ**とは、クライアント側のプログラムのことで、DNSサーバにIPアドレスを聞きに行ってくれるプログラムのこと。
・スタブリゾルバとフルサービスリゾルバがある。スタブがとりあえずDNSサーバにIPアドレスを聞きに行ってくれるクライアント側のプログラムのこと。大体がこれ。

・スタブリゾルバは**プログラム**で、フルサービスリゾルバは**DNSサーバ**である。
・いろいろ問い合わせてくれるDNSサーバのことをフルサービスリゾルバとしたが、**DNSキャッシュサーバ**と呼ばれる。
・権威DNSサーバとDNSコンテンツサーバは、IPアドレスを教えてくれるだけのサーバ
・**DNSルートサーバ**とは、DNSキャッシュサーバが一番初めに聞きに行くDNSサーバのこと。聞きに来られる側のDNSサーバの頂点の役割を持つ。
・トップレベルドメインというものがあり、.comや.jp、.netなどドメインの最後に位置する部分のことを指している。
・DNSサーバは、ドメインやIPを聞かれたときに参照するファイルがある。それを【**ゾーンファイル**】と呼ぶ。
・**DNSラウンドロビン**とは、一つのドメイン名に対して複数のIPアドレスを持たせることで、負荷分散を実現する機能のこと。
・**レイテンシーベースルーティング**とは、最寄りのサーバへ接続させる機能のこと。
・**DNSフェイルオーバー**とは、アクセスしようとしたプライマリサーバがしんでいるときに、セカンダリサーバへアクセスするよう設定すること。
・ネームサーバ=DNSサーバ



#主要レコードまとめ
・**SOA**レコード...管理する範囲や動作する範囲の情報が書かれているもの。
・**NS**レコード...管理を委託しているDNSサーバの名前が記載されているもの。
・**MX**レコード...ドメイン宛のメールの配送先メールサーバが記載されているもの。
・**A**レコード...DNSサーバの最も有力なレコードのことで、ドメイン名に対応するIPアドレスが記載されているもの。(IPv4)
・AAAAレコード...IPv6が記載されているもの。
・**CNAME**レコード...ドメイン名に対して別のあだ名が記載されているもの。


#Route53でのレコードの書き方ルール
今回は example.com をドメインとする。

・**Zone apex**とはexample.comみたいにサブドメインを含めないドメイン名のこと。
・Route53では、Zone apexにCNAMEの定義が出来ない仕様になっている。
・www.example.com  やyyy.example.comなどはサブドメインとなる。

【CNAMEレコード作成の注意点】最後のドット(.)を付け忘れない!!!!
www.example.com  IN   CNAME    aaa.example.com.
www.example.com  IN   CNAME    bbb.example.com.
など同じドメインやサブドメインを使用することはできない。

example.com. CNAME example.cname.jp.
などZone ApexにCNAMEは定義できない。

www.example.com. IN    CNAME    aaa.example.com.
www.example.com. IN    A        1.2.3.4
のように別タイプのレコードも書くことはできません。
よってCNAMEレコードはNSレコードやAレコードなどと共存出来ない仕様となっている。
これはDNSのRFC1912に記載されている。
**※同じサブドメインでCNAMEレコードを書けないことに要注意。**

ホストゾーンを作成するには、ドメインの権威DNSサーバを定義するNSレコードの登録が必要である。例えば
example.com. NS example.content.jp
ちなみにRoute53ではドメイン登録時(ホストゾーン作成時)にNSレコードが自動で定義されています。
【Zone ApexにはNSレコードが必要】であるため、example.comというZone ApexのCNAMEを書くことが出来ない。何が言いたいかというとexample.comのCNAMEレコードは書けないということ。
よってCNAMEを利用する場合はホスト名付きのサブドメインであることが必要。
www.example.com. CNAME yyy.example.com.←←Zone ApexじゃないためOK


#Route53(エイリアスレコード)の使用例
ELBのIPアドレスをAレコードにマッピングしたいけど、ELBは自動で冗長化され、IPアドレスも変動するため、Aレコードを登録するのが現実的でない。また、ELBのDNS名をCNAMEでマッピングしようとすると、Zone Apexにはマッピングできないため、未使用のサブドメインにマッピングすることが必要である。そこでRoute53では、エイリアスレコードという独自の機能が備わっており、AレコードにELBのDNS名を指定することが出来る。
エイリアスレコードを使うことでZone Apex とELBのDNS名を紐づけることが出来ます。
example.com. A ALIAS dualstack elb-〇〇〇
ALIAS dualstack e1b-〇〇〇　A 192.〇.〇.〇
上2つを記述することで、example.com→→192.〇〇.〇〇.〇

さらに、
example.com. A 192.〇.〇.〇
で一発でexample.com→192.〇〇.〇〇.〇
に名前解決が可能。

まとめるとIPアドレスが変動してしまうロードバランサーやS3ウェブサイトホスティング機能を用いるときに、CNAMEレコードを書いてもIPが変わってしまうため、エイリアスレコードを用いることでCNAMEレコードをAレコードとして利用することができ、変化するIPアドレスに沿ってエイリアスレコード内のアドレスも自動的に変わってくれる、またAレコードであることからNSレコードやSOAレコードとも併用可能となっている非常に優れたDNSサービスである。
git pullしたのちにでるrspecエラーの解消

#git pullしたあとにrspecを走らせてでるエラー解消
今までは普通に走っていたのに、関係ないとこをpullしてエラーがでたりします。
そんな時の一つの対応策として参考にしていただけたらなと思います。

##原因
pullした後に**rails db:reset**コマンドを打ってもなおらい。
これだけとrspecを走らせている環境のリセットにはなっていないから。
つまり、リセットはするもののテスト環境を指定してリセットをかける必要がある。

##解決
```
rails db:reset RALS_ENV = test
```

これでテスト環境を指定してエラーの解消できます。
TensorFlowのDataset.shuffleのbuffer_size

# この記事は
Tensorflowのtf.data.Dataset.shuffleの引数であるbuffer_sizeについて、公式ドキュメントを読んだだけではいまいち理解できなかったので、実際に動かして確認した結果のメモです。
※確認はver 2.0.0で行っています。

# ドキュメントに書いてあること
buffer_sizeで指定された要素数のバッファを用意して、そこからランダムにサンプリングする。サンプリングされた値は次の要素で置き換えられる。
**完全にシャッフルしたい場合はデータ数よりも大きい値を指定すべし。**

# 確認用コード

0~999の数字を順に生成して、shuffleでどのように並べ替えられるか確かめる。

```python
import tensorflow as tf
import matplotlib.pyplot as plt

fig, ax = plt.subplots(4,2, figsize=(8,12))

for i, size in enumerate([1, 100, 500, 10000]):
    seq = [v for v in range(1000)]
    val = [v.numpy() for v in tf.data.Dataset.range(1000).shuffle(size)]
    ax[i][0].scatter(seq, val, s=3, label="buffer_size: "+str(size))
    ax[i][0].plot(seq, color="black")
    ax[i][0].legend(loc="upper left")
    ax[i][1].hist(val[500:])
    ax[i][1].set_xlim(0, 1000)
plt.show()
```

# 結果

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156722/8de21f37-db64-da1d-d90f-0199ab2edc15.png)

左側の図
- 横軸：shuffle後のインデックス
- 縦軸：shuffle前のインデックス

右側の図：shuffle後の後半データ（500~999番目）の元のインデックスのヒストグラム

buffer_size=500で説明すると、shuffle後に最初に値を取得すると、元のインデックスで0~499番目のデータがサンプルされる。次のデータは0~500番目から選ばれる。ただし、すでに選ばれたものは除外される。
これを繰り返すと、n番目のサンプルデータは元のインデックスで0~(500+n)番目のデータから選ばれる。ただし、前半はすでにサンプルされてしまっている可能性が高いため、前半インデックスによって偏りが生じる。

ゆえに、均等にシャッフルするためには、buffer_sizeをデータ数より大きくしなければならない。

# 結論

データが多すぎてメモリに乗らないなどの特別な理由がなければbuffer_sizeはデータ数と同じ値にしとけばよさそうです。
Autodesk Inventor API Hacking (アドイン マネージャ)

# 0. はじめに
Inventorの`アドイン マネージャ`についての情報をまとめます。
![AddInManager.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424028/58eb264c-d2b1-70c5-62d6-8f38d11e24b9.png)

# 1. 情報の保管場所
`アドイン マネージャ`では、各アドインのロード状態、自動ロード、ブロック解除を設定できます。この情報は、以下に保管されています。

```
%APPDATA%\Autodesk\Inventor <バージョン番号>\Addins
# 言い換えると
C:\Users\<User Name>\AppData\Roaming\Autodesk\Inventor <バージョン番号>\Addins
```

この中に、拡張子が`.addin`のfileがあり、ここに記載されている内容は各AddIn標準の`.addin`を上書きするようです。
このdirectoryを複数用意して差し替えることにより、使用するAddIn構成を変更できます。

# 2. 説明の多言語化
Inventor標準のAddInでは、説明領域の文章が言語によって変わります。
![説明.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424028/54926895-4711-c5dc-496b-add736515a08.png)
![Description.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424028/c5bcb3d5-04b6-2028-5c2d-ec866442acfd.png)
これは、`.addin`内のtagに`Language`属性を指定することで可能になります。

```
<Description Language="1033">This is useful command!</Description>
<Description Language="1041">これは便利なコマンドです!</Description>
```

参考例として、

```
%ProgramData%\Autodesk\Inventor 2020\Addins\Anark.Core.addin
```
を見ると記述方法が良くわかると思います。

恐らく本ページを見られている方は、日本語と英語、場合によってはもう幾つかの言語について記述するのでしょうが、記述されていない言語のInventorで見た場合は、どの言語が選択されるのでしょうか。
私の実験結果では、

* 英語(`Language="1033"`)がある場合は、それが選択される。
* 英語(`Language="1033"`)がない場合は、もっとも番号が若いものが選択される。

ようです。

# 3. APIからのaccess
APIでは、`Application.ApplicationAddIns`から、各種情報の取得および、`Activate()`と`Deactivate()`が出来ます。

# 4. 注意点
`アドイン マネージャ`からでもAPIからでも、無効/`Deactivate()`は、AddInの`Deactivate()`を呼ぶだけで、**memoryからはunloadされません**。

# 99. 親の記事に戻る
[Autodesk Inventor API Hacking (概略)](https://qiita.com/yamarah/items/cee08eb8f2b7aecbda83)
sudo無しでLinuxへJUMAN++をインストール

# はじめに

- end-to-endでのインストール方法の説明
- root以外（sudoなしで）userでのインストール方法

が見つからなかったため備忘録としてまとめておく．

# 環境
```
Ubuntu 18.04.2
JUMAN++ v2.0.0-rc3
```

# 非rootの対処
よくあるビルドが`sudo make install`と， sudoを必要とするが， これは`/usr/local/bin/`へのアクセス権限の問題っぽい．
だから， `~/usr/local/(={user}/usr/local/)`を作成し，そこに`bin/jumanpp`を置く．
そして， そのパスを`jumanpp`コマンドで実行できるように`~/bashrc`を書き換える

以下コマンド等

```sh:~/.bashrc
# 以下を追加
export $PATH = export PATH="$HOME/usr/local/bin:$PATH"
```
```sh:ubuntu
# ~/usr/localの作成
$ mkdir ~/usr
$ mkdir ~/usr/local

# .bashrcをリロード(変更内容を有効にする)
$ exec $SHELL -l 
```


# パッケージインストール
[githubのページ](https://github.com/ku-nlp/jumanpp/releases)から最新verのパッケージをインストールする．
「When is the final release?」の下の「Assets(3)」の一番上のやつ(リンクをコピー).
あとは以下参照

```sh:ubuntu
# コピーしたリンクを引数としてwget (macOSならcurlだっけ?)
$ wget https://github.com/ku-nlp/jumanpp/releases/download/v2.0.0-rc3/jumanpp-2.0.0-rc3.tar.xz

# 解凍してディレクトリに入る
$ tar xvf jumanpp-2.0.0-rc2.tar.xz 
$ cd jumanpp-2.0.0-rc2

# ビルド用ディレクトリを作成・移動
$ mkdir bld
$ cd bld

# ビルド
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/usr/local # 先ほど作ったパスを指定
$ make
$ make install
```

# 終わり
jumanppの実行確認ができたらok

```terminal:ubuntu
$ jumanpp -v
Juman++ Version: 2.0.0-rc3 / Dictionary: 20190731-356e143 / LM: K:20190430-7d143fb L:20181122-b409be68 F:20171214-9d125cb

$ echo "すもももももももものうち" | jumanpp
> すもも すもも すもも 名詞 6 普通名詞 1 * 0 * 0 "自動獲得:テキスト"
> @ すもも すもも すもも 名詞 6 普通名詞 1 * 0 * 0 "代表表記:酸桃/すもも 自動獲得:EN_Wiktionary"
> も も も 助詞 9 副助詞 2 * 0 * 0 NIL
> もも もも もも 名詞 6 普通名詞 1 * 0 * 0 "代表表記:桃/もも ドメイン:料理・食事 カテゴリ:植物;人工物-食べ物 漢字読み:訓"
> @ もも もも もも 名詞 6 普通名詞 1 * 0 * 0 "代表表記:股/もも カテゴリ:動物-部位"
> も も も 助詞 9 副助詞 2 * 0 * 0 NIL
> もも もも もも 名詞 6 普通名詞 1 * 0 * 0 "代表表記:桃/もも ドメイン:料理・食事 カテゴリ:植物;人工物-食べ物 漢字読み:訓"
> @ もも もも もも 名詞 6 普通名詞 1 * 0 * 0 "代表表記:股/もも カテゴリ:動物-部位"
> の の の 助詞 9 接続助詞 3 * 0 * 0 NIL
> うち うち うち 名詞 6 副詞的名詞 9 * 0 * 0 "代表表記:うち/うち"
> EOS
```

# 参考
[JUMAN++公式github](https://github.com/ku-nlp/jumanpp)
[Juman++インストール[Ubuntu 16.04 LTS]](https://qiita.com/spiderx_jp/items/f0466705d1dda1a8c396)
研究室の先輩🙇‍♂️
Cloudinary + Rails 画像アップロード

## 経緯
Railsで開発をしていて必ず直面するのが画像アップロード機能です。

実際の運用では画像データの保存にはAWSのS3を使うことが多いです。しかし、プログラミングを始めたばかりの人や、お試しでやってみたいだけという人にとっては、AWSに登録してクレジット情報を記入し、IAMのキーを発行し、S3バケットを作成するというのは結構ハードルが高いものです。

そこでお気軽に使えるのがCloudinaryというサービスです。今回はその使い方を説明していきたいと思います。


## 事前準備
①クラウディナリーにサインアップ
https://cloudinary.com/users/login

②Railsプロジェクトを用意

```sh:terminal
$ rails new cloudinary_uploader
```
```ruby:gemfile
gem 'cloudinary'
gem 'carrierwave'
```

```sh:terminal
$ bundle install
$ rails g scaffold article title content image
$ rails db:migrate
$ rails g uploader article_image_uploader
```


## 設定ファイルのダウンロード

シークレットキーやその他の設定情報が記載されたyamlファイルをログインした状態で、<a href="https://cloudinary.com/console/cloudinary.yml">ここ</a>からダウンロードし、`config/cloudinary.yml`に配置してください。

## credential.ymlの編集

cloudinaryの設定情報には秘密情報も含まれているのでそれを`config/credentials.yml.enc`に追記します。`credentials.yml.enc`は直接編集できませんので、以下のように編集してください。

```sh:terminal
$ EDITOR='code --wait' rails credentials:edit
# Atomの人は以下のように
# EDITOR='atom --wait' rails credentials:edit
```
するとエディターで`config/credentials.yml`が開くので、以下を追記してください。(<span>****</span>の部分に`config/cloudinary.yml`中の`api_key`,`api_secret`の値を代入してください。)

```
cloudinary:
  cloud_name: *************
  api_key: *************
  api_secret: *******************

```

## cloudinary.ymlの書き換え
秘密情報の書き込みが終わったら先ほど配置したファイルを以下のように書き換えてください。

```config/cloudinary.yml
---
development:
  cloud_name: Rails.application.credentials.cloudinary[:cloud_name]
  api_key: Rails.application.credentials.cloudinary[:api_key]
  api_secret: Rails.application.credentials.cloudinary[:api_secret]
  enhance_image_tag: true
  static_file_support: false
production:
  cloud_name: Rails.application.credentials.cloudinary[:cloud_name]
  api_key: Rails.application.credentials.cloudinary[:api_key]
  api_secret: Rails.application.credentials.cloudinary[:api_secret]
  enhance_image_tag: true
  static_file_support: true
test:
  cloud_name: Rails.application.credentials.cloudinary[:cloud_name]
  api_key: Rails.application.credentials.cloudinary[:api_key]
  api_secret: Rails.application.credentials.cloudinary[:api_secret]
  enhance_image_tag: true
  static_file_support: false
```

## uploader、modelの設定

次にアップローダーの設定です。 `storage :file`の部分を以下のように変更してください。

```article_image_uploader.rb
class FlyerImageUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick

  if Rails.env.production?
    include Cloudinary::CarrierWave
    CarrierWave.configure do |config|
      config.cache_storage = :file
    end
  else
    storage :file
  end
  # 後略
end
```
開発環境でデバッグをしたい場合は、if文を消して`include Cloudinary::CarrierWave`だけ書いて試してみてください。


最後にarticle modelにuploaderの設定を以下のように反映します。

```models/article.rb
class Article < ActiveRecord
  mount_uploader :image, article_image_uploader
end
```

## herokuにアップロード

変更内容をコミットし、herokuにプッシュした後、herokuのconfigにマスターキーを登録すれば完了です。

```sh:terminal
$ git push heroku master
$ heroku config:set RAILS_MASTER_KEY="**********" # config/master.keyの中身を貼り付け
```


## 公式ドキュメント
https://cloudinary.com//documentation/rails_integration
webプログラミング演習ノート ４回目(３、４限)

#配列について array

##配列
一つの変数で、複数のデータを扱うためのデータ構造
phpでは[]を使って配列を定義する。
配列の各要素には、インデックスをつかってアクセスする
インデックスでのアクセス時にも[]を使う
インデックスは０から始まる

```php
$array = ["apple", "banana", "strawberry"];
$apple = $array[0];
$banana = $array[1];
$strawberry = $array[2];
$array_length = count($array);   //3
```

##配列の操作法例
配列の最初の要素から最後の要素までを繰り返しする際、繰り返し分を使うことで簡潔に書くことができる。

```php
for($i = 0; $i <count($array); $i += 1){
&item = $array[$i];
//$itemに対して処理を書く
}
```

for文を使った配列の操作は、イディオムとして覚えるとよい。
###ちなみに
配列の中身を書き換える場合も、インデックスを使って

```php
$array[1] = "orange";
```

のように書ける。

###配列の末尾
に値を追加する場合は

```php
$array[] = "lemon";
```

のように、インデックスを省略すると追加できる。

```php
$array[10] = "cherry";
```
のように、最初は要素がなかった位置に値をいれることもできる。
この場合、空いた位置には NULL という値が入る。

```php
["apple", "orange", "strawberry", "lemon", NULL, NULL, NULL, NULL, NULL, NULL, "cherry"]
```
**※ NULL　は何もないを表す値のこと**

""配列のインデックスに使える要素

配列のインデックスには数値以外も使える
よく使うインデックスには文字列がある。

```php
$data = ["night" => "Good night."];
$data["morning"] = "Good morning";
$data["afternoon"] = "Good afternoon";

print "Hello!" . $data["afternoon"];
//Hello! Good afternoon.
var_dump($data);
```


http=ハイパーテキストトランスファープロトコル

ねっむいとりあえずこのノートはここまで・・・・
Async/Awaitを使ったNodemailerでのメール送信

## 概要
- 「[速攻NodeJSで簡単メール送信](https://qiita.com/kashih/items/59e1c0a8c3b1e483ecbe)」を参考に、ES7のasync/awaitを使ったNode.jsでメールを送信するロジックの自分用メモです。
- 最近はGmailのSMTPサーバを間借りするとエラーとなるようなので、Lolipopのメールサーバで送信できることを確認しました。

## 前提
1. Node.jsのプロジェクト作成済みであること
1. nodemailerのパッケージが追加済みであること

```console
npm install nodemailer

# このサンプルではnodemailerのv6.3.0を使用しています。同じバージョンを指定する場合は下記コマンドで
# npm install nodemailer@6.3.0
```

## ソース

```index.js
const nodemailer = require('nodemailer');

(async () => {
    // 宛先アドレス
    const receiverEmailAddress = 'receiver@example.com'
    // 送信者アドレス(smtpサーバのログインアドレス)
    const senderEmailAddress = 'sender@example.com'
    // 送信者のログインパスワード
    const senderEmailPassword = 'SMTP Password'

    const transporter = nodemailer.createTransport({
        // SMTPサーバのホスト
        host: 'smtp.lolipop.jp',
        port: 465,
        secure: true, // SSL
        auth: {
            user: senderEmailAddress,
            pass: senderEmailPassword
        }
    });

    // メールの内容
    const mailOptions1 = {
        from: senderEmailAddress,
        to: receiverEmailAddress,
        subject: '{件名}',
        text: '{本文}'
    };
    try{
        // 送信
        const result = await transporter.sendMail(mailOptions1);
        console.log(result);
    }catch(e){
        console.error(e);
    }
})();
```
2019-10-15 NetCDF > Error: Function 'nf_def_var_deflate' at (1) has no IMPLICIT type > --has-nc4がnoになっている

```
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
GeForce GT 730 1GB GDDR5
CentOS Linux release 7.7.1908 (Core)
```

WRF (Weather Research and Forecasting Model)関連。

### 背景

- NetCDF (C APIとFortran API)をmake installした
- NetCDFを使うソフトをビルド時にエラーが出る (下記)

```
Error: Function 'nf_def_var_deflate' at (1) has no IMPLICIT type
```

### 関連情報

https://www.flexpart.eu/ticket/132

> I have checked my netcdf library configuration status. It shows
> --has-nc4 -> no
> Is it indicating my netcdf library configured by disabling netcdf4 ? 

### nc-configでの確認

```
$ cd /usr/local/netcdf-4.7.1/gcc44/bin/
$ ./nc-config --all
...
 --has-nc2       -> yes
  --has-nc4       -> no
  --has-hdf5      -> no
...
```

確かにnetcdf4の機能がdisableになっているようだ。

### yumパッケージとの違い

yumでインストールしたnetcdf-develおよびnetcdf-fortran-develにもnc-configはある。
nc-configを実行すると、そちらの情報になる。

そもそもyumパッケージで問題がなければ、そちらを使うのでいい気はするが。
ASP.Net Core でjQuery無しでHTML5のバリデーションを利用する

　以前投稿した「ASP.NET Core でSPAではなくVue.jsを利用してみる」で記述していたASP.Net core のRazorPageのバリデーションアトリビュートをある程度まで実装してみました。
　サンプルとして自由に利用してみてください。
　以下に、これを作るうえで気づいたことを書いておきます。

###基本思想
（１）基本的にHTML5のバリデーションを用いてクライアントサイドでチェックする。
（２）サーバー側のバリデーションは基本的にエラーにならないが、POSTを手作業で行った場合などを考慮して一応作っておく。

###気づいたこと、苦労したこと
（１）MergeAttributeは上書きできない
　最初に躓いたのがこれです。
　クライアントバリデーションの属性を設定しようとしたのですが、設定されていない属性は追加できるのですが、既に設定されている属性は変更できない仕様みたいです。おそらく、RazorPageを記述している時に手で記述した属性を優先させるためと思われます。ただ、バリデーションで属性を設定する前にタグヘルパーが属性を設定してしまう為、バリデーションの処理の時点ではtype属性が設定されいて、変更することができませんでした。

（２）setCustomValidityを利用した場合、inputイベントでクリアしておく必要がある。
　次に引っかかったのが「setCustomValidity」を利用してエラーを発生させた場合、それを消さないとずっとエラーのままでした。設定する可能性のあるコントロールのみ対象とすればよいのですが、大変なので「input」タグ全てを対象としました。これをしないと一度エラーになった項目はずっとエラーのままです。

（３）html5のバリデーションのサポート範囲が異なる
　ブラウザごとにhtml5のバリデーションサポートの範囲が異なるので、自動的にサポートしている場合はそちらを優先させるようにしました。具体的にはinputイベントの処理でCustom以外のエラーがある場合は何もせず、無い場合のみ独自のバリデーション処理を実施しています。

（４）Compareの実装
　比較先のコントロールでもinputでのチェックを行う必要がありました。当たり前ですね。

###サポートしたバリデーション
|バリデーション|概要|
|:-----------------|:------------------|
|Require|必須。require属性に「require」を設定。ほとんどのブラウザでサポートされています。ErrorMessageを設定するとエラー時のメッセージが変更できます。|
|StringLength|入力文字列の長さ制限。MaxLength,MinLengthで最大長と最小長を設定できます。空文字は必須チェックで行うので最小が設定されていてもエラーになりません。OverMaxErrorMessageとUnderMinErrorMessageを設定すると独自のエラーメッセージが設定できます。（ErrorMessagは利用していません）|
|Date|日付入力のバリデーションです。ErrorMessageを設定するとエラー時のメッセージが変更できます。|
|Email|メールアドレスのバリデーションです。ErrorMessageを設定するとエラー時のメッセージが変更できます。|
|Enum|列挙型のバリデーションです。手入力で行うようなインターフェースは考えられないので使うことはないと思います。|
|RegularExpression|正規表現バリデーション。ErrorMessageを設定するとエラー時のメッセージが変更できます。|
|Range|範囲指定バリデーション。整数と実数で利用可能です。Min、Max、Stepを設定して、最小値、最大値、刻み幅を設定できます。刻み幅は最小値からの刻み幅となりますので、最小値の設定が必須となります。メッセージ変更はそれぞれ、UnderMinErrorMessage、OverMaxErrorMessage、NoStepErrorMessageに設定します。|
|Compare|他の入力と一致確認バリデーション。比較対象の項目を与えます。ErrorMessageを設定するとエラー時のメッセージが変更できます。|

###ソース
　GitHubの「nosa67/html5Validation」に作ったものを保存しておきました。
　煮るなり焼くなり自由にしてください。
　簡単なテストはしていますが、まだまだエラーはあると思います。特にサーバーでのチェックは甘いです。
　すこしでも参考になれば幸いです。

###助言がほしいです
　いろいろと考慮して作成してみたら、クライアントのjavaScriptがやたらと大きくなって汚くなってしまいました。
　もっと、スマートな方法をご存知ならコメントください。
Golangでのstructのmixinの方法


Golangでのstructのmixinの方法です。

```golang
package main

import (
	"fmt"
)

type Widget struct {
	name string
}

type WidgetMap map[string]string

type WrappedWidget struct {
	Widget
	WidgetMap
}

func main() {
	widget := Widget{"my widget"}
	widgetMap := map[string]string{"key1": "value1", "key2": "value2"}
	wrappedWidget := WrappedWidget{Widget: widget, WidgetMap: widgetMap}

	fmt.Printf("%#v\n", wrappedWidget)

	fmt.Println(wrappedWidget.name)        // アクセス出来る。
	fmt.Println(wrappedWidget.Widget.name) // こちらもアクセス出来る。

	// for _, v := range wrappedWidget { // これはエラー
	for _, v := range wrappedWidget.WidgetMap { // これはOK
		fmt.Println(v)
	}
}

$ go run main.go
main.WrappedWidget{Widget:(*main.Widget)(0xc000010200), WidgetMap:main.WidgetMap{"key1":"value1", "key2":"value2"}}
my widget
my widget
value1
value2
```

structのフィールドに、別のstructを名前無し（匿名）で設定すると、promoted fieldとなり、上記コードで言うと `wrappedWidget.name` でアクセス出来ます。

また、匿名で設定したフィールドの名前は、設定したstructと同じものになるため、上記で言うと `wrappedWidget.Widget.name` でそのままダイレクトにアクセスも可能です。

mapをmixinして、forループのrangeで回す場合、 `range wrappedWidget` ではできず、 `range wrappedWidget.WidgetMap` のように、一旦ダイレクトアクセスが必要です。

詳しくは、下記です。

https://golang.org/ref/spec#Struct_types
高度な継承abstract,interface -java

現時点で処理の決まっていない抽象的なクラスを作るときは
**abstract**を使う

```java:sample
	public abstract class Classicmusic {
	// クラシック音楽についての抽象クラス

	public abstract String getCountry();
	 // 出身国を取得する抽象メソッド
	 // return作曲家出身国 
	 
	public abstract String[] getmusicList();
	 // 曲リストを取得する抽象メソッド
	 // return 代表曲一覧
```
抽象メソッドを**1つでも実装したクラスは、必ずabstractをつけた抽象クラス にする**必要がある。
そして、抽象クラスは new でインスタンスを生成することができない。
注）抽象クラスにもabstractでないメソッドを実装することが可能。

抽象メソッドは**子クラスが実装することで、処理の内容を確定させる。**
**abstractを継承するときはextends**を使う。

```java:sample

	public class Bach extends Classicmusic {
	public String getCountry() {
		return "ドイツ";
	}

	public String[] getmusicList() {
	String[] mList = {"ゴルトベルク変奏曲","イタリア協奏曲","イギリス組曲"};
			return mpList;
		}

```

抽象メソッドを継承したクラスは、抽象メソッドを必ず実装しなければならない。
その処理の内容は**継承したクラス側で決めます**。
それまで未定だったメソッドの内容を確定させることを、**実装**といい、
継承したabstractメソッドは、実装しなかった場合コンパイルエラーになります。

これにより、実装を継承先の子クラスに委ねることができます。
このように、実装する内容は決まっていないけど必ず実装する必要があるという処理を抽象メソッドにすることで、
**実装を強制させることができる**。

特に抽象度の高いクラスを**インターフェース**として扱うことができる。

インターフェースとして扱うには条件として
**・すべてのメソッドが抽象メソッドである**
**・フィールドを1つも持たない**
ことが必要

```java:sample
	public abstract class Classicmusic {
	public abstract String getCountry();
	public abstract String[] getmusicList();
	}

//以下のようにインターフェースにすることができる。

	public interface Classicmusic {
	String getCountry();
    String[] getmusicList();
	}

//インターフェースを実装する場合は、extendsではなく implements を使う。

	public class Bach implements Classicmusic
Javascript で Slack へ通知する手順

Slack へ Javascript から簡単な通知を送りたいことがあったので、手順をメモしておきます

公式の設定手順は [こちら](https://api.slack.com/incoming-webhooks#getting-started)

## App の作成

まずは通知を送るための App を作成します

https://api.slack.com/apps へアクセスして「Create New App」をクリックし、
以下の入力、選択をします

| 項目 | 説明 |
|-----------------|------------------|
| App Name: | 通知用 App の名前を入力します |
| Development Slack Workspace: | 通知を送りたい Slack のワークスペースを選択します |

入力、選択したら「Create App」をクリックします

## App の設定

「Create App」をクリックしたら作成した App の設定画面に遷移するので、
そこで「Incoming Webhooks」をクリックし、「Activate Incoming Webhooks」の Off を On に切り替えます

すると下部に Webhook URL のリストが表示されるので「Add New Webhook to Workspace」をクリックします

投稿先のチャンネルを選択する画面が表示されるので、投稿先にしたいチャンネルを選択して「許可する」をクリックします

Webhook URL が追加されたらコピーしておいて、Slack 側の設定は完了です

## Javascript の処理

Javascript からは、以下のような関数を追加して呼び出せば OK です

```javascript
// JQuery の $.ajax を使った場合
function slack(message) {
    const url = '[コピーしておいた Webhook URL]';
    const data = {
        text: message
    };
    $.ajax({
        type: 'POST',
        url:  url,
        data: `payload=${JSON.stringify(data)}`
    });
}

// XMLHttpRequest を使った場合
function slack(message) {
    const url = '[コピーしておいた Webhook URL]';
    const data = {
        text: message
    };
    const xml = new XMLHttpRequest();
    xml.open("POST", url, false);
    xml.setRequestHeader("content-type", "application/x-www-form-urlencoded;charset=UTF-8");
    xml.send(`payload=${JSON.stringify(data)}`)
}
```
確率統計3回目

#確率変数から求める分散s**2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/fe36b302-cdc8-ebfa-4a5f-089ee35e16fc.png)

##STEP1 期待値を求める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/cdde1d00-8fd1-ec05-dcac-0fc3c81e70b0.png)

#STEP2 偏差を求めて2乗する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/c80c6d9b-bc46-95c3-a7f9-86a215e5d9d3.png)

##STEP3 偏差の2乗の期待値を求める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/267356e4-4ab5-9b2b-fc0a-9ba497977b31.png)

参考文献
https://atarimae.biz/archives/19027#step2-3
GKEにおけるモニタリング [Datadog, Mackerel]

# Saas 監視ツール
組み合わせて使うことが大事

例えば Mackerel の場合だと、メトリクスを収集してサーバ監視や独自のアプリ ケーション監視を行うことは得意ですが、APM が必要な場合は NewRelic を、複雑 な通知やインシデント管理をおこないたいのであれば PagerDuty や OpsGenie など のサービスと組み合わせて使うことをお勧めしています。

# Datadog
2010~

## 導入
1. DatadogアカウントとGCP Project を紐付ける
https://docs.datadoghq.com/integrations/google_cloud_platform/?tab=datadogussite#setup
2. Datadog Integrations APIs ページからAPI Keyを作成
https://app.datadoghq.com/account/settings#api
3. API Keyを用いてhelm, kustomizeでdatadog-agentをデプロイ
https://app.datadoghq.com/account/settings#agent/kubernetes

以上でDatadogのダッシュボード上で稼働中のGKEほかGCPサービスのモニタリングが可能です。
https://app.datadoghq.com/screen/integration/86/kubernetes---overview

## 費用
インフラ監視

ライセンス | 料金 | メトリクス保存期間 | コンテナ監視
--- | --- | --- | ---
Free | $0 | 1日 | 
Pro | 1Host $18/月  年間契約 $15/月 | 15ヶ月 | 10コンテナ
Enterprise | 1Node $27/月 年間契約 $23/月 | 15ヶ月 | 20コンテナ

https://www.datadoghq.com/pricing/

## メリット
- インテグレーションが豊富 
- UIが見やすい
- ダッシュボードのカスタマイズ性が高い
- 多種多様なメトリクス取得
- メトリクスの絞り込み
- ライブコンテナモニタリング
- 細かなアラート設定
- ワークロード毎のモニタリング
- GCP Projectを紐づけをしていればGCPの各ミドルウェアのモニタリングが可能
- 設定の煩わしさからの解放 人件費の削減
- 外れ値の検出
- dev, stag, prod 環境の監視を一括できる
- チーム全員が監視システムにアクセスできる
- `datadog-agent`はGoで実装されており、マルチプラットフォームで動作する

## デメリット
- 高い

# Mackerel
2014~
## 費用
- 1Host $18/月

## メリット
- URL外形監視というシンセティック監視機能も標準で備えている
- `mackerel-agent`はGoで実装されており、マルチプラットフォームで動作する
- AWSインテグレーションが豊富
いろはちゃんコンテスト Day2 D - 楽しすぎる家庭菜園(最小全域木、クラスカル法)

https://atcoder.jp/contests/iroha2019-day2/tasks/iroha2019_day2_d

最小全域木の問題。クラスカル法のライブラリ用に。


```python

from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations
import sys
import string


INF = float('inf')
def LI(): return list(map(int, sys.stdin.readline().split()))
def I(): return int(sys.stdin.readline())
def LIM(): return list(map(lambda x:int(x) - 1, sys.stdin.readline().split()))
def LS(): return sys.stdin.readline().split()
def S(): return sys.stdin.readline()
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def LIRM(n): return [LIM() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
mod = 1000000007


class UnionFind:
    def __init__(self, n):
        # 負  : 根であることを示す。絶対値はランクを示す
        # 非負: 根でないことを示す。値は親を示す
        self.table = [-1] * n


    def root(self, x):
        if self.table[x] < 0:
            return x
        else:
            self.table[x] = self.root(self.table[x])
            return self.table[x]


    def is_same(self, x, y):
        return self.root(x) == self.root(y)


    def union(self, x, y):
        r1 = self.root(x)
        r2 = self.root(y)
        if r1 == r2:
            return
        # ランクの取得
        d1 = self.table[r1]
        d2 = self.table[r2]
        if d1 <= d2:
            self.table[r2] = r1
            if d1 == d2:
                self.table[r1] -= 1
        else:
            self.table[r1] = r2


n, m = LI()
U = UnionFind(n)
L = LIR(m)
sort_range = sorted(range(m), key=lambda x: L[x][2], reverse=True)
ans = []
cnt = 0
for i in range(m):
    k = sort_range[i]
    a, b, c = L[k]
    if not U.is_same(a - 1, b - 1):
        cnt += 1
        ans += [k + 1]
        U.union(a - 1, b - 1)
    if cnt >= n - 1:
        break


for l in sorted(ans):
    print(l)
```
Raspberry Pi3 で Google Home に喋らせる

Raspberry Pi と Google-home-notifier を使うと Google Home に
メッセージをプッシュすることができる
# OSのインストール
:strawberry: Raspbian をインストールする。
2019/10 時点で最新の Buster を使うとうまく構築できないので
一つ前のバージョン [Stretch](http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2019-04-09/) からダウンロード:inbox_tray: を使う。
イメージを MicroSDカード:floppy_disk: に書き込んで、無線LAN設定ぐらいまで終わらせておく。

```
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
VERSION_CODENAME=stretch
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
$ cat /etc/debian_version 
9.11
```
# お約束の最新化と node、npm インストール
インストールしたらバージョンチェックもしておく。

```
$ sudo apt update & apt upgrade
$ sudo apt install -y nodejs npm
$ sudo npm cache clean
$ sudo npm install npm n -g
$ sudo n lts
$ node --version
v10.16.3
$ npm --version
6.9.0
```
# 次のパッケージもインストールしておく

```
$ sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev
```
[README.md 参照](https://github.com/noelportugal/google-home-notifier/blob/master/README.md)
# Google Home Notifier インストール

```
$ mkdir ghn
$ cd ghn
$ npm install google-home-notifier
```
# インストール後の作業
google-tts-apiのバージョンアップ
package.json の google-tts-api を 0.0.4 に設定

```sh:node_modules/google-home-notifier/package.json
   "bundleDependencies": false,
   "dependencies": {
     "body-parser": "^1.15.2",
     "castv2-client": "^1.1.2",
     "express": "^4.14.0",
-    "google-tts-api": "https://github.com/darrencruse/google-tts/tarball/british-voice",
+    "google-tts-api": "0.0.4",
     "mdns": "^2.3.3",
     "ngrok": "^2.2.4"
   },
```
修正したpackage.jsonで更新

```
$ cd node_modules/google-home-notifier/
$ npm update google-tts-api
```
browser.js の修正

```sh:node_modules/mdns/lib/browser.js
 Browser.defaultResolverSequence = [
-  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
+  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
 , rst.makeAddressesUnique()
 ];
```
rst.getaddrinfo に引数 {families:[4]} を追加する。

```sh:main.js
const googlehome = require('google-home-notifier')
const language = 'ja';

const msg = process.argv[2]

googlehome.device('Google-Home', language);
googlehome.notify(msg, function(res) {
  console.log(res);
});
```
```
node main.js メッセージを送信しました
```
応用例）
IFTTTと連携させると、家のそばに来たらメッセージを喋らせるなどを行うことができる。
WebAPIを作ってメッセージを投げられるようにすれば、外部から発話させることができる。

今後の課題）
音楽を流しているとき、メッセージをプッシュすると音楽が止まってしまう。

参照：https://github.com/noelportugal/google-home-notifier
DebianにOpenCV4.1.1の環境を構築しC++で利用

DebianでOpenCVをC++で使う必要があったので環境を構築したら大いに苦戦したので構築メモを残す。
今回導入したバージョンはOpenCV4.1.1。 もしかしたらOpenCV3.xならもっと楽だったかもしれない。

ちなみにPythonでOpenCVを使うならば下記のサイトのインストールスクリプト(install-opencv.sh)を実行するだけで簡単だった。
http://milq.github.io/install-opencv-ubuntu-debian/

基本的にはOpenCVの公式サイト( https://opencv.org/ )の「Tutorials」→「Introduction to OpenCV」→「Installation in Linux」の通りに進めていく。

一応転記していく

必要なソフトウェアをインストールしていく

```Bash:compiler
sudo apt-get install build-essential
```

```Bash:required
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
```

```Bash:optional
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
```

ソースコードを取得

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

ビルドしたものを格納するディレクトリを作る

```bash
cd opencv
mkdir build
cd build
```

cmakeする。割とすぐ終わる。

```bash
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
```

makeする
jの後の数字は使用PCのスレッド数に合わせると高速になる。
ふつうのPCなら数分で終わるが、ふつうじゃないPCだと1日放置するレベルで時間がかかる。

```bash
make -j4
```

makeしたものを使えるようにする。
こちらもふつうのPCなら一瞬で終わるが、ふつうじゃないPCだと(なぜか)1日放置するレベルで時間がかかる。

```bash
sudo make install
```

時間がかかる場合はこちらもjを指定するとよい(かも)

```bash
sudo make -j4 install
```

上記が完了したらさっそくOpenCVを使ってみる。
C++のコードは以下

```c++:test.cpp
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace cv;

int main(){
	Mat image = imread("xxxx.bmp");
	return 0;
}
```

```bash
g++ test.cpp
```

当然のごとくエラー

```
test.cpp:4:30: fatal error: opencv2/opencv.hpp: そのようなファイルやディレクトリはありません
compilation terminated.
```

インクルードパスを設定する。
インクルードパスはOpenCV4.xでは3.xと変わっているので注意

参考：OpenCVインストール構成の変遷（OpenCV 3.4.3，3.4.4，4.0.0）
https://qiita.com/dandelion1124/items/eae435e601fba2adb0d1

```bash
g++ -I/usr/local/include/opencv4 test.cpp
```

本当にこれでよいのか？とりあえずインクルードは通るがまだエラーはでる。
Mat image = imread("xxxx.bmp");の行を消せばコンパイルは通る。

ライブラリパスを指定する。

```bash
g++ -I/usr/local/include/opencv4 -L/usr/local/lib test.cpp
```

これでもエラーが変わらず。

/usr/local/libにあるすべてのOpenCVのライブラリを-lで指定。

```bash
g++ test.cpp -I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_cudabgsegm -lopencv_cudaobjdetect -lopencv_cudastereo -lopencv_dnn -lopencv_ml -lopencv_shape -lopencv_stitching -lopencv_cudafeatures2d -lopencv_superres -lopencv_cudacodec -lopencv_videostab -lopencv_cudaoptflow -lopencv_cudalegacy -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_photo -lopencv_imgcodecs -lopencv_cudawarping -lopencv_cudaimgproc -lopencv_cudafilters -lopencv_video -lopencv_objdetect -lopencv_imgproc -lopencv_flann -lopencv_cudaarithm -lopencv_core -lopencv_cudev
```

これでコンパイルができた。オプションも -I -L -lの順番じゃないと(なぜか)ダメだった

いちいちライブラリを個別で指定しなくてもpkg-configを使えばよいらしいが、今回の手順では使えなかった。追加で何か設定が必要？

```bash
g++ `pkg-config --cflags --libs opencv4` test.cpp
```
新人向けチートシート: vim

##はじめに
`vimtutor`とターミナルで入力することで、vimの公式チュートリアルを実施することができます。
以下はチュートリアルに含まれないものを含めてよく利用するコマンドをまとめています。

###保存系
```
#保存
<Esc>
:w

#上書き保存
<Esc>
:wq

#保存せずに終了
<Esc>
:q!
```

###移動系
```
gg #文書の先頭に移動
G  #文書の最後に移動

0 #行頭に移動
$ #行末に移動

% #括弧系((),{},[])の対になるものへ移動

w #次の単語に移動

<line number>G #指定して行に移動

<ctrl>+f #ページをめくる(forword)
<ctrl>+b #ページを戻す(back)
```

###挿入系
```
a #今の行からINSERT
o #次の行からINSERT

#複数行に同じ文字を入力する
<ctrl>+v #VISUALモードで挿入したい範囲を矩形選択
<shift>+I #INSERTモード
#入力したい文字を入力
<Esc>
<Enter>
```

###削除系
```
<number>dd #指定行数を削除
dG #文書の最後まで削除
dt<character> #指定文字までを削除
di" #クォート内を削除
di( #カッコ内を削除
dit #htmlタグ内を削除
dat #htmlタグを含めて削除

:g/<pattern>/d #patternを含む行を削除
```

###検索系
```
#単語検索
# #検索したい単語にカーソルを合わせて"#"
n #マッチした次の単語に移動
```

###置換系
```
#単語を選択して置換
# #単語を選択
:%s//<text to replace>/g


#選択した範囲で検索置換
<ctrl>+v #置換したい範囲を選択
: #コロンを打つと'<,'>が補完される
:'<,'>s/<text to search>/<text to replace>/g
```

#コピーアンドペースト
```
yy #一行コピー
<number>y #入力数字行分コピー
p #ペースト
```

###その他
```
<ctrl>p #入力補完(INSERTモード)
:vs <file path> #画面分割
:! <shell command> #shellコマンドの実行

#タブからスペースへの変換
:set expandtab
:retab　<number>
```

###vimrc参考URL
* [何も考えず~/.vimrcにこれを書くんだ！ 〜vim初心者によるvim初心者のためのvim入門〜](https://qiita.com/morikooooo/items/9fd41bcd8d1ce9170301)
* [よく使われているvimrcの設定ランキング](https://qiita.com/reireias/items/230c77b3ff5575832654)

###新人向けチートシート
* [git](https://qiita.com/taisukek/items/1c4fbb4ea4f7c2d4fad1)
* [terminal](https://qiita.com/taisukek/items/673103c19cec398e81bc)
Functionめっちゃつかいやすくね

##Functionインターフェイス

ラムダ式でメソッドをFunctionとして書けるようになりました。
とりあえずやってみましょう。

参考
[公式リファレンス](https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Function.html)

```Function.java
package functionPractice;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

/**
 * To practice function-interface
 * 
 * @author me
 *
 */
public class FunctionPractice {

	/**
	 * main
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			run();
		} catch (NumberFormatException e) {
			echo.accept("・ω・ｖ");
		}
	}

	/**
	 * run
	 * 
	 * @throws NumberFormatException if conversion to numeric number is impossible.
	 */
	private static void run() throws NumberFormatException {
		generate.get().stream().filter(Objects::nonNull).map(toString.andThen(add3).andThen(toInteger)).forEach(echo);
		echo.accept(join.apply(generate.get()));
		List<Integer> list = generate.get().stream().map(toInteger).collect(Collectors.toList());
		echo.accept(list);
		echo.accept(sum.apply(list));
	}

	/** Output */
	static Consumer<Object> echo = v -> System.out.println(v);
	/** Generate */
	static Supplier<List<String>> generate = () -> Arrays.asList(null, "1", "2", "3");
	/** Object to String */
	static Function<Object, String> toString = v -> String.valueOf(v);
	/** Object to Integer */
	static Function<Object, Integer> toInteger = v -> Integer
			.parseInt(Optional.ofNullable(v).orElse("1").toString());
	/** Add "3" */
	static UnaryOperator<String> add3 = v -> v + "3";
	/** Join comma */
	static Function<List<String>, String> join = v -> v.stream().filter(Objects::nonNull).collect(Collectors.joining(","));
	/** Sum integer list */
	static Function<List<Integer>, Integer> sum = v -> v.stream().filter(Objects::nonNull)
			.collect(Collectors.summingInt(Integer::intValue));
}

```

`Function<引数, 戻り値>`と宣言して、あとは好きな処理を書くだけ。
<ul>
<li>.andThenメソッドでFunctionを合体できる(連続して実行的な)
<li>引数なしなら`Supplier`、.get()メソッドで実行
<li>戻り値なしなら`Consumer`、.accept()メソッドで実行
<li>引数１つ、戻り値１つなら`Function`、.apply()メソッドで実行
<li>引数と戻り値の型が同じなら`UnaryOperator`、.apply()メソッドで実行
    (`Function<String, String>`ってやってもいいから実質不要)
</ul>

まぁほかにもいろいろありますけど、公式参照されたし。


普段メソッドで書いてるものも、Funtionで書くことによって
めっちゃ行数減ったり、見やすくなったりしますね。

javaDocが見にくくなるのが難点？

にしてもめちゃくちゃスマートになりますよねこれ...
MayaPlugin C++ アウトライナ 取得


アウトライナに表示してる特定のオブジェクトくれよ！一覧でいいからくれよ！
defaultObjectSetがとりたいと仮定する。

![defaltObjName.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/9cf39307-d97d-6721-b85f-9c6e22943f80.jpeg)

あげる。どこかで呼んでください。

```perl:test.cpp
	Printf("---- name start ----- ");

	MItDependencyNodes Itdag;
	for (; !Itdag.isDone(); Itdag.next())
	{
		MFnDependencyNode dn;
		dn.setObject(Itdag.item());
		const char *nodeName = dn.name().asChar();
		Printf("ThisName:/ %s\n", nodeName);
	}

	Printf("---- name end ----- ");

``` 

MItDependencyNodes を使えばアウトラインに出てる奴全部取得できる！

以下VisualStudioの出力結果。赤字は社内プラグインなので伏せ
![list.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/46fffff1-1c71-ab9c-d714-12081d1db1dc.jpeg)

よけいなのめっちゃでてる。なんで？アウトライナには５こぐらいしかでてなかったよ？

それはアウトライナのDisplayの表示項目のせいだよ。
![Dhispy.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/54d5ba86-cfdd-eaf5-f2e3-c28dcb489a62.jpeg)

他にもデフォでいろいろチェック入ってるから注意してね。
いや、DAG Objects Obnly状態の物が欲しい。フィルターとかかけられないの？

かけれるよ。

```perl:test.cpp
	Printf("---- name start -----\n ");

	MItDependencyNodes Itdag(MFn::Type::kSet); //単体走査タイプ指定
	for (; !Itdag.isDone(); Itdag.next())
	{
		MFnDependencyNode dn;
		dn.setObject(Itdag.item());
		const char *nodeName = dn.name().asChar();
		Printf("ThisName:/ %s\n", nodeName);
	}

	Printf("---- name end -----\n ");
```

初期化の時にタイプ指定するとフィルタリングできるよ。他にも複数指定とかできるけどMItType系のフィルタークラスがあるからそれにMIntArray系で指定できたはずだよ。面倒だから誰か書いて。
重要なのはここで
MItDependencyNodes Itdag(MFn::Type::kSet); //単体走査タイプ指定
MFn::Type::kSetを指定したけどなんでKSetなの？

アトリビュートをみるとobjectSet:とかいてあるよ。これらはkSetになるよ。なんでKobjectSetじゃないの？そういう所だぞAutDesk！
![kSet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/ceebc31a-0483-bd86-80b2-22012b399056.jpeg)

visual studio の表示結果

![kirei.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/ff5c291e-7c87-d449-3c29-00e93a362e23.jpeg)

更新で呼んでるので何度も表示されるけど
だいたい合ったのでよしとする。

## 重要なのは　MItDependencyNodes　クラス
他にもMIt系はたくさんある!Itってのはイテレーターの略です。ぶん回して走査するので軽くはない。
Maya2018の公式リファレンスをみるといい。英語だから読みたくないけど。大正義の情報源はここ。
http://help.autodesk.com/view/MAYAUL/2018/JPN/?guid=__cpp_ref_class_m_graph_editor_info_html

![MIt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255687/25af0b5d-866b-2ecb-12ca-8a9a7d81db23.jpeg)

さよなら