OmniAICreator/Qiita-1.07M huggingface dataset:
Cognos のTivoli Access Manager(TAM)経由のSSOでジャンクション作成時の-jオプションが必要

#概要
Cognos BIやCognos Analyticsで、Tivoli Access Manager(TAM)やIBM Security Access Manager(ISAM)を経由してシングルサインオンを実現したい場合に、TAMのジャンクション作成時に -j オプションを付与してジャンクションを作成しないと、SSOが実現できない場合が良くあります。

覚えておいて欲しい事は**「CognosとTAM(ISAM)のSSO時は、ジャンクションの作成時に-jオプションを考慮が必要」**という一言なのですが、-jオプションってなんだろう、というのを調べたので投稿しておきます。

#ジャンクションの-jオプション
WebSEALはリバースプロキシとして動作します。
リバースプロキシ処理のためにWebSEALはバックエンドサーバーをWebSEAL上の仮想ディレクトリとしてマッピングします。
仮想ディレクトリのことをジャンクション（Junction）と呼びます。
仮想ディレクトリ名の追加、削除処理をするためにコンテンツをWebSEALで変換する必要があります
WebSEALの変換処理は万能ではないため、WebSEALが処理出来るようにコンテンツの変更が必要なケースがあります
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/9cce386c-0c65-9609-bd32-42ec45aea5b3.png)

WebSEALはリバースプロキシーの処理をする際に、バックエンドサーバごとにジャンクション名をつけることで、複数のサーバを識別します。
ブラウザからコンテンツにアクセスするときに、ジャンクション名つきのURLでアクセスさせる必要があります。
レスポンス送信時にURLのパスにジャンクション名を付け加えます。
この動作をURLフィルタリングと呼びます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/5ad1152c-e996-16bb-e18b-880c0b29c9fc.png)

URLフィルタリング出来ないままコンテンツがクライアントに送られた場合、ブラウザからWebSEALのジャンクションを含まないURLに対するリクエストが送信される可能性があります。
例: JavaScriptで文字列の演算を行ってURLを生成するケースなどでWebSEALを通過する時点でフィルタリング対象のURLと見なされなかったコンテンツ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/53b05dea-440f-bb6f-7b73-c9534c57831e.png)

**ジャンクションオプション –j**
この様な場合にジャンクション名を補完する機能として、-j オプションがあります。
ジャンクション名をCookieにセットしてブラウザに記憶させます。
HTMLコンテンツにCookieをセットするJavaScriptを挿入します。
Cookie名: IV_JCT
値にはジャンクション名が入ります。
WebSEALへのリクエストURLにジャンクション名が入っていなくてもCookieでジャンクション名を補うことで正常にアクセスが可能になります。

ジャンクションを作成するときに–j オプションを指定することでCookieがセットされるようになります。

-jオプションを指定すると、URLフィルタリングの動作が変わりますので注意が必要です。
–バックエンドサーバーが発行するCookieのpathの処理
–バックエンドサーバーが発行するCookieの名前の処理

#参考情報
実際にCognos Analytics 11とISAM(TAM)で構成した時の事例を投稿していますので、うまく行かない場合はこちらもご参照下さい。
**Cognos Analytics と ISAM(TAM)でSSO実装する時に必要な設定**
https://qiita.com/shinyama/items/7877bc2240e27c7e0723
OpsWorks (Chef 11.10) 内のカスタムレシピでaws-sdk-v2を使う方法

# 背景

OpsWorks (Chef 11.10) でカスタムレシピを利用しようとすると、aws-sdkのバージョンがv1のため、最近のサービスをAPIから利用できませんでした。
以下、v2を利用するための手順です。

# 手順

## aws-sdk-v2をgem install

具体的には以下のカスタムレシピをまず実行しときます。

```install_aws_sdk_v2.rb
chef_gem "aws-sdk" do
  version "2.10.55"
  action :install
end
```

# 利用するときにaws-sdk-v2をrequire

`aws-sdk` で require してしまうと、v1が読み込まれてしまいます。
v2を利用するためには、 `aws-sdk-resources` を指定すれば良いです。
以下はv1では利用できなかったALB連携の例。

```
require 'aws-sdk-resources'

region = node["opsworks"]["instance"]["region"]
ec2_instance_id = node["opsworks"]["instance"]["aws_instance_id"]

client = ::Aws::ElasticLoadBalancingV2::Client.new(region: region)

target_to_attach = {
  target_group_arn: "xxxx",
  targets: [{ id: ec2_instance_id }]
}

client.register_targets(target_to_attach)
```

これでv2を利用できました。
libmemcached-1.0.16にはsession.lazy_writeのバグがあるようだ

# libmemcached-1.0.16にはsession.lazy_writeのバグ

## 現象
- sessionの書き込みに5秒近くかかる

## 原因
- php7はsession.lazy_writeがデフォルトでON
- session.lazy_writeをOFFにすると大丈夫

## 結論
- libmemcached-1.0.16は使用せず、最新にしましょう。

## 参考
https://github.com/php-memcached-dev/php-memcached/issues/310
ImageMagick > 画像をずらす (+ 画像サイズを拡大)  > convert green.png -page +0+20 -background none -extent 40x40 -flatten green_shift.png

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
gcc version 4.4.7 (とgfortran)
NCAR Command Language Version 6.3.0
WRF v3.7.1を使用。
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
```

### 参考

http://www.imagemagick.org/discourse-server/viewtopic.php?t=20823

### 実行例

サンプル画像を作成。

```
$ convert -size 20x20 xc:green green.png
```

下に20ピクセルずらす (画像サイズを40x40に拡大)

```
$ convert green.png -page +0+20 -background none -extent 40x40 -flatten green_shift.png
```

右に20ピクセルずらす (画像サイズを40x40に拡大)

```
$ convert green.png -page +20+0 -background none -extent 40x40 -flatten green_shift.png
```
sshの鍵認証でパスワード無しでログインする・ssh-copy-id

毎回調べてるのでメモ。

# やりたいこと
* ssh で入るときに鍵を使いたい
* ユーザー名を毎回入力せず済むようにする
* パスフレーズを毎回入力せずに済むようにする

# 手順
## クライアント側で鍵作成
```shell-session
$ cd ~/.ssh
$ ssh-keygen -t rsa -f id_rsa_hoge
```
`id_rsa_hoge`は適当につける。
パスフレーズは何も入力せず、enterを押す。

パーミッションは以下を設定しておくこと。

```shell-session
$ chmod 600 ~/.ssh/id_rsa_hoge
$ chmod 700 ~/.ssh
```

## サーバーに鍵転送・設定
### ssh-copy-idを使ったかんたんなやり方
`ssh-copy-id` コマンドを使うことで、一行で転送・設定が行える。

```shell-session
$ cd ~/.ssh
$ ssh-copy-id -i id_rsa.hoge {user}@{host}
```

### ちょっと面倒なやり方
クライアント側から公開鍵をscpする。

```shell-session
$ cd ~/.ssh
$ scp id_rsa_hoge.pub {user}@{host}:~/.ssh/
```
サーバーに.sshディレクトリがなければ作る。 `chmod 700 ~/.ssh`しておくこと。

サーバー側で以下の設定をする。

```shell-session
$ cd ~/.ssh
$ cat id_rsa_hoge.pub >> authorized_keys
$ chmod 600 authorized_keys
$ rm -fv id_rsa_hoge.pub
```
パーミッションをちゃんと設定しないとつながらないので注意。

## クライアント側の設定
`~/.ssh/config`を以下のように編集しておく。

```
Host {host}
  HostName {hostname}
  User {user}
  IdentityFile ~/.ssh/id_rsa_hoge
```
パーミッションも設定する

```shell-session
$ chmod 600 ~/.ssh/id_rsa_hoge
```
クライアント側からは`ssh {host}`ってやるだけでssh接続ができるようになる

# 参考URL
[SSHの鍵認証設定 - Qiita](https://qiita.com/gotohiro55/items/36a22516de2b381b3c6e)
[ssh-copy-idで公開鍵を渡す - Qiita](https://qiita.com/kentarosasaki/items/aa319e735a0b9660f1f0)
[SSHで鍵認証を用いて、パスワードなしでログインする方法](https://hack-le.com/20462465-2/)
ImageMagick > 画像をアスペクト比を保たずに任意のサイズに変換する > mogrify green.png -resize 100x20! green_exp.png 

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
gcc version 4.4.7 (とgfortran)
NCAR Command Language Version 6.3.0
WRF v3.7.1を使用。
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
```

### 希望

20x20のサイズの画像を100x20のサイズに伸ばす。

### 方法

参考: https://stackoverflow.com/questions/20438898/resize-image-with-mogrify-without-keeping-aspect-ratio

mogrifyというコマンドがImageMagickにはあるようだ。

```
mogrify input.png -resize 256x256! output.png
```

サイズの後ろに「!」をつけることで、アスペクト比を保たずに変換ができるようだ。

### 試してみた

サンプル画像を作成

```
$convert -size 20x20 xc:green green.png
```

コマンドを実行
(ただし、出力ファイルがすでにないとエラーになる。コピーしてから実行？)

```
$mogrify green.png -resize 100x20! green_exp.png 
```

横方向に伸びた画像が生成された。


### サイズ確認

```
$ identify green.png 
green.png PNG 20x20 20x20+0+0 8-bit PseudoClass 1c 203B 0.000u 0:00.000
```

```
$ identify green_exp.png 
green_exp.png PNG 100x20 100x20+0+0 8-bit PseudoClass 1c 204B 0.000u 0:00.000
```

関連: [ImageMagick > 画像ファイルの情報を見る > identify test.bmp](https://qiita.com/7of9/items/19d34b9cf185c2362a41)

コマンド名identifyを忘れてしまう。

### 関連

[jsFiddle + Google Maps > 指定の緯度経度範囲(四角)をマーキングで表示 v0.1](https://qiita.com/7of9/items/86657cf16b1905f13664)
laravel で認証でリダイレクトした際に、認証後に元のページに戻す

laravel 5.4

middleware で auth を指定しているページにアクセスした際に、認証前だとリダイレクトがかかります。
その後に認証をしたら、もともと閲覧したかったページにリダイレクトするようにします。

### 認証にはじかれた際にリダイレクトする箇所で、閲覧したかったページをsessionに保存します

```php:/app/Exceptions/Handler.php
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }
        return redirect()->guest(route('login'))->with('path', $request->path());
    }
```

path というセッション名にパスを保存します。


### 認証画面のフォームで path を hidden で引き継ぎます
```html:
<input type="hidden" name="path" value="{{ session('path') }}" />
```


### ログイン処理のコントローラー内で、 path があればパスに飛ばす処理を追加
元のページに飛ばすことが出来ます。
Ruby on RailsでMySQLを使おうと思ったらエラー発生！

# 現象
Railsで新規プロジェクトを作成するときに、DBをMySQL指定したところエラーが発生した。

``` :実行コマンド
rails new schedule -d mysql
```

エラーはこんな感じ
>2 warnings generated.
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

>Gem files will remain installed in /var/folders/31/rzft9l6s2cv9v44kjfsbslzm0000gn/T/bundler20171004-27749-ft0ms1/mysql2-0.4.9/gems/m
ysql2-0.4.9 for inspection.
Results logged to /var/folders/31/rzft9l6s2cv9v44kjfsbslzm0000gn/T/bundler20171004-27749-ft0ms1/mysql2-0.4.9/gems/mysql2-0.4.9/ext/m
ysql2/gem_make.out
An error occurred while installing mysql2 (0.4.9), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.4.9'` succeeds before bundling.


gemでmysql2をインストールすればいいの？と思い、インストールしたがまだ同じエラーが出てくる。おいおいおい・・・（天の声：もっとちゃんとエラー文読みな？）

ライブラリが見つからないエラーが出てるので多分ここが原因
> ld: library not found for -lssl

調べて見ると、同じようなエラーになったという記事を見つけた。
>[macOS Sierra で mysql2 の bundle install に失敗する場合](http://nekonenene.hatenablog.com/entry/2016/10/31/061350)

解決方法はいくつかあるようだが、Xcode Command Line Toolsの最新版であれば問題ないようなので今回はxcode-selectをインストールします。

インストール後に再度Railsの新規プロジェクトを作成すると見事作成に成功しました！

#### 環境
---
MacBook Pro
macOX Sierra 10.12.6
Rails 3.2.21
MySQL 5.7.18
Spyderで2度めのPyQtが実行出来ない

`It seems the kernel died unexpectedly. Use 'Restart kernel' to continue using this console.`

と出力され続ける。
新しいpython consoleを開かないと再実行できない。

# <i class="fa fa-cogs"></i> 検証環境

* Python 2.7 (WinPython-32bit-2.7.10.3)
* Spyder 3.0.0 (同梱)
* PyQt4
* Windows7


```py
import sys
import PyQt4

app = PyQt4.QtGui.QApplication(sys.argv)
mw = PyQt4.QtGui.QMainWindow()
button = PyQt4.QtGui.QPushButton('Hello World')
mw.setCentralWidget(button)
mw.show()
app.exec_()
```

# 対処

```py
import sys
import PyQt4

app = PyQt4.QtGui.QApplication(sys.argv)
mw = PyQt4.QtGui.QMainWindow()
button = PyQt4.QtGui.QPushButton('Hello World')
mw.setCentralWidget(button)
mw.show()
# 追加
app.aboutToQuit.connect(app.deleteLater)
app.exec_()
```

終了時に接続を開放するということかな？
参考ではインスタンスの使い回しを示唆するコードがあったが、現状これで動いているので様子見。

# 参考

* [pyqt - Spyder + Python 3.5 - how to debug kernel died, restarting? - Stack Overflow]
* [Python Kernel crashes after closing an PyQt4 Gui Application - Stack Overflow]

***

* [jupyter や Spyder IDE などでPyQt 系をやっていると、kernel restarting が頻繁に起きる問題の解決法 - Qiita]

[jupyter や Spyder IDE などでPyQt 系をやっていると、kernel restarting が頻繁に起きる問題の解決法 - Qiita]:https://qiita.com/mmsstt/items/ef68e1a65f9d4f66f64f


[pyqt - Spyder + Python 3.5 - how to debug kernel died, restarting? - Stack Overflow]:https://stackoverflow.com/questions/43328064/spyder-python-3-5-how-to-debug-kernel-died-restarting

[Python Kernel crashes after closing an PyQt4 Gui Application - Stack Overflow]:https://stackoverflow.com/questions/24041259/python-kernel-crashes-after-closing-an-pyqt4-gui-application
Cognos Analytics 11.0.7 on AIXでのサンプルのセットアップ

#内容
Cognos Analytics 11.0.7のAIX版では、インストールモジュールが2GBを超えてしまい、AIXの制限により、インストールモジュール中に以下のサンプルを含めて無いようです。

\<cognos_analytics_server_install_location>/samplesディレクトリ
\<cognos_analytics_server_install_location>/deployment/Samples_for_Install.zip ファイル

この様に、AIX版のインストーラーでは、サンプルのチェックボックスが無いようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/e4fbe817-7af6-8df3-b8a5-9816479b7331.png)

では、どうしたら良いかというと、以下の対応になります。

方法1.
WindowsやLinuxで導入したCognos Analytics環境からコピーしてくる。

方法2.
以下のリンクからダウンロードしてくる。
ftp://public.dhe.ibm.com/software/data/sw-library/cognos/mobile/AIX/samples.zip

#参考
**Samples for IBM #Cognos Analytics 11.0.7 on AIX**
https://www.ibm.com/communities/analytics/cognos-analytics-blog/samples-for-ibm-cognos-analytics-11-0-7-on-aix/
jsFiddle + Google Maps > 指定の緯度経度範囲(四角)をマーキングで表示 v0.1

Google Mapsから指定の緯度経度範囲をマーカー表示するツール。
便利なツールでしたが、2017年10月4日に確認したところ、リンク切れ状態でした。

[[廃版] onlineTool > 緯度経度からgoogleマップへマーカー表示](https://qiita.com/7of9/items/113860b302b4f684b490)

## v0.1

### ないなら作る(ありあわせのものから)

Google MapのAPIキーをとろうとしたら、「処理中」のまま進まない。
他の方法を検討した。

そういえば、**今話題**のズンドコキヨシで冗談で実装したコードがあったような。

[ズンドコキヨシ with Google Map API on jsFiddle](https://qiita.com/7of9/items/04cd12dab9883c9f5a35)

上記をベースに変更したのが以下。

https://jsfiddle.net/1q16ysrx/5/

### 設定項目

以下の設定を「度」の単位で行う。

```
// TODO: define the center
var vcenter = 35.0;
var hcenter = 135.0;
var latspan = 10.0;
var lonspan = 10.0;
```

### 動作環境

地図の(見える|見えない)は以下で異なる

- `MacOS X 10.8.5 + Chrome`では地図が見えず
- `MacOS X 10.8.5 + Safari`なら地図が見えた
- `Windows 8.1 pro(64bit) + Chrome`でも地図が見えない
- `Windows 8.1 pro(64bit) + IE`で「セキュリティで保護されているコンテンツのみ表示しています。全てのコンテンツを表示しますか」で「はい」にしたら地図が見えた
- Windows 10 Pro (64bit) + IEで「セキュリティで保護されているコンテンツのみ表示しています。全てのコンテンツを表示しますか」で「はい」にしたら地図が見える
- Windows 10 Pro (64bit) + Edge: 未対応 (固まる)

(追記: 2018/07/03)

- `Windows 8.1 pro(64bit) + IE`でも地図が見えない
    - 関連: [jsFiddle + Google Maps > 動作状況 (2018-07-03) > Ubuntu + FireFox Quantumで動作](https://qiita.com/7of9/items/a48a546894ae583e0abc)

### 例

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/d353d9b4-18a0-68ac-5674-f594f638a400.png)

### 備考

指定の範囲を切り出す場合、下のマーカーは邪魔かもしれない。

- 右下のマーカーを消す
- 左下のマーカーを左に移動

上記を行えば、gimpなどで四角を切り取り可能だろう。
ASTERIA ビッグデータを扱うには

# ASTERIAはJOINが苦手

DBから抽出するRDBGetでは, 20万レコードを取り出したとき, 動かなくなくりました.
また, 5万レコードと1万レコードをJOINしたとき,
JOINは出来たのですが, 処理時間が遅すぎて使い物になりませんでした.

結論, ASTERIAはビッグデータの操作が苦手.

# 対処方法 DBサーバに処理をさせ,ASTERIA側はプロシージャの結果を受け取る

MySQLでは, 
viewではユーザ変数が使えないので,
行番号はtemporary tableで作成する.

temporary tableは自己結合が出来ないので,
サブクエリに関してもtemporary tableを作成する.

それをストアプロシージャで一つの処理とする.

## 実際に作ってみた.

```SQL:getLastRow()
delimiter //  
create procedure getLastRows() 
BEGIN
-- メイン句
SET @i=0;
drop table if exists addRowNo;
create temporary table addRowNo 
 -- インデックスを貼ると高速化
(
  `行番号` int(11),
  primary key(`行番号`)
) 
AS
SELECT
  cast(@i:=@i+1 as SIGNED) AS '行番号',
  稟議番号,
  稟議ステータス,   
  稟議承認者名
FROM
  DUMMY_TABLE

-- SubQuery(Temporary は自己結合できないので)
 SET @j=0;  -- 変数名を変える
 drop table if exists getKeys;
 create temporary table getKeys
 (
  `行番号` int(11),
  primary key(`行番号`)
) 
AS
SELECT
  max(cast(@j:=@j+1 as SIGNED)) AS '行番号',
  稟議番号
FROM
  DUMMY_TABLE
GROUP BY 稟議番号;

-- 最終行を取得するクエリ
SELECT MAIN.* 
FROM addRowNo MAIN
LEFT getKeys SUB
on  MAIN.行番号 = SUB.行番号
WHERE SUB.行番号 is not null;

END //
delimiter ;

```


これを

```SQL:SQLCall1
call getLastRows() 

```
で呼び出すことが出来る


参照(以前の記事をもとにしています])
[ASTERIA WARPでキーごとの最終行(=履歴の最新行)を取得するには](https://qiita.com/nacopon/items/2c225030894e5ef24f6a)
linuxに、root userでも使えるpyenv環境の構築


ブログにも記事を写しました。[linuxに、root userでも使えるpyenv環境の構築](http://u-kan.hatenadiary.jp//entry/linux-pyenv)

ほとんど[PyenvによるPython3.x環境構築(CentOS, Ubuntu)](https://qiita.com/akito1986/items/be5dcd1a502aaf22010b)のモノマネですので、環境構築をしたい人は上記を参考にしてください。メモです。

## 背景

1. ansibleをpipでインストールしようとする
1. pyenvで管理されてるpythonとシステム pre-install pythonが呼ばれたり呼ばれなかったりでうまくいかない。
2. 全部pyenvでインストールしてるものを使ってしまいたい。

## やったこと

ec2上にpythonのインストール。systemにもともとインストールされているpythonに何もかも突っ込んで言って辛い思いをした過去があるので、できればバージョン切り替え用のパッケージをかませたい。

結果pyenvを導入した。多くのプロジェクトが同一サーバー化で動くことは想定していないので、仮想環境構築はしない。（virtualenv等）

## やらなかったこと

virtualenv/pyenvなど仮想環境構築ツールの導入。

## コード

#### pyenvインストール

[PyenvによるPython3.x環境構築(CentOS, Ubuntu)](https://qiita.com/akito1986/items/be5dcd1a502aaf22010b)にある通りです。下記コマンドで起動スクリプトを作成。

```/etc/profile.d/pyenv.sh
export PYENV_ROOT="/home/ec2-user/.pyenv"
export PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${PATH}"
```

この後に設定を反映させるために下記コマンドを実行。

```
source /etc/profile.d/pyenv.sh
```

ログインし直した時も、この設定は反映されるようなので、一度実行すればきにする必要はなさそうです。

豆知識程度に補足をすると、```/etc/profile.d```にはアプリケーション毎の設定を記述していくそうです。ここに設定を書いておくと、ログインユーザに関係なく起動時に読み込んでくれます。（下記手順）

1. ```/etc/profile```を実行
1. ```/etc/profile```によって、```/etc/profile.d```ディレクトリ配下のすべてのファイルを実行
1. ログインユーザーのホームディレクトリにある```~/.bash_profile```を実行
1. ```~/.bash_profile```によって、```~/.bashrc```を実行
1. ```~/.bashrc```によって、```/etc/bashrc```を実行



#### sudoでもuserのパス設定を引き継げるように設定

あとは、ログインユーザから```sudo```で実行した時に、path情報とかを引き継げるように設定をする。

これをやらないと、なんかしらのscripthがpythonコマンドを叩こうとした時に、pyenvが呼ばれないことがある。```visudo```を利用して設定ファイルを書き換える。

```
$ visudo 

~~~  編集モードに入るので、下記のように変更  ~~~

# Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin  コメントアウト
Defaults    env_keep += "PATH"  # 追加
Defaults    env_keep += "PYENV_ROOT"  # 追加
```
Project Euler Q11 【格子内の最大の積】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
下の $20×20$ の格子のうち, 斜めに並んだ4つの数字が赤くマークされている.

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 <font color="Red">26</font> 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 <font color="Red">63</font> 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 <font color="Red">78</font> 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 <font color="Red">14</font> 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

それらの数字の積は $26 × 63 × 78 × 14 = 1788696$ となる.

上の $20×20$ の格子のうち, 上下左右斜めのいずれかの方向で連続する4つの数字の積のうち最大のものはいくつか?

## 解答

```bash
time cat problem11.txt |
awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}} END{for(i=4;i<=NF;i++){for(j=1;j<=i;j++){printf a[i-j+1,j]" "};print ""};for(i=2;i<=NF-3;i++){for(j=1;j<=NF-i+1;j++){printf a[NF-j+1,i+j-1]" "};print ""};for(i=1;i<=NF-3;i++){for(j=1;j<=NF-i+1;j++){printf a[j,i+j-1]" "};print ""};for(i=2;i<=NF-3;i++){for(j=1;j<=NF-i+1;j++){printf a[i+j-1,j]" "};print ""};for(i=1;i<=NF;i++){for(j=1;j<=NF;j++){printf a[j,i]" "};print ""}}' |
cat - problem11.txt |
awk '{for(i=1;i<=NF-3;i++){print $i*$(i+1)*$(i+2)*$(i+3)}}' |
sort -k1,1nr |
head -1
70600674

real    0m0.016s
user    0m0.015s
sys     0m0.007s
```

少し強引だがワンライナーでできた。
最初のめっちゃ長い`awk`で斜めと縦を抽出、横はただ結合すればいいだけなので`cat`で結合する。


## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/011.html
Ruby で遅延 Proc 呼び出し

TracePointネタです

こんな感じでコードを書くと

```rb:defer.rb
$proc_stack = Hash.new { |h, k| h[k] = [] }

TracePoint.trace(:return) do |tp|
  next if tp.method_id == :defer

  key = "#{tp.defined_class}::#{tp.method_id}"

  while block = $proc_stack[key].pop
    block.call
  end
end

module Kernel
  def defer(&block)
    b = caller_locations[0]
    key = "#{self.class}::#{b.base_label}"
    $proc_stack[key] << block
  end
end
```

これが

```rb
def hello
  defer { puts "world" }
  defer { puts "second" }

  puts "hello"
end

hello
```

こんな感じに

```console
$ ruby defer.rb 
hello
second
world
```


これが

```rb
def count
  puts "counting"

  1.upto(10) do |i|
    defer { puts i }
  end

  puts "done"
end

count
```

こんな感じになります。

```console
$ ruby defer.rb 
counting
done
10
9
8
7
6
5
4
3
2
1
```

こんな感じで `defer` で登録した Proc オブジェクトがそのメソッドの終わりに呼び出されるようになります。元ネタとしては golang の [Defer](https://tour.golang.org/flowcontrol/12) を見て Ruby でも出来そうだなと思ったのがきっかけです。（正しく実装できているかは怪しいですが、ネタなのでその辺りはあまり気にしない方向で）


## 仕組み

実装としては、まず `defer` 呼び出し時に `caller_locations` を呼び出して、`defer` の呼び出し元を調べます。その後、`どこから呼び出されたのか` を key にして `$proc_stack` に渡された Proc オブジェクトを登録しておきます。

そしてメソッドの終了時に TracePoint の `return` イベントが発生するので `どのメソッドが終了したのか` を調べ、 `$proc_stack` に登録されている Proc オブジェクトがなくなるまでスタックから取り出して call しています。
Azure SQL DatabaseとPHPの注意点

# 接続オプション
SQL周りで誤ったコードを書いたら以下のワーニングが出た。

```:Console
Warning: Uncaught exception 'PDOException' with message 'SQLSTATE[IMSSP]: This function is not implemented by this driver.' 
```

SQL Database が PDO::ERRMODE_EXCEPTIONに非対応とのこと。
接続オプションを変更したら出なくなった。

```:PHP
   //Azure SQL Database が PDO::ERRMODE_EXCEPTION 非対応のためコメントアウト
   //$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
```
数学-三角関数-正弦定理の証明

# 正弦定理の証明

※[円周角の定理（同じ弧に対する円周角は同じ角度になる）](4cbb3a4b1244d13c60a8)

[戻る](12efd87e80b55fc0835f)

## 角Ａが鋭角の場合

- 辺ＢＣが中心Ｏに対して点Ａと反対側にある場合。

![basic-proof-of-law-of-sines-01.png](https://qiita-image-store.s3.amazonaws.com/0/4641/5fa3a707-4237-cfda-4862-6c5859113884.png)

```math
\\
\begin{array}{l}
半径Ｒとする円に内接する三角形ＡＢＣがあるとする。\\
点Ｂから中心Ｏを通る線を引き、円との交点をＤとする。\\
円周角の定理より \angle A = \angle D \\
\\
ＢＤは直径（２Ｒ）であり、\angle C = \frac{\pi}{2} となり三角形ＢＣＤは直角三角形となる。\\
\sin D = \sin A = \frac{BC}{BD} = \frac{a}{2R} (\angle A の対辺BCを a とする) \\
\therefore \sin A = \frac{a}{2R}　=>　\frac{a}{\sin A} = 2R \\
\\
\angle B, \angle C も同様なので \frac{a}{\sin A} = \frac{b}{\sin B} = \frac{c}{\sin C} = 2R \\
\end{array}
\\
```

[上へ](#正弦定理の証明)


## 角Ａが直角の場合

- 辺ＢＣが中心Ｏ上にある場合。

![basic-proof-of-law-of-sines-02.png](https://qiita-image-store.s3.amazonaws.com/0/4641/6e830008-1034-e8a8-945b-12441be787a9.png)

```math
\\
\begin{array}{l}
半径Ｒとする円に内接する三角形ＡＢＣがあるとする。\\
辺ＢＣは直径（２Ｒ）となるので、a = 2R (\angle A の対辺BCを a とする) \\
\sin A = \sin \frac{\pi}{2} = 1 \\
\therefore \frac{a}{\sin A} = 2R \\
\\
\angle B, \angle C も同様なので \frac{a}{\sin A} = \frac{b}{\sin B} = \frac{c}{\sin C} = 2R \\
\end{array}
```

[上へ](#正弦定理の証明)


## 角Ａが鈍角の場合

- 辺ＢＣが中心Ｏに対して点Ａと同じ側にある場合。

![basic-proof-of-law-of-sines-03.png](https://qiita-image-store.s3.amazonaws.com/0/4641/7ecb8d8b-3272-96e3-4588-70de03880aeb.png)

```math
\\
\begin{array}{l}
半径Ｒとする円に内接する三角形ＡＢＣがあるとする。\\
点Ｂから中心Ｏを通る線を引き、円との交点をＤとする。\\
四角形ＡＢＣＤは円に内接するので \angle D = \pi - \angle A \\
\\
ＢＤは直径（２Ｒ）であり、\angle C = \frac{\pi}{2} となり三角形ＢＣＤは直角三角形となる。\\
\sin D = \sin (\pi - \angle A) = \sin A \\
\sin D = \frac{BC}{BD} = \frac{BC}{2R} = \frac{a}{2R} (\angle A の対辺BCを a とする) \\
\therefore \sin A = \frac{a}{2R}　=>　\frac{a}{\sin A} = 2R \\
\\
\angle B, \angle C も同様なので \frac{a}{\sin A} = \frac{b}{\sin B} = \frac{c}{\sin C} = 2R \\
\end{array}
```

[上へ](#正弦定理の証明)
VSCodeの効率的な学び方

先日、[VSCodeに移行すべき5つの理由](https://qiita.com/szk3/items/43aeb8963f01abbd9ccc)という記事を書きました。

この記事はそのフォローになります。

VSCode入門者や初心者、またVSCodeについて使い方を聞ける人が周りにいない方が**最短で使い方をマスターするための手順**をまとめました。

# TL;DR
下記の順番で**基礎から固めていく**のが、結果的に最も効率的:writing_hand:だと思います。

**VSCodeの基本概念や操作方法の取得はそれほど難しくない**ので、きっと**2-3日もかからずに必要十分に使いこなせるようになる**と思います。

1. 公式サイトの動画を見る
2. Tips集で俯瞰する
3. ショートカットをひたすら覚える
4. 実際に手を動かす（**一番大事**）

# :writing_hand:公式サイトの動画を見る

Webを検索すれば、VSCodeの使い方はたくさん出て来ますが、どうしても断片的になりがちです。

なので、最初は迷わず**公式サイトのドキュメントを確認**するのがいいでしょう。

公式ドキュメントを初めに抑える効能は、**大枠としての全体像や用語を効率よく抑えられる**ことにあります。

そして、VSCodeのインストールが終ったら、**公式サイトの導入ビデオ**を一通り見ましょう。

:tv:導入ビデオ
https://code.visualstudio.com/docs/getstarted/introvideos

最初の取っ掛かりなので、ドキュメントを読むより**動画で見たほうが手っ取り早いし、鮮明なイメージを簡単に持つことができる**と思います。

全部見てもたかだか**39分程度**:stopwatch:なので、ランチの間にでも見てしまいましょう。今後発生しうる調査コストを考えれば、最初に全体像を抑えておくと効果的です。

できれば、一緒に手を動かしておくとなおベターだと思います。


## :writing_hand:Tips集で俯瞰する
Tips集は2つあります。やや差異がありますが、内容はほとんど同じです。

どっちを見ても基本的なことは抑えていますので、お好みで確認してください。

迷っている方は、公式ドキュメントにあるTips集のほうが個人的には若干リッチだと思うのでそちらをオススメします。

1. [公式ドキュメント](https://code.visualstudio.com/docs/getstarted/tips-and-tricks)
2. [Githubリポジトリ](https://github.com/Microsoft/vscode-tips-and-tricks)

量的にはそこそこありますが、基本機能ごとにGifアニメで動きが確認できるようになっているので、**俯瞰や復習用資料として最適**です。

一通り全部目を通したほうがベターですが、目次から気になるコンテンツを確認するだけでも良いでしょう。

# :writing_hand:ショートカットを覚えよう

初めに覚えるべきショートカットは、「**キーボードショートカットを開く**」です。
Macだと「⌘K ⌘S」、Windows/Linuxだと「Ctrl+K Ctrl+S」になります。

このショートカットさえ覚えておけば、**目的のショートカットを忘れてしまった際もすぐに確認することができます**し、ショートカット一覧を機能一覧として見立てて俯瞰することもできます。

何か操作に困ったら、ショートカット一覧を開くクセを付けておき、自分に必要なショートカットを探して覚えましょう。

あたりまえですが、**ショートカットの効能で操作が劇的に早くなります**。

どんなショートカットを覚えればいいのか検討がつかないという方は、以下チートシートから**General → Display → File Managementの順**に覚えて行って、後は自分の好みで覚えていくと良いと思います。

Mac
https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf
Linux
https://code.visualstudio.com/shortcuts/keyboard-shortcuts-linux.pdf
Windows
https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf

# :writing_hand:実際に手を動かす

**一番書くことがないのですが、一番大切なパート**です。

座学は手を動かす前の下準備にしかすぎません、学習内容の定着には実践あるのみです。

**手を動かして、知識を経験に落とし込みましょう。**

ショートカットは脊髄反射で反応できるくらい繰り返し練習するといいと思いますが、仮に忘れたとしても「キーボードショートカットを開く」で簡単に確認できるので、**自分で確認できる状態になっていればOK**です。

# まとめ

以上、自分が**VSCodeの触り始めに知りたかったこと**をまとめました。

自分の場合、一番初めに機能把握を目的として全ショートカットに目を通しました。ですが、慣れない用語と操作イメージの紐付けが難しいことが多々あり、もっと基礎的な知識を初めに入れておけば良かったと反省しました。

他にも細かい反省はありますが、**それら反省点を踏まえ上記のような至ってベーシックな学習手順が良い**と考えています。

基本的なことさえ覚えてしまえば、後は自身の開発スタイルに合わせた拡張機能をインストールしては、それらのショートカットを覚えるということを繰り返すだけで、**簡単に開発効率が上がっていく**と思います。

この記事が、VSCode学習者のお役に立てれば幸いです。

## おまけ
余裕があれば、FAQも読んでおくと理解が深まると思います。
https://code.visualstudio.com/docs/supporting/faq

また「awesome-vscode」も良い資料なのでオススメです。
https://github.com/viatsko/awesome-vscode
【mac】VPN設定せずにVPNしたかのようにする

# 【mac】VPN設定せずにVPNしたかのようにする

![vpn-3-433x300.jpg](https://qiita-image-store.s3.amazonaws.com/0/62822/effac090-0d5e-6f61-76a9-51ea42cd3318.jpeg)

## この記事でできるようになること
- まるでVPNのしているかのように、特定LAN内のブラウジングが可能になります。
- 例えば、学内のみしかアクセスできないページを閲覧する（履修登録とか！！）

## 条件
- 特定LAN内のサーバーにSSHできる必要があります。

## 概念
- Dynamic Forward＋SOCKS プロキシを使います。

![dynamicportforwarding.jpg](https://qiita-image-store.s3.amazonaws.com/0/62822/710badaf-6bbd-9715-7d4b-1e98f5e267f5.jpeg)

## 設定方法
### sshの確認
- まず、ターゲットとするLAN内のサーバーにSSHできるか試し `.ssh/config` を作成します
- そしてDynamicForwardの設定を追記します

```~/.ssh/config
Host terget-lan
  HostName aaa.bbb.com
  IdentityFile id_rrrssssaaa
  User oreoreoreore
  DynamicForward {任意のポート番号 100080など}　#<- この設定を追加

```
  
### ネットワークの追加
- 🍎のシステム環境設定から「ネットワークの設定」を選びます。
- edit locationsを押します
- 適当にvpn-testとしました
- **ネットワークを追加しておけば、設定をミスってもその設定ごとやり直せるのでおすすめです。**

<img width="667" alt="Screen Shot 2017-10-03 at 8.24.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/5271f3db-4b0d-bc66-fb00-d58d35be8bf6.png">

### Advanced(詳細設定)
- そのまま、Advanced(詳細設定)を押します
- SOCKS Proxyにチェックを入れます
- SOCKS Proxy Serverに `localhost` : `{任意のポート番号}`　を入力します

<img width="665" alt="Screen Shot 2017-10-03 at 8.29.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/c6cd451d-8e39-9938-d088-e522acb0389a.png">

### 適用する
- okを押して詳細設定を抜けます。
- この時、ネットワークがvpn-testが選択されていることを確認して適用を押しましょう。

<img width="669" alt="Screen Shot 2017-10-03 at 8.31.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/394d7ce4-c67e-6c4f-3b30-f8abaa1266fe.png">

### sshしてみる
- `ssh terget-lan` として特定LAN内しかアクセスできないページにアクセスしてみましょう！！

## 注意点
- ssh先のサーバーを通してすべて通信するようになるので、sshが切れるとどこにもアクセスできなくなります。焦らずsshし直すか、locationを自動に変更しましょう(´・ω・`)

## locationの切り替え
- 🍎のlocationのところからすぐに切り替えれるようなボタンが出現しているので、そちらを使うと便利です。

<img width="450" alt="Screen Shot 2017-10-03 at 8.44.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/62822/0b03d078-fcd2-e78f-808a-03c5f5bc2cf0.png">


## まとめ
- VPN申請はめんどくさいです。
- これ以外と役に立ちますのでおすすめです
iOSアプリの起動時間を2.3秒短縮した話

昨日Mediumで[CarthageでStatic FrameworkとしてビルドしてiOSアプリの起動時間を短縮する](https://medium.com/@r.izumita/ca10a0a29381)という記事を書きました。この記事ではサンプルプロジェクトでの起動時間の計測だったのですが、今度は実際に私が仕事で作成しているアプリの起動時間を短縮してみようと思います。

## まずは計測

以前から社長に起動時間を短縮して欲しいといわれてまして、まぁ遅いわけです。その起動時間を確認してみます。実行環境は記事と同じくiPhone 6 / iOS 11.0です。

```
Total pre-main time: 4.5 seconds (100.0%)
         dylib loading time: 1.9 seconds (41.7%)
        rebase/binding time: 200.17 milliseconds (4.3%)
            ObjC setup time: 557.89 milliseconds (12.1%)
           initializer time: 1.9 seconds (41.7%)
```

記事ではmillisecondsという単位でしたが、アプリではsecondsの単位。4.5秒、これでは起動時間短縮を指示されるわけです。

## どのライブラリをStaticフレームワークにするか

早速Staticフレームワークにしていきましょう。といっても言語や画像などのリソースを持つフレームワークはStaticフレームワークにしにくかったりできなかったりするので、一つ一つ選別しなければいけません。

Cartfileで指定しているフレームワークを一つ一つ確認して23個Staticフレームワークにできそうです。

## Staticフレームワークに再ビルドする

ld.pyスクリプトとCarthageでStaticビルドするスクリプトを設置して再ビルドコマンドを実行しました。

一つビルドが失敗するフレームワークがあったのでそれはDynamicのままにしておきました。それ以外すべてStaticでビルドして実行してみると…アプリのビルドに失敗。

`failed to import bridging header '/Path/to/Hoge-Bridging-Header.h'`になってしまいました。これはもしかしたら一つずつ再ビルドしてその度にアプリも実行してみる必要があるのでは…と思い、しかたないので初めに戻って一つずつ再ビルドすることにしました。しかし初期の状態でアプリをビルドしても同じエラーが。Cleanしてみるとエラーが消えました。どうやらStaciフレームワーク化をするとこのエラーが発生し、クリーンにより解決するようでした。

また、RealmやSDWebImageなどがStaticフレームワークとしてビルドしたにも関わらずDynamicフレームワークのままでした。

## 再計測

お楽しみの再計測です……………

```
Total pre-main time: 2.2 seconds (100.0%)
         dylib loading time: 1.4 seconds (63.0%)
        rebase/binding time: 153.40 milliseconds (6.7%)
            ObjC setup time: 129.07 milliseconds (5.6%)
           initializer time: 560.55 milliseconds (24.5%)
```

なんと4.5秒が2.2秒まで短縮されました。その差2.3秒

ただし実際のアプリの起動はもう少しかかります。ストップウォッチで計測すると、Dynamicフレームワークでは約5秒、Staticフレームワークでは4秒台後半でした。ほぼ誤差。これは骨折り損だったのか…

ふと、2回目以降の起動だったのでキャッシュされて起動が速くなっているのではないかと思いつき、iPhoneを再起動してから計測し直しました。すると初回起動においてDynamicでは約12秒、Staticでは約9.5秒という結果に。これはStatic化して高速化された秒数と近いことが分かります。ということは、キャッシュされていない状態での実際の起動でも順当な高速化がされたという結果が得られたことになります。つまり初回起動やキャッシュがない状態では確実に速くなると思われます。

以上のように、CarthageでStaticフレームワークとしてビルドすることでiOSアプリの起動の短縮が可能だということが分かりました。具体的な作業手順は[CarthageでStatic FrameworkとしてビルドしてiOSアプリの起動時間を短縮する](https://medium.com/@r.izumita/ca10a0a29381)に記述してありますので、参考にしてみてください。
Slack、チャンネル内のメッセージの一括削除…

このやり方ができなくなっていた＞＜
Slackのメッセージを一括削除
https://qiita.com/nightyknite/items/9e350ca8b2ece3e84972
https://チーム名.slack.com/archivesってアクセスできない...

よくわかってなかったが
メッセージ数とストレージ容量は別カウントぽい。
RSS取得のせいでメッセージ数が上限10000？に近づいていたのだ。
やられた気分…
~~(sendだから送信数でみてて、消しても意味ないのかも！このチャンネル止めないとダメかも？)~~

先にわかったことをまとめると。
>・POST内容をメッセージと呼称
・トータル・メッセージは10000件を超えるとアーカイブに入り、検索はできなくなる。
・メッセージの削除は公式にはできない。チャンネルの削除はできる。
・チャンネルを残してのメッセージ削除は、api経由でやる。https://github.com/kfei/slack-cleaner
・メッセージのバックアップは公式でできる。https://my.slack.com/services/export?
・鍵付きチャンネルは管理者でもバックアップできない気配
・"Analytics"のトータル・メッセージの反映は48ｈ遅れうる。
・ファイル・ストレージは5Gまで


バックアップ、準備後連絡が来て、ダウンロード。jsonでくる。
https://my.slack.com/services/export?

こいつを試す。slack-cleaner
https://github.com/kfei/slack-cleaner
python2.7筋かdockerでやる

```
python
pip install slack-cleaner
```

```
docker
$ docker pull kfei/slack-cleaner
$ docker run -it kfei/slack-cleaner
```


ダイレクトに下記のコマンドを打ち込む
　- チャンネル名：python3rss
　- トークンの取得
https://api.slack.com/custom-integrations/legacy-tokens

```
slack-cleaner --token <Token> 
--message --channel python3rss --bot --perform

slack-cleaner --token <Token> 
--message --channel python3rss --bot --user "*" --perform
```
--perform抜きのと2、3回実行したｗ
--message か --file　は必須

python2.7, win32で実行、py3はどうなんだろうか…　サイトに何か書いてある気配。
urllib3に警告がでても、なんとか実行できてる。
2000メッセージ20~30分くらいかかったかも
dockerがあるので、最初からそちらでやったらよかったかも
（やってみたが、すでにほとんど消えてた）

消えないのがあるとのことだが、何回かやって、
一時してアクセスしたら、消えてる気配だ。
https://syui.gitlab.io/blog/post/2017-05-31-slack/
しかし、analyticsのメッセージ数の計測に反映されてないな…（大汗）
**(わかった！トータル・メッセージは、"Analytics"への反映に48h遅れる可能性があるらしい。)**

p.s.
~~あ、sendだから送信数でみてて消しても意味ないのかも！~~
さくらのレンタルサーバのCRONでmysqldump、がすんなりできなかったお話

# 経緯
取引先の社内システムが「さくらのレンタルサーバ（php + MySQL）」で動いていて、
そろそろデータベースのバックアップも取り始めなきゃ…と思い、やりはじめる

# 実装
## シェルかphpか
シェルで記述したんでいいかーと思っていたけど、今後バッチ処理として何かしたいことができたりしたときとか、さくらのレンタルサーバのCRON設定個数が5個までしかできないということを考えて、phpでバックアップ処理を実装することに。
## ロジック
ものすごく単純。
稼働している3つのスキーマをmysqldumpでバックアップするだけ。
backupディレクトリに7日分保持。
過去のファイルは削除and削除。

# どこに詰まったのか
さくらのレンタルサーバでCRONを設定するときには色々とクセが有ることが多く、ネットの各ページには
- ユーザーディレクトリ（/home/username）に移動させて（cd）からでないとうまく動かない
- 実行ファイルはフルパスで書いておかないと動かない
とか書いてあったりして、少し混乱することがありますが、
基本は
```
/usr/local/bin/php /home/username/backup.php 1 >/dev/null
```
で大丈夫

コントロールパネルから設定してCRON動作を確認。
動いているっぽいからバックアップファイルを確認....と思ったところで問題発生。
バックアップファイルのファイルサイズが0バイト....

ディレクトリの権限を疑うものの、ファイルができてるから書き込み権限はあるはず。
ということでここから色々検証。

# 検証
## １．プログラムが問題ないかを検証
phpで書いているプログラムなので、www以下に持っていって直接叩いてもいいし、
さくらのレンタルサーバはsshの接続もできるので、sshで接続してCRONに記述した内容をコピペで叩いてもいい。

ちなみに今回は後者を選択。
これでバックアップファイルがちゃんと書き込みされていることを確認。

## ２．-qオプションをつける
CRONも起動されているし、ファイル書き込み権限もあって、プログラム自体も正しく動いているのなら、これはさくらのレンタルサーバ固有の動き方のお話だろうと思ってとにかくググってググって...
というところで下記ページを確認
http://www.omnioo.com/record/else/mysqldump-q-cron/

```php
exec("mysqldump -Q -u username -pPassword --default-character-set=binary -h XXXX.db.sakura.ne.jp username_db > $backup");
```
みたいな感じで実行してみる。
が、まだ0バイトファイル。。。。

## ３．mysqldumpをフルパスで書く
http://tanaka8.com/2014/12/mysqldump-php-cron/
上記のページに「コマンドまでのパスを記述しないと、cronでの実行に失敗します。」と書いてある。。。
でもsshから叩いたときは動いたけども？？？
と思いながら

```php
exec("/user/local/bin/mysqldump -u username -pPassword --default-character-set=binary -h XXXX.db.sakura.ne.jp username_db > $backup");
```
と書き直して実行。

~~おお、動いたぞ…でもなんで…？？~~
コメントにて頂いたとおり、CRONでの実行時は環境変数がセットされていないです。
完全に失念。。。（インフラとかサーバーとか弱すぎて困る）

# 結論
~~まあ動きはしたものの、ちょっとしたことでつまづくなーというイメージ。
普通に使う以外はあまりさくらのレンタルサーバを使わないほうがいいのはわかってるけど、法人かつシステム担当が薄い法人にとってみると、さくらのレンタルサーバ（ビジネス）とかって便利だからねえ、難しいところ。~~
自分のスキル不足つらい。。。
MapDをAWS上で試してみた

# MapDとは
https://www.mapd.com/
地図データを扱うことに長けたデータベース製品であり、データを可視化するVisual Analytics Platformを持つ
データベースの検索から地図上への表示までがとても高速なのが売り
Enterprise Edition(有償)とCommunity Edition(無償)があり、どちらもAMIが提供されているため、AWS環境があれば簡単に触ることができる
今回はCommunity EditionのAMIを試してみる
ちなみに、AMIには既にデモデータが入っているため、どれだけ高速にデータを可視化できるのか試すことができる

# インスタンス作成上限の制限緩和申請
MapD Community EditionのAMIは次の3つのインスタンスタイプでしか作成できない

+ p2.xlarge
+ p2.8xlarge
+ p2.16xlarge

しかし、これらのタイプのインスタンスの作成上限はデフォルトで0になっているようで、このままではインスタンスを作成できない
そのため、AWSコンソールにログインし、EC2サービスを開いて、左上にある"制限"という項目から、今回利用したいインスタンスの上限制限を緩和する申請を出さなければならない
私の場合は申請してから1日後にインスタンスを作成できるようになった

# 費用
Community Editionの費用

| インスタンスタイプ | 1時間当たりの費用 |
|--------------------|-------------------|
| p2.xlarge          | $1.542            |
| p2.8xlarge         | $12.336           |
| p2.16xlarge        | $24.672            |
2017年10月時点

# 導入手順
## インスタンスの作成
1. AWSコンソールにログインし、EC2サービスを開く
2. インスタンスの作成をクリックし、左側のペインからAWS Marketplaceを開く
3. AWS Marketplace 製品の検索に`MapD`と入力し、Community Editionを選択する
4. インスタンスタイプは`p2.xlarge`を選択した
5. ネットワークは必要に応じて設定し、ストレージはデフォルトのままとした
6. セキュリティグループはデフォルトの設定に加えてHTTPSを通すように設定した

## ElasticIPとパブリックDNS
1. ElasticIPを使ってインスタンスにグローバルIPを割り当てる
2. パブリックDNSが表示されればok
3. されない人は、VPCの設定から、DNS解決とDNSホスト名を「はい」に設定する

# 早速触ってみる
```
https://<public_dns>:8443
```
上記のURLにアクセスすると、次のような画面になります。
(安全な接続ではありませんというエラーが出ても無視して進む)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201287/e53a7ee6-5423-7f7e-b5c3-a0e5428f57aa.png)

ここでPASSWORDにインスタンスIDを入力するとログインできる
ログイン後の画面はこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201287/d5607e76-eb70-2ae3-b9df-90ec5a055515.png)

デモデータはニューヨークのタクシー情報のよう。。
画面をスクロールすると、右側の表示がリアルタイムに切り替わっていく
(右上にデータ件数が表示されているのですが、この件数をほぼリアルタイムで可視化できる！)
右側の棒グラフをクリックすると、そのデータだけ地図上に表示できたりする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201287/a81c19a1-34db-9fa4-856f-ea360e7a5b13.png)


# まとめ
+ MapDの立ち上げは、ものの15分ぐらいでできた
+ デモデータも入っているし、可視化まで簡単にできるので、どの程度の性能なのか見たい人にオススメ
Google Chrome で スクロールアニメーション付きのページ内ジャンプが動かない件

2017/10/04：
現在進行形で未解決。


# 現象
ロングスクロールでレスポンシブな感じのWebサイトを制作・公開してるんですが、
依頼元から

「PCの Google Chrome だとヘッダのメニュークリックしてもスクロールしないんだけど」

とご報告頂きました。
まさかと思って動かしてみたところ、確かにヘッダメニューのリンクをクリックしても
ページ内のスクロール移動が動かない。
Chrome の Dev Tools で見てもエラー無し。

# 実装内容

アンカーリンク（メニュー）にハッシュ(#)付きのURLを書いて、リンクの on("Click") イベントで
スクロールアニメーション付きのページ内ジャンプを実装しています。

加えて、ページ最下部の「TOPに戻る」ボタンも。
こんな感じ。

```javascript:sample.js
    $(".navtotop").on("click", function (e) {
       	e.preventDefault()
       	$("html, body").animate({
       	    scrollTop: 0
       	}, 500);
    });
```

これも全く動きません。

# 原因
調べてみたら、以下のページに行きつきました。

document.body.scrollTop always is 0
https://bugs.chromium.org/p/chromium/issues/detail?id=766938

どうやらどうスクロールしても document.body.scrollTop が 0 を返している模様。
この記事投稿時の最新バージョン (61.0.3163.100) でも改善していません。

# 対処 ※ 暫定
暫定的対処として、ページ内リンクのスクロールアニメーションを外しました。
こんな感じ。無念。

```javascript:sample.js
    // Chrome ブラウザ判定
    var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);

    $(".navtotop").on("click", function (e) {
        // 暫定的な対処 - https://bugs.chromium.org/p/chromium/issues/detail?id=766938
        if(isChrome) {
            window.href = "#wrapper";
        } else {
            e.preventDefault()
            $("html, body").animate({
                scrollTop: 0
            }, 500);
        }
    });
```

Chrome ブラウザだけ、アニメーションしないようにしています。

早く治らないかなー。

## 参考
 * [Chrome61は$('body').scrollTop()で常に0を返す - Qiita](https://qiita.com/r1tccv/items/9037490b78e26566e7bf)
 * [document.body.scrollTop always is 0 - bugs chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=766938)
 * [Google chrome document.body.scrollTop always returns 0 - StackOverflow](https://stackoverflow.com/questions/43717316/google-chrome-document-body-scrolltop-always-returns-0)
［Ruby/Rails］APIモードを使ったAPI実装方法

##共有すること
① Rails5のAPIモードで、JSONデータを提供するAPIを実装する方法
② CSVで用意した初期データを投入する方法


##利用する技術
Rails 5

##活用した情報
《京阪電鉄》  淀屋橋駅 【平日・出町柳方面】 時刻表の始発〜午前７時台まで<br>https://www.keihan.co.jp/traffic/station/stationinfo/010.html

**補足(2021/06/19追記)**
2017年8月時点のダイヤを参考に作成しています。

##下準備
時刻表データをCSV形式で準備
（今回ファイル名は **yodoyabashi.csv** に設定）

|発車時刻|列車種別|行先|備考|
|-------|------------------|------------------|------------------|
|05:04|普通|出町柳|３扉車|
|05:33|普通|三条|３扉車|
|05:48|急行|出町柳|３扉車|
|05:52|普通|出町柳|３扉車|
|06:01|普通|出町柳|３扉車|
|06:08|急行|出町柳|３扉車・京橋で普通に連絡|
|...|...|...|...|

**補足(2021/05/16追記)**
時刻表（PDF）の情報を Excel や Numbers 等の表計算ソフトに手入力して、その後 CSV として出力しました。


##コード例

① APIモードでアプリを新規作成（今回アプリの名前は、 **keihan_api** に設定）

```command:command
$ rails new keihan_api --api
```

② **keihan_api** ディレクトリまで移動

```command:command
$ cd keihan_api
```

③ 時刻表データを格納するモデル（ **Timetabe** ）を実装

|カラム|データ型||
|-------|------------------|------------------|
|dept_time|String|発車時刻|
|train_type|String|列車種別|
|destination|String|行先|
|memo|String|備考|

```command:command
$ rails g model Timetable dept_time:String train_type:String destination:String memo:String
```

④ マイグレーションを実行

```command:command
$ rails db:migrate
```

⑤ 時刻表データ（yodoyabashi.csv）を、dbディレクトリに格納

⑤ db/seed.rbを編集

```ruby:db/seeds.rb
require 'csv'

CSV.foreach('db/yodoyabashi.csv') do |row|
    Timetable.create(:dept_time => row[0],:train_type => row[1],:destination => row[2],:memo => row[3])
end
```

⑥ マイグレーションを実行

```command:command
$ rails db:seed
```

##実行結果

下記コマンドを入力後、http://localhost:3000/timetables にアクセス

```command:command
$ rails s
```

時刻表のデータがJSONで帰ってくることが確認できる。

![スクリーンショット 2017-10-04 1.59.59.png](https://qiita-image-store.s3.amazonaws.com/0/199441/2f60be67-7e3e-c1c3-9e8a-8c2164287d07.png)

## 《備考》 APIを解析するコード


```ruby:sample.rb
require 'json'
require 'uri'
require 'net/http'

uri = URI.parse("http//:www.sample.com")

json = Net::HTTP.get(uri)
result = JSON.parse(json)

puts result
```
macでPythonのseleniumを初めて動かす時のメモ


pythonでselenium環境構築でハマったのでメモ。
てかheadlessなったり、動きが激しいので古い記事は役立たず、公式ページをみるが正。
いやー　しかしseleniumはブラウザ間の依存がひどい。。

#環境
mac os
python3.5

#結論

ドライバーをダウンロードしてある場所にコピる必要あり。そのパスをコード実行時に指定するのだ。
下の内容には惑わされず、ここから最新とってください。
https://www.seleniumhq.org/download/

Selenium Client & WebDriver Language BindingsのPythonバージョンを取得。

```
sudo pip install selenium
wget https://github.com/mozilla/geckodriver/releases/download/v0.19.0/geckodriver-v0.19.0-macos.tar.gz
#展開して/usr/local/binにコピー
wget https://chromedriver.storage.googleapis.com/2.32/chromedriver_mac64.zip
#展開して/usr/local/binにコピー
```


```py:

import time
from selenium import webdriver

driver = webdriver.Chrome('/usr/local/bin/chromedriver')  # Optional argument, if not specified will search path.
driver.get('http://www.google.com/xhtml');
time.sleep(5) # Let the user actually see something!
search_box = driver.find_element_by_name('q')
search_box.send_keys('ChromeDriver')
search_box.submit()
time.sleep(5) # Let the user actually see something!
driver.quit()

```

で実行。

#ローカルのファイルを実行した場合

getするときに file:// を前につけて　絶対パスにするとうまくいった。
htmlのデータセットを大量に作ってスクリーンショットを撮りまくりたかったのでこんな雰囲気で使った。


```py:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

class capturer():

    def take(self, file_name):
        options = Options()
        options.add_argument("--headless")
        options.add_argument("--disable-infobars")
        browser = webdriver.Chrome(chrome_options=options, executable_path="/usr/local/bin/chromedriver")
        browser.get('file:///Users/hoge_user/hoge_tool/'+file_name+".html")
        browser.save_screenshot(file_name+".png")
        browser.close()

cap = capturer()
cap.take('hoge')
```


https://stackoverflow.com/questions/42950789/selenium-open-local-files


#エラー１
selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH. 

geckodriver
https://github.com/mozilla/geckodriver/releases

参考
http://pc.atsuhiro-me.net/entry/2017/01/15/124308

#エラー２
selenium.common.exceptions.WebDriverException: Message: unknown error: Runtime.executionContextCreated has invalid 'context'

brewではダメなんだと言われた。

```
brew uninstall --force chromedriver
```

直でダウンロードしてbinにコピーしたらいけた
https://chromedriver.storage.googleapis.com/index.html?path=2.32/

参考
https://stackoverflow.com/questions/46439714/selenium-common-exceptions-webdriverexception-message-session-not-created-exce

Selenium API(逆引き)
http://www.seleniumqref.com/api/webdriver_gyaku.html
PythonでSeleniumを操作する
https://kurozumi.github.io/selenium-python/index.html
言語ごとのselenium
https://yizeng.me/2014/02/23/how-to-get-window-size-resize-or-maximize-window-using-selenium-webdriver/#python-example
Object#timeout is deprecated, use Timeout.timeout instead. 

# 自分用メモ

## ruby のバージョン違いで環境変えたらエラーが出た。

### エラー文

> Object#timeout is deprecated, use Timeout.timeout instead. 

というエラーが出た場合の対処


> Timeout(0.05)

などは

> Timeout.timeout(0.05)

に、書き換える。

### ついでに

> TimeoutError 

は

> Timeout::Error

に書き換える
俺でもわかるApple Deployment Program入門のはずがわからなかった件

俺です。
これは停滞中の駄文です。

モバイルデバイスマネジメントの導入を考えてます。

導入にあたり、ひとまずAppleIDの法人化ってどうやるのって調べてたら法人プログラムとして[Apple Deployment Program](https://help.apple.com/deployment/business/?lang=ja#/tesa266f623b)というのがあるようでした。

早速登録してみることにします。

# AppleIDを登録する

管理用のメーリングリストにしようかなと考えてましたが、メアドは後から変更可能みたいなので
とりあえず俺の天上天下唯我独尊唯一無二なカッコイイ会社用メールアドレスで[作成](https://appleid.apple.com/account#!&page=create)します。

- いい感じにアカウント情報を設定
- 二段認証忘れずに

<img width="1161" alt="Apple_ID_を管理.png" src="https://qiita-image-store.s3.amazonaws.com/0/42755/0a5bf596-7768-4fa7-b2e8-c19e16d0200a.png">

# Apple Deployment Programへの登録

作ったAppleIDでdeploy.apple.comにアクセスし、認証します。
ここからはじまる最強のオサレマカー伝説(法人版)デビューなわけですが...

<img width="1422" alt="DUNS.png" src="https://qiita-image-store.s3.amazonaws.com/0/42755/4b11e2f7-8c65-d820-d8a1-36fbd8f884e4.png">

D-U-N-S番号というものをもっておらず、挫折しました。
きょうはここまで。

# D-U-N-S番号(ダンズナンバー)とは

[AppleIDと踊(ダンス)っちまう](https://www.google.co.jp/search?biw=1628&bih=953&tbm=isch&sa=1&q=%E3%83%8F%E3%83%BC%E3%83%89%E3%83%A9%E3%83%83%E3%82%AF%E3%81%A8%E3%83%80%E3%83%B3%E3%82%B9%E3%81%A3%E3%81%A1%E3%81%BE%E3%81%A3%E3%81%9F%E3%82%93%E3%81%A0%E3%82%88&oq=%E3%83%8F%E3%83%BC%E3%83%89%E3%83%A9%E3%83%83%E3%82%AF%E3%81%A8%E3%83%80%E3%83%B3%E3%82%B9%E3%81%A3%E3%81%A1%E3%81%BE%E3%81%A3%E3%81%9F%E3%82%93%E3%81%A0%E3%82%88&gs_l=psy-ab.3..0.11085.13719.0.14060.13.12.0.0.0.0.258.1672.0j6j3.9.0....0...1.1j4.64.psy-ab..6.7.1363...0i4k1j0i4i24k1j0i30k1j0i24k1.0.eeNWTlsUzEM)ために必要な[ダンズナンバー](http://www.tsr-net.co.jp/service/product/get_a_duns_number)とは
世界唯一の企業番号とのことで国税庁が割り振る[法人番号](http://www.houjin-bangou.nta.go.jp/setsumei/)とは異なる番号で、日本では東京商工リサーチが運営しているようです(運営と書いてあるけど、[Webサイト](http://www.tsr-net.co.jp/service/product/get_a_duns_number)上の関連団体に無いのは..)

鼻ほじってりゃできるだろうと思ったのですが鼻血がでてもできないようなので、まずはダンズナンバーの申請をしたいと思います。

なんかさーせんしたって感じでおわり。
うわーん。
HanamiのEntityは値を書き換えることができない

HanamiのEntityは、初期化した後で値を書き換えることができません。イミュータブル！

ちょっと個人的にインパクトが大きかったので記録を残しておきます。

##どうやってupdateするのか

Hanamiでデータベースに保存されている値を更新するコードは以下のようになります

```ruby
repository = UserRepository.new

user = repository.find(id)
repository.update(user.id, name: 'new name')
```

データの更新って↓のようなイメージだったのですが、Userエンティティの値を書き換えることはできないのでエラーになります。びっくりしてしまいました。

```ruby
# うごかない
repository = UserRepository.new

user = repository.find(id)
user.name = 'new name' # NoMethodError: undefined method `name='
user.update
```

## Entity内部から書き換えることもできない
オブジェクトの外側から値を書き換えられませんでしたが、内側からも同様です。ユーザーのパスワードを暗号化するために、以下のようなメソッドを作ったらエラーになりました。

```ruby:lib/myproject/entities/user.rb
class User < Hanami::Entity

  def password=(password)
    # # NoMethodError: undefined method `password_digest='
    self.password_digest = BCrypt::Password.create(password).to_s
  end

  def password
    BCrypt::Password.new(password_digest)
  end
end
```

やっぱりセッターの `password_digest=` メソッドが存在しないと言われます。
ソースを読んでみたら、コンストラクタの最後に`Object#freeze`が実行されていました。どうやっても値を変更することはできないようです。

```ruby:entity.rb
    def initialize(attributes = nil)
      @attributes = self.class.schema[attributes]
      freeze
    end
```
https://github.com/hanami/model/blob/24004ee2c07eb09e6b353dd27c580d0a000de17f/lib/hanami/entity.rb#L122-L125

```ruby:irb
irb(main):001:0> User.new.frozen?
=> true
```

##イミュータブルでも大丈夫
Entityがイミュータブルと聞いてショックでしたが、それは「Entityは値の入れものでしかない。Entityにビジネスロジック的なことを書いてはいけない」っていう風に誤解してしまったからで、よーく考えてみるとそんなに慌てることもないような気がしてきました。
値の書き換えができなくても処理は書けるし、データベースから取得したか、あるいはnewした時点の状態と変わってないことが保証されるので、安全性が増す気がします。

ちなみに、ユーザーのパスワードについてどう実装したらいいかググってみたら、Hanamiのチャットで中の人がコンストラクタでセットするといいよって言ってたので、コンストラクタをオーバーライドして以下のようになりました。

```ruby:lib/myproject/entities/user.rb
class User < Hanami::Entity

  def initialize(attributes = {})
    if attributes.has_key? :password
      super attributes.merge(
        password_digest: BCrypt::Password.create(attributes[:password])
      )
    else
      super attributes
    end
  end

  def password
    BCrypt::Password.new(password_digest)
  end

end
```
[Windows10]デフォルトのタスクバーのピン留めを変更する

Windows10 のタスクバーにはデフォルトで Microsoft Edge が居座っている。
しかし、諸事情によりユーザーには Internet Explorer 11 を使わせたい。
そんな要望を実現するためのキッティング手順。

1.　レイアウト変更用XMLファイル(LayoutModification.xml)を作成する。

```xml:LayoutModification.xml
<?xml version="1.0" encoding="utf-8"?>
<LayoutModificationTemplate
    xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification"
    xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
    xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
    xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout"
    Version="1">
  <CustomTaskbarLayoutCollection PinListPlacement="Replace">
    <defaultlayout:TaskbarLayout>
      <taskbar:TaskbarPinList>
        <taskbar:DesktopApp DesktopApplicationLinkPath="%APPDATA%\Microsoft\Windows\Start Menu\Programs\Accessories\Internet Explorer.lnk"/>
      </taskbar:TaskbarPinList>
    </defaultlayout:TaskbarLayout>
  </CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>
```

**PinListPlacement="Replace"**があると既存のアプリを指定したアプリに置き換える。
これがない場合は既存のアプリに指定したアプリが追加される。
上記例は、既存のアプリを削除してIEに置き換えたもの。

2.　レイアウト変更用XMLファイルを下記フォルダに格納する。

`C:\Users\Default\AppData\Local\Microsoft\Windows\Shell`

設定は以上。

【補足】
- 上記設定の**後**にプロファイルが作成されたユーザに対しては**有効**。
- 上記設定の**前**にプロファイルが作成済みのユーザに対しては**無効**。
- 機能アップデートでレイアウト変更用XMLファイルが消える？
- レイアウト変更用XMLファイルはスタート画面のレイアウト(タイル)も定義可能。

参考: [Windows 10 タスク バーの構成](https://docs.microsoft.com/ja-jp/windows/configuration/configure-windows-10-taskbar)
pryでメソッドや、クラス、モジュールの定義を確認する

pryにはshew-docというメソッドがある。

show-doc = メソッドや、クラス、モジュールの定義をpry上で直接確認できるコマンドです。
setクラスの実装を見てみましょう。

[1] pry(main)> require "set"
=> true
[2] pry(main)> show-source Set#add

From: /usr/lib/ruby/2.3.0/set.rb @ line 312:
Owner: Set
Visibility: public
Number of lines: 4

def add(o)
  @hash[o] = true
  self
end
[3] pry(main)> show-source Set

From: /usr/lib/ruby/2.3.0/set.rb @ line 69:
Class name: Set
Number of lines: 492

class Set
  include Enumerable

  # Creates a new set containing the given objects.
  def self.[](*ary)
    new(ary)
  end

  # Creates a new set containing the elements of the given enumerable
  # object.
  #
  # If a block is given, the elements of enum are preprocessed by the
  # given block.
  def initialize(enum = nil, &block) # :yields: o
    @hash ||= Hash.new(false)

    enum.nil? and return

参考　パーフェクトRuby
良書です。
addPeriodicTimeObserverを使う際のメモ


### 開発環境

+ XCode9
+ Swift4
+ iOS11


AVPlayerを利用する際にUISliderを再生時間に合わせて動かすというよくあるやつですが、addPeriodicTimeObserverを使いますが、非同期処理を行うので、弱参照を意識しないと駄目なようです。

```
timeObserverToken = appDelegate.player?.addPeriodicTimeObserver(forInterval: time, queue: nil) { [weak self] (time) in
            guard let `self` = self else {
                return
            }
            
            // slider の位置更新
            // label　の再生時間更新
            }
```

addPeriodicTimeObserverを使う場合はremoveTimeObserverも呼び出すようにしないとずっと非同期処理が走るみたいですので、再生が終わったらremoveTimeObserverを呼び出します。

```
if let _timeObserverToken = timeObserverToken {
            appDelegate.player?.removeTimeObserver(_timeObserverToken)
            self.timeObserverToken = nil
        }
```




参考サイト
[addPeriodicTimeObserver(forInterval:queue:using:)](https://developer.apple.com/documentation/avfoundation/avplayer/1385829-addperiodictimeobserver)
Appleの公式で弱参照にしろよって解説があった。ついでにqueueにnilをすると、dispatch_get_main_queue()を使うようです。

[AVFoundationPiPPlayer](https://developer.apple.com/library/content/samplecode/AVFoundationPiPPlayer/Listings/AVFoundationPiPPlayer_PlayerViewController_swift.html)
addPeriodicTimeObserverを使ったアプリのAppleのサンプル

[Swiftの"[weak self]"にアクセスする時に"if let weakSelf = self"とか"self?"を書きたくない人へ](http://fromatom.hatenablog.com/entry/2016/01/27/125657)
すごく参考になりました。self?の?が無くなるのでロジック的にもソース的にも楽。
2to3でPython2.xのコードを3.xのコードに変換

## 概要
Python2.xで書かれたコードを3.xのコードに自動変換する。

## 2to3
Pythonに標準で同梱されている2.xのコードから3.xのコードに変換するスクリプト。

## 前提環境
Python2.xかpython3.xをインストール済みの環境

## 使い方
Windowsはパスが通っていないので直接指定するかパスを通す。
` (Pythonをインストールしたディレクトリ)\Tools\scripts\2to3.py `

Linux系はpythonをインストールするだけで使える。

` 2to3 (pythonファイル) `
変換前と変換後の差分が表示される。
ファイルの変更、保存は行われない。

### オプション
- ` -h ` ` --help `  
ヘルプを表示
- ` -w (pythonファイル) ` ` --write (pythonファイル) `  
変換したコードを元ファイルに上書きする。  
(pythonファイル).bak に元ファイルがバックアップされる。
- ` -n ` ` --nobackups `  
バックアップファイルを作成しない。


## 参考サイト
- [https://docs.python.jp/3/library/2to3.html](https://docs.python.jp/3/library/2to3.html)
- [http://blog.amedama.jp/entry/2015/09/21/045643](http://blog.amedama.jp/entry/2015/09/21/045643)
- [http://www.python-izm.com/contents/basis/2to3.shtml](http://www.python-izm.com/contents/basis/2to3.shtml)