OmniAICreator/Qiita-1.07M huggingface dataset:
JavaのキャッシュライブラリとEviction Policy

# TL;DR
* キャッシュとEvictionについて、簡単にまとめてみました
* 合わせて、Javaの代表的なキャッシュライブラリが採用しているEviction Policyについてもまとめてみました


# Eviction？

Evictionというのは、日本語で「追い出し」などを指します。

キャッシュの文脈では、キャッシュで保持できる容量を超えて新しいデータを保存しようとした時に、「新しくキャッシュに保存する容量を確保するために、どのデータを消せばよいか？」という戦略で扱われます。

「キャッシュで保持できる容量を超えて」で指す上限というのは、キャッシュ内に保持するエントリ数だったり、オブジェクトのサイズだったりと、上限の設定はキャッシュを扱う製品によって様々です。

Expire（有効期限）とはまた違うので、注意しましょう。


# 代表的なEviction Policy

Wikipediaを見ると、Eviction Policyの例が書かれています。

[キャッシュアルゴリズム](https://ja.wikipedia.org/wiki/%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0)

例えば、LRU、LFU、ARCなど。


## 有名どころ

### LRU（Least Recently Used）

LRUは、もっとも使われていないデータを削除対象とするアルゴリズムです。

とても有名どころで、わかりやすいアルゴリズムですが、例えばバッチ処理なのでキャッシュに格納したデータのほとんどにアクセスするようなケースだと、あまり効率の良いキャッシュの使い方にならなかったりします。


### LFU（Least Frequently Used）

LFUは、データのアクセス頻度を保持し、頻繁に使われていないデータを削除対象とするアルゴリズムです。


# Javaのキャッシュライブラリで実装されている、Eviction Policy


## Caffeine

最近の有名どころ、[Caffeine](https://github.com/ben-manes/caffeine)から。

Caffeineは、[Google Guava Cache]()にインスパイアされたキャッシュライブラリです。

Caffeineで実装されているEviction Policyは、TinyLFUです。

> Caffeine uses the Window TinyLfu policy due to its high hit rate and low memory footprint.

[Efficiency](https://github.com/ben-manes/caffeine/wiki/Efficiency)


## Ehcache 3

Ehcache 2の頃はJavaでのキャッシュライブラリといえばEhcacheでしたが、今はあまり聞かなくなったような気がするEhcache 3です。

Ehcache 3では、Eviction Policyがなくなっています。ヒープ、オフヒープなどの保存先がある状況に対して、効率的にEvictionを実装するのが難しい、という結論みたいです。

[How to specify ehcache3 eviction strategy when cache is full ?](https://github.com/ehcache/ehcache3/issues/2134)

ちなみに、Ehcache 2.xの頃は、LRU、LFU、FIFOがありました。

[Built-in Memory Store Eviction Algorithms](https://www.ehcache.org/generated/2.10.4/html/ehc-all/#page/Ehcache_Documentation_Set%2Fco-evict_builtin_algorithms.html%23wwconnect_header)

Ehcache 3でも、Eviction Advisorを作成すればPersistenceの層でコントロールすることはできるみたいです。これは、先程の保存先に対しての話につながりますね。

[Eviction Advisor](https://www.ehcache.org/documentation/3.8/eviction-advisor.html)

つまり、キャッシュエントリを保存する先に合わせて自分で作りましょう、と…。


## Google Guava Cache

最後は、Google Guava Cache。Caffeineが登場した今となっては、使うことがないかもしれませんが。

GuavaのCacheの場合は、サイズ、時間、参照でのEviction設定が可能です（Evictionと言いつつ、Expireでは？という感じがするものもありますが）。

[CachesExplained / Eviction](https://github.com/google/guava/wiki/CachesExplained#eviction)

このうち、参照でSoftReferenceを使うと、LRUな感じになるようです。


## とりあえず

このあたりの情報を、手始めに押さえておけばよいのではないでしょうか。
cordova-plugin-inappbrowserの"message"イベント

# cordova-plugin-inappbrowser "message"イベントでネイティブ側で処理

非常に役に立つ"message"イベント。
これを使えばinappbrowser側でのイベントをひっかけてネイティブにもってこれる。
cordova側の処理。


        this.Ref.addEventListener("message", function(event){
            var type = event.type;
        });

とても楽。


呼び出す側。


        if (window.webkit && window.webkit.messageHandlers) {

                var messageObj = {
                        "type": type
                        , "data" : data
                };
                var stringifiedMessageObj = JSON.stringify(messageObj);
                webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj);
        }

とても楽。
渡すパラメータはjsonにしてやるみたいでござるよ。

注意すべきはAndroid時の挙動か。
window.webkitはネイティブ側のonなんたらFinishイベントで捏造しているくさい。
document.readyとかでイベントはしらせたら多分はしらない。たぶんね。
（cordova_iabというオブジェクトを直で使えば動かせるかも）

https://github.com/apache/cordova-plugin-inappbrowser
【GAS】StandaloneScriptsでスクリプトを共通化する

## 目的
Container Bound ScriptsとしてスプレッドシートにGASを組み込んでいるが、そのシートを10ファイルほど複製して使用することになった。
この場合、GASに変更を加える時に10ファイル全て変更しなければならないので
今のうちにStandalone Scriptsに機能を移動し共通化しておきたい。
これが意外と情報が出てこなかったのでメモしておく。

## Standalone Scriptsを作成する
Google Driveの任意の場所にGoogle Apps Scriptファイルを作成する。 
`「右クリックメニュー」 > 「その他」 > 「Google Apps Script」`

これがContainerにBoundしていない、Standalone Scriptsとなる。
スプレッドシート上で行いたい処理を上記ファイルに記述し、
各スプレッドシートからはその処理を読み込む形にする。

デフォルトの「コード.gs」にサンプルとして以下の関数を作成した。

``` javascript
function oishiiOniku() {
  var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadSheet.getSheetByName("シート1");

  sheet.getRange(1, 1).setValue("おいしいお肉");
}
```

関数を作成したので、これをスプレッドシートから読み込むための準備をする。
`「メニュー」 > 「ファイル」 > 「版を管理...」`

<img width="517" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/98fa2506-7648-fcce-16d2-57386f5fe85a.png">

版を管理のダイアログに記載がある通り、
他のスプレッドシートからこのファイルをライブラリとして読み出すためにはバージョンを定義しなければならない。
変更内容を入力して「新しいバージョンを保存」を行うとVer1が定義されるので「OK」を押す。

次にプロジェクトのプロパティを表示し、「スクリプトID」を控えておく。
`「メニュー」 > 「ファイル」 > 「プロジェクトのプロパティ」`

## スプレッドシートに連携する
スクリプトを使用する側のスプレッドシートを立ち上げ、
スプレッドシートからスクリプトエディタを表示する。
続けて、スクリプトエディタからライブラリのダイアログを表示する。
`「メニュー」 > 「リソース」 > 「ライブラリ...」`

「ライブラリを追加」のところに先ほど控えたスクリプトIDを入力して「追加」を押す。
<img width="520" alt="03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/9f6ad7df-f3a4-5ffb-af27-06abcd77a64a.png">

「バージョン」は版を管理で定義したバージョンに合わせる必要がある。
今回であればVer1にする。当然最新のVer以外を指定することもできる。
また、「識別子」はスクリプトを読み出す際にコードに記述するため、
わかりやすく編集しておくと良い。

## oishiiOnikuを実行する
あとは通常通りスプレッドシードのスクリプトとしてoishiiOnikuを読み出す処理を書けば良い。

``` javascript
function myFunction() {
  Sample.oishiiOniku();
}
```

「識別子.関数名」と書いて実行するだけで、無事処理が実行された。
<img width="249" alt="04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/97795d8b-388f-bd80-fee2-cdc9ead2f824.png">

## 補足
スクリプトのバージョンを更新した場合に、結局すべてのシートで
バージョンを合わせに行く必要があるのでは…？と思ったが、
最新バージョンが定義された場合は自動で追従しているようだった。(詳細未確認)

## 参考にした情報
[1つのGASを複数のスプレッドシートで利用する方法（Google Apps Script）](http://pineplanter.moo.jp/non-it-salaryman/2018/11/14/gas-plural-spreadsheet/ "1つのGASを複数のスプレッドシートで利用する方法（Google Apps Script）")
ECMAScriptの歴史

1995 JS誕生
1997 ES1
1998 ES2
1999 ES3
ES4 → 放棄
2009 ES3.1  → ES5
2015 ES6 → ES2015
2016 ES7 → ES2016
2017 ES2017(8th)
2018 ES2018(9th)
2019 ES2019(10th)
node-mssql を普通にinstallするとパラメータクエリーに使う .input() で型指定がうまくいかない原因と対策

# 概要

[node-mssql](https://github.com/tediousjs/node-mssql) とは SQLServer に node.js から接続するモジュール。
これを普通に

```
npm install mssql
```

でインストールすると、v5 台が入ります。
ですがこれで、ドキュメントにあるように

```js
let result1 = await pool.request()
            .input('input_parameter', sql.Int, value)
            .query('select * from mytable where id = @input_parameter')
```

とやっても

```
parameter.type.validate is not a function
```

というエラーが出てSQLが実行されません。


# エラーの意味

これは、`sql.Int` が正しい型ではないという意味のエラーのようです。
実際、ソースを追いかけると、`sql.Int().type.validate` を実行しようとしてエラーとなっているようです。

# なぜエラーになるのか。

この type の構造は、v6 台（まだ beta）で大きく変わっているのですが、
validate メソッドはそちらには存在しています。
つまり、v5 で v6 のメソッド呼んでエラーになってる感じです。

勝手な想像ですが、開発されている方が v5 で構造変えて、v6 にもっていって、v5 はテストしないまま、v6 にフォーカスしてしまっているのではないかと。


# 対処法

### 1. 型を省略する

```js
let result1 = await pool.request()
            .input('input_parameter', value)  // 型省略
            .query('select * from mytable where id = @input_parameter')
```

とりあえず、これで動きます。
`NVarChar型` や `Date型` を明示したい時など困りそうですが。。。


### 2. 変更後の構造で指定する

`tedious` の型に依存しているので、`tedious` から型情報をもっていきます。

```js
let result1 = await pool.request()
            .input('input_parameter', () => ({ type: require('tedious').TYPES.Int }), value)
            .query('select * from mytable where id = @input_parameter')
```

とりあえず、動きますが、これ書くのは嫌ですね。
どこかでプルリク出そうかな。
インターネッツのファイルの更新日時を取得する

とある **kenkooooさんのAtCoderProblems** の Datasetが更新されたら取得する、というプログラムを組もうと思いました。

どうやったら更新情報を取得できるのか…… :thinking: 

っ [file_get_contents使うと $http_response_header がついてくるよ](https://www.php.net/manual/ja/reserved.variables.httpresponseheader.php)

という情報があったんですが、file_get_contents使っちゃうとなぁ…… **目的のデータは460MB以上** なんだよねぇ…… :sweat_smile: 

更新情報を取得するためだけに何度も460MBの転送を発生させてしまうと、kenkooooさんに戦車砲 :bomb: でやられてしまうような気がしたので、別の方法を。

# get_headers()

`get_headers` を使います。
`get_headers` を使って、 `$http_response_header` と同等の情報を取得します。
ヘッダ情報取得だけなので、本体をダウンロードする必要はありません。
（`file_get_contents`を使うと45秒ほどかかりましたが、 `get_headers`の方なら約0.2秒でした）
ヘッダ情報の中の、 `Last-Modified` が最終更新日時です。

# サンプル
```PHP
<?php
    $url = "https://s3-ap-northeast-1.amazonaws.com/kenkoooo/atcoder.sql";

    $data = get_headers($url, 1);
    $time_modify = $data['Last-Modified'];
    echo date("Y-m-d H:i:s", strtotime($time_modify));
```
- 実行結果

```bash
2019-08-13 03:42:06
```
親子関係を変更したときにTransformが書き換わってしまう場合の対処法

# Transform値の引き戻り現象
UnityはGameObjectの親子関係を変更してもワールド座標は維持されるので、位置や角度が変わったりすることはないのが普通です。
しかし、VRChatのアバターなどで、GameObjectの親子関係を変更すると、ローカル座標のほうが維持されてしまい、ワールド座標の位置や角度がおかしくなってしまう現象が発生します。

こんな感じですね。
![EBSZyZuVAAILFFn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275693/1326b997-4d3f-d3fa-9e63-fa60f5b9c59c.png)
※こちらは妻が調整した[シルヴィアさん](https://booth.pm/ja/items/1254604)の改変アバターです

先日、私が発表したスカートDynamicBone設定支援ツール[「SkirtSupporter」](https://sites.google.com/view/skirtsup)でこの現象が発生してしまいました。（修正済です）
いや、それより前から発表している[DynamicBone吊りスカート](https://qiita.com/hoke946/items/c868329ee15fb91a890d)の理論を各自でやってみた方も中にはこの現象が発生していたかもしれません。
それを思うと申し訳ないです。

この現象を突き詰めてみると、そこに組み込まれているDynamicBoneに原因があることがわかりました。
どういう必要があってかはわかりませんが、DynamicBoneの視覚化機能の中に、**内部で保持してるローカル座標をTransformに書き戻す処理が入っています**。

#手操作で発生したときの対処法１
「X」というGameObjectの親を「A」から「B」に変更したい場合とします。
前提として、シーンのどこかに、Rootに「X」が指定されたDynamicBoneが存在するはずです。（多くの場合は「X」そのものにあるでしょうが、他のGameObjectにあっても同じことです。）
問題が発生した後だともう対処できないので、Ctrl+ZやプレハブのRevertなどで状態を戻したところから開始してください。

- 該当のDynamicBoneのRootに他のオブジェクトを設定する（ただし、親でもない無関係のものとする）
- 「X」を「A」から「B」に移動する
- DynamicBoneのRootを「X」に戻す

これでOKです。

#手操作で発生したときの対処法２
親子関係を変更したい対象が沢山あって、対処法１では煩わしい場合です。
一時的にDynamicBoneのスクリプトを書き換えてしまいましょう。

```DynamicBone.cs
    void OnDrawGizmosSelected()
    {
        if (!enabled || m_Root == null)
            return;

        if (Application.isEditor && !Application.isPlaying && transform.hasChanged)
        {
            //InitTransforms();　  <- 一時的にコメントアウト
            SetupParticles();
        }
           :
           :
```
225行目あたり、OnDrawGizmosSelectedの中のInitTransforms();を「//」でコメントアウトします。
これで、GameObjectを参照したときの書き戻しが発生しなくなります。
親子関係の変更を行ってください。

しかし、このままツールのコードを壊しておくのは決して望ましくありません。
**親子関係の変更が終了したら、必ず元に戻しておいてください**。

#スクリプティングの対処法
さて、Editorなどのスクリプトを組もうとする場合ですが、
結論としてはDynamicBoneのコードを破壊せずに根本的に対処する方法が無くて詰みました。
内部の「p.m_InitLocalPosition」「p.m_InitLocalRotation」の値を外部操作で更新できればいいのですが……。
現状、これらの値を書き換えられるpublicメソッドはありません。
良い方法があれば教えてください。

とりあえずの対処法としては、「変更前後の親のワールド座標を完全に一致させる」ことです。
親の座標が一致していれば、ローカル座標が書き戻っても問題なくなります。
変更先のGameObjectの下にもう一つGameObjectを加え、positionとrotation（いずれもワールド座標）を変更前の親と一致させ、そこへ移動させるようにしましょう。
[iterm2 / Python API] 現在フォアグラウンドなセッションのカレントディレクトリを取得する 

iTerm2 バージョン3.3で追加されたPython scripting APIを使って、現在アクティブなセッションのカレントディレクトリを取得する方法です。

![active-session.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78881/b7ec4f3f-a988-0d2e-6b16-1a0365189e14.png)

# 1. スクリプト

`iterm2.run_until_complete`に指定したコルーチンの仮引数（`Connection`型）から`App`オブジェクトを取得し、そこから`current_terminal_window`、`current_tab`、`current_session`プロパティで現在フォアグラウンドなセッションを取得します。

そのセッション内の変数`path`に、カレントディレクトリが格納されているので、`async_get_variable( "path" )`で取得できます。

```python
#!/usr/bin/env python3.7

import iterm2
import os

async def main( connection ):
    
    print( f"Current path on Python script: {os.path.abspath( os.path.curdir )}" )

    app = await iterm2.async_get_app( connection )
    # 現在フォアグラウンドなターミナルウィンドウを取得
    cur_window = app.current_terminal_window
    # ↑のウィンドウで、現在フォアグラウンドなタブを取得
    cur_tab = cur_window.current_tab
    # ↑のタブで、現在フォアグラウンドなセッションを取得
    cur_session = cur_tab.current_session
    # ↑のセッション内の変数から、現在フォアグラウンドなセッションのカレントディレクトリを取得
    cur_path = await cur_session.async_get_variable( "path" )
    print( f"Current path on Foreground session: {cur_path}" )

iterm2.run_until_complete( main )
```

```
# 実行結果（iTerm2のスクリプトコンソールのログより）

Current path on Python script: /
Current path on Foreground session: /usr/local/Cellar
```

ちなみに実行結果より、iTerm2から実行したPythonスクリプト上での現在のディレクトリ（`os.path.curdir`）は、システムのルートディレクトリになっていることが分かります。


# 参考サイト

* [Python API - iterm2](https://www.iterm2.com/python-api/)
* [Variables - iterm2](https://www.iterm2.com/documentation-variables.html)
Tomcatでlogback.xmlの場所を指定する

#はじめに
普段eclipseでjavaアプリの開発をしているときはsrc/main/resources直下（クラスパス上に）logback.xmlを置いています。ですが、開発環境以外ではどこに置けばいいのでしょうか？

tomcatのdockerコンテナ内にwarのアプリをデプロイしてlogback.xmlを反映させる方法を調べました。

#logback.xmlを置く場所

こちらにルールが記載されています。
https://logback.qos.ch/manual/configuration_ja.html#auto_configuration

> 1. logback はクラスパス上でlogback.groovyというファイルを探します。
> 2. 見つからなかったら、今度はクラスパス上でlogback-test.xmlというファイルを探します。
> 3. 見つからなかったら、今度はクラスパス上でlogback.xmlというファイルを探します。
> 4. 何も見つからなかったら、自動的にBasicConfiguratorを使って設定します。ロギング出力は直接コンソールに出力されるようになります。

開発中は1~3で十分です。eclipseのコンソールに出力したり、ファイルに出力したりと。
ポイントは4です。評価環境や本番環境ではこの方法を使って、logback.xmlの場所を設定可能なんです。やり方は簡単です。VMの実行時引数に以下を指定するだけです。eclipseではサーバーの起動時設定でVM引数を設定できるので、試してみて下さい。仮にクラスパス上にlogback.xmlを置いていたとしても、この4の方法の設定が優先されることが確認できるかと思います。

https://logback.qos.ch/manual/configuration_ja.html#configFileProperty

```bash

java -Dlogback.configurationFile=/usr/local/tomcat/conf/logback.xml
```

#dockerのtomcatコンテナに反映させる

さて、本題です。私はdockerのtomcatコンテナにwarをデプロイして実行しようとしていました。
このときにlogback.xmlの場所をどうやって渡すかです。

利用するコンテナイメージは以下になります。
https://hub.docker.com/_/tomcat

tomcatにVMの実行時引数を設定するにはsetenv.shを利用します。
こちらの記事が参考になりました。
http://asuwa.hatenablog.com/entry/20110629/1309356081

> 1) クラスパス
> まんま CLASSPATH。これは追加で指定したいでしょう。でも、catalina.sh 中でクリアされてしまう。なので、このスクリプトの外部からは指定できない。で、catalina.sh から呼ばれるスクリプトに、setclasspath.sh と setenv.sh がある。
setclasspath.sh には、デフォルトで色々書いてあるから、変更したくない（そもそも、既存のファイルに手を入れたくない）。こんな名称のくせに。。
bin の下に setenv.sh を作っておくと読んでくれるので、ここに指定するのがよいのではないかと思う（デフォルトでは setenv.sh は存在しない）。

setenv.shファイルをbin以下に配置しておくと自動でcatalina.shが読み込んでくれます。
catalina.shは上記のtomcatコンテナが起動時に実行されるファイルです。


では簡単なsetenv.shファイルを用意します。

```bash:setenv.sh

#!/bin/bash

JAVA_OPTS="-server \
        -Dfile.encoding=UTF-8 \
        -Dlogback.configurationFile=/usr/local/tomcat/conf/logback.xml"
```

dockerのrunコマンドで、これをCATALINA_HOMEのbin直下に配置します。
ついでにlogback.xmlとwarもコンテナ内にマウントします。

```bash
docker run -p 8080:8080 -d \
   -v /path/to/setenv.sh:/usr/local/tomcat/bin/setnev.sh \
   -v /path/to/logback.xml:/usr/local/tomcat/conf/logback.xml \
   -v /path/to/sample.war:/usr/local/tomcat/webapps/sample.war \
   tomcat:8.5-jdk8-corretto
```

以上のようにすればtomcatに任意のlogback.xmlを渡すことが可能になります。


# logback.xmlの読み込み状況を確認する

こちらはうまく反映されないときの参考になればと思い記載します。

logback.xmlの読込状況を確認するためには、
logback.xml内のconfigurationタグ直下に以下のようにstatusListenerタグを追記して下さい。

```xml:logback.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>
<configuration>
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
  ...
</configuration>
```
するとログにlogback.xmlをどう探しているかなどが出力されます。

```
14:44:54,034 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
14:44:54,035 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
14:44:54,035 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/nishiyama/Develop/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/sample-front/WEB-INF/classes/logback.xml]
```
詳細はスタータスリスナーの登録についてを参照下さい。
https://logback.qos.ch/manual/configuration_ja.html#statusListener


以上
IntelliJ IDEA で .dig を目に優しく扱う

# .digとは

.digは[digdag](https://www.digdag.io/)というタスクスケジューラで扱うファイルの拡張子です。

.digはYAMLで記述されているため、IntelliJでカラーハイライト付きで扱うことができます。


# IntelliJ IDEA で.digを扱うための設定

1. File -> Settings -> Editor > File Types で YAMLを選択
2. 下ウィンドウの「+」をクリックして「*.dig」と入力→ＯＫ→Apply

![yaml_dig_intellij.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395743/d6035690-b591-4f89-be3b-3f73fd596016.png)
golangのjson parseについて(marshal/decode/json.RawMessage)

* golangでjsonをparseする時、いくつか方法があるので、パターン別に自分の使い分けを解説。

## jsonテキストをstructの変数に流し込む(json.Unmarshal)

* jsonテキストをパースする一番よくあるパターン。まあ現実的には同じ関数内で作ったjsonテキストをparseなどしないが…

```golang
package main

import (
	"encoding/json"
	"fmt"
)

type jsonData struct {
	Name string `json:"name"`
	Num  int    `json:"num"`
}

func main() {
	jsonStr := `{"name":"Apple","num":3}`
	jsonBytes := []byte(jsonStr)
	var d jsonData
	json.Unmarshal(jsonBytes, &d)
	fmt.Println(d.Name, d.Num)
}
```

## io.Readerから１回でstructの変数に流し込む場合(json.NewDecoder)

* よくあるパターン。例えばサーバのapiに`http.Get`でリクエストして、Response typeのBody fieldをparseするような場合だ。
* サンプルとかも多いので解説の必要はないだろう。シンプルに以下でいい。

```golang
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type respBody struct {
	Result  int
	Message string
}

func main() {
	resp, err := http.Get("どっかのAPI")
	var data respBody
	err = json.NewDecoder(resp.Body).Decode(&data)
	if err != nil {
		fmt.Println(err.Error())
	}
}
```
* このパターンの場合、`resp.Body`は`io.Reader`で読み込みは一度しかできない。

## io.Readerから複数回でstructの変数に流し込む場合(json.Unmarshal, json.RawMessage)

* APIからのresponseをparseする場合に割とあるのがこれ。responseの構造がapiの結果によって変わる場合などだ。200応答と、500応答とでpayloadの構造が違う…とか。
* この場合、一部のfieldだけparseしてから残りを処理分岐したい。
* io.Readerのままだと複数回読み込みはできないので、[]byteなどでデータを持っておく必要があるが、加えて一度parseしたfieldを再度parseするというのはどうにもダサい。
* 以下のようにparseを遅らせたい項目を`json.RawMessage`にしておくと、後から`json.Unmarshal`を行うことができる。
* `json.RawMessage`は`[]byte`を型定義したものなので、そのまま`json.Unmarshal`で処理可能だ。

```golang
package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
)

type respBody struct {
	Result  string          `json:"result"`
	Payload json.RawMessage `json:"payload"`
}

type respPayloadOK struct {
	Message string `json:"message"`
}

type respPayloadErr struct {
	ErrCode    int    `json:"errCode"`
	ErrMessage string `json:"errMessage"`
}

func main() {
	resp, err := http.Get("どっかのAPI")

	bodyBytes, err := ioutil.ReadAll(resp.Body)

	var data respBody

	if err = json.Unmarshal(bodyBytes, &data); err != nil {
		fmt.Println(err.Error())
		return
	}

	if data.Result != "ok" {
		var payloadErr respPayloadErr
		if err = json.Unmarshal(data.Payload, &payloadErr); err != nil {
			fmt.Println(err.Error())
			return
		}
		fmt.Println(payloadErr.ErrCode, payloadErr.ErrMessage)
		return
	}

	var payload respPayloadOK
	if err = json.Unmarshal(data.Payload, &payload); err != nil {
		fmt.Println(err.Error())
		return
	}

	fmt.Println(payload.Message)
}
```
GCIデータサイエンティスト育成講座の解答を作ってみた(5章)

松尾研究室のGCIデータサイエンティスト育成講座やってみた

解答が無かったので、自分で作ってみました。間違えていたらすみません、教えて頂けると嬉しいです
https://weblab.t.u-tokyo.ac.jp/gci%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88%E8%82%B2%E6%88%90%E8%AC%9B%E5%BA%A7%E3%83%BB%E6%BC%94%E7%BF%92%E3%82%B3%E3%83%B3%E3%83%86/


5.3.1 Scipy

<練習問題 1>
以下のデータに対して、線形補間の計算をして、グラフを描いてください。
<練習問題 2>
2次元のスプライン補間をして上記のグラフに書き込んでください(2次元のスプライン補間はパラメタをquadraticとします。)

```python:
x = np.linspace(0, 10, num=11, endpoint=True)
y = np.sin(x**2/5.0)
plt.plot(x,y,'o')
plt.grid(True)
x1 = np.linspace(0, 10, num=100, endpoint=True)
f=interpolate.interp1d(x, y,'linear')
f2=interpolate.interp1d(x, y,'cubic')
plt.plot(x1,f(x1),"-",x1,f2(x1),"--")
```
<練習問題 1>
以下の行列に対して、特異値分解をしてください。
B = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])

```python:
B = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
U, s, Vs = sp.linalg.svd(B)
m, n = B.shape
S = sp.linalg.diagsvd(s,m,n)
print("U.S.V* = \n\n",U@S@Vs)
```

<練習問題 2>
以下の行列に対して、LU分解をして、 𝐴𝑥=𝑏 の方程式を解いてください。

```python:
#データの準備
A = np.identity(3)
print(A)
A[0,:] = 1
A[:,0] = 1
A[0,0] = 3
b = np.ones(3)
(LU,piv) = sp.linalg.lu_factor(A)
L = np.identity(3) + np.tril(LU,-1)
U = np.triu(LU)
P = np.identity(3)[piv]
# 解を求める
x = sp.linalg.lu_solve((LU,piv),b)
```


<練習問題 1>
以下の積分を求めてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/a9c2f923-5503-ef6b-2f17-42c1b2b8063a.png)

```python:
integrate.quad(lambda x:(x+1)**2,0,2)
```

<練習問題 2>
cos関数の範囲 (0,𝜋) の積分を求めてみましょう。

```python:
from numpy import cos
integrate.quad(cos,0,math.pi/1)
```

<練習問題 1>
以下の関数が0となる解を求めましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/e7f2579c-ee7c-0322-9827-21e60201e462.png)


```python:
def f(x):
    return 5*x-10
sol1=fsolve(f,0)
print(sol1)

```
<練習問題 2>
以下の関数が0となる解を求めましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408729/16a0c2f2-5b31-0326-9de4-b15b14ef9db2.png)


```python:
def f2(x):
    return x**3-2*x**2-11*x+12
sol2=fsolve(f2,0)
print(sol2)
```

5.4 総合問題
5.4.1 総合問題1
以下の行列に対して、コレスキー分解を活用して、𝐴𝑥=𝑏の方程式を解いてください。

```python:
A = np.array([[5, 1, 0, 1],
              [1, 9, -5, 7],
              [0, -5, 8, -3],
              [1, 7, -3, 10]])
b = np.array([2, 10, 5, 10])


L = sp.linalg.cholesky(A)

t = sp.linalg.solve(L.T.conj(), b)
x = sp.linalg.solve(L, t)
```
```
# 解答
print(x)
[-0.051  2.157  2.01   0.098]
```

5.4.3 総合問題3
以下の最適化問題をSicpyを使って解いてみましょう。
```

```
C > datetime > 2019/06/31をstrptime()はどう扱うか > 2019/06/31として格納 | mktime()だと2019/06/31は2019/07/01になる | C++20 std::chronoのカレンダ

```txt:動作環境
C++ Builder 10.2 Tokyo
C (gcc 8.3) @ ideone
```

### C++ BuilderでのエラーとCのエラー

C++ Builder 10.2 Tokyoにおいて、`EncodeDate(2019, 6, 31)`はエラーになる。

一方で、strftime()に関してはどういうことになるかを確認した。

### man

- [STRPTIME](https://linuxjm.osdn.jp/html/LDP_man-pages/man3/strptime.3.html)

### 実装

https://ideone.com/9gYbK9

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
int main(void) {
	struct tm tm;
	char buf[255];
 
	memset(&tm, 0, sizeof(struct tm));
	strptime("2019-06-31", "%Y-%m-%d", &tm);
	strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
	printf("%s\n", buf);
 
	return 0;
}
```

```txt:stdout
31 Jun 2019 00:00
```

6/31として格納された。


### 教えていただきました

@SaitoAtsushi さんの[コメント](https://qiita.com/7of9/items/143b160fb4f8b22d051a/#comment-5647693722f381711303)にてmktime を教えていただきました。

情報感謝です。

@yumetodo さんの[コメント](https://qiita.com/7of9/items/143b160fb4f8b22d051a/#comment-c8b6f21443832f8e4f74)にてC++20の`std::chrono`のカレンダについて教えていただきました。

情報感謝です。
[Corda]Token SDK 入門（してみた

お盆休みにこんにちは。
どーも、のぶこふです。

今回は、CordaでもToken SDKがあるというのを
風の噂で耳にしたので、
「ちょいと触ってみるか〜〜〜」な記事です。

内容は[Corda githubのReadme](https://github.com/corda/token-sdk)を参考に実施します。
Token SDKについては[ホワイトペーパー](https://github.com/corda/token-sdk/blob/master/design/design.md)を参照してください。

ネタとしては、他にもCordaでのJDBC使用方法であったり、
Notaryさんのちょっとヤバメな話とかあるのですが、
今回は、おいておきます。

## 環境
今回は、Mac環境で実施していきます。

## インストール
既存のソースコードにSDKを導入するのも良いのですが、
~~手抜きで~~ テンプレを使用します。

```terminal:適当なディレクトリにcloneして、ブランチを切り替えます。
git clone http://github.com/corda/cordapp-template-kotlin
cd cordapp-template-kotlin
git checkout token-template
```

## ビルド＆ノード起動
おなじみのコマンドを実行します。
「IntelliJで開きましょう」的なコメントがありますが、
気にせずにコマンド叩いて問題なしです。

```terminal:おなじみのコマンド
./gradlew clean deployNodes
./build/nodes/runnodes
```

## 実行
PartyAのノードで下記コマンドを実行します。

```terminal:PartyAで実行
start ExampleFlowWithFixedToken currency: GBP, amount: 100, recipient: PartyB
```

```terminal:実行結果
>>> start ExampleFlowWithFixedToken currency: GBP, amount: 100, recipient: PartyB

 ✅   Starting
➡️   Done
Flow completed with result: SignedTransaction(id=669A6458BFA5A684C03ECA139DED8CC631AF277EC2890808FC6F94BC902E1CB9)

>>> 
```

PartyBで確認してみます

```terminal:PartyBで実行
run vaultQuery contractStateType: com.r3.corda.lib.tokens.contracts.states.AbstractToken
```

```terminal:実行結果
>>> run vaultQuery contractStateType: com.r3.corda.lib.tokens.contracts.states.FungibleToken
states:
- state:
    data: !<com.r3.corda.lib.tokens.contracts.states.FungibleToken>
      amount: "100.00 TokenType(tokenIdentifier='GBP', fractionDigits=2) issued by\
        \ PartyA"
      holder: "O=PartyB, L=New York, C=US"
      tokenTypeJarHash: null
    contract: "com.r3.corda.lib.tokens.contracts.FungibleTokenContract"
    notary: "O=Notary, L=London, C=GB"
    encumbrance: null
    constraint: !<net.corda.core.contracts.SignatureAttachmentConstraint>
      key: "aSq9DsNNvGhYxYyqA9wd2eduEAZ5AXWgJTbTEw3G5d2maAq8vtLE4kZHgCs5jcB1N31cx1hpsLeqG2ngSysVHqcXhbNts6SkRWDaV7xNcr6MtcbufGUchxredBb6"
  ref:
    txhash: "669A6458BFA5A684C03ECA139DED8CC631AF277EC2890808FC6F94BC902E1CB9"
    index: 0
statesMetadata:
- ref:
    txhash: "669A6458BFA5A684C03ECA139DED8CC631AF277EC2890808FC6F94BC902E1CB9"
    index: 0
  contractStateClassName: "com.r3.corda.lib.tokens.contracts.states.FungibleToken"
  recordedTime: "2019-08-13T04:13:49.336Z"
  consumedTime: null
  status: "UNCONSUMED"
  notary: "O=Notary, L=London, C=GB"
  lockId: null
  lockUpdateTime: "2019-08-13T04:13:49.390Z"
  relevancyStatus: "RELEVANT"
  constraintInfo:
    constraint:
      key: "aSq9DsNNvGhYxYyqA9wd2eduEAZ5AXWgJTbTEw3G5d2maAq8vtLE4kZHgCs5jcB1N31cx1hpsLeqG2ngSysVHqcXhbNts6SkRWDaV7xNcr6MtcbufGUchxredBb6"
totalStatesAvailable: -1
stateTypes: "UNCONSUMED"
otherResults: []

>>> 
```

発行されていることが確認できました。


## おわりに

ということで、本当にちょっとだけ触ってみました。
次回あたりでは、独自のトークンを作成したりしてみましょう。

今回はここまでです。
ありがとうございました。
Kerasの損失関数履歴をデータフレームに変換する

#Kerasの損失関数の履歴が欲しい
　自分の作ったモデルがどのように収束していくかは非常に大事な情報です。
そこで、Kerasの損失関数（などの）履歴をファイルに残すために、Pandasのデータフレームに変換するスクリプトを紹介します

```Python
history_callback = model.fit(x_train, y_train, ....)
loss_history = history_callback.history
```
これで履歴が記録されます

```Python
loss_history #dict型
list_losss_history = list(loss_history.items()) #listへ変換
print(type(loss_history),type(list_losss_history))
print(list_losss_history)
```
出力

    <class 'dict'> <class 'list'>
    [('loss', [0.5525253211575696, 0.4036650247471646, 0.36141999579291056, 0.33595747268301807, 0.3177382633604555, 0.29891023940306444, 0.2881778943508099, 0.27792962343876176, 0.26560747584624167, 0.25740950032279025]), ('val_acc', [0.8358461538461538, 0.8772307692307693, 0.8713846153846154, 0.8776923076923077, 0.8813846153846154, 0.8852307692307693, 0.8812307692307693, 0.8816923076923077, 0.8872307692307693, 0.9003076923076923]), ('val_loss', [0.4148623236967967, 0.35430374641487233, 0.3401262025305858, 0.33813549585525804, 0.3276629987571102, 0.30808376993124303, 0.32132247155217025, 0.340628393916843, 0.30153624791250777, 0.2850437596107905]), ('acc', [0.8024273504273505, 0.8550427350427351, 0.8704615384615385, 0.8781880341880342, 0.8857264957264958, 0.8917264957264958, 0.8942222222222223, 0.8978803418803418, 0.9025982905982906, 0.9046666666666666])]

#変換するスクリプト
```Python
list2D=[]
colname=[]
for i in range(len(list_losss_history)):
    list2D.append(list_losss_history[i][1])#単純にリストに追加していく
    colname.append(list_losss_history[i][0])
hist_data = pd.DataFrame(np.array(list2D).T,columns=colname)
print(hist_data)
```
出力

           loss   val_acc  val_loss       acc
    0  0.552525  0.835846  0.414862  0.802427
    1  0.403665  0.877231  0.354304  0.855043
    2  0.361420  0.871385  0.340126  0.870462
    3  0.335957  0.877692  0.338135  0.878188
    4  0.317738  0.881385  0.327663  0.885726
    5  0.298910  0.885231  0.308084  0.891726
    6  0.288178  0.881231  0.321322  0.894222
    7  0.277930  0.881692  0.340628  0.897880
    8  0.265607  0.887231  0.301536  0.902598
    9  0.257410  0.900308  0.285044  0.904667

あとは、ファイルにセーブすればOKです。
###参考URL
https://codeday.me/jp/qa/20190301/346082.html
python – Kerasの損失出力をファイルに記録する方法
Lossのみの結果を取り出す方法が書いてあります
手動でapp/proxy/entity/src/Eccube/Entity以下のエンティティ拡張用のファイルを消してしまったときの対処法


手動で`app/proxy/entity/src/Eccube/Entity`以下のエンティティ拡張用のファイルを消してしまったとき、以下のようなエラーが発生する。

```
FatalErrorException
Compile Error: Symfony\Component\Debug\DebugClassLoader::loadClass(): Failed opening required
 '(プロジェクトルート)/app/proxy/entity/src/Eccube/Entity/ProductClass.php' 
(include_path='.:')
```

composerのオートローディング時に削除したファイルを読み込んでしまうことが原因のため、composerのオートローディングのクラスマップを再生成することにより、解決する。


```
$ composer dump-autoload
Generated optimized autoload files containing 7238 classes
```

上記コマンドで対応付けのためのクラスマップが生成される。
Rubymine　まとめ

##RubyMine
RubyMineを最近使い始めたので、備忘録として各種ショートカットを載せておきます。

##Shift+Shift
シフトを二回押せば、クラス、ファイル、シンボルなど調べることができ、該当するものがあればそこまでジャンプできる

##Command+b
コマンドとbを押せば、変数やメソッドの定義元までジャンプできる
##Command+Shift+f
全文検索。該当するwordをプロジェクトの中から調べてくれる

##Option+Fn+F12
RubyMine内でターミナルを開くことができる
Python 10進数で回文

#問題
10進数、2進数、8進数の何で表現しても回文数となる数のうち、
10進数の10以上で最小の値を求めてください。
例）9（10進数）= 1001（2進数）= 11（8進数）
　※この例は10進数で10未満なので対象外
引用「プログラマ脳を鍛える数学パズル　著者 増井敏克」


#回答
```answer.py
num = 11
while num > 0:
    if str(num) == str(num)[::-1] and format(num, "b") == format(num, "b")[::-1] and format(num, "o") == format(num, "o")[::-1]:
        print("RESULT: ", num)
        break
    num += 2

# => RESULT: 585
```

#修正後
```answer_after.py
num = 11
while True:
    if all(f'{num:{t}}' == f'{num:{t}}'[::-1] for t in 'dob'):
        print("RESULT:", num)
        break
    num += 2
```

#つまづいたところ
10進数を変換！ということで、
はじめに安易に組み込み関数の`bin()`と`oct()`を使ってしまいました。
しかしそれぞれにプレフィックスが追加されてしまい、
回文数になりませんでした。
`format`に直したところうまくいきました。
また、スライスのところも`reversed()`から修正したところになります。
初めてスライスを使ったような気がします。

#修正追記
@shiracamus様にコメントをいただきそのまま修正後としました、
ご教示いただきありがとうございました。

こちらの方がかなりスッキリしていますね。
all関数を使い、if文中の全ての要素がTrueの時だけ、
`print("RESULT:", num)`を返します。
これでとりあえず`and`はいらなくなりますね。

f-stringとジェネレータ式によって中身がガラッと変わりました。
f-stringは文字列の前に`f`または`F`を置きます。
そうすると文字列中の置換箇所`{}`内に変数をそのまま指定することができます。
`f'{num:{t}}'`の`num`は11、13、15・・・となるわけですね。

次に`t`の部分です。
ここでジェネレータ式が関わってくると思うんですが理解が及ばず・・・
わかった範囲では、
`f'{num:{t}}'`の`t`には`'dob'`をfor文で回した`d`、`o`、`b`が入るみたいです。

f-stringとジェネレータ式によって、
`f'{num:{t}}'`ははじめに`f'{11:d}'`になります。
さらに`t`の部分が`d`なら10進数に変換、
`o`、`b`ならそれぞれ8進数、2進数に変換となるわけですね。

あとはそのままの状態と反転させた時がTrueであれば、
その値を返してbreakで終了、
Trueでなければ2加算して・・・と繰り返しとなります。

こんなところで追記は以上となります。
ご拝読ありがとうございました。
Railsのフロントエンド環境をwebpackにした


タイトルどおりRailsのフロントエンド環境をwebpackにしました。

## 前提

- Rails 5.2.1
- 開発はdockerを使ってる
- 既存はSprocketsを使ってる
- 本番はAWSで稼働してる
- deployにはcapistranoを使用している

## 対応方針
https://qiita.com/necojackarc/items/afa674ab10aafa9784eb

基本はこれをほぼパクった(本当に感謝してます)
deployのことを考えるとSprocketsのいいところを残しつつ、JS周りをnpmに寄せるのが良さそうかと思いました。
なるべくgem依存をなくしたかったので、webpackerも使っておらずwebpackだけです。

参考にした記事とはwebpackのバージョンが恐らく変わってるのでその辺の書き方だけ補足しておきます。

css周りは特にいじってないのでそのままです。
app/assets/stylesheets以下にscssで書いてるのを配信
foremanは今の所使ってないが、必要になったら使う予定

## webpackの設定

- webpack 4.39
- webpack-cli 3.3.6

```frontend/config/webpack.config.js
webpack = require('webpack')
const path = require('path')

// Sprocketsを使わずにwebpackだけでやるなら、hashをつける
// let fileName = argv.mode == 'development' ? '[name].js' : '[name]-[hash].js';
module.exports = (env, argv) => {
  return {
    entry: {
      application: './src/javascripts/application.js',
    },
    output: {
      path: path.resolve(__dirname, '../../app/assets/javascripts'),
      filename: [name].js
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: [
            {
              loader: "babel-loader",
              options: {
                presets: [
                  "@babel/preset-env"
                ]
              }
            }
          ]
        },
      ]
    },
    plugins: [
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
      })
    ]
  }
}
```

また、package.jsonのscriptsの書き方も変えました。

```frontend/package.json
  "scripts": {
    "release": "webpack --mode production --config config/webpack.config.js",
    "build": "webpack --mode development --devtool inline-source-map --open --config config/webpack.config.js",
    "watch": "webpack --mode development --devtool inline-source-map --watch --config config/webpack.config.js"
  },
```

あとはapplication.jsをいい感じに修正を加えます

```frontend/src/javascripts/application.js
import * as jquery from 'jquery';
global.$ = jquery;

import Rails from 'rails-ujs';
Rails.start();

import * as ActiveStorage from 'activestorage';
ActiveStorage.start();

import 'bootstrap';
import 'popper.js';

import './hogehoge.js'; //  自作のjs
```

一応これで動いたんですが、デプロイ時にエラーになりました。
参考記事通りに .gitignoreに/app/assets/javascriptsを入れたことで、capistranoで以下のようなエラーが出ました。

`Sprockets::ArgumentError: link_directory argument must be a directory`

javascriptsのフォルダ自体は消すとダメだと思い以下のように修正したら動きました。

```gitignore
- /app/assets/javascripts
+ app/assets/javascript/*.js
```

## 参考リンク
- https://speakerdeck.com/tomof/webpackgahe-gu-bi-yao-de-he-gu-fen-kariduraifalseka
AzureストレージとSnapを使用したNextcloud構築 

# はじめに
メモ書きです。
Azureのファイルストレージをマウントし、NextCloudで利用します。
Snapを使用しようします。個人使用です。ちゃんとやる人はマニュアルでお願いします。

# サーバ環境
今回の手順は、以下の環境で実施。

* Ubuntu 18.04

# 手順
## AzureVMを作成後
ログイン後ルートで作業を実施します。

```
$ sudo -i
```

## インストール

### 1. snapでインストール

```
$ snap install nextcloud
```
### 2.ファイアウォールの設定 
F/Wを設定します。
※作業後はAzure側で22番ポートをDenyにしておく。SSHで作業するときだけAllowにする。

```
$ ufw enable
$ ufw allow 22
$ ufw allow 80
$ ufw allow 443
$ ufw reload
```

### 3.nextcloudのポートを指定し、SSL化します。

```
snap set nextcloud ports.http=80 ports.https=443
nextcloud.enable-https lets-encrypt
```

### 4. 外付けマウントの記憶媒体を許可します。

```
snap connect nextcloud:removable-media
```

### 5. Azureポータルにログインし、マウントコマンドをコピーし修正。

※以下例
※ディレクトリを0770としないとログイン画面がでてきません。

```
mkdir /mnt/<ストレージアカウント名>
 if [ ! -d "/etc/smbcredentials" ]; then sudo mkdir /etc/smbcredentials; fi
 if [ ! -f "/etc/smbcredentials/<ストレージアカウント名>.cred" ]; then     sudo bash -c 'echo "username=<ストレージアカウント名>" >> /etc/smbcredentials/<ストレージアカウント名>.cred';     sudo bash -c 'echo "password=<固有>" >> /etc/smbcredentials/<ストレージアカウント名>.cred'; fi
chmod 600 /etc/smbcredentials/<ストレージアカウント名>.cred
bash -c 'echo "//<ストレージアカウント名>.file.core.windows.net/nextcloud /mnt/<ストレージアカウント名> cifs nofail,vers=3.0,credentials=/etc/smbcredentials/<ストレージアカウント名>.cred,dir_mode=0770,file_mode=0777,serverino" >> /etc/fstab'
mount -t cifs //<ストレージアカウント名>.file.core.windows.net/nextcloud /mnt/<ストレージアカウント名> -o vers=3.0,credentials=/etc/smbcredentials/<ストレージアカウント名>.cred,dir_mode=0770,file_mode=0777,serverino

```

### 6. データ保存場所をNextcloud側で変更します。
こんな風にしなくても、管理者メンバー作成する前であればとあるコンフィグで変更が可能らしい。

```
mkdir /mnt/<ストレージアカウント名>/data
```

```
nano /var/snap/nextcloud/current/nextcloud/config/config.php
```

```
  'datadirectory' => '/mnt/<ストレージアカウント名>/data',
```

```
snap disable nextcloud
```

すでに作成されたデータをコピーまた移動してあげます。ちょっとgdgdな手順。

```
cp -r /var/snap/nextcloud/common/nextcloud /mnt/<ストレージアカウント名>/data
```

```
snap enable nextcloud
```

```
touch .ocdata
```

```
snap restart nextcloud
```

# あとがき
本来はBlobストレージに挑戦していましたが、うまくいきませんでした。
SMBならうまくいくかもと思いやってみました。

8/15追記 BlobfuseでマウントしたAzure Blobストレージは
permissionが変更できず、0777？0770?しか付与できないっぽいので、ログイン画面に遷移しません。
初回ログインはいけるんですよね。残念。

注意点はsnapではwebサーバのコンフィグはいじれません。※たぶん

## 参考
https://www.wintellect.com/nextcloud-and-azure-blob-storage-a-match-made-in-the-cloud/
[メモ] NanoPi NEO2 で SoftEther を動かす

NanoPI NEO2 で SoftEther を動かした時のメモです。OS は [Armbian Buster](https://www.armbian.com/nanopi-neo-2/)、ローカルブリッジには USB 接続の有線 LAN アダプターを使用しました。

# OS のインストール

詳しくは [[メモ] NanoPi NEO2 を Armbian で使う](https://qiita.com/sgr@github/items/3807bd587cb893d25a9a) をご覧ください。 

![CA344597-FB99-4386-842F-44CB5FE1CCF1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18365/85bca065-25f0-d7bf-d0e1-45fec8cbda90.jpeg)


# SoftEther のビルドとインストール

```shell-session
sudo apt install libreadline-dev libncurses-dev clang
wget https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/releases/download/v4.29-9680-rtm/softether-src-v4.29-9680-rtm.tar.gz
tar zxvf softether-src-v4.29-9680-rtm.tar.gz
cd v4.29-9680/
./configure
```

生成された Makefile を編集し、インストール先を `/opt/softether` コンパイラを clang にしました。

```patch:Makefile.patch
--- src/makefiles/linux_64bit.mak       2019-02-28 20:05:23.000000000 +0900
+++ Makefile    2019-08-13 13:49:42.316522782 +0900
@@ -60,7 +60,7 @@
 
 # Variables
 
-#CC=gcc
+CC=clang
 
 OPTIONS_COMPILE_DEBUG=-D_DEBUG -DDEBUG -DUNIX -DUNIX_LINUX -DCPU_64 -D_REENTRANT -DREENTRANT -D_THREAD_SAFE -D_THREADSAFE -DTHREAD_SAFE -DTHREADSAFE -D_FILE_OFFSET_BITS=64 -I./src/ -I./src/Cedar/ -I./src/Mayaqua/ -g -fsigned-char -m64
 
@@ -70,11 +70,11 @@
 
 OPTIONS_LINK_RELEASE=-O2 -fsigned-char -m64 -lm -ldl -lrt -lpthread -lssl -lcrypto -lreadline -lncurses -lz
 
-INSTALL_BINDIR=/usr/bin/
-INSTALL_VPNSERVER_DIR=/usr/vpnserver/
-INSTALL_VPNBRIDGE_DIR=/usr/vpnbridge/
-INSTALL_VPNCLIENT_DIR=/usr/vpnclient/
-INSTALL_VPNCMD_DIR=/usr/vpncmd/
+INSTALL_BINDIR=/opt/softether/bin/
+INSTALL_VPNSERVER_DIR=/opt/softether/vpnserver/
+INSTALL_VPNBRIDGE_DIR=/opt/softether/vpnbridge/
+INSTALL_VPNCLIENT_DIR=/opt/softether/vpnclient/
+INSTALL_VPNCMD_DIR=/opt/softether/vpncmd/
 
 ifeq ($(DEBUG),YES)
        OPTIONS_COMPILE=$(OPTIONS_COMPILE_DEBUG)
```

ビルドし、インストールします。

```shell-session
make
sudo mkdir -p /opt/softether/bin
sudo make install
```

# vpnserver の動作確認

vpnserver を動かす前に、 [OpenSSL default version and security level raised](https://www.debian.org/releases/buster/amd64/release-notes/ch-information.en.html#openssl-defaults) を参考に、 `/etc/ssl/openssl.cnf` を編集します。

```config
[system_default_sect]
#MinProtocol = TLSv1.2
#CipherString = DEFAULT@SECLEVEL=2
MinProtocol = None
CipherString = DEFAULT
```

vpnserver を手動で動かし動作確認します。設定には vpncmd や [VPN サーバー管理マネージャ](https://ja.softether.org/4-docs/1-manual/2/2.4) を用います。

```shell-session
sudo /opt/softether/bin/vpnserver start
sudo /opt/softether/bin/vpnserver stop
```

# 自動起動設定

動作が確認できたら、systemd の自動起動設定を行います。

```config:/etc/systemd/system/vpnserver.service
[Unit]
Description=Softether VPN Server Service
After=network.target

[Service]
Type=forking
User=root
ExecStart=/opt/softether/bin/vpnserver start
ExecStop=/opt/softether/bin/vpnserver stop
Restart=on-abort

[Install]
WantedBy=multi-user.target
```

手動でサービスを起動し、動作確認します。

```shell-session
sudo systemctl daemon-reload
sudo systemctl start vpnserver
```

問題なければサービスを有効にします。

```shell-session
sudo systemctl enable vpnserver
```
Virtual DOM(仮想DOM)とShadow DOMの違い

名前は似てるけど中身は全然違うんじゃ〜

# Virtual DOM (仮想DOM)
VueやReactなどのJavaScriptのライブラリ/フレームワークにおける**Viewの設計図**。VueやReactは、画面上の文字列などが変更された直後に、内部的に仮想DOMを設計図として作り、新旧の設計図を見比べて内容が変更されている箇所だけ実DOM（実際にHTMLで描画されるDOM）を書き換える（＝**差分更新**）。大体の場面において仮想DOMは実DOMよりも速いとされる。
Qiitaでは「[なぜ仮想DOMという概念が俺達の魂を震えさせるのか](https://qiita.com/mizchi/items/4d25bc26def1719d52e6)」が有名ですね。

# Shadow DOM
Web Componentsにおける技術のひとつで、**カプセル化されたDOM**またはそれを実装するための技術のこと。Shadow DOMはメインのドキュメントツリーには存在せず、独自のサブドキュメントツリーを形成し、それを元に画面に描画される。例えば、Chromeの`<video>`タグは内部的にShadow DOMで実装されており、videoタグを使うと再生ボタンや時間表示・音量ゲージなどが表示されるが、devtoolsのHTML文書構造からはこれらのDOMは確認できないようになっています。
WebComponentsについては拙作「[【コードなしで理解する】 WebComponents超入門](https://qiita.com/aykusu/items/a39dbbeced42eb5702ab)」をご覧ください。

## 参考
- [Virtual DOM vs Shadow DOM](http://wilsonyu.io/virtual-dom-vs-shadow-dom/)
- [Learn the differences between Shadow DOM and Virtual DOM](え)
「問題が発生したため、プロセス「android.process.acore」を終了します。」報告

機種：SHARP QAUOS SH-RM02
Androidバージョン 5.0.2
カーネルバージョン 3.4.0
ビルド番号01.00.04

>問題が発生したため、プロセス「android.process.acore」を終了します。
OK

という画面が出る。


アプリによっては、OKを押せば操作が継続できる場合と、
OKを押すとアプリが終了する場合がある。

#以前からあった不具合

電話アプリで、電話が取れる相手と、着信を押しても取れない相手がある。
同じ人で取れる場合と取れない場合があるような気もする。


四重苦：Wi-Fiが繋がらない。google playがloginできない。携帯が繋がらない。＜３解決＞電話出れない＜１未解決＞
https://qiita.com/kaizen_nagoya/items/cb208dae9a9b8fbedb91


#アプリが終わる場合

「電話」アプリ
「設定」アプリの「プロフィール」



#アプリはそのまま動く場合

「設定」アプリの「ディスプレイ」


#警告が今、出ていないアプリ
過去に出たかどうかの記録を取ってなく、記憶は定かではない。今日でなかったのは次の５つ。

twitter
facebook
instagram
SHカメラ
楽天ポイント


# 対応
電源ボタンを2秒ほど押す。
「電源を切る」「再起動する」の表示を長押し。
「再起動してセーフモードに変更」の表示がでたら「ok」
再起動
「android.process.acore」表示でない
電源ボタンを2秒ほど押す。
再起動

数時間はエラーがでなくて、夜安心して眠った。
朝になったら、また
>問題が発生したため、プロセス「android.process.acore」を終了します。

#other error
Lineアプリで　Line ポイントを選ぶと
>一時的なエラーによりリクエストが完了しませんでした。もう一度お試しください。再試行

再試行を押すと、「ウェブページへのアクセス不可」という画面が少し暗く表示して、上記エラーに戻る。

##状況

アプリで

電話 1.48MB
電話 6.25MB
電話 2.35MB
電話/SMS用ストレージ 748KB

と似たアイコンがならんでいる。最初と最後が同じ３次元アイコンで色が濃く、
３番目のがややちいさく、２番目のが一番小さい。


#参考資料(reference)

android.process.acoreを終了しますの表示の際の５つの解決法｜スマホの解決法
公開日 : 2018年3月7日 / 更新日 : 2019年6月5日
https://www.enjoylife.fun/android-process-acore


【アンドロイド】「android process acore を終了します」の場合は？
2016-06-23
https://apicodes.hatenablog.com/entry/processacore

#文書履歴(document history)
ver. 0.01 初稿　20190813
ver. 0.02 対応追記　20191003
ver. 0.03 翌日再度出現　20191004
ver. 0.04 翌々月出現 20191202


<a href="https://b.hatena.ne.jp/entry/s/qiita.com/kaizen_nagoya/items/e644faeeefecc78dff06" class="hatena-bookmark-button" data-hatena-bookmark-layout="basic-label-counter" data-hatena-bookmark-lang="ja" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a><script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>

https://b.hatena.ne.jp/guide/bbutton
TypeScript + Reduxの型のimportでつまずいた件

TypeScriptでReduxを書いていて、Actionの型を`redux`からimportしようとしたとき下記のエラーが出て困ったので、（とても簡単ですが）解決法をメモしておきます。

```js

import { Action } from 'redux'
```
と書くと、「"Action"はreduxのexportメンバーにないよ！」って怒られました。

```js

TS2305: Module '"/node_modules/redux/es/redux"' has no exported member 'Action'.
```
下記のように記述するとエラーは消えたのですが、

```js

import { Action } from 'redux/index.d.ts'
```

こんな書き方あまり見たことないし、ちょっと気持ち悪かったので数時間調べて最終的にstackoverflowで聞いたところ、

> Redux provides it's own type definitions, so you don't need to install them from Definitely Typed. If you uninstall @types/redux, TypeScript should use those provided by the redux package, and your import will work.

> [和訳] Redux自体が型定義を提供しているので、TypeScript型定義ファイル（dts）をインストールしなくていいよ。@types/reduxをアンインストールすればTypeScriptはReduxの型定義を読みに言ってエラーは消えるよ。

とのことで、早速試したところ動きました。`@types/redux`はdeprecatedになっていたみたいですね。

参考: https://stackoverflow.com/questions/57470757/typescript-cannot-find-imported-type-action
C ++ APIを使用したGoogle Edge TPU

C ++を使用してモデルで推論を実行する場合、主に使用するので **TensorFlow Lite C ++ API** のある程度の経験が必要です。 追加の`edgetpu.h`ファイルには、Edge TPUデバイスを指定するコンテキストオブジェクトや、TensorFlow Lite `Interpreter`APIでカスタムopを登録するためのAPIなど、APIの小さなセットのみが含まれています。 （Edge TPU C ++ APIには、Python APIにあるような推論を実行するための便利なメソッドは含まれていません。）

C ++ Edge TPU APIの詳細については、`edgetpu.h`ファイルを読む必要がありますが、基本的な使用には以下が必要です:

- `EdgeTpuContext`：これにより、Edge TPUに関連付けられたオブジェクトが作成されます。 通常、使用するEdge TPUは1つだけなので、これを `EdgeTpuManager :: OpenDevice（）` でインスタンス化できます。 ただし、複数のEdge TPUを使用することは可能であるため、このメソッドはオーバーロードされるため、使用するEdge TPUを指定できます。

- `kCustomOp` and `RegisterCustomOp（）`：`tflite :: Interpreter`がコンパイル済みモデル内でEdge TPUカスタムopを実行する方法を理解するために、これらを`tflite :: BuiltinOpResolver.AddCustom（）`に渡す必要があります。

一般に、記述する必要があるコードには次の要素が含まれます:

1.コンパイル済みのEdge TPUモデルを`FlatBufferModel`としてロードします:

```
const std::string model_path = "/path/to/model_compiled_for_edgetpu.tflite";
std::unique_ptr<tflite::FlatBufferModel> model =
    tflite::FlatBufferModel::BuildFromFile(model_path.c_str());
```
このモデルは、以下の`tflite :: InterpreterBuilder（）`で必要です。

2.`EdgeTpuContext`オブジェクトを作成します:

```
std::shared_ptr<edgetpu::EdgeTpuContext> edgetpu_context =
    edgetpu::EdgeTpuManager::GetSingleton()->OpenDevice();
```
このコンテキストは、以下の`tflite :: Interpreter.SetExternalContext（）`で必要です。

3.`Interpreter`オブジェクトを作成するときに、Edge TPUカスタムopを指定します:

```
std::unique_ptr<tflite::Interpreter> model_interpreter =
    BuildEdgeTpuInterpreter(*model, edgetpu_context.get());

std::unique_ptr BuildEdgeTpuInterpreter(
    const tflite::FlatBufferModel& model,
    edgetpu::EdgeTpuContext* edgetpu_context) {
  tflite::ops::builtin::BuiltinOpResolver resolver;
  resolver.AddCustom(edgetpu::kCustomOp, edgetpu::RegisterCustomOp());
  std::unique_ptr interpreter;
  if (tflite::InterpreterBuilder(model, resolver)(&interpreter) != kTfLiteOk) {
    std::cerr << "Failed to build interpreter." << std::endl;
  }
  // Bind given context with interpreter.
  interpreter->SetExternalContext(kTfLiteEdgeTpuContext, edgetpu_context);
  interpreter->SetNumThreads(1);
  if (interpreter->AllocateTensors() != kTfLiteOk) {
    std::cerr << "Failed to allocate tensors." << std::endl;
  }
  return interpreter;
}
```
4.次に、インタープリター（上記の`model_interpreter`）を使用して、tflite APIを使用して推論を実行します。 主な手順は`tflite :: Interpreter :: Invoke（）`を呼び出すことですが、入力を準備してから出力を解釈する必要もあります。 詳細については、[TensorFlow Liteのドキュメントを参照してください]。(https://www.tensorflow.org/lite/guide/inference)

![unnamed-_3_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/8f0b85b8-837f-5426-fc25-fd19bdaf59bd.jpeg)

> 開発ボードとアクセラレータはどちらもGoogleのEdge TPUチップを搭載しています。これは、汗をかくことなくAIモデルを実行するように設計された、あなたの指の爪ほどの大きさのASICプロセッサです。その間、カメラは開発ボードのためのアドオンとしてあります。https://store.gravitylink.com/global で贩卖を開始できます。
【RDB設計】RailsアプリDB設計における制約について

簡単なブログアプリを作ってるんすが、データベース設計の際に必要になりそうなものがあったので、
手早くまとめます。

意外と検索してもヒットしなかったんだこれが。

<h2>制約とは</h2>
制約とは特定のデータの保存を許さないためのバリデーションです。例えば同じメールアドレスのユーザーを登録できないようにする、名前のデータが空のユーザーを保存できないようにするといったことができるようになります。

RubyOnRailsの場合だと、rails g model [テーブル名(単数形)]をターミナルで打ち込むと、マイグレーションファイルが出来上がります。

このファイルにカラムの指定をした後、rake db:migrateすることでデータベースにカラムが反映されます。

制約はこのカラム一つ一つに対して使います。

<h2>NOT NULL制約</h2>
NOT NULL制約を設定すると、そのカラムの値にはNULL（空の値）を入れることができなくなります。

ブログアプリの場合でしたらユーザー登録が必要になるので、ユーザー登録の際のEmailやパスワード、nameなんかが対象になります。下記のnull: falseが入っている箇所のことです。

マイグレーションファイル

```ruby
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
  end
end
```

<h2>一意性制約</h2>

一意性制約はテーブル内で重複するデータを禁止する制約です。
ユーザー登録をする際に、もう登録したことあるサイトなのに、自分のEメールアドレスを登録しようとしたことってありませんか？すでに使われてるアドレスです、なんて怒られたと思います。

その制約をカラムに対して行うことですね。

ブログアプリの場合はやはりEmailカラムが対象になります。unique :trueが制約している文になります

マイグレーションファイル

```ruby
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name  , null: false
      t.string :email , null: false , unique: true
      t.timestamps null: false
    end
  end
end
```

<h2>外部キー制約</h2>

外部キー制約は、外部キーの対応するレコードが必ず存在しなくてはいけないという制約です。

これはミニアプリの場合、UserテーブルではなくArticle(記事)テーブルになるかと思います。
記事を投稿するのに、投稿したユーザーが不明瞭ではだれが書いたがわかりませんよね？

この制約は、t.referenceを使います。これによりuserではなくuser_idというカラムを作成してくれるため、テーブル間のリレーションを意識しやすくなります。また、後述しますがインデックスを自動で貼ってくれます。

foreign_key: trueというのが制約文に当たります。

マイグレーションファイル

```ruby
class CreateArticles < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      t.string     :text
      t.references :user , foreign_key: true
    end
  end
end
```

<h2>インデックスとは</h2>

インデックスはデータベースの機能の一つで、テーブル内のデータ検索を高速化することができます。インデックスはカラムに対して設定することができ、設定したカラムでの検索が高速になります。

ただし、インデックスには以下の2つのデメリットがあります。

・データを保存・更新する速度が遅くなる
・データベースの容量を使う

ミニアプリであれば、Userテーブルのnameなんかが該当するでしょうか。Articleテーブルのnameも該当しそうですね。投稿者名で検索、記事名で検索みたいな。

ただし記事名にインデックスを貼るのは考えた方がいいかもしれません。データの保存・更新に関してはスピードを要すルものではないかもしれませんが、データベース容量はユーザーが増えてくればサーバーサイドとの相談になりそうですね。

add_index :usersがインデックスを貼り付ける文になります。
補足的にですが、同時に二つのカラムにインデックスを貼る場合も書いています。

```ruby
class CreateUsers < ActiveRecord::Migration
  (省略)
  add_index :users  # インデックスを一つに貼る　
  add_index :users,  [:name, :email] # インデックスを2つにまとめて貼る
  end
end
```

<h2>主キー制約</h2>

主キー制約は、主キーである属性値が必ず存在してかつ重複していないことを保証する制約です。主キーに対してNOT NULL制約と一意性制約を両方設定するのと同義になります。

railsの場合はもともと機能が備わっていて、データベースを見たときに、それぞれのテーブルでIDというカラムがあるかと思います。

それが主キーに当たります。

制約文といいうよりは概念として非常に重要ですので記載しました。

ってまた30分くらいかかっちゃったよおおお。

手早くって言ったのにいいい・・・
【React.createRef】<Form>から受け取った値をオブジェクトに格納する

#はじめに

プログラミング歴2ヶ月の素人が書いています。（間違っていたらご指摘ください）

WesBos.com のオンラインビデオコースでReactを学習しています。
動画は以下から。
https://reactforbeginners.com/

「React.createRef」についての学習メモです。


#そもそもReact.createRefとは

以下がわかりやすい。（英語です）
https://blog.logrocket.com/how-to-use-react-createref-ea014ad09dba/


ざっくり説明すると...
**`ref`属性を要素に付与することで、直接DOMにアクセスすることができる。**

通常DOMに介入するためには、`state`や`props`を通じて行うことが原則であるが、`ref`を使用することでより直接的にDOM情報のやりとりをすることが可能。

ただし、原則を崩してしまうと全体として訳が分からないプログラムになってしまうので、使用は推奨されていないみたいです。


#`<Form>`で受け取った値を`ref`で扱ってみる

```react
const Form = () => {

    return (
        <form onSubmit={createItem}>
            <input name="name"  type="text" />
            <input name="price" type="text" />
            <button type="submit"> + Add! </button>
        </form>
    );
};

```

ここにFormのコンポーネントがあります。

やりたいことは、以下です。

* フォーム内の`input`に入力された値（value）を受け取って使いたい。

要は、

```javascript
document.querySelector(<input>).value
```

をReactでやりたい、ということです。

これを実現するために、`ref`属性を`<input>`に付与します。



```react
const Form = () => {

    const nameRef  = React.createRef(); //refの作成
    const priceRef = React.createRef(); //refの作成

    return (
        <form onSubmit={createItem}>
            <input name="name"  ref={nameRef}  type="text" /> {/*refの付与*/}
            <input name="price" ref={priceRef} type="text" /> {/*refの付与*/}
            <button type="submit"> + Add! </button>
        </form>
    );
};

```

`React.createRef()`で作成した`ref`を`<input>`タグに付与します。

その名のとおり、`ref`は付与された要素への参照になります。
例えば、`<input　name="name"/>`に入力された値に、以下のようにアクセスできるようになります。

```react
nameRef['current'].value
```

参照した`ref`の`['current']`プロパティ内から、必要な要素の情報にアクセスすることができます。



#完成品

`<buttom>`を押すと、`createItem()`が動いて、入力された値を保存します。

```react
const Form = () => {

    const nameRef  = React.createRef(); //refの作成
    const priceRef = React.createRef(); //refの作成

    const createItem = () => {
        const item = {
            name   : nameRef['current'].value,  //オブジェクトに格納
            price  : priceRef['current'].value, //オブジェクトに格納
        };
    };

    return (
        <form onSubmit={createItem}>
            <input name="name"  ref={nameRef}  type="text" /> {/*refの付与*/}
            <input name="price" ref={priceRef} type="text" /> {/*refの付与*/}
            <button type="submit"> + Add! </button>
        </form>
    );
};

```


#まとめ

`ref`属性を要素に付与することで、直接DOMにアクセスできる。
Gitでpullできない場合(error: cannot lock ref ...)

pullできない場合

```shell-session:shell-session
❯ git pull
error: cannot lock ref 'refs/remotes/origin/branch': 'refs/remotes/origin/branch2' exists; cannot create 'refs/remotes/origin/branch'
From github.com:ABC/DEF
 ! [new branch]          branch -> origin/branch  (unable to update local ref)
```

下記で解消

```shell-session:shell-session
❯ git remote prune origin
```