OmniAICreator/Qiita-1.07M huggingface dataset:
Haskell入門ハンズオン! #5 - 当日用資料 (4/5)

Haskell入門ハンズオン #5 - 当日用資料 (4/5)
======================================

[その1はこちら](https://qiita.com/YoshikuniJujo/items/94647877c6bc02beb961#_reference-0feae16207cc35e4f20b)

演習課題の説明
------------

これから5題の演習問題を解いていただく。

* 演習1. Hello, world!
* 演習2. 再帰、またはリスト
* 演習3. 代数的データ型
* 演習4. 型クラス
* 演習5. 計算クイズ

できなくても、問題ない。「考えてみる」ことで、あとの説明を理解しやすくなるので。わからないところは質問してください。

### 演習1. Hello, world!

「Hello, world!」を標準入出力(画面)に書き出す。

1. コードを作成する
2. コンパイル・実行する

文字列を標準出力に書き出す関数はputStrLnだ。変数mainを束縛する(に代入された)入出力が実行される。コンパイルは、つぎのようにする。

```terminal
% stack ghc -- hello.hs -o hello
```

ちなみに、僕はタブ文字への警告を消したいので

```terminal
% stack ghc -- -fno-warn-tabs hello.hs -o hello
```

### 演習2. 再帰、またはリスト

1からnまでの積をもとめる。

1. 関数を作成する
2. 対話環境で試してみる

作成する関数は「再帰関数」になる。つぎのように試す。

```terminal
% stack ghci
```

```
> :load product.hs
> productN 5
120
```

### 演習3. 代数的データ型

円と長方形を含む型を作成し、面積をもとめる。

1. 円と長方形を含む型を作成する
2. それらの面積をもとめる関数を作る

つぎのように使用できるようにする。

```
> Circle 3
Circle 3.0
> Rectangle 4 7
Rectangle 4.0 7.0
> area (Circle 3)
28.274333882308138
> area (Rectangle 4 7)
28.0
```

* ヒント1: データ型の定義の末尾にderiving Showをつける。対話環境で表示するため。
* ヒント2: 関数areaの定義にはパターンマッチを使う

### 演習4. 型クラス

Bool型の値以外を真偽値として使う。

1. 「Bool値(False, True)に変換できる」性質を示す型クラスを定義する
    * 型クラスBoolLikeはクラス関数toBoolをもつ
2. 型Integerを型クラスBoolLikeのインスタンスにする
    * toBool 0はFalse
    * toBool xはxが0でなければTrue
3. 型Charを型クラスBoolLikeのインスタンスにする
    * toBool '\NUL'はFalse
    * toBool cはcが'\NUL'でなければTrue
4. 型クラスBoolLikeのインスタンスである型の値を、真偽値として使用するmyIfを作成する

つぎのように使えるようにする。

```
> toBool (0 :: Integer)
False
> toBool (3 :: Integer)
True
> toBool 'c'
True
> toBool '\NUL'
False
> myIf 123 "OK!" "Bad!"
"OK!"
> myIf '\NUL' "OK!" "Bad!"
"Bad!"
```

### 演習5. 計算クイズ

たし算、ひき算、かけ算の練習用ソフトを作成する。仕様は、つぎのようにする。

* 計算はつぎの3種類
    + 0から100までの整数どうしのたし算
    + 0から100までの整数どうしのひき算
    + 0から9までの整数どうしのかけ算
* これらのなかからランダムに10問出題する
* ユーザはそれに対する答えを入力
* 正答か誤答かを表示
* 最後に何問正解したかという結果を表示する

[その5へ](https://qiita.com/YoshikuniJujo/items/f601195d44aeafc0fadb)
PyOCRでモジュールは入ってるはずなのにImportError: No module named 'pyocr.builders'; 'pyocr' is not a packageというエラーが表示されるときは呼び出し元スクリプトのファイル名がpyocr.pyになっている

# タイトルで全部言っちゃうスタイル

5分なやんだ。
プロキシの証明書を信用させる

# はじめに

[BurpSuite](https://portswigger.net/burp), [ZAP](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project), [Fiddler](https://www.telerik.com/fiddler) は、SSL の通信を解読しながら転送するプロキシツールで、デバグ/セキュリティ診断で使われている

最近、オレオレ証明書のままだと、(診断対象外のドメインの)外部JSを読まない(「オレオレだから危険承知でアクセスしてね」ダイアログがHTMLページの内部処理(XHRなど)なので表示されない)で、エラーとなるケースが結構多いので、そろそろプロキシの証明書を認証局として信用させる方法をメモしておく

# プロキシの仕組み

- SSL の証明書とドメイン名が一致しないと信用されない(オレオレ証明書)。
- プロキシは、認証局を立ち上げ、接続先ごとに動的に証明書を生成(証明書のドメインと接続先が一致する)するようにしている。こうする事で、証明書エラーがでない。
- 当然、Webブラウザに提示される証明書の指紋(フィンガープリント)などは異なるけど、そんなことは誰も気にしない
- このためにプロキシの証明書(プロキシの認証局の証明書)をブラウザに信頼させる必要がある。

# BurpSuiteの場合

- 証明書をエクスポートして、ブラウザごとに信頼させる
- 特に、Firefox(Windowsの場合)は、独自に管理しているので、Windowsに信頼させておしまい。という事ではない点に注意
- Firefoxでも信頼させれはいい

![burp.jpg](https://qiita-image-store.s3.amazonaws.com/0/182822/35c62685-a08f-6940-8a40-b3e3af34f622.jpeg)

# ZAPの場合

- 証明書をエクスポートして、ブラウザごとに信頼させる
- 特に、Firefox(Windowsの場合)は、独自に管理しているので、Windowsに信頼させておしまい。という事ではない点に注意
- Firefoxでも信頼させれはいい

![zap.jpg](https://qiita-image-store.s3.amazonaws.com/0/182822/bd286874-f7ec-9c08-3cc7-78b43e98515e.jpeg)

# Fiddlerの場合

証明書を信頼させるためのメニューがある

![Fiddler.jpg](https://qiita-image-store.s3.amazonaws.com/0/182822/0daaba9e-4ebd-8571-0474-e579dc71ddd7.jpeg)

ただし、このメニューだと Firefox には信頼されないと思う(Firefoxは独自管理だから)

# タンデムにしてもよいと思う

Fiddlerは簡単に信頼させられるので、使いやすいプロキシとタンデムにして運用するのも**アリ**だと思う

つまり

`Webブラウザ⇔Fiddler⇔BurpSuiteまたはZAP⇔Webアプリケーション`

な感じ。

# Index

[Indexへ戻る](https://qiita.com/tomoki0sanaki/items/258d6e77e4b16bc7d1c9)

# 以上
Macでフォルダの中にある画像を一括で ".eps" にするシェル置いときます

# はじめに
Macで任意のフォルダの中にある画像の拡張子を全てepsに変換するシェル作ったので置いときます
卒論とか修論とかで使えるのではないでしょうか

# 現状のフォルダ構成
カレントディレクトリに `convert.sh`ファイル および `images` フォルダを作成してください
imagesフォルダの中には，変換したい画像を全て入れてください


# Macにconvertコマンドをインストール
以下を，参考にしてみてください．
https://qiita.com/sowd/items/832594dd22d99aebc8a2

# シェルスクリプト作成
```shell:convert.sh
for file in `\find ./images -maxdepth 1 -type f`; do
    # 元のファイルを取り出す(拡張子なし)
    before_image="${file%.*}"
    before_image="${before_image}."
    # 元のファイルの拡張子を取り出す
    before_image_extend="${file##*.}"
    # convert
    after_image="${before_image}eps"
    convert $before_image$before_image_extend $after_image
done
```

# 実行
`$ chmod 755 convert.sh`
`$ ./convert.sh`

# 終わりに
もっとこうすればいいのではないかなどの，アドバイスよろしかったらお願いします．
お聞き下さいましてありがとうございました．:sunny:
Unityメモ: Win10 + iOS端末でunity remote動かない件

# 動かない状態

* Widows10 ＋ Unity 2018.3.0f2 (+ iTunes)
* iPad(iOS12.1.1) + Unity Remote 5

iPadをUSB接続しても、Unityで認識してくれない。
Edit > ProjectSetting の Editor > Unity Remote : Device の候補に端末名が出ない。
`Any iOS Device` を選ぶと、`EntryPointNotFoundException` などとエラー表示される。

# 動いた

* Unityの旧ver（私は2017.2.5.f1にした）をインストールして、
* (旧ver)/Editor/Data/PlaybackEngines/iOSSupport にある、`x86_64` をフォルダごとコピー、
* (現ver)/Editor/Data/PlaybackEngines/iOSSupport にペースト。

Device の候補に端末名が出てきた。
選択したら、エラー等も無く、想定通り動作した。

## 情報元
[[WINDOWS] UNITY REMOTE 5 DOESN'T WORK ON IOS BECAUSE THE X86_64 FOLDER IS MISSING FROM PLAYBACKENGINES\IOSSUPPORT](https://issuetracker.unity3d.com/issues/windows-unity-remote-5-doesnt-work-on-ios-because-the-x86-64-folder-is-missing-from-playbackengines-slash-iossupport)
このバージョンだとこのフォルダにあるぞ、とかいうコメントがついている。

# 最新情報
上記掲示板では **Fixed in Unity 2019.1** とあるので、たぶんもう大丈夫なんでしょう。
まだバージョンアップしてないので、未確認。
というか現時点(2019年2月アタマ)まだアルファ版だった。

そのフォルダが配布から漏れただけの問題っぽいし、解決してるでしょうよ。
ionic4で@ionic-native/cameraが使えないときの対処法

## エラーの内容
以下を実行してもcameraモジュールが使えない(2019/1/30日現在)

```bash:console
$ ionic cordova plugin add cordova-plugin-camera
$ npm install @ionic-native/camera
```

```typescript:app.modules.ts
import { Camera } from '@ionic-native/camera';

providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    Camera
]
```

エラーメッセージ
`Type 'CameraOriginal' is missing the following properties from type 'FactoryProvider'`

## 原因
@ionic-native/coreのバージョンが5.0.0より低い

## 対処法
@ionic-native/coreのバージョンを上げる 
「@」以降のバージョン指定は適宜書き直してください。

```bash:console
npm i --save @ionic-native/core@5.0.0
npm i --save @ionic-native/splash-screen@5.0.0
npm i --save @ionic-native/status-bar@5.0.0
ionic cordova plugin add cordova-plugin-camera
npm install @ionic-native/camera
```

```typescript:app.modules.ts
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { Camera } from '@ionic-native/camera/ngx';

providers: [
    StatusBar,
    SplashScreen,
    Camera,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
]
```

import元のディレクトリが「@ionic-native/camera」から「@ionic-native/camera/ngx」になっていることに注意してください。
Heroku ConnectのDBをローカルDBに復元

1. HerokuのPostgreをバックアップ ＆ バックアップデータのURL取得
    1. `heroku pg:backups capture --app ＜アプリ名＞ && heroku pg:backups public-url --app ＜アプリ名＞`
1. バックアップデータのURLをブラウザに入力してバックアップデータをダウンロード (出力ファイル名は「herokudb.backup」とする) 
    1. wgetで行う場合
        1. wgetをインストール (Chocolatelyを使っていれば`cinst -y wget`)
        2. wgetでバックアップデータをダウンロード `wget "＜バックアップデータのURL＞" -O herokudb.backup`
1. ローカルDBを準備 (ローカルDB名は「herokudb」、スキーマ名は「salesforce」とする)
    1. ローカルDBが存在していれば削除、ローカルDB作成
        1. `psql --username postgres -c "DROP DATABASE IF EXISTS herokudb" && psql --username postgres -c "CREATE DATABASE herokudb"`
    1. (初回のみ)ユーザ作成 ※バックアップデータの中にHeroku ConnectのHerokuのPostgreのユーザ名があるので一致させる
        1. `psql --username postgres -c "CREATE ROLE ＜(HerokuのPostgreの)ユーザ名＞ WITH LOGIN PASSWORD '＜パスワード＞'"`
1. バックアップデータをローカルDBにリストア
    1. `pg_restore --dbname=herokudb --username=postgres herokudb.backup`
1. 不要なテーブル・トリガー・Functionを削除
    1. (初回/テーブル増減時)後掲のdrop_objects.sqlファイルを作成/編集
    1. `psql --dbname=herokudb --username postgres --file drop_objects.sql`

```drop_objects.sql
-- スキーマ名が「salesforce」の例
DROP TABLE salesforce._hcmeta;
DROP TABLE salesforce._sf_event_log;
DROP TABLE salesforce._trigger_log;
DROP TABLE salesforce._trigger_log_archive;

-- スキーマ名が「salesforce」の例、テーブル毎に追記
DROP TRIGGER hc_account_logtrigger ON salesforce.account;
DROP TRIGGER hc_account_status_trigger ON salesforce.account;
DROP TRIGGER hc_case_logtrigger ON salesforce.case;
DROP TRIGGER hc_case_status_trigger ON salesforce.case;
DROP TRIGGER hc_contact_logtrigger ON salesforce.contact;
DROP TRIGGER hc_contact_status_trigger ON salesforce.contact;
DROP TRIGGER hc_group_logtrigger ON salesforce.group;
DROP TRIGGER hc_group_status_trigger ON salesforce.group;
～以下略～

-- スキーマ名が「salesforce」の例、テーブル毎に追記
DROP FUNCTION salesforce.tlog_notify_trigger();
DROP FUNCTION salesforce.hc_capture_insert_from_row(hstore,varchar,_text);
DROP FUNCTION salesforce.hc_capture_update_from_row(hstore,varchar,_text);
DROP FUNCTION salesforce.hc_account_logger();
DROP FUNCTION salesforce.hc_account_status();
DROP FUNCTION salesforce.hc_case_logger();
DROP FUNCTION salesforce.hc_case_status();
DROP FUNCTION salesforce.hc_contact_logger();
DROP FUNCTION salesforce.hc_contact_status();
DROP FUNCTION salesforce.hc_group_logger();
DROP FUNCTION salesforce.hc_group_status();
～以下略～
```

＜コピペ用＞
heroku pg:backups capture --app ＜アプリ名＞ && heroku pg:backups public-url --app ＜アプリ名＞
wget "" -O herokudb.backup
psql --username postgres -c "DROP DATABASE IF EXISTS herokudb" && psql --username postgres -c "CREATE DATABASE herokudb" && pg_restore --dbname=herokudb --username=postgres herokudb.backup && psql --dbname=herokudb --username postgres --file drop_objects.sql

＜おまけ＞
SLA(downtime) https://devcenter.heroku.com/articles/heroku-postgres-plans#plan-tiers
[Swift]inoutの引数に渡した変数は常に willSet/didSet が呼ばれる

`inout` の引数に渡した値は、関数の中で何もしなくても常にコピーされます。

# 確認に使ったコード

```swift
func doNothing(_ i: inout Int) { }

var n = 0 {
    didSet { print("did set \(n)") }
}

doNothing(&n)
doNothing(&n)
doNothing(&n)
```

```plaintext:出力
did set 0
did set 0
did set 0
```

# mutating な関数も同じ

`mutating` な関数は `self` が `inout` で渡されるので同じことが起きます。

```swift
struct Natural {
    var value: Int
    
    mutating func decrement() {
        guard 0 < value else { return }
        value -= 1
    }
}

var nat = Natural(value: 3) {
    didSet { print("did set \(nat)") }
}

nat.decrement() // 2
nat.decrement() // 1
nat.decrement() // 0
nat.decrement() // なんとなく didSet が起きないような気がする
```

```plaintext:出力
did set Natural(value: 2)
did set Natural(value: 1)
did set Natural(value: 0)
did set Natural(value: 0) ← わお
```

# The Swift Programming Language

Property Observers セクションに明記されていました。
https://docs.swift.org/swift-book/LanguageGuide/Properties.html

> If you pass a property that has observers to a function as an in-out parameter, the willSet and didSet observers are always called. This is because of the copy-in copy-out memory model for in-out parameters: The value is always written back to the property at the end of the function. For a detailed discussion of the behavior of in-out parameters, see In-Out Parameters.
fitbitのデータをpythonで取る



殴り書き。


	today = datetime.date.today()
	
	
	import fitbit	
	fitbit = fitbit.Fitbit(APPID, APPSECRET, access_token = TOKEN1, refresh_token = TOKEN2)

	fitbit.get_sleep(today)

	fitbit.time_series('sleep/minutesAfterWakeup', base_date=today,period="1m")
	fitbit.time_series('sleep/minutesAsleep', base_date=today,period="1m")
	fitbit.time_series('sleep/minutesAwake', base_date=today,period="1m")
	fitbit.time_series('sleep/minutesToFallAsleep', base_date=today,period="1m")
	fitbit.time_series('sleep/timeInBed', base_date=today,period="1m")
	fitbit.time_series('sleep/startTime', base_date=today,period="1m")
	fitbit.time_series('sleep/awakeningsCount', base_date=today,period="1m")
	fitbit.time_series('sleep/efficiency', base_date=today,period="1m")

	fitbit.time_series('body/bmi', base_date=today,period="1m")
	fitbit.time_series('body/fat', base_date=today,period="1m")
	fitbit.time_series('body/weight', base_date=today,period="1m")

	fitbit.time_series('foods/log/caloriesIn', base_date=today,period="1m")
	fitbit.time_series('foods/log/water', base_date=today,period="1m")

	fitbit.time_series('activities/heart', base_date=today, period='1m')

	fitbit.time_series('activities/calories', base_date=today, period='1m')
	fitbit.time_series('activities/caloriesBMR', base_date=today, period='1m')
	fitbit.time_series('activities/steps', base_date=today, period='1m')
	fitbit.time_series('activities/distance', base_date=today, period='1m')
	fitbit.time_series('activities/floors', base_date=today, period='1m')
	fitbit.time_series('activities/elevation', base_date=today, period='1m')
	fitbit.time_series('activities/minutesSedentary', base_date=today, period='1m')
	fitbit.time_series('activities/minutesLightlyActive', base_date=today, period='1m')
	fitbit.time_series('activities/minutesFairlyActive', base_date=today, period='1m')
	fitbit.time_series('activities/minutesVeryActive', base_date=today, period='1m')
	fitbit.time_series('activities/activityCalories', base_date=today, period='1m')

	#2019/02/26追記。目標の睡眠時間を取る。apiが用意されておらず、プリミティブな関数を直で呼ぶ
	fitbit._resource_goal('sleep')
Dataproc で BigQuery からのデータ読込に失敗する事象への対応

## 概要
以前動いていた Dataproc の PySpark ジョブが失敗する事象が今月中旬から発生していたので対応しました。似たような事象に合ってる人もいるかもしれないなと思ったので簡単にまとめておきます。

内容は下記の通りです。

1. 問題：2019年1月中旬から Dataproc の PySpark ジョブが BigQuery からのデータ読込の部分で失敗するようになっていた
2. 原因：Dataproc のデフォルトのイメージバージョンが 1.3 に変わった (デフォルトで BigQuery コネクタが入っていない)
3. 対応：jar を指定してジョブ送信することで BigQuery からのデータ読込に失敗しないようになった

## 問題
BigQuery からデータを読み込んで処理する PySpark ジョブを一昨年ごろ[こちらのドキュメント](https://cloud.google.com/dataproc/docs/tutorials/bigquery-sparkml?authuser=1&hl=ja) 等を参考に作った[^1]のですが、それが最近失敗するようになりました。

[^1]: ちなみに記事を書くにあたって改めてドキュメントを読んだら、ちゃんと今回の事象に関連する記述が追記されてましたね。事前準備の項目に「Cloud Dataproc バージョン 1.3 以降（サポートされている Cloud Dataproc バージョンを参照）を使用している場合は、BigQuery コネクタをインストールします。」と記載されています。




ジョブのエラーログを見てみると、下記の部分で

```python
table_data = spark.sparkContext.newAPIHadoopRDD(
    "com.google.cloud.hadoop.io.bigquery.JsonTextBigQueryInputFormat",
    "org.apache.hadoop.io.LongWritable",
    "com.google.gson.JsonObject",
    conf=conf)
```

下記のエラーが発生していました。

```
java.lang.ClassNotFoundException: com.google.cloud.hadoop.io.bigquery.JsonTextBigQueryInputFormat
```

今月中旬に初めてこのエラーが発生したんですが、１つ紛らわしかったのは、その時は再実行したらジョブが成功してしまったんですよね・・。優先度が高くないジョブだったこともあり、その時はそれで「何か Google 側の不調があったのかな？」程度に思って様子見としてしまいました。

## 原因
Dataproc 1.3 ではデフォルトで BigQuery コネクタが入らないようになったのが原因のようです。

[リリースノート](https://cloud.google.com/dataproc/docs/release-notes)によると 2019/1/4 からデフォルトの Dataproc バージョンが 1.3 になっているようです。

> Beginning 2019/01/04, Cloud Dataproc 1.3 will be the default version for new clusters.

そして [BigQuery コネクタのドキュメント](https://cloud.google.com/dataproc/docs/concepts/connectors/bigquery?authuser=1&hl=ja#getting_the_connector)によると、1.3 以降はデフォルトで BigQuery コネクタが入らないようです。

> Cloud Dataproc 1.3 以降ではデフォルトで BigQuery コネクタはインストールされないため、次のいずれかの方法で使用する必要があります。
> 1. 初期化アクションを使用して BigQuery コネクタをインストールする
> 2. ジョブを送信するときに、jars パラメータに BigQuery コネクタを指定する
--jars=gs://hadoop-lib/bigquery/bigquery-connector-hadoop2-latest.jar
> 3. アプリケーションの jar-with-dependencies に BigQuery コネクタのクラスを含める

## 対応
今回は上記で引用した対応方法の 2 で対応しました。
Python クライアント経由でジョブを作成していたので、ジョブに送信する body に下記のような感じで jarFileUris を指定することで問題が発生しないようになりました。

```python
 body = {
    'projectId': 'hogehoge',
    'job': {
        'placement': {
            'clusterName': 'fugafuga'
        },
        'pysparkJob': {
            'mainPythonFileUri': 'piyopiyo',
            'jarFileUris': [
                'gs://hadoop-lib/bigquery/bigquery-connector-hadoop2-latest.jar'
            ]
        }
    }
}
```

参考：[Dataproc の API ドキュメント](https://cloud.google.com/dataproc/docs/reference/rest/v1beta2/PySparkJob?hl=ja)

## 終わりに
この記事では Dataproc の PySpark ジョブで BigQuery からのデータ読込に失敗する事象の原因と対処についてまとめました。一つの事例として少しでもどこかの誰かの参考になればいいなと思います。
ちなみに[利用するイメージのバージョンの固定](https://cloud.google.com/dataproc/docs/concepts/versioning/overview?hl=ja)とか、バージョンアップへの追従とかもちゃんと考えないとなぁとは思いました。
Elixir: 列挙型データから値を探すEnumモジュールの関数

[`Enum`](https://hexdocs.pm/elixir/Enum.html)は列挙型(enumerable)データを扱うモジュールです。`Enum`の関数はさまざまな列挙可能なデータ型に使える[多態性](https://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0)をもちます。扱うデータは[`Enumerable`](https://hexdocs.pm/elixir/Enumerable.html)プロトコルを実装していればよいのです(「[Elixir入門 10: EnumとStream](https://dev.to/gumi/elixir-10-enumstream-4fpb)」参照)。それらの関数の中から、値を探す3つの関数をご紹介します。とくに、`Enum.find_value/3`については、公式ドキュメントよりわかりやすいコード例を示しました。


# `Enum.find/3`
[`Enum.find/3`](https://hexdocs.pm/elixir/Enum.html#find/3)は、第3引数`fun`の戻り値が`true`と評価される最初の要素を返します。関数が引数に受け取るのは、取り出される各要素です。

>
```
find(enumerable, default \\ nil, fun)
find(t(), default(), (element() -> any())) :: element() | default()
```

第2引数はデフォルト値です。省くと`nil`が与えられます。

```elixir
iex> Enum.find([1, 2, 3], fn x -> rem(x, 2) == 0 end)
2
iex> Enum.find([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
iex> Enum.find([1, 2, 3], 0,  fn x -> rem(x, 4) == 0 end)
0
```


# `Enum.find_index/2`
[`Enum.find_index/2`](https://hexdocs.pm/elixir/Enum.html#find_index/2)は、第2引数`fun`の戻り値が`true`と評価される最初の要素のインデックスを返します。関数が引数に受け取るのは、取り出される各要素です。

>
```
find_index(enumerable, fun)
find_index(t(), (element() -> any())) :: non_neg_integer() | nil
```

インデックスは0から始まる連番整数です。いずれの要素も、第2引数の関数`fun`が`true`と評価される値を返さないときは`nil`となります。

```elixir
iex> Enum.find_index([1, 2, 3], fn x -> rem(x, 2) == 0 end)
1
iex> Enum.find_index([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
```


# `Enum.find_value/3`
[`Enum.find_value/3`](https://hexdocs.pm/elixir/Enum.html#find_value/3)は、第3引数`fun`の戻り値が`true`と評価される最初の要素について、戻り値そのものを返します。関数が引数に受け取るのは、取り出される各要素です。

>
```
find_value(enumerable, default \\ nil, fun)
find_value(t(), any(), (element() -> any())) :: any() | nil
```

第2引数はデフォルト値です。省くと`nil`が与えられます。

```elixir
iex> Enum.find_value([1, 2, 3], fn x -> rem(x, 2) == 0 end)
true
iex> Enum.find_value([1, 2, 3], fn x -> rem(x, 4) == 0 end)
nil
iex> Enum.find_value([1, 2, 3], &is_number/1)
true
iex> Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!"
iex> Enum.find_value([1, 2, 3], fn x ->
...>   case rem(x, 2) do
...>     0 -> {:even, x}
...>     _ -> false
...>   end
...> end)
{:even, 2}
```

[公式ドキュメントの`Enum.find_value/3`の項](https://hexdocs.pm/elixir/Enum.html#find_value/3)には、使い途の浮かぶ例が掲げられていないようです。たとえば、つぎのようにキーワードリストから値を取り出すことが考えられます。

```elixir
iex> profile = [{company: "gumi, inc"}, {headquarters: "tokyo/japan"}]
iex> Enum.find_value(profile, fn {key, value} ->
...>   case key do
...>     :headquarters -> value
...>     _ -> false
...>   end
...> end)
"tokyo/japan"
```

この例は、[`and/2`](https://hexdocs.pm/elixir/Kernel.html#and/2)を用いるともっと短く書けます。

```elixir
iex> Enum.find_value(profile, fn {key, value} -> key == :headquarters and value end)
"tokyo/japan"
```
kintoneのテーブルでSUMIF（条件つきの合計値計算）を行う

kintoneでサブテーブルに含まれる数値を全て合計する方法は、計算フィールドに用意されています。
ですが、各行に入力されたデータを条件とするなど一部の数値だけの合計を計算する方法はありません。

エクセルでいう**SUMIF**という関数の機能ですが、これをプラグイン「[機能拡張スタンダードAll-In](https:/spica.tokyo/bluelaunch/)」を使って設定してみます。
使う機能は**「自動計算」**です。

# サンプル用のアプリ内容

サンプルとして以下のようなアプリを作成しました。

![sample-01.png](https://qiita-image-store.s3.amazonaws.com/0/67365/cf33cf6f-2b95-4362-79cb-75a02a1c8e11.png)

* ドロップダウンフィールド**「品目」**
* 数値フィールド**「個数」**
* 数値フィールド**「金額」**

が配置されたテーブルを作成しました。
テーブル名は **Table** です。

その他のフィールドとして、

* 品目「サンプルＡ」の個数合計の入力先として、文字列フィールド**「サンプルＡ個数合計」**
* 品目「サンプルＢ」の個数合計の入力先として、数値フィールド**「サンプルＢ個数合計」**
* 金額の総計を入力するフィールドとして、数値フィールド**「金額総計（自動計算）」**

を設置。

またkintoneの計算フィールドを使用した合計金額の計算と比較するために、

* 計算フィールド**「金額総計（計算フィールド）」**

も設置しました。計算の設定内容は、

```
SUM(金額)
```

です。

# プラグインの設定

「サンプルＡ」の個数合計を求める設定を行っていきます。

## 合計値の初期化

合計個数の入力先である「サンプルＡ個数合計」に 0 を代入します。

![sample-11.png](https://qiita-image-store.s3.amazonaws.com/0/67365/20af9b41-e175-05bd-f2c0-58ee600ccbe9.png)

## 「サンプルＡ」の行だけ個数を加算する

条件と代入先や演算項などの計算内容を細かく設定します。

![sample-12.png](https://qiita-image-store.s3.amazonaws.com/0/67365/895a3a39-c18d-b0b3-82cd-e1523efdffb5.png)

### まず条件の設定です

条件判定値に **Table.品目** を選択
判定方法に **=（等しい）** を選択
条件値の入力方法は **（直接入力）** で、条件値は **「サンプルＡ」** と入力。

これで、品目フィールドに「サンプルＡ」と入力されている行だけが自動計算対象となります。

### 次に計算内容の設定です

代入先に **サンプルＡ個数合計** を選択。
演算項の1行目、演算項に **サンプルＡ個数合計** を選択。
演算項の2行目、演算に **＋** 、演算項に **Table.個数** を選択。

計算はテーブル行を1行目から最後の行まで順番に、判定と演算を行います。
条件にマッチした行の個数だけが、サンプルＡ個数合計フィールドに加算されていきます。
結果として、サンプルＡの個数が全て加算された数値が代入されます。

サンプルＢの個数合計も同様の設定をおこないます。

![sample-13.png](https://qiita-image-store.s3.amazonaws.com/0/67365/ab0d59df-52fb-87c9-d8f5-ed769e959933.png)

「サンプルＢ個数合計」の初期化で**空欄**を選択していますが、空欄は数値計算に使用した場合は0とみなしますので、この内容でも問題ありません。

## 合計金額の設定

![sample-14.png](https://qiita-image-store.s3.amazonaws.com/0/67365/53b42429-c9a5-a258-d180-146097e57bc1.png)

まず合計金額を代入するフィールドの初期化します。これは個数合計を計算するのと同じ手順です。

計算内容です。

条件判定は**（常に適用する）**を選択。
これで全ての行が条件にマッチしていることになります。

計算内容は、
代入先に **金額総計（自動計算）** を選択。
演算項の1行目、演算項に **金額総計（自動計算）** を選択。
演算項の2行目、演算に **＋** 、演算項に **Table.金額** を選択。

以上で全ての行の**金額**を合計した結果が、**金額総計（自動計算）**へ代入されます。

# サンプルデータ

レコードを作成し、下記のようなデータを入力しました。

| 品目 | 個数 | 金額 |
| ---- | ----: | ----: |
| サンプルＡ | 10 | 1000 |
| サンプルＢ | 12 | 24000 |
| サンプルＡ | 5 | 500 |
| サンプルＢ |  |  |
| サンプルＢ | 8 | 16000 |

4行目のデータは個数と金額をあえて空欄にしています。
自動計算の結果がこちら。

![sample-21.png](https://qiita-image-store.s3.amazonaws.com/0/67365/c9e39374-fff8-399a-02c7-9f97d08d70a6.png)

サンプルＡとサンプルＢの個数が正しく求められています。
また金額も総計が入力されました。

kintoneの計算フィールドをみてみるとエラーが表示されています。
これは4行目の金額が空欄のままなので、合計金額が正しく計算できなかったのです。
プラグイン機能の自動計算では空欄は0とみなしますので、計算結果を求めることができています。

---

#このプラグインについて
・[キーワード検索](https://qiita.com/spica/items/9fd2131252702f263e12)
・[自動計算・自動採番](http://qiita.com/spica/items/803af7cd540ae0b8f718)
・[条件書式](http://qiita.com/spica/items/24027003e9dfb9363819)
・[フィールド属性](http://qiita.com/spica/items/73107bda2cff4a94cf41)
・[選択数制御](http://qiita.com/spica/items/1c3ba3927b844b6bb72b)
・[レコード一括更新](http://qiita.com/spica/items/f0e84a1cf430670c4292)
・[自動計算によるレコード一括更新](kintoneプラグイン『機能拡張スタンダード All-In』を使って自動計算でのレコード一括更新を行う)
windwosでdocker-composeのvolumesでマウントできない件

# ある日突然docker-composeのvolumesがマウントできなくなった。
原因はwindowsのパスワードを変更したからだった。
## 以下対応策
Docker for windowsのsettingsを開いてShared Drivesのチェックを外してApply。
再度チェックを入れApplyするとWindowsのパスワード認証が出てくるので新しいパスワードを入れてOK。
これでマウントされるようになる。

これで丸1日はまったので共有しておきます。
Jupyter NotebookをDocker上で立ち上げる時にパスワードはenvironmentで渡せるようにしたやつ

Jupyter NotebookをDocker上で立ち上げる時にパスワードはenvironmentで渡せるようにしたやつです(閉じた環境用)。

# 物
- https://github.com/ko-he-/my-jupyter-notebook

# 使い方
gitから一式clone

```
git clone https://github.com/ko-he-/my-jupyter-notebook

cd my-jupyter-notebook
```

パスワードを設定させるためにdocker-compose.ymlの`JUPYTER_PASS`を変更

```
version: '3'
services:
  jupyter:
    build:
      context: ./jupyter
    volumes:
      - ./ipynb/:/home/jovyan/work
      - ./data/:/home/jovyan/work/data
    ports:
      - 8888:8888
    environment:
      - JUPYTER_PASS=password # ここを変更
```

ついでにpipで入れたいものがあれば`./jupyter/requirements.txt`に追記

最後に起動

```
docker-compose up -d
```
- その他
  - hostからコンテナに渡したいデータがある場合は./dataに格納。  
  - host側の`./ipynb/`は`/home/jovyan/work`にマウントされている。
  - `./data`と`./ipynb`は適切にpermissionをつけてください
  - **`./data`と`./ipynb`は`gitignore`に含まれているので注意**
  - jupyter/datascience-notebookをベースにしてるので他が必要な場合はDockerfileをいじってください。
  - パスワードはgitにpushしないように注意しましょう(.envとかに設定してgitignoreとか)
SourceTreeでGitHubにSSH接続する方法

# SourceTreeでGitHubにSSH接続
GitHubの2段階認証を有効にするとHTTP接続ができなくなり、SSH接続する必要がある。
SourceTreeはクセが強く、色々とハマったところがあったので、備忘録として情報を残す。

### SSH認証の公開鍵と秘密鍵を作成
SSHで接続するための公開鍵と秘密鍵を作成する。
コメントの部分は何でも良いらしいが、GitHubではメールアドレスを推奨している？

```
$ ssh-keygen -t rsa -C [コメント(メールアドレスとか何でも良い、空でも良い)]
```

鍵をどこに保存するか聞かれるので、そのままで良いならEnter。

```
Enter file in which to save the key (/Users/evitch/.ssh/id_rsa):
```

パスフレーズを2回入力する。

```
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/evitch/.ssh/id_rsa.
```

これでSSH認証の公開鍵と秘密鍵が作成される。
id_rsa: 秘密鍵
id_rsa.pub: 公開鍵

```
$ cd ~/.ssh
$ ls
id_rsa		id_rsa.pub
```

秘密鍵のパーミッションを設定する。

```
$ chmod 600 id_rsa
```

**(重要！)鍵にパスフレーズを設定した場合のみ、以下のコマンドを実行する。**
これでssh-agentに鍵を登録しないと、SourceTreeが正常に鍵情報を読み込んでくれない模様。

```
$ ssh-add -K
```

~/.ssh/configを作成し、以下のように記述する。

```
Host github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User git
```

### GitHubへ公開鍵を登録
設定ページの「SSH and GPG keys」をクリックする。

SSH Keys の「New SSH key」ボタンをクリックする。

Title欄には任意の名前を入力し、Key欄には以下のコマンドでクリップボードにコピーしたものを貼り付ける。

```
$ pbcopy < ~/.ssh/id_rsa.pub
```

<img width="1016" alt="スクリーンショット 2019-01-30 12.08.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/322144/9b0f9201-ca95-97d7-cc22-cb8337009a47.png">

「Add SSH key」ボタンを入力して、GitHubへ公開鍵を登録する。

### SourceTreeの設定
SouceTreeメニューの「環境設定...」から、アカウント画面を開く。
![スクリーンショット 2019-01-30 12.16.17.png](https://qiita-image-store.s3.amazonaws.com/0/322144/5aa3fe9c-1053-4604-64ab-389ad69da05d.png)

「追加」をクリックし、以下の画面が表示されたら、ホストを「GitHub」にし、「接続アカウント」をクリックする。
![スクリーンショット 2019-01-30 12.18.09.png](https://qiita-image-store.s3.amazonaws.com/0/322144/9976cc57-faba-21c2-4bb1-ae035b0b48d0.png)

ブラウザに飛ばされるので、「SourceTreeを開く」をクリックすると、SourceTreeにGitHubのアカウントが連携される。
<img width="446" alt="スクリーンショット 2019-01-30 12.18.41.png" src="https://qiita-image-store.s3.amazonaws.com/0/322144/9e333be3-76df-7d99-4679-b70c8d54d6f1.png">

「保存」をクリックして、ウインドウを閉じる。

次に、SouceTree画面右上の「設定」をクリックし、リモートタブを開く。
![スクリーンショット 2019-01-30 12.22.38.png](https://qiita-image-store.s3.amazonaws.com/0/322144/cad8e7ca-09d8-d8b5-a432-dab1f48ef2c5.png)

ここにリモートリポジトリへの接続方法を入力する。
SSHで接続するため、GitHubのリポジトリページのトップからコピペする。
<img width="440" alt="スクリーンショット 2019-01-30 12.25.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/322144/28e8e3df-831e-0345-d698-9615db6dab2c.png">

「OK」をクリックして、ウインドウを閉じる。
以上。
neovimがターミナルのカーソル設定を変更してしまうのを解決した

vimからneovimに移行した際に、neovimを起動するとiTerm2のカーソル設定が勝手に変更されてしまう、という事象に遭遇した。

# TL;DR
init.vimに```set guicursor=```を書き加える

# 環境
iTerm2 build3.2.7
neovim v0.3.4

# 起こったこと
iTerm2のカーソル設定は

- Vertical bar
- Blinking cursor

の状態でneovimを起動して、:qで閉じると、設定画面は変わらないまま、ターミナル上のカーソルのみが

- Box
- （Blinking cursorなし）

になってしまっていた。

# やったこと
[こちら](https://github.com/neovim/neovim/wiki/Following-HEAD#20170402)を参考に、neovimの設定ファイルであるinit.vimに以下を追記。

```vim:~/.config/nvim/init.vim
set guicursor=
```
要は、guiのカーソルには変更を加えない(=空白)、ということらしい。

# 結果
neovimを起動してもターミナルのカーソルには影響が出ない。
FFFTPに登録したパスワードを忘れてしまった時の対処法

先日、会社で使用しているFFFTPのパスワードをど忘れしてしまい、
接続するのに手間取ったので、調べる方法をメモしました。

##ゴール
以前FFFTP登録したが、忘れてしまったパスワードを表示する

##手順
1.FFFTPを起動
2.「接続(F)」＞「設定(S)」＞「FileZilla XML に設定をエクスポート」の順に選択
3.出力されたXMLファイルのコードを確認


##1.FFFTPを起動
FFFTP内の設定した内容を取り出すので、まずはツールを起動します。


##2.「接続(F)」＞「設定(S)」＞「FileZilla XML に設定をエクスポート」の順に選択
FFFTP内のツールを「接続(F)」＞「設定(S)」＞「FileZilla XML に設定をエクスポート」の順に選択していきます（※下記の画像を参照）。
![picture_pc_53c166232d5670e95b12ab8232d426cf.png](https://qiita-image-store.s3.amazonaws.com/0/351760/feab9160-5403-2479-dd0c-2e24236b83bc.png)


##3.出力されたXMLファイルのコードを確認
エクスポートが完了すると「FileZilla.xml」が作成されているので、メモ帳などテキストエディタを使ってファイルを開きます。
開いたファイルの「\<Pass>〜\</Pass>」の部分にパスワードが書いてあります（※下記の画像の赤背景部分を参照）
![アートボード 1_1.png](https://qiita-image-store.s3.amazonaws.com/0/351760/e518b675-3dac-89bd-567b-45958793a3f3.png)
FFFTPの設定が複数個ある場合は、「\<Server>〜\</Server>」が設定した数（ホストの数）だけ存在します。
その場合は、「\<Host>〜\</Host>」にホストの設定名が書いてあるので、知りたいホストのパスワードをそこで確認してみてください。
上記の画像で言うと「testHost」がホストの設定名になりますね。


以上で確認方法の説明は終わりです。
最後までお読みいただき、ありがとうございました。

----
今回の確認方法の他にも方法があるようですが、
私の使用しているFFFTPのバージョンだと使えませんでした…。
参考程度にサイトを紹介しておきます。

##参考サイト
・[FFFTPで忘れてしまったFTPパスワードをさくっと調べる方法](https://accelboon.com/tn/ffftp%E3%81%A7%E5%BF%98%E3%82%8C%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9Fftp%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E3%81%95%E3%81%8F%E3%81%A3%E3%81%A8%E8%AA%BF%E3%81%B9%E3%82%8B/)
はじめての LitElement エレメントの作り方 - Step1


wrote: 2019/1/28


# 

lit-html は Polymer Project の一環で、Tagged Templetes によってビューを管理するライブラリです。

[lit-html を使い倒す](https://aggre.io/post/make-the-best-use-of-lit-html) より


## 

以下のチュートリアルに沿って進みます。
[Build your first LitElement element](https://polymer-japan.github.io/litelement-first-element/index.ja.html#0)


![image](https://qiita-image-store.s3.amazonaws.com/0/49910/cb95983e-e852-37c0-ba9a-ab5906d0d273.png)


# 準備

## サンプルプログラム

リポジトリをクローンして、`npm i`です。

>インターネット回線が遅いと、とても時間がかかる場合があります....

とあるように、`npm i` は結構時間かかる場合あります。

```shell
git clone https://github.com/Polymer-Japan/litelement-first-element.git
cd litelement-first-elements
npm i
```

## デモを実行

```shell
npm start
````
以下の画面が起動します。

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/726cb1b8-4970-e1b9-40bd-3a69f737562e.png)



# start-lit-element:

[PolymerLabs/start-lit-element: Hello World app for LitElement.](https://github.com/PolymerLabs/start-lit-element#build-for-production-and-serve-locally)


ここまでやって、Polymer3のチュートリアルとあまり変わらない事に気づきました。

続きはまたいつか書きます。
colconビルドで便利なオプション

せしまるです。

今回はほぼ備忘録ですが、colcon buildの便利なオプションを書きます。
困ったらcolcon build -hを！

|オプション|説明|
|:-:|:-:|
|--build-base PATH|パスで指定したディレクトリにCOLCON_IGNOREと.build_byファイルが作成される。なんで。|
|--install-base PATH|ビルド後にパスで指定したディレクトリにパッケージがインストールされる。|
|--symlink-install|可能なら、ファイルコピーの代わりにシンボリックリンクを使用してインストールする。|
|--continue-on-error|パッケージのビルド失敗時に、他のパッケージのビルドを続行する。|
|--executor (parallel or sequential)|複数パッケージを並行してビルドするか、1個ずつビルドするかを指定できる。|
|--parallel-workers NUMBER|並行してビルドするパッケージ数を指定する。デフォルトは4。|
|--base-paths PATH|パスで指定したディレクトリ配下のパッケージを再帰的にビルドする。|
|--packages-up-to PKGNAME|指定したパッケージと依存パッケージをビルドする。|
|--packages-select PKGNAME|指定したパッケージをビルドする。|
|--packages-select-by-dep|指定したパッケージと指定したパッケージに依存しているパッケージをビルドする。|
|--packages-skip-build-finished|ビルドが完了しているパッケージのビルドをスキップする。|
|--event-handlers ARG|ビルド時の設定。標準出力・ログの指定ができる。|
react-native run-android で Genymotion で確認するまで

Andr○id Studi○ がとにかく重い！！（全然伏せてない）
ということで、少なくともそれよりは軽いであろう Genymotion で動かすまでに、ちょっとハマったことを書き残しておきます。

react native version: `"react-native": "0.57.4"`

## `Could not determine java version from '11.0.1'` 的なメッセージが出て起動できない

`react-native run-android` をすると早々に `Could not determine java version from '11.0.1'` 的なエラーが出て起動ができませんでした。

調べてみると java8 にすれば動くようで、素直に `Java SE Development Kit 8` をインストールしてみます。
が、 `java -version` してもバージョンが切り替わらない！

すごく丁寧に説明されている記事を見つけ、解決しました。

[OSXでJavaのバージョンを切り替える](https://qiita.com/ringo/items/db58b34dc02a941b297f)

これで無事 `react-native run-android` で Genymotion にアプリがインストールされました。
（先に 仮装デバイスの起動と、 USB debugging を有効化しておかないとダメかもしれません）

## Genymotion の仮装デバイスで localhost に接続できない

赤い画面では `10.0.3.2:8081` に接続しようとしている様子。
以下の手順で localhost に接続することができます。

1. `Cmd + M` で設定モーダルを開く
1. Dev settings をタップ
1. Debug server host をタップ
1. `localhost:8081` を入力

参照：[React-native android debugger connecting to 10.0.2.2 instead of localhost](https://stackoverflow.com/questions/49499250/react-native-android-debugger-connecting-to-10-0-2-2-instead-of-localhost)

## Google Play が入ってない

これは開発しているアプリによるかもしれませんが、Google Play が入っておらずアプリが正常に動作がしなかったため、Genymotion の仮装デバイスに Google Play を入れます。

これも丁寧に説明されている記事がありました。

[AndroidシミュレータGenymotionに Google Play ストア をインストール](https://qiita.com/sou_lab/items/bb06bb653b291c90bf45)

Google Play のインストールは自己責任でお願いします。

---

これでちょっと快適な Android 開発環境を手に入れることができました。
では開発に戻ります。
ラズパイの音量を設定したあと、再起動しても元に戻らなくする

# ラズパイの音量を設定したあと、再起動しても元に戻らなくする
再起動すると音が大きくなるのを防ぎます

## ラズパイの音量を調整
左上のメニュー→設定→Audio Device Settings→音量を調整

## ターミナルで、音量の設定を保存するコマンドを入力

```
sudo alsactl store
```
mondrian schemaで memberのformatを変更するには


```schema.xml
 <Dimension name="4. Department">

      <Hierarchy hasAll="true">

        <Level name="group1" column="group1" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never">
          <MemberFormatter>
            <Script language="JavaScript">
              if (member.getName().toUpperCase().indexOf("NULL") >= 0) { return "OTHER" }
              else { return member.getName();}
            </Script>
          </MemberFormatter>
        </Level>
        <Level name="group2" column="group2" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never">
          <MemberFormatter>
            <Script language="JavaScript">
              if (member.getName().toUpperCase().indexOf("NULL") >= 0) { return "OTHER" }
              else { return member.getName();}
            </Script>
          </MemberFormatter>
        </Level>

        <Level name="group3" column="group3" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never">
          <MemberFormatter>
            <Script language="JavaScript">
              if (member.getName().toUpperCase().indexOf("NULL") >= 0) { return "OTHER" }
              else { return member.getName();}
            </Script>
          </MemberFormatter>
        </Level>

        <Level name="group4" column="group4" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never">
          <MemberFormatter>
            <Script language="JavaScript">
              if (member.getName().toUpperCase().indexOf("NULL") >= 0) { return "OTHER" }
              else { return member.getName();}
            </Script>
          </MemberFormatter>
        </Level>

        <Level name="partner" column="partner" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never" />
        <Level name="owner_alias" column="owner_alias" type="String" uniqueMembers="false" levelType="Regular" hideMemberIf="Never" />

        <Level name="account_id" column="account_id_2" type="String" uniqueMembers="true" />

      </Hierarchy>

    </Dimension>
```

- MemberFormatterで指定
- javascriptで変更できる．
- nullの場合は，OTHERに変えるとか
- 他のlanguageで何か使えるかは？？？
EgretEngineでRPGマップはどう実現するか？ (1) ベストプラクティスなサンプルのインストール

# 話の発端

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">スクロール系ならオブジェクトを動かしてそれっぽくする感じですよね。<br>RPG系でStage移動しようと思うと、めちゃくちゃ恐ろしいですね(絶対重い)ｗ<br>また考えますｗ</p>&mdash; ko-ki (@kokig_creat) <a href="https://twitter.com/kokig_creat/status/1089882388040011776?ref_src=twsrc%5Etfw">2019年1月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 今回の課題

EgretEngineでRPGのフィールドマップのような広大なエリアをスクロールして移動するにはどうすべきか？

## ヒントを探す流れ
EgretEngineの公式コミュニティで「地图」(Mapという意味)で[検索](https://bbs.egret.com/search.php?mod=forum&searchid=1&orderby=lastpost&ascdesc=desc&searchsubmit=yes&kw=%E5%9C%B0%E5%9B%BE)していみました

![検索結果](https://qiita-image-store.s3.amazonaws.com/0/302078/9168f60f-b750-f52f-bd48-72610d32b3a9.png)

上から四つ目の「新人小白就想求个RPG地图的DEMO就那么难吗？都说官方有DEMO」という記事を確認します。

記事 → [新人がRPGマップを作成するのはそれほど難しいでしょうか。公式の方はデモがあると言っていました](https://bbs.egret.com/forum.php?mod=viewthread&tid=53078&highlight=%E5%9C%B0%E5%9B%BE)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/a8cc608f-7ef5-772d-f6fb-3e4d15448827.png)

 > ちょー昔に作りましたのでどうぞ https://github.com/yicaoyimuys/EgretGameEngine

# デモをインストールして動かしてみる

こちらで公開されているRPG風ゲームのデモをインストールします
https://github.com/yicaoyimuys/EgretGameEngine

## ステップ1. リポジトリーをダウンロードしてください

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/8e07e615-6bee-af7e-10c6-050a87e3e046.png)

## ステップ2. 適当な場所に展開してください

## ステップ3. Egret Launcherを開いて Engine 5.1.9をインストールしてください
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/835a537b-a9d2-277b-5b20-4d1ec82154e9.png)

## ステップ4. インポートする
「Import project」から先ほど展開したディレクトリを開くと、下のように「EgretGameEngine-1.4」プロジェクトが読み込まれます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/1417a455-8776-7ab7-c4fb-1da63c5ae817.png)

## ステップ5. プロジェクトを開く

Egret Launcherのプロジェクト一覧の「EgretGameEngine-1.4」プロジェクトの右端のVS-Codeのロゴをクリックするとプロジェクトが開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/cf45f740-3117-a11e-6cdf-10c2b54711a4.png)

## ステップ6. 起動する
左端の〇なアイコンをクリックしてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/c9584c1e-ba20-11d1-53e2-240c274ae35b.png)

次に赤い〇をつけた緑の△をクリックするとデバッガが起動します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/205486c4-b6bc-0f62-2487-4480764b7f4b.png)

もしその右の選択ボックスに「Egret Debugger」と表示されていない場合は、選択ボックスをクリックしてください。

リストに構成の追加という項目がありますので、それを選択してください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/9ee272f4-79c7-4d73-a190-f385bb613e57.png)

追加できる構成のリストが表示されるので「Egret Debugger」を選択してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/fc5fe514-b813-70e0-0339-08f137c50dd2.png)

# 起動結果

こんな感じのRPGのマップが表示されます。

たくさんのモンスターが出現して、画面はスクロールすることができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/302078/5856e311-ceb3-8552-10a2-b8db1fcdfa39.png)

# 次回

今日はここまで

次回はソースコードをおっかけてみます
Vue.jsにGravatarを入れてみた

Vue.jsで作ったプロジェクトにGravatarを入れてみたので、導入方法をメモメモ

### Gravatarとは
Gravatarとは、Qiitaの右上にある、あれのことである。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/316291/4ef0be0c-5fdb-9c94-0fc5-d2fd0d74d73c.png)

Gravatarにアカウントを作成しアイコンを登録しておくことで、Qiitaをはじめとした様々なWebサービスで共通のアイコンを使えるようになるので、Gravatarに対応したサービスで新たにログインアカウントを作成しても、アイコン登録をしなくて済むという優れもの。

これをVue.jsで作ったプロジェクトに埋め込んでみたい、と思い立ったので導入してみた。
以下、参考にした公式サイト。
https://ja.gravatar.com/site/implement/

### npmでインストールする
公式サイトを見ると、HTML上に直接書き込んで導入できるようだが、Gravatarから画像のURLを引っ張ってくるために利用するメールアドレスなどをmd5で暗号化したりしなければならず、多少の手間がかかる。

探してみると、Node.jsのライブラリが提供されていることが分かったので、こちらの方法で導入することを選択。
https://www.npmjs.com/package/gravatar

ということで、導入したいプロジェクトのrootで以下コマンドを実行。

```console
$ npm install gravatar
```

コマンドを実行すると、node_modules配下にgravatarディレクトリが作成されライブラリが配置される。
また、package.jsonに下記が追加される。

```package.json
 "dependencies": {
    "gravatar": "^1.8.0",
  },
```

これで、利用するための準備が完了。

### vueファイルにimport定義を追加する
vueファイルのScriptの書き出し部分にimport定義を追加。

``` vue
<script lang="ts">
import gravatar from '@/node_modules/gravatar';
```

### 画像のURLを取得する
template部にGravatarで呼び出される画像のURLをimgのsrcに配置する。

```vue
<div class="user-icon"><img :src="gravatarUrl" ></div>
```

Script部はimportしたライブラリからurlメソッドを利用して、Gravatarの画像のURLを取得する。

```vue
  private beforeMount(): void {
    // gravatarからユーザーアイコンを取得
    this.gravatarUrl = gravatar.url(this.loginUser.mail);
  }
```

### 完成
画像URLの取得に成功すると、gravatarに登録されているアイコンが表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/316291/2cbf7ca6-2e3b-8086-e006-f7ea181e6561.png)

なお、デフォルトは正方形の画像が表示されるため、アイコンっぽさを出すには、

```css
.user-icon {
    border-radius: 50%;
}
```
あたりを使ってみるとよい。

### まとめ
手順を記載の通り、とても手軽に導入できた！
ユーザーアカウント毎のアイコン管理の仕組みを1から実装するのはかなり手間なので、それっぽくアイコン表示させたいのならGravatarを導入してみるのもいいかもしれない。
FlutterのiOSビルド時にtrack-widget-creationオプションが見つからないエラーが出る

# 環境情報
```
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.0.0, on Mac OS X 10.14 18A391, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK 28.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.1)
[✓] Android Studio (version 3.2)
[✓] IntelliJ IDEA Community Edition (version 2018.3.2)
[✓] Connected device (2 available)
```

# 問題
FlutterアプリのiOSビルドを行うと下記エラーが発生する。

```
$ flutter build ios --release

---
Xcode's output:
↳
    === BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Release ===
    Could not find an option named "track-widget-creation".

    Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and options.
    Failed to build xxx.
    Command /bin/sh failed with exit code 255

```

# 解決方法
Flutterのxcode_backend.shを編集する。
（track-widget-creationオプションを付けないようにする）
なんか根本的な解決方法になってないと思うので、CIでのビルドでコケたら追記します。

```
$ vi $FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh

local track_widget_creation_flag=""
if [[ -n "$TRACK_WIDGET_CREATION" ]]; then
  # track_widget_creation_flag="--track-widget-creation"
  track_widget_creation_flag=""
fi
```

追記：
Release.xcconfigにTRACK_WIDGET_CREATION=を追記する方が正しそうです。

```
$ vi $PROJECT_ROOT/ios/Flutter/Release.xcconfig

TRACK_WIDGET_CREATION=// 追記
```


# 参考

https://github.com/flutter/flutter/issues/24239
https://wapa5pow.com/flutter-ci-cd/
Vue.js アプリケーションにおけるエントリーポイントの書き方メモ

## はじめに

これは備忘録です。
Vue.js アプリケーションを書いていく時にエントリーポイントの書き方がいくつかあるなぁと思ったので、これまで自分がやったパターン（といっても片手で数えられるくらい）をメモします。

## 触れない話

- Nuxt.js

## 書き方達

### 単純な Vue.js アプリケーションの時

CSSセレクタで対象を指定して Vue インスタンスをマウントします。
初期化時の引数に `el` プロパティを指定するか、 `el` を指定せずに作成したインスタンスに対して `$mount()` を実行します。

参照:
`el`: https://jp.vuejs.org/v2/api/#el
`$mount()`: https://jp.vuejs.org/v2/api/#vm-mount

```html
<div id="app">
  <App/>
</div>
```

```js
import Vue from 'vue'
import App from './components/App.vue'

// パターン1
new Vue({
  el: '#app',
  components: {
    App
  }
})

// パターン2
new Vue({
  components: {
    App
  }
}).$mount('#app')
```

### マウント先をコンポーネントで置き換える形

`render()` メソッドを使うことで、マウント先を指定のコンポーネントで置き換えるように描画できます。
以下の例では、Vueインスタンスのマウント後は `div#app` が `span.foobar` に置き換わります。

属性の `id="app"` は `div` ごと消えるので、このままでは再利用できません。 `#app` のセレクタを再利用した場合は `createElement()` の引数を確認するか、1つ後の書き方を参照してください。

参照:
`render()`: https://jp.vuejs.org/v2/api/#render
`createElement()`: https://jp.vuejs.org/v2/guide/render-function.html#createElement-%E5%BC%95%E6%95%B0

```html
<div id="app"></div>
```

```vue:components/App.vue
<template>
  <span class="foobar">
    foobar
  </span>
</template>

<script>
export default {
  name: 'App'
}
</script>
```

```js
import Vue from 'vue'
import App from './components/App.vue'

new Vue({
  render(h){
    return h(App)
  }
}).$mount('#app')
```

`h()` というのは `createElement()` の事で、「 `html` （のような物）を生成するメソッド」に対してエイリアス的によく付けられる名前のようです。多分。
（参考: [What does \`h\` mean? · Issue \#6 · vuejs/babel\-plugin\-transform\-vue\-jsx](https://github.com/vuejs/babel-plugin-transform-vue-jsx/issues/6)）

### VueRouter を使いつつ root 要素にコンポーネントを描画したい。

上とやる事は同じで `render()` を使います。
SPAを作る際にページ単位を担当するコンポーネントを、 body 直下などの root 要素として配置したい場合などが該当します。

ただ、今回は全ページコンポーネントに対し `id="app"` を動的に付与したい場合の対応も行います。
こうすることで画面内に常に `#app` というセレクタが存在することになるので、例えば `link` タグ等で読み込んでいる CSS 内で `#app` に対するスタイルが記述されていても、問題なく反映されます。

```html
<div id="app"></div>
```

```js
import Vue from 'vue'
import VueRouter from 'vue-router'

import PageRoot from './components/PageRoot.vue'
import Page1 from './components/Page1.vue'
import Page2 from './components/Page2.vue'

const routes = [
  {
    path: '/',
    name: 'PageRoot',
    component: PageRoot
  },
  {
    path: '/page1',
    name: 'Page1',
    component: Page1
  },
  {
    path: '/page2',
    name: 'Page2',
    component: Page2
  },
]

const routerOption = {
  routes
}

Vue.use(VueRouter)

new Vue({
  router: new VueRouter(routerOption),
  render(h){
    return h('router-view', {
      attrs: {
        // router-view で描画されるコンポーネント全てに、常に `id="app"` を持たせたい場合に記述します。
        id: '#app'
      }
    })
  }
}).$mount('#app')
```

肝は `createElement()` で `router-view` コンポーネントを描画させている部分です。
[Python][Pandas]データフレーム中の欠損値を平均値で補完する

scikit-learnのImputerクラスの使い方について、毎回細かい部分を忘れるので備忘のため掲載。

```python:
from sklearn.preprocessing import Imputer
import numpy as np
import pandas as pd

# 対象データフレームから数値型のカラム名のみ取得
list_num_columns = df.select_dtypes(include='number').columns
list_except_num_columns = df.select_dtypes(exclude='number').columns

# 行ごと(axix=0)の平均値(atrategy='mean')を計算する
imr = Imputer(missing_values='NaN', strategy='mean', axis=0)
imr = imr.fit(df[list_num_columns].values)
impyted_data = imr.transform(df.drop([list_except_num_columns ], axis=1)

# 数値型とそれ以外のデータフレームを作成する
df_only_num = pd.DataFrame(impyted_data.values, index=df.index ,columns=list_num_columns)
df_except_num = df[list_except_num_columns]

# 作成した各データフレームを結合
df = pd.merge(df_except_num, df_only_num, right_index=True, left_index=True)
```
ラズパイを起動したら、ターミナル開いてシェルを実行する方法

#ラズパイを起動したら、ターミナル開いてシェルを実行する方法

ラズパイの電源を入れたら、GUI上でターミナルが開いて、プログラムの実行が始まります。

## 自動実行用のフォルダを作成

ラズパイのターミナルから以下を実行

```
cd .config
mkdir autostart
cd autostart
```

この　/home/pi/.config/autostart に、設定ファイルを置くと自動実行できるようになります。

## 設定ファイル（.desktop）の作成

ファイル名は、任意に決められます。ここでは、「sebastien」にします。

```
nano sebastien.desktop
```

エディタが開くので以下を入力します。

```
[Desktop Entry]
Exec=lxterminal -e /home/pi/codama/codama-doc/sebastien/example/autorun.sh
Type=Application
Name=Sebastien
Terminal=true
```
Execに、ターミナルを起動する「lxterminal」を指定します。-eオプションのあとに、フルパスで実行したいシェルを指定します。（Nameは適当でOK、その他は真似してください。）

ちなみに、autorun.shの中身はこんな感じです。
フォルダを移動させたあとに、pythonのプログラムを起動しています。

```
#!/bin/sh
cd ~/codama/codama-doc/sebastien/example/
python3 main.py
```

autorun.shには、実行権限が必要

```
chmod +x autorun.sh
```
wordpressのブログページ（カテゴリー毎）のpaginationが途中からindexに飛ばされてしまう

wordpress自作テーマでサイトを作成しています。ブログのページでpaginationを設定していますが、ブログのカテゴリー毎のページのpaginationでは3ページ目以降indexに飛ばされてしまい、chromeのタイトルバーには「ページが表示されません」となります。

ブログ全体（最新順）ではpaginationは機能しますが、カテゴリー毎に表示したときに、paginationを1回クリックしたときは動きますが、2回目(3ページ目）に移動しようとするとこの現象が起きます。

function.phpにpaginationのコード下記の通り記載しています。

//pagination
function pagination($pages = '', $range = 4)
{
     $showitems = ($range * 2)+1;  
 
     global $paged;
     if(empty($paged)) $paged = 1;
 
     if($pages == '')
     {
         global $wp_query;
         $pages = $wp_query->max_num_pages;
         if(!$pages)
         {
             $pages = 1;
         }
     }   
 
     if(1 != $pages)
     {
         echo "<div class=\"pagination\"><span>Page ".$paged." of ".$pages."</span>";
         if($paged > 2 && $paged > $range+1 && $showitems < $pages) echo "<a href='".get_pagenum_link(1)."'>&laquo; First</a>";
         if($paged > 1 && $showitems < $pages) echo "<a href='".get_pagenum_link($paged - 1)."'>&lsaquo; Previous</a>";
 
         for ($i=1; $i <= $pages; $i++)
         {
             if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
             {
                 echo ($paged == $i)? "<span class=\"current\">".$i."</span>":"<a href='".get_pagenum_link($i)."' class=\"inactive\">".$i."</a>";
             }
         }
 
         if ($paged < $pages && $showitems < $pages) echo "<a href=\"".get_pagenum_link($paged + 1)."\">Next &rsaquo;</a>";
         if ($paged < $pages-1 &&  $paged+$range-1 < $pages && $showitems < $pages) echo "<a href='".get_pagenum_link($pages)."'>Last &raquo;</a>";
         echo "</div>\n";
     }
}

ブログをカテゴリー毎に表示したときのpaginationの動作を正常に動かすプログラムがお分かりでしたらご教示願えますでしょうか。
どうぞ宜しくお願いいたします。
vuejsの{{{波括弧３つ}}}が効かなかった｜廃止されていた

#対策


```errormustashe.html

<p>{{{test}}}</p>

```

▼

```okmustashe.html

<p v-html="test"></p>

```

このようにv-html属性を指定することで対応できました。

#参考サイト
[github](https://vuejs.org/v2/guide/migration.html#HTML-Interpolation-removed)
[vue本家](https://github.com/kazupon/vue-i18n/issues/73)
[vue2.0の変更点※少し古めのスレッドです](https://github.com/vuejs/vue/issues/2873)

廃止された理由を探して見たんですが見つけられませんでした。
セキュリティが強化されているんでしょうか？
記述の統一が目的でしょうか？
ご存知の方いましたら教えて下さい。

#そもそも{{{}}}とは？
ムスタッシュタグと呼ばれるもの。
Mustasheというテンプレートエンジンで使われているとのこと。
今回は{{{}}}と３つのものを書いていますが
{{}}という２つのものもありこちらは現在でも使えます。

＃波括弧３つ{{{}}}と２つ{{}}の違い

```mustashe3.html
{{{<span style="color: red">赤くなる</span>}}}
```

mustashe3の表示結果
<font color="red">赤くなる</font>

```mustashe2.HTML
{{<span style="color: red">htmlソースが表示される</span>}}

mustashe2の表示結果
<span style="color: red">htmlソースが表示される</span>
```



波括弧３つはhtmlソースを解釈してくれます。
Docker - OCI runtime create failed エラー


## `OCI runtime create failed` エラー

`docker-compose up`（`docker run` でも同様）時に発生。以下のようなエラーを吐いてコンテナ起動に失敗する。

```bash
ERROR: for amazonlinux2-with-xxxx  Cannot start service app_server: OCI runtime create failed: container_linux.go:344: starting container process caused "chdir to cwd (\"/root\") set in config.json failed: permission denied": unknown

ERROR: for app_server  Cannot start service app_server: OCI runtime create failed: container_linux.go:344: starting container process caused "chdir to cwd (\"/root\") set in config.json failed: permission denied": unknown
ERROR: Encountered errors while bringing up the project.
```

### 状況

似たようなエラーが出るケースはいくつかある模様。エラーの種別としては `OCI runtime create failed` エラーと言える様だ。

ケースによって対応方法が異なる模様。

- [“dockerが起動しない（OCI runtime create failed: container_linux.go:344） - Qiita”](https://qiita.com/sakapun/items/750e4e9f40e372aa1e5b)
- [“docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused \"open /proc/self/fd: no such file or directory\". · Issue #297 · docker/cli”](https://github.com/docker/cli/issues/297)

今回 Docker イメージとコンテナの削除、 Docker の再起動では復旧せずハマる。

### 原因

`starting container process caused "xxxx"` の xxxx のところがエラーを引き起こした処理とエラーメッセージなのでこれが原因に関係するはず。

今回の場合

```
chdir to cwd (\"/root\") set in config.json failed: permission denied
```

なので、作業ディレクトリを `/root` に変更しようとしたら `permission denied` エラーになった、ということ。

今回の場合 `Dockerfile` で

```Dockerfile

〜〜省略〜〜

ARG APP_USER_NAME='local-user'
ARG APP_USER_GROUP="$APP_USER_NAME"

RUN groupadd $APP_USER_GROUP && \
	useradd $APP_USER_NAME -g $APP_USER_GROUP

WORKDIR /root

〜〜省略〜〜

USER $APP_USER_NAME
```

という感じで `WORKDIR /root` したあと、一般ユーザーに切り替えた場合、`WORKDIR /root` が効いたままになっているのに一般ユーザーでなにかしようとして `permission denied` エラーになったというのが原因。

初歩的なケアレスミス。

### 今回の場合の解決方法

`USER $APP_USER_NAME` の前後に `WORKDIR /home/$APP_USER_NAME` という感じで、ワークディレクトリをそのユーザーにアクセス権限があるディレクトリに変更すれば解決。


### 発生環境 docker version

```bash
$ docker version
Client: Docker Engine - Community
 Version:           18.09.1
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        4c52b90
 Built:             Wed Jan  9 19:33:12 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       4c52b90
  Built:            Wed Jan  9 19:41:49 2019
  OS/Arch:          linux/amd64
  Experimental:     false
```