OmniAICreator/Qiita-1.07M huggingface dataset:
Netlify CMS②管理画面を設定

## ログイン画面を作成する
[サイト名/admin]で管理画面にログインできるようにする
↓目指す画面
![スクリーンショット 2022-06-21 13.13.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717593/436dca0e-165e-8b39-1d5c-aa34a57830db.png)

### ①adminフォルダの作成
adminファイルの中に、index.htmlとconfig.ymlを作成する
```
$mkdir admin
$cd admin
$admin touch index.html
$admin touch config.yml
```
#### index.htmlの中に追記
```
<!-- admin/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Content Manager</title>
    <!-- Include the identity widget -->
    <script src="https://identity.netlify.com/v1/netlify-identity-widget.js" type="text/javascript"></script>
  </head>
  <body>
    <!-- Include the script that builds the page and powers Netlify CMS -->
    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
  </body>
</html>
```
#### config.ymlの中に追記
```
# config.yml

backend:
  name: git-gateway
  branch: main # Branch to update (optional; defaults to master)
media_folder: 'assets/uploads'
collections:
  - name: 'blog'
    label: 'Blog'
    folder: '_posts/'
    fields:
      - { name: Title }
```
### ②header.htmlとfooter.htmlに追記
NetlifyIDウィジェットを追加する
#### header.htmlに記述する
```
<head>
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
</head>
```
#### footer.htmlに記述する
(body内なので場所は任意で大丈夫です)
```
<script>
  if (window.netlifyIdentity) {
    window.netlifyIdentity.on("init", user => {
      if (!user) {
        window.netlifyIdentity.on("login", () => {
          document.location.href = "/admin/";
        });
      }
    });
  }
</script>
```
## 参考
Netlify CMS ジキル ： <a href="https://www.netlifycms.org/docs/jekyll/">https://www.netlifycms.org/docs/jekyll/</a>
Netlify CMS widget ： <a href="https://www.netlifycms.org/docs/add-to-your-site/#add-the-netlify-identity-widget">https://www.netlifycms.org/docs/add-to-your-site/#add-the-netlify-identity-widget</a>
Netlify CMS①githubを連携

### Netlifyでアカウントを作成
<a href="https://www.netlify.com/">Netlify</a>でLoginする

### GitHubを連携する
※予め、GitHubでリモートリポジトリを作成しておく
#### ①GitHubをクリック
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717593/e1db394a-b7c4-40bf-7055-87b845f011d5.png)
#### ②GitHubの画面からリポジトリを選択
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717593/eb98e519-d2b1-6c55-fbaa-ddfdf2fb2f12.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717593/7eb9568f-9bef-7dc4-58c9-b42e7ae44772.png)
#### ③Netlify画面側からも確認して終了
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/717593/17210577-c288-2f8e-53f2-7020d3f704ea.png)

## 参考サイト
NetlifyとGithubを連携させ、サイトのアップロード作業を自動化する方法 : <a href="https://rightcode.co.jp/blog/information-technology/netlify-github-up">https://rightcode.co.jp/blog/information-technology/netlify-github-up</a>
LaravelのMigrationで外部キーを使用したら、エラー発生

Laravelのmigrationをしようとした際、
![スクリーンショット 2022-06-21 12.16.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714247/3b636871-dc53-ecf2-8e47-8d524384ca30.png)

```
SQLSTATE[42000]: Syntax error or access violation: 1702 Key column 'categoryId' doesn't exist in table
```
というエラーにハマってました。

## 解決方法
unsignedBigIntegerを外部キー参照している前の行に記入！
```php:unsignedBigInteger.php
$table->unsignedBigInteger('categoryId'); //ここ
$table->foreign('categoryId')->references('categoryId')->on('category')->onUpdate('RESTRICT')->onDelete('RESTRICT');
```

https://qiita.com/howaito01/items/d7bc0f1e5e4c81044599
opencv インストール(Mac用)

# OpenCVとは
- OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. OpenCV was built to provide a common infrastructure for computer vision applications and to accelerate the use of machine perception in the commercial products. Being a BSD-licensed product, OpenCV makes it easy for businesses to utilize and modify the code.

 https://opencv.org/about/

# OpenCVのインストール
1. Homebrewのインストール
- MacOS上でソフトウェアの導入を単純化するパッケージ管理システムの一つ
- インストールする際は、下記コマンドを実行
```
$ ruby -e "$(curl -fsS http://gist.github.com/raw/323731/install_homebrew.rb)” 
```
- 詳しくは以下のサイトを参照

https://qiita.com/omega999/items/6f65217b81ad3fffe7e6

2. OpenCVのインストール(Mac)
- Homebrewが入ったら、以下のコマンドを実行する
```
brew install opencv
```
- その後、python用のopencvをインストールするために以下を実行
```
pip3 install opencv-python
```
**pip3としているのは、python2とpython3の両方があるため、2と3の違いを明記するため。少なくとも私のMacにはデフォでpython2が入っているので、python3をインストールしても、デフォのpipコマンドではpython2の方が指定されている。zshのAliasに加筆すれば解決するらしいが、少々面倒なので、pip3を使っている。詳しくは以下のサイトを参照**

https://ottan.xyz/posts/2020/04/macos-catalina-python3-default/

- OpenCVが入ったかの確認
```
import cv2
```
上記のコマンドを実行してエラーが出なければ問題ない。

Windowsにおけるインストール法は今後追記していく予定
FlutterとAndroidStudioを使ってRakutenMiniでアプリを動かす

# 背景
- 迷子猫捜索アプリを作りたい
- 入力フォームとデータ取得APIを用意したい
  → [GoogleFormとGoogleSpreadSheetとGoogleAppsScriptで、フォームとDBとデータ取得APIを作成する](https://qiita.com/itortie/items/a4712fcf330a486a7092)
- 今ある知識（Web系）でアプリを作りたい
  - [ハイブリッドアプリを作れるMonacaを試してみる](https://qiita.com/itortie/items/bcb2ddedc0cf8c8afda8)
  - Flutterを試してみる　←　ここ

Monacaで開発を進めるには有料プランが必要そうだったので、無料で作れる方法を探してFlutter&AndroidStudioを試す

# Flutter Install

公式ドキュメントを参考にインストール
https://docs.flutter.dev/get-started/install/windows

FlutterSDKを適当なフォルダにダウンロードして解凍
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/53d98df7-01d8-16ea-4ca4-0b173347c702.png)

解凍したフォルダへのPATHを追加
windows10の場合、スタート＞システム＞詳細情報＞システムの詳細設定＞環境変数　で設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/4ea8b03d-a5f6-bb49-047f-5c29ebdb54f4.png)

コマンドプロンプトでflutter doctorを実行してエラーがないか確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/8c436f07-ec1a-52ba-a3c4-43d839977d4d.png)

以下、エラーが出た場合の対処
## Android Studio
Android Studioがない場合、以下を参考にインストール
https://developer.android.com/studio/install?hl=ja

##　Android toolchain
Android Stduioを起動
File＞Settings＞Plugins　でFlutterをインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/2e8ec478-c6d6-9c46-b6e1-6bd433f231e1.png)

# 仮想デバイス
開発用に仮想デバイスを設定
手持ちの端末がRakutenMiniなので、RakutenMiniを作る

AndroidStudio＞tools＞DeviceManager＞CreateDevice
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/ef5e6d3d-fbe7-9bf9-35de-b9a52c4f1f9e.png)

New Hardware ProfileでRakutenMini用のプロファイルを作成
寸法やRAMなどは公式HPに掲載されたスペックから引用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/ed19c60d-bfd6-8d79-0b93-fdbe47efad31.png)

Launch
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/dd7b42e2-a766-659c-a601-63cacd132e04.png)

## エラーが出た場合
### Android SDK
必要であればAndroidSDKをインストール
Tools＞SDK Manager＞Android SDK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/2f7e1d4b-9f89-95ae-8c15-81e1653ea5ab.png)

### CPUがエミュレータに対応していない
VMを使った仮想環境だとcpuがエミュレータに対応していないケースがある
→　その場合、あきらめて別の環境を使う

### エミュレータが真っ黒

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/e2db18ba-c038-4a0b-f8e3-6d3a9f1f0c47.png)

WipeDataで初期化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/20065141-110e-8338-999c-dd88b2ae201c.png)

# Flutter

AndroidStudioで新しいプロジェクトを立ち上げ、Dartを使ったサンプルアプリを展開

デバイスを指定して実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/03bddce9-37f7-7f32-1c6d-fbdaa98d109c.png)

Flutterのサンプルアプリが起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/02d3d705-d386-fa12-831a-0ee1c78db6ef.png)

＋マークをクリックすると数字が増加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628523/3a30dee7-0eb6-6f5b-5fb4-55da0be04c96.png)


# まとめ
Flutter、AndroidStudio、RakutenMiniの開発環境が整った
次回はDartを使いながら、GASで作ったAPIと連携させる
また、Glideを使ったアプリ開発もGASと相性が良いかもしれないので時間があれば試す
microk8s：Dashboard利用に必要なトークンを取得できない問題への対応

# はじめに

microk8sでDashboardを利用するために、以下の手順でトークンを取得しようとすると、トークンが取得できない問題が発生しました。

```
token=$(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1)
microk8s kubectl -n kube-system describe secret $token
```

Kubernetes 1.24 より、サービスアカウント用のデフォルトトークンが生成されなくなったため、上記の手順ではトークンが取得できないとのこと。

# 対応方法

以下のコマンドを実行することで、トークンが生成されます。

```
microk8s kubectl create token default
```


# 参考
https://github.com/canonical/microk8s/issues/3254

https://unix.stackexchange.com/questions/705289/no-token-for-microk8s-dashboard
Google driveにあるソースコードがQuicklookで表示できない

# MacのQuicklook
Google driveに保存したJuliaとかPythonのソースコードがM1 Macbook AirでQuicklookで表示できなくて困った話です。

Quicklookでみると真っ白。Google driveだとダウンロードしてあるファイルでないとQuicklookできませんが，ダウンロード自体はしてあります。ファイルを開けば見れる状態です。
![Monosnap 2022-06-21 12-24-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/364cd9f3-0fcd-a085-f8c6-6bdacee9213b.png)

こうなってほしい。
![Monosnap 2022-06-21 12-24-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/6391df05-a3d0-c567-acf9-5631d9e8a852.png)

隣りにあるIntel Mac miniでは表示できているのになんでだと1時間悩みました。M1だからとか考えましたが，原因はセキュリティでした。

# 解決策
システム環境設定のセキュリティ＆プライバシーのFiles and FoldersにあるSyntax Highlightの設定で，Google driveをチェックします。下の画像みたいになってれば大丈夫です。

![Security & Privacy 2022-06-21 12-25-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/ff0d51b6-4b19-e2fb-a35a-dc679d67ccf7.png)

確認したら，この状態でした。なぜ，Google driveだけ外されていたのか。。。。
個別にこれはハイライトさせるとかしないとか設定させなくても良くないかね。。。
![Security & Privacy 2022-06-21 12-25-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43609/36223cb3-63b1-379f-c129-54713562bd80.png)
FreeRadius で使用する証明書についてのメモ

FreeRadius には、EAP などで使用する SSL/TLS 証明書の簡単に作成できるように、専用の証明書作成テンプレが用意されています。例えば debian の freeradius の場合、/etc/freeradius/3.0/certs がそうです。

このディレクトリにある *.cnf ファイルを編集し、make を実行すると自己証明書一式と、pkcs12 形式のファイルなどが生成されます。

ca.cnf ・・・CA 証明書用の設定ファイル
server.cnf ・・・サーバ証明書用の設定ファイル
client.cnf ・・・クライアント証明書の設定ファイル

ここでうっかり見落としがちなのが、xpextensions というファイルです。Makefile を見ると分かりますが、サーバ証明書やクライアント証明書を作成する際に、拡張ファイルとして指定されていて、設定が必要なファイルであることが分かります。

このファイルでは、xpclient_ext、xpserver_ext セクションの項目が定義されています。

#### xpclient_ext セクション

クライアント証明書用のセクションです。

extendedKeyUsage = 1.3.6.1.5.5.7.3.2

この 「1.3.6.1.5.5.7.3.2」という OID は「clientAuth」として定義されており、この証明書がクライアント証明書であることを拡張設定に組み込みます。

crlDistributionPoints = URI:http://172.30.228.127/ca.crl

crlDistributionPoints は、リボークリストの URI を証明書に埋め込むことができます。

#### xpserver_ext セクション

サーバ証明書のセクションです。

extendedKeyUsage = 1.3.6.1.5.5.7.3.1

この 「1.3.6.1.5.5.7.3.1」という OID は「serverAuth」として定義されており、この証明書がサーバ証明書であることを拡張設定に組み込みます。

crlDistributionPoints = URI:http://172.30.228.127/ca.crl

crlDistributionPoints は、リボークリストの URI を証明書に埋め込むことができます。

certificatePolicies = 1.3.6.1.4.1.40808.1.3.2

certificatePolicies で証明書のポリシーを設定出来ます。

引数は２種類あり、「Trust Override Disabled - STRICT」、「Trust Override Disabled - TOFU」が指定できます。

「Trust Override Disabled --STRICT」を指定すると、クライアントデバイスで、システムが用意する証明書以外は受け付けなくなります。

「Trust Override Disabled - TOFU」を指定すると、クライアントデバイスが接続しようとしたときに、初回、ユーザ側に FreeRadius で作成した証明書をインストールするかどうかの確認をしてくれるようになります。こちらがデフォルトになっています。
[Java] 基礎的なカプセル化について

### はじめに
Javaの学習のまとめです
以前にもざっくりとしたまとめを書きましたが、今回はカプセル化に絞って投稿しています。

### かなりオススメします

https://www.youtube.com/channel/UC57H40XcMcL4Lbp_Uq2MVaQ

とてもわかりやすいし、説明がすんなり入ってきます。
なぜ使うのか・いつ使うのかも含めて丁寧に説明してくれているのでJava学習をはじめたばかりの方はぜひ！
わかりやすいように構成が考えられているようで、その時その時に必要な情報を出してくれるのでパンクしないで済みます。
また、オブジェクト指向についても解説してくれていますので曖昧な方もぜひ！

### アクセス修飾子
クラス・メンバ変数・メソッドの**公開範囲**を指定できる
| 修飾子 | 同クラス | 同パッケージ | サブクラス | その他 |
|:-:|:-:|:-:|:-:|:-:|
| public  | ◯  | ◯  | ◯  | ◯  |
| protected  | ◯  | ◯  | ◯  |   |
| (無し)  |  ◯ | ◯  |   |   |
| private  | ◯  |   |   |   |

### カプセル化
メンバ変数は隠蔽`private`
クラスとメソッドは公開`public`にする設計方針のこと

privateで宣言した変数を呼び出したい時はgetterメソッド`get変数名();`かsetterメソッド`set変数名();`で取得する
直接`stu.変数名`だとコンパイルエラーになる

##### メリット
- 代入前処理
正しい値かどうかを**代入前**にチェックできる

例）メンバ変数に値を設定するとき
```java:Student.java
class Student {
  private int score;
  public void setScore(int s) {
    score = s;
  }
}
```
というクラスがあったとすると`score`に入る整数は0点~100点
`setScoreメソッド`の頭にif文で`if (0 <= s && s <= 100)`と処理をしておけば有効な数字以外は自動で弾かれ、代入しなくて済む
逆にscoreに直接代入できてしまうとこれは出来ずに500点でも代入されてしまう
```java:実行ファイル
  　　　　　　︙
  // 有効な数字は代入される
  stu.setScore(80);
  // 無効な数字は代入されないで済む（setScoreメソッドの処理を変更している前提）
  stu.setScore(500);
  // 有効・無効関係なく代入される
  stu.score = 500;
```
- プログラムの修正範囲が狭まる
例）上の`score`を`mathScore`と`engScore`に変更したいというとき
`private`指定していればStudentクラスにしかそのメンバ変数はいないはずなので修正箇所はそのクラス内だけで済む

### 最後に
閲覧いただきありがとうございました！
BigQueryの確定的暗号化SQL関数が便利

# BigQueryの新機能

確定的暗号化SQL関数(Deterministic encryption SQL functions) という機能が登場しました。

https://cloud.google.com/bigquery/docs/release-notes#June_15_2022

https://cloud.google.com/bigquery/docs/reference/standard-sql/aead_encryption_functions?hl=en#deterministic_encrypt

# できること
特定の平文とキーに対して常に同じ暗号文を生成できます。
そのため、平文でGROUP BYやJOINに使っていたカラムについて、暗号化しても同じように利用できます。

https://cloud.google.com/bigquery/docs/column-key-encrypt?hl=en#use-case_example

※AEAD 暗号化関数は同じ平文とキーでも暗号化すると別の暗号文が生成されます。

# やってみた
今回追加された`DETERMINISTIC_ENCRYPT`と以前からあった`AEAD.ENCRYPT`を比べてみます。


```sql:sample.sql
DECLARE KEYSET_DETERMINISTIC BYTES;
DECLARE KEYSET_NON_DETERMINISTIC BYTES;
SET KEYSET_DETERMINISTIC = (SELECT KEYS.NEW_KEYSET('DETERMINISTIC_AEAD_AES_SIV_CMAC_256'));
SET KEYSET_NON_DETERMINISTIC = (SELECT KEYS.NEW_KEYSET('AEAD_AES_GCM_256'));

WITH data AS (
  SELECT 'test' AS col
  UNION ALL
  SELECT 'test' AS col
  UNION ALL
  SELECT 'test2' AS col
  UNION ALL
  SELECT 'test2' AS col
)
SELECT
  DETERMINISTIC_ENCRYPT(
    KEYSET_DETERMINISTIC,
    col,
    'additional_data'
  ) AS Deterministic,
  AEAD.ENCRYPT(
    KEYSET_NON_DETERMINISTIC,
    col,
    'additional_data'
  ) AS NonDeterministic
FROM data
```

```sh:Cloud Shell
$ bq query --nouse_legacy_sql < sample.sql
Waiting on bqjob_r2ed8bea8d2387ac5_000001818439fff8_1 ... (1s) Current status: DONE   
WITH data AS (
  SELECT 'test' AS col
  UNION ALL
  SELECT 'test' AS col
  UNION ALL
  SELECT 'test2' AS col
  UNION ALL
  SELECT 'test2' AS col
)
SELECT
  DETERMINISTIC_ENCRYPT(
    KEYSET_DETERMINISTIC,
    col,
    'additional_data'
  ) AS Deterministic,
  AEAD.ENCRYPT(
    KEYSET_NON_DETERMINISTIC,
    col,
    'additional_data'
  ) AS NonDeterministic
FROM data; -- at [6:1]
+--------------------------------------+------------------------------------------------------+
|            Deterministic             |                   NonDeterministic                   |
+--------------------------------------+------------------------------------------------------+
| AReUWLWZbNBW+aRx5XaJhA8PDyH9Lx9PcA== | AdydJB4/zP0vV7tpPOxWmTYXLkVMD6tZaqbDoDHPWhyUfHLLMw== |
| AReUWLWZbNBW+aRx5XaJhA8PDyH9Lx9PcA== | AdydJB4yPyg+c+cqj0Cnj2glVFS00Pa0Qrgm0iyZLZPE8PUZcA== |
| AReUWLXQHtnTrZd+njoUNKcSY20q5TGVPDI= | AdydJB42M2DrYU8vVVUHDJueg6UHH683dvvdrhdxK+O0GZhsPHU= |
| AReUWLXQHtnTrZd+njoUNKcSY20q5TGVPDI= | AdydJB7ouQfwv2eCvD4eRSTFFQ+esCo5AZKucyYe6Som5e5BdEs= |
+--------------------------------------+------------------------------------------------------+
```

平文は2種類を2行ずつ投入しています。
Deterministicは2行ずつ結果が一致していますが、
NonDeterministicは全て結果が一致していません。
用途により使い分けられるので便利です。
【Swift】TextFieldに入力した文字をUserdefaultsに保存してみる

<h2>環境

【Xcode】13.4.1
【Swift】5
【iOS】15.5
【macOS Monterey】12.4

<h2>はじめに

入力したデータを<b>永続化</b>する、といったことをする機会がありました。
"永続化"というのは、データをそのまま保持させると言ったニュアンスです。
アプリを落としても、入力したデータを消したくない時に使用することが多いと思います。

Swiftでは何個か永続化の方法があるそうですが、今回は一番簡単な<b>"Userdefaults"</b>を備忘録的にまとめたいと思います。
（気分が乗ればいつかCoreDataとかも書くかも）
ではいってみよー！

<h2>Userdefaultsとは？

UserDefaultsは、<b>"アプリ内"にデータを保存する仕組み</b>です。
アプリの設定やユーザー設定などの軽量データを扱う操作を想定した仕組みで、大量のデータを扱うには不向きです。
アプリを終了してもデータは消えませんが、アプリを削除するとデータも消えてしまいますので、重要なデータをUserDefaultsのみに持たせるのは控えたほうがいいでしょう。

要はちょっとのデータを保存させときたいと気に使います。
([データ容量がどのくらいかはこれ読んで]( https://ja.stackoverflow.com/questions/82821/userdefaults-%E3%81%AB%E6%A0%BC%E7%B4%8D%E3%81%A7%E3%81%8D%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%AE%B9%E9%87%8F%E3%81%AE%E4%B8%8A%E9%99%90%E3%81%AF ))

<h2>実際に使ってみる

さぁ、実際に使ってみましょう。
今回は認証機能がないログイン画面を想定してTextFieldに入力された文字をButtonを押すことでUserdefaultsに保存されるようにします。

<b>言い忘れましたが、Userdefaultsの基本的な使い方は以下のような感じ。</b>
・UserDefaultsオブジェクト（userDefaults.standard）のインスタンスメソッドで操作
・データはキーと値のペアで保存
・キーは常に文字列で、保存できる値は次のいずれかのデータ型になる
　　-Data、String、Number（Int、Float、Double）、Date、Array、Dictionary、Bool
([メソッド諸々はここを参照して](https://capibara1969.com/2531/))

↓Code（Swift）

    import UIKit

      class ViewController: UIViewController {

        @IBOutlet weak var TextField: UITextField!
    
        override func viewDidLoad() {
          super.viewDidLoad()
      }
    
        @IBAction func LogInButton(_ sender: Any) {
          //Userdefaultsへ保存
          let writtenText = TextField.text! as NSString
          let defaults = UserDefaults.standard
          defaults.set(writtenText, forKey: "id")
          view.endEditing(true)
          //コンソールに一応表示
          print("ID:\(defaults.string(forKey: "id")!)")
      }
    
        @IBAction func RemindData(_ sender: Any) {
          //UserdefaultsのデータををTextFieldに表示、確認
          let defaults = UserDefaults.standard
          let value = defaults.string(forKey: "id")
          TextField.text = value
      }
    
    }
↓イメージはこんな感じにしてます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516597/6e1de1af-c9cd-bd1b-4a1a-ae009c5f0b63.png" width=50%>

注目すべきは、LogInButtonの中の以下です。
ここで、変数defaults.setをすることで永続化されています。
この時、forkeyを忘れないようにしてください。
なぜなら、このdefaultsを呼び出すときにデータを特定するのに必要になります。

    let writtenText = TextField.text! as NSString
    let defaults = UserDefaults.standard
    defaults.set(writtenText, forKey: "id")

<h2>まとめ

いかがでしょうか、結構簡単にアプリ内にデータを保存できました。
使い方は色々ありますが、自分なりに工夫してみると面白いかもしれません。

ではでは〜
ExpoでiOSアプリをeas buildする時はbuildNumberをapp.config.tsで動的に設定すると楽だよって話

# やりたいこと
- Expoを利用したReact NativeアプリでiOSアプリをApp Store Connectにアップロードする時、アップロードのたびにapp.jsonの中のbuildNumberをインクリメントする必要がある。
- しかし、buildNumberを手動で更新するのは忘れがち。忘れたまま`eas build`すると、buildで時間がかかった後にエラーで失敗するので、非常にもどかしい。ゆで卵がうまく剥けなかった時くらいもどかしい。
- そこで、buildNumberを動的に設定することでbuildNumberを手動で更新しなく済むようにしたい。


# app.config.tsで動的にbuildNumberを設定する
やり方は簡単。
[app.jsonはapp.config.tsから動的に設定することができる。](https://docs.expo.dev/workflow/configuration/)(jsで書いてる場合はapp.config.js)

よく環境に合わせてAPIのbaseUrlをここで動的に設定したりする。


それと同じ要領で次のようにapp.config.tsに書き込むことで、buildNumberも動的に設定することができる。


```app.config.ts
import { ExpoConfig, ConfigContext } from '@expo/config';
import dayjs from "dayjs";
import ja from "dayjs/locale/ja";
dayjs.locale(ja);

export default ({ config }: ConfigContext): ExpoConfig => {
    return {
        ...config,
        ios: {
            ...config.ios,
            //　↓ここで設定している
            buildNumber: dayjs().format("YYYYMMDDHHmm") 
        },
    }
};

```

buildNumberは以前の値と同じ値は使えず、かつ以前の値よりも大きい値である必要がある。
今回は日付と時間を文字列に変換することで、それを解決している。（時間は前にしか進まないので、日付と時間を使えば必ず前回より大きな値を設定することができる）
`eas build`を連続で行うことは（おそらく）ないので、「年月日時分」まででフォーマットしている。（毎秒`eas build`したい人は秒まで含めてください笑）

副産物的として、App Store Connectでビルドを見た時に、いつビルドしたものなのかがぱっと見で判断できるというメリットもあったりする。

![スクリーンショット 2022-06-21 11.56.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268579/62893c75-92df-1e76-3b5c-40a1007fe2ed.png)



# 注意
AndroidではversionCode（＝buildNumber）の最大値が2100000000までと決まっており、`YYYYMMDDHHmm`は上限を超えてしまうため、この方法は採用できない。
https://developer.android.com/studio/publish/versioning?hl=ja

# まとめ
ExpoのiOSアプリをApp Store Connectにアップロードする時には、app.config.tsでbuildNumberを日付と時間を使って動的に設定すればインクリメントし忘れがなくて楽。

# 追記
続き？を書きました
[Expoでeas buildする時はversionCodeを動的にインクリメントしようぜ](https://qiita.com/0ba/items/76d250d402f5eb205623)


Twitterもやってるので、よければフォローお願いします。
→https://twitter.com/ObataGenta
Selenium入門

https://ai-inter1.com/python-selenium/

python環境構築はこちら

https://qiita.com/mkgchk/items/857d9b7ef16912848074

https://www.seleniumqref.com/introduction/python/Python_Sele_Ins.html

https://qiita.com/mastar_3104/items/0a1ce2bfa1d29287bc35

https://sites.google.com/chromium.org/driver/downloads

https://sites.google.com/chromium.org/driver/getting-started

https://qiita.com/apukasukabian/items/77832dd42e85ab7aa568

https://www.seleniumqref.com/api/python/element_set/Python_special_send_keys.html

レスポンス取得プラグイン

https://pypi.org/project/selenium-wire/#browser-setup

pipを最新化
```
~/temporary/venv/bin/python -m pip install --upgrade pip
```
```
pip install selenium
```
ライブラリ一覧確認

```:pip list
temporary % pip list
Package          Version
---------------- ---------
async-generator  1.10
attrs            21.4.0
certifi          2022.6.15
cffi             1.15.0
cryptography     37.0.2
h11              0.13.0
idna             3.3
outcome          1.2.0
pip              22.1.2
pycparser        2.21
pyOpenSSL        22.0.0
PySocks          1.7.1
selenium         4.2.0
setuptools       58.1.0
sniffio          1.2.0
sortedcontainers 2.4.0
trio             0.21.0
trio-websocket   0.9.2
urllib3          1.26.9
wsproto          1.1.0
```
Chromeのバージョンを確認
... 右上の３点リーダ>ヘルプ＞Chrome について
バージョン: 102.0.5005.115（Official Build） （x86_64）
ダウンロードページで確認したバージョンのものをダウンロード

If you are using Chrome version 102, please download ChromeDriver 102.0.5005.61

https://chromedriver.storage.googleapis.com/102.0.5005.61/chromedriver_mac64.zip

https://self-development.info/selenium-4で「deprecationwarning」が出る場合の対策/

mkdir web-driver

cd web-driver

mv ~/Downloads/chromedriver

mkdir source

echo "" >> test.py

open -a textedit ./test.py

Webドライバのパス指定は、ルートからの絶対パスのみ、相対ぱすは使えない
from selenium import webdriver 
driver = webdriver.Chrome("ルート〜/temporary/web-driver/chromedriver")
driver.get("https://google.co.jp")

python source/test.py

"chromedriver"は開発元を検証できないため開けません

環境設定＞プライバシーとセキュリティ＞一般　このまま許可を選択

https://kurozumi.github.io/selenium-python/locating-elements.html
自分が何を変えたのかがわかる

# 自分が何を変えたかを見る
## HEAD、ステージ、作業ツリーの差を表示する
```
git diff
git diff --staged
git diff HEAD
```
### git diff
作業ツリーとステージの差を出力する。
```
**************@mbp training % git diff
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index aa9c133..2da7628 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,7 +4,9 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="************" name="変更" comment="" />
+    <list default="true" id="************" name="変更" comment="">
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+    </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
     <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -157,6 +159,9 @@
       <workItem from="1652682099833" duration="65000" />
       <workItem from="1652936559531" duration="238000" />
       <workItem from="1653011747564" duration="76000" />
+      <workItem from="1654566045827" duration="849000" />
+      <workItem from="1654582160922" duration="634000" />
+      <workItem from="1654585766258" duration="75000" />
     </task>
     <servers />
   </component>
diff --git a/hello.txt b/hello.txt
index 10ddd6d..dd2db19 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-Hello!
+Hello!!
```
### 思ったこと
どれだけのファイルをステージングしていないかが分かる。
```+```は新たに追加されたことを表している。
## git diff --staged
ステージとHEADの差を表示する。
```
***********@mbp training % git diff --staged
***********@mbp training %
```
何もステージングされていないから差が発生しない。

### 思ったこと
コミットしていないかが分かる。

## git diff HEAD
作業ツリーとHEADの差を表示する。
```
***********:@mbp training % git diff HEAD
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index aa9c133..2da7628 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,7 +4,9 @@
     <option name="autoReloadType" value="SELECTIVE" />
   </component>
   <component name="ChangeListManager">
-    <list default="true" id="************************" name="変更" comment="" />
+    <list default="true" id="************************" name="変更" comment="">
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+    </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
     <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -157,6 +159,9 @@
       <workItem from="1652682099833" duration="65000" />
       <workItem from="1652936559531" duration="238000" />
       <workItem from="1653011747564" duration="76000" />
+      <workItem from="1654566045827" duration="849000" />
+      <workItem from="1654582160922" duration="634000" />
+      <workItem from="1654585766258" duration="75000" />
     </task>
     <servers />
   </component>
diff --git a/hello.txt b/hello.txt
index 10ddd6d..5cd4d80 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1,3 @@
 Hello!
+I am a student.
+
```
## 気づき
これらからわかったことはステージングはしているけどコミットはされていないことがわかる。
Ubuntuで日本語キーボードレイアウト変更後にはupdate-initramfsが必要

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

インストール時に日本語キーボードに設定するのをミスったので修正したけど、update-initramfs をし忘れてて、再起動すると元に戻った件です。

# 1. Ubuntuでキーボードレイアウトを直す

インストール時に日本語キーボードに設定し忘れたので直します。
コンソールから設定しています。
X-Windowでキーボードレイアウトを設定する場合は不要と思われる。

## 1-1. コンソールで使うキーボードレイアウトの設定

よくある普通に検索すると出てくる設定方法です。

```shell
sudo dpkg-reconfigure keyboard-configuration
```

`Generic 105-key PC (intl.)` > `Japanese` > `Japanese` > `The default for the keyboard layout` > `No compose key` > `Yes` と入力する。

# 2. initramfsを更新する

## 2-1. update-initramfs を実行する

再起動後にもキーボードレイアウトを有効にしたいので、initramfsを更新します。

```shell
sudo update-initramfs -u -k all
```

# 3. まとめ

`update-initramfs` 忘れがち。

参考:
https://qiita.com/vochicong/items/6452ac54bde56b0e0bb3
AndroidStudio(あるいはIntelliJ)で使い捨てのスクリプトを書き残す方法

# ScratchFiles

IntelliJ系IDE上でScratchFilesという機能を呼び出せることに気づきました。

https://twitter.com/derakudo/status/1538789035866755072?s=21&t=Mo7fCxXUEIbsoKAXbxb8Ew

## コマンド
Macなら`⇧ ⌘ N`
Windowsなら`Ctrl+Alt+Shift+Insert`

## メリット

https://www.jetbrains.com/help/idea/scratches.html?keymap=secondary_macos

以下、引用部分はGoogle翻訳

> スクラッチファイルは、構文の強調表示、コードの補完、および対応するファイルタイプの他のすべての機能をサポートする、完全に機能し、実行可能で、デバッグ可能なファイルです。

プロジェクト内に作成するほどじゃないスクリプトを試したいときに良さそう。AndroidStudioで試した感じだと、kotlinは実行可能でした。dartは試したけど実行方法がわからなかった。

> スクラッチバッファは、コーディング支援機能のない単純なテキストファイルです。

オートコンプリートなどは無いってことですね。

> スクラッチバッファは、簡単なタスクリストや自分へのメモに使用できます。また、プロジェクトディレクトリには保存されず、他のプロジェクトから開くことができます。

複数のリポジトリにまたがって操作することがあるので、リポジトリまたいで参照できるのは嬉しい気がする

## 所感

今までちょっとした動作確認は[Kotlinプレイグラウンド](https://play.kotlinlang.org/)で確認していましたが、わざわざブラウザを開くのが面倒でした。
これからはウィンドウを変えずにローカルで確認できるので、ちょっとだけ便利になった気がします。
演算子

■ 演算子
はじめに
演算子には、「算術演算子」、「代入演算子」、「比較演算子」、「論理演算子」などある。
この演算子を使い「式」を作ることが可能です。
「算術演算子」「代入演算子」 を使えば 「計算式」 になり、
「比較演算子」 を使えば 「条件式」 になり、
「論理演算子」 を使えば 「論理式」 に。


```配列の宣言
int[] arr = new int[5];

// 配列arrに値を代入
arr[0] = 3;         // 1番目（先頭）の要素に 3 を代入
arr[1] = 1;         // 2番目の要素に 1 を代入
arr[2] = 6;         // 3番目の要素に 6 を代入
arr[3] = 0;         // 4番目の要素に 0 を代入
arr[4] = 4;         // 5番目の要素に 4 を代入

// arrを簡略化
int[] arr = {3, 1, 6, 0, 4};

// 配列arrの要素数を出力
System.out.println("配列arrの要素数…" + arr.length);
要素数は、 1からカウント （1, 2, 3, 4...）
添え字（インデックス）、 0からカウント（0, 1, 2, 3...）
```

以上のことは、 配列 の基礎知識。

算術演算子
```
記号　機能

+ 　　加算
－　　減算
* 　　乗算
/ 　　除算
% 　　剰余
```
「算術演算子」を使い計算式を作ると、

式の評価は、演算子の優先順位に従いながら左から行われる。
複数の演算子が含まれる式を記述する場合、どの順番で計算が行われるのか注意すること。
「 a > 20 || b < 30 」の式の場合は以下の順序。

優先順位1「>」と「<」
優先順位2 「ll」
LINEで送るのタグの改行をする

aタグでlineで送るボタンをカスタムしたボタンで実装したい。
しかもメッセージは長めなので改行する必要性がある。
と言う時に、\nの改行コードではダメだった。

## 前段として
LINEで送るをリンクで実装する場合の事なので
```php
<a href=”http://line.me/R/msg/text/?<?php echo $hensu;?>リンク先</a>
```
のような書き方になり、$hensu部分にエンコードした文字列を入れる。
しかし改行コードが\nだと動かない。

```php:解決策
$kaigyou = utf8_encode("%0d%0a");
$hensu = "こんにちは".$kaigyou."改行します”;
```
とした場合にLINEメッセージで得られる出力は
```
こんにちは
改行します
```
と言う事になる。

改行コードを明示的にutf8でエンコードしたら解決出来たと。
Xamarin.FormsでBroadcastReceiverを使う場合は覚悟する


# はじめに

Xamarinは、C#でアプリ作りたい人は良いかもしれません。
特にXamarin.Formsを使い、Androidアプリでローカル通知も考えている人向きの記事になります。

# BroadcastReceiver

Xamarin.Formsは、`DependencyService.Get` 経由でOSネイティブの処理をDI的に呼び出すことができます。

Androidネイティブ処理と同様にプログラミングするとローカル通知などでネイティブ処理と同様に処理できるのですが、ここでは詳しいことは省略します。

```
[BroadcastReceiver(DirectBootAware = true)]
public class AlarmReceiver : BroadcastReceiver
{

    public override void OnReceive(Context context, Intent intent)
```

などとするとブロードキャストを受け取れます。

# OSネイティブからXamarin.Formsの処理も呼び出せる

さてここで、依存プロジェクトを設定するとOSネイティブから `Xamarin.Forms`側に書いた処理も呼び出せます。

ログや次の通知などの処理も共通処理として呼び出すことができます。

# アプリがメモリ上から消えていた場合の罠

大抵は
OSネイティブ -> Xamarin.Forms
側の処理を呼び出しても問題ないのですが、


長時間アプリが使われてない場合やタスクキルされた場合、
アプリがメモリ上から消えていた場合、`DependencyService.Get`　で例外が発生する可能性があります。


```
You MUST call Xamarin.Forms.Init(); prior to using it
```

`DependencyService.Get`は `Xamarin.Forms`の初期化が必要だったのです。

タスクキルされるとその初期化の状態も失います。

しかもバックグラウンドなのでアプリが落ちたという表示もありません。

`OnReceive` から `global::Xamarin.Forms.Forms.Init(this, bundle);`
を呼び出せばよいが初期化に時間がかかってバックグラウンドでの制限時間オーバーのため打ち切られてしまう可能性もある。


つまりできることは、
OSネイティブ -> Xamarin.Forms
で呼び出す処理すべてから `DependencyService.Get`　を取り除かないといけないことになります。

しかも一旦書いてしまったものから取り除くのは大変で、ライブラリの中で書かれていたりすると大変です..

もう投げ出したくなります。

# ローカル通知のテスト

`OnReceive` で次の通知を設定しようとしているなら、テストがさらに大変です。

直近のローカル通知はおそらく何も問題がないのですが、その`OnReceive`を受け取った段階では`Xamarin.Forms` が生きてない可能性があるため、
直近のローカル通知を受け取る前にタスクキルや端末再起動などを行って、メモリ上から消えている状態にして
logcatとにらめっこすることや、adbコマンドなどで通知の存在を確認することになります。

`
adb shell dumpsys alarm
`

このコマンドの存在を知らなかったらだいぶきつい。

これをちゃんと確認しないと、「テスト段階では通知来たので大丈夫と思ったのに、本番だと通知が来ない。」
という羽目になります。

# まとめ

`DependencyService.Get` くらい`Xamarin.Forms`の初期化なしで使わせてほしい。

~~そもそもXamarinを~~
ボックスの横並び

ボックスを横並び

親要素に
`display: flex;
justify-content: center;`



ボックスが多いとき
`display: flex;
  flex-wrap: wrap;
  justify-content: center;`

wrapを加えるだけでボックスのサイズを超えるときに
下に改行してくれる。
2×2のボックスを配置したいときに使う。
Oracle Analytics Cloud：1クリック統計の計算内容を計算式に変換して再利用する

# はじめに
Oracle Analytics Cloud（**OAC**）には、マウスのクリック操作で簡単に統計的計算をビジュアライゼーションに加えることができる機能があります。
この計算内容を、簡単にマイ計算で定義する計算式に変換することができます。
計算式を再利用する方法とあわせて紹介します。

# まずはワークブックとビジュアライゼーションを作成
[Oracle Analytics Cloud：前年の値を計算](https://qiita.com/tyo38/items/71de5c655ce0b17fd5a0)で紹介したサンプルをインポートしました。
「Sample Order Lines」というデータセットがインポートされるので、これを使って新規にワークブックを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/76bca2ff-2740-0aa4-3d02-4a9f872d1aa0.png)
コントロールキーを押しながら、「Product Name」「Sales」「Shipping Cost」をまとめて選択し、そのまま右のエリアにドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/8400f007-42c4-3647-7fac-25342c5f19eb.png)
自動的に散布図が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/2a38a393-f4f3-3bfa-724c-a6a7bd3ad7c9.png)

# クラスタを計算
散布図を右クリックします。
表示されるメニューの「統計の追加」から「クラスタ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/ac394e40-8469-6572-6b84-511abf0445e3.png)
5つのクラスタに分類されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/27b18fcb-ac1b-06b9-61f9-e772981d154c.png)

# マイ計算の「式」に変換
散布図の文法パネル（X軸やY軸を指定する場所のこと）の「色」に自動的に配置された「クラスタ」を右クリックし「マイ計算に追加」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/78acb307-e392-9dc5-9d53-b6d4ec768332.png)
追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/a97132dd-bf89-77fa-5e26-c5fad633c548.png)
右クリックして、計算式を確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/f0ec5ef2-97b1-d4df-d11d-24379302bfb0.png)
これが自動的に作成された式です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/20844536-5e6b-9982-6c62-61e3cf05d262.png)

# 他のビジュアライゼーションで再利用
マイ計算に自動的に作成された列と「Profit」を使用して棒グラフを作成してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/17871cfd-cbc0-ce4f-1b9d-f2b97417dd38.png)
クラスタ4はかなりマズいことになっていますね。

# おわりに
このように、OACでは統計情報をクリックするだけで簡単にビジュアライゼーションに追加できるだけでなく、計算式を永続化して他のビジュアライゼーションで再利用することができます。
統計計算の永続化は、ここで紹介したクラスタ以外に外れ値でも利用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/92d4381c-cc76-ec17-2e01-e61238beca4c.png)
Lottie-webのNuxtでの使い方

## インストール
```
$ npm i lottie-web
```

## コンポーネントに記載
※　複数ファイルが存在する場合は、その分のコンポーネントを用意しましょう！
```
<template>
  <div id="lottie" ref="lottie"></div>
</template>

<script>
import lottie from 'lottie-web';
import animationData from '@/assets/ファイル.json';

export default {
  mounted() {
    lottie.loadAnimation({
      container: this.$refs.lottie, 
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData,
    });
  },
};
</script>
```

## このコンポーネントを使いたいページ、コンポーネントで呼び出す！
```
<template>
 <div>
  <Guide01 />
  <Guide02 />
  <Guide03 />
  <Guide04 />
 </div>
</template>

<script>
import Guide01 from '~/components/lottie/guide01.vue'
import Guide02 from '~/components/lottie/guide02.vue'
import Guide03 from '~/components/lottie/guide03.vue'
import Guide04 from '~/components/lottie/guide04.vue'

export default {
  components: {
    Guide01,
    Guide02,
    Guide03,
    Guide04,
  }
}
</script>
```
6.12 (標準) 最尤推定6，推定量の評価5 クラメール・ラオ不等式1

## 方針

スコア関数，フィッシャー情報量，クラメール・ラオ不等式について．スコア関数は対数尤度関数のパラメータについての微分なので，「標本X_iの値に依存する，パラメータの関数」である．一方，フィッシャー情報量はスコア関数の二乗の期待値なので，「標本X_iの値には依存しない，パラメータの関数」である．これを理解しておくといくつかの公式を覚えやすい．

クラメール・ラオ不等式は，**不偏推定量**に対し成り立つ不等式である．不偏推定量はバイアスがゼロなので，いくつかの不偏推定量の良し悪しの評価は，その分散について行われることになる．その分散の下限を与えるのがクラメール・ラオ不等式である．

![知ったこと-70.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/28c3943e-90f0-14a9-dd17-aadd015a356a.jpeg)
![知ったこと-71.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/52499135-4fd6-1bda-0740-1d7998379479.jpeg)
![知ったこと-72.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/62958920-bdf8-22df-7d21-01c810fc3592.jpeg)

## 答案

![6. 2周目-28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/5e1f54cf-190d-9ba2-06a3-3112b611df2c.jpeg)
![6. 2周目-29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/bc444ba2-ff04-27ff-93a6-7ab4cbc5b1e9.jpeg)
![6. 2周目-30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/7cd2f6fd-6d7d-fb24-511f-642b30240062.jpeg)

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
TerraformでLambdaEdgeをCloudFrontに登録


# 概要

* TerraformでCloudFrontにLambdaEdgeの登録をしたい
* Terraform公式にあるやり方でも他記事でもうまくいかない。結構はまった。
* 他にも困っている人向けに
* Terraformバージョンアップ早いのですぐ変更される可能性あり


# 詳細

* 成功イメージ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/c12a0d4a-c866-ef6d-6b13-605c699742a1.png" width=50%>

* エラー
    *  Lambdaのarnはバージョンが必要である旨のメッセージ
    *  そんなことは公式マニュアルに書いてないはず 

```
Error: error updating CloudFront Distribution (ET80HP6KGL1W5): InvalidLambdaFunctionAssociation: The function ARN must reference a specific function version. (The ARN must end with the version number.) ARN: arn:aws:lambda:us-east-1:121212121212:function:dev-lambdaedge-cloudfront:$LATEST
```
* Terraform公式:指定の記述方法でもエラーになる（なにか不足があるのかもしれないが。。）
    * https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/e567db2f-f0bb-7208-0376-b92e1fc55583.png" width=50%>


* LambdaEdge側

```lambdaedge.tf
resource "aws_lambda_function" "dev_lambdaedge_cloudfront" {
  filename      = "dev-lambdaedge-cloudfront.zip"
  function_name = "dev-lambdaedge-cloudfront"
  role          = aws_iam_role.dev_iam_role_lambda_edge.arn
  handler       = "index.handler"
  provider      = aws.virginia
  publish       = true #PublishされたLambdaしか連携できないので注意
  source_code_hash = filebase64sha256("dev-lambdaedge-cloudfront.zip")
  runtime = "nodejs14.x"
  # 環境変数が中途半端？にあるとCloudFront側でエラー（""The function cannot have environment variables."）
  #environment {
  # variables = {
  #               project = "hoge"
  #  }
  # }
}
```

* CloudFront側

```cloudfront.tf
resource "aws_cloudfront_distribution" "dev_cloudfront_distribution_admin" {

  //オリジン設定
  origin {

  //ビヘイビア設定
  default_cache_behavior {
    :
  
    lambda_function_association {
      event_type = "origin-request"
      #lambda_arn = aws_lambda_function.dev_lambdaedge_cloudfront.arn #エラーになる
      #lambda_arn = aws_lambda_function.dev_lambdaedge_cloudfront.qualified_arn #エラーになる
      //以下のようにバージョンを明示的に記載すると成功する。数値をベタ書きでも良い。
      lambda_arn   = "${aws_lambda_function.dev_lambdaedge_cloudfront.arn}:${aws_lambda_function.dev_lambdaedge_cloudfront.version}"
      include_body = false
    }
  }
```

* 上記のような記述条件を満たし"terraform apply"すれば成功
JSでAppiumを始める【編集中】

# Introduction
## Appium
### Appiumとは?
オープンソースのテスト自動化フレームワーク。
ネイティブ、Hybrid& Mobile Web Appsに使える。


### Appiumを使うと何がいいの？

iOS, Android, Windows appsのクロスプラットフォームで使える。
appiumはベンダーが提供したフレームワークを使う。
iOS: XCUITest
Android: UIAutomator
Windows: WinAppDriver
このようなフレームワークをWebdriver APIにまとめ上げている。


## WebdriverIOとは?
JavaScriptのE2E自動化フレームワーク。

### WebdriverIOを使うと何がいいの?
いろんなブラウザーやOSで使える。

### WHy is it popular?
始めるのが簡単。
コードが簡単。

# セットアップ

### インストールするもの
- node.js

- JDK(Set JAVA_HOME path)
https://qiita.com/yurihyp/items/c16247815405e3154a65

- Android studio(Set ANDROID_HOME path)
https://qiita.com/yurihyp/items/765c3dd7eb41f89fc102

- Appium Desktop Inspector
- 

## Appium
詰まった




## WebdriverIO

## Write Tests(Android & iOS)
### 構文を理解する
### 要素の見つけ方
### エラーが出た場合の対処法

## NAtive Features
- Alert boxes
- Scrolling
Stripe Elementsで要素が表示されるまでの間ローディング画面を表示させる方法

Stripe Elementsの`PaymentElement`では、カード決済以外にもコンビニ決済やWeChatPayなど、さまざまな決済方法を自動で表示できます。

ですが、PaymentIntentの`client_secret`を要素に渡してから、フォームが完全に表示されるまでに少しタイムラグが発生することがあります。

## `loader`属性を利用して、ローディング画面を表示する

Elementsには`loader`オプションが用意されています。

この値を`auto`または`always`に設定すると、Stripeが用意したローディング画面を表示できます。

**@stripe/react-stripe-jsの場合**
```jsx
          <Elements
            options={{
              loader: 'always',
              clientSecret: 'CLIENT_SECRET',
            }}
            stripe={loadStripe(process.env.STRIPE_PUBLISHABLE_API_KEY)}
          >
            <CustomPaymentForm />
          </Elements>
```

**@stripe/stripe-jsの場合**

```js
const elements = stripe.elements({
  clientSecret: 'CLIENT_SECRET',
  loader: 'always',
});
```

## 表示されるローディング画面

ローディング画面では、カード決済の時の画面に近いスケルトンが表示されます。

![screenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/45cea928-2f62-5280-4780-011e70b9bb5d.jpeg)

## ローディング画面を自作する方法

もし独自の画面を実装したい場合は、`loader: 'never'`を設定します。
```jsx
          <Elements
            options={{
              loader: 'never',
              clientSecret: 'CLIENT_SECRET',
            }}
            stripe={loadStripe(process.env.STRIPE_PUBLISHABLE_API_KEY)}
          >
            <CustomPaymentForm />
          </Elements>
```

その後、`PaymentElement`の[`ready`イベント](https://stripe.com/docs/js/element/events/on_ready)を利用して、画面の実装を行いましょう。

```jsx

const CustomPaymentForm: FC = () => {
  const [show, isShow] = useState(false)
  return (
    <form>
      {show ? null : (<p>Loading...</p>)}
      <PaymentElement
        onReady={e=> {
          isShow(true)
        }}
      />
      <button type='submit'>Pay</button>
    </form>
  )
}
```

## 関連ドキュメント

- https://stripe.com/docs/js/element/events/on_ready
- https://stripe.com/docs/js/elements_object/create#stripe_elements-options-loader

## [PR] Stripe開発者向け情報をQiitaにて配信中！

- [Stripe Updates]：開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について週に２〜３本ペースで更新中です。

-> [Stripe Organizationsをフォローして最新情報をQiitaで受け取る](https://qiita.com/organizations/stripe)
Pandas: データフレームについて--07: パイプ

# パイプ

関数型言語では，データ処理のときに関数を入れ子にすることで中間結果（変数）を明示しないというやり方が，ある意味普通である。

## 1.　入れ子式に関数を呼ぶ場合


```python
import pandas as pd
df = pd.DataFrame({
    'a': [1, 2, 3, 4, 5],
    'b': [1.2, 3.4, 5.6, 7.8, 9.0]
})
df

def func1(df):
  return df.transform('sqrt')

def func2(df, power=2, constant=1):
  return df.transform(lambda x: x**power + constant)
```


```python
print(func2(func1(df)))
```

         a     b
    0  2.0   2.2
    1  3.0   4.4
    2  4.0   6.6
    3  5.0   8.8
    4  6.0  10.0


## 2.　パイプで順次関数を呼ぶ場合

これに対し，パイプは一つの関数の結果を次の関数の入力にするというように，あたかも「関数をパイプで繋ぐ」ように記述できるため，一部で人気（R など?）。Python でもできるが，効果の程は？

    pipe(func: 'Callable[..., T] | tuple[Callable[..., T], str]', *args, **kwargs)


```python
df.pipe(func1).pipe(func2, power=3, constant=5).pipe(print)
```

               a          b
    0   6.000000   6.314534
    1   7.828427  11.269290
    2  10.196152  18.252019
    3  13.000000  26.784214
    4  16.180340  32.000000


以下のように書いたほうがわかりやすい場合もある。


```python
(df.pipe(func1)
    .pipe(func2, power=3, constant=5)
    .pipe(print)
)
```

               a          b
    0   6.000000   6.314534
    1   7.828427  11.269290
    2  10.196152  18.252019
    3  13.000000  26.784214
    4  16.180340  32.000000


## 3.　もっと知りたい人

    help(df.pipe) # Help on method pipe in module pandas.core.generic
youtube再生リスト(独自形式)自動生成プラグインV1.0を公開しました。

# 概要
今回作成の「youtube再生リスト(独自形式)自動生成プラグインV1.0」は、複数の再生リストを自動生成するものです。
この[プラグイン](https://chrome.google.com/webstore/detail/youtube%E3%83%AA%E3%82%B9%E3%83%88%E9%80%A3%E7%B6%9A%E8%87%AA%E5%8B%95%E7%94%9F%E6%88%90%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3-10/janckccopfoagnbghegoojecglaaolmf?hl=ja "このプラグイン")をインストールし、以下のサイトで実行します。


(1)https://sample-blog.tecoyan.net/user/index.php
本日、デモ用に公開しました。
生成された再生リストはサーバーのデータベースに保存されます。
これらの再生リストは同サイトページで再生できます。
# 再生リストの生成方法
ページの画面に「リスト作成」ボタンがあります。
このボタンをクリックすると、以下のポップアップ画面が表示されます。
![youtubeポップアップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198006/0470e230-d3f9-f1e8-609c-adb7a2a1c184.png)
この画面で、複数のクェリーを入力します。個々のクェリーはカンマで区切ります。
次に、ジャンル選択でジャンルを選択しますが、今回の公開はデモ用のため、利用者の方は「デモジャンル」を選択します。
この2つのパラメータを設定後に、サーチ実行ボタンをクリックすると、別タグでyoutubeサーチページが開きます。
## youtubeサーチページの動き
youtubeサーチページでは、自動的にスクロールし、再生リストを作成します。約100件ほどの動画を再生リストに追加すると、作成を終了し、サーバーのデータベースに指定されたデモジャンルへ再生リストを保存します。
## 複数クェリーの実行
一つのクェリーサーチを完了すると、次のクェリーサーチへ移ります。youtubeタブは次のクェリーに切り替えられます。同様に、100件ほどの再生リストが作成されるとデータベースに追加されます。
すべてのクェリーのサーチが終了すると、最初のページに戻り、「完了しました。」という通知メッセージが表示されます。
## クェリーサーチ完了画面
完了すると、以下の画面に切り替わります。

![youtubeポップアップ完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198006/f02a77a7-f4ba-d1db-99ce-724720476ed8.png)

# あとがき
youtubeの動画を整理して再生リストを保存し、あとから、再生して楽しみたいと思いからこのプラグインを作成しました。
この再生リストは、独自形式のため、再生は専用のyoutubeプレーヤーが必要になります。
[専用プレーヤー](https://sample-blog.tecoyan.net/user/index.php)
［ConoHa VPS］SoftEther VPN ServerをCentOS Stream8にインストール

# 1. はじめに
前回はオンプレミスのLinuxサーバーにSoftEther VPN Serverを構築しました。
[［オンプレ］SoftEther VPN ServerをUbuntuにインストール - Qiita](https://qiita.com/yuki-masaki/items/90ed5bcac157fdef3a4f)

今回はConoHa VPSに構築します。
前回との違いは以下の通りです。
- CentOS Stream8を使用
- VPS上にDHCPサーバーを用意していないため、仮想DHCPサーバー機能を有効にしている

# 2. SoftEther VPN Serverをインストール
必要パッケージをインストールする。

```
sudo su
dnf install -y gcc make
```

作業用ディレクトリに移動する。

```
mkdir tmp
cd tmp
```

最新版をダウンロード、解凍する。
https://www.softether-download.com/ja.aspx?product=softether

```
wget https://~.tar.gz
tar -xzvf softether~.tar.gz
```

ビルドする。

```
cd vpnserver
make
```

ディレクトリを移動、パーミッションを設定する。

```
cd ..
mv vpnserver /usr/local
cd /usr/local/vpnserver
chmod 600 *
chmod 700 vpncmd vpnserver
```

サービスに登録する。

```
nano /etc/systemd/system/vpnserver.service
```

次の通り編集する。

```/etc/systemd/system/vpnserver.service
[Unit]
Description=SoftEther VPN Server
After=network.target

[Service]
Type=forking
User=root
ExecStart=/usr/local/vpnserver/vpnserver start
ExecStop=/usr/local/vpnserver/vpnserver stop
Restart=on-failure
RestartSec=3s

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

Ctrl + X　→　Y　→　Enterで保存。

```
systemctl daemon-reload
systemctl enable vpnserver
systemctl start vpnserver
```
サービスを有効化。

# 3. ファイアウォールの許可設定

```bash
nano /etc/firewalld/services/vpnserver.xml
```

```/etc/firewalld/services/vpnserver.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
    <short>VPN</short>
    <description>SoftEther VPN Server</description>
    <port protocol="tcp" port="443"/>
</service>
```
Ctrl + X　→　Y　→　Enterで保存。

```bash
firewall-cmd --add-service=vpnserver --zone=public --permanent
firewall-cmd --add-service=ipsec --zone=public --permanent
firewall-cmd --reload
reboot #最後に、サーバー再起動しておきます。
```

# 4. 管理ツールからサーバーに接続、設定
クライアントPCにSoftEther Server Manager for Windowsをインストールする。
https://www.softether-download.com/ja.aspx?product=softether

- リモートアクセスVPNサーバーを有効
- 仮想ハブを作成
- L2TPサーバー機能を有効
- 事前共有キーを設定
- VPN Azureは無効
- ユーザーを作成
- 仮想ハブと物理NIC(本記事の場合「eth0」)をローカルブリッジする
- 「SecureNATの設定」>「仮想NAT機能を使用する」のチェックを外す
- 「SecureNATを有効にする」をクリックする

以上で構築完了です。

※ローカルブリッジと仮想NATを同時に有効化するとパケットのループが発生してサーバーがハングアップする可能性があるので要注意。
[VPNFAQ005. VPN Server のプロセスの CPU 使用率が何もしていないのに異常に高くなる - SoftEther VPN プロジェクト](https://ja.softether.org/4-docs/3-kb/VPNFAQ005)

※VPN接続時、VPNサーバー自身にアクセスしたい場合は下記サイトに記載の設定が必要です。
[VPNサーバー構築(SoftEther VPN Server) - CentOSで自宅サーバー構築](https://centossrv.com/softethervpnserver.shtml)

# 5. 参考文献
[【Centos7】SoftEther Server 構築手順【L2TP/IPsec】 - Qiita](https://qiita.com/nobu-maple/items/61f51baa9965dbd6fb04#%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%AE-vpnserver-%E3%83%9D%E3%83%BC%E3%83%88%E8%A7%A3%E6%94%BE%E8%A8%AD%E5%AE%9A)
create next appでカレントディレクトリに展開する方法

# はじめに

## create next appでカレントディレクトリにファイルを展開する方法

誰かが作った空のブランチとか、すでに存在するディレクトリ内とかにソースコードを展開する時だったり、```create next app```でrootディレクトリを作成せずにファイルを展開したい場合があると思います。そういう場合に```create next app```する方法をメモします。

# どうやるか

## ```.```を使うとできる
![スクリーンショット 2022-06-18 9.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364026/ab5f55b5-8580-4bfa-98dc-6f4d731745af.png)

直接カレントディレクトリを指定、もしくはディレクトリ名指定せずに実行してプロジェクト名の入力時に```.```を指定
```
npx create-next-app .

//もしくは
npx create-next-app
✔ What is your project named? … .
``` 

# おわりに
今回は、```create-next-app```でカレントディレクトリにファイルを展開する方法を記述しました。
言語処理100本ノック解いてみた（0~3）

# お腹すいた
今日からずっと書きます。フィードバックよろしく。
言語処理100本ノック : https://nlp100.github.io/ko/ch01.html
ど偉い俺様のギット：https://dongkeuny50.github.io/
初作成：２０２２/０６/２１
## 問１
```python
print("stressed"[::-1])
```
```python
desserts
```
説明するまでもない。
## 問２
```python
"".join(["schooled"[i* 2 + 1]for i in range(4)])
```
```python
cold
```
同じく。競プロやってたらすぐです。これも一文でできなかったら今すぐ競プロやれ。

## 問３
```python
"".join(["shoe"[_] + "cold"[_] for _ in range(4) ])
```
```python
schooled
```

## 問４
```python
print([len(_)for _ in "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.".replace(".","").replace(",","").split()])
```
```python
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]
```
簡単簡単、認識違いはあったけどなおしました。
Rubyの範囲オブジェクトについてまとめてみた

# はじめに
Rubyの範囲オブジェクトについて学んだことをまとめました！

# 参考
+ プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで

# 範囲オブジェクトとは
「1から5まで」や「aからdまで」のように、「〜から〜まで」を示すオブジェクトのこと

# 範囲オブジェクトの書き方
下記のように、..もしくは...を使用して記述します。

```ruby:範囲オブジェクトの例
1..5 #1以上5以下
1...5 #1以上5未満
'a'..'d' #aからdまで
'a...'d #aからcまで
```

# 範囲オブジェクトのクラス
範囲オブジェクトはRangeクラスになります。
```ruby:範囲オブジェクトのクラス
puts (1..5).class #=>Range
```

# 範囲オブジェクトの使用機会
「〜から〜まで」が伴う処理に使うと便利です！
例えば、
1. 配列aの2番目から４番目までを取得する
1. 引数に渡した数値が「0から50まで」か判定する
1. ある範囲を配列に置換する
などが挙げられます。
一つずつ見ていきましょう！
```ruby:配列aの2番目から４番目までを取得する例
a = [1,2,3,4,5]
p a[1..3] #=>[2, 3, 4]
```
```ruby:引数に渡した数値が「0から50まで」か判定する
def liquid?(num)
    puts (0..50).include?(num)  
end

liquid?(1) #=>true
liquid?(-1) #=>false
liquid?(50) #=>true
liquid?(51) #=>false
```
```ruby:ある範囲を配列に置換する
p ('a'..'d').to_a #=>["a", "b", "c", "d"]
p (1...5).to_a #=>[1, 2, 3, 4]
```
# まとめ
範囲オブジェクトは、「〜から〜まで」が伴う処理では、活用出来そうですね！
間違いやアドバイス等ありましたら、是非ご教示ください！
condaを叩いたら「AttributeError: module 'colorama' has no attribute 'init'」が出るようになり、なんとか解決できた話

# 0. 事の発端
それはPythonでのデータ分析を勉強中のことでした。
自然言語処理のお勉強で、形態素解析をするためにMeCabをjupyter noteboookで使いたい（ちなみにOSはWindows11）と思い、Anacondaにインストールする作業をしていました。
ところが、MeCabとMeCab-python3の両方をインストールしないといけないことが分かっておらず、コマンドプロンプトでMeCabのバージョンは出力できるのにいざpythonでimportするとエラーになったことで「あれれ～おかしいぞ～～？？」とあれこれpathを変えてみたりAnacondaをupdateしてみたりしているうちに、コマンドプロンプトからもAnaconda Promptからも、condaコマンドを使おうとするととにかく「AttributeError: module 'colorama' has no attribute 'init'」とエラーが出るようになってしまいました。

ちなみに超蛇足ですが、この他「コマンドプロンプトからjupyter notebookが開けなくなった」「コマンドプロンプトで`python`と打ってもインタプリタが開かずWindowsストアが開くようになってしまった」「jupyter notebookのkernelがpythonを認識できなくなって使えない」などなど色んな踏んだり蹴ったりが連鎖的に起こり、日曜日が溶けました。悲しい。
悲しすぎて、解決策がなかなか見つからず一番最後まで残っていたこの問題が今朝急転直下で解決したことが衝撃過ぎてこれはいつか誰かの役に立てば…と、~~腹いせに愚痴を書き殴る~~ 備忘録を残します。

# 1. 解決できた方法
結論を言うと、どうやらcoloramaの中身自体が消えてしまったことが原因のようでした。
解決方法は以下。

1. まずはここからcoloramaのtar.gzを適当なフォルダにダウンロード。
https://pypi.org/project/colorama/#files

2. 解凍するには、コマンドプロンプトなどで以下を叩く。
`tar -xzf ファイル名.tar.gz`
3. 解凍したフォルダの中にある「colorama」ディレクトリを、`.../anaconda/Lib/site-packages/colorama`と置き替えることで解決。

この問題を解決する前は、このcoloramaフォルダの中身が空っぽになっていました。

# 2. 参考
最終的に解決策はこちらから見つけました。
[stall Jupyter in conda env - "AttributeError: module 'colorama' has no attribute 'init'"](https://stackoverflow.com/questions/60902025/install-jupyter-in-conda-env-attributeerror-module-colorama-has-no-attribu)

この記事が参照している[issue 8842](https://github.com/conda/conda/issues/8842)にあるように、確かに`conda update -all`をやった気もするので、これの影響でcoloramaの中身が吹っ飛んでしまったのが原因だったようです。

# 3. 結論
「環境構築が一番しんどい」と言われる所以の片鱗を味わい、僕もエンジニアになったんだなぁ！と思いました。（喉元過ぎて熱さを忘れそうな人）
みんなも環境構築するときには設定をぶっ壊さないよう気を付けよう！