OmniAICreator/Qiita-1.07M huggingface dataset:
Gitのリポジトリ間で同期する

# これは何？
あるGitリポジトリ（Primary）の履歴（コミット、リファレンス等）をそのまま別のリポジトリ（Secondary）を作成し、引き続き同期（シンク）をし続ける方法のメモです。（GitHub的に言うとForkってやつ。）
例えば、BitbucketからGitHubに、逆にGitHubからBitbucketにそのまま内容を手動で移行するときに使えるはず。

# 手順の概要

以下の手順で同期を行う。

1. Primaryからリポジトリの内容をローカルPCにClone (a)
2. SecondaryのURLをremoteとしてCloneしたリポジトリに追加
3. Primaryから履歴等をfetchする
4. Secondaryに対してPushする(b)
5. 随時同期：Primaryから差分をfetchしてきて、SecondaryにPush

<img width="509" alt="Screen Shot 2019-10-02 at 9.42.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61221/6f248d54-2d0e-a5db-0fd7-ec10e7056881.png">

## 1. PrimaryからCloneする (a)
ローカルPCからの操作で一旦ローカルにコピーCloneする。

```shell
$ git clone --mirror https://01_url/prm_repo.git
```

## 2. SecondaryのURLを追加する
remoteのURLを追加して同期する先のリポジトリを指定する。

```shell
$ git remote add --mirror=fetch secondary https://02_repo_url/scd_repo.git
```
## 3. Primaryからfetch
Primaryから履歴等すべてをfetchする。

```shell
$ git fetch origin
```

### 4. Secondaryに対してPush
```shell
$ git push secondary --all
```

### 5. 随時同期する

```shell
$ git fetch origin && git push secondary --all
```

# おわりに
ここでは、PrimaryからSecondaryへ一方通行の同期をメモをしたが、以下のReferenceのURLでは逆方向（Secondaryの更新をPrimaryに同期する）の方法も記載されているので、必要に応じて確認してください。

# Reference

- [How to keep two Git repositories in sync](https://www.opentechguides.com/how-to/article/git/177/git-sync-repos.html)
canvasで描いた絵のURLをDBに保存する

#概要
私は9月ごろから独学でRuby on Railsを始めたのですが、題名の通りcanvasで描いた絵をURLに変換してDBに保存する際に数日詰まったので自分への戒めのために今回の記事を書く運びとなりました。

#詰まったところ
```console
ArgumentError (When assigning attributes, you must pass a hash as an argument.):
```
ハッシュにしてから受け渡してください的なエラーが出る。

##受け渡したデータ
JavaScriptでcanvasのデータをURL化しているため、そのままJavaScriptでPOSTしました。
こんなかんじ

```javascript
//変数imageにはcanvasのURLが入っています
function send_url(image){
                var form = document.createElement('form');
                var request = document.createElement('input');

                form.method = 'POST';
                form.action = 'save';
 
                request.type = 'hidden';
                request.name = 'text';
                request.value = image;
            
                form.appendChild(request);
                document.body.appendChild(form);
            
                form.submit();
}
```
受け取り側はこのようになっています

```ruby
private
    def post_params
          params.require(:text)
    end
end
```
この形式で受け取るとpost_paramsは送信されてきた文字列だけをデータに持ちます。
#修正後
先ほどの関数post_paramsを次のように書き換えました

```ruby
def post_params
      img = params.require(:text)
      hash_url = {"image_url" => img}
      return hash_url
end
```
**力技です。**

#最後に
セキュリティなどの観点で見てこれが大丈夫なやり方なのかはわかりませんが、とりあえずこのハッシュにしたデータを渡すことで無事URLをDBに渡すことができました。
display:none; だと、transitionが効かない時の解決


## 問題

ツールチップを作る際、hover時に
ふわっと表示されるようにしたいが、
今回都合上displayプロパティを使用することになった。

```css
.tooltip {
 display:none;/*いつもはopacity:0;と書いていた*/
 transform: translateY(5px);
 transition: 0.3s;
}
.tooltip:hover {
 display:block;/*いつもはopacity:1;と書いていた*/
 transform: translateY(0px);
}
```

すると、transitionが効かない。


## 解決

```css
@keyframes tooltipShow {
  from {
    opacity: 0;
    transform: translateY(5px);
  }

  to {
    opacity: 1;
    transform: translateY(0px);
  }
}
.tooltip {
  display: none;
}
.tooltip:hover {
  animation: tooltipShow 0.3s linear 0s;
  display: block;
}
```
【Google Apps Script】チェックボックスでスプレッドシートの特定行の表示／非表示を切り替える

# はじめに

スプレッドシートにチェックボックスを配置し、そのアクティブ状態によって指定行を表示／非表示の切り替えをしたいと要望がありました。
GASを使えばいけそうなので、早速試してみたので書いてみます。

# 完成図

![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/31d9954c-e8ca-97f0-ba20-68f9c4851f04.gif)

# 下準備

スプレッドシートを新規作成。
１．　A1〜A3に「A」「B」「C」と入力。
２．　B1〜B3にチェックボックスを配置。チェックボックスは挿入→チェックボックスで配置できます。
3. C1〜C3に、カンマ区切りの適当な数字を入れます。ここに入れた行数が、チェックした場合の表示する行になります。

<img width="459" alt="s1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/ef67ba31-c0dc-664c-962d-818c8190f302.png">


ツール→スクリプトエディタを選択し、以下コードを貼り付けます。

# コード全文

```javascript
var CHECKBOX_COLUMN = 2; // チェックボックスの列
var CHECKBOX_COUNT = 3; // チェックボックスの数
var HIDDEN_FIELD_START = 6; // 何行目から消すのか
var HIDDEN_FIELD_END = 30; // 何行目まで消すのか

// スプレッドシートの値が変更された時に発火
function changeEvent() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var activeCell = sheet.getActiveCell();
  if (activeCell.getColumn() == CHECKBOX_COLUMN){ // チェックボックス列の値が変更された場合
    checkBoxEvent(sheet);
  }
}

// チェックボックスのチェック状態に合わせて表示・非表示を切り替える
function checkBoxEvent(sheet) {
  var rows = sheet.getRange(1, CHECKBOX_COLUMN, CHECKBOX_COUNT, 1).getValues();
  hiddenFields(sheet);
  for (var i = 0; i < rows.length; i++) {
    if (rows[i][0] === true) {
      var showRows = sheet.getRange(i + 1, CHECKBOX_COLUMN + 1).getValue().split(',');
      for (var j = 0; j < showRows.length; j++) {
          sheet.showRows(showRows[j]); // チェックボックスの1個右のセルの値に記載されている行数を表示する
      }
    }
  }
}

// 非表示行エリアを全非表示にする
function hiddenFields(sheet) {
  sheet.hideRows(HIDDEN_FIELD_START, HIDDEN_FIELD_END - HIDDEN_FIELD_START + 1);
}
```

# 動作確認

スプレッドシートのカーソルをB列のどこかに置きます。

```
  if (activeCell.getColumn() == CHECKBOX_COLUMN){ // チェックボックス列の値が変更された場合
```

ソースコードで見るとこの部分、B列の値変更イベントにのみ発火するように設定しているためです。

スクリプトエディタで実行→関数の実行→changeEventを選択。
実行許可のウィンドウが出るので、[過去記事のスクショ](https://qiita.com/rf_p/items/0535ec495df8f9d2b894#1msgbox%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9Fhello-world)を参考にしてください。

スプレッドシートの１０〜３０行目が非表示になり、チェックONになっているセル右隣で指定している行のみ表示されれば成功です。

# トリガーの設定

チェックボックス変更した場合、自動的に行の表示／非表示されるように、スプレッドシートの変更イベントをトリガーとしてchangeEvent関数が自動実行されるよう設定します。

スクリプトエディタ「編集→現在のプロジェクトのトリガー」もしくは時計アイコンからトリガー設定画面に飛びます。
右下の「トリガーを追加」から、下記の通り設定します。

<img width="831" alt="s2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/f9c4e1f8-7cff-437e-ce7a-9cdad49cc8b9.png">

![movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/31d9954c-e8ca-97f0-ba20-68f9c4851f04.gif)

# 追記(2019/10/21)

```javascript
function changeEvent() {
```

を、

```javascript
function onEdit() {
```

にするだけで、トリガーを設定しなくとも勝手に動きます。
ポモドーロ+RPGな個人開発サービス開発を支える技術。を色々改善したい

先日リリースした、『[g4](https://www.g-g-g-g.games)』というポモドーロ+RPGなサービスの開発周りの運用ついて残しておきます。
開発周りは結構発展途上で、整えたい部分がいっぱいあるので、現状の改善点を自分用にメモ。

ちなみに、技術周りについてはこちらに書きました。

[React PWA + Rails GraphQLで作ったポモドーロサービスに使った技術やその選定理由を書いてみた](https://qiita.com/shwld/items/9320cd9bcbb5f9f39580)

# 開発運用周りはこんな感じ
![g4開発.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51402/999f9913-7c44-2952-94e9-28100a24e15b.png)

1. フロントエンドとバックエンドのリポジトリが別れている
2. フロントエンド
    - Github Actionsでテストを回している
    - ②デプロイは手動である
    - Firebase storageのcors設定や、Cloud Run、fly.ioへのデプロイを手動で行っている
    - fly.ioはステージングと本番に加えβ版的にUIを確認するアプリがあり、3つ全部に手動でデプロイしてる
3. バックエンド
    - circleciでテストを回している
    - テストが通れば、GAEにデプロイされる③
    - GAEにはstagingタグとcommitハッシュタグの2バージョンが１度にデプロイされる
    - stagingが問題なければ本番はGAEのコンソールからバージョンを切り替えることで反映する
    - DBのmigrationは自動化しておらず開発端末から手動で実行してる
4. ステージング検証
    - バックエンドの修正は基本的に後方互換性を残して行っている（反映終わったら消すこともある）
    - バックエンドのステージング反映を行い、フロントは古い状態で確認を行う
    - 問題なければフロントもステージングに反映して確認
5. リリース前検証
    - ステージング問題なければバックエンドを本番反映
    - フロントエンドはbetaチャンネルのみ反映
    - betaの状態で1日くらい使ってみて、問題なさそうなら本番に反映する
6. バージョンアップ
    - パッケージのセキュリティアップデートなどは①Dependabotを使って対応しています。アップデートあると勝手にGithubにPR作ってくれてめっちゃ便利なのでおすすめ
7. エラー検知
    - フロントエンドもバックエンドもSENTRYを入れています。何かあれば個人用のSlackに飛んでくる④
8. ④Pivotal Tracker
    - 課題管理的なやつです。
    - こいつは相棒です。
    - 本業でも使ってるんですがとても優秀。優先順位付けの管理しやすいので個人開発にも向いてる
    - 自分はg4に限らず、個人開発でやることをすべてこいつに突っ込むようにしてます。
    - g4以外でも優先度高い対応あればそっちをアサインしたりできてよい
    - あと開発以外の「この記事書く」とかのタスクも全部入れてます

みたいな感じです。

# いいとこ
1. バックエンドの本番反映はDBマイグレーションを除けば自動化できていていい感じです
2. betaチャンネルでUI検証するのいい感じ。割とフロントエンドだけ直すってことも多いので、この運用は良い
3. SENTRYの安心感。こいつ無いと不安すぎますね
4. Pivotal Tracker万歳

# 改善したいとこ
1. フロントエンドのデプロイを自動化したい感
    - [これ](https://github.community/t5/GitHub-Actions/GitHub-Actions-Manual-Trigger-Approvals/td-p/31504) 実装されたらなぁ。masterマージでstagingは自動で反映して問題なかったら、ボタンポチーしてbetaとか本番配信できると嬉しい。ブランチ分けて自動化すればできるけどそうじゃないんだよなぁ。。。
    - いや、masterブランチマージした後戻したいとか、beta確認中に緊急対応とかあるので分けるほうがいいとは思うんですが、まだ1人だしmasterブランチ以外の管理をしたくないんですよね

2. バックエンドのDBマイグレーション
    - GAEでDBマイグレーション走らせた後ってもしかして、アプリの再起動必要系じゃないです? なんかそんな挙動だったんですよね。今怖いから再起動してるけど、再起動結構時間かかるのでどうにかならんものか
    - あとDBマイグレーションの自動化したい
3. バックエンドデプロイ時間かかる
    - GAEデプロイ遅いすね...20分くらいかかってる
    - Dependabotわりとエラーでずにマージできるんだけど反映に時間かかるのでマージ躊躇しがち
3. フロントエンドのDependabot
    - そのままマージできることがほとんどない。なんか改善できるんだろうか

そんな感じで[g4](https://www.g-g-g-g.games)開発してます。
鍵盤機能鍵連続・班別確認試験

Macintosh　の鍵盤(keyboard)で、機能鍵(function key)が連続しているものと、班別に空間があるものとがある。

機能鍵(function key)が連続しているもの Apple Keyboard Model No. A1048
![key2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/b3bd301d-3117-536d-7bd5-234293fa55f0.png)

機能鍵(function key)が班(group)別に空間(space)があるもの Apple Keyboard Model No. M7803
　　　　　　　　　　　　　　　↓　　　　　　　　　　↓　
![key1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/6d11d2a3-c0f7-383c-cf9d-a7b4a33cde84.png)


どちらの方式が、どれくらい操作間違いがあるかもしれないか。
どちらの方式が、どれくらい操作時間がかかるかもしれないか。

試験ソフトウェアを考案中。

パッドのブラウザを想定して、鍵盤機能鍵連続・班別確認ソフトウェア作成予定。

参考になるプログラムを検索中。

よさげなものがありましたら、コメント欄でご紹介くださると幸いです。

#仕様

１０から１６くらいの鍵数。

画面の大きさによっては自動判別して鍵の数を調整できるようにするかどうかは未決定。

空間の大きさは１種類から３種類を想定。

鍵にはF１ーF１６の数を記載するか、機能名を記載するかは、いろいろな種類を設定できるようにする。

鍵の幅は10mm-20mm くらいを想定。
表示の大きさが画面の大きさに依存しない方式とする。
場合によっては、画面の大きさを取得して調整できるとよい。そうでなければ、特定の機器向けに作る。
現在調査中。

利用した機材の情報（ハードウェア、ソフトウェア）を取得できるとよい。
利用年月日時間などを計測する。

表示してから鍵が押されるまでの時間を計測できるとよい。

#参考資料(reference)



機械安全規格を活用して災害防止を進めるためのガイドブック
https://www.mhlw.go.jp/file/06-Seisakujouhou-11200000-Roudoukijunkyoku/kikai_kikaku_2.pdf

電子情報技術産業協会規格 JEITA IT-1004 (旧JEIDA-63-2000)
産業用情報処理・制御機器設置環境基準
Standard of Japan Electronics and Information Technology Industries Association
Standard for Operating Conditions of Industrial Computer・Control System
https://home.jeita.or.jp/is/publica/standard/IT-1004.pdf

5.8.共通 PC・オフィスプリンタ
https://www.ipa.go.jp/files/000025494.pdf

##参考資料(reference) on Qiita

jQueryでスクリーンキーボード
https://qiita.com/yutaro_kamo/items/e5b030b7846aa21f1db3

#文書履歴(document history)
ver. 0.01 20190902
PHPの参照渡しと値渡しの説明

# PHP参照渡しまとめ

## RAMとアドレス
変数はコンピュータの中のメモリRAMに値が保存される。メモリにはアドレスが有ってどのアドレスどんな値が入っているかを管理している。

## 値渡し
メモリーの違うアドレスに値をコピーして保存する方法。元の変数と別のアドレスで管理される。

## 参照渡し
メモリーの同じアドレスを参照する方法。メモリーの同じアドレスを使うので元変数でも渡した後の変数のどちらかでも変更すると同じ値になる。

## PHPでは
関数の引数は値渡しになる。
オブジェクトはインスタンスIDが渡されるため参照渡しの様に振る舞う。ある関数にオブジェクトを渡して、関数内でオブジェクトを更新したら呼び出し元に戻ったときにも関数内で更新された状態が戻ってくる。
引数、変数の先頭に＆を付けると参照渡しになる。


```php5

<?php
//------------------------------------
$name1 = 'Hikakin';
$name2 = &$name1; // ← name2はname1と同じアドレスの変数を参照する
$name3 = $name1; // ← name3はname1と違うアドレスに変数を保存する
$name1 = 'Seikin';  // name1 を Seikinにする
echo $name2."\n"; // Seikin  参照渡しでname1と同じアドレスを参照しているのでSeikinに変わっている
echo $name3."\n"; // Hikakin 値渡しでコピーした値を持っているのでHikakinのまま

//------------------------------------
$val1 = 'abc';
function funcOne($val) // ← 値渡し 別アドレスに値をコピー
{
    $val = 'xyz'; 
}

funcOne($val1);
echo $val1 . "\n"; // abc

//------------------------------------
$val2 = 'abc';
function funcTwo(&$val) // ← 参照渡し caller側と同じアドレスの変数を参照
{
    $val = 'xyz';
}

funcTwo($val2);
echo $val2 . "\n"; // xyz

//------------------------------------
$list1 = ['a','b','c'];
function funcThree($val) { // ←Arrayも値渡し。別アドレスにコピーされている
    $val = ['x','y','z'];
}
funcThree($list1);
var_dump($list1); // 'a','b','c'

//------------------------------------
$list2 = ['a','b','c'];
function funcFour(&$val) {
    $val = ['x','y','z'];
}
funcFour($list2);
var_dump($list2); // 'x','y','z'

//------------------------------------
$obj = new stdClass; // ←オブジェクトID#1が作成される
$obj->name = 'Hikaru';
function funcFive($obj) { // ←オブジェクトはオブジェクトを管理するIDが渡される
    $obj->name = 'Repezen'; // ← オブジェクトID#1 に対して操作するので 参照渡しの様に振る舞う
}
funcFive($obj);
var_dump($obj); // 'Repezen  ←レペゼンが侵食していく
```
WAFの文字列一致条件を設定するCloudFormation

# 概要
WAFの文字列一致条件をCloudFormationで設定する機会があったので
書き方とポイントについてまとめておきます。


CloudFormationにおけるWAFの文字列一致条件については
以下のAWSドキュメントで情報が公開されています。

[文字列一致条件に関するAWSのドキュメント](
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-waf-bytematchset.html)

## 文字列一致条件とは

ウェブリクエストに表示される文字列に基づいて、リクエストを許可または拒否するかどうかを設定するもの。
文字列一致条件が識別するのは、

- 検索する文字列
- AWS WAF で文字列を検査する先のウェブリクエスト部分 (指定されたヘッダーやクエリ文字列など) 

　例： デフォルトは拒否で、URIが/public/で始まるリクエストは許可したい。

## 最終的なCloudFormation
最終的には以下の内容になりました。

＜このテンプレートで作成できるAWSリソース＞

- WAF
- WAFRule
- WAFByteMatchSet(文字列一致条件)

```
AWSTemplateFormatVersion: 2010-09-09
Description: template for waf checking String and regex matching
Parameters: 
  Prefix:
    Type: 'String'
    Default: 'test'
Resources:
  WAFWebACLTEST:
    Type: 'AWS::WAF::WebACL'
    Properties:
      DefaultAction:
        Type: BLOCK　←WAFのデフォルトアクションを拒否
      MetricName: !Sub {Prefix}waf
      Name: !Sub ${Prefix}-waf
      Rules:
          - Action:
              Type: ALLOW　←WAFRuleStringMatchに当てはまるときは許可
            Priority: 0
            RuleId: !Ref WAFRuleStringMatch

  WAFRuleStringMatch:
    Type: 'AWS::WAF::Rule'
    Properties:
      MetricName: !Sub ${Prefix}stringmatch
      Name: !Sub ${Prefix}-stringmatch
      Predicates:
        - DataId: !Ref WAFByteMatchSetString
          Negated: false
          Type: ByteMatch

  WAFByteMatchSetString:
    Type: 'AWS::WAF::ByteMatchSet'
    Properties:
      ByteMatchTuples:
      # URIが/4/で始まるリクエスト
        - FieldToMatch:
            Type: URI
          PositionalConstraint: STARTS_WITH
          TargetString: /4/
          TextTransformation: LOWERCASE
      # URIが/public/で始まるリクエスト
        - FieldToMatch:
            Type: URI
          PositionalConstraint: STARTS_WITH
          TargetString: /public/
          TextTransformation: NONE
      Name: !Sub ${Prefix}-string

```

## ポイント
- （文字列一致条件に関するものではないですが）WAFのメトリック名に「-（ハイフン）」は使えない。
- TextTransformationは攻撃者がWAFをバイパスするためにウェブリクエストで使用する異常なフォーマットの一部を削除する変換方法を指定するもの。必ずなんらかの変換方法を指定する必要があるので、変換しない場合はNONEと指定する。

## 参考
- [AWS公式 CloudFormationのドキュメント](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-waf-bytematchset.html)
dockerのコンテナの中に入る

#【値の確認方法】
##1.コンテナに入る
■動いているコンテナに入る

```
$ docker-compose exec container_name bash
```

```
$ docker exec -it container_name /bin/bash
```

■止まっているコンテナに入る

```
$ docker-compose run container_name bash
```
ONNXで split 最適化

ONNXがサポートしている最適化 split について調べました。

最適化をしている場所はここ。
https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/split.h

コメントを読んでいくと、推論時にグラフの中で定数ととして扱えるものを別のsubgraphに分離する最適化のようです。面白そう。

早速試してみました。add0の入力が定数になるようなグラフを作成します。

![split.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/c340a3b8-e893-ad89-77f2-226b05a5f415.png)

左上のAddが定数のみの足し算です。グラフの計算を実行する時に毎回計算する必要が無い部分です。真ん中のAddは、入力Xによって結果が変わるので毎回計算必要です。

最適化は、定数として扱える部分を抜き出すのにsplit_init、推論時に計算が必要な部分を抜き出すのにsplit_predictを指定して、2回呼び出しました。使い方は合ってるはす・・・。

```python
# 最適化パスを指定
passes = ['split_init', ]

optimized_model_init = optimizer.optimize(model_def, passes)
onnx.save(optimized_model_init, 'onnx/split_init.onnx')

passes = ['split_predict', ]

optimized_model_pred = optimizer.optimize(model_def, passes)
onnx.save(optimized_model_pred, 'onnx/split_pred.onnx')
```

最適化後の初期化部分がこっち。定数同士の加算部分だけを別グラフにし、add0_outという名前で出力しています。初期値扱いで、一度計算すれば再計算は不要です。

![split_init.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/033b0b01-755a-597b-241b-1411b98eba39.png)


推論の計算部分がこっち。上のグラフで計算したadd0_outの結果を使って、全体の計算を行っています。再計算が不要な部分は、別グラフに分離してあるので、定数などは気にせず全部の計算を行えばOKです。

![split_pred.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/2b2b599e-40bb-fe8c-67a3-8a3946165176.png)


上手く分離されてますね。面白い。

全ソースです。

```python
import numpy as np
import onnx
from onnx import helper, numpy_helper
from onnx import TensorProto
from onnx import optimizer

X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1])

A = np.ones((1,), dtype=np.float32)
B = np.ones((1,), dtype=np.float32)

const0 = onnx.helper.make_node(
    'Constant',
    inputs=[],
    outputs=['const_0'],
    value=onnx.helper.make_tensor(
        name='const_tensor',
        data_type=onnx.TensorProto.FLOAT,
        dims=A.shape,
        vals=A.flatten().astype(float),
    ),
)

const1 = onnx.helper.make_node(
    'Constant',
    inputs=[],
    outputs=['const_1'],
    value=onnx.helper.make_tensor(
        name='const_tensor',
        data_type=onnx.TensorProto.FLOAT,
        dims=B.shape,
        vals=B.flatten().astype(float),
    ),
)


add0 = helper.make_node(
    'Add',
    inputs = ['const_0', "const_1"],
    outputs = ['add0_out'],
)

add1 = helper.make_node(
    'Add',
    inputs=['X', 'add0_out'],
    outputs=['Y']
)

gemm = helper.make_node(
    'Gemm',
    ['X'],
    ['Y'],
    transA=1
)

graph_def = helper.make_graph(
    [const0, const1, add0, add1],
    'test-model',
    [X],
    [Y],
    initializer=[]

)

model_def = helper.make_model(
    graph_def,
    producer_name='onnx_example'
)

onnx.save(model_def, 'onnx/split.onnx')

onnx.checker.check_model(model_def)

# 最適化パスを指定
passes = ['split_init', ]

optimized_model_init = optimizer.optimize(model_def, passes)
onnx.save(optimized_model_init, 'onnx/split_init.onnx')

passes = ['split_predict', ]

optimized_model_pred = optimizer.optimize(model_def, passes)
onnx.save(optimized_model_pred, 'onnx/split_pred.onnx')
```
PlayFramework の Form で Custom Mapping を作る2つのパターン

久しぶりに PlayFramework の Controller を実装するなどしてリクエストボディを [Form](https://www.playframework.com/documentation/2.7.x/ScalaForms) を使ってパースするなどした。CustomMapping を作るパターンを2つ紹介する。

# その1. Formatter を実装する

ブログでよく見かけるやつ。
リクエストボディが下記のようになっていたとする。

```json
{ "name": "something string" }
```

これを下記にマッピングしたい。

```scala
case class Whoami(name: Name)
case class Name(value: String)
```

`play.api.data.format.Formatter` の型パラメータに
対象の `ValueObject` の型を指定し `bind` と `unbind` を実装して、
暗黙の関数として定義する。

```scala
trait CustomFormatter {

  implicit def userFormat: Formatter[Name] = new Formatter[Name] {

    override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], Name] = {
      Formats.stringFormat.bind(key, data).right.map(Name)
    }

    override def unbind(key: String, value: Name): Map[String, String] =
      Map(key -> value.value)
  }
}
```

使うときは `Forms.of` に型パラメータを与えることでよしなにやってくれる。
今回は↑で作った `trait` を継承して使う。

```scala
object SampleMapper extends CustomFormatter {

  val sampleForm = Form(
    mapping(
      "name" -> Forms.of[Name]
    )(Whoami.apply)(Whoami.unapply))
}
```

作成した `Form` を `Controller` で使う。
`SampleMapper` を `import` して `bindFromRequest()` を呼び出す。

```scala
import com.google.inject.Inject
import javax.inject.Singleton
import play.api.data.Forms.mapping
import play.api.data.format.{Formats, Formatter}
import play.api.data.{Form, FormError, Forms}
import play.api.mvc.{AbstractController, ControllerComponents}

@Singleton
class FormSample @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

  import SampleMapper._

  def post() = Action { implicit request =>
    sampleForm.bindFromRequest().fold(
      e => BadRequest(e.errors.toString), whoami => Ok(whoami.toString))
  }
}
```

基本的な使い方はこんな感じ。

# その２. Form#transform を使う

Formatter の実装と同様に `ValueObject` をマッピングするだけならこっちのが楽ちん。先程の Form の定義を下記のようにするだけ。

型の指定は必須。

```scala
Form(
  mapping(
    "name" -> text.transform[Name](Name, _.value)
  )(Whoami.apply)(Whoami.unapply)
)
```

### 配列を受け取る場合

例えば下記のように、メールアドレスの配列を受け取ったとする。

```json
{
  "name": "something string",
  "emails": [
    "a@qiita.com",
    "b@qiita.com",
    "c@qiita.com"
  ]
}
```

この場合は組み込みのコレクションマッパーのコンストラクタに指定。

```scala
val sampleForm = Form(
  mapping(
    "name" -> text.transform[Name](Name, _.value),
    "emails" -> seq(text.transform[Email](Email, _.value))
  )(Whoami.apply)(Whoami.unapply))

case class Whoami(name: Name, emails: Seq[Email])
case class Name(value: String)
case class Email(value: String)
```

更に `emails` を ファーストクラスコレクションとする場合は下記のようになる。

```scala
val sampleForm = Form(
  mapping(
    "name" -> text.transform[Name](Name, _.value),
    "emails" -> seq(text.transform[Email](Email, _.value))
      .transform[Emails](Emails, _.values)
  )(Whoami.apply)(Whoami.unapply))

case class Whoami(name: Name, emails: Emails)
case class Name(value: String)
case class Email(value: String)
case class Emails(values: Seq[Email])
```

# 所感

CustomMapping は `transform` の利用でほぼこと足りた。
`Formatter` を実装するほうが嬉しいときってどんなときだろ？
tidyrのpivot_longerでできることをpivot_longerを使わないでやってみる

# gather → pivot_longerの追加

神、ハドリーが作りし`tidyr`パッケージに`gather`と`spread`に代わり、`pivot_longer`と`pivot_wider`関数が最近追加されました。

ばりばりの`gather`と`spread`ユーザーなので、その必要性がいまいち理解できていないので、とりあえず`vignette("pivot")`にあるユーズケースを`pivot_*`を使わないで再現してみて、どのように動くのかを実感してみたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143095/42776c5b-c46c-486e-2eb2-6108561751a1.png)

## WHOデータの概略

Vignettの一番最初にある例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143095/47cf116c-d716-ac02-edf0-732ac4c40bfe.png)

列名がまったくtidyでないデータです。

`new_sp_m1524`

のように、国別の結核の発症を、

>(rel = relapse, sn = negative pulmonary smear, sp = positive pulmonary smear, ep = extrapulmonary) to a code for gender (f = female, m = male) to a code for age group (014 = 0-14 yrs of age, 1524 = 15-24 years of age, 2534 = 25 to 34 years of age, 3544 = 35 to 44 years of age, 4554 = 45 to 54 years of age, 5564 = 55 to 64 years of age, 65 = 65 years of age or older).

というコードで表しているとのことでした。

## pivot_longer

まずは、vignetteの結果をみてみると、

```r
pivotwho <- who %>% pivot_longer(
  cols = new_sp_m014:newrel_f65,
  names_to = c("diagnosis", "gender", "age"), 
  names_pattern = "new_?(.*)_(.)(.*)",
  names_ptypes = list(
    gender = factor(levels = c("f","m")),
    age = factor(
      levels = c("014", "1524", "2534", "3544", "4554", "5564", "65"), 
      ordered = TRUE
    )
  ),
  values_to = "count",
  values_drop_na = TRUE
)
```
で、処理結果が、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143095/9f2910d1-df90-ff13-948d-46a776a2e669.png)

みごとに、`new_sp_m1524`等の変数名が分けられており、ひとつの関数を通っただけでtidyな形になっています。
（`pivot_*`系の関数そんなにいらないんじゃないかと思っていてごめんなさい）

## gather等を駆使してみる

では、次に、`pivot_longer`を使わずに同じ処理をやってみます。
pivot_longerに対応するargumentをコメントで入れてみました。
 
```r
oldwho <- who %>% 
    gather(-country, -iso2, -iso3, -year, 
           key = key, value = count) %>%  # values_to = "count",
  　extract(key, 
            c("diagnosis","gender","age"), # names_to = c("diagnosis", "gender", "age"), 
            "new_?(.*)_(.)(.*)") %>%  # names_pattern = "new_?(.*)_(.)(.*)",
  　mutate( # names_ptypes = ...
    　gender = factor(gender, levels = c("f","m")),
    　age = factor(age, levels = c("014", "1524", "2534", "3544", "4554", "5564", "65"), 
                 ordered = TRUE)
  ) %>% 
  filter(!is.na(count)) # values_drop_na = TRUE

```

## 確認

```r
> identical(summary(oldwho), 
+           summary(pivotwho))
[1] TRUE
```

## 感想

というわけで、`pivot_longer`でした。感覚的には、tidyrの各種関数を良い感じでwrapしてくれているものという印象です？まだ、argumentの指定方法には慣れていないのですが、使いこなせると、よくある横に長いnon-tidyなデータを効率的に可読性が高い状態で処理できそうです。

（スクリプトについて、何かご指摘いただける点等ありましたらご指摘いただけると幸いです。）
Raspbian Buster 2019-09-26 Release-note 翻訳

(追記: 2020/2/8にRaspbian Buster 2020-02-25がリリースされています)
https://qiita.com/utaani/items/02f8ab119fedef3469e5

http://downloads.raspberrypi.org/raspbian/release_notes.txt

2019-09-26：

- rpi-eeprom が含まれています
 - これにより、Raspberry Pi 4のSPI EEPROMが最新の安定バージョンに自動的に更新されます。<br>
       詳細については、https://rpf.io/eeprom を参照してください。
- ファイルマネージャーアイコンの新しいアイコンテーマ
- 外観設定-両方のモニターで同一のデスクトップのオプション
- 外観設定-両方のモニターに異なるデスクトップアイコンを表示するオプション
- 起動時にモニター1が見つからない場合に、タスクバーがモニター0に自動的に移動
- ボリュームプラグインに追加された2つのHDMIデバイス間のオーディオ出力の切り替え
- ボリュームプラグインに追加されたオーディオ入力デバイスの切り替え
-  .asoundrc（ALSA設定ファイル）は、より多くのデバイスをサポートするために「plug」値を使用するようになりました
- 重複したコードを減らしボリュームプラグインとより密接に統合するようにオーディオ設定ツールが変更されました
- 画面構成ツールに、解像度とリフレッシュレートの個別のメニューが表示されるようになりました
- プライマリおよびアクティブモニター設定が画面構成ツールから削除されました
- FKMSドライバーのオーバースキャンサポートが追加されました
- 新しいキーボードショートカットが追加
 - Ctrl-Alt-End でシャットダウンメニューが表示
 - Ctrl-Alt-M はタスクバーをモニター間で移動します
- Bluez ALSAインターフェイスの最新の変更が統合され、Bluetoothオーディオデバイスへの接続が改善されました
- leafpad に代わって Mousepadがシンプルなテキストエディタとして使用
- Thonnyのバージョン3.2が追加されました
- Chromiumのバージョン74が追加されました
- VLCバージョン3.0.8が追加されました
- Flash Playerのバージョン32.0.0.255が追加されました
- RealVNC Serverのバージョン6.5.0が追加されました
- RealVNC Viewerのバージョン6.19.715が追加されました（フルイメージのみ）
- Mathematicaのバージョン12.0.1が追加されました（フルイメージのみ）
- Node-REDのバージョン0.20.8が追加されました（フルイメージのみ）
- Sonic Piバージョン3.1.0が追加されました（フルイメージのみ）
- Scratch3追加（フルイメージのみ）
- バグ修正 -ターミナルでのURL処理
- バグ修正 -ネットワークプラグインのSSIDの8進数値
- バグ修正 -ファイル転送時の進行状況バーの残りの値
- バグ修正 -xarchiverツールとファイルマネージャーの統合
- バグ修正 -間違ったモニターでメニューを開いてしまう
- バグ修正 -最小化されたアプリケーションが2番目のモニターのタスクバーに誤って表示される
- バグ修正 -x86プラットフォームでBluetoothをオフにするとBluetoothアイコンが消える
- バグ修正 -x86プラットフォームで画面構成ツールが表示されず、設定が保存されない
- さまざまな翻訳の更新
- さまざまなマイナーなバグ修正
- Epiphany/Webは削除されました
- ntfs-3gが含まれています
- pciutilsが追加されました
- Linuxカーネル4.19.75
- Raspberry Piファームウェア01508e81ec1e918448227ca864616d56c430b46d
Homebrew で Error: Cask XXXXXX exists in multiple taps と言われたら

## 現象

AdoptOpenJDK をインストールしようとした時のこと。

「Error: Cask adoptopenjdk8 exists in multiple taps」というエラーが表示された。

```
$ brew cask install adoptopenjdk8
Error: Cask adoptopenjdk8 exists in multiple taps:
  homebrew/cask-versions/adoptopenjdk8
  adoptopenjdk/openjdk/adoptopenjdk8
```

これは homebrew/cask-versions と adoptopenjdk/openjdk の両方の tap に adoptopenjdk8 が存在するということを示している。

調べてみると、確かに以下の2箇所に adoptopenjdk8 が定義されている。

- https://github.com/Homebrew/homebrew-cask-versions/blob/master/Casks/adoptopenjdk8.rb
- https://github.com/AdoptOpenJDK/homebrew-openjdk/blob/master/Casks/adoptopenjdk8.rb

## 対応方法

不要な tap を削除するか、または tap を指定してインストールする。

### brew untap で不要な tap を削除してからインストールする例

```
$ brew untap adoptopenjdk/openjdk

$ brew cask install adoptopenjdk8
```

### brew cask install で tap を指定してインストールする例

```
$ brew cask install homebrew/cask-versions/adoptopenjdk8
```

## そもそも tap とは何なのか

tap はサードパーティのリポジトリ。

[brew tapとは \- Qiita](https://qiita.com/saa/items/85ed5e914d424fbf9fd6)

> brew tapとは公式以外のリポジトリをフォーミュラとしてHomebrewに追加するもので、brewのもとでinstall,uninstall,updateなどが行えます。もちろん自分が公開しているものも簡単に追加できます。

[brew/Taps\.md at master · Homebrew/brew](https://github.com/Homebrew/brew/blob/master/docs/Taps.md)

> Taps (third-party repositories)

brew tap コマンドでは追加したい GitHub リポジトリのパスを指定する。例えば https://github.com/foo-user/bar-repository の場合は以下のように指定する。

```
$ brew tap foo-user/bar-repository
```

追加済みの tap は brew tap コマンドで確認することができる。

```
$ brew tap
adoptopenjdk/openjdk
heroku/brew
homebrew/cask
homebrew/cask-versions
homebrew/core
homebrew/services
```
parcel+riot.js v4でstyleタグの挿入が上手くいかなかったときの対処法

### 環境
parcel: v1.12.3
riot: v4.6.2
riotjs/compiler: v4.4.3
riotjs/parcel-plugin-riot: v4.0.1
Windows 10 64bit 1903

## 問題
parcelバンドラーを使ってriot.js v4製アプリを試作中していたときのこと。
以下のようにriotタグファイルにstyleタグを含めるとcssが適用されるはずだが、コンパイルしても空っぽのスタイルタグが挿入されるだけで期待するような動作にならない…

```html:app.riot
<app>
  <style scoped>
     p {
       color: red;
     }
  </style>
  
  <!-- 文字が赤くなるはずだが･･･ -->
  <p>hello world!</p>
</app>
```
（めっちゃ簡略しています）

### 原因
調べてもよく分からず、しょうがないのでriot.jsのソースを見ることに。
cssManagerというシングルトン？がaddメソッドによってスタイル挿入を行っているらしい。
以下該当箇所を抜粋。

```js

  /**
   * Save a tag style to be later injected into DOM
   * @param { string } name - if it's passed we will map the css to a tagname
   * @param { string } css - css string
   * @returns {Object} self
   */
  add(name, css) {
    if (!CSS_BY_NAME.has(name)) {
      CSS_BY_NAME.set(name, css);
      this.inject();
    }

    return this;
  },

  /**
   * Inject all previously saved tag styles into DOM
   * innerHTML seems slow: http://jsperf.com/riot-insert-style
   * @returns {Object} self
   */
  inject() {
    getStyleNode().innerHTML = [...CSS_BY_NAME.values()].join('\n');
    return this;
  },
```

```CSS_BY_NAME``` は[Mapオブジェクト](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map)である。valuesメソッドで得られたiteratorをスプレッド構文でパースというシャレオツなことをしている。
このMapが問題だった。

parcelはバンドルの際、~~勝手に~~自動的にbabel-preset-envでjsトランスパイルを行う。
しかしMapのiteratorあたりの変換が上手く行ってなかったようなのか、```...CSS_BY_NAME.values()```の部分が空の文字列になってしまっていた。

用途的にはバベる必要が無かったのでトランスパイルを切りたかったけど、どうもそういうオプションは無いっぽいようなので、package.jsonに以下のオプションを追加して実質的にトランスパイルを無効化することに。

```package.json
"browserslist": ["last 1 Chrome version"]
```

あるいは.babelrcを用意して、以下の内容を追記する。

```js:.babelrc
{
  "presets": [
    ["env", {
      "targets": {
        "browsers": [
          "last 1 Chrome version",
        ]
      }
    }]
  ]
}
```

ただこれも不要なbabel-coreとかいろんなパッケージをインストールしてくるので何か気持ちが悪い。他に適切な方法があれば教えてほしい…

ちなみにasync/awaitを使った際にも似たような問題が起こる。
[ParcelのBabelでAsync関数を変換せずに使う設定](https://takamints.hatenablog.jp/entry/not-to-convert-async-function-with-parcel)

parcelは便利だけど、たまにzero-configなのが仇になることがあって難しい。
AndroidスマホでFORTRAN IV

# 概要
AndroidスマートフォンにLinux環境を構築し、FORTRANプログラムを走らせるためのセットアップについて説明します。

Android OSのバージョンは9ですが、たぶんtermuxが動作してその上でCコンパイラが動けばほかのバージョンでもOKのはずです。

# はじめに
長年のガラケーユーザだった私のところにもスマホがやってきました。

さあ何しよう....

そうだ、プログラム書こう!!

今時の人だったらPythonとかそうしたものをやると思いますが、CとBASICとFORTRANとアセンブラしか知らないのでどうしたものか....

そうだ、FORTRANで書こう!!

FortranじゃなくてFORTRAN。古のあのFORTRAN IVのプログラムを最新Androidスマホでやろう....

かくして悪戦苦闘の結果何とかFORTRAN IVのプログラムを動かすことに成功したので次の通り報告します。

FORTRAN 貴方のお家は何処?
私のお家はFACOMなのよ やさしいコンパイラのひとつなのよ
(FACOM FORTRANのマニュアルより)

# 手順

## termuxのインストール

まずはAndroidスマホ上にLinux環境を構築します。最初はCCToolsにしようと思っていたのですが、いつの間にかGoogle Playストアから消えてなくなっていたので、課金なしで使えるtermuxをインストールしました。

Google Playストアで探すとすぐ見つかり、ワンタッチでインストールできます。

すまほ、べんり!! (ガラケーユーザなのでとても感動する)

## Cコンパイラなどのインストール

インストールしたtermux上でCコンパイラをインストールします。

Linux上のCコンパイラといえばgcc、FORTRANコンパイラといえばgfortranなのですが、NDKが最近全面的にclangベースに切り替わってしまったらしくgcc系が動かないみたいなので、clangをインストールします。

```
termux $ pkg install clang
termux $ pkg install make
```

必要かどうかわかりませんがits-pointlessもインストールしてみました。

```
termux $ wget https://its-pointless.github.io/setup-pointless-repo.sh
termux $ bash ./setup-pointless-repo.sh
```

## f2cのソースをダウンロード

gfortranがtermux上でインストールできないみたいなので、昔懐かしのf2cをインストールすることにします。

FORTRAN(77まで)のソースをCコンパイラが食べられるソースに変換するプログラムです。ソースおよびマニュアル類は

http://netlib.org/f2c

以下にあります。

必要なのはf2cのソース(tgz)とlibf2cのソース(zip)です。下記のとおりダウンロードして展開します。

```
termux $ wget http://netlib.org/f2c/src.tgz
termux $ wget http://netlib.org/f2c/libf2c.zip
termux $ tar zxvf src.tgz
termux $ unzip libf2c.zip
```

## f2cのソースをコンパイル

展開したらmakefile.uファイルをMakefileにコピーします。あとはmake一発でコンパイルできます。

コンパイルできたらtermuxのusr以下にファイルをコピーします。

f2c -> usr/bin
xsum -> usr/bin
f2c.h -> usr/include

## libf2cのソースをコンパイル

こちらも展開したらmakefile.uファイルをMakefileにコピーします。

コピーしたらMakefileのCFLAGSのところに次の定義を追加します。

-DNON_UNIX_STDIO

次に、uninit.cファイルの中から"\_\_linux\_\_"を探して、次のinclude文をコメントアウトします。

```
// #include "fpu_control.h"
```

この1文をコメントアウトしておかないとコンパイル時にエラーになります。

準備ができたらmakeでコンパイルし、出来上がったlibf2c.aをtermuxの usr/lib 以下にコピーしておきます。

# いざコンパイル

次のプログラムを書きました。なお、昔ながらのFORTRANですので固定書式じゃないとf2cから構文エラーで怒られます。

```test.f
      WRITE(6,100)
  100 FORMAT(12H HELLO,WORLD)
      END
```

コンパイル実行は次のとおり行います。

```
termux $ f2c -T. test.f
termux $ cc test.c -lf2c -lm
termux $ ./a.out
 HELLO WORLD
```

# まとめ

Androidスマホ上でFORTRAN IVプログラムを動かす方法について報告しました。

これでいつでもどこでもFORTRANプログラミングが楽しめます。最新スマホで大昔のFORTRAN IVプログラミングをやるのもなかなか楽しいものです。
【備忘録】AppProxyで別サーバーのコンテンツを表示できないケースとその対応

社外から社内のWebアプリ使うのに、VPN を毎回引くのは面倒。AzureAD AppProxy を使えば、VPNを引かなくても社内Webアプリを使えてしまう。便利。

前回は[iOSから安全に社内リソースにアクセスする](https://qiita.com/hisssa0102/items/85b9583e15b1db2931e7)ってことでiOSからのアクセスについて書いた。別にiOSでなくてもWindowsでもMacでも使える。割当さえすればアプリランチャーに表示されるので、2クリックぐらいでアクセスできるようになる。


さて、そんなAppProxyで、あるシステム内に埋め込んだ動画が再生できない、というトラブルに当たってしまった。その原因と解決した方法をまとめてみた。

#問題
あるアプリ（xxx.hoge.com）内に動画（ただしyyy.hoge.com)に埋め込んだ動画が、素のURLであれば再生できるんだけど、AppProxy経由だと再生できない。

・yyy.hoge.comもxxx.hoge.comも単体だとAppProxyで正常に動作する。
・xxx.hoge.comに埋め込んでいるyyy.hoge.comの動画が再生できない
・でも、動画のサムネイルは表示される
・もちろん、AppProxyを通さない場合は何の問題もない。

URLリダイレクトの処理で何か問題が起きてる。設定がたりないのかと思っていましたが、1か所設定変更すれば解決できました。

#解決方法

今回はここを設定変更すれば解決しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237698/acc2e498-75c9-fadb-482a-97396109a337.png)

登録済みのアプリの場合は、AzureAD → エンタープライズアプリケーションから、アプリを選ぶ→ アプリケーションプロキシを開く。
で、[変換するURLの場所]でアプリケーション本文を [はい] にして保存。

#参考記事

この記事を参考にして解決しました。本当は別件調べてたのですがその中で試してみたら解消できました。

[Azure AD アプリケーション プロキシで公開されているアプリのハードコードされたリンクをリダイレクトする](https://docs.microsoft.com/ja-jp/azure/active-directory/manage-apps/application-proxy-configure-hard-coded-link-translation)

デフォルトでは [いいえ] になっているので、うまくいかないケースではこれで解決するかも。
kubernetes クラスターが role-based access control（RBAC）で動作していることを確認する方法

### 前置き

例えばEKSでContainer Insightsを使用したい場合、 RBACが有効になっていなければならないらしいです。

> 前提条件の確認
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Container-Insights-prerequisites.html

ところがそこからリンクされている確認方法を見てもなにがなにやらさっぱりわかりません。
ていうか、これはRBAC認証の説明であって、確認方法じゃないよ...。

> Using RBAC Authorization
https://kubernetes.io/docs/reference/access-authn-authz/rbac/


なんやかんやでggった結果、解法を発見。もちStackoverflow。


### 方法

> how to check whether RBAC is enabled, using kubectl
https://stackoverflow.com/questions/51238988/how-to-check-whether-rbac-is-enabled-using-kubectl


```sh
kubectl api-versions
```

結果に以下が含まれて入れば、有効になっているとのこと。

```sh
.rbac.authorization.k8s.io/v1
```


-------------------

ネットを回遊しているとkubernetesまっさかりという感じですが、この程度の情報も日本語で見つからないとなると、現実はこれから...なんでしょうか。
LTE→5Gは直ちにはブレークスルーにならないけれど　その２

[[LTE→5Gは直ちにはブレークスルーにならないけれど]](https://qiita.com/azumabashi/items/7ddfaba6de1c8d9d2efe) の続きです。

8月30日付けで発表された東京都の[[TOKYO Data Highway 基本戦略]](http://www.metro.tokyo.jp/tosei/hodohappyo/press/2019/08/30/documents/16a.pdf) ではさらに踏み込んで、アンテナ基地局設置への都の保有するアセットの開放が示されていて興味深いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/0654557f-dbbc-429a-af24-32c9b93e2b1c.png)

9月20日付けで東京都副知事になられた宮坂学さん（前ヤフー会長）の動きにも注目しておきたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/94564154-7d76-40b2-9a69-d6412c909d57.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/1a5edca8-a816-9f0a-ca50-46708738f5e4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/16dc4766-c41b-c990-3f6a-29bb81d39c2f.png)
【Swift】 ボタン押下時に画面にViewを追加する

####はじめに
会社で提供してるWebサービス専用のタブブラウザを作れないか、というコトで、実現性評価を何段階かに分けてやってるうちの１つ。
ボタン押下時にUIViewを画面に追加する。

####開発環境
端末:MacBook Pro/MacOS 10.14.5(Mojave)
Xcode:10.2.1
Swift:5

####やったこと
ボタン押下時に、画面のランダムな場所に10px*10pxのUIViewを表示。
　→ボタンを押下するたびにどんどんUIViewを追加していく。

####実装
#####画面イメージ
|起動時|
|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/ee289962-0ffd-12fe-c39b-f000081521c9.png" width="300">|

|ボタン連打|
|:-:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/5dc4bd69-4d93-e319-bd57-48dd30808404.png" width="300">|
※色と場所がランダムに設定されたUIViewがボタンを押すたびに画面に配置されていく。

#####ソースサンプル

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var btnCreateView: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        btnCreateView.center = view.center
    }

    @IBAction func createView(_ sender: Any) {
        let testView: UIView = UIView()
        
        let viewWidth = UIScreen.main.bounds.width
        let viewHeight = UIScreen.main.bounds.height
        
        let randX = CGFloat(Int.random(in: 0 ... Int(viewWidth)))
        let randY = CGFloat(Int.random(in: 0 ... Int(viewHeight)))
        
        let randRed = CGFloat(Int.random(in: 0 ... 255))
        let randGreen = CGFloat(Int.random(in: 0 ... 255))
        let randBlue = CGFloat(Int.random(in: 0 ... 255))
        
        testView.backgroundColor = .init(red: randRed/255,
                                         green: randGreen/255,
                                         blue: randBlue/255,
                                         alpha: 1)
        
        testView.frame = CGRect.init(x: randX, y: randY, width: 10, height: 10)
        
        view.addSubview(testView)
    }
}
```

####感想等
実現性評価というか、まぁこうなるだろうな〜ってイメージを順当に形にした感じです。
【Blob・File・Base64・データURL・FileReader】 それぞれの特徴とブラウザへの表示について

# はじめに
この記事では、ファイルを受け取ってからブラウザ上に表示するまでに登場する、インターフェースやオブジェクトの特徴を調べ、みなさんが要件に適したファイル操作を選択できるよう祈りながら書きました。


# それぞれの特徴
### Blob
- HTML5のFile APIで定義されたインターフェースである
- バイナリ・ラージ・オブジェクトの略である
- Blobオブジェクトには、**生のバイナリデータが格納されている**
- プロパティはsizeとtypeのみで、**中のデータに直接アクセスすることはできない**
- Blobオブジェクトはimmutable(不変)であり、を直接編集することはできない
- が、sliceメソッドによる分割や、コンストラクタによる結合を行うことができる


>https://developer.mozilla.org/ja/docs/Web/API/Blob
https://ja.javascript.info/blob

### File
- HTML5のFile APIで定義されたインターフェースである
- Blobインターフェースを継承しているため、**Blobを引数に取るメソッドに渡すことができる**
- 異なるのは、よりファイルを扱いやすくするために、**name,lastModifiedプロパティが追加されている**点
- `<input type="file">`にローカルファイルを与えると、files属性か、onchangeイベント経由で、 FileListオブジェクトが得られる。FileListオブジェクトに対してインデックスを渡すことでFileオブジェクトを取得することができる

>https://developer.mozilla.org/ja/docs/Web/API/File
https://ja.javascript.info/file

### FileReader
- FileReaderは、**Blob（File）オブジェクト内のバイナリデータを読み込むためのオブジェクト**
- FileReaderオブジェクトには、下記のようなメソッドがあり（非推奨のものは除く）、Blobオブジェクトを様々な形式で読み取ることができる
    - `readAsArrayBuffer()` →ArrayBuffer
    - `readAsDataURL()` →DataURL
    - `readAsText()` →文字列
    - `abort()` →読み取り中断

>https://developer.mozilla.org/ja/docs/Web/API/FileReader
https://ja.javascript.info/file

### Base64
- Base64というクラスやインターフェースは存在せず、バイナリデータをStringに変換するための**エンコード方式である**
- エンコード前のバイナリデータと比べて**約33~37%データサイズが増加する**

### データURL
- `data:[<mediatype>][;base64],<data>`という形式で記述されたURLである
- 例えばテキストデータでは、`data:text/plain;base64,dGVzdA==`のような感じのURLで、これをアドレスバーに入力するとtestと表示される
- jpeg画像ファイルを示すデータURLは`data:image/jpeg;base64,`という文言から始まる
- URL内にテキストや画像データが埋め込まれているため、**URL自体が比較的大きいサイズになる**


# BlobやFileに格納されているファイルをブラウザ上に表示する方法
以下、画像ファイルの表示を例にして説明する。
画像ファイルをブラウザ上に表示するためには、imgタグのsrc属性にURL（データURLを含む）を与える必要がある。

URLを取得するには２つの方法がある

- Blob(File)をデータURLとして読み取る
- Blobを参照するURLを生成する

以下、方法とメリット・デメリットを記述する

### BlobをデータURLとして読み取る

```js
const reader = new FileReader();
reader.onload = function(e) {
  console.log(e.target.result) //データURLがコンソールに表示される
}
reader.readAsDataURL(blob) //ここでBlobオブジェクトを読み込み、読み込みが完了したタイミングでreader.onloadに定義した関数が実行される
```
#### メリット
- ファイルの読み込みを非同期で行うことができる。
- URLそのものにデータが埋め込まれているため、URLを直接サーバーに渡すことが可能。

#### デメリット
- Base64エンコードの仕様に則り、データサイズが１３３％ほどに増える
- メモリ上にファイルを展開するため、**メモリを圧迫する**

### Blobを参照するURLを生成する

```js
const imageUrl = window.URL.createObjectURL(blob) //URL生成
console.log(imageUrl) //メモリ上のBlobを参照するURLがコンソールに表示される
window.URL.revokeObjectURL(imageUrl) //URL破棄
```

#### メリット
- URLの生成が即時完了する

#### デメリット
- **一時的なURL**であり、ブラウザを開き直したり、他端末や他ブラウザに渡してもアクセスできない
- `window.URL.revokeObjectURL()`によってURLを破棄しないと、ブラウザを閉じるまで**メモリ上にURLが残ってしまう**
薬学部がプログラミングを始めるきっかけ

今年からDeep Learningの勉強をし始めて思ったことを書き綴っていこうと思います。ペン握って文字を書くより何十倍もこっちの方が早いので楽ですけどね。
#1まず初めにプログラミングの世界に入ってみたいなと思った動機について
私がプログラミングの世界に入ってみたいと思ったきっかけは
[2019AI・人工知能EXPO](https://www.ai-expo.jp/ja-jp/about/previous/sokuho2019.html)
でした。
AIの活躍の場として、様々な場面に生かされていくのだろうということが容易に想像できました。
自然言語処理や画像認識などの技術が様々な形で出展されているのを見て「この技術をもっと医療の分野にも導入していくことができたら」と思いました。
なぜ医療なのかというと、私が6年制の薬学部に所属しているからです。
将来的にはもっと医療分野にも機械化が進んでいくと思っています。その一つの形として、私はあるアプリを紹介します。
[CLINICS](https://clinics.medley.life/)
これはオンライン上で診療を行っていくというサービスを提供するものです。利用者の視点に立つと、時間や労力を節約しながら医療を受けられるという形に私は将来性を感じました。
#2今後
今度また以下のリンクにあるEXPOに行く予定です。
[日経 xTECH EXPO 2019](https://expo.nikkeibp.co.jp/xtech/)
[クロスヘルス EXPO 2019](https://expo.nikkeibp.co.jp/xhealth/)
また今後勉強したことも少しずつアウトプットしていく予定です。
Bashで標準出力と標準エラー出力先をファイルに変えたり戻したりしたい

`echo >> stdout.txt` を繰り返し書くのは面倒だし忘れると辛いので。

サンプルとして関数の中だけ標準出力と標準エラー出力をファイルに書きだして関数を抜ける直前に戻す、ということをやる。

https://wandbox.org/permlink/hWspuZCUdCKtYFzk

``` bash
#!/bin/bash

function f(){
  local n=$1
  # (FDはFile Discriptorの略)
  # FD3を作ってFD1(標準出力)に更新
  # FD1をstdout.txtを追記モードでopenしてそのFDに更新
  # ... という感じ。順番が前後すると意味が変わるので注意。
  # 両方同じファイルのFDを持ってしまい、標準出力が消えちゃう（はず）
  exec 3>&1 1>>stdout.txt 4>&2 2>>stderr.txt
  
  echo out$n
  echo err$n >&2
  # 後始末
  # FD1をFD3が持つ標準出力のFDに更新
  # FD3は閉じる
  exec 1>&3 3>&- 2>&4 4>&-
}

echo out1
echo err1 >&2

f 2

echo out3
echo err3 >&2

f 4

echo out5
echo err5 >&2

echo ---stdout.txt---
cat stdout.txt
echo ---stderr.txt---
cat stderr.txt
```


```
out1
err1
out3
err3
out5
err5
---stdout.txt---
out2
out4
---stderr.txt---
err2
err4
```

スクリプトや関数を呼び出すときに都度リダイレクトすればいいじゃん、というケースが多いのだけど、たまに欲しくなるのでメモです。
【未解消】ロケールID（LCID）が日本語でない場合に、文字列変換関数がうまく動かない

標題の通りの事象で躓いているためメモする。

##ロケールIDって？
ロケール ID（LCID：LoCale IDentifiers）は、言語を表すコード（参考サイトより）
例：英語 (U.S.)	1033、日本語	1041

- https://www.kanaya440.com/contents/script/vbs/others/lcid.html
- https://www.relief.jp/docs/001403.html

##ロケールIDの例
- SystemDefaultLangID
- UserDefaultLangID
- SystemDefaultUILanguage
- UserDefaultUILanguage
- SystemDefaultLCID
- UserDefaultLCID

##ロケールIDをWindows上で変更する方法
下記の参考サイトによると設定アプリから可能との事だが、プルダウンメニューで日本語以外が選べない。調査中。


###参考にさせて頂いたサイト
- http://sygh.hatenadiary.jp/entry/2014/05/24/181319
- https://gdgd-shinoyu.hatenablog.com/entry/20091027/1256601600
　→ここの整理分かりやすい。
- https://blogs.msdn.microsoft.com/dd_jpn/2008/10/29/windows/
文字列をそのまま扱ってくれるraw stringという形式

## 背景

先日、Kolinのリファレンスを読んでいたら、不思議なコードを見かけました。

```kotlin
val text = """
    for (c in "foo")
        print(c)
"""
```

ダブルコートが３つ！？嘘だろ..と思い
これがなんなのか調べました。
（と言いつつ、リファレンスで見つけたので、リファレンスを読んで試しただけです。）

## トリプルクウォートで囲まれた文字

kotlinでトリプルクウォートで囲まれた文字はraw stringと呼ぶようです。
この中では、改行やスペースや「"」などのエスケープ文字が必要になる記号を、そのまま入力しても入力したままの文字として扱ってくれるようです。

```kotlin
val text = """
    "hello world",
    \n
    ¥¥¥¥
    &&'`123n%^&*
    """

println("$text")
```

output

```
    "hello world",
    \n
    ¥¥¥¥
    &&'`123n%^&*
```


ただ、インデントまで文字列として入ってしまうよう...
なので `trimMargin()` が用意されています。

`trimMargin()` の引数には行の先頭の記号を指定できます。（デフォは"|"）
このメソッドを使用することで、その記号が行の先頭になります。

```kotlin
val text = """
    |Tell me and I forget.
    |Teach me and I remember.
    |Involve me and I learn.
    |(Benjamin Franklin)
    """.trimMargin()

println("$text")
```

output

```
Tell me and I forget.
Teach me and I remember.
Involve me and I learn.
(Benjamin Franklin)
```

## 終わりに

正直、これといって使い道は思い当たらないですが、
覚えておくといつか使えそうな気がします。

詳細は、下記のリファレンスを見てみてください。

https://kotlinlang.org/docs/reference/basic-types.html#string-literals
Pipenv+Pytestを使って気象情報API用のPythonライブラリを作成した

# 本記事向けの方
- Pipenvを使ったPythonパッケージのリポジトリを見てみたい。
- Pytestを使った単体試験を行いたい。
- Yahoo気象情報APIを使いたい。

# 概要
本記事はPipenvを使った開発とPytestを使った単体試験を組み込んで、Yahoo気象情報API用のライブラリを作成してみた記事である。
※本記事は実際のリポジトリ内での使われ方や調査した中で自分が分かったことを記述した。実際のPipenvやPytest自体の使い方は先人の方の記事が山ほどあるので最下部の「参考にしたリンク」をご参考に。

作成したライブラリのリポジトリは下記となる。
https://github.com/doara-developer/weatherlib



# Pipenv
Pythonの仮想環境を作成するためのツール。
https://pipenv-ja.readthedocs.io/ja/translate-ja/#


## Pipenvだけでパッケージ管理はダメ？
実際にコードを動作させる環境が限定されていて、その中でPipenvを使える状況ならばPipenv(Pipfile)のみでも良いが、そうでないならば通常のパッケージのようにsetup.py/setup.cfgを用意するべき。

## それなら何故Pipenvを利用するのか？
Pipenvを利用することで、開発時の動作環境を保証することが出来る。よくある「開発環境で動くが、実際の環境で動作しない。」という類の不具合を防止することが出来る。便利。
pipenv installを介してライブラリをインストールすることで、Pipfileに環境が書き込まれる。また、そのPipfile通りの実行環境を別環境でも容易に構築することが出来る。

Pipfile

```
[dev-packages]
flake8 = "*"
autopep8 = "*"
pytest = "*"
pytest-cov = "*"
pytest-mock = "*"
pytest-randomly = "*"

[packages]
requests = "*"
```

## （参考）Pipenvか、Poetryか
「最近ならPipenvじゃなくてPoetryじゃないの？」という人がいるかもしれない。しかし、今回の記事にあたりいくつか調べたところ現在は「今後はPoetryが流行っていくかもだが、まだPipenvが主流」という状況だと思っている。今後自分の中で比較するためにも今回はPipenvを採用した。



# Yahoo気象情報APIの使い方
下記の手順で利用可能、特に難しいことはない。

1. Yahooアカウントを取得する
2. アプリケーションIDを取得する
https://www.yahoo-help.jp/app/answers/detail/p/537/a_id/43397
3. アプリケーションIDをparameterに入れて気象情報APIを叩く
https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/weather.html

# Pytest
Pythonのテストフレームワーク。
https://docs.pytest.org/en/latest/

本リポジトリでは、Pipfile内で定義してある下記スクリプトで実行可能。

```
[scripts]
test = "pytest -v --cov=weatherlib --cov-report=html"
```
## 利用したプラグイン
### pytest-mock
試験したいモジュールが利用するライブラリの返り値を操作することで様々な試験が可能。本リポジトリではYahoo APIから返ってくるレスポンスをモックしている。

### pytest-cov
テストするモジュールのテスト網羅率（カバレッジ）を計測することが出来る。基本的に100%網羅するテストコードを書くべき。

### pytest-randomly
記述されているテストの実行順番を毎回ランダムで実行してくれる。これによりテストの実行順番によっては全てPassしてしまうようなモジュールの不具合を検知することが出来る。（今回程度のテスト量ではあまり意味はないが、、、）
実行時のseed値をメモしておけば、失敗した手順の試験を再実行可能。
https://pypi.org/project/pytest-randomly/

## （参考）Pytest vs Nose
noseを別プロジェクトで使ったことがあり、今回比較の意味でも利用してみた。、が今回利用した機能ぐらいでは大きな差は感じなかった。強いて言うならばPytestの方が書いたコード量が少し少なかったかな・・・。



# まとめ
今回の背景には、Google Nest Hub+ラズベリーパイ+Yahoo気象情報APIを使って、「雨が降りそうになったら通知する」を組んでみようと思い立ち、ただ組むだけでなく、せっかくなのでモダンなPythonライブラリの開発スタイルを勉強してみたい、というところから始まった。

その勉強の中で、PipenvやPytest自体の記事は結構あるが、「じゃあ実際にリポジトリ内でどんな感じで管理しているの？」というのを示しているのは、そこまで多くない気がしたので、今回本記事を書いてみた。

リポジトリのリンクをもう一度貼っておく。
https://github.com/doara-developer/weatherlib


# 参考にしたリンク
とても勉強になりました、感謝いたします。

Pythonのパッケージ周りのベストプラクティスを理解する
https://www.m3tech.blog/entry/python-packaging

2019年に向けてPythonのモダンな開発環境について考える
https://techblog.asahi-net.co.jp/entry/2018/11/19/103455

Pipenvを使ったPython開発まとめ
https://qiita.com/y-tsutsu/items/54c10e0b2c6b565c887a

pytestのとりあえず知っておきたい使い方
https://qiita.com/kg1/items/4e2cae18e9bd39f014d4

pytest-mock を使ってみた #python
https://su-kun1899.hatenablog.com/entry/2019/03/11/020000

すぐに使えるpytestによるカバレッジ計測のコマンド
https://qiita.com/kg1/items/e2fc65e4189faf50bfe6
AndroidのBottomNavigationViewの上にインジケータを楽に取り付け


やぁおはこんばんにちわ。
元気ですか？
いつもスッキリさせるものを紹介するんですが、今日もその類です。

6行程度の実装とレイアウトに少し変更を加えるだけで簡単に実装できるのでメモがてら共有ってかんじですね。
フルソースコードは[こちら(Github)](https://github.com/Pooh3Mobi/Android_EasyProgressSample) におきました。

まず動作を録画してGitアニメーションつくったのでみてください。

![ezgif.com-video-to-gif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4493/57b38aef-15bc-124c-983e-8278e52229c9.gif)



どうやったかというとLinearLayout(Vertical)内のViewのWeightをコードからいじることでアニメーションさせるトリックをつかいました。
Kotlinのコードはこちら


```kotlin
    fun changeBottomNavProgress(index: Int) {
        if (index < 0) return
        val progress = (index) * 33f
        with(bottomNavProgressLeftPaddingView) {
            val lp = layoutParams as LinearLayout.LayoutParams
            lp.weight = progress
            layoutParams = lp
            (this.parent as ViewGroup).layoutTransition.enableTransitionType(android.animation.LayoutTransition.CHANGING)
        }
    }
```
差し込んだレイアウト側はこんな感じ

```xml
    <LinearLayout
        android:id="@+id/progressbar"
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:animateLayoutChanges="true"
        android:orientation="horizontal"
        android:weightSum="99"
        android:background="@android:color/darker_gray"
        android:layout_marginBottom="?attr/actionBarSize"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <View
            android:id="@+id/weight_progress_left_padding"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="33"
            android:background="@color/design_default_color_primary" />

    </LinearLayout>
```

動作は`weight_progress_left_padding`のweightを0にしたり33にしたり66にしたりすると、隣にある青い色のViewが動いているように見えるようにつくってます。知ってみれば簡単なことですね。簡単だしシンプルだし。

`android:weightSum="99"`としてやるのが結構ミソです。まぁ３にして`val progress = (index)`にしてもいいんですが・・・そこはご愛嬌です。レビューでは３にしろって言われるでしょうねw

アニメーションさせるにはKotlinコード側で`(this.parent as ViewGroup).layoutTransition.enableTransitionType(android.animation.LayoutTransition.CHANGING)`をsetLayout前後で書いてやる必要があります。
あとレイアウトXML側にも`android:animateLayoutChanges="true"`をつけてやらないと実行時に例外でコケます。

いやぁシンプルでいいですね。これでスッキリかけます。楽したい人はどうぞ。

（ちょっとレイアウトに差し込むのが面倒だったので、みんなも頑張って。リンクにおいたソースコードのやつ使えばいけそうだけどね！）

### おまけ
プログレスバーの擬似実装もやってみました。コードは増えますがとてもシンプルなコードです！
![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4493/769e6201-cf15-d0c9-2e39-f61f9aef11cf.gif)

コードは上で紹介したリンクみてやってください。