OmniAICreator/Qiita-1.07M huggingface dataset:
Google Photos(Picasa)から画像URLを取得する

Google Photosから画像URLの取得の仕方について調べたので備忘します。
Google PhotosのAPIはないため、Picasa Web Albums Data APIを用います。

# Google　APIsのセットアップ

Google OAuth2.0認証のクライアント登録、RefreshTokenの取得は以下を参考に実施。

- [Node.jsでGoogle SpreadSheetsを操作してみよう。](https://dotstud.io/blog/google-spreadsheets-from-nodejs/)
- [スマホで撮った写真を Line Message API を利用して Google Cloud Functions から Google Photos へアップする](https://qiita.com/kkeisuke/items/1fd615005fad2ee6703d)
- [GooglePhotoにある写真を取得し、Slackに送信するBotを作った話
 ](https://qiita.com/romukey/items/f03f24e209d30b360af8)

# esteban-uo/picasa 3rdパーティを利用しました

公式のクライアント　ライブラリの中にnode.jsは提供されていないので、以下「picasa」ライブラリを用いました。
https://github.com/esteban-uo/picasa

Picasa Web Albums Data API　公式Doc:
https://developers.google.com/picasa-web/docs/3.0/reference

## サンプルコード

```javascript:index.js
'use strict';

const Picasa = require('picasa');

const config = {
    clientId:        'yourClientId',
    redirectURI:     'redirectURI',
    clientSecret:    'yourClientSecret'
};
const refreshToken = 'yourRefreshToken';


const picasa = new Picasa();
let accessToken;

// アクセストークンを取得します。
picasa.renewAccessToken(config, refreshToken)
    .then(token => {
        accessToken = token;
        // アルバム一覧を取得します。
        return picasa.getAlbums(accessToken, null);
    })
    .then(albums => {
        // アルバム内の写真一覧を取得します。
        return Promise.all(albums.map(album => {
            return picasa.getPhotos(accessToken, {albumId: album.id});
        }));
    })
    .then(albumResults => {
        for (const photos of albumResults) {
            for (const photo of photos) {
                console.log(`Content-Type: ${photo.content.type}, URL: ${photo.content.src}`)
            }
        }
    })
    .catch(error => {
        console.log(error);
    });
```

AlbumとPhotoのオブジェクトについては以下のような構造でした。
(適当にマスクしました。)

## album オブジェクト

```album.json
 {
 	"thumbnail": [{
 		"url": "https://lh3.googleusercontent.com/.../.../.../.../xxx",
 		"height": 160,
 		"width": 160
 	}],
 	"id": "6495466432978937825",
 	"name": "6495466432978937825",
 	"num_photos": 270,
 	"published": "2017-12-03T23:27:09.000Z",
 	"title": "アルバムタイトル",
 	"summary": "",
 	"location": "",
 	"nickname": "Kenji K",
 	"rights": "protected",
 	"access": "protected"
 }
```

## photo オブジェクト

```photo.json
 {
 	"id": "xxx",
 	"album_id": "xxx",
 	"access": "protected",
 	"width": "6000",
 	"height": "4000",
 	"size": "1725207",
 	"checksum": "",
 	"timestamp": "1511213016000",
 	"image_version": 25335,
 	"commenting_enabled": "true",
 	"comment_count": 0,
 	"content": {
 		"type": "image/jpeg",
 		"src": "https://lh3.googleusercontent.com/.../.../.../.../DSC_0856.JPG"
 	},
 	"title": "DSC_0856.JPG",
 	"summary": ""
 }
```
Ubuntuを16.04から18.04にアップグレードしたらタッチパッドの右クリックが効かなくなった

物理的なボタンがないタッチパッドの右下をクリックしても右クリックをシていることにはならなくなったらしい。
その代わりに、タッチパッドを二本指でタップすると右クリックになる。

このあたりの挙動を変えたければ、Tweaksというアプリを使うことでカスタマイズできる。

# 参考
* [11 Things To Do After Installing Ubuntu 18.04 LTS](https://www.omgubuntu.co.uk/2018/04/things-to-do-after-installing-ubuntu-18-04)
MCP 70-533 : Microsoft Azure Infrastructure Solutions の実装

「MCP 70-533 : Microsoft Azure Infrastructure Solutions の実装」に合格しました。以下は2018年4月時点の内容です。

#試験概要
- ~~120分~~150分
- 53問
- 合格ライン 700点/1000点
- ¥21,103 JPY（公式サイト上に記載された価格）

自分の場合は[isaオンラインショップ](https://www.isa-onlineshop.net/products/detail.php?product_id=10188)で
・Microsoft Azure Exam Packバウチャー(再受験付き)
・販売価格(税込) : 21,060 円
・有効期間 : 2018年6月30日
を購入しました。再受験はしなくて済んだけど。

#試験範囲
[公式サイト](https://www.microsoft.com/ja-jp/learning/exam-70-533.aspx)参照。（どうでもいいけどこのサイトってなんでこんなに重いの・・・）

- Azure Appサービスアプリケーションの設計と実装 (10-15%)
- 計算リソースの作成と管理（20〜25％）
- ストレージ戦略の設計と実装（10-15％）
- 仮想ネットワークを実装する（15-20%）
- ARMテンプレートの設計と展開（10-15％）
- Azureセキュリティと回復サービスを管理する（25〜30％）
- Azure操作を管理する
- Azureのアイデンティティを管理する

ASMは出ないと思ったのに、自分の受験した限りにおいては出ました。これからAzure触る人が`Set-AzureVNetConfig`なんて使わないでしょ・・・とか。問題のめぐり合わせみたいなのがあるんでしょうか。

#自分のスペック
- AWS認定 アソシエイト３つ、プロフェッショナル２つ
- GCP認定 クラウドアーキテクト、データエンジニア

AWS→GCPときたのでついでにAzureも...という流れ。

#結果
835点
受験後のレポートに分野ごとの得点の棒グラフが記載されていて、各分野ごとの点数まではわからないけど、大まかな正解率は把握することができます。「Azure IDの管理」が低かった・・・。他はまあまあ。

#感じたこと
「Azureの実践的なスキルレベルを測定する試験」というより「過去問（※あやしげな日本語訳の問題集とか）を知ってるほど有利な試験」という印象。試験の問題が古い？本当に新しい試験範囲に対応してる？と感じることがありました。特に ASM や Cloud Services の問題は出ないと思い込んでいたのに何問かでてきたので焦りました。
53問中、最初の9問は一度回答すると後戻りができない作りになっているので、慎重に回答するべきでした。10問目以降は普通にあとから見直し可能。試験時間は十分に余裕がありました。（1時間で終わった。）

#勉強方法
試験に受かることに特化した勉強ではなく、Azureを全般的に理解することを第一の目的とした勉強を行いました。とはいえ「実践的な知識」だけでは合格は難しく、受験の直前には「試験のための勉強」もやりました。結果として「試験のための勉強」も不可欠と感じました。

##（書籍）[Azureテクノロジ入門](http://ec.nikkeibp.co.jp/item/books/P53630.html)
Microsoftの公式本。ゼロから学習をスタートする場合、Azureの全体感をつかむのには最適。

##（書籍）[Azure実践ガイド](https://book.impress.co.jp/books/1117101015)
タイトルのとおりAzureを実際に使うことを想定した実践的な内容。取り上げるサービスの種類は少ないけど70-533の主要な試験範囲はわりとカバーしているのでは。
12章までは主要なサービスについてしっかり書かれているので読み応えがありました。
「13章 Infrastructure as Code」、「14章 リファレンスアーキテクチャと構築テクニック」は内容が実践的すぎるので「今すぐAzureを仕事で使う予定もないし・・」という自分としては読み流す程度。

##[Pluralsight](https://pluralsight.com/)
　あまり他の人の受験記に出てこないですが、個人的にはおすすめなオンライン講座。基本は有料ですがMSDNのサブスクリプションを持っていれば3ヶ月もしくは6ヶ月の無料特典があります。
おしゃれなUIでコンテンツも豊富、そして新しいコンテンツも適宜追加されているようです。この手のオンライン講座は英語オンリーなところが多いですが、Pluralsightは日本語字幕がついている！（自動翻訳ベースのわかりづらい箇所もあるけど、それでもかなり優秀なほうだと思う）英語が苦手な自分としてはこれは大きいポイント。スマホアプリもありますが日本語字幕が対応していないのが難点。せっかくコンテンツの事前ダウンロード機能があるのに。。仕方がないので通勤中はスマホのブラウザでストリーミング再生です。パケットが・・・
自分の場合はPluralsightでAzure関連のコンテンツを視聴しまくってベースとなる知識を蓄えました。

##（書籍）[ひと目でわかるAzure Active Directory](http://ec.nikkeibp.co.jp/item/books/P98790.html)
ActiveDirectoryは苦手分野なので、基本的な知識を補うために読みました。

##[Whizlabs](https://www.whizlabs.com)
問題集サイト。英語オンリーなのが弱点ですが、安いです。「\$29.95 なのが期間限定で\$15.95」と表示されています。それに加えて「今日だけの特別クーポン！」 みたいなのがピョコっと表示されて、そのクーポンコードを入力すると更に半額になります。怪しい・・・。1000円足らずで70問×3セット（計210問）の練習ができます。
「内容も古そうだしあまり役に立たないかもしれないけど、試験の雰囲気を感じるだけでもいいか・・・（安いし）」と思ってトライしましたが、結果的にここでの経験が本番での得点アップにつながりました。
クラムメディアなどの問題集は手を出しませんでしたが、同様に試験対策としては有効なのではと感じました。

##Azureの実物を触る
言うまでもなく。

##Azureの公式ドキュメント
苦手分野や興味のある分野はここを読んで正確な情報を得ます。

#まとめ
学習する前は「パブリッククラウドはAWS一強」と思い込んでいましたが、Azureも相当な勢いでサービスを揃えてきていると感じました。
学習コンテンツや試験に関する情報量ではAWSが圧倒的ですね。AWS >> Azure >>> Google というかんじ。Azureの学習コンテンツは（公式ドキュメントは別として） Channel9 とか edX とか MVA(Microsoft Virtual Academy) とか散らばりすぎて一貫性がなく、目的のコンテンツに辿り着く前に英語と日本語のサイトをリダイレクトされまくって見失ったりします。さすがはMicrosoftです。次は70-532を目指したいと思います。
Python3からMySQL繋ぐ時は、いろいろあるけどとりあえずPyMySQLにしとこうや

どうもmiyachi（[@_38ch](https://twitter.com/_38ch)）です
Flask+MySQLでアプリを作ろうとしてるんですが、Python3でMySQLに接続するためのパッケージがいろいろあって、どれがよくてどれが悪いのかよくわからない。
いろいろ使ってみようとした結果、PyMySQLが個人的に一番シンプルで使いやすかったので、使い方書いておきます。

「Python3 MySQL」で英語設定でググって一番最初に出てくる、stackoverflowで比較されていた中から選びました。そこでの紹介文を単純に翻訳すると

* **ピュアPython** (Pure python）
* **mysql-connectorより速い** (Faster than mysql-connector)
* **pymysql.install_as_MySQLdb()を呼び出せば、MySQLdbとほぼ完全な互換性がある** (Almost completely compatible with MySQLdb, after calling pymysql.install_as_MySQLdb())

## インストール

```unix
pip install PyMySQL
```

## DB情報設定

```python
import pymysql.cursors

conn = pymysql.connect(host='host_name',
                    user='user_name',
                    db='db_name',
                    charset='utf8mb4',
                    cursorclass=pymysql.cursors.DictCursor)
```

## クエリを書いて情報を取得する
**SELECT**

```python
try:
    with conn.cursor() as cursor:
        sql = "SELECT user_id, user_name FROM users WHERE user_id = %s"
        cursor.execute(sql, ('123',))
        result = cursor.fetchall()
        print(result)
finally:
    conn.close()
```
printの結果

```
{'user_id': 123, 'user_name': 'Jon Doe'}
```

**INSERT**

```python
try:
    with conn.cursor() as cursor:
        sql = "INSERT INTO user (user_name, email) VALUES (%s, %s)"
        cursor.execute(sql, ('Jon Doe', 'sample@gmail.com'))

    # オートコミットじゃないので、明示的にコミットを書く必要がある
    conn.commit()
finally:
    conn.close()
```

シンプルで良い！

## 関連ページ
* [How can I connect to MySQL in Python 3 on Windows?
](https://stackoverflow.com/questions/4960048/how-can-i-connect-to-mysql-in-python-3-on-windows)
* [PyMySQL](https://pymysql.readthedocs.io/en/latest/)
* [PyMySQL (GitHub)](https://github.com/PyMySQL/PyMySQL)


## 宣伝
プライベートでWalicaという複雑な割り勘のサポートサービスを作っているのでもしよかったら、使ってみてください。
[![Custom Preset.png](https://qiita-image-store.s3.amazonaws.com/0/209160/c22a07a1-ff33-1b19-1255-2bf1296f1cc9.png)](https://walica.jp?share=qiita)
突然Azure のWeb appが403?エラーでサイトごと落ちた解決方法

AzureのWeb appを使用していて、
何も触っていないのに、
急に「The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.」
でサイト全部が落ちたけど、復旧。情報が探せなくて苦労したので、メモ。  

結論。PHPが突如オフになっていた。  
  
AzureでWeb Appの「プアプリケーション設定」PHPのバージョン選んでONにしてあげたら直った。  


多分、古いバージョンのPHP使っていたから、
Azureが対応終わらせて古いバージョンは自動的にOFFになったと思われる。
どのバージョンだったかはちょっと覚えてないけど。  

ただ、最新のバージョンにしたら、違うエラーがでちゃったので、修正しないと・・・。
tensorflow のコアダンプ解消 [tensorflow 1.8]

想像以上にハマったので忘れないようにメモ．

cuda， cuDNN をそれぞれアップデートして，tensorflow 1.8 を導入しようと，いつものように `pip install tensorflow-gpu` 叩きインストールしたところ，`import tensorflow` と入力しただけで突然のコアダンプ．

調べた所，自前の PC の CPU が古いらしく自分でビルドしないといけないということに．
https://www.tensorflow.org/install/install_sources
上記のチュートリアルに従っていって，いざ build しようとすると，

```sh
python: can't open file 'external/local_config_cuda/crosstool/clang/bin/crosstool_wrapper_driver_is_not_gcc': [Errno 2] No such file or directory
```


とエラーメッセージが...
bazel のキャッシュを見てもファイル自体は存在しているので謎を極めて居た所，パッケージのソースディレクトリ以下で build コマンドを叩いたら無事 build 完了．
ということで，以下のようなコマンドで動く．

```sh

cd package/path/tensorflow/tensorflow 
bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
```

灯台下暗しというかなんというか...

|実行環境|
---
|ubuntu 16.04
|cuda 9.0
|cuDNN 7.0.5
|bazel 1.0.0


#追記
python 2.7 で build しようとすると同様のエラーが起きた．
以下の URL を参考に sudo で叩いたら動いた．
結局原因はなんだんだろう...

https://github.com/bazelbuild/bazel/issues/3788

```sh
sudo bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package```
Windows10にKeras(+TensorFlow)をインストールしてAnaconda+Jupyterで動かしてみる 

久々に環境構築やりました。
作業メモとして残します。

# 前提環境
- Windows10 Professional 64bit
- Anaconda3 5.0.0 64bit(Python3.6)

# 導入するもの
- CUDA 9.0
- cuDNN 7.1.3
- TensorFlow
- Keras

# 導入
## CUDA 9.0のインストール
[ここ](https://developer.nvidia.com/cuda-90-download-archive)からCUDA9.0をダウンロード。
Base Installerに加えて、Patch 1、Patch 2があったので、全て入れました。
構成は推奨設定にしました。

## cuDNN 7.1.3のインストール
[ここ](https://developer.nvidia.com/rdp/cudnn-download)からcuDNN 7.1.3 for CUDA 9.1をダウンロード。
zipを解凍した中身を確認し、CUDAをインストールしたディレクトリにコピー。
[C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0]に、cuDNNを解凍したディレクトリと同じ、bin,include,libディレクトリがあります。

## 仮想環境の作成
Anaconda Promptを起動し、以下の入力をして仮想環境を作成し、アクティブ化する。

```console:create_env
conda create -n [仮想環境名] python=3.6 jupyter
activate [仮想環境名]
```

## TensorFlowのインストール
Anaconda Prompt上で以下のコマンドを実行する。

```console:install_tensorflow
pip install --ignore-installed --upgrade tensorflow-gpu
```

バージョン確認

```shell-session:check_tensorflow_version.py
import tensorflow as tf
tf.__version__
```

```text:実行結果
'1.8.0'
```

## Kerasのインストール
Anaconda Prompt上で以下のコマンドを実行する。

```console:install_keras
pip install keras
```

バージョン確認

```shell-session:check_keras_version.py
import keras
keras.__version__
```

```text:実行結果
'2.1.6'
```

バックエンドは自動でTensorFlowになってました。
以下で確認可能です。

```C:\Users\[User]\.keras\keras.json
"backend": "tensorflow"
```

#動作確認
Jupyterノードブックを作成し、[Keras公式のMNISTサンプル](https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py)を貼り付けると、ちゃんと動作しました。

Kerasのimportに失敗するので、最初に仮想環境へのパスだけ通しました。
仮想環境でモジュールを追加すると毎回必要になるのだけど、Anaconda仮想環境＋Jupyterで、もっといいやり方ないだろうか。

```sample.ipynb
import sys
sys.path.append('C:\\Users\\[User]\\Anaconda3\\envs\\[仮想環境名]\\Lib\\site-packages')
```

#参考
- [Windows10：KerasでGPUを使用する環境構築のTip's（TensorFlow)](https://qiita.com/maemori/items/71ddec3ada7f51113d88)
- [TensorFlow(+Keras)がWindowsで簡単にインストールできた件](https://qiita.com/samacoba/items/207f2650ee60fe1de25a)
Arduino DueでSPI通信

```Arduino
/*
 * SPI Interface
 * Read Program  
 */

#define XCS_PIN   10
#define SCLK_PIN  13
#define MISO_PIN    9
#define MOSI_PIN 11

unsigned int readData;

void setup() {
  // pin
  pinMode(XCS_PIN ,OUTPUT);
  pinMode(SCLK_PIN,OUTPUT);
  pinMode(MOSI_PIN,OUTPUT);
  pinMode(MISO_PIN ,INPUT);
  // initial condition
  digitalWrite(XCS_PIN ,HIGH);
  digitalWrite(SCLK_PIN,HIGH);
  digitalWrite(MOSI_PIN,HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
  readData = 0;
  spi_read(0x82);
}

void spi_read(byte readAddress) {
  digitalWrite(XCS_PIN ,LOW);

  digitalWrite(MOSI_PIN,(readAddress & 0x80 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x40 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x20 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x10 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x08 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x04 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x02 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  digitalWrite(MOSI_PIN,(readAddress & 0x01 ? HIGH : LOW));
  digitalWrite(SCLK_PIN,LOW);
  digitalWrite(SCLK_PIN,HIGH);

  // 16bit Read
  for(int i = 0; i < 16; i++) {
    digitalWrite(SCLK_PIN,LOW);
    readData += digitalRead(MISO_PIN) << i;
    digitalWrite(SCLK_PIN,HIGH);
  }

  digitalWrite(XCS_PIN ,HIGH);
}
```
同じメソッドをインスタンスメソッドにもクラスメソッドにも利用したい場合

## 移譲

[module Forwardable](https://docs.ruby-lang.org/ja/latest/class/Forwardable.html#I_DEF_DELEGATOR)を使います。
ForwardableはRubyの標準ライブラリです。


[標準添付ライブラリ紹介 【第 6 回】 委譲](http://magazine.rubyist.net/articles/0012/0012-BundledLibraries.html)
> オブジェクトの機能を再利用する手法の一つとして、Ruby では言語仕様としてクラスの継承とモジュールの Mix-in を提供しています。これらは、元になるクラスやモジュールの実装までもをそのまま取り込んでしまいますが、他の手段で機能の再利用を実現する手法として、委譲があります。

> 委譲では、再利用したい機能を自分に取り込むのではなく、その機能を持つオブジェクトに処理を依頼します。

>Ruby では特に言語仕様として委譲がサポートされているわけではありませんが、委譲を実現するためのライブラリとして forwardableとdelegate が用意されています。具体的には、これらのライブラリを使用することによって、あるメソッド呼び出しを他のオブジェク>トのメソッドにたらい回すということを簡単に記述することができます。



## インスタンスメソッドに移譲

```ruby
class Outer
  extend Forwardable
  def_delegators :@inner, :hello

  def initialize
    @inner = Inner.new
  end

  class Inner
    extend Forwardable
    def_delegators :hello

    def hello
      puts "hello, world!!"
    end
  end
end

obj = Outer.new
obj.hello  #=> "hello, world!!"
```

Outer::InnerのインスタンスメソッドをOuterのインスタンスメソッドに移譲したので、どちらもインスタンスメソッドです。

```ruby
Outer.instance_methods(false)
#=> [:hello]
Outer::Inner.instance_methods(false)
#=> [:hello]
```

## クラスメソッドに移譲

以下のサンプルでは、Innerクラスの中身は全く変わっていないことに注目してください。

```ruby
require 'forwardable'

class Outer
  class << self
    extend Forwardable
    def_delegators :inner, :hello

    def inner
      Inner.new
    end
  end

  class Inner
    extend Forwardable
    def_delegators :hello

    def hello
      puts "hello, world!!"
    end
  end
end

Outer.hello  #=> hello, world!!
```

Innerクラスのhelloメソッドはプライベートメソッドですが、Outerクラスではクラスメソッドになっています。

```ruby
Outer.methods(false)
#=> [:inner, :hello]
Outer::Inner.methods(false)
#=> []
Outer::Inner.instance_methods(false)
#=> [:hello]
```

## さいごに
https://github.com/willnet/gimei

gimeiのコードを追っていて、どうして`include`や`extend`を普通に使わないのだろう？
と思ったのがこの記事を書くきっかけとなりました。

[gimeiを詠む](http://chamao.hatenablog.com/)
まわれるクエリ・・・をひっそりと補足

Qiitaの作法を致命的にわかってないので前の投稿では日記ノリで安易に左巻き礼賛してしまいました。さいきんの忖度とかの風潮みてると左によせすぎても危険が怖いので巣に帰る前に中立性をみせつけて身辺の安全を図っておこうかと。（…というほどの内容しかない）


###左回りの定義ふたたび
左回りは左回りです。それ以外のなにものでもありません。前の投稿でPostGISは面積の正負で回転方向を判断してると書きましたが、正負だけわかれば充分なので二次元座標値を投影などせずに計算してます。経緯度座標系の場合、日本の近辺では経度緯度がどっちも正の数になるのですが、経緯度原点より西とか南、ようするにアメリカや~~四国~~オーストラリアでは負数が出てきますので不安を感じる人もいるかもしれません。実際オーストラリアとかでForceCCW()してgeojsonlintとかでチェックかけたらすぐわかるんですが、もちろん地域によって回転方向に差があるってことはないです。
（面倒なので例は省略）

###MVTって、くそだよねー(CV:ポプ子)
Mapbox Vector Tilesの初版の仕様書では回転方向について定義がなかったんですが、V.2をつくるときにOGCに倣ってCCW(左回り)を正にするって方針にしようとして、
http://github.com/mapnik/mapnik/pull/2739
MVTの座標原点は左上なのでY座標が上下反転してるから回転方向を裏向き（逆）にしてみたとかいう話ですが、
http://github.com/mapbox/mapnik-vector-tile/pull/164
先生、何言ってんのかわかんないっす！
(WebGLもGIS的な意味でない右手系じゃなかったっけ?)

最終的な仕様はこれ。
http://www.mapbox.com/vector-tiles/specification/#winding-order
動画PNGまでつける念の入れよう。

###まとめ
右巻き標準の仕組みを実装してしまった方に右巻きのフレンズの存在をお知らせすることでひとりじゃないってことを伝えたかったのです。
Raspberry Piを使ってGoogle Homeアプリを作るうえでの準備

Raspberry Piを使ってGoogle Homeアプリを作るうえで必要な準備についてまとめてみた。

###簡単なフロー
前提としてGoogle Homeに呼び掛けてから実際に処理がなされるまでの流れを簡単に図にした。
例として「OK Google, ただいま」と言った際、部屋の温度が25度以上であれば冷房を入れるというもの
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253915/f694ef4b-5bae-449b-262f-b7a839bcd08b.png)


処理の内容は違えど、今のところやろうとしていることのほどんどは上記のフローとなる。
実装にあたって必要な準備をまとめる。

####Google Home側での準備
- Action On Googleでprojectを作成
- Dialogflowで会話の作成

####RaspberryPi側での準備
- OSインストールなど初期セットアップ
- 外部とネットワークとの接続⇒ngrok
- APIサーバーとしての機能⇒Flask-Assistant
プログラマ脳を鍛える数学パズル Q.4「棒の切り分け」

問題の順番が前後していますが引き続き問題を解いていきます。
問題は[プログラマ脳を鍛える数学パズル](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E8%84%B3%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B%E6%95%B0%E5%AD%A6%E3%83%91%E3%82%BA%E3%83%AB-%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%A7%E9%AB%98%E9%80%9F%E3%81%AA%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E6%9B%B8%E3%81%91%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8B70%E5%95%8F-%E5%A2%97%E4%BA%95-%E6%95%8F%E5%85%8B/dp/479814245X/ref=asap_bc?ie=UTF8)より。
# 今回の問題
>長さn[cm]の1本の棒を1[cm]単位に切り分けることを考えます。ただし、1本の棒を一度に切ることができるのは1人だけです。切り分けられた棒が3本であれば、同時に3人で切ることができます。
最大m人の人がいるとき、最短何回で切り分けられるかを求めてください。例えば、n=8, m=3のときは（中略）4回で切り分けることができます。
**問題1**
n=20, m=3のときの回数を求めてください。
**問題2**
n=100, m=5のときの回数を求めてください。

# 実装手順
①切り分けられた棒の個数がnを超えない場合のループ文を書く
②切り分けられた棒の個数がnを超えた場合のループ文を書く
③結果を出力する

# 書いたPHPコードと出力結果
```php:q04.php
<?php
// 問題1
$m = 20;
$n = 3;
// 問題2
$m = 100;
$n = 5;

// 切る回数
$cut = 0;

// 切り分けられた棒の個数がnを超えない場合
for ($count = 1; $count < $n; $count *= 2) {
  $cut += 1;
}

// 切り分けられた棒の個数がnを超えた場合
for ($count; $count <= $m; $count += $n) {
  $cut += 1;
}

// 結果の出力
echo $cut.'回です';

// 問題1
8回です
// 問題2
22回です
```
# 今回の学び
- 問題を読んですぐに実装の方法が分からなければ、一度手書きで式や図を書いてみると法則が見つけられることがある。
- 別解で再帰処理を用いていたので、別記事でまとめる。
active adminとdeviseを同時に新規導入したときに起きたエラーと対処

# 概要
* active adminをdeviseと共に新規導入しようとしたらエラーが発生
* deviseがrailsに正しく認識されていないことが原因なので、deviseを先にインストールしてからactive_adminをインストールすれば解決

# 環境
* rails 5.2 （この作業ではじめてactive adminとdevise導入した。）
* activeadmin (1.3.0)
* devise (4.4.3)

# エラー状況

[ActiveAdminの公式](https://activeadmin.info/0-installation.html)のインストールページに従ってインストールしたらうまく行きませんでした。

```
# Gemfile

# active admin
gem 'activeadmin'
gem 'devise'
```

bundle installする。

```console
> bundle install
```

そしてactive_adminのファイルをgenerateしようとしたら下記のエラー。

```console
> rails g active_admin:install

# 省略
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/dynamic_matchers.rb:22:in `method_missing': undefined method `devise' for AdminUser (call 'AdminUser.connection' to establish a connection):Class (NoMethodError)
# 省略
```

deviseがキチンとインストールされていないことにより、メソッドが認識されていないことが原因。

# やったこと
deviseを先にインストールしてから`rails g active_admin:install`を実行したらうまくいきました。

bundle install完了までは、上記と同様に行い、その後、まずdeviseをインストールする。

```
> rails g devise:install     
```

deviseのインストールがうまくいった後に、active_adminのファイルをgenerateする。これで、エラー発生せずインストールが完了できた。

```console
> rails g active_admin:install
Running via Spring preloader in process 49
      invoke  devise
    generate    No need to install devise, already done.
      invoke    active_record
      create      db/migrate/20180429115354_devise_create_admin_users.rb
      create      app/models/admin_user.rb
      insert      app/models/admin_user.rb
       route    devise_for :admin_users
        gsub    app/models/admin_user.rb
        gsub    config/routes.rb
      append    db/seeds.rb
      create  config/initializers/active_admin.rb
       exist  app/admin
      create  app/admin/dashboard.rb
      create  app/admin/admin_users.rb
      insert  config/routes.rb
    generate  active_admin:assets
Running via Spring preloader in process 58
      create  app/assets/javascripts/active_admin.js.coffee
      create  app/assets/stylesheets/active_admin.scss
      create  db/migrate/20180429115359_create_active_admin_comments.rb
```

以上、
Let's NoteにLinuxをインストールしたがスピーカーから音が出ない問題【解決!!】

#レッツノートの内蔵スピーカーから音が出ない

一年ぐらい前に中古でCF-NX1を3万円程度で購入し、SSD化 + 16GBメモリまで増設。つい先日、レッツノートのバッテリー交換プログラムもあり、バッテリも新品に。

OSは、Linux Mint 17.1 をインストールし、かなり快適に過ごしていましたが非常に快適に過ごしているのですが、唯一もやもやすることがありました。

それが、**内蔵スピーカーから音が出ない**ことでした。

サウンドデバイスはきちんと認識されており、youtubeなどを再生すると、音量メーターが動きます。
イヤホンを挿せば問題なく聞こえますし、HDMIで音を出すのも問題なし。

本当に、**内蔵スピーカーからだけ音が出ない**のです。

#壊れているのか?
中古PCでしたが、Windows7はインストールされていました。Windowsの時に音が出ていたのか? と、言われると、確か起動時にWindowsの音が鳴っていた気がするという、曖昧な記憶のままSSD化してしまったため、確証が持てませんでした。

改めて、元のHDDに付け直して起動したところ、Windowsからは音が出る! 全く問題なし。ということで、やはりLinux側での問題ということに落ち着きました。

その後、いろいろと調べましたが、Let's noteはWindows側でミュートの状態を記憶するのでまずはWindows側でミュートを解除するとか、speech-dispacherを入れなおすなど、様々な情報がありましたが、試した限りでは、どれも効果はありませんでした。

#月日は流れ
そもそも、音が必要か? と言われると私は音楽を聞く習慣もなく、動画などであればタブレットで見るので、特に不都合は感じませんでした。それよりも、何かの拍子に突然音が出てしまう心配が全く無いので、安心してどこでもPCを使えていたので、メリットでもあり、音が出ないことについては、いつしか気にならなくなり、一年ぐらい放置していました。その間、Linux Mint18にアップグレードしたものの状況は変わりませんでした。

#Linux Mintが悪い?
ただ、ふとした時に好奇心が湧き、そもそもLinux Mintが悪いのかを調べてみたくなり、他のUbuntuはどうなのかを確認してみました。

USB に Kubuntu 18.04をLiveで起動させてみましたが、やはり、状況は変わりませんでした。
Fedora27を入れても変わらず、どうもLinux全般的にうまく動作しないということが分かりました。

#結論としては

以下のコマンドを実行することで直りました。実際にはよく分かっていないのですが、**alsamixer**コマンドで音量を確認せよという記事が多数ある中で、**alsactl init** コマンドで直ったという人がいました。
(※2018/4/30こちらについて、最下部に追記)

[SOLVED] Sounds issues - Realtek HDA - 14.2 
https://www.linuxquestions.org/questions/slackware-14/sounds-issues-realtek-hda-14-2-a-4175596546/

実際にやってみると・・・

```
% sudo alsactl init

Found hardware: "HDA-Intel" "Realtek ALC269VC" "HDA:10ec0269,10f70200,00100202 HDA:80862805,80860101,00100000" "0x10f7" "0x8338"
Hardware is initialized using a generic method
```

なんだかデバイスが再検出されて音が出ました!!

音が出なくてもいいやと思っていましたが、いざ音が出ると快適ですね。無駄にyoutubeとか見たくなります。
再起動する度に実行しなくてはならないので、起動時に実行されるように設定されるとよいと思います。私はミュートになっているか常に気になってしまうので、本当に音を出したい時だけ実行することにします。

もしかしたら、Let's Noteの CF-SX1, CF-NX2, CF-SX2なども該当するかもしれません。

Fedora27のLive CD上でも音が出るようになりましたので、Linuxで音が出ない方がいたら、ぜひ試してみてください。

#2018/4/30 追記(alsamixerにてheadphoneの音量を上げるだけで改善可能)
音が出るようになってからいろいろな方のサイトを改めて見直し、alsamixerあたりのキーワードで探すと、alasmixerで改善したという報告が多いことに気づきました。

改めて、alasmixerを確認したところ、音が出ていない時は、\<Speaker>\の音量は100のものの、\<Headphone\>の音量は0。alsactl initを実行したところ、\<Speaker\>の音量は100、**\<Headphone\>の音量も100**に。つまり、内部的にHeadphoneとSpeakerの音量表記が入れ替わっていて、更にデフォルトのHeadphoneの音量が0という非常にわかりにくい状態になっていたのでした。

つまり、alsactl initを実行するとたまたまHeadphone(実際にスピーカー)の音量が100で初期化されるというだけでした。

いろいろな方が説明をされていたのに、斜め読みをしていて見逃していた模様です。
http://iranoan.my.coocan.jp/essay/pc/201609061.htm
electron-vueで、ビルドするとスタイルに差がでる問題の解決

# はじめに
`electron-vue` については、下記の記事や公式ドキュメントを参照してみてください。
- [2017年度版 electron-vueで始めるVue.js](https://qiita.com/1ntegrale9/items/6e233f03b8cbff0b3c76)]
- [electron-vue公式ドキュメント（日本語）](https://simulatedgreg.gitbooks.io/electron-vue/content/ja/)

`electron-vue` では `electron-packager` もしくは `electron-builder` を選択してアプリケーションをビルドします。デフォルトでは、 `electron-builder` が選択されています。

今回は、 `electron-builder` を使用した際の問題について記述します。

# Element UI + 独自のスタイル で問題発生

Element UIはVueで使える、UIコンポーネントライブラリです。
[Element UI 公式サイト（英語）](http://element.eleme.io/#/en-US)

## Element UI 導入

ElementUI を使いたいので、導入します。

```
$ yarn add element-ui
...
✨  Done in 8.42s.
```

公式ドキュメントに従って、`src/renderer/main.js` にElement UIを使うコードを追加します。

```src/renderer/main.js
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
```

## Elementのコンポーネントを使ったページの追加

ElementのButtonコンポーネントを使った簡単なサンプルコードを用意します。

```Element.vue
<template lang="html">
  <div class="element">
     <el-button type="primary">何もスタイルあたってないボタン</el-button>
     <el-button class="element__originalButton">カスタムなボタン</el-button>
  </div>
</template>

<script>
export default {
}
</script>

<style lang="css">
.element__originalButton {
  background-color: #111;
  color: #fff;
}
</style>
```

`yarn run dev` で実行した結果は、下記のスクリーンショットのようになります。
真っ黒なボタンが１個追加されているのがわかります。

<img width="1112" alt="スクリーンショット 2018-04-29 21.01.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/62429/8e491bc8-c107-3f3b-4cb2-8af6e3f6f018.png">

## ビルドして実行してみる

コマンドが既に用意されているので、実行します。それなりに長いので気長に待ちます。

```bash
$ yarn run build
  ✔ building main process
  / building renderer process
✨  Done in 238.62s.
```

ビルドが完了したら、
`build/mac/アプリ名.app` を立ち上げてみます。

なんと、黒いボタンのスタイルが消えてしまい、Element UIデフォルトのボタン色がでてしまっています。

<img width="1112" alt="スクリーンショット 2018-04-29 21.10.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/62429/2179e690-3362-3435-b31c-78377c15fbfa.png">

# スタイルに差がでてしまう原因

スタイルに差がでてしまう原因は、 **ビルドすると、style.cssを生成しますが `main.js` で読み込んでいるものは一番最後に style.css に挿入されてしまう事です。**

つまり、 `.vue` ファイル内に書いたスタイルが、結局ElementUIのcssに上書きされてしまっているのです。

#解決方法

記事冒頭で、 `src/renderer/main.js` に記述した ElementUIのスタイルを読み込みコードを `src/renderer/App.vue` に移動させます。

```Diff:src/renderer/App.vue
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    name: 'element-vue-style'
  }
</script>

<style>
+ @import "~element-ui/lib/theme-chalk/index.css";
</style>
```

再度、ビルドして実行してみるとしっかりとスタイルが当たっていることがわかります。

<img width="1112" alt="スクリーンショット 2018-04-29 21.23.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/62429/a88471d4-96a4-3353-3c29-7eb15137805d.png">


めでたしめでたし。
WEBから自動的にダウロードするバッチを作成する

#概要
スクレイピングの勉強をしていたら、そもそもURLから直接ダウンロードできるファイルはコマンドで簡単にダウンロードできるんじゃねって思ったので自分用メモも兼ねて。ダウンロードしたファイルの解凍にはコマンドライン(コマンドプロンプト)から圧縮・解凍ができる「7-zip」というアプリを使用している。

#やりたいこと
公開されている[日経平均のヒストリカルデータ](https://indexes.nikkei.co.jp/nkave/index?type=download)を所定の場所に格納したいとする。![nikkeidownload.png](https://qiita-image-store.s3.amazonaws.com/0/250105/ac5f2759-db01-ad09-e060-af75d5e3095a.png)

上の画像の赤丸をクリックすると日次の日経平均株価がダウンロードできる。

ブラウザでアクセスしてクリックするだけなので簡単だが、ダウンロードフォルダから移動させるところまで自動化する。
上のサイトでは、csvファイルをダウンロードできるが、zipファイルに圧縮されている場合にも対応する。

#設計
最初に設計書を書く。これぐらいなら設計書なんかいらなくて、コマンド調べながら直接コーディングしていけばできるんだけど、設計書書くクセをつけないと後々なにやってるかわからなくなって効率が悪い(戒め)。


WEBからダウンロードして所定フォルダに移動するバッチ

```bat:nikkei_download.bat
1.ダウンロード
  bitsadmin /transfer <URL> <保存先フルパス>

2.解凍
　7z.exe x <保存先フルパス> -o<解凍先ディレクトリ>
　
3.ディレクトリ移動
　cd <保存先ディレクトリ>

4.zipファイル削除
　del hoge.zip

5.ディレクトリ移動
　cd <解凍先ディレクトリ>

6.解凍済ファイル移動
  move /Y <最終保存先ディレクトリ>

7.ディレクトリを戻す
　cd <ホームディレクトリ>　
```
##bitsadminコマンド
linuxでいうcurlのようなファイルをダウンロードするためのDOSコマンド
`bitsadmin /transfer ＜URL＞ ＜ダウンロード先＞`
###絶対パスの取得
bitsadminで指定するURLは、httpから始まる絶対パスでなければならない。
リンクを右クリックして、リンク先をコピーしたものが絶対パスになっていればよいが、そうでない場合はデベロッパーツールなどを使って、ルートパスを確認し、絶対パスに変換する。
chromeならctrl+shift+Iで切り替わる。
![nikkeidownloadhtml.png](https://qiita-image-store.s3.amazonaws.com/0/250105/c87980f4-6570-e5e5-7b4c-00b348d5df60.png)
画像のように、階層を下っていき、目的のリンクがはられているところにたどりついたら、
`href=/nkave/historical/nikkei_stock_average_daily_jp.csv`
となっているところが見るかる。
これだけだと絶対パスにならないので、このサイトのホームURLとつなげて
`https://indexes.nikkei.co.jp/nkave/historical/nikkei_stock_average_daily_jp.csv`
がダウンロード先のURLとなる。

###保存先
保存先のフォルダはどこでもよいが、bitsadminは、フルパスにしないとエラーとなるので、
`C:nikkei_download\hoge.csv`
など、ファイル名まで指定する。

##7-zip
ダウンロードするファイルが圧縮されたものだった場合は、コマンドラインから使える圧縮・解凍のフリーソフト[7-zip](https://sevenzip.osdn.jp/)を使用する。
7z.exeはインストールするとデフォルトで、program Fileに入るので、そこにPATHをあらかじめ設定しておく。
 `7z.exe x <保存先フルパス> -o<解凍先ディレクトリ>`
保存先フルパスは先ほどのものと同じ、解凍先のディレクトリを-oの後に記述する。どうせあとで移動するので、解凍先はどこでもよい。
zipファイルは削除したあと、解凍先のディレクトリにcdで移動する。

#解凍済ファイルを移動
`move /Y <最終保存先ディレクトリ>`
moveコマンドを使って、最後に保存したいディレクトリに移動する。
/Yで自動的に上書きできる。/-Yとすると、上書きするかどうか聞かれる。

##完成したバッチファイル
```bat:nikkei_download.bat
@echo off
rem 日経平均csvをダウンロードして、所定のフォルダに移動させるバッチファイル
bitsadmin /transfer https://indexes.nikkei.co.jp/nkave/historical/nikkei_stock_average_daily_jp.csv C:\nikkei_download\hoge.csv
　
rem ディレクトリ移動
cd C:\nikkei_download\

rem解凍済ファイル移動
move /Y C:\nikkei_download\csv

remディレクトリを戻す
cd C:\user\hogehoge
```
#そして自動化へ
このバッチファイルをコマンドプロンプトがされたときのホームディレクトリにおいておけば、nikkei_downloadと打ち込むだけで、自動的にダウンロードが可能となる。
今後は、PCを起動したとき、もしくは定時で自動的にダウンロードされるようにしたい。
JavaScriptの正規表現でキャプチャを使う

以下のような文字列からhttps://...pngの部分を取り出したいとする。

```
start"Url":"https://a/b/aaa.png","Url":"https://a/b/bbb.png","Url":"https://a/b/ccc.png"end
```

phpであればpreg_match_allで$result[1]に配列で格納される。

```php
$str = 'start"Url":"https://a/b/aaa.png","Url":"https://a/b/bbb.png","Url":"https://a/b/ccc.png"end';

preg_match_all('/"(https.+?)"/', $str, $result);

print_r($result);

=>
Array
(
    [0] => Array
        (
            [0] => "https://a/b/aaa.jp"
            [1] => "https://a/b/bbb.jp"
            [2] => "https://a/b/ccc.jp"
        )

    [1] => Array
        (
            [0] => https://a/b/aaa.jp
            [1] => https://a/b/bbb.jp
            [2] => https://a/b/ccc.jp
        )

)
```
Javascriptもstr.matchで簡単に取れると考えてましたが。。。

```javascript
let str = 'start"Url":"https://a/b/aaa.png","Url":"https://a/b/bbb.png","Url":"https://a/b/ccc.png"end';

let result = str.match(/"(https.+?)"/g);
console.log(result);

=>
[ '"https://a/b/aaa.png"',
  '"https://a/b/bbb.png"',
  '"https://a/b/ccc.png"']
```

matchでは取り出したい文字にダブルクォートがついた形でしか取り出せない。
なのでRegExp.execを使う。

```javascript
let str = 'start"Url":"https://a/b/aaa.png","Url":"https://a/b/bbb.png","Url":"https://a/b/ccc.png"end';

let match;
let matches = [];
while (match = regexp.exec(str)) {
  matches.push(match[1]);
}
console.log(matches);

=>
[ '"https://a/b/aaa.png"',
  '"https://a/b/bbb.png"',
  '"https://a/b/ccc.png"']
```

最初はこのexecの繰り返しで何で取得できる値が変わっていくのかが理解できませんでした。
mozillaのドキュメントを読むと正規表現オブジェクトのlastIndexプロパティの値から検索を始めると書いてました。つまりexecを実行する度に正規表現オブジェクトのlastIndexの値が更新されていくんですね。
ドキュメントにもそう書いておいて欲しかった。。。

MDN: [developer.mozilla.org](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec "Qiita")
[Kaggle]House Pricesへの挑戦#01

# はじめに
Python(Scikit-Learn)を活用し、Kaggleの[「House Prices: Advanced Regression Techniques」](https://www.kaggle.com/c/house-prices-advanced-regression-techniques)に挑戦していきます。
目標はGW中に上位10%に入ることとします。

- 「House Prices: Advanced Regression Techniques」とは  
住宅の販売価格を予測するデータ分析コンペです。
- ソースコードについて  
ソースコードはKaggleのKernelという形で公開しております。（タイトル：HousePrice_00）  
※現在kernelの公開方法についてkaggleに問い合わせ中なためkernel一覧から確認出来ない可能性があります。

# 学習モデル作成から予測結果提出まで
ベースとなるモデルを作成し、結果を提出します。

行ったこと
- データの確認
- 説明変数と目的変数の相関を確認
- 利用する説明変数の選択（相関の高い上位14項目を利用）
- 欠損値の対応
- 機械学習アルゴリズム(ランダムフォレスト)でのモデル作成
- 住宅価格の分布の確認から仮説１「目的変数の対数変換によるモデル作成」

結果
Score(RMSE）：0.16392
Rank：3027/5194 (2018/04/30時点)

今後の予定
- ハイパーパラメータの調整
- 外れ値の除去
- 説明変数の再選定および追加作成
- 機械学習アルゴリズムの再検討
- RF、SVM、XGBoostによるスタッキングモデルの作成：[参考](https://qiita.com/katsu1110/items/a1c3185fec39e5629bcb)
- 精度向上のための仮説作成および施工


# 終わりに
ご指摘、ご意見、アドバイス、ご要望などコメントいただけますと大変ありがたいです。
[Ubuntu 18.04] ログイン画面の背景を変える

# はじめに
デスクトップの背景やロック画面は簡単に変えられますが、ログイン画面は少し特殊なのでまとめました。

デフォルトだとこんな感じです。
![Screenshot from 2018-04-29 20-00-40.png](https://qiita-image-store.s3.amazonaws.com/0/130043/576064f0-5d02-4d4e-edfa-c9cbb2f184fc.png)

# 方法
まず、画像を用意します。（形式はpngかjpg)
ログイン画面の背景は全ユーザー共通なので、システムの背景画像フォルダ`/usr/share/backgrounds/`に置いておくのが適切でしょう。

```console
$ sudo cp <用意した画像のPath> /usr/share/backgrounds/
```
次に、`sudo vi`などで設定ファイル`/etc/alternatives/gdm3.css`の`#lockDialogGroup`を変更します。
デフォルトだとこうなっています。

```css:/etc/alternatives/gdm3.css
/* <<< 省略 >>> */

#lockDialogGroup {                                                               
  background: #2c001e url(resource:///org/gnome/shell/theme/noise-texture.png); 
  background-repeat: repeat; }

/* <<< 省略 >>> */
```

これを以下のように変更してください。

```css:/etc/alternatives/gdm3.css
/* <<< 省略 >>> */

#lockDialogGroup {
  background: #2c001e url(file:///usr/share/backgrounds/<用意した画像のファイル名>);         
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center; }

/* <<< 省略 >>> */
```

再起動で反映されます。
国際エンジニア10年のスウェーデン人が、日本語でアドバイスします！

こんにちは！スウェーデン生まれの純粋なスウェーデン人のオリバーです。この度は日本語でブログを始めたので、ここで初めて書き込みをさせてもらいます。

## まず自己紹介から！

早稲田大学と慶應義塾大学の留学を経て、スウェーデンのルンド大学で言語学を専攻して卒業。株式会社クラシコムにてリードエンジニア、ノルウェー最大のイーコマースSaaSでウェブデベロッパーを経験。国際エンジニアとして10年近く経験を積み、現在は日本でフリーランサーとしてウェブデベロッパーをやっています。

## このブログはなぜ？

私の拠点は松本市なんですが、一年の３分の１は世界のどこかに行って現地から仕事をしています。普段はコワーキングスペースから仕事をしていて、この前もChiang MaiのPunspaceとバリのHubudとDojo Baliに行ってきました。５月にはまた５週間ぐらいヨーロッパのコワーキングスペースを転々としながら、仕事をする予定です。

やはり海外にいくとまた日本で経験できないことや、日本でなかなか手に入らない情報を知ることができます。私は拠点は日本で、そこそこ日本語もできるので、海外で得た知識と、今までのキャリアで経験したことを何かの形で共有できたらと思い、このブログを立ち上げました。

## このブログはなに？

私が今までのキャリアで経験したこと、覚えたことをもとにかしこまらずに投稿していこうと思います。プログラミングのコンセプトの説明だったり、もっと一般的なテーマでエンジニアのだれにでも役に立つアドバイスなどをアップしていきたいと思います。

また、「これについてなんか話してよ」なんかリクエストがあればぜひサイトのコメント欄に書き込みをしてください。もしこのブログに興味をもっている人がそれなりいましたら、今後もっとちゃんとした情報共有の場にしていきたいと考えています。

では、ブログはこちらです、ぜひみてみてください！
[https://プログラミング教育.net/](https://xn--qcka9i7azcwa9b5777ejp5b.net/)

Best,

Oliver Lundquist
GASで開発する

# 本記事の目的
僕がGAS開発のためにはじめにやった事を共有・保存しておく。

# GASって何？
ググれgas

# GASの開発環境を整える
まずは基本の開発環境から。
GASはクラウド上（ブラウザ上）で全て開発できる。でもバージョン管理はgitにしたいし、いつも使っているエディタで書きたい。

## git管理にする
これについてはすでにエントリがある。
[claspを使い、Google Apps Scriptプロジェクトをgitでバージョン管理する](https://qiita.com/rf_p/items/7492375ddd684ba734f8)

上記記事のように、[clasp](https://www.npmjs.com/package/@google/clasp)を使って管理できる。
使い方はgitコマンドに似ていて、

```bash
$ clasp create project_name
```

でプロジェクトの作成、あるいは

```bash
$ clasp clone project_id
```

でクローンができる（project_idは、ドライブにあるScriptに割り当てられていて、ブラウザから確認できる）。

## VSCodeで編集する
VSCodeで公開されているプラグインに、GASのsyntax highlightはまだない。
そこで.gsファイルには.jsのsyntax highlightを適用するように設定変更する。
下記記事を参考にした。

[VSCodeのシンタックスハイライトと拡張子の関連付け](http://siamcats.hateblo.jp/entry/2017/05/09/180613)

方法は二つあるが、どちらもfiles.associationsを変更している。

方法1でMacなら、
1. Command + ,
2. files.associationsと入力
3. 下記をUser settingsに追記

```.json
{
    "files.associations": {
        "*.gs": "javascript"
    }
}
```

# GASのサンプルを読んでみる

最近は、「マニュアルに沿って書くと一つ動くものができる」形式のプログラミング講座が溢れているように見える（僕はこれを、ディアゴスティーニ式と読んでいる）。

何かしらプログラミングをしたことのある人なら、すでにできているコードを読むほうが学びが多く早い。
GASの場合は、普通にgithubに公式のサンプルアプリがある。説明も中に書いてある。

https://github.com/gsuitedevs/apps-script-samples


ドキュメントは下記
https://developers.google.com/apps-script/
Perlのforとwhileとmapの処理速度を比較してみた。

# 概要
Perlのforとwhileとmapの処理速度をそれぞれ比較してみました。

# 環境
OS: macOS Sierra
プロセッサ: 2.3 GHz Intel Core i5
メモリ: 8 GB 2133 MHz LPDDR3

# 検証方法
それぞれ50万回ループさせて、Time::HiResで時間を測ってみる。

# 検証
```test.pl
use strict;
use warnings;
use utf8;

use feature qw/say/;
use Time::HiRes qw( usleep gettimeofday tv_interval );

# for
my $t1 = [gettimeofday];
my $a = 0;
for (1..500000) {
    $a++;
}
say int(tv_interval($t1) * 1000), "ミリ秒";

# while
my $t2 = [gettimeofday];
my $b = 0;
while ($b < 500000) {
    $b++;
}
say int(tv_interval($t2) * 1000), "ミリ秒";

# map
my $t3 = [gettimeofday];
my $c = 0;
map {
    $c++
} (1..500000);
say int(tv_interval($t3) * 1000), "ミリ秒";
```

# 結果
```
$ perl test.pl
15ミリ秒
14ミリ秒
29ミリ秒
```

気にするほどではないが、for, whileに比べて、mapは少し遅いみたい
WebMIDI MIDIマッピングを製作

webMIDIで制御するのは良いけど、マッピング出来たら楽だなぁと思ったので作ってみました。



SelectIndex(0で音量,1で再生速度）を選択して、Add miniでMIDIデータ上位2バイトを配列に保存して設定完了です。

JSON形式にしてローカルファイルに保存、参照できたら良いけど面倒なのでパス。

```html:html
<!DOCTYPE HTML>
<html lang="jp">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
	<input id="Afile" type="file">
	<audio id="Aplayer"></audio>
	<input type="checkbox" id="play_pause">PLAY/PAUSE
	<input type="checkbox" id="loop">LOOP
	<input type="range" id="volume" value="1" min="0" max="1" step="0.05">GAIN
	<input type="range" id="pitchAdj" value="1.00" min="0.84" max="1.16" step="0.01">PITCH
	<select id="midiMapping" size="2">
		<option value="gain">GAIN</option>
		<option value="pitch">PITCH</option>
	</select>
	<input type="button" value="add midi" id="add">
	<script>


	</script>
</body>
</html>
```

```js:javascript
var inputs = [];
var highNibble;
var lowNibble;
var highDatabyte;
var lowDatabyte;
var mapping;
var midiData = [];
var gain;
window.onload = function() {
	//ファイルの読み込み
	var Actx = new(window.AudioContext || window.webkitAudioContext)();
	gain = Actx.createGain();
	var source = Actx.createMediaElementSource(Aplayer);
	Afile.onchange = function() {
		Aplayer.src = URL.createObjectURL(this.files[0]);
		Aplayer.currentTime = 0;
		play_pause.checked = false;
	};
	//再生、一時停止
	play_pause.onchange = function() {
		(play_pause.checked) ? Aplayer.play(): Aplayer.pause();
	};
	//ループ
	loop.onchange = function() {
		(loop.checked) ? Aplayer.loop = true: Aplayer.loop = false;
	};
	//音量
	document.getElementById('volume').addEventListener('input', function() {
		gain.gain.value = this.valueAsNumber;
	});
	//再生速度の変更
	document.getElementById('pitchAdj').addEventListener('input', function() {
		Aplayer.playbackRate = this.valueAsNumber;
	});
	//再生終了時チェックを外す
	Aplayer.onended = function() {
		play_pause.checked = false;
		Aplayer.currentTime = 0;
	};
	//ルーティング
	source.connect(gain).connect(Actx.destination);
	//MIDIマッピング
	document.getElementById("add").onclick = function() {
		mapping = document.getElementById("midiMapping").selectedIndex;
		midiData[mapping] = [highNibble, lowNibble, highDatabyte];
	};
};
//MIDIデバイスへ接続
navigator.requestMIDIAccess().then(function(midiAccess) {
	var inputIterator = midiAccess.inputs.values();
	for (var i = inputIterator.next(); !i.done; i = inputIterator.next()) {
		inputs.push(i.value);
	}
	inputs[0].onmidimessage = function(e) {
		highNibble = (e.data[0] & 240) >> 4;
		lowNibble = e.data[0] & 15;
		highDatabyte = e.data[1];
		lowDatabyte = e.data[2];
		//MIDIコントロール
		if (midiData[0].toString() == [highNibble, lowNibble, highDatabyte]) {
			gain.gain.value = lowDatabyte / 127;
		}
		if (midiData[1].toString() == [highNibble, lowNibble, highDatabyte]) {
			Aplayer.playbackRate = lowDatabyte / 127 * 0.16 + 0.92;
		}
	};
});
Loomを試しているので必要な点を纏めてみた(ENG)

個人用メモ

## create struct
`
struct User{
  uint id;
  string name;
}

User[] public users;
`
## create function && FUNCTION TYPES
- public    : Open to anywhere
- private   : Closed, which only accessible from inside of contract
- external  : Similar to public, Closed from inside but ONLY FROM OUTSIDE
- internal  : Similar to private, Closed from outside but can be called from parents

if fuctions are public or external you can create interface to defince outside.
- YourContract yourcontract = YourContract("CONTRACT_ADDRESS")<br >
yourcontract.somefunction();


- All functions are public by Default, this means can be executed from anyone or anywhere;
- put private for functions mostly
- Naming conventions are usually with _ ("underscore")

`function _giveName(string _name, uint _id) private{
  users.push(User(_name, _id))
}`

- return values
`function setRundomAge(uint a, uint b) private pure returns(uint){
  return a * b;
}`

** pure **  => * Not to Access * data in APP; <br >
** private ** => * Unabled to access * from outside; <br >
** view ** => access to view but * not to MODIFY *

## Events
- Create events for fron-end app to listen for event.

declare event <br >
`event NewUser(uint userId, string name)`

trigger event <br >
`NewUser(id, name)`

## mapping
- mapping (address => uint) public accountBalance; <br >
=> Financial APP Storing a uint to hold the user's account account balance
- mapping (uint => address) userIdToName; <br >
=> To store or lookup username based on userId

## msg.sender
- refers the address of the person called the current function
- any function(contract) should be called when it is required to be used

## keccak256
- hash function to return SHA3, change input string into a random 256-bit hexidecimal number

## require
- the function which you want to be called once per user.
- require will act like stopper for checking if any condition is true or not.
- if any condition is false the function will be not executed.

## is for inheritence
- if you wanna inherit some functions or variables from other contract,
you just add is after declaring a contract

`contract Person{
  function greeting() public returns(string){
    return "こんにちは";
  }
}
contract Employee is Person{
  function greetingAtOffice() public returns(string){
    return "お疲れ様です。";
  }
}`

## for Split files
- import files, just import './anywhere.sol';

## Where to store your values
- Memory : which only temporary data, variables declared within function are memory by default  
- Storage : which store in Blockchain permanently, variables declared outside of functions by default
ラズベリーパイ工作　センサー感知カメラ

今回はセンサー感知式カメラを作成中。


![alt](https://qiita-image-store.s3.amazonaws.com/0/245059/a6dd9d8f-f43a-2410-c22c-3fef9b93bb54.png)



しかし
なぜかinvalid syntaxに阻まれる

```
except Keyboard Interrupt:
     ^

Syntax Error invalid syntax
``` 

何が悪いのか一切わからず難航中。
あと少しなのに悔しいです。

助言など頂ければ幸いです。
PaypalのSandBoxを使えるようにするまで

# きっかけ

PayPalの決済を行いたい場合に、いきなり本番で作るのはリスキー。
そのため、PayPalではサンドボックスの環境が使えるようになっている。

ただ、英語のサイトということがあってか、使い方をよく忘れる。

ここでは購入ボタンから、リダイレクトするような仕組みができるかの確認をする。

# 前提

自分でPayPalアカウントを持っているわけではないので、ここではPayPalのビジネスアカウントが完全に使えるようになったものが用意されている段階からの操作。
→とりあえずのアカウント作成レベルだと、サンドボックスは30日でまともに使えなくなる。

# 手順
## 開発者用ダッシュボードにログイン
https://developer.paypal.com/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/70375e6c-d821-4bc6-5bc3-2933c8bee8f0.png)

ログイン情報は、持ち主から教えてもらったビジネスアカウント。

## テスト用購入者アカウントと販売者アカウントの作成

Accountsから、テストアカウント一覧画面を表示。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/8dc5079f-32ff-0b14-7a9b-b12c64b7e6e9.png)

Create Accountをクリック。
→このボタンがなかなか表示されなかった気がするが、気のせいだろうか？（色々画面を移動しているうちに、表示された）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/329dadde-ccfe-7d4a-3a2f-f108372488b4.png)

→適宜入力してアカウントを作成。Personal (Buyer Account)とBusiness (Merchant Account)両方作る。


## Merchant Account→販売者側のアカウントでログイン

サンドボックス用のURLは別にあるようで、次のURLからログイン。
https://www.sandbox.paypal.com/jp/webapps/mpp/merchant

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/ee8e6eb7-d675-f5c4-0191-a353fae361fb.png)

ログインすると、販売者側の管理画面が開く。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/124c3801-436b-5b76-f635-f736c8abe091.png)

## 購入ボタンの作成
ツール→すべてのツールをクリック。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/9a5402e2-1fb1-7481-03bc-97d12bbd79b9.png)

行いたい決済のボタンで、「新しいボタンの作成」を選択。
→実はどのボタンでも「新しいボタンの作成」を選択したら同じ画面の様子。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/3e65125d-de02-4d09-b553-2e74870eb071.png)

適宜入力項目を埋めると、ボタンが作成される。
ステップ3の項目で「顧客がチェックアウトを完了すると、このURLにリダイレクトされます。」にチェックを入れてリダイレクト先のURLを入れることで、購入後にそのサイトへ飛ばしてくれる模様。

ボタンが作成された旨の画面で、ボタンのHTMLか、メールに張り付けるURLを選べる。
→私の場合はURLがほしかったので、それをボタンのリンクにした。

## 購入テスト
ボタンを張った画面を開き、ボタンをクリックするとPayPalのログインが求められる。
→今度はBuyer Account→購入者側のアカウントでログインする。

決済を行うと次の画面が現れる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/57515/f5588716-2d02-dfb0-23b0-68ad85b0ff97.png)

リダイレクトは、自動的にではなくて「test seller's Test Storeに戻る」をクリックするときに行われる動作だった。
JAVA_HOMEはフルパスで設定しないようにしよう

久々にmvn使おうとしたらJAVA_HOMEの指定でハマったので備忘録がてらメモ。

## mvn cleanすっぞ！
High Sierraにアップデートしたら仕事で使ってるJavaプロジェクトの依存関係がリセットされていたので、とりあえずmvn cleanすっかと思った矢先

```console
$ mvn clean
The JAVA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
NB: JAVA_HOME should point to a JDK not a JRE
```
### えええええ

どうやら環境変数のJAVA_HOMEが悪いらしい。
どう設定してたっけ。

## フルパスじゃん
```console
$ cat ~/.bash_profile

...

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home

$ java -version
java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)
```
フルパスで指定してるので、JDKのバージョンアップした途端無意味な環境変数に早変わり。
むしろよく今まで無事だったもんだ。

## もっと頭のいい設定方法があるはず
どうやらこの記法ならJDKをバージョンアップしても自動で追ってくれるらしい
このパスで保存してっと...

```console
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
```

## 結果
```console
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home

$ mvn -v
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T16:58:13+09:00)
Maven home: /usr/local/Cellar/maven/3.5.2/libexec
Java version: 1.8.0_172, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.4", arch: "x86_64", family: "mac"
```

無事設定完了です。
大体コピペで済ませていましたが、環境変数も気をつけないとハマりますね。
05/10 初めての機械学習 〜Tensorflowを使って、手書きの数字を認識させる〜

# こちらは勉強会で使用する記事です。
勉強会終了後に、必要事項を記載して一般の向けに更新します。

# 実際の手順
画像データをダウンロードする
"MNIST_data"フォルダの下に配置されます

```
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
```
TensorFlowの読み込み
これで以下の「tf.~」の関数が使えるようになります

```
import tensorflow as tf
```
配列x（画像データの配列）を作成します。
placeholderとは、「入れ物」です。この入れ物にあとでデータを突っ込んでいきます。

```
x = tf.placeholder(tf.float32, [None, 784])
```

配列W（重み"weight"、xの係数）と、配列b（定数"bias"）を作成します。
Variableは「変数」です。今回は初期値を全てゼロにしています。この二つを学習しながら変化させていくことになります。

```
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
```

配列y（ある画像の、それぞれの数字の確率）を作成します。これは式で決まるものです。

```
y = tf.nn.softmax(tf.matmul(x, W) + b)
```

配列y_を作成します。これは、実際の正解のデータが入る配列です。なので、またplaceholderを使って「入れ物」だけ用意します。

```
y_ = tf.placeholder(tf.float32, [None, 10])
```

今回は配列yをy_に近づけることが目的です。「その二つがどれくらい違うか」を示すのがcross_entropyになります。**ここは今回深掘りしません。**勾配降下法という手法を使用しています。さらに勉強したい人はご自分で調べてみてください。

```
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ *tf.log(y), reduction_indices=[1]))
```

このcross_entropyを小さくするステップが、train_stepです。

```
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
```

ここはおまじないだと思ってください。処理をスタートさせるための式です。

```
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
```
学習データかでWとbを学習させます。学習用データからランダムに100個持ってきて学習させる、というステップを1000回繰り返します。

```
for i in range (1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys })
```

実験後のyと、正しいデータy_がどれくらい正解しているかを示すaccurancyを定義します。

```
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accurancy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
```

テストデータをインプットしてみて、そのaccurancyを出力させます。

```
print(sess.run(accurancy, feed_dict={x: mnist.test.images, y_:mnist.test.labels}))
```

さあ、正解率は何％だったでしょうか？？？
GenymotionでFCMの通知を受け取る

# やりたかったこと

GenymotionでもFCMのリモート通知内容を確認したかった

# 方法

[OpenGApps](http://opengapps.org/)から対象のバージョンのZipをダウンロードしてGenymotionにドラッグアンドドロップする。

自分は下記を選んで動作確認した所、問題なくFCMからの通知内容が表示出来るようになった。

Platform: x86
Android: 8.0
Variant: nano

# 雑記

調べてみたら思いのほか簡単に対応出来た。
(WIP) WordPressとBuddyPressをちょっとだけカスタマイズする

# はじめに
　とあるSNSサイトを作ることになり、いろいろなPHP系のCMS/SNSを試したところ、WordPress + BuddyPressが要件にマッチしていたので調査がてら、ちょっと足りないところがあったのでテーマとプラグインで対応してみた。

# 追加したコード
## サイト名をクリックしたら、個人ページへ飛ぶ

子テーマで対応。親テーマは`twentysixteen`を使用。

```php:child/header.php
	<?php if ( is_user_logged_in() ) : ?>
		<?php $login_user = wp_get_current_user(); ?>
		<?php if ( is_front_page() && is_home() ) : ?>
			<h1 class="site-title"><a href="<?php echo esc_url( home_url( '/member/' . $login_user->user_login ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
		<?php else : ?>
			<p class="site-title"><a href="<?php echo esc_url( home_url( '/member/' . $login_user->user_login ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></p>
		<?php endif; ?>
	<?php else : ?>
		<?php if ( is_front_page() && is_home() ) : ?>
			<h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1>
		<?php else : ?>
			<p class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></p>
		<?php endif; ?>
	<?php endif; ?>
```

## ログインした後に、個人ページに飛ぶ

プラグイン開発(?)で対応。

```php:plugin.php
public function redirect_member_mypage($login_user) {
	wp_safe_redirect('/member/' . $login_user);
	exit();
}
add_action( 'wp_login', 'redirect_member_mypage', 10, 1 );
```

# 使用プラグイン
## BuddyPress系
1. [BuddyPress](https://wordpress.org/plugins/buddypress/)   
WordPress用SNSプラグイン
1. [BuddyPress Activity Plus](https://wordpress.org/plugins/buddypress-activity-plus/)   
BuddyPressのアクティビティにメディアを追加可能にする
1. [BuddyPress Activity Privacy](https://wordpress.org/plugins/buddypress-activity-privacy/)   
BuddyPressのアクティビティの公開範囲を設定可能にする
1. [BuddyPress Members only](https://wordpress.org/plugins/buddypress-members-only/)   
会員制のクローズドSNSを作るために使用。ログインをしないとSNSページが表示されなくなる