OmniAICreator/Qiita-1.07M huggingface dataset:
Dialog要素の背景をクリックした時のイベントを取得する

# Dialogの背景をクリックしたい

HTML 5.2で追加されたDialog要素は、まだChromeでしかデフォルトで使うことが出来ません。

https://developer.mozilla.org/ja/docs/Web/HTML/Element/dialog

しかし、タグを追加してちょっと表示するだけでいい感じのモーダルが表示できるので、今後他のブラウザでも実装され次第積極的に使いたいと思っています。

が、このダイアログ、背景の半透明の部分をクリックしても閉じたりできません。

今回はこいつの背景にクリックイベントを割り当てたいと思います。

## Dialog要素の背景について

Dialog要素の背景はCSSを見ればわかりますが、疑似要素です。

`dialog::backdrop`

こいつがいい感じに半透明になって背景にいます。色を濃くしたい場合はCSSで`::backdrop`疑似要素に対してスタイルを当てましょう。

本題としてはこれの当たり判定を取りたいところですが、一つ問題があります。疑似要素はスタイルの補助みたいな感じなので、JSで要素を探して直にクリックなどのイベントを割り当てることは出来ません。

しかし、Dialog要素にクリックイベントを追加すると、疑似要素をクリックしたときにも親がクリックされたかのように反応します。

ならば、中にコンテンツ用の要素を仕込み、そいつのクリックイベントを伝播しないように食い止めれば、背景とコンテンツの判定を分けることができそうです。

## 実装

```html
<style>dialog { padding: 0; }</style>
<dialog>
	<div class="contents">test</div>
</dialog>
```

```js
const dialog = document.querySelector( 'dialog' );
dialog.addEventListener( 'click', (event) =>
{
	console.log( 'Background' );
}, false );

contents = dialog.querySelector( '.contents' );
contents.addEventListener( 'click', ( event ) =>
{
	event.stopPropagation(); // ここでクリックイベントを止める
	console.log( 'Contents' );
}, false );
```

めでたく背景とコンテンツのクリックイベントを分けて取得できました。

# まとめ

とりあえず肝は親要素に設定されている疑似要素にはクリックイベントなどをしかけられないが、親要素にクリックイベントを割り当てると疑似要素クリック時にも反応するという挙動かなと思います。
コンテンツ用に階層が一つ増えますが、そこはまぁ許容しましょう。
特定のlambdaからのみS3のバケットを操作できるバケットポリシーを作りたい

## やったこと

lambdaを使ってデータをS3に保存するときにバケットをパブリックにしてしまうとセキュリティー的によろしくないのでアクセスを制限するためにバケットポリシーを作成しました。
今回は`A`というバケットに `PutObject` を `put_s3` というlambdaからのみ許可させます。

## ハマったとこ

最初、以下のようなバケットポリシーにしていました。
lambdaからのアクセスを許可するんだからprincipalには **lambda** のarnを入力したらいけるでしょって感じで。
しかし、これで保存をしようとすると `Invalid principal in policy` とエラーが...

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "test_policy",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:lambda:ap-northeast-1:xxxxxx:function:put_s3"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::A/*"
        }
    ]
}
```

## 解決策

以下のように **lambda** のarnでは無く **lambdaに付与しているrole** のarnを指定することで無事バケットポリシーを作成することができました。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "test_policy",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxx:role/lambda_role"
            },
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::A/*"
        }
    ]
}
```
SlackBotを一時的に静かにさせる。

SlackBotで一時停止する方法が見つからなかったので乱暴なやり方で作成。
一応動いております。

```py
@respond_to(r'黙れ|静かにしろ|滅びろ', re.IGNORECASE) #一時的に終了します。100秒立ったら起動します。
def listen_func(message):
    """ room lock  """
    if message.body["channel"] not in CHANNEL_LIST:
        return

    message.reply('100秒ほど寝てきます') # メンション
    try:
        sys.exit()
    finally:
        """os exit. before process start. """
        proc = Popen("sleep 100; bash /root/bot/start.sh",
                        shell=True,
                        #close_fds=True,
                        #preexec_fn=os.setsid
                        )
        logwrite('info', message.body["user"]," : bot stop")
        os._exit(0)

```

`sys.exit()`で中途半端に終了（無駄処理？）して`finally`で無理やりサブプロセス(Shellコマンド)呼んでます。

```
sleep 100; 
bash /root/bot/start.sh
```

ちなみにStartShellは環境変数を読み込んで実行してるだけです。


start.sh

```sh
#!/bin/bash

source ./slackbot_settings.sh


if [ ! -e ./output_log/ ]; then
	mkdir ./output_log
fi

nohup python3 ./run.py  > ./output_log/out.log 2>&1 &
```

slackbot_settings.sh

```sh
export SLACK_BOT_TOKEN=xoxb-##############-##############
```
Python socketでちょっとしたチャット作ってみた

# Python socketでチャット作ってみました


##●はじめに
久しぶりにサイバーセキュリティプログラミングの本を読みました。
TCPサーバとTCPクライアントを作ってたら「もしかしたらチャット作れるんじゃない？」っていう感じで作ってみました。  
チャットと言っておきながらサーバ-クライアント間なので、なんちゃってチャットになってます。
今回はサーバをConohaのVPS(Centos7),クライアントをwindows上で動かしてます。
##1,TCP_SERVER

```python:TCP_SERVER
import socket



host_ip = socket.gethostbyname(socket.gethostname())        #ホストのIPを取る
port = 1890

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #ソケット作成

server.bind((host_ip, port))                                #IPとポート結び付け

server.listen(1)                                            #接続数

print ("[*]Server waiting on %s : %s" % (host_ip, port))    

client, addr = server.accept()                              

print ("[Connection from %s:%s ]" % (addr[0], addr[1])) 



def input_encode():                                         #送るメッセージ入力
    data = input("[Server] > ")
    
    if data == "exit":                                      #終了条件
        client.send(b'exit')
        print ("////Finish Connect////")
        server.shutdown(1)
        server.close()
        exit()
        
    else:
        data = data.encode('utf-8')                         #エンコード
        return data

def decode(response):                                       #デコード 
    response = response.decode()

    if response == "exit":                                  #終了条件
        print ("////Finish Connect////")
        client.close()
        exit()

    return response



while True:
    response_data = client.recv(1024)                       #データ受け取り
    response_data = decode(response_data)
    print ("[Client] > %s " % (response_data))              
    
    client.send(input_encode())                             #メッセージ送信
```

#<br>


##2,TCP_CLIENT

```python:TCP_CLIENT
import socket


target_host = "サーバIP"                       
target_port = 1890

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      #ソケット作成
client.connect((target_host, target_port))                      #サーバのIPとポートで接続 

print ("Connect Success!! %s : %s" % (target_host, target_port))



def input_encode():                                             #エンコード
    data = input("[Client] > ")
    
    if data == "exit":                                          #終了条件
        client.send(b'exit')
        print ("////Finish Connect////")
        client.shutdown(1)
        client.close()
        exit()
    
    data = data.encode('utf-8')
    return data

def decode(response):                                           #デコード
    response = response.decode()
    
    if response == "exit":                                      #終了条件
        print ("////Finish Connect////")
        client.close()
        exit()
    
    return response

while True:
    client.send(input_encode())         
    
    response = client.recv(4096)                                #データ受け取り
        
    response = decode(response)                                 #受け取りデータをデコード
    print ("[Server] > %s " % (response))                       

```
#<br>
##まとめ
チャットもどき完成した！　けど、まだまだ改善する点がありそう。
一番詰んだ点は、サーバ側のpythonが2.7でinputがうまくいかなくてずっと悩んでました
結局Python3.5入れて動かしました。

次はクライアント間でチャットできるのを作ります。
Rails Jbuilderにおける「should」のエラー

# Jbuiderで「should」が使えない・・・
Elasticsearchのsearchメソッドの引数を作成するために、Jbuiderを使用していますが、謎の現象が起こりました。

```ruby:sample_controller.rb
Jbuilder.encode do |json|
  json.query do
    json.bool do
      json.should do
        json.terms do
          json.hogehoge_id [1, 2, 3]
        end
      end
    end
  end
end

# => "{}"
```
shouldの部分をmustやてきとうな文字列piyopiyoなどに変換すると、うまく変換されます。

```ruby:sample_controller.rb
Jbuilder.encode do |json|
  json.query do
    json.bool do
      json.must do
        json.terms do
          json.hogehoge_id [1, 2, 3]
        end
      end
    end
  end
end

# => "{\"query\":{\"bool\":{\"must\":{\"terms\":{\"hogehoge_id\":[1,2,3]}}}}}"
```

「json.should」を使用すると、空のjsonが返ってきてしまいます。

##「json.should」が使えない原因
rails consoleでJbuilderをオブジェクトを確認すると、

```sh
Jbuilder.new.must
# => "{\"query\":{\"bool\":{\"must\":{\"terms\":{\"hogehoge_id\":[1,2,3]}}}}}"
Jbuilder.new.should
# => #<RSpec::Matchers::BuiltIn::PositiveOperatorMatcher:0x0055c2e05b8bc0 @actual=>
```

おそらく、RSpecでもshouldが使われていてバッティングしているんだな〜と思い、「rails jbuilder should rspec elasticsearch」でググると以下ページが見つかりました。

https://discuss.elastic.co/t/managing-namespace-conflicts-with-jbuilder-rspec-when-creating-boolean-queries-filters-with-should/14800

##解決策
上記リンクの通り、「json.set! :should」でうまくいきました！

```ruby:sample_controller.rb
Jbuilder.encode do |json|
  json.query do
    json.bool do
      json.set! :should do
        json.terms do
          json.hogehoge_id [1, 2, 3]
        end
      end
    end
  end
end

# => "{\"query\":{\"bool\":{\"should\":{\"terms\":{\"hogehoge_id\":[1,2,3]}}}}}"
```
Rictyのバッククオートを修正する

Rictyはライセンスの関係上、使用に際してフォントを手元で合成する必要がありますが、2018年6月26日現在、合成後のフォントに不具合があり、バッククオート(`←これ)が後続の文字に重なって表示されてしまいます。
FontForgeを使うと簡単に修正できるのですが、軽くググった感じだと情報が見付からなかったので、ここでまとめておきます。

コメントでCUIで完結させる方法を共有してくださっているので、そちらもぜひ参照してください。

# 用意するもの
- 合成済みのRicty / Ricty Discord
- FontForge GUI

# 修正手順
1. FontForgeのGUIを起動します
2. 編集したいフォントファイルを開きましょう(`Ricty-Regular.ttf`, `RictyDiscord-Regular.ttf`等)。
3. ずらっと表示された文字の中から、バッククオートを見付けましょう。文字コードはU+0060で、小文字のaの一個前に表示されているはずです。
4. 見付けたバッククオートを右クリックし、「グリフ情報」を開きます。
5. 左のリストから「Unicode」を選択すると、設定画面の「OTFグリフクラス」が「マーク」になっているはずです。
6. 「OTFグリフクラス」を「マーク」から「基底グリフ」に変更します。
7. 「OK」を押してウィンドウを閉じます。
8. 「ファイル」メニューから「フォントを出力」を選んで、編集したフォントを書き出しましょう。ファイル名は元のファイルから変えておいた方がわかりやすいでしょう(`Ricty-Regular-fixed.ttf`とか)。
9. 「生成」を押すとファイルが書き出されます。いろいろと警告が出てくると思いますが全部無視して「はい」や「生成」を選んでかまいません
10. 完了！

必要なら、他のファイルも編集し、書き出しましょう(ObliqueとかBoldとか)。
修正してもフォント名は「Ricty」のままで変わらないので、もし修正前のフォントがインストールされているなら、そちらは削除してしまった方がよいでしょう。
WordPress環境のIPアドレスが変わってしまったときの対処法

## 背景
AWS(EC2)上に構築したWordPress環境があった。ElasticIPを関連付けていなかったため、ElasticIPを関連付けようと、作業を行った。作業を行った結果、グローバルIPが変更されてしまった。ために、次の2つが設定と合わなくなってしまい、WordPress環境が開かなくなってしまった。

- WordPressアドレス
- サイトアドレス

## やったこと
今回のパターンはよくあることらしいので次の記事を参考にした。
https://www.nishi2002.com/4207.html

`wp-config.php`に次の2項目を追加した

```php
define('WP_SITEURL', 'http://***.***.***.***/wp'); // WordPressアドレス
define('WP_HOME', 'http://***.***.***.***.***'); // サイトアドレス
```

今回利用しているWordPress環境は、RDSにて外部DBを持っているため、この変更だけではWordPressの設定値を書き換えることができない。（外部DBがない場合はこれだけで大丈夫なはず？未確認）

そこで、RDS環境に直接入り、UPDATEをかけた。

```sql
select * from wp_options limit 2;
+-----------+-------------+--------------------------+----------+
| option_id | option_name | option_value             | autoload |
+-----------+-------------+--------------------------+----------+
|         1 | siteurl     | http://xxx.xxx.xxx.xxx/wp | yes     |
|         2 | home        | http://xxx.xxx.xxx.xxx    | yes     |
+-----------+-------------+--------------------------+----------+

> update wp_options set option_value = 'http://***.***.***' where option_name = 'home';

> update wp_options set option_value = 'http://***.***.***' where option_name = 'home';
```

### 注意点
`http://` から記載しないと、相対パスになってしまうので注意。これで何回かハマってしまった。。。
開発者のためのイベントとはどういうものか、インフラジスティックスの Distinct から学ぶ

本日 [Distinct -モダンアプリケーション開発を成功に導くための進化とそのアプローチ](https://connpass.com/event/89509/) というイベントに参加しました。製品発表会であると思って参加したイベントでしたが、**開発者にとって実に有意義なイベント**でした。

もともとここで発表された Indigo.Design という製品を学びに来たのですが、参加して感じた事もあるので、先にそちらを書いておいて、後日 Indigo.Design についても書いていきます。

# イベント概要

インフラジスティックス・ジャパンが主催の半日イベントで、「モダンアプリケーション開発を成功に導くための進化とそのアプローチ」というサブタイトルで開催された、開発者向けのイベント。詳細は [Connpass のページ](https://connpass.com/event/89509/) 参照。

# インフラジスティックスが提供するもの

もともと ASP.NET や Angular などで利用できる UI コンポーネントを提供。しかし最近では Indigo Studio という UX ツールを提供するなど、UX/UI レイヤー全体をカバーする製品やサービスを提供。今日は [Indigo.Design](https://jp.infragistics.com/products/indigo-design) の発表イベント。

# セッションの構成として面白かった点

以下本日のセッションのタイトルとスピーカー。

3 つしかセッション無いのに、初めの 2 つは外部の人でした。また内容でも一切インフラジスティックス製品にも触れない。純粋にモダンアプリ開発に関する話。しかし 2 つとも最後のインフラジスティックスのセッションにとって繋がりのある、重要なものであった。

**モダンアプリケーション開発のチャレンジと、今押さえておきたい技術とツールの活用**
日本マイクロソフト 井上章

このセッションで開発者が意識しないといけない世界観と苦労する点を参加者と意識を共有。

**なぜAngularなのか、2018年の答え**
Angular日本ユーザー会 代表 稲富 駿 (@laco2net) 氏

このセッションで Angular というフレームワークの重要性だけでなく、「フレームワークを提供する組織の姿勢やコミュニティなどの仕組みが重要」というメッセージ。

**Distinct: モダンアプリケーション開発において他者との差別化を実現する Indigo D2C Studio**
Infragistics, Inc. Senior Vice President of Developer Tools
Jason Beres (@jasonberes)

最後に上記を踏まえたセッションの実施。いい流れ。

# Indigo.Design のセッション

最後のセッションでようやく Indigo.Design の紹介。Jason が英語で話し、東さんが日本語訳をするという流れ。また日本市場を重要視しているというメッセージが強い。このセッションでも開発者を意識できていて、話が聞きやすい。

**Indigo.Design が必要な理由**
詳細はまた後日書きますが、UX のことであっても開発者が興味をもって話を聞ける背景を説明。ただ前置きは比較的短く簡潔。

**分かりやすいデモ**
UX 製品だけあって製品のデモも綺麗な感じで見やすい。また UX のモックだけでなくコードに繋げられるという点を強調。開発者としては UX モックできるのは大事ですけど、じゃあこれでと言われた際のコーディングが一番大事なので嬉しい限り。

**誰が何をするかという説明**
出来ることがいくつかあるが、それぞれデザイナーがやるのか、開発者がやるのかという点を明確にしているため、頭を切り替えて聞ける。

**キーメッセージ**
簡単にアプリがモックできるだけでなく、カスタマイズもできるため、本当の UX を確認できるよという点と、そこからコーディングにもスムーズに繋げられるよという話でした。

# 何を学んだのか

**開発者向け**イベントだけでなく、どんなイベントにも共通することですが、やはり参加者視点でイベントの構成を考える。その際に以下の点が大事だなと感じました。

- 関係が深く、かつ興味を惹くコンテンツを、組織に捉われずオープンに考える
- 製品の機能だけではなく、参加者が得られるベネフィットについてメッセージを出す
- 以下に既存のワークフレームに**統合**しているかという点を強調して、安心感を出す
- デモでは、極力同じ画面を出してコンテキストを拾いやすくする
- 紹介するシナリオをより出席者が共感できそうなものを選ぶ

製品以外にも色々学べる面白いイベントでした。

# 参照
[Indigo.Design](https://jp.infragistics.com/products/indigo-design) 
[Indigo Studio を使って UX を開発にうまく取り込む！](https://qiita.com/kenakamu/items/f11380b908337f014710)
[Angular と Ignite UI for Angular でクロスプラットフォームアプリを作る その 1](https://qiita.com/kenakamu/items/f256a154e5caf5c55c54)
[Angular と Ignite UI for Angular でクロスプラットフォームアプリを作る その 2](https://qiita.com/kenakamu/items/e3db361ad1821786dd7d)
Serverless Framework 事始め(setup〜hello world)

# 準備

## node のバージョンを最新にする。

[こちら](https://nodejs.org/en/)から推奨の最新バージョンをチェックする。
2018年6月26日現在、v8.11.3が良さそうなのでそれにする。

```bash
$nvm install v8.11.3
```

## 公式に従ってセットアップ

[こちら](https://serverless.com/framework/docs/providers/aws/guide/installation/)を参照して行う。

```bash
$npm install -g serverless

# インストール完了
$serverless -v
1.27.3
```

aws のクレデンシャルの設定を行う。
[こちら](https://serverless.com/framework/docs/providers/aws/guide/credentials/)を参照

1. Admin 権限の IAM ユーザを作成する。
2. 設定をする。

```bash
# aws の profile を指定する場合は以下をする必要がある
$ export AWS_PROFILE="profileName2" && export AWS_REGION=eu-west-1.

```


## Hello world
[こちら](https://serverless.com/framework/docs/providers/aws/examples/hello-world/node/)を参考
How to Install Oracle JDK 1.8 in Ubuntu 18.04 LTS?

# 1. Download JDK 1.8.172
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

# 2. Unzip
```
# sudo mv ~/Download/jdk-8u172-linux-x64.tar.gz /opt
# cd /opt
# sudo tar zxvf jdk-8u172-linux-x64.tar.gz
# sudo chown -R root:root jdk1.8.0_172/
# sudo ln -s jdk1.8.0_172/ jdk
```

# 3. Set Env
```
# sudo vim /etc/profile.d/java-sdk-env.sh

export JAVA_HOME=/opt/jdk
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin

:wq!
```

# 4. Reboot
```
# sudo reboot
```

# 5. Check
```
# 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)
```
ngrokをubuntu18.04上にインストール


ngrok を使って気軽に手元のサーバを外部に公開する方法です
###ngrok とは

ngrok
https://ngrok.com/

自分の開発環境を外部からアクセス可能にするためのツールです。
Firewall等の設定を考えなくていいので楽です。



### インストール
https://ngrok.com/download 
上記のURL画面中央左に、Download for Linuxという大きいボタンがあるので
そこからzipファイルを取得する。

ngrokのあるフォルダに移動(設定を変えていなければ /home/[ユーザ名]/ダウンロード)
`$ unzip ngrok-stable-linux-amd64.zip`
解凍されてできたディレクトリを/usr/binへコピーする。
`$ sudo cp ngrok /usr/bin/`

上記の設定が終わり、ngrokへアクセスできることを確認する。
`$ ngrok version`
`ngrok version 2.2.8`


### アクセス方法
80番ポートを外部に公開する
`$ ngrok http 80`

なにやら表示されるので、アクセスURLをコピーし、ブラウザでアクセスする。
# 
    ngrok by @inconshreveable
    (Ctrl+C to quit)
    Session Status                online
    Session Expires               7 hours, 59 minutes
    Version                       2.2.8
    Region                        United States (us)
    Web Interface                 http://127.0.0.1:4040
                                  ↓↓↓これでアクセスできる↓↓↓
    Forwarding                    http://xxxxxxxx.ngrok.io -> localhost:80
    Forwarding                    https://xxxxxxxx.ngrok.io -> localhost:80
    Connections                   ttl     opn     rt1     rt5     p50     p90
    0       0       0.00    0.00    0.00    0.00

`$ curl http://[ランダムな文字列].ngrok.io`


#### ユーザ登録するとドメイン設定できたりするらしいですが、割愛。
AWS Systems Manager(SSM) パラメータストアに改行コードを含むデータを保存するときの方法

# この記事について
AWS Systems Manager パラメータストア(以下SSM)はCloudFormation等には記載したくないパスワードやsshの鍵などを暗号化して保存することができる便利な機能です。深く使っていくにつれて改行を含むような秘匿データを保存したい用途が出てくるのですが、改行を含むデータを保存したいときのやり方が以前と変わっているようなので、記録を残す目的で作成しました。

# 昔はできてたやり方
旧来は、SSM に対してput-parameterする際のValueに **\n** を入れることでget-parameterする際に改行として認識されましたが、現在は使用できなくなっています

# 現在（2018/6）時点でのやり方
Valueに直接改行を入れることでput-parameterすることができます。

# 方法１：ファイルに入力データを入れて読み込む
入力したいデータをテキストファイルで用意します(以下の例だとhoge.txt)。それを--valueに指定することでputできます。

```
aws ssm put-parameter --name "/key/name" --value fileb://C:\hoge.txt --type "SecureString" --key-id "key_id" --overwrite
```

#方法２：直接改行する
短い文章の場合は直接改行を入れても改行できます。Linuxでコマンド途中に改行を入れるには`Ctrl+V → Ctrl+J`とすると改行できます。（Windowsは知りません）

```
aws ssm put-parameter --name "/key/name" --value "text1
text2
text3
" --type "SecureString" --key-id "key_id" --overwrite
```
TwitterRの利用

```R
install.packages('twitteR')
install.packages('base64enc')

# ライブラリの読み込み
library("twitteR")
 
# 情報の入力
consumerKey <- "Consumer Key"
consumerSecret <- "Consumer Secret (API Secret)"
accessToken <- "Access Token"
accessSecret <- "Access Token Secret"
 
# 処理の準備
# httr_oauth_chcheを保存
options(httr_oauth_cache = TRUE)
# 認証情報の取得
setup_twitter_oauth(consumerKey, consumerSecret, accessToken, accessSecret)

# @deskplateのツイートを最新１０件取得　　上限は3200件
tweets <- userTimeline("deskplate", n = 10)
# 表示
tweets
```
Pythonモジュールのimportができなくなったときの対処記録

# 概要
自動化処理の勉強中、それまでインポートできていたPythonのrequestsモジュールが急に（？）インポートできなくなったので対処しました。現在はこの方法でうまくいっています。

# 環境
windows10
Python 3.6.5
Anaconda3
requests2.19.1

# エラー内容

```python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'requests'
```
先日までできてたのに急にこんなエラーが出ました。
requestsなんて名前のモジュールは無いからインポートできないと言われているわけです。

# 状況確認
まずは、適切にrequestsがインストールされているのか確認しました。pipコマンドでインストールしたもののリストを表示し、確認しました。

```console:PowerShell
$ pip list
```
結果：ありました

次に、requestsがインストールされたパスを確認しました。

```console:PowerShell
$ pip show requests
```

次に、Pythonシェルで、モジュールを探索するパスのリストを確認しました。

```python:PythonShell
>>>import sys
>>>sys.path
```

結果：requestsがインストールされているパスが、Pythonが探索するパスのリストに含まれていないことが確認できました。

# 対処
Pythonが探索するパスのリストに、requestsがインストールされているパスを追加すればよいので、以下を実行しました。


```python:PythonShell
>>> import sys
>>> sys.path.append('該当のパス')
```

これで無事、requestsのインポートができるように直りました。

# まとめ
Pythonが探索するパスとモジュールがインストールされているパスに差異ができていたため、適切なパスを設定しなおすことで、今回の問題は対処できました。
Google Apps Scriptを使ってGoogle Drive上のファイルを分割する

# 概要
Google Drive内にあるサイズの大きなファイルをGoogle Apps Script（GAS）で処理しようとすると、扱うことのできるサイズに制限が設けられているために直接処理することはできません。そのため、ファイルを分割することを考えます。バイト配列や文字列に変換してから分割という方法もあるのですが、この場合、GASで扱うことのできる``blob``の最大サイズが50 MB (52,428,800 bytes)と制限されているため、50 MBよりも大きなサイズのファイルを扱う場合にどのようにして分割しようか悩まされました。悩んだ結果、50 MB以上の大きなファイルをGoogle Driveへアップロードするために用意されている[Resumable upload](https://developers.google.com/drive/v3/web/resumable-upload)がありますが、Resumable downloadもあってよいのではないかと思い、これを探したところ、[Partial download](https://developers.google.com/drive/api/v3/manage-downloads#partial_download)なる機能を発見しました。これはまさにResumable downloadのためのものです。これを利用することで50 MB以上のファイルでも無事に分割して処理することができるようになりました。この記事ではPartial downloadを用いたファイル分割について紹介します。

# 使い方
このサンプルを使用する際は、事前にGoogleの拡張サービスとAPIコンソールでDrive APIを有効にしてください。

1. Googleの拡張サービス
    - スクリプトエディタから リソース -> Googleの拡張サービス を開き、Drive APIを有効にしてください。

1. APIコンソール
    - スクリプトエディタの「リソース」 -> 「Cloud Platformプロジェクト」を開きます。
    - 「このスクリプトが現在関連付けられているプロジェクト:」の下のリンクをクリックします。
    - 「スタートガイド」の「API を有効化し、鍵などの認証情報を取得」をクリックします。
    - ダッシュボードにDrive APIが見えている場合はそれをクリックします。見えていない場合は、左側のサイドバーにある「ライブラリ」をクリックします。
    - 「APIとサービスを検索」へ Drive API と入力して検索します。
    - 表示された中からDrive APIをクリックします。
    - ここでDrive APIを有効にします。ボタンをクリックしてから少しの待ち時間があります。

次に、スクリプトの一番上にある``fileId``, ``chunk``, ``fileName``を使用する環境に合わせて変更してください。

- ``fileId``は分割したいファイルのファイルIDです。
- ``chunk``は分割したいそれぞれのファイルのサイズです。最後のファイルは残りのサイズが割り当てられます。
- ``fileName``は分割したファイルのファイル名です。ファイル名の後に通し番号が付加されます。

# サンプルスクリプト
~~~javascript
// 下記3つの変数は環境に合わせて修正してください。
var fileId = "### fileId ###";
var chunk = 123456; // Set chunk size.
var fileName = "sample";


var accessToken = ScriptApp.getOAuthToken();
var baseUrl = "https://www.googleapis.com/drive/v3/files/";

// Retrieve file size.
var url1 = baseUrl + fileId + "?fields=size";
var params1 = {
    method: "get",
    headers: {Authorization: "Bearer " + accessToken},
};
var fileSize = Number(JSON.parse(UrlFetchApp.fetch(url1, {headers: {Authorization: "Bearer " + accessToken}}).getContentText()).size);

// Calculate number of output files.
var start = 0;
var end = chunk;
var loop = Math.floor(fileSize / chunk);
loop = fileSize % chunk > 0 ? loop + 1 : loop;

// Split large file by chunk size (bytes).
var results = [];
var url2 = baseUrl + fileId + "?alt=media";
for (var i = 0; i < loop; i++) {
    var params = {
        method: "get",
        headers: {
            Authorization: "Bearer " + accessToken,
            Range: "bytes=" + start + "-" + end,
        },
    };
    var f = Drive.Files.insert({title: fileName + (i + 1)}, UrlFetchApp.fetch(url2, params).getBlob());
    results.push({name: f.title, id: f.id});
    start += chunk + 1;
    end = start + chunk;
}
Logger.log(results);
~~~

# サンプル
他の状況として、大きなサイズのCSVファイルを分割しつつ、スプレッドシートに変換するサンプルは[こちら](https://gist.github.com/tanaikech/3e44c779f05374d19333444c9a4dd5ba)をご覧ください。
Swift UITabbarでBarItem選択時にTintColorでアイコンが塗りつぶされるのを防ぐ

デフォルトのままだとタブバーのアイテム選択時にアイコンの画像がTintColorで塗りつぶされてしまう。
それを防ぐ例の１つ。

・baritemのselectedImageをwithRenderingMode(.alwaysOriginal)で登録

```swift
class MainTabBarController: UITabBarController {
    
    override func viewDidLoad() {
        
        let tabBar = self.tabBar
        
        // 選択時の画像を登録しておく
        (tabBar.items![0] ).selectedImage =  UIImage(named: "ico_tab_xxx.png")?.withRenderingMode(.alwaysOriginal)
        (tabBar.items![1] ).selectedImage =  UIImage(named: "ico_tab_xxx.png")?.withRenderingMode(.alwaysOriginal)
        (tabBar.items![2] ).selectedImage =  UIImage(named: "ico_tab_xxx.png")?.withRenderingMode(.alwaysOriginal)
        (tabBar.items![3] ).selectedImage =  UIImage(named: "ico_tab_xxx.png")?.withRenderingMode(.alwaysOriginal)
        (tabBar.items![4] ).selectedImage =  UIImage(named: "ico_tab_xxx.png")?.withRenderingMode(.alwaysOriginal)
    }
}
```
[デプロイ]アセットパイプラインとはなんぞや？？？[本番環境]


# はじめに
ある時、僕はアプリを作ってAWSでデプロイをしました。
デプロイ自体はできて本番環境でちゃんと動いてくれたんですよね。わーいですよね。
が、しかしですね、CSSがあたらかったんですよね。むちゃ困りますよね。

そして、原因としては、アセットパイプラインでした。アセットパイプラインが上手くできておらず、そのためcssが無くて崩れて表示されていたんですよね。

そのときに、
「アセットパイプラインとはなんぞや？？？」
と思ったので、調べてわかったことをまとめてみました。



# 対象とする人
・デプロイした時、cssが当たらないんですけど・・・・な人


#この記事の流れ
・一言でいうと・・・
・前提として・・・・
・詳しく書くと・・・
・まとめ

# 一言でいうと・・・

### 「CSSファイル,imageファイル、javascriptsファイルを一つのファイルにまとめること」
です！！！！


では、詳しく書いていきますね〜。

# 前提として・・・・
詳しく書く前に、
まず、前提として、インターネット上の情報は、Webブラウザを介して見ることがほとんどですよね。

そのWebブラウザ上に画面が表示されるのは、
”WebブラウザがHTMLとCSS、JavaScriptを認識してくれる” 
からなんですよね。

当たり前やん！と思われたかもしれませんが、このことを頭に置いて、記事を読み進めていってもらえたらと思います。

# 詳しく書くと・・・

何かアプリケーションを作成する時、
開発環境においてはjsファイルや、cssファイル、imageファイルは別のディレクトリに入っていますよね。

例　　　①cssファイル➡︎app/assets/stylesheets/hogehoge.css
　　　　②jsファイル➡︎app/assets/javascripts/abc.js

どうして分かれているかというと、
<b>「開発環境で開発をするときに、一つのディレクトリの中に色々なファイルが全て入っていたら開発がしにくいから」</b>
です。

　例えばcssファイルとjsファイルが同じディレクトリの中にあると、なんのファイルがどこにあるかが分かりづらく、あのファイルどこだっけ？どのディレクトリにあるんだっけ？みたいなことになりかねません。
　そのため、開発環境ではjsファイルや、cssファイル、imageファイルは別のディレクトリに分かれています。

そして、開発環境では、その分かれているファイルをちゃんと読み込んでくれるので、cssが崩れたりすることはありません。

ですが！

本番環境では、その分かれているファイルを読み込むことができません。
そのため、「アセットパイプライン」という仕組みが用いられるようになりました。



流れとしては、

アプリケーションを開発！
⬇︎
本番にデプロイ
⬇️
cssファイル、jsファイル、imageファイルを本番環境にも適応させてwebブラウザで見れるようにしなくちゃ。
でも、webブラウザには複数のファイルを読み込む力が無いよー
⬇️
どうしよう・・・・。
⬇️
そうや！複数のファイルを読み込むんじゃなくて、結合して一つにしたらええんやわ！そうしたら、ちゃんとwebブラウザも読み込んでくれる！
⬇️
結合して一つのファイルにするには・・・・
⬇️
アセットパイプラインを使えばええんや！


こんな流れです。
さらに、アセットパイプラインを使えば、一つにファイルがまとめられるため、その分処理が高速になります。

そして、そのアセットパイプラインを使うために、
本番環境上で「プリコンパイル処理」というのをします。

本番環境上で、

```
rails assets:precompile
```
をします。

最後に、本番環境上でアセットパイプラインを自動で通るように設定を変更すればCSSファイル等が崩れずに表示されます。
production.rbに書かれている

```production.rb
config.assets.compile = false
```
というものを

```production.rb
  config.assets.compile = true
```

に変更します(falseをtrueに変更します)



以上で、CSSやJavaScriptを反映させることができます。




# まとめ

アセットパイプラインを使う理由は・・・・
・CSSファイル,imageファイル、javascriptsファイルを一つのファイルにまとめて、webブラウザでちゃんと読み込めるようにすること。
・一つのファイルにまとめることで、処理を高速にして、webブラウザでページの表示を素早くさせるということ。


# というわけで・・・
お読みいただきありがとうございました。
次はハッシュ値について時間があるとき書けたらなぁと考えております。


間違い等ございましたら、ご指摘いただけると嬉しいです！
Macのdateコマンド（フォーマット指定でエラー）

こういうエラーがでました。

```
$ date -j -f "%b %d %Y" "Jun 26 2018" "+%Y/%m/%d"
Failed conversion of ``Jun 26 2018'' using format ``%b %d %Y''
date: illegal time format
usage: date [-jnRu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
```

調べてみと、どうやら日本語環境での`%b`に違いがあるようです。

### 月のショートバージョン

```
$ date +%b
 6
$ LANG=c date +%b
Jun
```

日本語環境だと`半角スペース+数字`


### 月のロングバージョン

```
$ date +%B
6月
$ LANG=c date +%B
June
```
日本語環境だと`数字+月`

# 結論

下記は同じ結果です。

```
LANG=c date -j -f "%b %d %Y" "Jun 26 2018" "+%Y/%m/%d"
LANG=c date -j -f "%b %d %Y" "June 26 2018" "+%Y/%m/%d"
LANG=c date -j -f "%B %d %Y" "Jun 26 2018" "+%Y/%m/%d"
LANG=c date -j -f "%B %d %Y" "June 26 2018" "+%Y/%m/%d"

date -j -f "%b %d %Y" " 6 26 2018" "+%Y/%m/%d"
date -j -f "%b %d %Y" "6月 26 2018" "+%Y/%m/%d"
date -j -f "%B %d %Y" " 6 26 2018" "+%Y/%m/%d"
date -j -f "%B %d %Y" "6月 26 2018" "+%Y/%m/%d"

```

jオプション指定で`%b`と`%B`はどちらでも良さそうです。
Azure Automationを使ってVirtual Machineの自動起動・停止をしよう

## はじめに

AWSではCloudWatchEvents + Lambda + SQSなんかを組み合わせて自動化していたのですが、AzureではAzure Automationを使うとインスタンスの自動起動・停止を簡単に行うことができます。

自身で作ったスクリプトを動かすこともできますが、「ギャラリー」という自動化スクリプトが沢山置いてあるところからスクリプトをインポートして手軽に実行することができます。

インスタンスの自動起動・停止は、ネット上にはいくつか記事が出てきます。2018年6月時点ではアカウントの作成周りは簡略化されているようでしたので手順を載せておきます。

## Automationアカウントの作成（初回のみ）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/d0b0371b-bb52-cc41-7394-ad48c12e856a.png)

必要事項を記入して「作成」をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/3cbfd343-d88f-868f-1de1-8a5ad1b52060.png)

少し待つとautomation アカウントが作成されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/e745a674-c2db-0f75-1b6e-bbf6d2ace300.png)

## 起動停止スクリプトを取得します。

Runbook → ギャラリーを参照をクリック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/89e22369-25e2-3249-29cc-6a9300656a5b.png)

「Start Azure V2 VMs」「Stop Azure V2 VMs」をクリックして「インポート」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/f7a36b35-05ae-739a-9dbd-2612c6d5088f.png)

インポートするときに名前がつけられるので、今回は「StartAllVm」「StopAllVm」という名前を付けました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/ee41d9de-5909-327f-7e97-4cc765f8d222.png)

Runbookにスクリプトが保存されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/a0212eef-1cc6-5d9c-c24b-6710d882da14.png)

## StopAllVmの設定（Startの場合も操作は同じです）

StopAllVmをクリックして、「編集」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/5de10320-b266-09ba-78bb-97c48c734dd5.png)

「公開」をクリックします。
「テストウィンドウ」ではこのスクリプトのテストができます。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/58df22a5-597b-1030-9f0a-57b5670b34a9.png)

スケジュールを設定するには画面上部の「スケジュール」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/7d24150a-5c33-95dd-c999-ccd7d5f72e13.png)

時間を決めます。ここでは14:30にVMを停止するようにスケジュールしました。
一度きりでもできますし、定期的な繰り返しも設定可能です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/a53d5de8-2884-8098-0daf-65fe30f2372c.png)

パラメータの設定ができます。予め止めるVMが決まっている場合などは、VMの名前を指定しておくことができますし、
リソースグループ名だけ指定しておけばリソースグループ配下すべてを停止します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/2e0848a1-f1bd-3883-84dd-29b69d621427.png)

## ログの設定

ちゃんと動いたかどうか確認するにはログのトレースを取っておいてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/278ee7f5-f792-a037-1fa7-111b9b60276c.png)

## 動いたか確認する

完了になるまで待ちます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/aa5a4a8d-9ff1-6328-f754-d8a54480259d.png)

VMもちゃんと止まりましたね！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57686/de61e808-447b-c51d-8679-a171ec914926.png)

## さいごに

ギャラリーを覗いてみるとSQLDatabaseやHDInsightなどのサービスの便利スクリプトがたくさんありました。
気軽に自動化できるのはとても良いので作る前にギャラリーを覗いてみてはどうでしょう。
LaravelからDropboxの操作を行う

# はじめに
Laravelのストレージ操作は[Flysystem](http://flysystem.thephpleague.com/docs/)という抽象ファイルシステムを使用しており、ローカルのファイルシステムやAmazon S3、Rackspaceといったクラウドストレージを操作できるドライバが提供されています。

今回はここにDropboxを操作する設定を加えていきたいと思います。
（Laravel 5.1と5.5で動作することを確認済み）


# Dropbox側の操作

## アプリの作成開始

[App Console](https://www.dropbox.com/developers/apps)から、「My Apps」を開き、「Create app」をクリックします。

![dropbox_my_apps.png](https://qiita-image-store.s3.amazonaws.com/0/116677/279fe8a6-a1c2-ff0b-57a8-7bf4710edec1.png)

## 作成するアプリの設定

必要な情報を入力して、アプリの作成をします。
今回はDropbox上の指定フォルダのみを操作するアプリとして作成してみました。

![dropbox_create_new_app.png](https://qiita-image-store.s3.amazonaws.com/0/116677/de83fab5-dcc3-67b7-1239-439940b83d8c.png)

## accessTokenの取得

アプリが作成できたら、設定画面に自動遷移します。
OAuth2の欄内にある「Generate」をクリックして、作成されたaccessTokenをコピーしておいてください。

![dropbox_oauth2.png](https://qiita-image-store.s3.amazonaws.com/0/116677/49f72e94-afc6-86f8-9bd6-02b5541d9060.png)

accessTokenを作成すると、Dropboxの「アプリ」フォルダの下に、対応するフォルダが自動で作成されるようです。
（確認メールやらスマホアプリの通知やらが一斉に飛んできてビクッとしました）

# Laravel側の操作

## .envファイルに取得したaccessTokenを記述

```/.env
DROPBOX_ACCESS_TOKEN=hogehoge
```

`php artisan config:clear`を忘れずに。

## 必要なパッケージの取得

[コチラ](https://readouble.com/laravel/5.5/ja/filesystem.html)のドキュメントでは、`spatie/flysystem-dropbox`を使うような記述になっていますが、どうやらv1のAPIを使用しているようで、現在は使えません。

v2に対応している、コチラを使用します。

```
$ composer require srmklive/flysystem-dropbox-v2
```

## ServiceProviderを作成

```
php artisan make:provider DropboxFilesystemServiceProvider
```

## ServiceProviderの中身を実装

```/app/Providers/DropboxFilesystemServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

use Storage;
use League\Flysystem\Filesystem;
use Srmklive\Dropbox\Client\DropboxClient;
use Srmklive\Dropbox\Adapter\DropboxAdapter;

class DropboxFilesystemServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        Storage::extend('dropbox', function ($app, $config) {
            return new Filesystem(new DropboxAdapter(new DropboxClient($config['accessToken'])));
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```

## Filesystemの設定に追記

```/config/filesystems.php
'disks' => [
    // 以下を追記
    'dropbox' => [
        'driver' => 'dropbox',
        'accessToken' => env('DROPBOX_ACCESS_TOKEN'),
    ],
],
```

## ServiceProviderを登録

```/config/app.php
'providers' => [
    App\Providers\DropboxFilesystemServiceProvider::class,
],
```

# 動作確認

作成されたフォルダに適当なファイルを保存して...

```php
// ファイル一覧の取得
$filepaths = \Storage::disk('dropbox')->allFiles('/');

foreach ($filepaths as $filepath) {
    \Log::debug($filepath);
}
```

ログにファイルの一覧が出力されていれば完了です。
テキストファイルのみ抽出して改行コードを変換するワンライナーコマンド

# 概要
シェル上から、テキストファイルの拡張子を個別に指定して、改行コードをCRLF→LFに変換するワンライナーコードを紹介します。

# コード
```shell
$ find /path/to/directory -type f \( -name \*.php -or -name \*.js -or -name \*.txt -or -name \*.html -or -name \*.css \) -exec dos2unix {} \;
```

# 改行して見やすく
```shell
$ find /path/to/directory \
    -type f \
    \( \
        -name \*.php \
        -or \
        -name \*.js \
        -or \
        -name \*.txt \
        -or \
        -name \*.html \
        -or \
        -name \*.css \
    \) 
    -exec dos2unix {} \;
```

# 説明
findコマンドのオプションで特定の拡張子を指定し、それらをdos2unixコマンドに渡しています。
それだけといえばそれだけです。
該当のテキストファイルを上書きして保存するので、要注意です。
多層ニューラルネットワークの作成/①

```py
neuralnetwork.py

import tensorflow as tf
import matplotlib.pyplot as plt
import csv
import os
import numpy as np
import requests

birth_weight_file = 'birth_weight.csv'
# Download data and create data file if file does not exist in current directory
if not os.path.exists(birth_weight_file):
    birthdata_url = 'https://github.com/nfmcclure/tensorflow_cookbook/raw/master' \
                '/01_Introduction/07_Working_with_Data_Sources/birthweight_data/birthweight.dat'
    birth_file = requests.get(birthdata_url)
    birth_data = birth_file.text.split('\r\n')
    birth_header = birth_data[0].split('\t')
    birth_data = [[float(x) for x in y.split('\t') if len(x) >= 1]
                  for y in birth_data[1:] if len(y) >= 1]
    with open(birth_weight_file, "w") as f:
        writer = csv.writer(f)
        writer.writerows([birth_header])
        writer.writerows(birth_data)
        f.close()

# read birth weight data into memory
birth_data = []
with open(birth_weight_file, newline='') as csvfile:
    csv_reader = csv.reader(csvfile)
    birth_header = next(csv_reader)
    for row in csv_reader:
        birth_data.append(row)

birth_data = [[float(x) for x in row] for row in birth_data]

y_vals = np.array([x[8] for x in birth_data])
```

**y_vals = np.arry(x[8] for x in birth_data)**
このy_valsで毎回エラーが生じる。
**IndexError: list index out of range**
birth_dataの特徴量は全部で9つだからnp.array(x[8] …　in birth_data)の所は間違ってないはずなのに。
##→ 理由はファイルデータが一行ずつ改行されててそこもnp.array(x[8]...)で読み込んでたからだった。改行を消してみたらしっかりできた。

TensorFlowのcookbook
https://github.com/nfmcclure/tensorflow_cookbook/blob/master/06_Neural_Networks/06_Using_Multiple_Layers/06_using_a_multiple_layer_network.py

TensorFlow cookbookにも同じ風に書いてあるので違うところで間違ってる可能性があると思うんだけど全然わからない。対処法分かる方いたら教えてください。
Gmailで二段階認証を使って転送用アドレスを設定するメモ

#これはなに
Gmailで送信元アドレスを転送用アドレスに設定しようとしたら詰まったのでメモ．
前のやり方（https://qiita.com/_myouga/items/df0b6c2f470e466593a5 ）が最近はうまくいかないらしいので書き直し．
（以下の手順を行うためには二段階認証を有効化する必要がある．）

#やったこと
1. アプリパスワードの生成
Googleのヘルプが詳しい．
→ https://support.google.com/accounts/answer/185833?hl=ja
リンク先の手順に沿ってアプリパスワードを設定．使用する端末はWindows PCとかでOKだと思う．


2. Gmailの歯車→設定→アカウントとインポート→メールアドレスを追加
名前とメールアドレスを入れる．エイリアスの設定はお好みで．
SMTPサーバをsmtp.gmail.comに．ポート485，SSLを指定
ユーザ名はGoogleアカウントのものを入力
パスワードは**先に生成したアプリパスワード**を使用


3. 認証メールが届くので，メールに書かれたURLをクリックまたはコードを入力して転送アドレスを認証，無事送信元アドレスとして使用可能になる．

#感想
なかなかめんどくさい．セキュリティ性と利便性の相反性を実感．
似たようなことをやってうまくいかなかった方はコメントいただければ嬉しいです．（解決のお手伝いはできません）
緯度経度、ECEF系、方位角・仰角などの座標変換に便利なプログラムPyMap3d

## PyMap3d
PyMap3dはボストン大学のリモートセンシングが専門のMichael Hirsch教授が作った3次元の地理座標変換プログラムです。
Pyとついていますが、pythonだけではなく、Matlab・Fortranのプログラムも同じリポジトリで公開されています。

似たような座標変換のpyprojという便利なpythonモジュールもありますが、[pyproj](https://github.com/jswhit/pyproj)はC言語で書かれたPROJ4 libraryのPythonインターフェイスであるのに対して、pyMap3dは純粋にPythonで書かれています。Qiitaにpyprojの使い方の例もあります。
[[GPS]pyprojを使用してGPSの緯度経度から距離、方位角、仰角を算出する](https://qiita.com/tomo001/items/84d49e18e9dd3373ce0f)

また、PyMap3dはMatlab Mapping Toolboxで使われている名前に合わせた関数名にしてあり、理解しやすく、Matlab Mapping Toolboxは1000ドルのソフトのに対して、FreeBSDライセンスで公開されています。
また、pyprojが地表面上の計算や換算に特化しているのに対して、PyMap3dは空中を移動する物体やリモートセンシング向けに特化しています。自分の利用の範囲では、pyprojでは緯度経度上の表面距離は算出できても空中の2地点間の距離の計算は簡単には出来ない（数行かけば出来ますが…）ので、地上局から飛翔中のロケットの方位角や仰角・直線距離を簡単に算出するには不便でした。

PyMap3dではそれぞれの座標系の変換を行えます。
* ECEF（地球中心・地球固定座標系）
* ENU（東、北、上）
* NED（北、東、下）
* ECI（地球中心慣性座標系）
* 測地系（緯度、経度、高度（世界測地系））
* 局所水平座標系（Az-El）
* 赤道座標

## インストールと使い方
[githubのPyMap3dリポジトリ](https://github.com/scivision/pymap3d) にかかれている通りです。

```
pip install pymap3d
```

でインストールできます。
使い方の例として、東京にある皇居から富士山頂への方位角（真北から時計回りの角度）と仰角（水平面から上向きの角度）と直線距離を出力してみます。

```python
import pymap3d as pm

lat_Fuji = 35.360556 # [deg]
lon_Fuji = 138.727778 # [deg]
alt_Fuji = 3819.9 # 楕円体高 [m]

lat_Kokyo = 35.685175 # [deg]
lon_Kokyo = 139.7528 # [deg]
alt_Kokyo = 50  # 楕円体高 [m]

x,y,z = pm.geodetic2ecef(lat_Kokyo, lon_Kokyo, alt_Kokyo)

az,el,range = pm.geodetic2aer(lat_Fuji, lon_Fuji, alt_Fuji, lat_Kokyo, lon_Kokyo, alt_Kokyo)

print("皇居 ECEF座標 : %d [m], %d [m], %d [m]" % (x, y, z))
print("皇居 to 富士山 : 方位角 = %.1f [deg], 仰角 = %.1f [deg], 直線距離 = %.1f [m]" % (az, el, range))

```


> 皇居 ECEF座標 : -3958664 [m], 3350924 [m], 3699904 [m]
皇居 to 富士山 : 方位角 = 249.1 [deg], 仰角 = 1.7 [deg], 直線距離 = 99805.4 [m]


と表示されます。緯度経度さえ指定していれば、1行で必要な値が取れます。

## 想定される利用先
下記の利用などが想定でき、それぞれ1行でかけるので便利です。

* ドローン等から出力されるGPS情報から観測者からの距離、方位角、仰角を算出
* ドローン等が持っているカメラの向きを決めるのに観測したい座標を指定して向ける方位角・仰角（俯角）を算出
* ロケット等の飛翔体をアンテナで追いかけるのに必要な方位角・仰角を算出
* 緯度経度からECEF座標やECI座標系への変換
* 赤経・赤緯でまとめられている星表などから、観測地点でのその星の方位角・仰角の算出
junitでStringをJsonObjectに型変換するとNullになる

ハマったのでメモ

この現象はAndroidでjUnitを実行したときに起こるそうです。


## StringからJsonObject型に変換するときにJsonObjectがNullで返ってきてしまう。

JsonをパースしてModelに変換するテストを書いてる時にハマりました。

```kotlin

　　　　　　　　@Test
    fun jsonパースがちゃんとできているかのテスト() {

        val jsonObj = JSONObject("{\"key1\":\"aaaaa\",\"key2\":\"bbbbb\",\"key3\":\"ccccc\",\"key4\":\"ddddd\"}")
        val item = Info.Model.perse(jsonObj)
        Assert.assertEquals("aaaaa", item.key1)
        Assert.assertEquals("bbbbb", item.key2)
        Assert.assertEquals("ccccc", item.key3)
        Assert.assertEquals("ddddd", item.key4)
    }
```


これでテストを実行すると `jsonObj` がNullで返ってきてテストが失敗します。


## 解決方法


`app/build.gradle` に下記を追加します

```groovy

testImplementation 'org.json:json:+'
```


これで `jsonObj` がNullで返らなくてちゃんと `JsonObject` 型になります。
パッケージのソースを改変する


作業をするディレクトリはフルパスに日本語が含まれない場所で行ってください。
grdesktopを改変する定で進めます。

#### コマンドだけをみて簡単に確認
```
$ sudo vi /etc/apt/sources.list
-- ここで行頭がdeb-srcとなっている箇所を全てコメントアウトする
$ sudo apt update
$ mkdir grdesktop
$ cd grdesktop/
$ sudo apt-get build-dep grdesktop
$ apt-get source grdesktop
$ cd network-manager-l2tp-0.9.8.5/
-- ここでソースを改変する
$ dpkg-source --commit
$ dpkg-buildpackage -us -uc
```

#### コマンドがしている内容
ビルドに必要なパッケージをインストールするための準備
```$ sudo vi /etc/apt/sources.list
$ sudo apt update
```
作業ディレクトリを作成
```$ mkdir grdesktop
```
作業ディレクトリに移動
```$ cd grdesktop
```
該当パッケージのビルドに必要なパッケージを取得
```$ sudo apt-get build-dep grdesktop
```
該当パッケージのソースを取得
```$ sudo apt-get source grdesktop
```
ソースの入ってるディレクトリに移動
```$ cd network-manager-l2tp-0.9.8.5/
```
ソースの変更をコミットする
git commitと同じような物だと思えばOK
変更された箇所を記述したパッチファイルが開かれるため、「99_変更名」などの名前をつけて保存します。
```$ cd network-manager-l2tp-0.9.8.5/
```
変更したソースを元にビルドします。
```$ dpkg-buildpackage -us -uc
```
何かしらエラーが出て止まってしまう場合は以下の事を確認してください。
- 作業ディレクトリのフルパスに日本語が含まれていないか
- 行ったソースの変更に実行できなくなるような変更ミスがないか
    - ミスがあってもビルドが通ってしまうこともあります
sshログイン自動化４種

MacだとTeraTermがないので、.ttlファイルを渡されても困る、、、
中を開けばログインユーザ/IPアドレス/パスワードは書かれてるけど、毎回sshコマンド打つのしんどい、、、
サードパーティーのソフトとかダウンロードしてくればいいんだろうけど、探すのめんどい、、、
自分でShellScript書こう、、、

##基本Ver(パスワード認証方式)

```sh:base_pswd.sh
#!/bin/sh
  
USERNAME="hoge"
IPADRS="xxx.xxx.xxx.xxx"
PSWD="8MojiIjo!Random!"

expect -c "
    set timeout 5
    spawn ssh ${USERNAME}@${IPADRS}
    expect \"password:\"
    send \"${PSWD}\n\"
    interact
"
```

変数の値だけ書き換えてやれば使える超基本形。

##基本Ver(公開鍵認証方式)

```sh:base_rsa.sh
#!/bin/sh
  
USERNAME="hoge"
IPADRS="xxx.xxx.xxx.xxx"
PSWD="8MojiIjo!Random!"
KEY_PATH="~/.ssh/xxxx_rsa"

expect -c "
    set timeout 5
    spawn ssh -i ${KEY_PATH} ${USERNAME}@${IPADRS}
    expect \"${KEY_PATH}\"
    send \"${PSWD}\n\"
    interact
"
```

公開鍵のパスを指定して、パスコードを入力させる基本形。

##踏み台経由Ver

```sh:humihumi.sh
#!/bin/sh
  
USERNAME="hoge"
IPADRS="xxx.xxx.xxx.xxx"
PSWD="8MojiIjo!Random!"

HMDI_USERNAME="humidai_hoge"
HMDI_IPADRS="yyy.yyy.yyy.yyy"
HMDI_PSWD="8MojiIjo!Random!"

expect -c "
    set timeout 5
    spawn ssh -t ${HMDI_USERNAME}@${HMDI_IPADRS} \"ssh ${USERNAME}@${IPADRS}\"
    expect \"password:\"
    send \"${HMDI_PSWD}\n\"
    expect \"password:\"
    send \"${PSWD}\n\"
    interact
"
```

`ssh`コマンドに`-t`オプションを付けてやると、２段階でsshが出来る。

##応用Ver(引数次第で、踏み台にもその先にもいける)

```sh:humihumi_sonosaki.sh
#!/bin/sh
  
USERNAME="hoge"
IPADRS="xxx.xxx.xxx.xxx"
PSWD="8MojiIjo!Random!"

HMDI_USERNAME="humidai_hoge"
HMDI_IPADRS="yyy.yyy.yyy.yyy"
HMDI_PSWD="8MojiIjo!Random!"

case "$1" in
    humidai)
      expect -c "
          set timeout 5
          spawn ssh ${HMDI_USERNAME}@${HMDI_IPADRS}
          expect \"password:\"
          send \"${HMDI_PSWD}\n\"
          interact
      "
  ;;
    sonosaki)
      expect -c "
          set timeout 5
          spawn ssh -t ${HMDI_USERNAME}@${HMDI_IPADRS} \"ssh ${USERNAME}@${IPADRS}\"
          expect \"password:\"
          send \"${HMDI_PSWD}\n\"
          expect \"password:\"
          send \"${PSWD}\n\"
          interact
      "
  ;;
     *)
     echo "Usage: humihumi_sonosaki.sh {humidai|sonosaki}"
  ;;
esac
```

引数に応じて分岐させるパターン。
その先がWeb/App/Dbなど複数になっても、この辺だけ変えれば１ファイルで済む。
Googleタグマネージャを使っていて、GoogleAnalyticsイベントをJavaScript経由で取得できない場合の対処法

GoogleAnalyticsのイベントが送信されなくて、おやっ？となったので備忘録。


GoogleTagマネージャを利用してGoogleAnalyticsを管理している場合に
以下のようなコードを書いてもイベントが飛びませんでした。

```javascript
ga('send', 'event', 'Hoge', 'fuga', 'piyo');
```

サイトの一番うしろに持ってきたり、Onloadで囲んだりしてみたんだけど
結局[StackOverFlow](https://stackoverflow.com/questions/15744042/events-not-being-tracked-in-new-google-analytics-analytics-js-setup)様で発見。

GoogleタグマネージャでGoogleAnalyticsを管理している場合は

```javascript
if ("ga" in window) {
    tracker = ga.getAll()[0];
    if (tracker)
        tracker.send('event', 'Hoge', 'fuga', 'piyo');
}
```

みたいに書くのが正解らしい。
Atom利用中パッケージ

###tag
閉じタグ自動挿入してくれる。らくちんちｎ。
###highlight-column
インデント（字下げ）を可視化してくれる。
###file-icons
ファイルのアイコンを色分けてくれる。見やすい。見つけやすい。

###browser-plus
Atomのなかにブラウザを入れてくれるやーつ。
右クリックして'Open browser-plus'ボタンを押すか、
'ctrl + alt + o'のショートカットキーで表示される。
###color-picker
色を可視化してカーラーコードを設定できる代物。あると便利。
###pigments
すでに設定しているカラーコードに対して色を示してくれる。
###emmet
HTMLタグを自動で入れてくれる。全部打たなくていいかららくちんｔｎ。

###atom-clock
時間管理大事です。はい。
###minimap
ファイル内のソース全体を表示してくれる。
###highlight-selected
同じファイル内にある文字を検索してくれる。
対象の文字がハイライトで囲われるので見つけやすい。

- 引用元
 - https://www.sejuku.net/blog/3099
 - https://qiita.com/sayama0402/items/3bd8d905619c514179b7
 - http://co.bsnws.net/article/97
動的に生成したPDFをEdgeでインライン表示したい

# 背景
- PDFをiframeタグでインライン(埋め込み)表示したいよくある話
- サーバーサイドで動的に生成したPDFファイルを表示する
- レスポンスヘッダの設定などをしてもEdgeだけPDFをダウンロードしてしまう
- 資料が少なく自力で調査することになった

# Edgeの仕様
- ブラウザに標準でPDFリーダ機能が搭載されている
- POSTリクエストで取得したPDFファイルは強制ダウンロード
- レスポンスヘッダで`Content-Disposition: inline`を設定しても**POSTリクエストだと無視される**

# 解決策
- PDF生成に必要なパラメータはURLで送る(GET送信)
- iframeタグのsrc属性にパラメータつきURLを設定
- レスポンスヘッダの設定
    - `Content-Type: application/pdf`
    - `Content-Disposition: inline; filename="ファイル名"`
    - `Content-Length` は設定しなくてもよい

# 補足
- IEでのPDF表示にはアドオンが必要
- IE、Edgeではインライン表示時に保存ファイル名をあらかじめ指定することはできない
- Edgeでの「POSTの場合ダウンロードする」という挙動の回避策は見つからず

# 関連
- [Edge でのPDFダウンロード動作について - Microsoft](https://social.technet.microsoft.com/Forums/ja-JP/2d7870e6-8779-4fcf-91e6-0f87fbc68299/edge-pdf?forum=internetexplorerja)
document.writeでscriptを読み込んではいけない

***document.writeでes6 modulesをロードしてはいけない(戒め)***

# introduction

## 状況説明

最近(18/5/9)、**[Firefoxがes6 modulesに対応](https://developer.mozilla.org/ja/Firefox/Releases/60)**しました。
これで、主要なブラウザがすべてes6 modulesに対応したことになるといえるでしょう。

その流れで、手元の既存のjsをmoduleに対応させようと動かしてみたところ、**`type=module`なスクリプトが想定通りに読み込まれないというバグ**が現れました。

ブラウザによって、「ロードはされるが実行されない」という動きであったり、「ロードされず、スクリプトのGETリクエストも飛ばない」という状態だったりとまちまちです。

その動きの原因は、とあるフレームワーク内で使用されていた`document.write()`でした。
es6 modulesとの相性が悪いのか、**ブラウザごとに異なる挙動をする**という状態です。
(エラーは出ません。なぜか、エラーは出ません)

そこで、この`document.write()`を試してみました。

## テストに使用したコード

テストに使用したソースコードは以下の通りで、これを適当なサーバーで動かします。
Chrome、Firefox、Edgeでアクセスし、コンソールを確認しました。

```index.html
<html>
  <head>
    <script src="./index.js"></script>
  </head>
  <body>
    Hello World!
  </body>
</html>
```

```index.js
console.log('...')
$(document).ready(() => {
  console.log('...2')
  document.open()
  document.write('<scr' + 'ipt type=module>console.log("...3-1")</scr' + 'ipt><scr' + 'ipt>console.log("...3-2")</scr' + 'ipt>')
  document.write('<scr' + 'ipt>console.log("...3-3")</scr' + 'ipt>')
  document.write('<scr' + 'ipt type=module>console.log("...3-4")</scr' + 'ipt>')
  document.close()
  console.log('...4')
})
```

# result

なお、個人的な想定としては以下のようなものでした。

- すべて実行される
- `type=module`であるスクリプトは後から実行される(`defer`)

## Chrome 67.0

```chrome
...1
...2
...3-2
...3-3
...4
```

`type=module`であるスクリプトは呼ばれませんでしたが、`index.js`内の`console.log()`も動作しています。
`type=module`なスクリプトだけ、全く無視されるというのも、それはそれで想定外なのですが…。

## Firefox 60.0

```firefox
...3-2
...3-3
...3-1
...3-4
```

**`document.write()`で指定したスクリプトしか動作していません。**
そもそも`document.write()`自体非推奨になっているということもあり、あまり仕様を確認していませんでしたが、これは想定外です…。

## Edge 42

```edge
...3-2
...3-3
...3-1
...3-4
```

Edgeの動作は**Firefoxと同様**でした。
手元のブラウザだと2:1で、どうやらChromeの動きが少数派なようです。

# Conclusion

## テストについて

(注：個人の感想です)

`document.write()`に対する知識の不足もあり、想定していた結果に一致するブラウザが存在しないという結果になりました。

`type=module`なスクリプトも実行されるブラウザと実行されないブラウザで、処理が全く異なることが想像できます。

個人的に問題だったのが、ChromeとFirefoxの動作の違いです。
先述の「ロードはされるが実行されない」ブラウザがchromeで、「ロードされず、スクリプトのGETリクエストも飛ばない」ブラウザがFirefoxだったのですが、納得です。
全く違う結果です。

が、バグに納得できても仕様には納得できるものではありません。
特にChromeとFirefoxは「IE系よりも先に対応させておけ」と言われるようなブラウザですし、なんというかもう少し、その、同じような動きになっていただけませんか…？

## document.write()について

結論として何が言いたいかというと、**非推奨になるには相応の理由があるのでちゃんと従ってください**ということです。

この件、特にFirefoxについて、es6 modules対応が実装されたばかりということもあってか、issueトラッカーへの蓄積も少なく、`document.write()`の動きに行きつくところまでが大変でした。

先述の通り、そもそも`document.write()`自体、[HTML5で非推奨](https://dev.w3.org/html5/spec-LC/apis-in-html-documents.html#document.write)ということもあって、`type=module`なスクリプトを`document.write()`でロードするなどという奇特なことをやっているサンプル・バグなど見つかるはずもありません。

しかし、スクリプトの動的な読み込みの方法の一つとして`document.write()`の利用を提案しているWebサイトは多くあります。
また、今回の例のように、**直接的に使用していなくてもフレームワーク内で使用している**という場合はまだまだあるでしょう。
その際の**おかしな動き**について、「このような場合もあるのだ」程度にでも覚えていただけると幸いです。



# 参考
- https://developer.mozilla.org/ja/Firefox/Releases/60
- https://dev.w3.org/html5/spec-LC/apis-in-html-documents.html#document.write
Oracle データポンプ EXPDP時に「ORA-01555: スナップショットが古すぎます」のエラーが発生する

# ORA-01555: スナップショットが古すぎます
とある日から
Oracleのデータポンプで「ORA-01555: スナップショットが古すぎます」のエラーが発生する。
これはEXPDP時にOracle内のUNDO表領域が足りなくなって起こるエラー

# 原因
EXPDP時にエクスポート開始時点とエクスポート終了時点での整合性を保つ為に
UNDO表領域を使用しており、
EXPDP時に他のセッションからテーブルに更新がかかり、UNDO表領域が更新前のテーブルを保持しきれなくなって発生してしまうエラー

# どうすれればいいの？
解消する為には
UNDO_RETENTION のパラメータ(デフォルト:900秒)を拡張する

# 具体的に何秒にすればいい？
正常にexpdpが完了してた時にかかった時間と同等の時間
 普段expdpに２時間かかるのであれば、UNDO_RETENTIONは7200秒を指定すれば、まず問題は無いはず。
EC2にgoofysを使ってS3をマウントしたメモ

#S3をEC2にマウントした時に少し苦労したので書いておく。

[このブログを参考にgoofysを入れる。]
(https://dev.classmethod.jp/cloud/aws/how-to-use-s3fs-goofys/)

###Goとfuseをインストール
```
$ sudo yum install golang fuse -y
```
###goofysをインストール
```
sudo wget https://github.com/kahing/goofys/releases/download/v0.0.5/goofys -P /usr/local/bin/
```

###AWSと結びつけるためにAWSCLIの設定をする。
[AWSCLI　の設定については公式を参照]
(https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html)

```
aws configure
```

###マウントポイントの作成
フォルダを作るだけです。

```
mkdir s3
```

###S3をマウントする
下記コマンドを実行

```
 goofys S3バケット名  マウントポイント

```
このあとbin/goofysを見る権限がないって怒られて、sudoをつけるけれども `goofys` なんていうコマンドはないと怒られる。

原因はこのコマンドを打っていないから

```export GOPATH=$HOME/go```

そりゃそうですわ。

このあと実行コマンドを直し実行

```$GOPATH/bin/goofys  s3バケット名 マウントポイント```

でもだめ。
```main.FATAL Unable to mount file system, see syslog for details```
ただsyslogを見ろとエラーが出るのでまだ助かる。 `/var/log/messages`

syslogを見ると以下の通り
```
/home/ec2-user/go/bin/goofys[2856]: s3.INFO Switching from region 'us-east-1' to 'ap-northeast-1'
/home/ec2-user/go/bin/goofys[2856]: s3.ERROR code=NoCredentialProviders msg=no valid providers in chain. Deprecated.#012#011For verbose messaging see aws.Config.CredentialsChainVerboseErrors, err=<nil>#012
/home/ec2-user/go/bin/goofys[2856]: s3.ERROR code=NoCredentialProviders msg=no valid providers in chain. Deprecated.#012#011For verbose messaging see aws.Config.CredentialsChainVerboseErrors, err=<nil>#012
/home/ec2-user/go/bin/goofys[2856]: main.FATAL Mounting file system: Mount: initialization failed
/home/ec2-user/go/bin/goofys[2856]: main.ERROR Unable to access 's3バケット名': NoCredentialProviders: no valid providers in chain. Deprecated.#012#011For verbose messaging see aws.Config.CredentialsChainVerboseErrors
```

awsのconfigureが読み取れなかったみたいです。
コマンド `ls  ~/.aws` でconfigureがある場所を探すと 
root配下にありました。

毎回sudoコマンド打つのも嫌になったので
```sudo su -```
でrootユーザーに変更。

そうして上記マウントのコマンド打つと
```$GOPATH/bin/goofys  s3バケット名 マウントポイント```

無事マウントしました。


>参考にしたサイト

[EC2＋goofysでS3バケットをマウントしたい](https://qiita.com/0xmks/items/f1d325ce2de6a805c6f7)

[goofysを使ってAmazon LinuxにS3をマウントする。]
(https://qiita.com/kooohei/items/a14f22cb0381342d1861)