OmniAICreator/Qiita-1.07M huggingface dataset:
cyberduckでassume roleして、S3へアクセス

# cyberduckでassume roleして、S3へアクセス

CyberduckがAWS STSとAWS認証情報ファイルに対応/IAM RoleでS3の利用が可能になったらしいので試してみました。

Cyberduck のバージョン6.7.0以降で対応している様です。

設定方法は下記の公式マニュアルを参照してください。

https://trac.cyberduck.io/wiki/help/en/howto/s3

## 手順

### 1. ~/.aws/credentials

account1_userがaccount2_userへスイッチロールして、account2_userのS3バケットにアクセスします。

```~/.aws/credentials
[account1_user]
aws_access_key_id = ********************
aws_secret_access_key = ****************************************
[account2_user]
role_arn = arn:aws:iam::************:role/OrganizationAccountAccessRole
source_profile = account1_user
```

### 2.　S3 (Credentials from AWS Security Token Service) profileというファイルをダウンロード

[S3 (Credentials from AWS Security Token Service) profile リンク](https://svn.cyberduck.io/trunk/profiles/S3%20(Credentials%20from%20AWS%20Security%20Token%20Service).cyberduckprofile)

### 3.　ダウンロードしたファイルをCyberduckで開きます。

私の場合は、関連付けされていたので、ダブルクリックすると、Cyberduckが起動して
ブックマークの登録画面が開きました。

~/Library/Group\ Containers/G69SCX94XU.duck/Library/Application\ Support/duck/Profilesに置く方法もあるそうですが、私の場合は上手く行きませんでした。

### 4. Profile Name in ~/.aws/credentialsに、スイッチ先のアカウント「account2_user」を設定します。

### 5.　出来上がったブックマークを開くと、スイッチ先のアカウントのバケットにアクセスできます。

以上
回り道Python（１）

# リストのコピーにハマる
Pythonでリストの複製を行おうと思って以下のようなコードを書いてハマる。

```python:wrong1.py
sequence = [2, 3, 5, 7, 11, 13]
subsequence = sequence
subsequence.remove(13)
print(sequence)
print(subsequence)
```

期待していた実行結果は

```
[2, 3, 5, 7, 11, 13]
[2, 3, 5, 7, 11]
```

なのだが、実際の結果は

```
[2, 3, 5, 7, 11]
[2, 3, 5, 7, 11]
```

ハテ？ removeしたsubsequenceの方はともかく、なんでsequenceまで要素13が削除が削除されたの？

理由が分からなくて調べるとすぐに判明。`subsequence = sequence`というのが誤りで、これだとsubsequenceのIDをsequenceのIDで上書きしてしまう。つまり、subsequenceが指し示しているものと、sequenceが指し示しているものが、同一のものになるのだそうだ。だから、subsequenceにsequenceのコピーを作って内容を書き換えたつもりだったが、sequenceの内容そのものを書き換えていたのだ。

この辺は、C言語のポインタで出てくるような話に似ている。関数呼び出しの場合に参照渡し（アドレス渡し？ポインタ渡し？）すると呼び出し元の変数にアクセスできるようになるものだ。`swap()`関数のようなものをCで書く場合に良く例として挙げられるものだ。

ちなみに、上のPythonコードを期待通りに動作させる場合は、リストのIDをコピーするのではなく各要素をコピーするようにスライス`[:]`を付けてあげると良いのだそうだ。

```python:correct1.py
sequence = [2, 3, 5, 7, 11, 13]
subsequence = sequence[:]
subsequence.remove(13)
print(sequence)
print(subsequence)
```

ただし、このコピー操作はとても遅いのか、数万個要素のリストコピーを数万回のループで処理させていたらとても時間がかかっていたのに、その分を見直して削除したら途端に早くなった。長い系列処理で、こういうコードを繰り返し実行するのは避けるべきだ。
Serverless Frameworkを初めて使ったので覚え書き

# 最初に
案件で初めてServerlessFrameworkを使用しました。
自分の認識が正しいのか読んでくださった方にレビューを頂きたいのと、
将来忘れた頃に自分が作る事になるかもしれないので覚え書きとしてまとめておきました。
間違いがあれば編集リクエストを投げてくださると大変有難いです。宜しくお願いします。

# Serverless Framework
AWS CloudFormationのラッパーだよ。
CloudFormationはテンプレートを与えてやるとアプリケーションが構築出来ちゃうやつだよ。
👉今回はYAMLでテンプレートを書いたよ。
👉しかも、デプロイはコマンド一発で出来ちゃうよ。
👉デプロイすると、上から順番に一気に実行するよ。転けると途中で止まっちゃうよ。全部成功してから立ち上がるよ。
👉失敗すると、前のデプロイも取り消されちゃうよ。
👉一個だけデプロイしたい時は、コマンドで指定できるよ。

#開発の流れ
1. サーバ側(Cognito)を用意する
2. テンプレートを作成する
3. デプロイする
4. 出来上がる

#コマンドの種類
**基本コマンド**
`sls`
**デプロイ**
`sls deploy`
**特定の関数だけデプロイ**
`sls deploy -f hoge`
**特定のAPIステージを切りたい**
`sls deploy --stage hoge`

#ロール
それぞれLambdaが立つけど、ロールは共有されるよ

#テンプレート(YAML)の書き方

```YAML
service: hoge

custom:
    defaultStage: dev
    defaultProfile: default
    defaultRegion: ap-northeast-1
    congnitoARN: "arn:aws:cognito-idp:ap-northeast-1:hogehogehugahuga~~~"
provider:
    name: aws
    runtime: nodejs8.10
    timeout: 29
    environment:
        TZ: Asia/Tokyo
    ##opt:stageにはステージ名が入る
    ##sls deploy --stage hoge などでデプロイをかけない場合は
    ##defaultStageに設定したステージ名が入る(この場合はdevが入る)
    stage: ${opt:stage, self:custom.defaultStage}
    profile: ${opt:profile, self:custom.defaultProfile
    region: ${opt:region, self:custom.defaultRegion}
iamRoleStatements:
    - Effect: "Allow"
      Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/hogehuga"
      Action:
        - "dynamodb:GetItem"
        - "dynamodb:PutItem"
        - "dynamodb:Update"
        - "dynamodb:Query"
        - "dynamodb:DeleteItem"
Function:
  lambdaの名前:
    handler:どのJSを読み込む？
    description:説明文
    event: //キックされるタイミング
    -http: //APIGatewayの事
    
                        
```

Lambdaを追加する時はindex.jsにファイルをインポートしてあげなきゃダメだよ。

#デプロイしたものを削除したい
YAMLのdefaultStageを削除したいステージ名に変更してから、
`sls remove` を実行する。
Cloudstack APIのSignature生成方法

IDCFクラウドとCloudnがCloudstackベースのサービスであり、それらのサービスをREST APIで操作する際にCloudstack APIのSignatureが必要となるため、その生成方法のメモです。

- ```apikey=<API Key>&command=listVirtualMachines``` の箇所へ、Signatureを除いたクエリ文字列を定義する
- クエリ文字列は、予めKeyの順序をアルファベット昇順にソートしておく

```
echo -n \
`echo "apikey=<API Key>&command=listVirtualMachines" | tr A-Z a-z` \
| openssl sha1 -binary -hmac '<Secret Key>' \
| openssl base64 \
| nkf -WwMQ \
| tr = %
```
Android URIからMimeTypeを取得する


こんな関数を作成すればMimeTypeを取得できます。
拡張子から判別とか怪しい気もするので。。

```kotlin
private fun getMimeType(context: Context, uri: Uri): String? {
    val cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.MIME_TYPE), null, null, null)
    return cursor.use {
        if (cursor.moveToNext()) {
            return@use cursor.getString(0)
        } else {
            return@use null
        }
    }
}
```

参考
https://stackoverflow.com/questions/9414487/how-to-get-the-image-format-of-the-images-from-gallery
C# Generics忘備録短編

# 序論

こちらの記事は、sakano様の基礎から学ぶLINQの仕組みを自分なりに読み取った結果のアウトプット第一弾である。
こんな駄文を読むよりsakano様の記事を読むことをお勧めする。
sakano様の素晴らしい記事のリンク↓
https://qiita.com/sakano/items/d4ad645a20860c3a86c0

# Genericsについて

これは、態々引数を変えてオーバーロードを書かなくて良いという点がある。
どういうものか？例えば、2数の大きさを比較して大きい数値を返してくれるものを考えよう
そういったときに、高々引数の型が違うだけで態々コードを追加しなければならないのか？
それは無駄な処理であるといえる。なぜ？Genericsで簡単に記述ができるからだ。

```csharp


public static T Bigger<T>(T num1, T num2)
where T : IComparable<T>
{
    if(num1.CompareTo(num2)>0) return num1;
    return num2;
}

```

これで終わりだ。なぜ、普通にnum1>num2としないのかはGenericsだからと言わざるを得ない。どのような型が入るかわからないからいつもの演算子が使えないのである。よって、和を返す処理を書きたかったとしても結構面倒な処理があったので、今回は注意としてしか触れない。

かなり短いが、これくらいの方が書きやすいので以上とする。
もし、読んでくれた高スキルの方、私と同じレベルの方々へ。
何か問題点があれば是非ご教示願いたい。
配列オブジェクトにおけるsortメソッドまとめ

##sortメソッドを学ぶにあたり、はじめに特殊な比較演算子　『<=>演算子』を復習しましょう！
###比較演算子（<=>）とは？
```
a <=> b
```
a が b より大きいなら正の整数
a と b が等しいなら 0
a が b より小さいなら負の整数
a と b が比較できない場合は nilを返す

##では、sortメソッドを学んで行きましょう！
```
numbers = [9, 4, 1, 5, 2, 3, 10, 6, 4, 8]
numbers.sort
=> [1, 2, 3, 4, 4, 5, 6, 8, 9, 10]
```
sortメソッドは新しい配列を返します。
要素の比較には、上で説明した比較演算子（<＝>演算子）が用いられられて、
「a <=> b]を行い、a　< bであれば、負の整数を返し、aが先に来る。a=bであれば、０を返し、同じ。a>bであれば、正の整数を返し、bが先となる。
このような処理の結果として、配列オブジェクトの要素は昇順に並び替えられます。

##少し発展した形も学んで見ましょう！
```
numbers = [2, 8, 7, 3, 6, 10, 1, 4, 5, 9]
numbers.sort {|a, b| b <=> a }
=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
```
sortメソッドにブロックを渡すと、<=>演算子の代わりにブロックの戻り値によって要素をソートします。ブロック引数a、 bには、比較する2要素が入ります。ブロックの戻り値が負の整数ならaが先、0なら同じ、正の整数ならbが先となります。このような結果として降順に並び替えられます。

##最後に
sortメソッドは、初学者にとって非常に理解しづらいと思いますが、基本を抑えれば、少しずつ使えるようになって行きます。積極的に使って行きましょう！

#追記
みなさんから指摘を受け、sort_byを学習したので、追記します

##sort_byとは？
sortと同じように比較演算子<=>を用いて、並び替えを行うメソッドになります。
sortより優れている点は、拡張性、複雑な処理を行う際の実行の速さがあります。
（https://qiita.com/techno-tanoC/items/f64663eb9b6c0aa3dc37）

##sort_byの書き方
```
配列オブジェクトorハッシュオブジェクト.sort_by{|item| block }
```
流れとしては、
①配列オブジェクトorハッシュオブジェクトの要素を一つずつ変数(｜｜)に代入する
②blockにて処理を行う
③ブロックの戻り値を並び替える（<=>が動いている）

###配列オブジェクトのケース
```
fruits = ["strawberry", "orange", "apple"]
p fruits.sort_by{|fru| fru.size}
=>["apple", "orange", "strawberry"]
```
要素を一つずる変数に代入し、変数を文字数で並び替えを行う。
###ハッシュオブジェクトのケース
```
fruits = {strawberry: 120, orange: 39, apple:60}
p fruits.sort_by{|k,v| v}
=>[[:orange, 39], [:apple, 60], [:strawberry, 120]]
```
変数を二つ指定している理由として、キー、バリューをどちらも代入するためである。比較対象にしたい方をブロックに代入し、その返り値に基づき、並び替えを行う。
jupyterでpyprojを使おうとするとRuntimeError: b'no arguments in initialization list'が発生

# 問題

2018年9月11日現在，jupyterでpyprojを使おうとすると

```
RuntimeError: b'no arguments in initialization list'
```
のエラーが発生．

# （一時的）解決策

関連する記事を読むと，通常は特に考慮する事項もなく普通に使えるよう．おそらく使用しているビルドで何かしらの問題が起きていると思われるので，異なるビルドをインストール

```
$ conda search pyproj
\# Name                  Version           Build  Channel
pyproj                  1.9.5.1          py27_0  pkgs/free
pyproj                  1.9.5.1  py27h524b6af_1  pkgs/main
pyproj                  1.9.5.1          py34_0  pkgs/free
pyproj                  1.9.5.1          py35_0  pkgs/free
pyproj                  1.9.5.1  py35hb98d9bb_1  pkgs/main
pyproj                  1.9.5.1          py36_0  pkgs/free
pyproj                  1.9.5.1  py36hb98d9bb_1  pkgs/main
pyproj                  1.9.5.1  py37hb98d9bb_1  pkgs/main

$ conda install pyproj=1.9.5.1=py36_0
```

これで一応の所使えるように．
php-master-changes 2018-09-10

# 2018-09-10
## bukka: Fix ssl stream reneg limit test to print only after first renegotiation
- https://github.com/php/php-src/commit/be50a72715c141befe6f34ece660745da894aaf3
- ext/openssl のテストの共通コードで、複数回のリネゴシエーションを行うテストにおいても最初の一回だけ出力を行うよう修正

## weltling: Skip test on unsuitable env
- https://github.com/php/php-src/commit/27b270de896be6dbe3ce70866421d704cbee4c6f
- [昨日追加した](https://qiita.com/sj-i/items/ca1ef0402f7e8f024c45#weltling-add-test-for-bug-76850)テストが C locale 以外じゃないと意味なかったので、C locale ならスキップするよう修正

## dstogov: Fixed wrong assertion
- https://github.com/php/php-src/commit/64dad57d198cb9614e55014948f381727185bf72
- ext/opcache の誤ったアサーションを修正

## sgolemon: Enforce ordering of property compare in object comparisons
- https://github.com/php/php-src/commit/a26a107aae3f202580e5dfba8ecf735a29c907d4
- オブジェクト同士の比較の挙動を修正
- PHP 5.4 以降で print_r() の利用後など、オブジェクトの内部的なプロパティ順が変更されるような副作用があり、比較結果に影響を与えていた
    - https://3v4l.org/2figq こんなのあったんかとびっくり、print_r() でなく foreach で順繰りに要素アクセスしたり [array キャストしても同じことが起きる](https://3v4l.org/HaBjF)
    - PHP5.4 以降、オブジェクトへのある形でのアクセス時（ハッシュテーブルを順繰りにたぐるような操作？）、内部で持ってるプロパティの C 配列が初期化されて、この並び順はオブジェクト間で共有されず、しかしオブジェクト同士の比較にはその配列が使われてた、みたいな奴かな？ 修正はクラスエントリのデータ順で各オブジェクトのプロパティを引いて回るようにして一貫性を確保。時間の問題であまり見れてないので別途確認して追記（以下は追記分）
- [internals で 1 ヶ月ほど前に議論があった](https://externals.io/message/103076)
- 元は [Because, PHP](https://www.facebook.com/147594855443853/photos/a.255658437970827/861240274079304/) で出てきたネタ
- オブジェクト同士の大小比較の挙動は[マニュアル](http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.types)に[ない](http://php.net/manual/en/language.oop5.object-comparison.php)が、[php-langspec](https://github.com/php/php-langspec/blob/master/spec/10-expressions.md#user-content-relational-operators) にはある程度記述がある
- 同じクラスのオブジェクト同士で特に既定の挙動がなければ配列の比較に準ずる
- 配列同士のの比較は左辺のキーを順繰りに見て、最初の異なる値を見つけたら比較を抜ける、という挙動
- ただしこのケースでオブジェクトのプロパティを順繰りにたどる順序は、厳密には規定がない
    - オブジェクトから配列へのキャストについてはプロパティの宣言順に詰められるという[規定がある](https://github.com/php/php-langspec/blob/master/spec/08-conversions.md#converting-to-array-type)
    - が、このケースも継承で親から引き継いだ場合などのプロパティの順については規定がない
- 未定義の挙動は未定義の挙動としても、再現性は必要で、read-only なアクセスで変わるのはまずいですね、というので修正（動作の機序についてはまた別途追記）
変数のスコープ - Ruby

#変数
変数はスコープによって種類が分けられている。
命名規則があるため名前を見ただけで、なに変数なのかを判別できる。

###ローカル変数

**スコープ:** ブロック、メソッド定義、クラス・モジュール定義、トップレベル
**命名規則:** 先頭が小文字のアルファベットがアンダースコアではじまる名前　 **例、`ruby`, `_ruby`**

```sample.rb
foo = 'foo in toplevel'

def display_foo
  puts foo     # NameErrorが発生
end

puts foo       # "foo in toplevel"と表示
```
*メソッドの外で定義されたローカル変数をメソッドの中から参照できない*

```sample.rb
greeting = "Hello, "
people = ['Alice', 'Bob']

people.each do |person| # person <= ブロックローカル変数と呼ぶ
  puts grerting + person　　　　# "Hello, Alice"などと表示
end

puts person               #NameError: undefined local variable or method`'person'...
```
*ブロックの中からブロックのそとで定義されたローカル変数は参照できる*
*ブロックの外からプロックの中で定義されたローカル変数を参照しようとするとエラー*


###インスタンス変数
クラスから作成されたインスタンス毎にことなる値を格納される

**スコープ:** クラス内のメソッド(外部からのアクセスには`attr_accessor :インスタンス変数`を使用
**命名規則:**　@から始まる名前 **例、`@ruby`**

```sample.rb
class Ruler
  def length=(var)
    @length = var
  end
  
  def length
    @length
  end
end

ruler = Ruler.new

ruler.length = 30
ruler.length      # => 30
```

###クラス変数
クラスから作成された全てのオブジェクトで共有される

**スコープ:**クラスとそのインスタンス
**命名規則:**変数名の前に@@をつける **例、`@@ruby`**

```sample.rb
class Ruby 
 @@Ruby = "ルビー"
 def hello
  puts "こんにちは, #{@@Ruby}"
 end
end

input = Ruby.new
input.hello #=>こんにちは, ルビー
```

###グローバル変数

非常に広いスコープを持つ変数。どこからでも参照・変更できるがグローバル変数に依存したコードは読みづらくなる。

**スコープ:**どこからでも定義・参照・変更できる
**命名規則:**変数名の前に$をつける **例、 `$ruby`**

```sample.rb
$ruby = "Hello, Ruby"
```
Linux の LED 制御


# はじめに
LinuxでIoTデバイス開発をしていると、「LEDをこのパターンで点灯/消灯したい」という場合があります。
この記事ではその方法を記載します。

### 点灯/消灯
まず、対象のデバイスにどのようなLEDが定義されているかを確認しましょう。
下記コマンドを実行すると、以下のようにいくつかのディレクトリが表示されます。

```
$ ls /sys/class/leds/                                               
alfa:blue:lan   alfa:blue:wan   alfa:blue:wps                                   
alfa:blue:usb   alfa:blue:wlan  ath9k-phy0
```

このボードの場合は6つ表示されているので、6個のLEDが使用可能ということになります。

例としてLANを表すalfa:blue:lanを使用して説明していきます。
LANLEDという名前で定義しておきます。

```
LANLED="alfa:blue:lan"
```

以下のように記載することで、点灯できます。

```
echo "none" > "/sys/class/leds/$LANLED/trigger"
echo 255 > "/sys/class/leds/$LANLED/brightness"
```

同様に、下記で消灯です。

```
echo "none" > "/sys/class/leds/$LANLED/trigger"
echo 0 > "/sys/class/leds/$LANLED/brightness"
```

brightnessに書き込む値は、一般的には 0 が消灯で 1 以上が点灯です。
中間の明るさを表現できるLEDもありますが、私はあまりお目にかかったことはありません。

### 点滅
LEDを点滅させて欲しいという要求は割と多いものの、そのためだけにdaemonを起動するのはなるべく避けたいです。
IoTデバイスはリソースが限られるからです。
幸いなことにLinuxにはdaemonを用いずとも点滅させることができる仕組みがあります。
まず、下記コマンドでtriggerファイルに"timer"と書き込みます。
するとdelay_onとdelay_offというファイルが生えてきますので、これに対して点灯時間と消灯時間をmsec単位で書き込みます。
例えば1000msec点灯して500msec消灯するのを繰り返す場合は以下のように書き込みます。

```
echo "timer" > "/sys/class/leds/$LANLED/trigger"
echo 1000 > "/sys/class/leds/$LANLED/delay_on"
echo 500 > "/sys/class/leds/$LANLED/delay_off"
```

### シェルで使う場合
OpenWrtの/lib/functions/leds.shに便利な関数が定義されているので、これを借用するのも手です。

```shell
led_set_attr() {
	[ -f "/sys/class/leds/$1/$2" ] && echo "$3" > "/sys/class/leds/$1/$2"
}

led_timer() {
	led_set_attr $1 "trigger" "timer"
	led_set_attr $1 "delay_on" "$2"
	led_set_attr $1 "delay_off" "$3"
}

led_on() {
	led_set_attr $1 "trigger" "none"
	led_set_attr $1 "brightness" 255
}

led_off() {
	led_set_attr $1 "trigger" "none"
	led_set_attr $1 "brightness" 0
}
```

例えば1000msec点灯して500msec消灯するのを繰り返す場合は以下のように書くだけでできます。

```
led_timer $LANLED 1000 500
```
[kotlin] realm.useから値を返す


`realm.use` 関数は引数で渡したブロック終了後に`realm.close`を自動でやってくれるので便利です。
しかしブロック内でしかrealmのデータにアクセスできないので、 `use` ブロック内にいろいろ処理を書くことになってしまいます。

データ取得が終わったら早々にDBはクローズしてしまいたい時があり、`use`ブロックでデータを取得して戻り値として返す方法について調べました。

kotlinのlambda関数の戻り値に設定すればやりたいことができます。

```kotlin
val hoge = Realm.getDefaultInstance().use { realm ->
    val _hoge = realm.where(Hoge::class.java).equalTo("id",23L).findFirst() ?: return@use null
    val hoge = realm.copyFromRealm(_hoge) // 参照したいだけなのでunmanagedにする
    return@use hoge // 単にhogeでも可
}
// hogeを使用する後続の処理
```
Xcode ver 9 にFSCalendarを使用するための準備

MacOS High Sierra にインストール
$ sudo gem install cocoapods

私の場合は、Xcode Command Line Tool がインストールしていないので、これもインストールされた。
CocoaPodsのVersionは、1.5.3

$ pod setup　を実行する。

Xcodeで最初にProjectを作成しておく。

そして、ターミナルから

$ pod init　を実行して

実行後、ディレクトリ内にPodfileが作成されれば成功です。

Podfile をnanoコマンドで編集します。

  pod 'FSCalendar'
  pod 'CalculateCalendarLogic' 

  // 以下、Cocoapod ver 1.5.0のバク対応のコード
　　　　post_install do |installer|
  　　　　  installer.pods_project.build_configurations.each do |config|
        config.build_settings.delete('CODE_SIGNING_ALLOWED')
        config.build_settings.delete('CODE_SIGNING_REQUIRED')
    　　　　end
　　　　end

編集後、以下のコマンドでインストールをする。

$ pod install

これで完了です。
SAM新機能について

スクリーンショットもバージョンが古いもので、新機能の部分(詳細な条件を記載できる部分)の説明がない
やってみた感じ、前のバージョンで選択式だったやつが、自分で書けるようになっている雰囲気

https://docs.hortonworks.com/HDPDocuments/HDF3/HDF-3.2.0/building-a-sam-application/content/filter_events_in_a_stream.html

https://docs.hortonworks.com/HDPDocuments/HDF3/HDF-3.2.0/building-a-sam-application/content/use_aggregate_functions_over_windows.html

https://docs.hortonworks.com/HDPDocuments/HDF3/HDF-3.2.0/building-a-sam-application/content/join_multiple_streams.html

気になる点
postgresのDBに登録されている内容は以下の参考ページのやりかたで見れそう？
http://ijokarumawak.github.io/hdf/streamline/2017/06/26/streamline-udf/
terraform_remote_stateとworkspaceの落とし穴

Terraform の [Workspaces](https://www.terraform.io/docs/state/workspaces.html) 機能は便利ですよね。同一プロジェクトから複数環境(development, qa, staging, prodcution, ...)を切り替えて管理できるので重宝しています。

ワークスペースを変更すると tfstate も別に保存しなければならないため、それぞれ保存される場所が変わるように設定しなければなりません。僕は s3 backend を使っているので、以下のように設定しました。

```
terraform {
  backend "s3" {
    region               = "ap-northeast-1"
    bucket               = "my-tfstate"
    key                  = "network/terraform.tfstate"
    workspace_key_prefix = "env:"
    dynamodb_table       = "terraform_backend"
  }
}
```

`workspace_key_prefix` がミソで、これにより以下のようにワークスペースごとに異なる key が使われます。

| workspace | key |
| --------- | --- |
| `default` | `s3://my-tfstate/network/terraform.tfstate` |
| `staging` | `s3://my-tfstate/env:/staging/network/terraform.tfstate` |
| `qa`      | `s3://my-tfstate/env:/qa/network/terraform.tfstate` |

default 以外のワークスペースを選択すると `workspace_key_prefix` が key の先頭に追加され、`env:` の次にワークスペース名が入ることが分かるかと思います。

ちなみに `workspace_key_prefix` のデフォルト値は `env:` なので、わざわざ書く必要はありません。

```
terraform {
  backend "s3" {
    region               = "ap-northeast-1"
    bucket               = "my-tfstate"
    key                  = "network/terraform.tfstate"
    dynamodb_table       = "terraform_backend"
  }
}
```

これ自体は嬉しい機能なんですが、この tfstate を [terraform_remote_state](https://www.terraform.io/docs/providers/terraform/d/remote_state.html) で異なるプロジェクトから参照しようとしたときに超ハマりました。

まず、普通に書くとこうなるかと思います。

```
data "terraform_remote_state" "network" {
  backend = "s3"
  config {
    region = "ap-northeast-1"
    bucket = "my-tfstate"
    key    = "network/terraform.tfstate"
  }
}
```

backend の設定と同じように、現在のワークスペースによって補完されることを期待しています。
しかし、このリソースの属性を参照しようとすると、属性が見つからないというエラーになるんですね。

```
* output.aws_aaa: Resource 'data.terraform_remote_state.network' does not have attribute 'vpc_id' for variable 'data.ter
raform_remote_state.network.vpc_id'
```

どうやら `terarform_remote_state` では現在のワークスペースに応じて key を生成してくれるなんてことはなく、backend 設定で補完された key を明示的に書かないといけないようです。

```
data "terraform_remote_state" "network" {
  backend = "s3"
  config {
    region = "ap-northeast-1"
    bucket = "my-tfstate"
    key    = "env:/${terraform.workspace}/network/terraform.tfstate"
  }
}
```

まぁ異なるワークスペースの tfstate を参照したいケースもありますし、妥当な仕様だと思います。
が、すっかり backend と同じように自動で key が補完されるものと思い込んでおり、ずいぶん見当違いなところを調べ回っていました。

同じ問題にハマっている人の助けになれば幸いです。
自分用ごった煮メモ：python編

#競技プログラムにおける標準入力用
以下が詳しいが、よく使うものについて抜粋する
https://qiita.com/kyuna/items/8ee8916c2f4e36321a1c

```input.txt
3
3 1 2
2 5 4
3 6
```

```input.py

numberN = int(input())
seqAi = list(map(int,input().split()))
benefitBi = list(map(int,input().split()))
increaseCi = list(map(int,input().split()))
```

実行は、以下のようにすればOK

```
$ cat input.txt | input.py
```



#member関数から、同じclassのmember関数を呼び出すときは、引数にselfをつける

```
class SampleApi:

    def get_service_status(host=True, service=True, hogehoge=True):
        return self.__api_request(self, method, request_params)

    def __api_request(self, method=None, params=None):
        if not isinstance(method, str):
            print('error: arg[method] must be string')
            print(method)
            return False
```
これで実行すると、methodにparamsが入って
`error: arg[method] must be string`と言われる。

selfを引数に指定しましょう



#左側を0でパディングした日付を生成したい
左側を0でパディングした日付を生成するのに
`datetime` moduleの、`strftime()`
が非常に便利。

```
hidaro@debean3:~$ python  
Python 2.7.3 (default, Nov 24 2017, 16:26:37) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> dt_now = datetime.datetime.now
>>> print(dt_now.strftime('%H'))
08
>>> print(dt_now.strftime('%M'))
09
>>> print(dt_now.strftime('%m\%2F'))
09\2018-09-11
>>> print(dt_now.strftime('%m%%2F'))
09%2F
>>> print(dt_now.strftime('%Y%%2F%m%%2F%D'))
2018%2F09%2F09/11/18
>>> print(dt_now.strftime('%Y%%2F%m%%2F%d'))
2018%2F09%2F11
```

%を出力したい場合は`%%`でいいみたいです。
公式ドキュメント -> https://docs.python.org/ja/3/library/datetime.html#strftime-strptime-behavior

#append, extendの違い

https://www.pythonweb.jp/tutorial/list/index6.html

```
list = ["A", "B", "C"]

list.append(["D", "E"])
print list      # ["A", "B", "C", ["D", "E"]]

list.extend(["D", "E"])
rint list      # ["A", "B", "C", "D", "E"]
```

よく忘れるので...
nifi stats とれそうなrest-api

参考ページ
/flow/processors/{id}/status/history
/flow/remote-process-groups/{id}/status/history
/flow/process-groups/{id}/status/history

/controller-services/{id}/state

https://nifi.apache.org/docs/nifi-docs/rest-api/index.html

その他、APIのステータス取得に関するトピック

https://community.hortonworks.com/questions/99744/nifi-processor-monitor-data-send-or-recieve-by-pro.html
schema registryのへんこうてん

0.5.0 -> 0.5.2

0.5.1 変更点
バグフィックスのみ

ISSUE-394 Expose an API to get schema versions after filtering it with state id
状態IDでフィルタリングした後にスキーマバージョンを取得するAPIを公開する

ISSUE-398 Add an option to disable validation during schema migration in storage-tool
ストレージツールのスキーマの移行中に検証を無効にするオプションを追加する

0.5.2 変更点
バグフックス + マイナーアップグレード

ISSUE-397 Support for Docker added to run Schema Registry application inside the container
コンテナ内でSchema Registryアプリケーションを実行するために追加されたDockerのサポート

ISSUE-404 Support http proxy related configuration for registry server
レジストリサーバのhttpプロキシ関連の設定をサポート

ISSUE-397 Dockerized Schema Registry application with KDC server.
KDCサーバーを持つDockerized Schema Registryアプリケーション。

ISSUE-410 AvroFieldsGenerator produces Stackoverflow error when parsing a nested record schema.
AvroFieldsGeneratorは、ネストされたレコードスキーマを解析するときにStackoverflowエラーを生成します。

ISSUE-418 Add JWT based SSO as alternative authentication to common-auth module.
共通認証モジュールへの代替認証としてJWTベースのSSOを追加します。

ISSUE-420 Add migration to add extents for created tables to fix serializable as an isolation level for Oracle database
作成した表のエクステントを追加して、Oracleデータベースの分離レベルとしてシリアライズ可能なものを修正するための移行を追加する

ISSUE-415 Client side schema validation - Disable or Customize
クライアント側のスキーマ検証 - 無効化またはカスタマイズ

ISSUE-425 Provide tool to initialize database and user
データベースとユーザーを初期化するためのツールを提供する

ISSUE-428 Treat existence of database/user as success while initializing database
データベースの初期化中にデータベース/ユーザの存在を成功として扱う

ISSUE-433 SR home page just spins with some errors on debugger console
SRのホームページは、デバッガのコンソール上でいくつかのエラーで回転します

ISSUE-441 Let addOrUpdate be compatible with PostgreSQL under 9.5
addOrUpdateを9.5のPostgreSQLと互換性を持たせる

ISSUE-447 De-couple JWTAuthenticationHandler from Kerberos related base class
Kerberos関連の基底クラスからJWTAuthenticationHandlerを分離する

MINOR: Docker db hostnames are exposed to the user.
Docker dbホスト名はユーザーに公開されています。

MINOR Added APIs to build schema registry version
スキーマレジストリバージョンを構築するためのAPIの追加


参考ページ
https://github.com/hortonworks/registry/releases
Windows環境で右辺値参照を含むシンボル名をUnDecorateSymbolName関数でデマングリングできない問題

Windows環境(MSVC)でデマングリングする場合、`UnDecorateSymbolName`関数を使う(使っていた)が、[前の投稿](https://qiita.com/udaken/items/4b60612e4091f39a8f9c)で調べていたら右辺値参照(`&&`)を含むシンボルがデマングリングされないことに気づいた。  

Visual Studio 2017に付属している undname.exe は(当然)デマングリングできる。

## undname.exe でのやり方
undname.exe を dumpbin.exe でみると、VCRUNTIME140.DLL に存在する `__unDNameEx` をインポートしている。

## `__unDNameEx`/`__unDName` とは
[MSDN](https://msdn.microsoft.com/ja-jp/library/dn727675.aspx)を見ても、内部関数であること以外は特に情報はない。
Visual Studio 2017に付属しているソースコード(crt\src\vcruntime\undname.cxx)を参照すると、以下のシグニチャを持っているようだ。  
名前が `__UNDNAME_NAME`/`__UNDNAME_NAME_EX`となっているが、多分マクロで置き換わるのであろう。  
(ちなみにインクルードしている "undname.hxx" は私の環境では見当たらない)

```cpp
pchar_t __UNDNAME_IMP __cdecl __UNDNAME_NAME(
    _Out_opt_z_cap_(maxStringLength) pchar_t outputString,
	pcchar_t name,
	int maxStringLength,
	Alloc_t pAlloc,
	Free_t pFree,
	unsigned short disableFlags

)
...

pchar_t __UNDNAME_IMP __cdecl __UNDNAME_NAME_EX(
    _Out_opt_z_cap_(maxStringLength) pchar_t outputString,
	pcchar_t name,
	int maxStringLength,
	Alloc_t pAlloc,
	Free_t pFree,
	GetParameter_t pGetParameter,
	unsigned long disableFlags

)
...
```
## __unDNameEx/__unDName を呼び出す。
デマングするコードで、下記の宣言を加えた。  
最後の引数の `disableFlags` は、多分 `UnDecorateSymbolName` と同じフラグを指定する。  
ランタイムとスタティックリンクする場合はよくわからん。

```cpp
typedef char *        pchar_t;
typedef const char *  pcchar_t;

typedef void * (__cdecl * Alloc_t)(size_t);
typedef void   (__cdecl * Free_t )(void *);

EXTERN_C pchar_t _VCRTIMP __cdecl __unDName(
		_Out_opt_z_cap_(maxStringLength) pchar_t outputString,
		pcchar_t name,
		int maxStringLength,
		Alloc_t pAlloc,
		Free_t pFree,
		unsigned short disableFlags
	);
EXTERN_C pchar_t _VCRTIMP  __cdecl __unDNameEx(
		_Out_opt_z_cap_(maxStringLength) pchar_t outputString,
		pcchar_t name,
		int maxStringLength,
		Alloc_t pAlloc,
		Free_t pFree,
		void* pGetParameter,
		unsigned long disableFlags
	);
```
AIY Vision KitでLチカ

今年になり、日本でもAIY KitのシリーズのVision Kitが発売されて開封レビューなんかも出ていますが、実はこのVision Kitの本体の裏にはGPIOが使える端子あってここから通常のRaspberry PiのようにGPIOでいろんなものを接続させることができるようですが、それを試したことある方の記事は見かけないです。実際AIYプロジェクト公式サイトでも[最後の方](https://aiyprojects.withgoogle.com/vision/#makers-guide--gpio-pinout-and-expansions)にRaspberry Piやボンネット（Raspberry Piのピンヘッダに繋げる画像処理用のハード）の構造図が掲載されているぐらいで「あとはライブラリのドキュメントや例のリンクがあるからそこで見てちょーだい」という感じで終わっているからなのかもしれません。（そもそも買った人が少ないのだろうか…）というわけで実際にVision KitのGPIOを使ってLチカをやってみます。
# ボンネットのLEDでLチカ
ボンネットのGPIOピンの横にはLEDがあってこれもプログラムで制御できるようです。GPIOのサンプルは次のディレクトリにあります。
```/home/pi/AIY-projects-python/src/examples/gpiozero
```
それではボンネットに内蔵されたLEDでLチカをやってみます。ターミナルで次のコマンドで実行できます。

```
./led_example.py
```

![20180911_021308.GIF](https://qiita-image-store.s3.amazonaws.com/0/170520/7f9c342a-8a86-34b6-5c28-2827313716e4.gif)

実行すると見づらいですが、GPIOピンの右側のLEDが点滅します。

#繋いだLEDでLチカ
ボンネットのLEDだと地味なので、今度は実際にGPIOピンにLEDを繋いでLチカをしてみます。
![gpio-top.png](https://qiita-image-store.s3.amazonaws.com/0/170520/1d8d1c12-18dc-0192-46b0-2213c6ba2630.png)
*参照：https://aiyprojects.withgoogle.com/vision/#makers-guide--gpio-pinout-and-expansions*

接続はこの中の「5v power」をLEDの＋極側に接続し、「GPIO headers」のどれか一つをー極側に接続します。サンプルではどのGPIO端子に繋いでも出来るようになっているので、好きな所に繋いでOKです。電圧が５V出るので抵抗は必ずつけた方がいいです（150Ωあるといいです）。接続できたら、次のコマンドで実行します。

```
 ./led_chaser.py 
```

![20180911_022827.GIF](https://qiita-image-store.s3.amazonaws.com/0/170520/90441da2-5053-1673-00e8-eaa7cc35dbe3.gif)
ようやくお馴染みのLチカができました。この他にもボタンやサーボモータを接続するサンプルもあるのでVision Kitでもいろんなものが作れそうですね。
Raspberry PiにCloud9をインストールし開発環境を整える

自宅に設置したRaspberry Piに[Cloud9 Core](https://github.com/c9/core)をインストールし、自前のCloud9環境を構築する。

## Node.jsのインストール
最新版のNode.jsとnpmをインストールする。

```bash
$ curl -L https://git.io/v7kPb | bash
$ node -v
v10.10.0
$ npm -v
6.4.1
```
参考: https://qiita.com/mascii/items/77c685df65c4cbca9315

## Cloud9 Coreのインストール

```bash
$ git clone https://github.com/c9/core.git c9sdk
$ cd c9sdk
$ scripts/install-sdk.sh
$ node server.js --listen 0.0.0.0 -p 8080 -a : # ブラウザから動作確認する
```

# Cloud9をサービスとして登録しサーバ起動時に自動起動する
```bash
$ sudo vim /etc/systemd/system/c9.service
$ cat /etc/systemd/system/c9.service
[Unit]
Description=Cloud9 Core

[Service]
Type=simple
PIDFile=/var/run/cloud9.pid
ExecStart=/usr/local/bin/node server.js --listen 0.0.0.0 -p 8080 -a :
User=pi
Group=pi
WorkingDirectory=/home/pi/c9sdk
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
$ sudo systemctl enable c9
Created symlink /etc/systemd/system/multi-user.target.wants/c9.service → /etc/systemd/system/c9.service.
$ sudo systemctl start c9
```
これでRaspberry Piの起動時にCloud9も自動で起動されるようになる。
Cloud IAMあれこれ試行（その2：「プロジェクトメンバー追加と役割付与」）

# お題
表題の通り。
以下のチュートリアル相当のことをやっただけ。
https://cloud.google.com/iam/docs/quickstart

# 前提
- 試行端末はLinux（Ubuntu 17.10）
- GCPアカウント取得済み
- gcloudコマンドインストール及びセットアップ済み

# 実践
## ひとまず、プロジェクトを作成したオーナーのみ存在する状態から
![B01.png](https://qiita-image-store.s3.amazonaws.com/0/180599/42449e7d-b165-68ea-2121-c50e495cb99f.png)

## これ用に作ったGoogleアカウントに対して「Pub/Subパブリッシャー」と「ストレージのオブジェクト作成者」ロールを付与
![B02.png](https://qiita-image-store.s3.amazonaws.com/0/180599/3d2f1b2a-bf54-dca0-e126-0d7551b350d4.png)

## こうなる
![B03.png](https://qiita-image-store.s3.amazonaws.com/0/180599/af44e82d-7494-b6d7-ed81-cd24a2d45be6.png)

## これ用に作ったGoogleアカウントでログインしなおす（ホームのダッシュボードは参照できる）
![B04.png](https://qiita-image-store.s3.amazonaws.com/0/180599/3e09f55a-5007-af8b-5f15-6cf915e81889.png)

## GCEのロールは付けていないので参照できない
![B05.png](https://qiita-image-store.s3.amazonaws.com/0/180599/7c93fe87-19f3-7e3c-b2a6-dfee5a72f5d8.png)

## さて「Pub/Subパブリッシャー」ロール付けたからPub/Sub関連は強い権限あるのかと勝手に予想
![B06.png](https://qiita-image-store.s3.amazonaws.com/0/180599/4295499a-d249-33b2-32d8-0325f888fa62.png)

　**えっ、参照できない。。。**

![B07.png](https://qiita-image-store.s3.amazonaws.com/0/180599/4f9e30d9-a8c5-63d6-3b37-b47391b5066f.png)

　**こっちは「Pub/Subサブスクライバー」の管轄だろうから、まあ、参照できないのはわかる。。。**

## とりあえず、GCSの方も確認
![B08.png](https://qiita-image-store.s3.amazonaws.com/0/180599/901220d2-a562-885f-2383-e12c168d7375.png)

　**ダメだった。。。**

## あらためまして、オーナーでログインして権限確認
![B09.png](https://qiita-image-store.s3.amazonaws.com/0/180599/f8d67d38-2e81-44e3-8219-f6b0a674c586.png)

　**「Pub/Subパブリッシャー」は「トピックにメッセージをパブリッシュします。」とある。つまり、参照権限は無い？**
　**「ストレージのオブジェクト作成者」は「GCSにオブジェクトを作成できるアクセス権」とある。こっちは上位の”バケット”に関する権限がないためか？**

## なので、より強いと思われるロールに変えてみる
![B10.png](https://qiita-image-store.s3.amazonaws.com/0/180599/054cc3a7-5022-771e-4ccc-5931a37d91ce.png)
![B11.png](https://qiita-image-store.s3.amazonaws.com/0/180599/c08f96f8-6d8c-3fc1-a05c-a9c44b924b92.png)

## 今度は、どうだ？
![B12.png](https://qiita-image-store.s3.amazonaws.com/0/180599/a9f55701-6143-5fda-71f9-45ba456943e8.png)
![B13.png](https://qiita-image-store.s3.amazonaws.com/0/180599/11372a15-5ad2-e6d9-9ca4-6da077dfa5bf.png)
![B14.png](https://qiita-image-store.s3.amazonaws.com/0/180599/60a16e06-e9a0-972d-7ac4-64b5b69ee0ac.png)

　**トピック作れたっ！！**

## GCSは？
![B15.png](https://qiita-image-store.s3.amazonaws.com/0/180599/c033b61c-61c8-fab5-2628-a5a480c4a811.png)

　**さっきと違って、バケット作れそう。なので、満足。**

# まとめ
ロールによって何ができるかは確認した上で割り当てないといけない。
でも、どのロールが具体的にどこまでできる権限を持っているのかって何を見ればわかるんだ？
と思ったら、一応、↓に載ってた。
https://cloud.google.com/iam/docs/understanding-roles?hl=ja#cloud_pub_sub_roles
Docker経由でCargo buildするときにローカルのレジストリ情報を使う。

##はじめに
最近Dockerを使っていろんな言語でHelloWorldしてます。
RustをDocker経由でビルドするときに毎回

```bash
$ docker run --iroiro_option rust cargo build
>>> Updating registry `https://github.com/rust-lang/crates.io-index`
```

`Updating registry ~~`が実行されビルドに時間がかかっていたので、
ローカル（ホスト）にレジストリを作成してビルド時間を短縮しました。

###結論
`-v`オプションでビルドするホスト側のプロジェクトと、
依存パッケージを格納するホストディレクトリの両方をボリュームに割り当てることで、
ローカルのレジストリを使用してビルドできます。

```bash
$ docker run --rm \
   -v /path/to/your/project/:/usr/src/myapp \
   -v /path/to/your/registrory:/usr/local/cargo/registry/ \
   -w /usr/src/myapp \
   rust:latest \
   cargo build
```

###開発環境
- macOS High Sierra 10.13.6
- Docker for Mac
  - Engine : 18.06.1-ce
  - Compose : 1.22.0
- Rust : 1.28


##結論までの道のり

####1.まずは公式イメージをプルします。

```bash
$ docker pull rust
$ docker images
>>> REPOSITORY  TAG     IMAGE ID      CREATED     SIZE
>>> rust        latest  156ba9bbcf99  5 days ago  1.6GB
```

####2.コンテナを立ち上げプロジェクトの雛形を作成します。

```bash
$ docker run --rm \
   -e USER=your_name \
   -v $(pwd):/usr/src/myapp \
   -w /usr/src/myapp \
   rust:latest \
   cargo new your_project_name --bin
```
note : `-e`オプションで環境変数に`USER`を設定しないとコケるので注意。
コマンド実行後、ホストのカレントディレクトリ直下に`your_project_name`というプロジェクトが作成されます。

####3.Cargo.tomlに依存パッケージを追記します。

```toml:Cargo.toml
[package]
name = "your_project_name"
version = "0.1.0"
authors = ["your_name"]

[dependencies]
rand = "0.4.3" # 追記
```

```rust:main.rs
extern crate rand;
use rand::Rng;

fn main() {
    let random_number = rand::thread_rng().gen_range(1,101);
    println!("{} is generated!", random_number);
}
```

####3.レジストリ保存用のホストディレクトリをバインドしてビルドします。

```bash
$ docker run --rm \
   -v /path/to/your/project/:/usr/src/myapp \
   -v /path/to/your/registrory:/usr/local/cargo/registry/ \
   -w /usr/src/myapp \
   rust:latest \
   cargo build 
>>> Updating registry `https://github.com/rust-lang/crates.io-index`
>>> Downloading rand v0.4.3
>>> Downloading libc v0.2.43
>>>   Finished dev [unoptimized + debuginfo] target(s) in 5m 07s
```
2つ目の`-v`オプションを指定しホストディレクトリにレジストリの保存領域を確保してます。
rustのdocker公式イメージの場合、cargo管理下のレジストリは
`/usr/local/cargo/registry/`に配置されるようです。　
初回は依存パッケージのダウンロードが行われますが、
次回以降、

```bash
$ docker run --rm \
   -v /path/to/your/project/:/usr/src/myapp \
   -v /path/to/your/registrory:/usr/local/cargo/registry/ \
   -w /usr/src/myapp \
   rust:latest \
   cargo build 
>>> Finished dev [unoptimized + debuginfo] target(s) in 0.03s
```
パッケージのダウンロードが行われずコンパイルのみが実行されます。
お疲れさまでした！！
swift4 UIDatePickerからUITextfieldへ出力まで

DatePickerを使用して指定した日付を表示する際に少し困ったので、
同志たち(初学者)へ誰でも使えるように書き記します。

こんな感じでUITextfieldを選択すると、UIDatePickerが立ち上がって
日付を指定→指定した日付を出力させる方法についてのTips。
<img width="306" alt="スクリーンショット 2018-09-11 1.27.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/254495/17b25b17-38a1-abef-e7d5-1f5e116a3fe6.png">


# 日付を表示させるためのUITextfieldを準備
UITextfieldをstoryboardのuivewcontroller上に配置。
outletで接続しておきます。

```
 @IBOutlet weak var dateField: UITextField!
```

# 実際のコードがこいつ
```swift:BirthdayViewController.swift
import UIKit

class BirthdayViewController: UIViewController {

    //UITextfieldに紐づいてる
    @IBOutlet weak var dateField: UITextField!

    //UIDatePickerを定義するための変数
    var datePicker: UIDatePicker = UIDatePicker()


    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ピッカー設定
        datePicker.datePickerMode = UIDatePickerMode.date
        datePicker.timeZone = NSTimeZone.local
        datePicker.locale = Locale.current
        dateField.inputView = datePicker
        
        // 決定バーの生成
        let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 35))
        let spacelItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))
        toolbar.setItems([spacelItem, doneItem], animated: true)
        
        // インプットビュー設定(紐づいているUITextfieldへ代入)
        dateField.inputView = datePicker
        dateField.inputAccessoryView = toolbar
    }

    // UIDatePickerのDoneを押したら発火
    @objc func done() {
        dateField.endEditing(true)

        // 日付のフォーマット
        let formatter = DateFormatter()

        //"yyyy年MM月dd日"を"yyyy/MM/dd"したりして出力の仕方を好きに変更できるよ
        formatter.dateFormat = "yyyy年MM月dd日"

        //(from: datePicker.date))を指定してあげることで
        //datePickerで指定した日付が表示される
        dateField.text = "\(formatter.string(from: datePicker.date))"



    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
```

次回は指定した日付から年齢を取得できるようにします。
機械学習のために株価データを集める

#機械学習のためのデータを集める　2018/09


機械学習のために株価データが欲しい、でもデータの配布所がなかなかないため
データを集められる場所を集めてみました。

<dl>
<dt>1.yahooファイナス</dt>
   <dd>言わずと知れたyahooファイナンスの時系列データをコピペする。<br>
       ほぼ1度に30日分しか取れないのが欠点です。<br>
       じゃあ機械的に取得すれば！と思うかもしれませんが<br>
       参考記事にもありますが、yahooファイナンスは<br>
       <strong>スクレイピング禁止</strong>のためコピペ以上はやめましょう</dd>
</dl>
![yahoofinance.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/10c6aa46-5de1-d97d-4dac-6e8b171878e2.jpeg)

<dl>
<dt>2.ネット証券のサービスを利用</dt>
    <dd>これが現実的かと思います。私が確認できたサービスを載せます。
      基本的にネット証券は開設も口座の維持もタダです。
      ですが、サービスが気に入ったのであれば、入金＆株購入を考えましょう。
      薩摩守（タダ乗り）が増えるとサービス停止等もありますので・・・
      ただし、<strong>投資は自己責任でお願いいたします。</strong></dd>
</dl>
<dl>
<dt>2.1 松井証券</dt>
<dt>    ＜会社概要＞</dt>
<dd> 知らない人も多いですが日本で最初にネット証券を始めた会社です。
     現在ネット証券４位。松井社長はビジネス誌などで取り上げられることも多々。</dd>
<dt>    ＜利用方法＞</dt>
<dd>     HTML5をベースにしたネットストックスマートでログインします。
    「株価ボード」から「登録」で取得したい会社名や株価を入力します。
    ※日経平均は「101 日経平均」です。４桁の数字＋日経平均うんたらはETFです。
    「チャート」から範囲を指定して「CSV出力」します。
 </dd>
</dl>

↓以下画面のハードコピー（ログオン画面は省略）
![matsui1.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/69c73310-0a04-d851-faa3-a6bd2633412a.jpeg)
![matsui2.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/14814fa5-8e4c-81d9-0091-36a22d411711.jpeg)
![matsui3.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/0f2e38a9-dc5e-2790-b53a-43696b211728.jpeg)
![matsui4.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/107d3af5-08aa-4e69-f20c-c47f6a0df5a5.jpeg)
![matsui5.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/f302ce37-62a1-3ea3-4c0e-12543e28bfc2.jpeg)

＜結果＞
![matsui.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/ced846f1-7f93-e167-34f9-f0a1114089e7.jpeg)

＜読み込み＞

```
import pandas as pd
stock_data = pd.read_csv('stockchart_yyyymmdd.csv')
```

※yyyymmddにはダウンロードした日付が設定されます。

＜実行結果＞
![matsui6.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/c1e2fa91-3c1c-2536-0d89-78487af10cf0.jpeg)



<dl>
<dt>2.2 SBI証券</dt>
<dt>    ＜会社概要＞</dt>
<dd>    元々はソフトバンクの金融系の子会社です。
    （今は株は支配できるような量は保持していない）
    ネット証券首位。保険や銀行、仮想通貨なども行っています。</dd>
<dd>    ＜利用方法＞ 
    こちらはHYPER SBIというツールで取得します。
    ただし、これは<strong>信用口座も開くことでタダになる有料ツールです</strong>
    「個別チャート」から「時系列」を選び（小さい！）「CSV出力」します。</dd>
</dl>
↓以下画面のハードコピー（ログイン後から）
![SBI1.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/fea39168-e9a4-eceb-30bf-48fdc387b9e6.jpeg)
![SBI2.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/b035544e-12b0-d9f8-cd02-840116a06d3f.jpeg)

＜結果＞
![SBI.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/5f05b20d-3ed1-2abf-5347-424cd855e6cc.jpeg)

＜読み込み＞

```
import pandas as pd
stock_data = pd.read_csv('TimeChart.csv',encoding='cp932')
```



＜実行結果＞
![sbi3.jpg](https://qiita-image-store.s3.amazonaws.com/0/248083/d11349a1-a4f4-2ad1-a99b-5b41caea9875.jpeg)




3.その他
参考ページにある「株価データサイト k-db.com」様は2017年でサービス停止している模様です。





<参考>
日本株式のデータをスクレイピングなしで取得・リストにしたい
https://qiita.com/Kuma_T/items/911b5201c9313717ab50
DNSの勉強ノート【その3】フルサービスリゾルバとコンテンツサーバ

## はじめに

- 前回までのあらすじ
   - [DNSの勉強ノート【その1】名前解決](https://qiita.com/RyomaTaniyama/items/0a05316c5e1b4308af8e)
   - [DNSの勉強ノート【その2】A/CNAME/NS/MXレコード](https://qiita.com/RyomaTaniyama/items/6d8748e8096ea4f18b5b)

- 今回の内容
  - スタブリゾルバ
  - 優先ネームサーバと代替ネームサーバ
  - フルサービスリゾルバとコンテンツサーバ
  - ルートサーバ

## スタブリゾルバ

- ネームサーバにリクエストするクライアントのソフトウェアのこと。
- スタブリゾルバがネームサーバへドメインを問い合わせるとき、ドメインの指定は通常FQDNで行われる。
- ホスト名のみ指定され場合、スタブリゾルバはドメイン名を補完してFQDNを作る。このとき補完されるパスを **サーチパス** といい、通常ホスト自身が所属するドメインである。

![search_path.png](https://qiita-image-store.s3.amazonaws.com/0/288168/a21be3ff-a1a5-9919-8def-37dbbc60d738.png)

## 優先ネームサーバと代替ネームサーバ

- ネームサーバは通常、耐障害性の観点から2つ以上設定される。
- スタブリゾルバに複数のネームサーバを登録するとともに、通常問い合わせるネームサーバ（ **優先ネームサーバ** ）と、優先ネームサーバがダウンしたときに問い合わせるネームサーバ（ **代替ネームサーバ** ）を指定する。
- 複数のネームサーバの間で、キャッシュ情報に（IPアドレスの変更を反映していないなどの）矛盾があることがある。このとき、「ネームサーバは、自分が持つキャッシュが最新のものなのか」「スタブリゾルバは返却されたドメイン情報が最新のものなのか」を判断できない。

## フルサービスリゾルバとコンテンツサーバ

- Authorityを持つゾーン情報のみを返却するネームサーバを **コンテンツサーバ** という。rootドメインやレジストリのネームサーバがこれに当たる。
- 一方、ドメイン名前空間からドメインを検索するネームサーバを **フルサービスリゾルバ** という。
- フルサービスリゾルはリクエストに対応できるキャッシュ情報を持たない場合、ドメイン名前空間から検索してくる。そのため、フルサービスリゾルバはrootドメインのネームサーバを知っている必要がある。

![full_service_resolver_and_contents_server.png](https://qiita-image-store.s3.amazonaws.com/0/288168/b50cb4f7-038d-7251-8607-f3085828d4be.png)

## ルートサーバ

- rootドメインのネームサーバ（ルートサーバ）は、世界に13台存在する（`A.ROOT-SERVERS.NET`~`M.ROOT-SERVERS.NET`）。
- 最新のルートサーバ情報は **IANA** からルートヒントファイルとしてダウンロードしてくる。
- ルートヒントは、BINDでは`named.root`として管理される。
- 13台存在するルートサーバのうち、フルサービスリゾルバが問い合わせる対象は最も応答時間が短いもの。
   - フルサービスリゾルバは、ルートサーバと応答時間との対応表を持っている
   - 当初、それぞれの応答時間はランダムに設定されている
   - 以降、応答時間が最短のサーバに問い合わせるとともに、実際の応答時間で対応表を更新していく

## 再帰問い合わせと反復問い合わせ

- スタブリゾルバからフルサービスリゾルバに対するリクエストを **再帰問い合わせ** といい、フルサービスリゾルバからコンテンツサーバに対するリクエストを **反復問い合わせ** という。
- 再帰問い合わせに対するレスポンスは以下のいずれか。
   - ドメインに対応するIPアドレス
   - ドメイン名なし
- 反復問い合わせに対するレスポンスは以下のいずれか。
   - ドメインに対応するIPアドレス
   - ドメイン名なし
   - **ドメインを知っていそうなネームサーバ**

## つづく

## 参考文献

- 網野衛二 (2009) 『3分間DNS基礎講座』 技術評論社
pipenvを利用するときは、必ずPythonにパスを通すこと

Windows上のPythonでPIPENVを利用したらいろいろはまったのでメモ。

# そもそもpipenvとは
Pythonといえば`pip install`コマンドなどで簡単に様々なライブラリをインストールし使うことができますが、プロジェクトごとにどんなライブラリを使っているか、どのバージョンのライブラリを使っているかわかりにくくなるため、プロジェクト別の管理が必要になることがあります。

PHPのComposerなどのように、あらかじめプロジェクト内にライブラリをダウンロードし、ほかのプロジェクトとの衝突をなるべく避けたい。そんな時に便利なのがpipenvです。

# 参考

* [既存プロジェクトに pipenv を導入した方法 \- Qiita](https://qiita.com/tonluqclml/items/b09f4a5ed04ebcbd0af1)
* [Windows \+ Python 3\.6 \+ PipEnv \+ Visual Studio Code でPython開発環境 \- Qiita](https://qiita.com/youkidkk/items/b6a6e39ee3a109001c75)

# やろうとしたこと

とりあえずpipenvのごくごく基本的な利用方法については上記記事を読んでもらうとして、pipenvを使えばプロジェクトごとに必要なライブラリをダウンロードした仮想環境(venv)を作ることができます。

この環境で実行することで、ライブラリのバージョンがほかのものと衝突するという問題を防げるほか、ほかのPCで作業を続行する際の環境構築が容易になります。

今回はこのpipenvを使って、いくつかのライブラリをダウンロードした環境でスクリプトを実行しようとしました が、上手くいかずに2，3時間ほど悩みました。

## 何が上手くいかなかったか

仮想環境上にダウンロードしたライブラリが全く読み込まれない という問題が発生しました。

その後何度か試行錯誤し、とりあえずデバッグ実行したときはうまく動作することがわかりましたが、通常通りスクリプトを実行しようとしたときは一切ライブラリを読み込みませんでした。

### 動かなかった原因

いろいろ調べた結果、とりあえず以下の要因があることがわかりました。

* Pythonにパスを通さず、`C:\Windows\Py.exe`を経由でPythonを実行しようとしていたこと
* 実行時PYTHONPATHに、仮想環境のフォルダ(.venv)が含まれていなかったこと

`pipenv install --dev`コマンドを実行後、`pipenv shell`を実行し、そのままプロジェクト内のPythonスクリプトを実行しようとしていたのですが、それではPYTHONPATHに仮想環境のフォルダが含まれないようです。

### やってわかったこと

* pipenvを使う場合は、必ずPythonにパスを通すこと(Py.exeは使わないこと)
* プログラムを実行するときは、`pipenv run [任意のコマンド]`というふうにコマンドを指定すること(たとえば`pipenv run python .\main.py`/長いなと思った場合、上記記事に書かれているとおり、PipFileのscriptsセクションにコマンドを追加すること)
* もし`pipenv`とだけコマンドを入れて動かない場合は、パスが通っていない可能性が高いので、一度Pythonをアンインストールして、公式のインストーラよりインストールし直すと良いかもしれません(ついでに念のため、一度PCからサインアウトするか、再起動することをお勧めします)

`pipenv shell`は結局どう使うのかわかりませんでした。どうすれば良かったのだろう？(一応`pipenv shell`でShellを切り替え直後に、pythonコマンドでインタラクティブモードを起動すると、そこでは仮想環境にパスが通った状態でpythonが起動するようですが…)
[短文メモ][小ネタ]Pythonのenumerateで、インデックスを途中から始める

実は第二引数`start`を指定すると、インデックスを途中から始められる。

```py3
for i, c in enumerate("abc", 1):
    print(i, c) # => "1 a", "2 b", "3 c"
```

こういうとき便利だけど、ちょっと冗長。

```py3
for i, x in enumerate(arr[offset:], offset):
    pass
```

参考: [公式ドキュメント](https://docs.python.jp/2/library/functions.html#enumerate)
私がプログラミングの勉強をするときの手順とか使うサービスとか

# はじめに
この記事では私がプログラミングの勉強をするときに使う（使った）サービスや手順を紹介します。
といってもそんな特別なことは書かないと思うのでどっかの誰かの参考になれば程度で読んでください。

なにか技術を身につけるとき
なにかをインプットする→
インプットした知識をアウトプットする→
アウトプットするのに足りなかった知識をインプットする→
またアウトプットするということの繰り返しになると思います。

ここではその最初のインプットするのに使ってるサービスややり方を紹介します

## インプット時期１
### ドットインストール

https://dotinstall.com/

動画で環境構築からプログラミングまで紹介してくれるサイト
いまは有料、無料問わず動画で技術紹介してくれるサイト、サービスっていうのはたくさんあるけどかなり昔からある印象
自分のPCに環境構築から初めてプログラミングの勉強までできると思う。
確か課金したりすると追加でサービスを受けられるけど課金はしてないです。
### 学びたい言語の～入門的なサイト
これはすべての言語とかを網羅したサイトはないと思うので各自ググってくださいって感じ
俺は「～を勉強するのにおすすめのサイト」とかを紹介しているサイトなどを使って、その中でいくつも紹介されてるのをピックアップして２～３個ブクマしてます。
動画と違ってこの手のサイトを最初から最後まで読むとつかれるので辞書的な使い方をするべきですかね。
たださらーと読んでおくといいかもしれません。
あとこのサイトは一通りコーディングできるようになるといらなくなるのでそしたらブクマから削除してもいいと思います。
## アウトプット時期１
### progate

https://prog-8.com/mypage

かなり初歩的な内容から丁寧に解説しながらプログラムの勉強ができるサイト
いいところは
・無料でも利用できる（有料分も安価）
・プラウザ上で実行できるためローカルに開発環境を作成できる
・WEBサービスを作るのに必要なHTML、CSS、JavaSclipt、PHP、SQLとかとかは一通り揃ってる
悪いところは
・そこまでレベルは高くない
　このサイトを最大限利用してもだいたい入門書とか入社研修を終えたレベルくらいかなと
・対象になってる言語は多くない
　例えば私は仕事でC#使うことになって調べたけどなかった
書いてておもったけどこれはインプットかもね。
一応学習みたいなのがあってそれが上がっていくのが楽しいし、ある種の成果として残るのでアウトプットに分類
### paizaラーニング

https://paiza.jp/challenges

プログラミングの問題を出してくれるサイト
特に俺はなにか作ろうってなってもそもそも何を作ればいいの？ってなってしまうので作るものを提示してくれるのはとてもありがたい。
これもプラウザ上で実行できるので自前の環境を作る必要はないです。
ただコメントの記入ができなくてB以上のランクの問題を書く場合、コメントなしっていうのは実際良くないと思うので私はローカルの環境で作って終わったら流してます。
二度手間になるのでAの問題とかやってると時間オーバーします（笑）
でも仕事でやるときコメント一切書かないっていうのはないと思うので
paizaで高得点を取ることが目的ではないのでいいかな？って考えてます。
## インプット時期２
大きく分けるとここでやることは２つ
### アウトプットして不十分だと感じた情報を再度インプットし直す
例１）paizaとかで問題といたやつを数日置いて見直す
自分で書いたコードでも数日置けば他人が書いたようなもんです（笑）
もっと良い処理にできないか考える
処理時間が遅いとかで減点されてたらどうすればいいんだろうとか考える。
例２）参考書とかで読み飛ばしてた内容をなぜだか考え直す。
たとえば文字列連結でString型で連結しないでStringBufferでappendするのかとか
### なにか作るのに必要な情報を調べる
この次になにかアプリケーションを作ります。
そこで必要な情報を調べます。
上記で開発環境を作ってなかったらどうすればいいか調べます。
そのほかせっかくなら画面、DBもほしいなってなるのでそこらへんの環境構築方法も調べます。
## アウトプット時期２
アプリケーションをなんか作ります。
以上！！！！

というわけにもいかないので私が気をつけてる点をいくつか記載します
作りたいものがある方はそれを作ってみるといいと思います
ない方は
・検索画面、登録画面、更新画面がある（CRUD処理がある）
・MVCモデルになっている
みたいな基本的な要素を抑えてるアプリであれば何でもいいと思います
なにかの商品を検索・参照できて登録画面から登録できるとか
掲示板みたいなものとか・・・
YAMAHAの設定/操作メモやコマンド日本語訳(RTX１２００やらFW１２０やら)


## はじめに
お仕事でYAMAHAを弄る機会があったのでRTX1200を自前で買ってみたり、FWの設定を実機で設定してみたりのメモとか所感。
手元にメモにはいっぱい書き溜めてあるけど順次更新していく。特にコマンド周辺。コマンドが独特で結構こんがらがるので他のページよろしく日本語訳していく所存。そのうちつまったところとかも書いていきたい。

## お家でYAMAHAルータのルーティング
（マンションなのでプロバイダ情報とかはない）

①【コントロールパネル】からPCのIPアドレスを192.168.100.X(Xは1以外の任意の数字）で設定する。
②ブラウザを開き、「192.168.100.1」と入力。IDとパスワードは工場出荷時はないのでEnterを連打。

③【■初期設定】のウィザードだけをやる。

④【■ルーター機能】-【インターフェース】-【・静的経路の設定】で追加ボタンを押す。

⑤デフォルトをマンションのルータのIPに設定してエンド。
※ブラウザの更新ボタンを一度押さないと適用されない説あるのでやっておこう。

## とりあえずバージョンアップしとこう
マニュアルに書いてあるバージョンアップファイルが置いてある今のサイトは消えてるようなので[ここからbinファイルをダウンロード](http://www.rtpro.yamaha.co.jp/RT/firmware/firmware.php?model=rtx1200&rev=1001)してUSBにぶち込んでマニュアルに書いてある方法で読み込ませんとする

※最初にコマンドで一時間できないできないとうんうんうなってどうやらマニュアルに書いてあったURLが切れていたっぽい？

最終的にUSBに最新バージョンのbinファイルをぶち込んで一番上のファイルにしてRTX1200本体のUSBボタンとDownloadボタンを同時押しして5分くらい待つ。これが最強じゃった。



## コマンド（順次追記）
### コンフィグを取得する
`show config`

###表示する行数を無制限にする
`console lines infinity `

###　特権モード
`Administrator`
（直後にパスワードを求められるので管理者用パスワードを入力する）

### 保存する
`save`
### インターフェースlan2のNATルール１～２を定義
`ip lan2 nat descriptor 1 2`


### NATテーブルを表示する
`show nat descriptor address all`

### 文字化けしてるときに打つと解決するかも
`console character ascii`
Pythonで藤原竜也になりたい

# 藤原竜也になりたい

```python:tatsuya.py
tatsuyaChar = '゛'
beforeText = input("Please Text\n")
print(f"{tatsuyaChar.join(list(beforeText))}{tatsuyaChar}")
```

```:実行結果
Please Text
僕はキラなんかじゃない！！信じてくれよおおおおおお
僕゛は゛キ゛ラ゛な゛ん゛か゛じ゛ゃ゛な゛い゛！゛！゛信゛じ゛て゛く゛れ゛よ゛お゛お゛お゛お゛お゛お゛
```

3行でできました。「゛」を変数じゃなくすれば2行でできますね。
pythonはすごいですね。

追記:続きを書きました。[藤原竜也になりたい2](https://qiita.com/Euglenach/items/8b17ac2338f90d7b13c2)
swift4で宇宙船演算子を実装してufo気分を味わう その2

[これ](https://qiita.com/fumihiko-hidaka/items/2d91367bc13366760d30)の続き！

# nullableの比較ができない！

という致命的な問題が！
というわけでnullを最小の値として考慮する形で実装し直してみました。

```nil_ufo.swift
public func <=> <T: Comparable>(lhs: T?, rhs: T?) -> Int {
    if lhs == rhs {
        // 両方とも値が同じ場合は入れ替えない
        return 0
    }

    if lhs == nil || rhs == nil {
        // どちらかにnilがある場合
        return lhs == nil ? -1 : 1
    }

    let lhsValue: T! = lhs
    let rhsValue: T! = rhs

    // 昇順
    return lhsValue > rhsValue ? 1 : -1
}
```

今度こそ正しくufo気分を味わえた・・・はず！
iOSDCで発表した「UIViewとUITextInputで作る縦書きのTextView」について

## はじめに

iOSDC Japan 2018で「UIViewとUITextInputで作る縦書きのTextView」というタイトルで発表しました。発表資料は[こちら](https://speakerdeck.com/cc4966/vertical-textview-based-on-uiview-with-uitextinput)。動画は入ってません。

さて。この記事では、以下の3つを書きます。

- 発表の概要
- 発表の補足
- iOSDCの感想

## 発表の概要
- TextViewとは何か
    - IME/キーボードからのテキストを受け取ることができるView
    - 人間向けのフィードバックとしてテキストが表示されるView
- IME APIとは何か
    - IMEとViewの間に立ってテキスト入力を可能にするOS (GUI) の仕組み
    - IMEとViewがお互いの実装を知らずに動作可能になる
- UITextViewは実装できるか
    - どれも実装可能
    - 実装されるレイヤが多岐にわたるので注意
- iOSでの縦書きTextViewの注意点
    - できることは少ない
    - スマホでの縦書きはソフトキーボードとの領域の奪い合い

## 発表の補足
発表後にこういう反応がありました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自分が実装したときは拡大レンズになるときがいまいち分からず放置していたんだけれど、自前で実装でいいのだろうか。なんかかな漢字変換中に触ったりすると拡大レンズ表示されたりするからちゃんとプロトコル実装すればOSが出してくれるものかと思っていたけれど。 <a href="https://t.co/ED3royD72K">https://t.co/ED3royD72K</a></p>&mdash; ゆいしろ (@lifeaether) <a href="https://twitter.com/lifeaether/status/1036412047477497858?ref_src=twsrc%5Etfw">2018年9月3日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

そうなんです。
未確定文字列のときとそれ以外の時で、選択範囲を決めるという行為の持つ意味が大きく違うのです。
（このツイートを見るまで完全に忘れていた。情報を発信すると情報が集まってくるってこういうことなんですね）

具体的にどういうことかというと、

- 未確定文字列のないとき
    - キーボードがタッチイベントを奪うことはない
        - タッチイベントに基づく選択範囲の変更はすべてTextView側が行う
    - 選択範囲を変える＝特に何もおきない（キーボードの予測変換が変わるくらい）
- 未確定文字列があるとき
    - キーボードが未確定文字列の範囲のタッチベントを奪う
        - タッチイベントに基づく未確定文字列内の選択範囲の変更はキーボード側が行う
    - 選択範囲を変える＝未確定文字列が確定される

なので拡大鏡はキーボードが出すこともあるので、未確定文字列への縦書き対応は全然できないねということです。
悲しいですね。

## iOSDCに参加して
iOSDC楽しかったです。
iOSの知らなかった話や、よく覚えのある話といったのをたくさん聞けたのはもちろんiOSアプリ開発をしてる人はこんなにいるんだなーというのを実感とともに知ることができました。
他にも

- ランチが美味しい（特にニューヨークチキンライスが良かった）
- ネットワークが快適（グローバル IPが降ってくるやつは使わなかった）
- 会場・企画説明などの各種動画（ナレーションが声優さんなので聞いててなんか楽しい）

といった感じでした。

今回、縦書きエディタの話をしましたが、実はTATEditorに関連した話を外で発表するのは初めてでした。発表するまで、果たして縦書きエディタの話に興味ある人は世界のどこにいるんだろうと思ってましたが、興味のある人に聞いてもらえたようで良かったです。
発表後、縦書きやってるよという話もいくつか聞けました。残念ながら、縦書きエディタやってるよという話まではついぞ聞けませんでしたが。

来年もiOSDCで発表できたらいいなあ（何か話せることあるかな）。

##  おわりに
発表資料を作る過程でIME APIを中心にした、ViewとTextViewの関係についてまとまって自分の中でも色々と整理ができて良かったです。
なんかクロスプラットフォームなIME APIライブラリも意外と書けるのかも？という気が少ししました。

そういえばAndroidでも縦書きエディタ作ってるので、DroidKaigiにも応募しようかなと思ってます。

### 余談。

iOSDCのAsk the Speakerで、macOSの縦書きTextViewはどうやって縦書きであることを伝えるのかという話をしたらこういうツイートになって返ってきました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/iosdc?src=hash&amp;ref_src=twsrc%5Etfw">#iosdc</a> で <a href="https://twitter.com/496_?ref_src=twsrc%5Etfw">@496_</a>さんに縦書きエディタの話を聞いたので、縦書きモードでも変換候補ウインドウがテキストにかぶらないように修正できた。(iOSとは) <a href="https://t.co/ayPLn0LBDJ">pic.twitter.com/ayPLn0LBDJ</a></p>&mdash; mzp (@mzp) <a href="https://twitter.com/mzp/status/1035896027797061632?ref_src=twsrc%5Etfw">2018年9月1日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>