OmniAICreator/Qiita-1.07M huggingface dataset:
QX電装講座 #1 マイコンってなんなの?

# はじめに
電装に集いし初心者達へ、今回は多くのチームの滑空機に載せられているコンピュータであるマイコンと、マイコン・オブ・ザ・マイコンであるArduinoについて書いていこうかと思います。

# そもそも何で入れてるの?
マイコンを滑空機に載せている理由は大きく分けて2つの用途があります。

- コントローラ用
- ロガー用

では、これらについて詳しく述べていこうかと思います。

## コントローラ用

コントローラーの説明の前に、まずは滑空機をどうやって操作するかという話から始めます。

滑空機では大まかに2つの操舵方法が存在します。一つが重心移動。これはパイロットが重心の位置を変えることで操舵します。そしてもう一つが尾翼を振ることで操舵させる方法です。基本的に操舵の方法としてはこの2つがあります。
さらに、尾翼を動かすには更に2つの操舵方法があります。一つがワイヤーリンケージを這わせることで操舵する方法です。これは文字通りワイヤーを使って操舵する方法です。
もう一つの方法がサーボモーターを用いた方法です。これは、サーボモーターという指定された角度を出すことができるモーターを使って尾翼を操る方法です。
![Servomotor_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484148/e90159db-dc65-5595-f856-faece8d3a438.jpeg)
(Wikipediaより引用)

っと、まあ操舵方法でも様々な方法があります。わけわからなくなってしまったので、ここいら辺でまとめます。
操舵方法は大きく2つ、さらに尾翼を振るにも2種類、

- 重心移動(Pが重心の位置を変える)
- 尾翼(尾翼を動かしちゃう)
 - ワイヤーリンケージ(ワイヤーで振る)
 - サーボモーター(モーターで振る)

といった感じです。

QXではサーボでの操舵と重心移動での操舵を採用しているので、サーボモーターを動かすために電装が必要になってきます。サーボモータについては後ほど詳しく書いていきます。

また、他にも例えば足蓋をしまう、閉じるといった動作などに使用されます。

## ロガー用

ロガーは飛行時のデータを残すためにものです。今後の設計をより良いものにするため、加速度センサーや風速計、そもそも舵をどっちに切ったかなど様々なデータを収集します。そして、これで収集したデータはSDカードなどの媒体に保存され、飛行後に回収された機体から保存媒体を回収してデータの解析を行います。

# 気づいたかもしれないが…

ここまできて、ふっと思った人もいるかもしれない。
「自分らは必要なのだろうか?」
その答えは間違いなくYesです。

尾翼が動かせずに飛行禁止区域に突入してしまったら?
足蓋が閉まらなくて飛距離が落ちたら?
今後の研究材料に今年の機体の性能が必要だったら?

自分たちは**プラスを作ることはできない**。でも、自分たちがいないと**大きくマイナスになることがある**。
要するに、主翼が作った揚力、尾翼が作った安定感、それを最大限に活用するためにマイナス要因を可能な限り排除する縁の下の力持ち的な役割が電装です。

ということで、電装が最強です。異論は認めない。

# マイコン

話が大きくそれてしまいましたが、コントローラーを作るにもロガーを作るにも、電子的な機械で動かしている以上はコンピューターが必要になってきます。ただ、机の上にあるパソコンを積むかと聞かれると、旅客機なんかじゃあるまいし、んなわけ無いです。着水が前提ですから、二度と動かなくなることも念頭に入れないといけません。

そこで登場するのがマイコンです。マイコンとはマイクロコンピューターと呼ばれるもので、鳥界隈で一般的に用いられているマイコンがArduinoです。

![Arduino_Uno_-_R3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484148/7b07ec5c-6ad9-f4e4-877d-b5c3b1233e4e.jpeg)
Arduino UNO(Wikipediaより)

ArduinoはArduinoボードとIDEによって構成されているマイコンで、C言語風に書けるのが特徴の一つです。基本的には動作する分にはArduino一台で動作できる点や、IDEにプログラムを書いてすぐに実行できるという点でプログラミングがしやすく、初心者でも簡単にプログラムを作ることができます。

写真で見える黒い四角いプラスチックに多くの穴が開けられているが、これにセンサーなどを刺すことで接続ができるため、比較的接続も簡単な部類には入るかと思います。

# ArduinoIDEを入れよう

では、早速Arduinoを動かすための準備を行いましょう。見て分かるように、Arduinoにはパソコンのようにキーボードなどの入力するための機材がありません。そのため、USBでパソコンと接続して専用のソフト(ArduinoIDE)でプログラミングを行います。

ということで、ArduinoIDEをインストールしてみましょう。
1. Arduino財団のサイトに行きます。[Arduino](https://www.arduino.cc/)
2. ヘッダー内にあるSoftwareからDownloadを選択します。<img width="1440" alt="スクリーンショット 2019-09-01 23.40.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484148/a0934f0b-4e78-835b-34f8-febfc14c3c35.png">
3. Download the ArduinoIDEから自分のパソコンに合わせてデータをダウンロードします。<img width="1440" alt="スクリーンショット 2019-09-01 23.40.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484148/c4e20922-1150-6004-3264-96d8a10531dc.png">
4. 財団が寄付を呼びかけてくるので無視します。(しても内容は変わらないので、したければ止めはしません)<img width="1440" alt="スクリーンショット 2019-09-01 23.44.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484148/da19ae28-39e5-9c63-3f91-f38a278a14a0.png">
5. 圧縮されてダウンロードされるので、そのままインストールしてください。

これでパソコンの準備が整いました。

次回はArduinoの使い方を勉強して、早速プログラミングしてLEDを光らせてみましょう!

[QX電装講座 #2 Arduinoを使ってみた](https://qiita.com/GoshBird/items/078b19db33424d098b53)
HackerRank　Python3　Data structuresを解く　その2

#はじめに
未来電子テクノロジー（https://www.miraidenshi-tech.jp/intern-content/program/）
でインターンをしているrayaと申します。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

#今回の内容
前回の続きです。Data StructuresのMediumレベルにも挑みます。
前回の内容
↓
https://qiita.com/breakthrough/items/7f59a60133fbe569eb28

#Sparse Arrays
与えられたstringとqueriesが一致した場合、一致した数を配列の要素にして返す問題。

```python
def matchingStrings(strings, queries):
    d={}
    res=[]
    for s in strings:
        if s in d:
            d[s] += 1
        else:
            d[s] = 1
    for q in queries:
        if q in d:
            res.append(d[q])
        else:
            res.append(0)
    return res
```
一発では解けませんでした。さすがMediumレベル。
関数内に、最初に連想配列とリストを用意します。
一致した場合にその数を返す問題なので、stringsと一致した数をセットで扱える連想配列がぴったりです。
・if s in d:sはstringsから取り出した要素。その要素が新しく作った連想配列dの中にあるかどうかで条件分岐。無いならば、初期値で１を与え、あったならばさらに１を加える。
・res.append(d[q]):先に連想配列dの中にsがあるかを判別し、あれば１を足しているため、d[q]を指定することでd[s]と一致している値を取り出し、配列resの末尾に追加できる。

#Print the Elements of a Linked List
連結リストの要素を出力する問題。
連結リストとは、データを繋げて管理するデータ構造です。
１つのノードにデータの値と次のノードへのアクセスを格納して、それらのノードを繋げてデータの場所を検索できます。
新たにデータを挿入・削除しやすい一方で、ノードを１つずつ辿っていかないといけないので検索に時間がかかる場合があります。

参考↓
http://bacspot.dip.jp/virtual_link/www/si.musashi-tech.ac.jp/www/Python_IntroProgramming/05/index-1d.html

これはもともと記述してあるコードです。
理解半分なので間違っていたらコメントいただきたいです。
最初に連結リストのclassを作り、ノードのデータとそのデータを取り出すメソッドを定義します。
Noneは初期値です。
・self.data：ノードにデータを格納している場所
・self.next：次のデータへのアクセス
・self.head：先頭を取り出す
・self.tail：末尾を取り出す

```python
class SinglyLinkedListNode:
    def __init__(self, node_data):
        self.data = node_data
        self.next = None

class SinglyLinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    def insert_node(self, node_data):
        node = SinglyLinkedListNode(node_data)

        if not self.head:
            self.head = node
        else:
            self.tail.next = node

        self.tail = node
```

以下が答えです。

```python
def printLinkedList(head):
    if head is not None:
        print(head.data)
        printLinkedList(head.next)
```

先頭があればそのデータを取り出し、関数内で同じ関数を定義しているのでさらにその次のデータも取得しています。
難しい。。。

#終わりに
難しかったです。
こういう問題が自力で解けるようになりたいです。
頑張ります。
Devise　ユーザーネームとパスワードでログインしたい

deviseでは、最初の状態だと、メールアドレスとパスワードでログインするようになっているので、ユーザーネームとパスワードでログインできるように変更したい。

**すでにdeviseはインストールされていることが前提**

#Userテーブルを作成する。


`rails g devise users`
で作成する。

Userテーブルが作成されたねー

#ユーザーネームを収納するカラムを作成する。

deviseが用意したテーブルにはユーザーネームを収納するカラムがない！
ので、カラムを作成する。

ターミナルで、
`rails g migration AddUsernameToUsers name_string`

実行。
新しいカラムを作る時に、最初の文字は大文字にするって教えられたけど、アンダーバーでも良さそう。よくわかりません。

そして

`rails db:migrate`

ユーザーネームのカラムができましたねー

#application_controllerに書き加える。

deviseで用意されたコントローラーは、直接修正することができないので、ユーザーネームを追加したよってことをapplication_controllerに書き加えなければいけない。

`before_action :configure_permitted_parameters, if: :devise_controller?
`
これは、actionが実行される前に、`configure_permitted_parameters`が実行されるよ、ってこと

それでこの後に、
`configure_permitted_parameters`
を定義する。

`protected
def configure_permitted_parameters
    added_attrs = [ :username]
end
end`
これは、usernameのデータ操作していいよって言ってるものです。


##これでおっけー！
Intuneで、iOSアプリのミニマムバージョンを設定する

iOS13リリースに伴い、9月でiOS11未満がIntuneではサポートされなくなる。

https://docs.microsoft.com/ja-jp/intune/in-development#notices

--以下引用--
変更の計画: Intune で 9 月に iOS 11 以降のサポートを開始
9 月に、Apple によって iOS 13 がリリースされる予定です。 Intune の登録、ポータル サイト、および Managed Browser では、iOS 13 のリリース直後に iOS 11 以降がサポートされるようになります。

7 月以降、iOS 10 とポータル サイトが使用されている MDM 登録デバイスには、OS またはデバイスのアップグレードを求めるメッセージが表示されます。 アプリケーション保護ポリシー (APP) を使用する場合は、[iOS オペレーティング システムの最小要件 (警告のみ)] アクセスの設定を行うこともできます。
--引用ここまで--

日本語訳がイマイチだけど、iOS11以降のみサポートするよ、と言うことらしい。

その日が来たら強制でブロックされるんだろうけど、調べてみたらXデーまでの対応はいくつか選択できそうだったので、備忘録かねてまとめてみた。

#OSバージョンによる条件付き起動
OSバージョンが要件を満たさない場合は「警告」「ブロック」「ワイプ」と設定できる。

Intune→クライアントアプリ→アプリ保護ポリシー→プロパティ→条件付き起動から設定できる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/ded5fade-3aea-22ec-e25d-0a407438c720.png" width=75%>

試してはないので何とも言えないけど、11.0以下はブロック、12.0以下は警告、という方法も取れそう。

#OSバージョンアップの強制

いっそOSの更新を強制する、という方法もある。
https://docs.microsoft.com/ja-jp/intune/software-updates-ios

ただ、メモリの空き容量で失敗するケースもあるだろうし、強制アップデートはちょっと怖いな・・・。


#アプリごとのOSミニマムバージョン指定

アプリごとに、最低限のOSバージョンを指定できるが、条件を満たさない場合はIntuneからインストールされないだけで、強制力は持たせにくい。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/dc7b6ac7-8e11-53dd-c149-0fbbd8638296.png" width=75%>


#まとめ

OSバージョンを強制したい場合は、条件付き起動で設定しておくのがベター。
iOS13が出たらいろいろ変わりそうなので、早めにユーザーにはアナウンスして、バージョンアップしてもらおう。
ブラウザ Chrome（バージョンアップ）で表示が拡大されるのを元に戻す方法

ブラウザChromeのとあるバージョン以降、表示が拡大される。
表示をバージョンアップする前の大きさに戻したい場合、Cromeの起動時にオプションを付けることで対処可能。

### 手順
Chromeのアイコンを右クリックし、プロパティファイルを開く。

![chrome1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/dedee3c4-a60d-73d3-f016-48f3c1a0a610.png)

上記プロパティ画面の「リンク先」のChrome起動のコマンドにオプションを付ける。

変更前
`"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"`

変更後
`"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -high-dpi-support=1 -force-device-scale-factor=1`

Chromeのアイコンをダブルクリックして、起動すると元の表示でChromeが起動される。


以上
[JavaScript]プルダウンで生年月日を入力するフォーム

はじめまして。Leeと申します。
プログラミングの学習を始めて約半年の私が詰まったところなどをまとめていきます。

今回が初投稿になります。第一弾は下図のような、JavaScriptで生年月日を年/月/日と分けてプルダウンで選択するフォームを作成します。



<img width="539" alt="スクリーンショット 2019-08-31 23.56.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438220/4ea87fbd-7289-3c8d-f9ec-63836efd3f0f.png">

例えば２月３０日など存在しない日付などは選べないようにします。
なので日の選択肢は、年月によって動的に変化することを狙います。

##html

```html:index.html
<div>
  <select id="select_year" name="year"></select>年
  <select id="select_month" name="month"></select>月
  <select id="select_day" name="day"></select>日
</div>
```

フォームの中にこれを設置します。年月日それぞれの<select>タブがあって、それぞれに選択肢を```<option>```をJavaScriptで生成します。
JavaScriptで指定しやすいようにするためにidを付与しておきます。
name属性はフォームで送られる情報の名前になります。

##JavaScript

```JavaScript:main.js
(function(){
  'use strict';

   const select_year = document.getElementById('select_year');
   const select_month = document.getElementById('select_month');
   const select_day = document.getElementById('select_day');
   let i;

  function $set_year(){
    // 年を生成(100年分)
    for(i = 1919; i < 2020; i++){
      let op = document.createElement('option');
      op.value = i;
      op.text = i;
      select_year.appendChild(op);
    }
  function $set_month(){
    // 月を生成(12)
    for(i = 1; i <= 12; i++){
      let op = document.createElement('option');
      op.value = i;
      op.text = i;
      select_month.appendChild(op);
    }
  }

  function $set_day(){
    //日の選択肢を空にする
    let children = select_day.children
    while(children.length){
      children[0].remove()
    }
    // 日を生成(動的に変える)
    if(select_year.value !== '' &&  select_month.value !== ''){
      const last_day = new Date(select_year.value,select_month.value,0).getDate()

      for (i = 1; i <= last_day; i++) {
        let op = document.createElement('option');
        op.value = i;
        op.text = i;
        select_day.appendChild(op);
      }
    }
  }

  // load時、年月変更時に実行する
  window.onload = function(){
    $set_year();
    $set_month();
    $set_day();
    select_year.addEventListener('change',$set_day)
    select_month.addEventListener('change',$set_day)
  }
})();

```

JavaScriptは即時関数でHTMLの読み込みが終わってから実行します。

簡単に解説すると、```$set_yaer```と```$set_month```はfor構文で```<option>```を生成して、それぞれの```<select>```の子要素として配置しています。

一度作ってしまえばいいので、直接HTMLに```<option>```を配置してもいいかもしれません。

日に関しては、まず選択肢を全て空にします。日は２８日以上３１日以下なのでそれだけを変化させてもいいですが、処理が面倒そうだったので、全部消して再配置する方法をとりました。

年月が未選択の時以外に年月から最終日を取得しています。
最終日が分かれば、あとは年月と同様に```<option>```を最終日分生成します。

最後に画面の更新時に年月をセットし、年月が選択された時に日の選択肢を配置しています。
ただもし、年月を選びなおした時に日を再配置するため、addEventListenerのchangeを使っています。

##まとめ
年月からその月の最終日を取得して```<option>```を生成する処理でした。
実際にはバリデーションでリダイレクトされた時に元の値を復元することの方がなかなか理解できず苦労しました。

初めて書いたので、おかしい点やもっとこうした方がいいなどのアドバイスなどあれば、よろしくお願いします。

#参考リンク
https://www.hypertextcandy.com/year-month-date-form-example-with-javascript-and-laravel
Capistrano3+Puma+Rails5でデプロイ

Gemfileにcapistrano3-pumaを追加してbundle install。

```Gemfile
gem 'capistrano3-puma' , group: :development
```

puma関連のtaskが使えるようにcapistrano3-pumaライブラリを読み込む。
以下を追加。

```Capfile
require 'capistrano/puma'
install_plugin Capistrano::Puma  # Default puma tasks
```

`cap deploy`　時にpumaがrestartされるように設定を追加。

```config/deploy.rb
namespace :deploy do
  task :restart_puma do
    invoke 'puma:stop'
    invoke! 'puma:start'
  end
end

after 'deploy:finishing', 'deploy:restart_puma'
```

追加。

```config/deploy/production.rb
set :puma_init_active_record, true
set :puma_bind, 'unix:///deploy/my_app/shared/tmp/sockets/puma.sock'
set :puma_daemonize, true
```

本番用puma設定ファイルの出力

```
$ bundle exec cap production puma:config

// config/deploy/production.rbの内容を加味して設定ファイルが作られる。
00:00 puma:config
      Uploading /deploy/my_app/shared/puma.rb 100.0%
```

`bundle exec cap production deploy`　でいつもどおりデプロイ・再起動できる。

---

ほぼデフォルトの設定で出力したpuma.rbの内容。

```/deploy/my_app/share/puma.rb
#!/usr/bin/env puma

directory '/deploy/my_app/current'
rackup "/deploy/my_app/current/config.ru"
environment 'production'

tag ''

pidfile "/deploy/my_app/shared/tmp/pids/puma.pid"
state_path "/deploy/my_app/shared/tmp/pids/puma.state"
stdout_redirect '/deploy/my_app/shared/log/puma_access.log', '/deploy/my_app/shared/log/puma_error.log', true


threads 0,16



bind 'unix:///deploy/my_app/shared/tmp/sockets/puma.sock'

workers 0



daemonize


restart_command 'bundle exec puma'


prune_bundler


on_restart do
  puts 'Refreshing Gemfile'
  ENV["BUNDLE_GEMFILE"] = ""
end
```

`workers 0` なので シングルモードでの起動。
アクセス少ないサイトなのでこれで十分。
メモリ1GのサーバなのでPassengerのときは残りメモリが200MBを切っていたが、
250MB程度になった。

Railsで`force_ssl`していたがNginxでリバースプロキシするようになったので
リダイレクトループが起きてしまった。常時SSLはNginxの設定で実現するように移行。
Androidで書き出したファイルをPCへコピーする方法

#0. はじめに
Androidアプリを開発してて、ファイル書き出しをローカルに行うアプリを開発している時に、実際にできたファイルが確認したい！と思った時に、adb shell でPCへコピーしてくる方法をまとめておきます。

#1. PCコピーまでのコマンド
adbコマンドでshellを起動します

```ruby:qiita.rb
adb shell
```


そして、ファイルを書き出したアプリを起動します。

```ruby:qiita.rb
run-as {アプリのパッケージ名}
```

ちなみに。。。パッケージ名がわからない時は、shellを起動した後に、

```ruby:qiita.rb
pm list package
```

とすると、Android端末にインストールされているパッケージが全て列挙されます。

その後、ファイルのある場所（/data/data 配下）を探し、ファイルのある場所のパスをメモしていてください。
また、この時、ファイルへのパーミッションを chmod コマンドで変えておきます。

あとは、PC上のディレクトリを指定して、このコマンドを打つだけ。

```ruby:qiita.rb
adb pull {ファイルのある場所} {PC上のコピーしたい場所}
```

PC上の指定した場所にファイルがコピーされていると思います。
ここで、Permisson denied されたら、ファイルのパーミッションを変えるか、sdcardなどのアクセス可能な場所にファイルを移動してからPCローカルへpullしてみてください。
VisualStudioで吐き出すＸＭＬドキュメントを読み込んでみる

#VisualStudioの吐き出すXMLドキュメント
VisualStudioの吐き出すXMLドキュメントを読み込んで、名称・タイプ・名前空間・サマリのコメントに分けたら何かに使える？と思ってテスト的にコードを書いてみました。


        public class memberInfo
        {
            public string name;
            public string nameSpace;
            public string summary;
            public string type;
        }

        private List<memberInfo> loadMemberInfo(string fileName)
        {            
            //ＸＭＬ読み込む
            var xml = new XmlDocument();
            xml.Load(fileName);

            var memberInfoList = new List<memberInfo>();
            foreach (XmlNode node in xml.GetElementsByTagName("member"))
            {
                var item = new memberInfo();

                //タグのname属性を取得
                var attrName = node.Attributes.GetNamedItem("name");
                if (attrName != null)
                {
                    var temp = attrName.Value.Split(':');

                    item.type = temp[0];

                    var tempName = temp[1].Split('.').ToList();
                    item.name = tempName.Last();

                    tempName.RemoveAt(temp.Count() - 1);
                    item.nameSpace = string.Join(".", tempName);


                }

                //サマリータグを持ってくる
                var summary = node.ChildNodes.Cast<XmlNode>().FirstOrDefault(_ => _.Name == "summary");
                if (summary != null)
                {
                    item.summary = summary.InnerText;
                }


                memberInfoList.Add(item);
            }

            return memberInfoList;
        }

"出力"に出してみる

            var memberInfoList = loadMemberInfo(@"ファイルパス");

            foreach (var item in memberInfoList)
            {
                var summary = item.summary.Replace("\r\n", "").Replace("\"", "\"\"").Trim();
                System.Diagnostics.Debug.WriteLine(string.Format("{0},{1},{2}", item.name, item.type, summary));
            }
僕でもわかるasync/await

サルでも分かるで挫折し、ミジンコでも分かるで挫折したわたしに。

> サル ＞ ミジンコ ＞ 僕

僕でも分かるasync/awaitまとめました。
モダンブラウザで動きます。Developer Toolのコンソールで試してみてください。
（本記事のサンプルはgoogle.comドメインのページでお試しください。googleさんお邪魔します）

## fetch APIで試す

ブラウザからAjaxリクエストなどに使えるfetch APIで試します。

jQueryなどのAjax通信を思い出すと、レスポンスを取得した際のロジックはコールバック関数で定義しますね。fetchを使うと以下のように同期処理っぽく書けます。

```js
(async () => {
	const response = await fetch("https://www.google.com")
    const html = await response.text()
    console.log(new DOMParser().parseFromString(html, "text/html").title)
})()
```

```shell-session:実行結果
Google
```

awaitで呼び出すのはasyncで定義された関数です。
また、awaitはasyncで定義された関数の中で使う必要があります。
トップレベルなどで使うには上記のように無名関数で囲います。
（Chrome DevToolsのコンソールではasyncの無名関数が省略できます。便利。）

```js
async function hoge() {
    await ...
}

(async () => {
    await hoge()
})()
```

ちなみにエラー処理はこんな感じ。

```js
(async () => {
    try {
        const response = await fetch("https://not_exists_domain")
    } catch (error) {
        console.log(error)
    }
})()
```

## ループ処理で使う

### forEachで使う

forEachなどのコレクション用の関数内で利用するときは注意が必要です。
以下は構文エラーにはなりませんが、1週目と2週目が同時に実行されてしまいます。
しかもawait処理の終了を待ってくれません。

```js

(async () => {
    ["https://www.google.com", "https://www.google.com/doodles/"].forEach(async (url) => {
        const response = await fetch(url)
        const html = await response.text()
        console.log(new DOMParser().parseFromString(html, "text/html").title)
    })
    console.log("finish")
})()
```

```shell-session:実行結果
finish
Google
Doodle
```

### 順次実行する

順番に実行するためにはforやfor-ofなどを使います。

```js
(async () => {
    for (const url of ["https://www.google.com", "https://www.google.com/doodles/"]) {
        const response = await fetch(url)
        const html = await response.text()
        console.log(new DOMParser().parseFromString(html, "text/html").title)
    }
    console.log("finish")
})()
```

```shell-session:実行結果
Google
Doodle
finish
```

### 並列実行で全部終わるのを待つ

forEachをmapに変えてPromise.allを使います。

```js
(async () => {
    const results = await Promise.all(
        ["https://www.google.com", "https://www.google.com/doodles/"].map(async (url) => {
            const response = await fetch(url)
            const html = await response.text()
            return new DOMParser().parseFromString(html, "text/html").title
        })
    )
    console.log(results)
    console.log("finish")
})()
```

```shell-session:実行結果
["Google", "Doodle"]
finish
```

## まとめ

Promise.allが使えるのはasync/awaitの実体がPromiseだからですね。
async/awaitの入門記事にはPromiseから入るものが多く難しい印象でしたが、とりあえず使うためには本記事の理解くらいでもいいのかなーと思って書きました。

使い慣れてきたらPromiseの理解を深めていきましょう！
コンパイルなしでvueコンポーネントを外部ファイル化


webpackなどのコンパイルツールを利用せずにvueを利用して、
コンポーネントを外部ファイル化してみた。

単一ファイルコンポーネント（.vue）なら、
<template>タグを利用するところを.jsでテンプレートリテラルを利用します。

```js:home_component.js
const template = `
<div>
	{{ message }}
</div>
`;

export default {
    template,
    data() {
        return {
            message : "home page"
        }
    }
}
```


```js:child_component.js
const template = `
<div>
	{{ message }}
</div>
`;

export default {
    template,
    data() {
        return {
            message : "child page"
        }
    }
}
```

インポートする側では普通にimportして、利用します。

```js:import.js
import HomeComponent from './home_component.js';
import ChildComponent from './child_component.js';


const router = new VueRouter({
    mode: "history",
    routes:[
        { name:'home',path: '/', component: HomeComponent },
        { name:'child',path: '/child', component: ChildComponent },
    ]
});

const app = new Vue({
    router
}).$mount('#app');
```

htmlでは、cdnでvue, vue-routerを読み込みます。

```html:index.html
<html>
<head>
    <style type="text/css">
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<div id="app" v-cloak>
	<router-link to="/">home</router-link>
	<router-link to="/child">child</router-link>
    <router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="import.js" type="module"></script>
</html>
```


<img width="389" alt="スクリーンショット 2019-09-01 22.19.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274034/f09dc5f8-79b4-3b06-0e62-040d7fdb3ee3.png">
<img width="422" alt="スクリーンショット 2019-09-01 22.21.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274034/b69d7528-8aa4-d6a8-57cf-e81abca26c56.png">
[VMware]「この仮想マシンは使用中の可能性があります」の対処法

# 仮想マシンが開けない
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/9c0db68a-2b8c-80f9-9b3d-ceecfb33af3d.png)
VMwareでDebianを開こうととするとこんなエラーが出ました。
前の時に正しく終了しなかったからでしょうか？
取り合えず、「所有権を取得」をクリックして、解決を試みますが。。。

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/91b9fd2b-c4a8-a575-b29c-6e5363158e71.png)
失敗しました。

# 解決方法
このままではまずいので調べてみると、どうやら強制終了したときに、ロックファイルが残ってしまったようです。そのためロックファイルを削除すればよいとのこと。

削除するためにVMware 仮想マシンの実体ファイルがある場所を開きます。もし、場所を忘れてしまっても、エラーにパスが書かれているので大丈夫ですね。
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/e908c96f-020d-ddf4-8bc1-4fff1a4deb15.png)
削除するべきファイルは「~vmx.lck」だけでいいのでそれを削除します。(今回の例では黒枠のファイルです。)

その後、無事に起動ができました。

# 正しく終了させましょう
強制終了してしまうと、このようなことが起こってしまうことがあります。そのため、仮想マシンは正しく終了させましょう。
error storing credentials, 今日のdocker(73) error(32)

「Cの可変長引数とABIの奇妙な関係」のコメントのプログラムをdockerで
https://qiita.com/kaizen_nagoya/items/79e771ff681fb27f6070

の結果をdocker hubに登録しようとしたらエラーになった。
docker loginしようとしたらエラーになった。
ブラウザでパスワードを変更したらlogin できたことがあったような気がした。（どこかのキャッシュにごみが入っているかもなど）
ブラウザでパスワードを変更した。
再度loginしようとしてもエラーになった。

```shell-session:macOS
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: kaizenjapan
Password: 
Error saving credentials: error storing credentials - err: exit status 1, out: `error storing credentials - err: exit status 1, out: `The user name or passphrase you entered is not correct.``
```

あしたやり直そう。

```shell-session:macOS
$ docker login
Authenticating with existing credentials...
Stored credentials invalid or expired
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username (kaizenjapan):       
Password: 
Login Succeeded
```

別の機材では入れた。
# 可能性
Kyeboardのドライバの不調で、大文字・小文字の切り替えがうまくできていない。

Keyboardのドライバの不調で、英数字とかなの切り替えがうまくできていない。

日本語変換ソフトの不調で、入力したつもりの文字がアプリにうまく渡っていない。

アプリの不調で、入力したつもりの文字がアプリ内にうまく渡せていない。

これらの場合で、エディタなどブラウザ以外のソフトで入力してから、切り貼りするとうまく渡ることがある。

# Reference
Error一覧 error(0)
https://qiita.com/kaizen_nagoya/items/48b6cbc8d68eae2c42b8

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.
### 文書履歴(document history)
ver. 0.01 初稿 20190901
ver. 0.02 可能性追記 20190902
ver. 0.03 add URL　20240508
### 最後までおよみいただきありがとう4ざいました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
Apple DEPなのにIntune上のiPhone・iPadの所有権が、個人になってしまう。

組織で利用しているiPhoneやiPadは、MDMで管理しているケースは多いと思う。このMDMで管理する際にApple DEP(Device Enrollment Program)を利用すればいくつか管理がラクになる。たとえば、「キャリアにiPhone発注したら、自動でMDMにデバイスを登録してくれる」とか「管理できる範囲が広がる監視モードを適用できる」など。

また、Intuneにはデバイスの所有権という概念があり、デバイスのかなりの範囲の情報をみることができる「所有権が企業」のモードと、プライバシーに配慮してデバイスの一部の情報しか見えない「所有権が個人」のモードがある。どちらもセキュリティポリシーは同じものを適用できるけど、見える情報の範囲が違う。

さて、DEPは組織でないと手配できないので、DEPで手配している＝所有者は企業。・・・なんだけど、10%ぐらいのデバイスで、Intune上の所有権が企業でなく、個人になってしまってた。非DEPは問題ないんだけどな・・・なぜだろう。

自分の備忘録として、原因と対応をまとめてみた。
※解釈や条件の理解が間違えているかもしれない。

#原因

以下の2つの条件を満たすと発生するらしい。
・ポータルアプリの認証でプロファイル割り当てをする場合
・DEP登録後、24時間以上かかった場合

先に後者について。


巡り巡って、マイクロソフトのこんな記事にたどり着き、その中にこんなコメントが。
[Apple の Device Enrollment Program を使用して iOS デバイスを自動登録する](
https://docs.microsoft.com/ja-jp/intune/device-enrollment-program-enroll-ios#create-an-apple-enrollment-profile)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/76d3e344-78ea-85b5-05bb-3e7703ae297f.png" width=75%>

今一つ解釈しづらいので英語版。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/d64e966a-f7d8-6130-cd09-575f212d2be4.png" width=75%>

どっちもわかりづらいわ！

超意訳すると「DEPデバイスにポータルアプリをインストールしてから24時間以内にポータルアプリでログインしないと、登録に失敗して所有権が個人になっちゃうよ」ってことっぽい。
※突っ込み・指摘、お待ちしています。


前者は、ユーザーグループでプロファイルを変えている場合とか、多要素認証を有効にしている場合、条件付きアクセスを使う場合。これらのケースではポータルアプリでの認証が必須なので、確実にひっかかる。EMS使って条件付きアクセスを使わないケースはほとんどないとおもうので、ほとんど引っかかるんじゃないだろうか。

さっきの24時間制限はどうもAppleの仕様らしいけど、DEPで登録後デバイスが納品されてキッティング完了まで24時間以内に完了なんて、ありうるのか！？・・・困ったな。

#とりあえずの対応

すでに所有権が正しくないデバイスは、所有権を企業に変更する。手間だけどこれで所有権は正しくなる。

#要検証

文言通りなら、ポータルアプリをダウンロードして24時間以内にキッティングすればいいのだけど、どうも腑に落ちない。アプリをダウンロードするだけじゃデバイス登録はされないしな…。

・DEP登録通知が来て、Intuneに同期してから24時間
・デバイスの電源を入れてキッティングし始めてから24時間
・ポータルアプリをインストールして、初めて起動してから24時間

多分、これのどれかが発動条件だと思うので落ち着いたら検証してみる。
なんとなくだけど2番目ぽいと思ってて、DEP端末をフルワイプして電源入れて、24時間ちょっと待ってみる。

#まとめ

これから検証。結果はまた投稿します。
(小ネタ)WSFC環境のファイルサーバーに別名でアクセスする

#概要
ファイルサーバーのネットワークリソース名に、別名(Alias)を設定することで、
実際のネットワークリソース名を隠蔽できる。

#どんなときに使えそうか？
システム更改のとき、ちょっと楽できる。(ネットワークリソース名の引継ぎとか)
https://blogs.technet.microsoft.com/askcorejp/2015/04/30/windows-server-2012-cname/

#どうやるの？
ポイントは以下の2点。(両方とも実施が必要)

- DNSにCNAMEを作成する。
- PowerShellで、対象のネットワークリソース名に対して、別名登録する。
    - Get-ClusterResource  "ネットワーク名リソース名" | Set-ClusterParameter Aliases "エイリアス"

#注意点
Windows2012以降からの機能。Windows2008R2とかは対象外。
momoでラズパイカメラモジュールを使うときに映像の回転角度を指定する方法

ラズパイの専用カメラモジュールを使ってケースにおさめて使うときに、映像の角度が合わなくて270度回転させたいなという場面があります。

`raspivid` などの専用コマンドでは `-rot 270` とすれば回転角度を指定することができますが、momoにはそのようなオプションがありません。

でも以下のコマンドを実行することで映像の回転角度を指定することがわかりました。

```
v4l2-ctl -d /dev/videoX -c rotate=270
```

(`-d` でカメラモジュールのデバイス名を指定する。 /dev/video0のときは省略可能。)
`rotate` の設定値は{0, 90, 180, 270} のいずれか。

このコマンドは配信中でも実行可能で、即座に反映されます。

このコマンドは専用カメラモジュールのみ使用可能で、普通のWebcamには効きません。
Xfce環境下でカーソルテーマがまちまちなのを固定する

##Xfce環境下のカーソルテーマ
Xfceでは「設定」→「マウスとタッチパッド」→「テーマ(T)」で好きなテーマやマウスカーソルの大きさ（サイズ）を選択できます。
しかし、再起動するとアプリによってテーマが適用されたりされていなかったり。なんとか固定できないものかと思って調べてみました。

##.Xresourcesを編集する方法
```shell:.Xresources
Xcursor.theme: redglass
Xcursor.size: 64
```
ググってみたら下記の情報が参考にできました。うまくいってバンザイ。redglass好きです。

#####参考にした情報
>Firefoxなどのマウスカーソルを変更する方法
>http://sicp.seesaa.net/article/416756821.html
図解 terminal.sexy その１

###はじめに
terminal.sexyの使い方を画像つきで解説します。画像多め、文字少なめです。

###～ターミナル用ファイルを別の形式に変換する。～
ここでは「.Xresources」ファイルを「.itermcolors」に変換します。


####1.terminal.sexyにアクセスします。
https://terminal.sexy/

####2.選択されていなければ「Import」タブを選択し、赤矢印の枠をクリックし、カーソルを出します。
![ps1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/8ebd587a-d5d3-36a3-7d8e-2f507fe01215.png)


####3.notepadやgeditなどのテキストエディタで「.Xresources」ファイルを開き中のテキストをすべてコピーします。

####4.「2.」でカーソルのでた枠の中を右クリックしペーストを選択します。

####5.赤矢印で指している「Import」をクリックします。
![ps2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/a1fc916b-43d6-1047-05d8-142f6ccbec8d.png)



####6.赤矢印で指している「Export」タブをクリックします。
![ps3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/209a0bb1-f26b-cff4-b53a-c865caadc5e0.png)


####7.赤矢印で指している枠をクリックします。
![ps4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/cc1aeb7f-78de-2049-c6a5-093336614d16.png)


####8.今回は「.itermcolors」なので、「iTerm2」を選択します。(.itermcolorsは主にiTerm2で使われるcolor schemeです。)
![ps5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/2f9751ff-1e25-26ed-905d-4690f6cdeb59.png)


####9.赤矢印で指している「Download」の左隣の「Export」をクリックしてから「Download」をクリックします。
![ps6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448552/ef93932e-49a1-7333-ee5f-7176874c042d.png)


####10.ダウンロードしたファイルを「colorscheme」などのフォルダに配置しよう！

#####間違いや誤解を招く表現ないし箇所があれば、訂正します。2019/09/01
kindでお手軽にKubernetes学習環境を作る

## こんな人におすすめ
- KubernetesやってみたいけどGKEやEKS等のクラウドに出費はしたくない
- とりあえずマルチノードのクラスタをローカルで試してみたい

※ シングルノードで良ければ Docker Desktop に同梱されている Kubernetes を使うほうが早いです。

# kindとは
**K**ubernetes **in** **d**ocker で **kind**。
Kubernetes 公式の[入門ページ](https://kubernetes.io/docs/setup/#learning-environment)でも紹介されていて、dockerコンテナをノードにしてクラスタを組むことができる（？）っぽいです。
ドキュメントには「Kubernetes 1.11+ をテストするために設計されたプロジェクト」と書かれています。

# 前提条件
`docker` と `kubectl` がインストールされていること。

# インストール
[Qick Start](https://kind.sigs.k8s.io/docs/user/quick-start/) に書いてあることそのままですが、以下のコマンドを打ちます。

```sh
$ curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-$(uname)-amd64
$ chmod +x ./kind
```

落としてきたバイナリはPATHの通ったディレクトリに移します。
またバージョンは執筆当時のものなので、必ず公式のドキュメントを確認してください。

# シングルノードのクラスタを立てる
```sh
$ kind create cluster
```

これだけで立てられます。`--name hoge` とするとクラスタの名前を指定できます（デフォルトはkind）
コンテナイメージ取ってきたりControl-Planeの起動したりで結構時間かかります。

うまくいったら、`KUBECONFIG` を設定します。

```sh
$ export KUBECONFIG="$(kind get kubeconfig-path)"
```

ここまでできれば後は `kubectl` コマンドで何でもできます。

クラスタの破棄は

```sh
$ kind delete cluster
```

で簡単にできます。

# マルチノードのクラスタを立てる
次は

- Control-Plane(Master)
- Worker
- Worker

の3台構成でクラスタを立ててみます。

マルチノードクラスタには設定用のYAMLがファイルが必要になるので書いていきます。

```yml:kind-config.yml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
  - role: control-plane
  - role: worker
  - role: worker
```

あとはシングルノードの時と同様にコマンドを打ちます。

```sh
$ kind create cluster --config kind-config.yml
$ export KUBECONFIG="$(kind get kubeconfig-path)"
```

`--config` には先程書いたYAMLファイルを指定します。


```sh
$ kubectl get nodes
```
で確認してみると3台ちゃんと動いていることが分かると思います。

ということで筆者はやっとKubernetesの学習環境を手に入れたのでこれからがんばって勉強していきたいと思います。

# 参考文献
- kind  
  (https://kind.sigs.k8s.io/)
- お手軽Kubernetesクラスタ作成ツール "kind"の紹介 - Cybozu Inside Out | サイボウズエンジニアのブログ   
  (https://blog.cybozu.io/entry/2019/07/03/170000)
X205TA　サウンド対応カーネルのダウンロード

#1. 現役を引退したX205TAにXubuntu18.04を

Xubuntu専用機にすべくX205TAにインストールしました。サウンド対応カーネルがダウンロードできなくなっていました。対応した時のメモです。

###参考にした情報
>ASUS X205TA に Linux Mint 19.1 Tessa(MATE) をインストールする際にハマった点
>https://qiita.com/rapidliner00/items/1e1868e75b2e5e5ad481

ディストリビューションは違うものの、上のページを参考に実に快適にインストールできました。以前Xubuntuをインストールした時は、外付けのUSBキーボードとマウスが必要だったのに、内蔵のキーボードとタッチパッドで操作できました。

#2. あれ。サウンドカーネルがない・・・

###参考にした情報
>Xubuntu 入れたらやることリスト：個人的初期設定とインストールしたおすすめアプリ
>https://mogi2fruits.net/blog/os-software/linux/ubuntu/4279/

上のページから自分にとって必要と思われる部分をインストール。
また、サウンドに対応するカーネルがネットに公開されています。

###参考にした情報
>No sound on my Asus X205TA
>https://askubuntu.com/questions/1011459/no-sound-on-my-asus-x205ta

上のページにあった

> http://x205ta.myftp.org:1337/kernel/kernel-sound-64bit.tar

をwget しましたが、接続できません。ちょっと焦ります。

#3. 調べていくと
### ubuntu forumsの下記スレッドのharryharryharryさんの書き込みから
>Asus X205TA hardware support in Ubuntu
> https://ubuntuforums.org/showthread.php?t=2254322&page=209&p=13879816&highlight=#post13879816

どうやら、harryさんの環境に不具合があるようで。VPNがうまいこといかず、harryさんのサーバやルータを再起動できない環境にあるそうです。
MEGAにアップしてくれていたダウンロード先からカーネルをダウンロードできました。
WinSWでMetabaseをWindows10のサービス化する 

はじめに
---
この記事では、Metabaseをwindows10のサービス化して、windows10起動時に自動的Metabaseが起動する方法を紹介します。
（ただし、セキュリティ面はよくわかりませんので自己責任でお願いします。）


実行環境
---
この記事は以下の環境で動作確認しています。

・OS:Windows10
・Metabase :  v0.33.0
・WinSW.NET4 : V2.3.0.0

手順
---

**1.WinSWの入手**
WinSWをGoogleなどで検索して、ダウンロードして入手します。
  私の環境の場合は、WinSW.NET4.exeをダウンロードしました。

**2. WinSWを所望のフォルダに格納**
ダウンロードしてきた、WinSW.NET4.exeをmetabase.jarが格納されているフォルダと同じフォルダにコピーします。
(実際にサービス化して動作させると、logファイルなど色々が生成されるようですので、分かる人はフォルダを分けたほうがいいかもしれません。）

**3. WinSWのリネーム**
WinSW.NET4.exeをmetabase.exeにリネームします。
おそらく名前は自由でいいと思われますが、ここではmetabase.jarと同じmetabaseを使用します。

**4.設定ファイル metabase.xmlの作成**
 適当なエディタでmetabase.exeと同じフォルダ内にmetabase.xmlを作成します。
（いろいろ試した結果、下記のようにするとうまくいきました。）

```metabase.xml
<service>
  <id>metabase</id>
  <name>metabase</name>
  <description>This service runs metabase continuous integration system.</description>
  <executable>java</executable>
  <arguments>-jar "metabase.jar"</arguments>
  <logmode>rotate</logmode>
</service>
```

**5.metabase.exeのサービスへの登録**
コマンドプロンプトで同フォルダに移動して、`metabase.exe install`を実行します。
このときコマンドプロンプトは「管理者として実行」する必要がありますので、ご注意ください。

これでサービスとして登録されます。

**6.サービス登録の確認**
サービスとして登録されているかを確認します。
Windowsのサービスに登録されていれば下記のような内容が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265181/4b1d46eb-b103-558d-9af5-6282dfade4c9.png)

**7.動作確認**
では、Windowsを再起動して自動的にMetabaseが起動するか確認します。
再起動後に、Metabaseを起動するために実行していたコマンドプロンプトからの「java -jar metabase.jar」を実行せずに、
ブラウザからMetabaseにアクセスできれば成功です。
　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265181/d5f893d8-57a2-48c3-4515-63f55a54ec3b.png)

**8.別のパソコンからアクセスできることの確認**
また、このパソコン（Metabaseがサービス化されたパソコン）からサインアウトした状態で、別のパソコンのブラウザから確認できるかを確認します。
この時はプライベートIPアドレス＋ポート番号指定の`http://192.168.x.x:3000`等でアクセスします。
ポート番号はMetabaseのポート番号で、デフォルトは3000です。（変更もできるようです。）


私は下記のように同一ネットワーク内のスマホから確認しました。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265181/3a9f0aed-5429-e4ee-c455-b7103944a40a.png)

まとめ
----
上記の通り、WinSWによって、Metabaseをサービス化することができ、毎回起動する必要がなくなりました。
（セキュリティ的な面はあまりよくわかってませんので、注意してください。）
外部API情報をPHP curlを使ってビットコイン価格だけ取得

bitFlyerのパブリックAPIからビットコイン価格だけをcurlを使って取得します。

【bitflyer各種情報が確認できるURL】
https://api.bitflyer.jp/v1/ticker?product_code=BTC_JPY

2019/9/1現在の表示内容

```php
{"product_code":"BTC_JPY","timestamp":"2019-09-01T12:23:35.213","tick_id":2741559,"best_bid":1019318.0,"best_ask":1019938.0,"best_bid_size":0.01799886,"best_ask_size":0.01200473,"total_bid_depth":853.24377747,"total_ask_depth":2064.70810122,"ltp":1019318.0,"volume":49508.95318553,"volume_by_product":1568.33670575}
```

この中にBitcoinの価格が表示されています。

```php
"ltp":数字
```
の「数字」部分がBitcoin価格。

curlを使ってこの箇所だけを抜き出し、整形します。

```php:curl.php
<?php
$url = 'https://api.bitflyer.jp/v1/ticker?product_code=BTC_JPY';

//curlセッション初期化
$ch = curl_init();

//オプション設定
curl_setopt($ch, CURLOPT_URL, $url);//取得するURLを指定
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//実行結果を文字列で返す

//URLの情報を取得
$result = curl_exec($ch);

//結果の表示
$json = json_decode($result);

echo '現在のBTC価格は:' . number_format($json->ltp) . '円';

//セッションを終了
curl_close($ch);
?>
```

するとブラウザ上では
<img width="252" alt="スクリーンショット 2019-09-01 21.52.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490824/5bf23b8c-9324-5f8d-c189-20cf38b763f0.png">
とだけ表示されます。
macOSでDocker Remote APIを利用する方法

macでdocker remote apiを有効化する方法について調べた時のメモを残します。
（linuxだと検索すれば結構でてくるんですが、macだと該当の設定ファイル・コマンドがなかったりしてなかなか苦労しました。。）

# 環境

#### OS

```bash
>> sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G95
```
#### Docker

```bash
>> docker version ※一部抜粋
Client: Docker Engine - Community
 Version:           19.03.1
 API version:       1.40

Server: Docker Engine - Community
 Engine:
  Version:          19.03.1
  API version:      1.40 (minimum version 1.12)
```

# socatコマンドを使う

docker daemonはデフォルトで
`unix:///var/run/docker.sock`でリクエストを待ち受けていますが、
リモートホストからHTTPでAPIを叩く時はTCPのポートで待ち受ける必要があります。

socatコマンドはプロキシのような働きをし、あるポートへのリクエストを指定した宛先にフォワードしてくれます。
以下のコマンドを実行することで、2376ポートへのリクエストを`/var/run/docker.sock`へ飛ばしてくれるようになります。

```
socat TCP-LISTEN:2376,reuseaddr,fork UNIX-CONNECT:/var/run/docker.sock
```

以下コマンドでAPIのレスポンスがjsonで返ってくることが確認できます。

```
curl http://localhost:2376/containers/json
```

※あとでもっと情報が整理できたら追記するかも。。
AWS CLI で定期的に AWS SQS からメッセージを取得する

AWS のマネージドサービス->SNS->SQS->一般的なログファイルでアラートを連携して、既存のログ監視ツールに読ませることになったのでサンプルを作ってみました。

~~OSは RHEL7.6 の想定なので `jq` など入っていません。~~
EPELリポジトリに `jq` あったので使って良いらしい。

```bash:sqs.sh
#!/bin/bash
set -eu

yyyymmdd=$(date +%F)
log=./log_$yyyymmdd
archive=./archive_$yyyymmdd
longPollingInterval=0
url=https://sqs.ap-northeast-1.amazonaws.com/1234567890/hoge
Filter=./filter.awk

# デキュー
# https://docs.aws.amazon.com/cli/latest/reference/sqs/
m=$(aws sqs receive-message --max-number-of-messages "10" --queue-url $url --wait-time-seconds $longPollingInterval)

# デキューの結果があるときは繰り返し
while $(echo $m | grep -E -q '[[:graph:]]'); do

    # ラベリングしてログに保存、途中で加工前のデータをアーカイブとして保存。
    echo $m \
        | jq -r -c '.Messages[].Body' \
        | tee -a ${archive} \
        | awk -f ${Filter} \
        > ${log}
    
    # 削除（削除に失敗した場合はログ出力）
    echo $m \
        | jq -r -c '.Messages[]' \
        | jq -r -c '{ Id: .MessageId, ReceiptHandle: .ReceiptHandle }' \
        | jq -r -c -r '.' \
        | xargs -0 -I@ aws sqs delete-message-batch -queue-url $url --entries "@" \
        | jq -r -c '.Failed | fromjson? | .[]' \
        | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime()) ": メッセージ削除に失敗: " $0}' \
        > ${log}

    # もう一度デキューして残りが無いか確認する
    m=$(aws sqs receive-message --max-number-of-messages "10" --queue-url $url --wait-time-seconds $longPollingInterval)
done
echo $(date '+%F %R:%S') cmpl >> $log
```

メッセージの中間処理には(case文より) `awk` の方が適していると思ったので処理を分けます。

```awk
function label(m){
    print strftime("%Y/%m/%d %H:%M:%S",systime()) ":" m ": " $0
    next
}
$0 ~ "pattern1" { label("pattern1") }
$0 ~ "pattern2" { label("pattern2") }
{ label("parse error") }
```

こいつを `crond` に登録して毎分動かします。大量のメッセージが来る想定ではないので、単体で毎分動かす程度で十分かと。今どきは `systemd` の `timer` を使うのかもしれませんが、よく分からないので。

```
PATH=/usr/bin:/usr/local/bin:$PATH
* * * * * /bin/bash /opt/sqs.sh
```

AWS SQS が落ちていたりすると `/var/spool/mail/user` に大量のエラーメールがたまる懸念がありますので注意が必要です。ローテーションに組み込んでおきましょう（`MAILTO=""`しても良いのですがエラーは追えたほうが良いので）。
便利な TweetDeck の Viewer を作ってみた

作業中も TweetDeck 見たいですよね？僕は見たいです。
そこで、作業の邪魔をしないで TweetDeck を見るための Viewer を作ってみました。

本体は [GitHub/mini-deck](https://github.com/blue0513/mini-deck/) に置いておきます。

## これは何？

ちっちゃい TweetDeck を常に最前面に表示するアプリです。
**（注意）** 現在は macOS のみをサポートしています。

![minideck.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144707/5b308aeb-0a27-99e7-1e5e-ea59c58d1842.gif)

## 特徴

+ 簡単導入
+ ミニサイズなウィンドウ 
+ フレームレス
+ 常に最前面表示
+ 表示崩れなしで拡大縮小可
+ 通常の TweetDeck と同じ使用感

## 使い方

### アプリ版

1. [GitHub/Releases](https://github.com/blue0513/mini-deck/releases) から zip をダウンロードします
2. 展開してアプリを起動するだけ！

### CLI 起動版

1. レポジトリを `git clone` します
2. `npm install` で必要な package をインストールします
3. `npm start` で起動！

## どうやったの？

### TweetDeck の表示
TweetDeck 自体は Webview で表示させています。

```index.html
<body>
  <div id="wrapper">
    <webview
      src="https://tweetdeck.com/">
    </webview>
  </div>
</body>
```

### ウィンドウの諸々の設定
それ以外のウィンドウ設定は基本的に全て `index.js` で設定してます。
See: [Electron | Browser Window](https://electronjs.org/docs/api/browser-window)

```index.js
new BrowserWindow({
    // 中略
    width: 400,
    height: 200, // サイズを確定
    frame: false, // フレームを消す
    alwaysOnTop: true, // 常に最前面に表示
    titleBarStyle: 'customButtonOnHover', // ボタンを隠す
});
```

### ちょっとした工夫

TweetDeck 内のリンクをクリックした際に Chrome などのブラウザで表示させるには `openExternal(url)` を使います。
See: [Qiita | Electronn の <webview> 内でリンクを開いたときに外部ブラウザで開く](https://qiita.com/Linda_pp/items/219847322dda3973557b)

```main.js
function openExternalUrl(event){
  const url = event.url;
  if (url.startsWith('http://') || url.startsWith('https://')) {
    shell.openExternal(url);
  }
};
```

実は Electron の Frameless Window はデフォルトでドラッグが制限されています。なので CSS 側でドラッグを許可する必要があります。
See: [Electron | Frameless Window#Draggable region](https://electronjs.org/docs/api/frameless-window#draggable-region)

```style.css
body{
  /* 中略 */
  -webkit-app-region: drag;
}
```

## 参考

+ [Electron Documentation: BrowserWindow](https://electronjs.org/docs/api/browser-window)
+ [Electron Documentation: Frameless Window](https://electronjs.org/docs/api/frameless-window)
+ [Electronn の <webview> 内でリンクを開いたときに外部ブラウザで開く | Qiita](https://qiita.com/Linda_pp/items/219847322dda3973557b)
jQuery学習メモ2

アニメーションの実装できることリスト(lesson4-8,4-9を参照）

・フェードインとフェードアウト
・スライドしながら表示/非表示
・設定した要素を任意の場所に移動させる
・ページをスクロールするとボタンが出現、ボタンを押すとページのトップまで戻れる
・タブでコンテンツを切り替えられるようにできる
・アコーディオンメニューの作成
・複数の写真などを横スライドで表示させる（カルーセル、スライダー）
・写真をクリックすると拡大表示させる（ライトボックス）
・画面のに奥行きがあるように見せる（パララックス）
【chart.js】「Uncaught TypeError: Cannot read property 'getContext' of null」を解消する方法

こんにちは！
ねこじょーかー（[@nekojoker1234](https://twitter.com/nekojoker1234)）と申します。

「[chart.js](https://www.chartjs.org/)」を使用していると、デベロッパーツールのコンソール上で以下のようなエラーが出る場合があります。

<img width="576" alt="スクリーンショット 2019-09-01 20.30.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487218/396884de-625c-4d07-521c-62c06eba71c3.png">

エラーメッセージを読み解くと、`getContext`が`null`になっていることがわかりますね。
`getContext`は、グラフ描画の最初で呼び出しています。

```coffeescript
window.draw_graph = -> 
    ctx = document.getElementById("myChart").getContext('2d')
```

ここでエラーが出ているので、以下のようなチェック処理を入れてあげれば、エラーは出なくなります。

```coffeescript
window.draw_graph = -> 
    if document.getElementById("myChart") == null
      return
    ctx = document.getElementById("myChart").getContext('2d')
```

アプリを使っている分には、画面上でエラーが出ることはないのですが、他のjavascriptが正常に動作しなかったりもしたので、この処理を入れておくことをおすすめします。

エラーメッセージを読むと`turbolinks`が影響していることがわかるので、公式ドキュメントには載っていないのでしょう。

Railsで開発している人は、要注意です。

## あわせて読みたい

[HTMLもわからない初心者が、独学で「投稿型SNSサービス」を作ったって本当？【193日間の死闘】](https://qiita.com/nekojoker/items/2497b4f81ffd1cd7025c)

運営している PlayFab 専用ブログ
https://playfab-master.com
React 文字列型からboolean型への変換

Reactで文字列型をboolean型に変換するときにつまづいたのでメモです。
画面でradioボタンを押したときに、paramsというstateにisDeliveryAddressをboolean型で追加したいです。

####正しいコード
```React:CustomerForm.js
handleChangeBool(e) {
  this.setState({
    params: {
      ...this.state.params,        
      isDeliveryAddress: e.target.value === 'true',
    }
  });
}
```

####ダメなコード
```React:CustomerForm.js
handleChangeBool(e) {
  this.setState({
    params: {
      ...this.state.params,
      isDeliveryAddress: Boolean(e.target.value),
    }
  });
}
```

ダメなコードでうまくいかない原因は、e.target.valueで暗黙の型変換が起きてしまうためです。
e.target.valueには'true','false'というように文字列で入ってくるため,boolean型を指定をしてもうまく変換することができません。
正しいコードのように記述することで暗黙の型変換は行われないため、boolean型で取ることが可能となります。

####画面
```React:CustomerForm.js
<table className="redister__destination">
  <tbody>
    <tr>
      <th>
        配送先住所
        <font color="red">※</font>
      </th>
    </tr>
    <tr>
      <td className="redister__input_column">
        <label>
          <input
            type="radio"
            name="destination"
            value={false}
            onChange={e => this.handleChangeBool(e)}
          />
          上記住所
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="destination"
            value={true}
            onChange={e => this.handleChangeBool(e)}
          />
          別の住所に送る
      </label>
      </td>
    </tr>
  </tbody>
</table>
```

<img width="1059" alt="スクリーンショット 2019-09-01 20.11.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320179/bbd0b30a-9921-d163-35e2-a469fa97b9f7.png">

####まとめ
int型で取りたいときはNumber()でできてたのに、e.target.valueが絡んできてBoolean()で取れなかったときは非常に困りました。
理解が足りていない部分もあると思いますので、ご指摘いただけると幸いです。
【perl】モジュール一覧

### その1：モジュール名のみ

``` sh
perl -MExtUtils::Installed -le 'print for ExtUtils::Installed->new->modules'
```

以下とほぼ等価

``` perl
#!/usr/bin/perl
use strict;
use ExtUtils::Installed;  # -MExtUtils::Installed
for (ExtUtils::Installed->new->modules) {
  print;
  print "\n"; # -l
}
```

### その2：モジュール名とバージョン

``` perl
perl -MExtUtils::Installed -le 'print "$_\t".eval("use $_(); \$$_\:\:VERSION") for ExtUtils::Installed->new->modules'
```

以下とほぼ等価

``` perl
#!/usr/bin/perl
use strict;
use ExtUtils::Installed;  # -MExtUtils::Installed
for (ExtUtils::Installed->new->modules) {
  print;
  print "\t";
  print eval "use $_();".'$'.$_.'::VERSION';
  print "\n"; # -l
}
```

### その3：モジュール名とバージョンとインストール日時

``` sh
perldoc -tT perllocal |
perl -nle '$d=$1,$m=$2 if /\s+(.*): "Module" (.*)/;print "$m\t$1\t$d" if /"VERSION: (.*)"/'
```

``` perldoc -tT perllocal ``` を使用。

``` sh
$ perldoc -tT perllocal
(略)
  Sun Sep  1 01:53:32 2019: "Module" ExtUtils::MakeMaker
    *   "installed into: xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

    *   "LINKTYPE: dynamic"

    *   "VERSION: 7.36"

    *   "EXE_FILES: bin/instmodsh"

(略)
```

以下とほぼ等価

``` perl
#!/usr/bin/perl
use strict;
my $cmd = "perldoc -tT perllocal";
open PL, "$cmd |" or die "Can't exec '$cmd': $!";
my ($m,$v,$d);
while(<PL>) {
  $d=$1,$m=$2 if /\s+(.*): "Module" (.*)/;
  print "$m\t$1\t$d\n" if /"VERSION: (.*)"/;
}
```
.vimrcに適切な設定をしているが、vimでファイルを開くと文字化けするときの対処

## 文字化けの発生
以下のようなファイルを・・

```linux
$ cat curl_memo.txt 
curl "https://www.googleapis.com/youtube/v3/search?key=$YOUTUBE_DATA_API&part=snippet&q=手芸&type=video"
```

vimで開くと文字化けした

```
 
curl   "https://www.googleapis.com/youtube/v3/search?key=$YOUTUBE_DATA_API&part=snippet&q=謇玖敢&type=video"
~
~
~
curl_memo.txt [sjis][unix]
1,1     All
"curl_memo.txt" [converted] 1L, 112C

```
utf-8のファイルなのに、文字コード自動判別が誤ってsjisで開いてしまっているらしい。
```手芸```という文字コードがたまたま問題を引き起こしたようだ。

### 適切な.vimrcの設定とは？
googleで調べてみると、だいたい以下の設定を推奨していた。
過去に文字化けした時があり、自分も同じ設定をしている。

```vim
set encoding=utf-8
set fileencodings=iso-2022-jp,euc-jp,sjis,utf-8
```
###### 参考
- [vimで文字化けした時の対応](https://qiita.com/meio/items/08143eacd174ac0f7bd5)
- [vimの文字化け](http://hyper-thread.hatenablog.com/entry/2018/02/22/090517)
- [vimによる日本語文字コード自動判別と文字コード変換] 
  (https://itcweb.cc.affrc.go.jp/affrit/faq/tips/vim-enc)
- [Vimでエンコードを指定する](https://qiita.com/owlbeck/items/3cf6d163e624febe4c4a)



##対処

#### 案１ 文字コードを指定して開く
```vim -c ":e ++enc=utf8" curl_memo.txt```

デメリット：コマンドが長くて煩雑
#### 案２　自動判別文字コードの最優先をutf-8にする
.vimrx

```vim
set encoding=utf-8
set fileencodings=utf-8,iso-2022-jp,euc-jp,sjis
```

デメリット：utf-8ではない他のファイルを開くときに文字化けする可能性がある。

#### 案３　開くファイルの先頭行に誤認識しない適当な文字のコメントを入れてutf-8と認識させる


```
 
# ＡＰＩメモ
curl   "https://www.googleapis.com/youtube/v3/search?key=$YOUTUBE_DATA_API&part=snippet&q=手芸&type=video"
~
~
~
curl_memo.txt [utf-8][unix]
2,1     All
"curl_memo.txt" 2L, 127C

```

案３は本末転倒な対処ではあるが、お手軽に文字化けを意識しないで済む
プログラミング学習（五日目）その2　ProgateでRuby on Rails レッスン5　バリデーション、フラッシュ

#今日学んだこと
- 目次
    - バリデーション
    - saveメソッドの戻り値
    - renderメソッド
    - エラーメッセージ表示
    - フラッシュ

##バリデーション
####バリデーションとは
不正なデータがデータベースに保存されないために、データをチェックする仕組み。

####バリデーションの書き方
バリデーションはモデルで設定する。
書き方は
`validates :検証するカラム名, {検証する内容}`

具体的に書くと、

```ruby:models/post.rb
class Post<ApplicationRecord
  validates :content, {presence:true}
end
```


この内容は「contentカラム」に「値が存在するのか」をチェックしている。つまりcontentが空だと保存できない。
他には、`{length:{maximum:140}`と書くと、最大文字数を140に設定している。

また、検証する内容を入れるところはハッシュとなっており、
`{presence:true, length:{maximun:140}}`と書けたりもできる。

##saveメソッドの戻り値
saveメソッドは、保存に成功すると「true」、失敗すると「false」を返す。

##renderメソッド
コントローラにおけるアクションとは、そのコントローラと同じビューファイルのフォルダからアクション名と同じビューファイルを指定し、
ブラウザに表示するものだが、この「renderメソッド」を使うと、アクション名とは違うビューファイルを指定することができる。
具体的には、

```ruby:posts_controller.rb
def update
  render("posts/edit")
end
```
とすると、updateアクションからviews/posts/edit.html.erbを指定し、ブラウザに表示できる。

##エラーメッセージの表示
Railsではバリデーションによってデータの保存に失敗すると、自動的にエラーメッセージが生成され
「errors.full_messages」に配列として入る。

##一度だけ表示される「フラッシュ」
Railsではフラッシュを表示するために「flash」メソッドが用意されている。
アクションにて
`flash[:notice] = "表示したい文字列"`
とするとビューで「flash[:notice]」が使える。
フラッシュは色々な場面で使うので、「application.html.erb」で表示するのを推奨。
メモ帳の日時を簡単に入力するツール

#目的
業務中にメモをPC上で取ることが多いのですが、メモを取った時の日時の情報って後で情報を整理するときにとっても大切だったりする。
（特に業後報告の際、具体的な日時があると経過が見えやすい）
本記事ではメモ帳の日時を簡単に入力する方法について書いてみた。

#本記事でやりたいこと
押すと自動的に起動日時が記載されているメモを作成するタスクバーアイコンの作成

##使うツール
Windows OS に標準搭載されている以下のツールを使って作成する。

- メモ帳(notepad.exe)
- Windows バッチ(.bat)
- PowerShell

##メモ帳(notepad.exe)を使った日時を記入

-起動時にF5キーを押す

メモ帳に出力される日時の書式は以下のようになる。
hh:mm yyyy/mm/dd

##メモ帳を起動→日付入力を実行するps1ファイルの作成

```powershell:createMemo.ps1
#System.Windows.Formsのインポートを行う
add-type -AssemblyName System.Windows.Forms
#メモ帳を開く
notepad
#500ミリ秒スリープ
start-sleep -Milliseconds 500
#日時を入力[F5キーを押すだけ]
[System.Windows.Forms.SendKeys] ::SendWait("{F5}")
[System.Windows.Forms.SendKeys] ::SendWait("{ENTER}")
```

##上記のps1ファイルを実行するバッチファイルの作成
createMemo.ps1と同一ディレクトリ内に作成する

```createMemo.bat

@echo off

rem 実行ポリシーを変更してps1ファイルを実行 
powershell -ExecutionPolicy RemoteSigned [createMemo.ps1の絶対パス]

rem コマンドを終了する。
exit

```

##バッチファイルのショートカットをタスクバーに登録
1.バッチのショートカットファイルを作成
2.作成したファイルを右クリックし「ショートカットの作成」＞「プロパティ」
3.リンク先に「C:\Windows\System32\cmd.exe /c [batファイルへのパス]」と入力。
4.ショートカットファイルをタスクバーにドラッグ＆ドロップ

参考URL
・Windows10でタスクバーに.Vbsファイルや.Batファイルを入れる方法
　https://toolmania.info/post-10234/

#最後に
ショートカットアイコンがもう少しこだわれたらいいかなと思う。
最近は情報が多すぎる職場での記録補助ツールが欲しいと思うこのごろ、、、