OmniAICreator/Qiita-1.07M huggingface dataset:
Google Apps Scriptを使ってGoogleスプレッドシートと外部APIを連携してみる

# この記事について

- **外部APIの結果をスプレッドシートに書き込みたい！** という方向けの記事です
- qiitaのLGTM数などを定期的に取得してスプレッドシートに書き込む等ができるようになります
- また、業務においてもでAPIを提供しているプロジェクト管理ツール（Backlogなど）と連携することで **チームメンバーのチケット一覧** などを作れるようになります


# GASについて

- スプレッドシートとAPIの連携はGAS（Google App Script）を利用して行います
- GASについては、こちらの[記事](https://www.acrovision.jp/service/gas/?p=339)がわかりやすいかったです

# 連携方法
今回はサンプルとして、qiitaのAPIと連携してみます

- 適当なスプレッドシートを作成します

- スクリプトエディタを開きます
<img width="500px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490831/e6a8f585-482b-b2a7-7353-a51203a9a48f.png">

- 以下のようにコードを記述します
 - qiitaのAPIについては、[こちら](https://qiita.com/api/v2/docs#get-apiv2itemsitem_id)を参照ください
 - コード中に存在する `appendRow()` や `UrlFetchApp`、 `fetch ()` は、 GASで用意されているクラスや関数になるため、[こちらの公式](https://developers.google.com/apps-script/reference/spreadsheet/sheet#appendrowrowcontents)を確認ください

```js
function myFunction() {
  // URL情報
  const origin = 'https://qiita.com';
  const targetItemId = 'c2f7ba5997187854b7a4'; //この記事の記事ID
  const getItemUrl = `${origin}/api/v2/items/${targetItemId}`;

  // スプレッドシートを取得　
  // * XXX部分はスプレッドシートのIDが入ります
  // * IDはスプレッドシートURLを見れば確認できます
  const sheet = SpreadsheetApp.openById('XXX').getSheetByName('シート1');
  // 今日の日付を取得
  const date = new Date();
  const datetime = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;

  // APIとのやりとり
  const res = UrlFetchApp.fetch(getItemUrl);
  const item = JSON.parse(res)
  // スプレッドシートへ書き込み
  sheet.appendRow([datetime, item.title, item.likes_count]);
  
}

```

- スクリプトエディタの実行をクリック
<img width="500px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490831/0aeeab2a-9c85-239b-f574-7c789d3ac434.png">

- スプレッドシートの方を確認すると以下のようになっています
ヘッダー部分は手動で付けました、、笑
<img width="500px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490831/e2d5d1e5-f6d3-cd85-6780-8ae92ebeed26.png">

- これで連携完了です！意外と簡単に連携することができます

# 番外編：定期実行したい

往々にして、1時間ごとにAPIを実行して情報を取得したい等があると思います。
そういう場合は以下のように設定すると上記のスクリプトを定期実行してくれます。

- スクリプトエディタのトリガーをクリック
<img width="500px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490831/d5b3083a-c79a-fee2-5b7c-e9b4d1f78c53.png">

- トリガーの条件を設定する
  - この場合は1時間間隔で実行したいため、`時間主導型`を設定し、間隔を`１時間おき`にしています

<img width="500px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490831/5bd4bc84-20b7-d040-fb14-37b80b862900.png">

- 保存すればトリガーが生成され、定期実行できるようになります

# 最後に

- 筆者もまだまだGASを使いこなせていないため、こういう便利な使い方もあるよ！というコメントをお待ちしております :bow:
windowsでdockerのみでgitを扱う

本記事はwindows環境にてgitなどのインストールにより環境を汚さないためにdockerのみでgitを扱えないかという考えで作成したものです。

## 目次
- Dockerfile作成
- docker-compose.yml作成
- コンテナ起動
- git clone 
- git config 設定

## Dockerfile作成
まずはalpine linux にgitを追加したイメージを作成する

```Dockerfile
FROM alpine

RUN apk update && \
  apk add git bash

RUN mkdir /app
```

- apk コマンドで `git`と`bash`をインストール
- マウントするディレクトリを作成(任意)

## docker-compose.yml
次にデータのマウントを行うためにdocker-compose.ymlを作成する

```docker-compose.yml
version: '3'
services:
  app:
    build: .
    working_dir: /app
    volumes:
      - ./app:/app
```

- `build: .` 先ほどのDockerfileにより作成されたイメージを使用
- `working_dir: /app` コンテナ起動時のデフォルト作業フォルダを指定
- `volumes: - ./app:/app` ホストとコンテナのフォルダの共有設定

## コンテナ起動
コンテナのコンソールを`bash`により起動

```command
docker-compose run app bash
```

実行結果

```
docker-compose run app bash
Creating git_app_run ... done
bash-5.1#
```

## git clone
次にworkディレクトリに任意のリポジトリをクローン

```
bash-5.1# git clone https://github.com/<リポジトリ> .
```
`.`(カレントディレクトリ)を選択することにより作業ディレクトリへ直接クローンすることができる

## git config 設定
※ 2021/08/20現在こちらの設定については意味がないことが判明したため後日修正を致します。

最後に、現状ではcloneとcheckoutなどの変更を加えない作業しかできないためconfigを設定し、commitやpushをできるようにする

```
git config --global user.name <github ユーザ名>
git config --global user.email <github email>
git config --global user.password <github parsonal token>
```

以上

## 結果

gitを普通にインストールした方が楽ですね
Serverlessテンプレートでは, 共通部分はGlobalsにまとめよう

こんな感じで, ServerlessのTemplateにリソースを並べていませんか?

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

# 略

Resources:
  SampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      Handler: app.sample
      Role: !Ref RoleArn
      Environment:
        Variables:
          aaa: bbb
          ccc: ddd
      Layers:
        - !Ref MyLayer
      MemorySize: !FindInMap [EnvMap, !Ref Env, LambdaMemorySize]
      Runtime: python3.8
      Timeout: 5

  Sample2Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      Handler: app.sample2
      Role: !Ref RoleArn
      Environment:
        Variables:
          aaa: bbb
          ccc: ddd
          eee: fff
      Layers:
        - !Ref MyLayer
      MemorySize: !FindInMap [EnvMap, !Ref Env, LambdaMemorySize]
      Runtime: python3.8
      Timeout: 5

# ...
```

## Globalsにまとめる

Serverlessのテンプレートでは, globalsに共通部分をまとめることができます.

```yaml

Globals:
  Function:
    CodeUri: app/
    Environment:
      Variables:
        aaa: bbb
        ccc: ddd
    MemorySize: !FindInMap [EnvMap, !Ref Env, LambdaMemorySize]
    Layers:
      - !Ref MyLayer
    Runtime: python3.8
    Timeout: 5

Resources:
  SampleFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.sample
      Role: !Ref RoleArn

  Sample2Function:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.sample2
      Role: !Ref RoleArn
      Environment:
        Variables:
          eee: fff
```

スッキリしました!

Globalsは, Resourcesに書いたものとmergeされ, 同じキーの値はResourcesの値が優先されます.

## Globalsにまとめられるもの

[ここ](https://github.com/awsdocs/aws-sam-developer-guide/blob/master/doc_source/sam-specification-template-anatomy-globals.md#supported-resources-and-properties)によると,

* AWS::Serverless::Function のほとんど(Events, Roleは無理)
* AWS::Serverless::Api のほとんど
* AWS::Serverless::HttpApi の一部
    * Auth
    * AccessLogSettings
    * StageVariables
    * Tags
* AWS::Serverless::SimpleTable
    * SSESpecification

最も数が増えやすいLambdaは殆どをGlobalsにまとめられるので, 積極的に活用していきましょう
経済・ファイナンスデータの計量時系列分析（沖本）1章　Rコード

#１章
１章のRコードの解答例です。

```
・par(mfrow = c(2,2))
・library(lubridate) data$X = ymd(data$X) %データの構造を割と柔軟に解釈して変換して時系列に変換してくれる。
・Box.test
```
の３つは覚えときたい。 

カバン検定（Box.test)はH_0:全ての自己相関係数が0 を棄却する形で自己相関を見つける。（実質F検定）
OLSにおけるF検定と構造は同じだけど、偏自己相関ではなく自己相関を求めているので形がちょっと変？（重回帰ではなくそれぞれの_に行っているイメージ）。また誤差項の形に仮定をおいていないのでexactにはカイ二乗分布には従わない。（漸近的に自由度mのカイ二乗分布に従うので検定可能。）

（偏自己相関の検定は沖本には載っていなかったが、F検定で対応可能？怪しいので調べておく。）

mの調整によってよって高次の自己相関と検出力のトレードオフがあるので注意。グラフを見ながら見当をつけてやる必要がありそう。(m = log(T)が目安）


#コード
```R
setwd("Okimoto/1")
library(tidyverse)
library(gdata)
library(lubridate)
library(rugarch)

data = read.xls("economicdata.xls")

data$X = ymd(data$X)

par(mfrow = c(3,3))
names = colnames(data)
col_index = 0
x = data$X
for (col_name in colnames(data)){
  col_index = col_index + 1
  y = data[,col_name] #$で撮ろうとするとうまくいかない
  if (col_index != 0){
    plot(x,y)
    title(col_name)
  }
}

data = mutate(data,topix_ln = log(topix),exrate_ln = log(exrate), indprod_ln = log(indprod) ) %>%
  mutate(topix_diff  = topix_ln - dplyr::lag(topix_ln,n=1) ,exrate_diff  = exrate_ln - dplyr::lag(exrate_ln,n=1),indprod_diff  = indprod_ln - dplyr::lag(indprod_ln,n=1))

par(mfrow = c(2,2))
plot(x,data$topix_diff,type="l")
plot(x,data$exrate_diff,type="l")
plot(x,data$indprod_diff,type="l")

Box.test(data$topix_diff, lag = 5)
Box.test(data$exrate_diff, lag = 10)
Box.test(data$indprod_diff, lag = 10)

```

for文のループ内で$で参照しようとするとうまくいかなかった。ループしてる変数で参照するときは素直に[]で指定してあげた方が良さそう。

#結果
##グラフ
![Rplot01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900361/1e77960c-182a-c4aa-24bf-26ba8a15eef1.png)


![Rplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900361/f6c90d90-fc40-4ece-e1d7-28b06df34352.png)

#アウトプット
```
> Box.test(data$topix_diff, lag = 10)

	Box-Pierce test

data:  data$topix_diff
X-squared = 45.416, df = 10, p-value = 1.829e-06

> Box.test(data$exrate_diff, lag = 10)

	Box-Pierce test

data:  data$exrate_diff
X-squared = 53.189, df = 10, p-value = 6.868e-08

> Box.test(data$indprod_diff, lag = 10)

	Box-Pierce test

data:  data$indprod_diff
X-squared = 58.148, df = 10, p-value = 8.107e-09

```
p-value = P(H_1|データ, H_0) は十分小さいので、棄却できる。（自己相関はどこかには存在。）

#reference
Rによる基本的な時系列処理のまとめ
http://user.keio.ac.jp/~nagakura/R/ts_R1.pdf
SwiftUI 環境で表示中のUIViewControllerを取得する

## 概要

SwiftUIのプロジェクトで、現在フロントにあるUIViewControllerを手軽に取得する方法についてのTips

## SwiftUIとUIKitの連携

SwiftUIのViewとUIKit間での連携は

- UIHostingController
- UIViewRepresentable

を使った方法がある。

ただ、SwiftUIのプロジェクトで外部ライブラリなど使用する場合に

いま提示している「UIViewController」を渡すことが必要になるケースがある。


例えば、Googleの「UserMessagingPlatform」を使って

ATT事前許諾プロンプトを提示する際に

SwiftUIのコンテキスト上からライブラリ側にUIViewControllerを渡す必要がある。

方法は他にも色々ありそうだが、その時の対応メモ。


## 現在のUIViewControllerを探す

表示中のUIViewControllerを探す流れは

まず

1. UIApplicationから接続中のUISceneたちを取得
2. 前面にあるアクティブなSceneをフィルタ
3. SceneからUIWindowSceneを探す
4. UIWindowSceneが持つUIWindowからKeyWindowを探す
5. Windowから rootViewController  or そこから生えているpresentedViewControllerを見つける

なお、ここで実際に取得できるのは

``` UIHostingController<SomeOneView> ``` 


となり

これを任意のライブラリなりに渡せば良い。


### 検証

```swift
// 1
let scenes = UIApplication.shared.connectedScenes
debugPrint(scenes)

// 2
let active_scenes = scenes.filter({$0.activationState == .foregroundActive})
debugPrint(active_scenes)

// 3
let window_scenes = active_scenes.map({$0 as? UIWindowScene})
debugPrint(window_scenes)

// 4
let windows = window_scenes.compactMap({$0}).first?.windows
debugPrint(windows)
let first_keywindow = windows?.filter({$0.isKeyWindow}).first
debugPrint(first_keywindow)

// 5
let vc = first_keywindow?.rootViewController
if let _vc = vc?.presentedViewController {
    debugPrint(String(describing: type(of: vc!)))
}else{
    debugPrint(String(describing: type(of: _vc)))
}

// UIHostingController<ContextView>

```

### 上をまとめたもの

例えば、UIViewControllerにExtensionで追加して

```swift

extension UIViewController {
	static func getFrontViewController() -> UIViewController? {
	    let keyWindow = UIApplication.shared.connectedScenes
	        .filter({$0.activationState == .foregroundActive})
	        .map({$0 as? UIWindowScene})
	        .compactMap({$0})
	        .first?.windows
	        .filter({$0.isKeyWindow}).first
	
	    let vc = keyWindow?.rootViewController
	    guard let _vc = vc?.presentedViewController else {
	        return vc
	    }
	    return _vc
	}
}
```

```swift
guard let vc = UIViewController.getFrontViewController() else {
    return
}

// vc
```

みたいに使用したり。
【10章】Javaを学ぼう

今回の記事では、メソッドとクラスについて中心に書いていきたいと思います。私自身のアウトプットの場になりますので、よろしくお願いいたします！


#メソッドについて
メソッドとは、何らかの処理を割り当てた部品です。Javaのファイルを実行すると、自動的にmainメソッドが実行されます。mainメソッドの処理をメソッドに切り分けると、mainメソッドが各メソッドに指示を出し、各メソッドが個々の処理を実行するという構造になります。

##メソッドの定義について

```java:Main.java
public static void メソッド名() {                 
  実行する処理;
}
```

「public static void」の部分はまだ定型として覚えておきます。メソッドの名前は好きに付けることができますが、処理の内容が想像できるような名前をつけるのが理想です。

##メソッドの呼び出しと定義場所について
```java:Main.java
class Main {
 public static void main(String[] args) {        //①mainメソッドが呼ばれる
  hello();                                       //②mainメソッドの中で、helloメソッドが呼ばれる
 }
 public static void hello() {                    //③helloメソッドの中で、System.out.println("Hello World")が実行される
  System.out.println("Hello World");
 }
}
```

出力結果↓

```java:コンソール
Hello World
```

上図はhelloというメソッドを定義し、mainメソッドでhelloメソッドを呼び出しています。メソッドはクラスの中に定義します。クラスの中に定義しないとエラーになりますので気をつけましょう。メソッドを呼び出すためには、**メソッド名()**とするだけです。

##引数について
引数とはメソッドに与える追加情報のようなものという認識て大丈夫です。メソッドを呼び出すときに、一緒に引数を渡すと、メソッドの中でその値を利用することが可能です。

```java:Main.java
public static void メソッド名(データ型 変数名) {                 
  実行する処理;                //仮引数
}
```

メソッドに引数を渡すには、まず引数を受け取れるメソッドを定義しなければなりません。そのためには、メソッドの定義部分で、引数を受け取るための箱となる**変数（仮引数（かりひきすう））**を指定します。仮引数は、変数定義と同様に、データ型を指定する必要があります。

##メソッドに引数を渡す

```java:Main.java
class Main {
 public static void main(String[] args) {       
  hello("Mia");                                       
 }
 public static void hello(String name) {     
  System.out.println(name + "さん、おはようございます");
 }
}
```

出力結果↓

```java:コンソール
Miaさん、おはようございます
```

メソッドに引数を渡すには、メソッド名(引数)としてメソッドを呼び出します。渡された引数は、メソッドの仮引数で指定した変数に代入され、その変数はメソッドの処理の中で用いることができます。

##複数の引数
引数は複数渡すことも可能です。メソッドが複数の引数を受け取るためには、仮引数をコンマ（,）で区切って定義します。また、引数は左から順番に「第1引数、第2引数・・・」というように呼びます。

```java:Main.java
public static void メソッド名(データ型 変数名1, データ型 変数名2) {                 
  実行する処理;                //第1引数        //第2引数
}
```

それでは、実際にメソッドに複数の引数を渡してみます。

```java:Main.java
class Main {
 public static void main(String[] args) {       
  printPrice("ハンバーガー",500);
  printPrice("オレンジジュース",150);                                     
 }
 public static void hello(String item, int price) {     
  System.out.println(item + "は" + price + "円です");
 }
}
```

出力結果↓

```java:コンソール
ハンバーガーは500円です
オレンジジュースは150円です
```

仮引数は任意に順番を決められますが、メソッドを呼び出すときは、仮引数の順番通りに引数を渡さなければなりません。
下図を見てください。

```java:Main.java
class Main {
 public static void main(String[] args) {       
  printPrice(500, "ハンバーガー");                                     
 }
 public static void hello(String item, int price) {     
  System.out.println(item + "は" + price + "円です");
 }
}
```

**引数を渡す順序が反対**になっています。
その結果、String型の仮引数に整数を入れようとするので、エラーになってしまいます。


以上がメソッドとクラスについての記事になります。次章では戻り値を中心に記事を書いていきたいと思います。
よろしければご覧になってください！
最後までご覧いただきまして、ありがとうございました！
【9章】Javaを学ぼう

今回の記事では、配列について中心に書いていきたいと思います。私自身のアウトプットの場になりますので、よろしくお願いいたします！

#配列について

##配列とは
変数のセットというようなイメージです。
変数が1つしか値を扱えないのに対し、配列は複数の値をまとめていれておくことが可能です。
配列に入っているそれぞれの値のことを要素と呼びます。

##配列の変数定義について
配列を扱う場合には、配列型の変数に配列を代入します。配列型は、「int型の要素を持つ配列型」「String型の要素を持つ配列型」という風に指定する必要があります。記述方法は下図の通りになります。

```java:配列の変数定義
int[]    .......    数値を要素に持つ配列

String[]    .......    文字列を要素に持つ配列
```

[]の間にはスペースを空けないように注意しましょう！

##配列の作成方法
配列は{ }の中に、コンマ（,）で区切りながら値を書くことでつくることができます。[]と{}を混同しないように注意してください。

```java:Main.java
int[] numbers = {3,16,47};   .......    整数を要素に持つ配列 numbers

String[] names = {Tom,James,Mia};   .......    文字列を要素に持つ配列 names
```

##インデックス番号
配列の要素には、前から順に「0, 1, 2・・・」と数字が割り振られています。これをインデックス番号といいます。**インデックス番号は0から**始まります。
配列の各要素は、**配列名[インデックス番号]**とすることで取得することができます。

```java:Main.java
String[] names = {Tom,James,Mia};
System.out.println("私の名前は" + names[2] + "です");
```

出力結果↓

```java:コンソール
私の名前はMiaです
```

##配列の要素の上書き
特定の要素に値を代入することで、要素を上書きすることができます。下図を確認します。

```java:Main.java
String[] names = {Tom,James,Mia};
System.out.println(names[2]);
names[2] = "Emma";  //2番目の要素を上書き
System.out.println(names[2]);
```

出力結果↓

```java:コンソール
Mia
Emma
```

配列では存在しない要素に値を代入することはできません。エラーが発生しますので注意してください！

```java:Main.java
String[] names = {Tom,James,Mia};
names[3] = "Emma";  //存在しない要素のためエラー発生！！
```

#配列と繰り返しについて

##配列とfor文
配列namesの要素を全て出力するために、それぞれの要素にSystem.out.println()を用いることは非常に大変です。しかし、これを繰り返し処理で学んだfor文で書いてみると配列の要素の値を簡単に一覧表示できるようになります。

```java:Main.java
//for文を用いない場合
String[] names = {Tom,James,Mia};
System.out.println(names[0]);
System.out.println(names[1]);
System.out.println(names[2]);

//for文を用いた場合
String[] names = {Tom,James,Mia};
for(int i = 0; i < 3; i++) {
  System.out.println(names[i]);   //変数iが0,1,2の間、繰り返される
}
```

##lengthについて
配列には、要素の数を数えるlengthという機能が備わっています。
lengthを用いれば、for文の条件式「i < 3」を下図のように書き換えることができ、配列の要素数を気にする必要がなくなります。

```java:Main.java
//for文の中にlengthを用いる場合
String[] names = {Tom,James,Mia};
for(int i = 0; names.length; i++) {
              //配列.lengthとすることで、要素数を気にする必要がなくなる
  System.out.println(names[i]); 
}
```

##拡張for文について
for文は配列用に特別な構文である、拡張for文を用意しています。
これを使えば、先ほどのfor文をよりシンプルに書くことが可能になります。

```java:拡張for文の記述方法
for(データ型 変数名 : 配列名) {
  繰り返す処理; 
}
```

拡張for文では、配列の各要素の値を**順に代入する変数**を用意します。

```java:Main.java
//拡張for文を用いた場合
String[] names = {Tom,James,Mia};
for(String name : names) {         //for(データ型 変数名 : 配列名)
  System.out.println(name); 
}
```

上図では、繰り返しの度に、**変数nameに配列namesの要素が順に代入**されていきます。また拡張for文では、自動的に要素の数だけ繰り返しが行われます。
また、普通のfor文ではインデックス番号を用いて配列の要素を取得しなければなりませんが、拡張for文では**変数に配列の要素自体が代入**されます。拡張for文の方がシンプルに書けることが多いのため便利です。



以上が配列についての説明になります。次章からはメソッドについて記事を書きたいと思います。
よろしければご覧になってください！
最後までご覧いただきまして、ありがとうございました！
Airflow2.0のTaskflowAPIでmacroを使う方法

# 背景
Airflow2.0で、PythonOperatorやXComの受け渡しをシンプルに書ける [TaskflowAPI](https://airflow.apache.org/docs/apache-airflow/stable/tutorial_taskflow_api.html) が登場しました。TaskflowAPIでAirflowの[Macro](https://airflow.apache.org/docs/apache-airflow/stable/macros-ref.html)を使う方法なかなか見つからなかったのでメモしておきます。

# 実装

タスク内で `from airflow.operators.python import get_current_context` の `get_current_context()` を呼び出すとマクロが取得できます。

```py:sample.py
from airflow.decorators import dag, task
from airflow.utils.dates import days_ago
from airflow.operators.python import get_current_context


@dag(default_args={'owner': 'airflow'}, schedule_interval=None, start_date=days_ago(2))
def fetch_pd_log_entries():

    @task
    def execute_task():
        print(get_current_context()['execution_date']) # pendulumオブジェクトが取得できる

    execute_task()


hoge_dag = fetch_pd_log_entries()
```

# 参考

[Passing arguements using Taskflow API in Airflow 2.0](https://stackoverflow.com/questions/65611324/passing-arguements-using-taskflow-api-in-airflow-2-0)

https://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/operators/python/index.html#airflow.operators.python.get_current_context
MVCモデルのまとめ

#今日のテーマ
CRUDアプリの基礎部分を作り終えたので、今回はMVCモデルについて学んだことを投稿していこうと思います。

#MVCモデル
MVCモデルとは、ソフトウェア設計モデルの一つであり、プログラムの処理をModel,View,Controllerに分けて開発を行う方法のことである。
利点としては、役割別にすることで独立性が高くなり、依存性が少なくなることで、効率的なアプリケーション開発が行えることである。また、ある箇所の変更が他の要素に影響しにくくなるということも挙げられる。

#MVCモデルの概要
MVCモデルでは、以下のようにデータが処理されます(自分でまとめたものです)。ざっくりまとめると、

- ユーザーが、URLでアクセス
- ルーティングにより、必要なControllerに割り当てられる。
- Modelが必要なデータを取得する。
- 取得したデータをもとに、Viewを作成して、ControllerにHTMLを返す
- 生成したHTMLをユーザーに返す。



![スクリーンショット 2021-08-17 14.51.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864916/62b1013c-03b0-2562-e23e-3af7e8821402.png)

#Model
データベースとデータのやり取りを行うパーツ データベース内のデータを取得したり、データの更新や削除、新規作成などの機能を実装する。

#View
ユーザーが実際に見える画面の処理を行う。Webブラウザに表示する動的なHTMLを生成する。動的ページとは、アクセスした時の状況に応じて、データベースから取得したデータを埋め込んで異なるページを作成するものである。

#Controller
ユーザーの入力に基づいて、ModelとViewを制御する。ModelとViewの橋渡しをする役割 ユーザから受け取ったURLと、処理(コントローラーのアクション)を紐づけるのがルーティングである。

#まとめ
MVCモデルはソフトウェア設計パターンの一つであり、効率的なアプリケーション開発が行われる。
ブラウザで、廃墟を探索しお化けと自撮りしたい


#動機
mediapipe のhuman seqmentationを使ってゲームを作りたかった。
jsを勉強中なので、ブラウザで作りたい。
最初は、世界遺産で自撮りできるものを考えていたが、素材が集まらなかったので
https://qiita.com/im02kai/items/31fa6cfc8e50855bebff
を使って、素材を作成。
素材ありきで、廃墟探索になり静止画ではつまらないので、VRツアーにしました。

#完成サイト
https://www.web-tools.app/ghosttop


#動画です、
https://www.youtube.com/watch?v=Tbij9g68Hzs


#環境
mediapipeを使うので、レンタルサーバーでは、無理、ということで
https://qiita.com/im02kai/items/948dd616b86596e748d2
で環境構築

#構成
こちらも、mediapipeがpythonインターフェイスを持つので
flask
flask-socket.io
になりました。


#スクリプト は、この記事をもとにしてます
https://qiita.com/im02kai/items/2b150b875bea6a3035b8
https://qiita.com/im02kai/items/e460fa86be1501474275

肝心のmediapipe 部分は、上記 の合成部分をmediapipeで書き換え

```python:app.py
results = selfie_segmentation.process(img1)
mask = np.stack((results.segmentation_mask, ) * 3, axis=-1) >= 0.1
dst = np.where(mask, img1, img2)
```
    
これだけです　簡単。
ただ、場合によってはmediapipeが、インストールできないことがあります
私の場合は、ubuntu18.04だったためpythonが古く、python3.8.5をソースからビルドしました
apt では入りませんでした。
ubuntu20.04 にすれば何も問題ないです。

#デプロイ後の修正
最安プランを選択したため、リアルタイムでは処理が追いつかないので
カメラ画像を半透明にし、jsだけで擬似合成させ、１フレームのみ最終処理するという手段をとりました。


#これを使って、、、
insta360を購入したので、世界遺産は無理でも観光地ぐらいだったら
当初の目的を果たせるかなと思い、撮影の練習してます
dockerでmysql8.0を利用する最小確認構成

### 概要

### フォルダ構成

```tree
.
├─docker-compose.yml
└─mysql
   └─conf.d
      └─mysql.cnf
```

### ファイル

```docker-compose.yml
version: '3.8'
services:
  db:
    image: mysql:8.0
    ports:
      - '3306:3306'
    volumes:
      - ./mysql/conf.d:/etc/mysql/conf.d
      - mysql:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
      TZ: "Asia/Tokyo"
volumes:
  mysql:
```

```mysql/conf.d/mysql.cnf
[mysqld]
default_authentication_plugin = mysql_native_password
skip-host-cache
skip-name-resolve

character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init-connect = SET NAMES utf8mb4
skip-character-set-client-handshake

[client]
default-character-set = utf8mb4

[mysqldump]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4
```

### コマンド

コンテナ起動

```command
docker-compose up -d
```

mysql接続

```command
docker-compose run db mysql -h db -u root
```

### 結果
```
# mysql -h db -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.26 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

以上

railsなどから接続する際にはdatabase.ymlにて`host: db`としてやる
PytorchでCSVで保存しているデータを線形回帰する一歩手前までの話

前回に引き続き、今回もPytorchを使用した線形回帰についてです。

線形回帰を実践で行うには、CSVとして保存されているデータを読み込んで計算をすることでしょう。
今回は、CSVとして保存されているデータを、線形回帰を行う直前までの状態に加工します。

#目標

今回の目標は、CSVファイルとして1つのファイルに保存されている情報を、2つのPyTrochのtensor（targets, inputs）にすることです。

方針は以下の通りです。

>
>csvをnumpy.ndarrayとして読み込む
>読み込んだnumpy.ndarrayをinputsとtargetsに切り分ける
>切り分けたものを、PyTorchに読み込ませる
>

# csvをnumpy.ndarrayとして読み込む

numpy.loadtxt()メソッドを使って、csvを読み込みます。

```py
import numpy as np

#ファイルのパスは適切なものを入力する。
f =  np.loadtxt("C:\\Users\\YOURNAME\\Desktop\\FILENAME.csv", delimiter=',', encoding="utf-8", skiprows=1)

```

■失敗例
•パスをペーストしたときに"\"を"\\"にするのを忘れた。
　エラーが起こります。

•delimiterを設定し忘れた
　delimiterは、csvをndarrayにするための区切り文字です。
　delimiterを設定しないと、ndarrayの行・列の区切りが意図しない形になります。
　今回は、コンマをdelimiterとして設定しています。

•encodingを設定し忘れた
　文字化けします。

•skiprowsを設定し忘れた
　csvファイルの1行目には、各項目の項目名が、数字以外の文字で記載されている場合が多いかと思います。
　その項目名の行を飛ばさないと、ndarrayとして正しく読み込まれません。

•日本語が途中で混ざっていた
　ndarrayとして読み込ませたい部分に、本来ならば「49」などの数字だけが入ってほしいにもかかわらず「49件」などのように不要な文字が入っている場合があり得ます。
　その場合も、エラーを起こします。

#読み込んだnumpy.ndarrayをinputsとtargetsに切り分ける

PyTorchで線形回帰を行うためには、inputsとtargetsという2種類の情報が必要です。
しかし、csvを読み込んだばかりでは、使用したい情報がどちらも1つのndarrayとしてくっついてしまっています。

今回は、ndarrayの最も左の2列をtargets、それより右側すべてをinputsとして使用します。

```py
targets, inputs = np.hsplit(f, indices_or_sections = [2])
```

このようになります。
![hsplit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851956/03b2c754-7644-be5f-a21c-dfb61744ea71.png)


**h**splitといわれると、horizontalに(行が並んでいる方向)に沿って切断しそうに見えます。
しかし、実際には、horizontalなものを叩き切るのがhsplitのようです。
（風邪薬は風邪になるための薬ではなく風邪の症状に効く薬であるのに似ていますね。）

indices_or_sectionsは、刃を入れる箇所を指定できます。
刃を入れる箇所が1か所であろうと、配列で指定する必要があります。

#切り分けたものを、pytorchに読み込ませる

pytorchに読み込ませるには、from_numpyを使います。

```py
import torch

inputs  = torch.from_numpy(inputs)
targets = torch.from_numpy(targets)
```

![from_numpy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851956/50bbcd3c-4c3c-5cb9-33cb-60a0a647f442.png)


できました！

あとは、前回の記事のような形で線形回帰を行うことができます。
初心者に向けるTiDBの学習 ～ストレージ編 第3回～

## 初心者に向けるTiDBの学習メニュー
[初心者に向けるTiDBの学習 ～ストレージ編 第1回～] (https://qiita.com/it2911/items/a676bb6a63b07e865558)
[初心者に向けるTiDBの学習 ～ストレージ編 第2回～](https://qiita.com/it2911/items/8050f76eba36f6dc7a25)
[初心者に向けるTiDBの学習 ～ストレージ編 第3回～](https://qiita.com/it2911/items/054e7a05764753964059)  <- 今ここ
[初心者に向けるTiDBの学習 ～コンピューティング編 第1回～](https://qiita.com/it2911/items/0dc6ef5e351b4e7379c5)
[初心者に向けるTiDBの学習 ～コンピューティング編 第2回～](
https://qiita.com/it2911/items/0819844669fe12b3d6b2)
[初心者に向けるTiDBの学習 ～スケジューリング編～](
https://qiita.com/it2911/items/0a5e9b4c4f0eee846ba7)

![shutterstock_1566296494.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197234/27527a2e-be4e-0c18-5395-e8d5932813c5.jpeg)

初心者に向けるTiDBの学習の[ストレージ編 第1回](https://qiita.com/it2911/items/a676bb6a63b07e865558)と[ストレージ編 第2回](https://qiita.com/it2911/items/8050f76eba36f6dc7a25)でデータの格納、キーバリュー、RocksDB、Raftとリージョンなど概念を紹介いたしました。ストレージ編の最終回でMVCCとトランザクションを紹介します。みなさんは最後まで頑張りましょう。

MVCC
---
多くのデータベースでは、複数バージョンの同時制御(MVCC: Multi-Version Concurrency Control)が行われます。TiKVも例外ではありません。MVCCを介さずに2つのクライアントがキーの値を同時に更新すると、データはロックされます。分散シナリオでは、このような処理はパフォーマンス問題やデッドロック問題につながります。

TiKVは、キーにバージョンを付記することによってMVCCを実現します。MVCCを行わないと、TiKVのデータレイアウトは次のようになります。

```
    Key1 -> Value
    Key2 -> Value
    ……
    KeyN -> Value
```

MVCCを行うと、TiKV内のキー配列は次のようになります。

```
    Key1-Version3 -> Value
    Key1-Version2 -> Value
    Key1-Version1 -> Value
    ……
    Key2-Version4 -> Value
    Key2-Version3 -> Value
    Key2-Version2 -> Value
    Key2-Version1 -> Value
    ……
    KeyN-Version2 -> Value
    KeyN-Version1 -> Value
    ……
```

キーに複数のバージョンが存在する場合は、一番大きい数値を最初に配置します(必要に応じ、キーとは順序付けられた配列だと説明したキーバリューセクションにもう一度目を通してください)。このように、キーにバージョンを付記して値を取得するときには、キーとバージョンを使用したMVCCのキー(Key-Version)を構築できます。続いて、Seek(Key-Version)を直接実行し、このKey-Version以降である最初の位置を見つけることができます。詳細については、[「MVCC in TiKV (TiKVにおけるMVCC)」](https://pingcap.com/blog/2016-11-17-mvcc-in-tikv)を参照してください。


トランザクション
---
TiKVのトランザクションはパーコレーターモデルを採用しており、多数の最適化が行われています。ここで触れておきたいことは、TiKVのトランザクションは楽観的なロックを使用するということです。TiKVのトランザクションは、実行プロセスでは書き込み衝突を検出しません。衝突を検出するのはコミットフェーズ内だけです。先にコミットを終了するトランザクションは正常に書き込まれますが、他のトランザクションは再試行します。その会社の書き込み競合が深刻でなければ、このモデルのパフォーマンスはきわめて良好です。たとえば、大きなテーブル内の複数のデータ行をランダムに更新するといった作業に難なく対応できます。しかし、書き込み競合が深刻だと、パフォーマンスは低いものとなります。カウンタは極端な例と考えてください。多くのクライアントがわずかな行を同時に更新するという状況は、深刻な競合と多数の無効な再試行につながります。

後記
---
ストレージ編の記事では、TiKVの基本概念と若干の細部、この分散型トランザクションキーバリューエンジンのレイヤー構造、マルチデータセンターのディザスタリカバリを実現する方法などを紹介しました。次の記事では、分散データベースTiDBのコンピューティングについて紹介します。
モジュール結合度

モジュールが、他のモジュールとどのように結合するかを示す尺度。
弱いほどモジュールの独立性が高くて好ましい。

【データ結合】
単一のデータを引数として受け渡すモジュール

【スタンプ結合】
データ構造（複数のデータをひとまとめにしたもの）を引数として受け渡すモジュール

【共通結合】
データ構造を大域的データ（グローバル領域のデータ）として受け渡す

【内部結合】
すべてのモジュール内のデータを直接参照するモジュール
経済・ファイナンスデータの計量時系列分析（沖本）2章　Rコード

#２章
２章のRコードの解答例です。
以下はやっててちょっと注意が必要だなと思った点。
・基本的にはARIMAを使えば良い（AR, ARMAにspecificなのは使わなくて良い）
・acf使えばコレログラムは一瞬で出てくる。（コレログラムは単回帰に対応してる点に注意。）
・arimaの返り値はデータフレームっぽくなってるので$で要素を指定。(要素をループさせて取るときは[]で指定した方が良さそう。）

理論として気になったのは
・自己相関が存在してる時点で重回帰における多重共線性に対応する問題はかなり起きるはず。AR(2)を考えてx_tをx_{t-1}とx_{t-2}に回帰するときにx_{t-1}とx_{t-2}はかなり強い相関が存在することを考えると、AR(p)はかなり不安定になるのでは？
（多重共線性は係数のstdを通じて予測のstdにもかなり効いてきてしまうはず）
・AIC, BICを使うのが時系列の定石っぽいけど、理論的な裏付けを時系列の文脈でしている文献はまだ読めていない。クロスバリデーションでも良いような気がするけどどうなんだろう。

#コード
```R
#okimoto 2.5

setwd("Okimoto/2")
library(tidyverse)
library(gdata)
library(lubridate)
library(rugarch)
data = read.xls("economicdata.xls")

data$X = ymd(data$X)

arma40 = arima(data$nikkei225,order = c(4,0,0))
arma40$aic
Box.test(arma40$residuals, lag=10, type="Ljung-Box") 

arma12 = arima(data$nikkei225,order = c(1,0,2))
arma12$aic
Box.test(arma12$residuals, lag=10, type="Ljung-Box")



#2.6
setwd("Okimoto/2")
library(tidyverse)
library(gdata)
library(lubridate)
library(rugarch)
data = read.xls("arma.xls")

par(mfrow = c(3,3))

acf(data$y1,plot=T)
acf(data$y1,plot=T,type = 'p')

for (p in 0:5) for (q in 0:5){
  
  armapq = arima(data$y1,order = c(p,0,q))
  aic = armapq$aic
  cat("p =",p, "q =",q, "aic =", aic, "\n")
  
  }

```

#reference
シンプルな分析方法がまとまってる
http://user.keio.ac.jp/~nagakura/R/ts_R1.pdf
WindowsでGitHubの認証をパスワードからパーソナルアクセストークンに切り替える

# 環境
- Windows 10 64bit 20H2

# 手順
1. GitHub上で[パーソナルアクセストークンを発行](https://docs.github.com/ja/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token)する．
1. 設定→設定の検索で**資格情報マネージャ**を検索→起動<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/52f2f8fd-be5b-6055-c6b1-28f5207c476c.png)

1. **Windows資格情報**を選択する．<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/8ebc7a2a-fa06-f4b6-67bf-2ee49c47de2f.png)

1. **汎用資格情報**から`git:https://github.com`を探す．<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/1e85d5d9-4d2f-f35d-0934-61637d33615e.png)


1. **編集**をクリックして，パスワードをパーソナルアクセストークンに置き換える（ユーザ名はそのままでよい）．<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224040/88d4c0a8-b208-608f-39e2-ae2c72bb6858.png)

1. **保存**を押して完了．
AWS CLI上からCognito カスタム属性を追加したい

## 背景
Cognitoのカスタム属性を追加する上で、AWS CLIから作業する必要が発生し、備忘録としてメモ。。。
ドキュメントは[こちら](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-update-user-attributes.html)

## 前提
追加したいカスタム属性が設定されていること （以下画像であればenvが設定されていること）

![スクリーンショット 2021-08-17 14.33.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653537/09007f89-dffd-41ff-1910-e7a1830f2c17.png)

※もしかしたら必要ないかもしれませんが、筆者は先に設定して作業を行いました。

## 作業内容
実行コマンドは以下

```bash
aws cognito-idp admin-update-user-attributes --user-pool-id xxxxx --username xxxxxxxxxx --user-attributes Name="custom:xxxx",Value="xxxx"
```

## 解説
- `user-pool-id xxxxx`


"xxxxx"に以下画像の"プールID"の後の文字列を入力 
![プールIDモザイク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653537/ba8270ad-e477-cf33-0bd9-9d48330bddc5.png)

- `username xxxxxxxx`

"xxxxxxxx"に"ユーザーとグループ"タグにあるカスタム属性を追加したいユーザー名を入力
![スクリーンショット 2021-08-17 14.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653537/893f3766-1be6-be21-e330-14a28535739c.png)

- `user-attributes Name="custom:xxxx",Value="xxxx"`

custom:以下"xxxx"には、前提の項目で設定したカスタム属性名を入力(今回は"env"と入力)
Value=以下"xxxx"には、実際に追加したい値を入力

:::note warn
コマンドライン上で行うと、上記コマンド入力後に dquote> と表示される時があります 。その際は、ダブルクォーテーションの数を見直してみてください
:::

## 参考
https://qiita.com/USI/items/839d4beabfdfd030be89
ChromeのUser-Agentの行方（2021年8月現在）


# 今までの経緯

ChromeでのUser-Agentの扱いについての経緯はこちらの記事が分かりやすいかと思います。
[ChromeでUserAgentが凍結される日（User Agent Client Hintsの使い方）](https://qiita.com/paddy-oti/items/fae9ecca9facc9797035)

要約すると、

* 2020年1月：同年9月を目途にUser-Agent文字列を凍結する計画が示される
* 2020年4月：コロナ渦を考慮して2021年以降に計画が延期される

という状況です。

# 2021年8月現在の状況

今年2021年5月にChromium Blogに以下の記事が投稿されています。
[Update on User-Agent String Reduction in Chrome](https://blog.chromium.org/2021/05/update-on-user-agent-string-reduction.html)
また、下記のページにUser-Agent Reductionの計画についてまとめられています。
[User-Agent Reduction - Chromium Projects](https://www.chromium.org/updates/ua-reduction)

# UserAgentは凍結でなく削減？

元々は "Freeze" だった表現が、 "Reduction" に変化しています。
前述のページ "User-Agent Reduction" の "Sample UA Strings: Final Reduced State" を読むと下表のような対応になるようです。

|項目 | ステータス |
|:---|:---|
| OS | 継続 |
| OSバージョン | 廃止 |
| ブラウザ メジャーバージョン |継続|
| ブラウザ マイナーバージョン以下 | 廃止 |

# スケジュール

Phase1～6から成る移行フェーズが設けられますが、基本的に以下2つのトライアル期間が重要になりそうです。

|Phase| 期間 |説明|
|:---|:---|:---|
|Origin Trial| 最低6ヶ月 | Googleに申請することで、User-Agentの文字列削減を特定のサイトで **事前に** 確認できる|
|reverse Origin Trial| 最低6ヶ月 | Googleに申請することで、User-Agentの文字列削減の **開始後** 、特定のサイトで変更前の状態を維持することができる |

Origin Trialが最低6か月となっています。逆にいうと、Origin Trialの開始から最短で6ヶ月経つとフェーズ4のUser-Agentの文字列削減が開始する可能性があるわけです。現時点でトライアルの開始はまだアナウンスはされていないようですが、仮に2021年8月に開始した場合、2022年2年には開始される可能性があります。個人的には実際にはもっと延びるのではないかとも思いますが、プロジェクトとしては最短の場合を踏まえてスケジュールを考えた方が良いかと思います。
TensorFlowでのtext.Tokenizerがうまく動かなかったのでtensorflow_textを使ってみた

#作業環境
Jupyter Notebook(6.1.4)を用いて作業を進めた。
各versionは`pandas`(1.1.3), `tensorflow`(2.5.0), `tensorflow_datasets`(4.3.0), `tensorflow_text`(2.5.0)である。

#発生状況

`TensorFlow`について学習中、文章データを読み込みそれをトークンに分割する場面が出てきた。調べたところ`tensorflow_datasets`パッケージの中に`Tokenizer`クラスが含まれているようだったので以下を実行してみたところエラーになってしまった。

```python
import tensorflow as tf
import tensorflow_datasets as tfds

tokenizer =tfds.features.text.Tokenizer()
#---> AttributeError: module 'tensorflow_datasets.core.features' has no attribute 'text'
```

どうやらもうこのクラスは利用できなくなっているようである。[TensorFlowの公式ガイド](https://www.tensorflow.org/datasets/api_docs/python/tfds/deprecated/text/Tokenizer#methods "tfds.deprecated.text.Tokenizer")を見てみると、`text.Tokenizer`がdeprecated(非推奨)のクラスの中に入っていることが確認できた。一応以下のようにすると(2021年8月17日現在では)まだ使えるようである。

```python
tokenizer =tfds.deprecated.text.Tokenizer()
tokens = tokenizer.tokenize("What you know you can't explain, but you feel it.")
print(tokens)
#---> ['What', 'you', 'know', 'you', 'can', 't', 'explain', 'but', 'you', 'feel', 'it']
```

ただ非推奨なのでいつまで使えるのか不安ではある。そこで別の方法として`tensorflow_text`を使用してみた。

#`tensorflow_text`を使ってトークンに分割する

まずはプロンプトで以下のようにインストールを行った。

```
pip install tensorflow-text
```

[GitHubで公開されているガイド](https://github.com/tensorflow/text/blob/master/docs/guide/tokenizers.ipynb "tensorflow_textのtokenizerガイド")から以下を実行して試してみた。

```python
import tensorflow_text as tf_text

tokenizer = tf_text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
#---> [[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]

tokenizer = tf_text.UnicodeScriptTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
#---> [[b'What', b'you', b'know', b'you', b'can', b"'", b't', b'explain', b',', b'but', b'you', b'feel', b'it', b'.']]
```

1つ目の`WhitespaceTokenizer()`は単純にスペース区切りで一つの単語と認識し、2つ目の`UnicodeScriptTokenizer()`は記号も1つの単語として認識されている。

もともとやりたかった`text.Tokenizer()`の結果と見比べてみると、

- 区切り方は`UnicodeScriptTokenizer()`の方が近いが、記号もトークンとして認識されている
- `tensorflow_text`では一つ一つの単語がバイナリ表現で返ってきている
- `tensorflow_text`ではリストのリストとして返ってきている

といった違いがある。

そこでこれらを解消するために以下を実行して`text.Tokenizer()`の結果に寄せてみた。

```python
#「リストのリスト」状態を解消
l = tokens.to_list()[0]
#各要素をバイナリからstrへ変換
l = [s.decode('utf-8') for s in l]
#記号の削除
l = [i for i in l if not i in [',', '.', "'", '?', '!']]
l
#---> ['What', 'you', 'know', 'you', 'can', 't', 'explain', 'but', 'you', 'feel', 'it']
```

これで今回の文章については同じ結果を得ることができた。

#課題
以下のような課題があげられる。

- for文で実行しているのでかなり時間がかかる
- 記号の削除の仕方が限定的

二番目については正規表現をうまく使えばもっと落とすべき表現を広範囲に指定できそうである。また、'is'などの頻出表現を消去するのもこのあたりでいじってもいいかもしれない。
リモートカメラシステム （MQTT ブローカーに画像をそのまま送る）

次のシステムを構築するための検証です。
[Grove IoT スターターキット for SORACOM で作るリモートカメラシステム](https://qiita.com/ekzemplaro/items/541b82908cec46f6aa7b)

調べている過程で、MQTT ブローカーに画像をそのまま送れることが分かりました。

次のページを参考にしました。
[mosquitto，paho-mqttで画像のやりとり](https://qiita.com/masa-ramenO/items/6dcb706107e9307a599e)

パブリッシュ
camera.jpg という画像を送ります。

```sh:go_pub.sh
#
#	go_pub.sh
#
#					Aug/17/2021
#
BROKER='violet.local'
TOPIC='sample/imageTopic'
#
mosquitto_pub -h ${BROKER} -p 1883 -t ${TOPIC} -f camera.jpg
#
```

サブスクライブ
受け取った画像を output.jpg に保存します。

```py:subscribe_jpg.py
#! /usr/bin/python
#
#	subscribe_jpg.py
#
#						Aug/17/2021
# ------------------------------------------------------------------
import sys
import paho.mqtt.client as mqtt

host = 'violet.local'
port = 1883
topic = 'sample/imageTopic'

# ------------------------------------------------------------------
def on_connect(client, userdata, flags, respons_code):
	print('status {0}'.format(respons_code))
	client.subscribe(topic)

# ------------------------------------------------------------------
def on_message(client, userdata, msg):
	sys.stderr.write("*** on_message ***\n")
	str_out = msg.payload
	sys.stderr.write("%d\n" % len(str_out))
	outfile = open('./output.jpg', 'wb')
	outfile.write(msg.payload)
	outfile.close

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
client = mqtt.Client(protocol=mqtt.MQTTv311)
client.on_connect = on_connect
client.on_message = on_message
client.connect(host, port=port, keepalive=60)
client.loop_forever()
#
# ------------------------------------------------------------------
```
grpc ruby の UInt64Value フィールドの使い方を凡ミスしてた

gprc ruby で、UInt64Value タイプのフィールドにnilを設定する時に以下のミスをしてた。


## 再現手順


```proto
syntax = "proto3";
package myapp.post;
option ruby_package = "PostPb";

import "google/protobuf/wrappers.proto";

message GetLatestPostIdRequest {
  uint64 user_id = 1;
}

message GetLatestPostIdResponse {
  google.protobuf.UInt64Value post_id = 1;   /// 注目！
}
```

このprotoを使用して生成したgrpc rubyサーバーにおいて、post_idにnullを設定したいときに前者の方法で設定してしまっていた。


### case1 `post_id = nil` を与える場合
以下。`Google::Protobuf::UInt64Value.new`の出番はない。

```rb
### 間違った使用法

> MyApp::PostPb::GetLatestPostIdResponse.new(post_id: Google::Protobuf::UInt64Value.new(value: nil))
=> <MyApp::PostPb::GetLatestPostIdResponse: post_id: <Google::Protobuf::UInt64Value: value: 0>>

> MyAapp::PostPb::GetLatestPostIdResponse.new(post_id: Google::Protobuf::UInt64Value.new(value: nil)).post_id
=> <Google::Protobuf::UInt64Value: value: 0>

### 正しい使用法

> MyApp::PostPb::GetLatestPostIdResponse.new(post_id: nil)
=> <MyApp::PostPb::GetLatestPostIdResponse: >

> MyApp::PostPb::GetLatestPostIdResponse.new(post_id: nil).post_id
=> nil


### 正しい使用法２ (そもそも{post_id: nil}を初期時の引数に与えなくてもよい)

> MyApp::PostPb::GetLatestPostIdResponse.new()
=> <MyApp::PostPb::GetLatestPostIdResponse: >

> MyApp::PostPb::GetLatestPostIdResponse.new().post_id
=> nil
```



### `case2 post_id != nil` を与える場合

以下。`Google::Protobuf::UInt64Value.new` を使わないといけない。

```rb
### 間違った使用法

> MyApp::PostPb::GetLatestPostIdResponse.new(post_id: 909)

"Google::Protobuf::TypeError: Invalid type Integer to assign to submessage field 'story_id'."
"from (pry):8:in `initialize'"


### 正しい使用法

> MyApp::PostPb::GetLatestPostIdResponse.new(Google::Protobuf::UInt64Value.new(value: 909))

> MyApp::PostPb::GetLatestPostIdResponse.new(Google::Protobuf::UInt64Value.new(value: 909)).post_id
=> <Google::Protobuf::UInt64Value: value: 909>

> MyApp::PostPb::GetLatestPostIdResponse.new(Google::Protobuf::UInt64Value.new(value: 909)).post_id
=> 909
```

## 注意点

初期化時にnilの値を詰めるかどうかで条件分岐が必要っぽい。また、上記の挙動により、grpc client側のコードで、story_idを取り出す場合には、ぼっち演算子を使うことが必要になる。

```rb
story_id = responst_object.story_id&.value
```
gnuplotでガウシアンフィット


以下、gnuplot内での記述。

# ガウシアン関数の定義

```
f(x) = a*exp(-(x-b)**2/(2*c**2))+d
```

# データの確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221968/0853ee45-33c9-0e30-9b8d-31341e15f238.png)


いまから、これのx=11付近のピークを読む。

# 初期値の代入

a=ピーク高さ(y座標)
b=ピーク位置(x座標)
c=ピーク幅
d=バックグラウンド

```
a=10000;b=10;c=1;d=0
```


### フィッティング

```
fit [10:12.5] f(x) "mt.txt" u 1:2 via a,b,c,d
```

### フィットパラメータの確認

```
print a,b,c,d
```

### グラフ描画

```
plot "mt.txt" w lp, f(x)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221968/de9d8995-a970-6837-c355-9592c0338c92.png)
Laravel Voyagerでパンくずを独自にしたい

Laravel VoyagerでBREADを使わずに普通にLaravelでControllerを作った場合、
上部のパンくずがhttp://〜とか入って不思議だったので
調べた所、単に作ったViewBladeファイルに
@section('breadcrumbs')
を追加することで対応できそうです


## Laravel VoyagerのControllerを配下に移す

config/voyager.php

```php
    'controllers' => [
        //'namespace' => 'TCG\\Voyager\\Http\\Controllers',
        'namespace' => 'App\\Http\\Controllers\\Voyager',
    ],
```

```
php artisan voyager:controllers
```


## Controller,Blade,ルーティングを設定

resources/views/hello.blade.php 

```php

@extends('voyager::master')

@section('breadcrumbs')

<ol class="breadcrumb hidden-xs">
        <li class="active"><a href="/admin"><i class="voyager-boat"></i> Dashboard</a></li>
        <li>hello world!</li>
</ol>
@stop


@section('content')

hello!!!!!

@stop
```


app/Http/Controllers/HelloController.php 

```php
<?php
namespace App\Http\Controllers;

use App\Http\Controllers\Voyager\VoyagerBaseController;
use Illuminate\Http\Request;

class HelloController extends VoyagerBaseController
{
    public function index(Request $request)
    {
        return view('hello');
    }
}
```


routes/web.php 

```php
Route::get('/admin/hello', [App\Http\Controllers\HelloController::class, 'index'])->middleware('admin.user');
```


## 実行例
![スクリーンショット 2021-08-17 14.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19107/9d06ee89-ec57-9752-61a7-c981812a3702.png)


##ちなみに・・・

bladeでの

```php
@extends('voyager::master')
```

はVoyagerのメニューなどのフレームを利用する場合に入れておきます。


routes/web.php の

```php
->middleware('admin.user');
```
は、ログイン処理用のmiddlewareなんだそうです。
ログアウトしていた際、自動的にログイン画面にリダイレクトされるので、
入れておくのがいいでしょう。
無いとログアウト時にアクセスしたとき、ユーザ情報が取れないなど意味不明なエラーになります。

https://stackoverflow.com/questions/50831492/laravel-voyager-route-restriction
arm 64bit 環境で、arm 32bit バイナリをクロスビルドする

# はじめに
[いろんな組み込み用SBC](https://qiita.com/blue-7/items/c2467f4aab149e861d17)
を使おうとすると現在は、大部分が64ビット環境のOSとなります。
一方、RaspberryPIのOSで一番よくつかわれる環境は32ビット環境となり、RaspberryPI上の資産を別のSBCに持っていくときの障害の一つとなります。
INTEL環境の場合、gccに-m32 オプションをつけることで、64ビットOS上で32ビットのコードをコンパイルできますがARM環境の場合には、基本的にはビルド環境についてはクロスコンパイル環境として構築する必要があります。
ARMv7(32ビット)のクロス環境をARMv8(64bit)上で作る例があまりなかったので、書き留めておきます。
ARM環境上では、ARMv7 (32bit)のコードを　ARMv8(64bit)OS上で実行するには、ライブラリのインストールだけで実行が可能となりますが、コンパイラについては、基本的には別のコンパイラのインストールが必要となります。

#やったこと
ARMv8 環境上で、32bitの実行が可能なようにライブラリのインストール
32bit用のGCC,G++をインストール
32bit用のライブラリのインストール
コンパイル
<BR>
~~JETSONだと、ちゃんと調べてませんが、32ビットコードはそのまま実行できますが、~~
~~apt install xxxxx:armhf~~
~~でリポジトリがたりないんだかなんだかわかりませんが怒られます。~~
~~まあ外部ライブラリを使ってまでJetsonで32ビットコードをビルドすることは今のところ私はないので、放置ということで。。~~
JETSONだと32ビットの実行環境ははいってますが、add architecture されていないようなので、Nvidia関連がarmhfをサポートしていないと怒られますが以下で同様に動くはずです。

sudo dpkg --add-architecture armhf
sudo apt update

#32bit実行環境の構築
アーキテクチャ追加
sudo dpkg --add-architecture armhf
追加後のアップデート
sudo apt update
32ビット環境用の標準ライブラリのいンストール
sudo apt install libc6:armhf libstdc++6:armhf
リンク追加
cd /lib
sudo ln -s arm-linux-gnueabihf/ld-2.23.so ld-linux.so.3

#32ビットクロスコンパイラのインストール
GCC
sudo apt install gcc-arm-none-eabi
G++
~~sudo apt install g++-arm-none-eabi~~
sudo apt install g++-arm-linux-gnueabihf

#32ビット外部ライブラリのインストール
標準ライブラリのみの場合には必要ありませんが、ビルドにあたって、外部のライブラリが必要な場合には、
:armhf
を末尾に追加して、ライブラリをインストールしておく必要があります。
たとえば、libasound2だと
開発時のライブラリ
sudo apt install libasound2-dev:armhf
実行時のみ
sudo apt install libasound2:armhf
が必要となります。

#コンパイル
MAKE内の
GCCのかわりに
arm-linux-gnueabihf-gcc
G++のかわりに
arm-linux-gnueabihf-g++
を実行します。

#Executableの実行
シームレスに実行するだけです。
WSL2 (on Windows 11) を使って Linux GUI アプリを実行してみる

Windows 11 (Insider Preview 版) で Linux GUI アプリを実行してみました。
備忘録として手順を記載しておきます。

https://docs.microsoft.com/ja-jp/windows/wsl/tutorials/gui-apps

こちらの記事を基に実行しました。そのため詳しいコマンドなどはこちらを参考にしてください。

#前提条件
公式ドキュメントの前提条件には Windows 10 の Insider Preview が必要と記載があります。
ただし、自己責任で試したところ **Insider Preview 版の Windows 11** でも実行できました。

#実行環境

|  |  |
|:-:|:-:|
|  プロセッサ | Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz   1.50 GHz  |
| 実装 RAM  |  16.0 GB (15.6 GB 使用可能) |
| エディション  | Windows 11 Enterprise  |
|   バージョン| 21H2  |

#手順
1. Microsoft の公式ドキュメントに記載のあるリンクから適切なドライバーをインストールします。
今回は Intel の CPU なので、Intel 用のドライバーをインストールしました。
ドライバーのインストール時に ReadMe.txt を見ていただくと対応した OS と Platform の情報が記載されています。
これらに適した環境ではない場合はドライバーのインストールに失敗するようです。

2. WSL のインストール（まだインストールしていなかった場合）
今回は事前にインストール済みだったので、この手順はスキップしました。

3. WSL のアップデート（事前にインストール済みの場合）
今回は 2. の代わりにこちらの手順を実行しました。

4. Windows Terminal で Ubuntu のターミナルを実行し、アップデート

5. 各種実行したいアプリのインストール及び実行
今回は Gedit, gimp, Google Chrome for Linux を試しました

実行時の画像です。タスクバーのアイコンに Linux のペンギン（タックスというらしい）が小さく表示されてます。

![スクリーンショット 2021-08-17 140058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539633/1f15c4e2-4b95-fb61-f967-9fb77740869e.png)

#まとめ
お試しの際は自己責任で。
Pepper SDK入門(34) GoToでターゲットと巡り合ってもらう

#はじめに
GoToでは、Pepeprをどこかに移動させることができます。トラジェクトリファイルを利用したAnimateとは異なり、障害物を回避して目標地点に到達するように柔軟に動いてくれるのが特徴です。
![k0120_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/1c9dd00d-5ac1-40e4-7441-9eb44c084dcc.png)
このようなアクロバティック回避は不可なので、乗り越えられる塩梅の試練を課してあげてください。

```java
// ターゲットフレームを取得
Frame targetFrame = ...;

// アクションをビルド
GoTo goTo = GoToBuilder.with(qiContext)
                       .withFrame(targetFrame)
                       .build();

// 同期でアクションを実行
goTo.run();
```

#GoToの微に入り細を穿つ
GoToアクションの実行には三段階の準備が必要です。その内訳を順番に紹介します👐
1.まずはFrameを取得するか算出するかして、目標位置(ターゲットフレーム)を取得する。Frameについては[こちら](https://qiita.com/kskrin/items/30de2ddc630f21f120b3)を参考にしてください。

2.次にGoToアクションをビルドする

3.GoToアクションを実行する。これでPepperで道案内などができます🍉🙈

GoToアクションには次の三つのパラメーターがあります。

* Path Planning Policy
* Final Orientation Policy
* Maximum Navigating Speed

以下でこの三つの詳しい機能を説明します↓

__Path Planning Policy__
<font color="HotPink">GET_AROUND_OBSTACLES</font>(デフォルト):　移動経路上に障害物があった場合は迂回して目的地に向かう。
<font color="HotPink">STRAIGHT_LINES_ONLY</font>:　移動経路上に障害物があっても迂回せずに停止する。
__Final Orientation Policy__
<font color="HotPink">FREE_ORIENTATION</font>(デフォルト):　ターゲットフレームに到達時に向きを調整しない(最終的な進行方向を向いたままとなる)。
<font color="HotPink">ALIGN_X</font>:　ターゲットフレームに到達時に、Pepperの向きをターゲットフレームのX軸と同じになるように調整する
__Maximum Navigating Speed__
Pepperの移動速度を秒速何ｍにするか、指定することが可能。

下記のコードは使用例です。
ここではターゲットのX軸に沿って、毎秒0.55mで直進するように書かれています。

```java
// ターゲットフレームを取得
Frame targetFrame = ...;

// アクションをビルド
GoTo goTo = GoToBuilder.with(qiContext)
                       .withFrame(targetFrame)
                       .withPathPlanningPolicy(PathPlanningPolicy.STRAIGHT_LINES_ONLY)
                       .withFinalOrientationPolicy(OrientationPolicy.ALIGN_X)
                       .withMaxSpeed(0.55f)
                       .build();

// アクションを同期で実行
goTo.run();
```

#ターゲットと待ち合わせ
以下のコードはPepperを前に1m前進させるためのサンプルコードです↓

```java
//ロボットフレームを取得
Actuation actuation = qiContext.getActuation();
Frame robotFrame = actuation.robotFrame();

//移動内容を定義
Transform transform = TransformBuilder.create().fromXTranslation(1);


//空のフリーフレームの作成
Mapping mapping = qiContext.getMapping();
FreeFrame targetFrame = mapping.makeFreeFrame();

//空のフリーフレームにフレーム情報を設定する
//現在のPepperの位置(robotFrame)から1メートル前の位置(transform)にフレームを更新
targetFrame.update(robotFrame, transform, 0L);

GoTo goTo = GoToBuilder.with(qiContext)
                       .withFrame(targetFrame.frame())
                       .build();

goTo.run();

```

#障害物回避チャレンジ
Pepperも歩けば諸々のものに当たりそうになりますが、Pepperはその障害物を回避して目標地点まで到達しようとします。主人公気質ですね👑
障害物の回避は目的地まで１.２ｍ以上あり、且つ障害物と０.５ｍ以上離れて移動できる場合にのみ機能します。

#エラー色々
GoToの実行を妨げる要因には様々なものがあります🕳🕳🕳🕳🕳🕳🕳🕳

* センサーを妨げる太陽のような明るさ☀️
* モノリスのように回避できない障害物⬛️
* スレイプニルやサンタクロースといった生物のような動く障害物
* 地面の凹凸

こういった要因によるエラーが発生した場合に備えて、Pepperがタスクを放棄できるように定義しておく必要があります。

#あとがき
今回も[PepperSDKforAndroid](https://android.aldebaran.com/sdk/doc/pepper-sdk/ch4_api/movement/reference/goto.html)を参考に書かせていただきました。
さらに詳しい情報は、[GoToのAPIドキュメント](https://android.aldebaran.com/sdk/doc/javadoc/qisdk/com.aldebaran.qi.sdk.object.actuation/-go-to/index.html)を参照してください。

次回のPepperSDK入門はLocalizeです。ノーマライズは関係ありません🎧それでは〜
EC2インスタンスに一番簡単にログインする方法 

EC2インスタンスにログインする方法はいくつかありますが、その中でも一番簡単な`Instance Connect`について説明します。

ブラウザの操作だけでログインできるので非常に簡単です。ssh keyなどの設定は不要です。（インスタンス作成時にキーペアの登録は必要）
とりあえずすぐログインしたい時には重宝します。

# 1. EC2インスタンス一覧画面を開く

いろいろ方法はあると思いますが、もしわからない場合は、以下のキャプチャを参考にしてください。
サービス検索窓に`EC2 インスタンス`と入力すると出てくる`インスタンス`というリンクをクリックすればOKです。

![スクリーンショット 2021-08-14 12.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884434/1c63313e-7d2a-0225-d5f9-6dbe64304011.png)

# 2. ログインしたいEC2インスタンスIDをクリックする

![スクリーンショット 2021-08-14 13.02.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884434/8849e5ea-38fc-473c-33d8-354312511aee.png)


# 3. 「接続」をクリック

![スクリーンショット 2021-08-14 13.03.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884434/56c2f823-b88d-db24-1eda-23adf76b7c99.png)

# 4. 再度「接続（オレンジ色）」をクリック

`EC2 Instance Connect`が選択されていることを確認し、接続（オレンジ色）をクリックします。
接続ボタンが押せない場合は、インスタンス作成時にキーペアの登録がされていないかもしれません。

![スクリーンショット 2021-08-14 13.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884434/7e1dec2e-95a2-c8a0-508b-9efe60dd3c6b.png)

無事にログインできました！簡単ですね。

![スクリーンショット 2021-08-14 13.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1884434/d2f300df-3f3c-151e-84b4-73d227e16a00.png)
【Swift】KingfisherでUIImageのみを習得する

# どういうことか

基本的な使用例はこんな感じ。

```swift
import Kingfisher

let url = URL(string: "https://example.com/image.png")
imageView.kf.setImage(with: url)
```

UIKitにポン付けするカタチではなく、画像を取得してUIImageの変数に入れたい。

## KingfisherManagerを使う

```swift
var examImage: UIImage?

let url = URL(string: "https://example.com/image.png")

KingfisherManager.shared.downloader.downloadImage(with: url) { result in
    switch result {
    case .success(let value):
        self.examImage = value.image
    case .failure(let error):
        print(error)
    }
}

// 取得した画像をUIImageViewにセットする
imageView.image = examImage
```

おわり(´・ω・｀)
OSI参照モデル

第1層　物理層
データを数字の「0」「1」であるビット列に変換
ビット列を電気信号に変換
LANケーブル、Wi−Fi電波、ハブ、リピータ

第2層　データリンク層
届け先であるIPアドレスに向かってそのネットワーク経由で届けるかを決める
スイッチ、

第3層　ネットワーク層
複数のネットワークにまたがって配置されているコンピュータ同士の伝送を可能にする
ルータ

第4層　トランスポート層
データ伝送の信頼性を提供
ファイアウォール

第5層　セッション層
セッションを管理して、情報をやり取りする上で、必要となる状態や方法の同期をとる

第6層　プレゼンテーション層
コンピュータ同士のデータ形式の違いを補正して、データを正しく表現すること

第7層　アプリケーション層
ユーザーが利用するアプリケーションに対して、ネットワークがサービスを提供する
deviseのメモ

##サインアップ、サインイン後のリダイレクト

```application_controller.rb
#サインアップ
def after_sign_up_path_for(resource)
    リダイレクト先のパス名
end

#サインイン
def after_sign_in_path_for(resource)
    リダイレクト先のパス名
end
```

##ログアウト

```erb:ビュー
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
```

##ログイン済ユーザーのみにアクセスを許可する
ログインが必要なコントローラに

```rb
before_action :authenticate_user! 
```

##ログインしているかの判定
ログインしていれば、True
していなければ、Falseを返す

```rb
user_signed_in?
```