OmniAICreator/Qiita-1.07M huggingface dataset:
iOS16新機能ロック画面ウィジェットの対応方法

起きたらiOS16がリリースされたので、自分のためのロックスクリーンウィジェット作り


## iOS16でようやくロック画面にもウィジェットを配置できるようになった

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/f6470d4d-2dcb-b03d-c3bd-51af227001c0.png" width="400">


## ロック画面用のウィジェット３種類が追加された
 WidgetFamilyに　`.accessoryInline`、`.accessoryCircular`、`.accessoryRectangular` の３種類が追加されています。

`.accessoryInline`は上の画像では日付が表示されている部分、

`.accessoryCircular`、`.accessoryRectangular`は時計の下のエリアに配置できるようです。
`.accessoryCircular`はまるく切りに抜かれて１スロット使用、`.accessoryRectangular`は２スロット使用され、合計で４スロットまで配置できます。（少ない・・・）


ちなみにこれまでのホーム画面ウィジェットは、大中小で以下のサイズです。
`.systemLarge`、`.systemMedium`、`.systemSmall`


## 対応させる
`.supportedFamilies`に対応させたいウィジェットの種類を列挙します。
`.accessoryRectangular` を追加

```swift:Widget.swift
@main
struct portsWidget: Widget {
    let kind: String = "portsWidget"

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            portsWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("ports")
        .description("my ports.")
        .supportedFamilies([
            .systemSmall,
            .accessoryRectangular,
        ])
    }
}

```

SwiftUI側では、widgetFamilyでそれぞれviewを実装します。


```swift:portsWidgetEntryView.swift
struct portsWidgetEntryView : View {
    var entry: Provider.Entry

    @Environment(\.widgetFamily) private var widgetFamily

    var body: some View {
        switch widgetFamily {
        case .systemSmall:
            VStack {
                Text(entry.getPortName())
                HStack {
                    Rectangle()
                        .frame(width: 5, height: 20)
                        .foregroundColor(entry.getColor())
                    Text(entry.getCount()).bold()
                }.padding()
                Text(entry.getDate(), style: .time).font(.footnote)
            }
        case .accessoryRectangular:
            VStack {
                Text(entry.getPortName()).font(.footnote)
                Text(entry.getCount()).bold()
                Text(entry.getDate(), style: .time).font(.footnote)
            }
        default:
            EmptyView()
        }
    }
}

```

これだけでロック画面ウィジェットに対応できました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/3a842054-dd0f-e022-99e8-cdfdf6379f49.png" width="300">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7132/18064956-b35f-da6d-4e89-13f5cef36473.png" width="300">

ユーザー設定によって色は色を変えられたり、モノクロにできたりするので、実装は面倒そう、
今回は自分用なので色が付いてた部分は削除してしまいました。


## おわり
iPhone 14 Proからalways-on displayなのでさらに便利！


今年のWWDCに"Complications and widgets: Reloaded"というセッションがあるので、Lock screen widgetsこちらで詳しく説明されています。
https://developer.apple.com/videos/play/wwdc2022/10050/
Modelerストリームのコメントをmodeler scriptで取得する

Modeler ScriptをつかってModelerストリームのコメントを取得します。

以下のようなPythonのmodeler scriptで取得できます。

```python:comments.py
import modeler.api
stream = modeler.script.stream()
for comment in stream.comments():
    #print(dir(comment))
    print(comment.text)
```

以下のストリームからコメントを取得します。3つのコメントが書かれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/747fb8ed-8956-36ac-ec0a-0bc1ffe5e029.png)

以下のようにコメントを出力することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9b70c79c-298d-62c6-629f-85aa1b134fa3.png)
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その022

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: アプリケーションと活動
セールスアプリケーションとマーケティングアプリケーションの確認

にある練習問題2問目をご紹介します。
https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-applications-activities-and-mobile/review-sales-and-marketing-applications?trail_id=administrator-certification-prep


なお、この内容は動画でも公開しています

https://www.youtube.com/watch?v=If9JP5yEM3E

<iframe width="560" height="315" src="https://www.youtube.com/embed/If9JP5yEM3E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

問題はこちらです

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/62918480-9506-f626-dcef-30f8f8cff56b.png)


今回の問題の「商談の設定」はこちらです
![商談設定001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/c028e8fd-87f9-9416-03b7-b74be7827cee.png)
axiosのNettwork ErrorでAPIからデータが取得できない

# 環境

- Macbook Air 2020
- react 18.0.0
- react-native 0.69.4
- expo 46.0.6
- React Native Debugger 0.13.0
- iPhone12 mini
- ios 15.6

# １．状況

トレーニングマシン予約アプリを作成中、React NativeにてaxiosでAPI（Laravel）からジム一覧データを取得し、一覧表示させている。
動作確認のため、Expo Goアプリを使用し自分のiPhoneでアクセスしたところ、`Nettwork Error` が出ておりAPIからデータが取得できていなかった。
（React Native Debuggerではコンソールでデータが取得できていることは確認済み）

```jsx:Gym.tsx
useEffect(() => {
  getGymAll();
}, []);

/**
 * 登録している全ジムデータを取得
 */
const getGymAll = async () => {
  try {
    const { data } = await axios.get(`http://loalhost/api/gym`);
    setGyms(data);
    console.log(data);
  } catch (error) {
    console.log(error.message);
  }
}
```

アクセスした際に `getGymAll` メソッドが実行され、取得したデータをステートにセットしている。

# ２．エラー内容

```bash
Axios Error : "Nettwork Error"
```

# ３．調査

### axiosの書き方を変えてみる

下記記事を参考にコードを修正してみるも変化なし。

> [https://github.com/axios/axios/issues/3192](https://github.com/axios/axios/issues/3192)


```jsx:Gym.tsx
await axios.get(`http://localhost/api/gym`, {
  headers: {
    'Content-type': 'Application/json',
    'Accept': 'Application/json',
  },
  data: {},
})
```

### LaravelのCORS設定を有効にしてみる

下記記事を参考に設定してみるも変化なし。

> [https://takabus.com/tips/341/#toc2](https://takabus.com/tips/341/#toc2)


# **４．原因**

`http` にリクエストを送っているのが原因のよう。

> [https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed](https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed)


記事の中で **「iOSはデフォルトでHTTPリクエストを許可しておらず、HTTPSのみ許可している」** との記載があった。

> The problem here is that iOS does not allow HTTP requests by default, only HTTPS.
ここで問題となるのは、iOSはデフォルトでHTTPリクエストを許可しておらず、HTTPSのみ許可していることです。


# ５．解決策

`egrok` を使用し、 `https://XXXXXXXX.ngrok.io` アクセスしたら`localhost` にフォワーディングさせるようにした。

- egrokをインストール

> [https://ngrok.com/download](https://ngrok.com/download)

- egrokの設定

> [https://qiita.com/miriwo/items/8c1e6550a5ab279d60b5](https://qiita.com/miriwo/items/8c1e6550a5ab279d60b5)

- egrok起動

```jsx
ngrok http 80
```

起動すると  `Forwording https://XXXXXXXX.ngrok.io -> localhost` と出てくるのでコード内の `http://localhost` の箇所を `https://XXXXXXXX.ngrok.io` に変更する。

```jsx:Gym.tsx
useEffect(() => {
  getGymAll();
}, []);

/**
 * 登録している全ジムデータを取得
 */
const getGymAll = async () => {
  try {
    const { data } = await axios.get(`https://XXXXXXXX.ngrok.io/api/gym`);
    setGyms(data);
    console.log(data);
  } catch (error) {
    console.log(error.message);
  }
}
```

データが取得できた。
Cloud9でphpを実行できるようにする

# はじめに
この記事では、Cloud9でphpを実行するための手順を示しています。(Cloud9にプロジェクトをまだ作成していない方は[こちらの記事](https://qiita.com/webkobe24/items/0dca39bb72879a09923f)から作成してみてください)

# パッケージの最新化
あらかじめインストールされているパッケージが存在していることがありますが、こちらは最新バージョンではない可能性があるので、最新バージョンにアップデートしておきましょう。最新バージョンにアップデートしておくことで、機能追加や性能向上だけでなく、脆弱性対応も含まれていることがあります。
```
$ sudo yum update -y
```
問題なく実行できていれば大丈夫です。

# タイムゾーンの設定
タイムゾーンとは標準時が同じ地域ごとに区切った時間帯のことです。この時間帯は日本標準時にしていた方が都合が良いので、日本標準時に変更します。
```
$ sudo timedatectl set-timezone Asia/Tokyo
→問題なく実行できれば大丈夫
$ timedatectl
(省略)
       Time zone: Asia/Tokyo (JST, +0900)
(省略)
```
このような表示がされていれば変更できています。

# php実行環境セットアップ
バージョンによって、同じ言語でも対応している書き方やモジュールの違いがあるので、バージョンをしっかり合わせる必要があります。
今回はphp8.0で開発をしたいので、php8.0をセットアップします。
```
$ php --version
→PHP8.0でない場合は、以下のコマンドを実行

#　PHP8系Remiリポジトリの追加
$ sudo yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

# PHP8系Remiリポジトリの優先度設定
$ sudo vim /etc/yum.repos.d/remi-php80.repo
→「[remi-php80]」ブロックの最後に「priority=9」を追加する

# PHP8系パッケージのインストール
$ sudo yum install --enablerepo=remi-php80 php php-mbstring php-pdo_mysql php-pdo
→インストール確認項目が出てくる前に出力されるリストにおいて
Versionが8.0になっていることを確認して実行する。

$ php --version
→PHP8.0になっていれば大丈夫
```

以上でCloud9でphpを実行できるようになりました。
docker-compose でエラーが発生する

# Cannot create container for service
`docker-compose up -d` でコンテナを起動しようとすると上記エラーでたまに失敗するようになった。
毎回調べるのも手間なので自分用のメモがてら。

## コンテナの削除
```
docker system prune
```

個別に対応する場合はIDとか調べて消していくのがいいと思うけど。
終わったらもう一回ビルド。

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

## 原因の心当たり
最初にエラーが発生するようになったのは、`CORS policy` を回避するために、フロントエンドとAPIの別コンテナを同一ネットワークにしようと`docker-compose.yml`や`package.json`をいじっては何回もコンテナを立ち上げて-----を繰り返していたとき。

試行錯誤の結果、コンテナ削除という形に落ち着いた。
それでもこれ以降もたまに失敗するので、もっと根本的な部分があると思う。

## 参考
https://docs.docker.jp/config/pruning.html
paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript 部分列

部分列 (paizaランク B 相当)

https://paiza.jp/works/mondai/sort_advanced/sort_advanced__problems_speedup_step3

大きい方から足して,和が初めてx以上になった時の要素数が答えです。
事前準備として数列aを大きい順(降順)にソートしておきます。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//数列の長さを表す整数 n, x
const [n, x] = lines[0].split(" ").map(Number);
//数列 a
const a = lines[1].split(" ").map(Number);

//数列aを降順にソートする
a.sort((a, b) => b - a);

//大きい方から足して,和が初めてx以上になった時の要素数が答え
let sum = 0;//和
let ans = -1;//答えの要素数。和sumを x 以上にできない場合は、代わりに -1 
for (let i = 0; i < n; i++) {
    sum += a[i];
    if (sum >= x) {
        ans = i + 1;
        break;
    }
}
console.log(ans);
```
paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript マンハッタン距離

マンハッタン距離 (paizaランク B 相当)

https://paiza.jp/works/mondai/sort_advanced/sort_advanced__problems_speedup_step8

を解いてみました。
sort関数内で、比較する変数 `a, b`について、それぞれマンハッタン距離を求めます。昇順に並べ替えるので、`return (aのマンハッタン距離) - (bのマンハッタン距離);`とします。

```javascript:JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//n 個の点を原点とのマンハッタン距離が昇順になるように並び替え、改行区切りで出力
console.log(
    lines.slice(1).map(line => line.split(" ").map(Number)).sort((a, b) => {
        //マンハッタン距離で昇順にソート
        return Math.abs(Math.abs(a[0]) + Math.abs(a[1])) - 
            Math.abs(Math.abs(b[0]) + Math.abs(b[1]));
    })
    //改行区切りで出力
    .map(pair => pair.join(" ")).join("\n")
);
```
paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript 文字列のソート

文字列のソート (paizaランク B 相当)

https://paiza.jp/works/mondai/sort_advanced/sort_advanced__problems_speedup_step7

sort関数内で、
文字列の昇順は
```javascript
return a.length - b.length;
```
で、辞書順にするには、
```javascript
if (a < b) { //辞書順でaがbの前なら
    return -1;//aをbの前に並べる
}
if (a > b) { //辞書順でaがbの後なら
    return 1;//aをbの後に並べる
}
return 0;//一緒なら元の順序のまま
```
のようにします。

# 解答例(比較関数自作)
ソート関数の中で、優先順位にしたがってifで場合分けをします。

```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//文字列の数 n
const n = Number(lines[0]);
//文字列の配列 s
const s = lines.slice(1).sort((a, b) => {
    //1. 各文字列の文字数が昇順になるようにする。
    if (a.length !== b.length) {
        return a.length - b.length;
    //2. 文字数が等しい複数の文字列の中では、辞書順になるようにする。    
    } else {
        if (a < b) {
            return -1;
        }
        if (a > b) {
            return 1;
        }
        return 0;
    }
});
console.log(s.join("\n"));
```


# 解答例(優先順でソート順を変える)

優先順位が低い方からソートします。

```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//文字列の数 n
const n = Number(lines[0]);
//文字列の配列 s
const s = lines.slice(1);

//2. 文字数が等しい複数の文字列の中では、辞書順になるようにする。    
s.sort((a, b) => {
    if (a < b) {
        return -1;
    }
    if (a > b) {
        return 1;
    }
    return 0;
});

//1. 各文字列の文字数が昇順になるようにする。
s.sort((a, b) => a.length - b.length);

console.log(s.join("\n"));
```
Azure Pipelines にて同時実行数（max concurrency）を１とする方法

## 概要

Azure Pipelines にて同時実行数（concurrency）を１とするには、排他ロック(Exclusive Lock)機能の利用により可能となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/91a11d24-8725-6f80-2d16-076e585efd6d.png)

引用：[パイプラインデプロイの承認 - Azure Pipelines | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass#exclusive-lock)

本手順では `Enviroment` (環境)を用いる手順となっていますが、変数グループ等でも実施できるようです。

> 環境、サービス接続、リポジトリ、変数グループ、セキュリティで保護されたファイル、エージェント プールに対してチェックを構成できます。

引用：[パイプラインデプロイの承認 - Azure Pipelines | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass)

## 検証手順と結果

### 1. `Enviroment` を作成後、`Exclusive Lock` を設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/693de1a9-d73c-c801-95cd-0a69733c730c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9538ccde-17fa-1e1d-b963-2b8488e80f71.png)


### 2. 1 で作成した`Enviroment`(`concurrency`) を参照したパイプラインを構築

```yml
lockBehavior: sequential
jobs:
- job: delay
  pool: Server
  steps:
  - task: Delay@1
    displayName: 'Delay'
    inputs:
      delayForMinutes: 1
- deployment: echo_test
  displayName: 'echo test'
  dependsOn: delay
  pool:
    vmImage: 'ubuntu-20.04'
  environment: concurrency
  strategy:
      runOnce:
        deploy:
          steps:
          - script: echo Hello world

```

### パイプラインの実行を何度か行い、直列で処理さえていることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/78dad69f-da87-224e-be62-4788db8fd358.png)


## 参考リンク

-   [パイプラインデプロイの承認 - Azure Pipelines | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass#exclusive-lock)

-   [Azure PipelinesでEnvironmentsの排他デプロイ時挙動の違い - kkamegawa's weblog (hatenablog.jp)](https://kkamegawa.hatenablog.jp/entry/2021/08/15/190928)
AWS cloud9に新たなプロジェクトを作成する

# はじめに
この記事は、初めてwebアプリを開発するために開発環境を整えたい方に向けた記事になっております。実際に、投稿者の私もwebアプリを開発するのは初めてでしたので、そのような方には参考になるかと思います。

# cloud9に新しいプロジェクトを作成する
AWSからcloud9の画面に移ると右上の方に`cleate environment`というボタンをクリックすると以下のような画面が出てきます。
![スクリーンショット 2022-09-13 11.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821384/c1e5a980-730f-117a-5bb5-09948473935b.png)
この画面ではプロジェクトの名前と説明を入力する欄になっています。上の名前の部分だけ埋めれば大丈夫です。

続いて、以下のような画面が出てきます。今回は、特に何も変更せずにこのままの設定でプロジェクトを作成してみました。(Environment typeで一番上の欄を選んでいるとAWSの方に料金の請求がくることがあるので、詳しくは[Amazon EC2料金表](https://aws.amazon.com/jp/ec2/pricing/)でご確認ください)
![スクリーンショット 2022-09-13 11.58.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821384/ef148706-6cfd-3db6-df8d-58d614e1b261.png)
そのまま次のステップに進みます。
そうすると、確認画面が出てきます。間違いがないようでしたら右下の`cleate environment`をクリックしてください。
![スクリーンショット 2022-09-13 12.06.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821384/241257df-7d6f-8570-9902-d67b3dd951d9.png)
このような画面が出てきたら終了です。

# 最後に
この次の記事では、cloud9でphpの実行環境を整える方法を書きたいと思います。どの分野においても環境構築が大変だと思うので、１つずつ記事を作成していきたいと考えています。
オライリー（O’Reilly）ウェビナー　2022年9月14日12:00-12:45（日本時間）

技術チームやビジネスチームは、どのようにオライリーのプラットフォームを利用し、今時のトレンドを先取りできるかを共有するため、今回のウェビナーを開催いたします。

約30分のウェビナーの中では、早期リリース、テックコンファレンス、さらにプラットフォーム上でのコンテンツがどのように活用できるかをご紹介いたします。

オライリーについて、ご質問がある場合は、ウェビナーの最後に、Ｑ＆Ａセッションがありますので、お気軽にご質問ください。
![O'Reilly Logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775700/99d8653b-b084-f5c7-9339-adea3c3c9f4d.png)

2022年9月14日12:00-12:45（日本時間）日本語でご案内いたします。

※本ウェビナーは無料で一般公開されていますが、座席数に限りがありますので、ご登録が必要です。

登録無料


https://omg.oreilly.com/~lmalbas/Webinar/New%20Business/2022/NewBusiness-Demo-Webinar-JAPANESE.html
確率と統計

# 事象が排反するとは？
＜「排反事象」 について＞
２つの事象 A、B があるとき、

事象 A、B が ```同時に起こることがない``` 場合、「事象 A、B は 互いに排反である」
事象 A、B が 同時に起こることがある 場合、「事象 A、B は 互いに排反でない」 と言います。

たとえば、1組のトランプから1枚のカードを引いたとき
「ハートが出る」、「スペードが出る」 ということは同時に起きないので、これらは互いに排反ですが、 「ハートが出る」、「２のカードが出る」 ということは同時に起こることがあるので、排反な事象ではないです。
（Ａ、Ｂが互いに排反事象になるときは、ＡまたはＢとなる確率は、２つの事象の確率の和になります。）

出典

https://kou.benesse.co.jp/nigate/math/a13m0510.html

## 気づき
論理積がないことを指すのか。

# 問題１の気づき
天候に関する問題だった。
天候が変わる確率を見つけ、それらを掛け合わせなければならない。
二日間の天候の変わり方の確率を見つけなければならない。
２つの事象が二日間という括りで同時に起こるので論理積で求めるのかもしれない。

事象が起こる範囲で排反しているかしていないかを判別するのか。
一瞬の天気は晴れと雨同時に起こることがないからこの場合は排反になる。

# 問題2の気づき
今は理解できなかった。
これから理解しようと思う。
とりあえず公式を覚えよと思う。

どうやらビットパターンの個数は、８ビットの中から４ビットを取り出す時の選び方（組み合わせ）をわかるために使うらしい。

https://rikeilabo.com/formula-and-diferrence-of-permutation-combination#21

https://goukaku-suppli.com/archives/38298#:~:text=%E9%A0%86%E5%88%97%E3%81%A8%E7%B5%84%E3%81%BF%E5%90%88%E3%82%8F%E3%81%9B%E3%81%AE%E6%A6%82%E8%A6%81%E3%83%BB%E5%85%AC%E5%BC%8F%E3%83%BB%E9%81%95%E3%81%84,-%E9%A0%86%E5%88%97%E3%81%A8%E7%B5%84%E3%81%BF%E5%90%88%E3%82%8F%E3%81%9B&text=%E9%A0%86%E5%88%97%E3%81%A8%E3%81%AF%E3%80%81%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8B,%E3%81%AF%E5%85%B1%E9%80%9A%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

# 問題３の気づき
解けなかった。
問題文をしっかり読まなければいけなかった。
問題文の```この工場で製造された製品の一つを無造作に抽出して調べてたところ```と書いてあったことに気づかなかった。
これからしっかり読まなければならない。これは癖になっている。
また公式を知らなくても解けた問題だ。ため息が出る。

製造確率と不良発生確率は論理積になる。
全体の不良品発生確率の中のAの不良品発生確率で求まる。

# 問題４の気づき
## 正規分布（又の名を”ガウス分布” ）とは？
この形が鐘の形に似ているため、正規分布が描く曲線のことをベルカーブとも呼びます。
下図の横軸は```観測データ(確率変数)```を、縦軸はその値が生じる```確率(確率密度)```を表しています。
### 特徴
* ```左右対称```である
* ```平均の観測データが生じる確率が最も大きい```
* ```平均から離れるほど生じる確率は小さくなる```

出典 https://best-biostatistics.com/summary/normal_dist.html

## 標準正規分布とは？
* “ある範囲にどれくらいの観測データが含まれているか”を知るのにすごく便利です。
* 平均が0で、標準偏差が1の正規分布

出典　https://best-biostatistics.com/summary/standard-norm.html#i

## 標準正規分表とは?
”ある値以上が生じる確率”をまとめた表

出典　https://best-biostatistics.com/summary/standard-norm.html#i

## 標準化とは？
正規分布から標準正規分布に変換すること

出典 https://best-biostatistics.com/summary/standard-norm.html#i

調べたけどわからなかった。
公式を覚えた方が早いのだろうか？違う角度からの問題が来た時が大変だ。
とりあえず
未満となる値から平均を引き標準偏差で割った値を正規分布表と照らし合わせて割合を見つける。

# 問題５の気づき
## 平均とは？
```データの合計をデータの個数で割った```もの

## メジアンとは？
データの```昇順または降順に並べた時の中央値```。
データの個数が```偶数個だった場合は、中央２つの平均値```を取る。

## モードとは？
```出現頻度が最も高いデータ```のこと。

# 気づき
確率と統計の公式を知らなかったのが痛かった。
公式を覚えて円滑に進めていきたい。


# 出典　

https://gihyo.jp/book/2022/978-4-297-12375-8
SONY Spresense用の6軸センサーBMI270ボードをArduino IDEで動かしてみた

SONY Spresense用の6軸センサー(BOSH社製BMI270)ボードをArduino IDEで動かしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/fe514f4a-2ea2-b26a-308b-23665c3928dc.png)
**BMI270ボードのSpresense Main boardへの取り付け方法**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/407b069c-6141-3c7a-1e7b-2f481f032766.png)
**使用した機器**
Spresense Main board
BMI270 Add-on board

**プログラム開発環境**
Arduino IDE

**ベースにさせていただいたソースコード**
[TomonobuHayakawa/BMI270-Sensor-API](https://github.com/TomonobuHayakawa/BMI270-Sensor-API)  
(いつもお世話になっている T.Hayakawa 様のGitHubリポジトリ)

上記のGitHubから Arduino IDE用のソースコードと必要なファイルをダウンロードします。
(丸ごとクローンしてローカルでコピーした方が早いかも)

**必要なファイル**
BMI270_Arduino_example/BMI270_Arduino_example.ino
bmi2.c
bmi2.h
bmi270.c
bmi270.h
bmi2_defs.h

この6個のファイルをArduino IDEの作業フォルダーに **BMI270_Arduino_example** フォルダーを作ってその中に入れます。
BMI270_Arduino_example.ino をダブルクリックすると **Arduino IDE** が起動して6個のファイルが開かれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/3755132b-13ac-7913-face-f9158c9ff1b0.png)
エラー無くコンパイル出来るはずです。

なお、BMI270のI2Cアドレスは、ディフォルトのままであればソースの変更は必要ありませんが
**JP1をショート**している場合は BMI270_Arduino_example.ino の64行目を
**bmi2.dev_id = BMI2_I2C_PRIM_ADDR;**
に変更してください。

**実行結果**
プログラムが起動したらなんでも良いので1文字送信してください、計測が始まり、
傾けたり、振ったりしたらデーが変化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/9707ff73-5c1f-f5fa-4869-f9c17e266d1d.png)

**ライブラリとしてインクルード**
**TomonobuHayakawa/BMI270-Sensor-API**はライブラリとして Arduino IDE に取り込むことが出来ました。
ライブラリとしてインクルードすると、もっと簡単に扱うことが出来ます。
**メニュー**の**スケッチ**から**ライブラリをインクルード** ⇒ **.ZIP形式のライブラリをインストール**をクリックします。
![2022-09-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/a502c25e-d0a0-c822-f24d-3607f2fea6b4.png)
ダウンロードした**BMI270-Sensor-API-master.zip**を選択します。
![2022-09-14 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/6ae37581-61cf-9171-d08e-1b5c04935d48.png)
ライブらラリが正しくインクルードされたら以下のメッセージが表示されます。
![2022-09-14 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/f95fcd40-3063-53e9-ef52-96787cde14a8.png)
ファイルエクスプローラーで確認すると **Arduino/librariesフォルダー**の中に **BMI270-Sensor-API-masterフォルダー**が出来ているのが確認出来ます。
![2022-09-14 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/46b333a1-caa6-c968-0029-49a16456e1f1.png)
スケッチ例の中に**BMI270_Arduino_example**が有るのでこれを開いてください。
![2022-09-14 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/db24a518-d30f-c351-576b-05c13968a9ec.png)

**最後に**
半導体不足の影響を受けて加速度センサー類の入手が難しくなっていて、このBMI270もやっと入手できました。

この記事はArduino IDEを使ったやり方について書きましたが、
Spresense SDK を使われる場合は以下の記事を参考にしてください。
[SONY Spresense用 6軸IMU BMI270センサーボードをSPRESENSE SDKで制御してみました](https://qiita.com/ixy-shino/items/bb4be00e6c247676bcc3)
AWS ちょっと費用計算が楽になる係数

* $/時 => ¥/月
93,600 ≒ 9万 (為替130)
100,800 ≒ 10万 (為替140)

例: t3.large 0.1088$/h => 約1.1万円/月  (為替140)
為替140だと計算しやすくて良いね（吐血）


* $/日 => ¥/月
3,120 ≒ 3.1千 (為替130)
3,360 ≒ 3.4千 (為替140)
AssociatedTypeを使ってみた

Protocolを学んでいく上で、AssociatedTypeがなんなのかわからなかったため、メモ程度にここに記述。

# AssociatedTypeとは？
Swiftでよく使うGenericsと同じように、Protocol内で定義する連想型のこと！
準拠時にどんな型にするかを指定することができる。

# 具体例
なんらかのAPIを叩く際！

まずは、protocolから定義！
```Swift: APIRepository
    protocol APIConfigure {
    associatedtype ResponseEntity: Codable
    static var path: String { get }
    static func request(completion: ((ResponseEntity) -> ())?)
}
```

protocolにextensionを生やす！
```Swift: APIRepository
extension APIConfigure {
    static func request(completion: ((ResponseEntity) -> ())?) {
        guard let url = URL(string: Self.path) else { return }
        let task = URLSession.shared.dataTask(with: url) { data, _, _ in
            guard let data = data, let responseEntity = try? JSONDecoder().decode(ResponseEntity.self, from: data) else {
                return
            }
            completion?(responseEntity)
        }
        task.resume()
    }
}
```

protocolに準拠したstructを作成する（structの中身は適当に作りました。）

```Swift: APIClient
public struct APIClient {
    struct UserGet: APIConfigure {
        typealias ResponseEntity = User
        static let path = "https://qiita.com/api/v2/users/anies1212"
    }

    struct ItemsGet: APIConfigure {
        typealias ResponseEntity = [Item]
        static let path = "https://qiita.com/api/v2/items"
    }
}

struct User: Codable {
    let name: String

    init(name: String) {
        self.name = name
    }
}

struct Item: Codable {
    let name: String

    init(name: String) {
        self.name = name
    }
}
```

ViewControllerで実際に呼び出してみる！！

```Swift: ViewController
class ViewController: UIViewController {

    private let userNameLabel: UILabel = {
        let label = UILabel()
        label.textColor = .label
        label.font = .systemFont(ofSize: 12, weight: .semibold)
        label.textAlignment = .center
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(userNameLabel)
        getResponse()
        view.backgroundColor = .white
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        userNameLabel.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 50)
    }

    private func getResponse(){
        APIClient.UserGet.request {[weak self] user in
            DispatchQueue.main.async {
                self?.userNameLabel.text = user.name
            }
        }
    }
}
```

# 思ったこと
```Swift
private func getResponse(){
        APIClient.UserGet.request {[weak self] user in
            DispatchQueue.main.async {
                self?.userNameLabel.text = user.name
            }
        }
    }
```
ViewController内でこんだけでレスポンスを呼べるのはとても便利だなと感じた。
protocolにassociatedTypeを持たせてあげるだけで、CodableなEntityである限り、なんでも共通のメソッドでレスポンスを呼べる！！
Google Optimize ABテストで苦労したくないので割とよくやる方法

# まず初めに
私がこんな方法をよく使ってるなぁという体感（）ベースなので、半分ポエムだと思ってください。他の方法やいい方法がありましたらコメント下さい。

## 結論
### パターン1

※slimです。htmlへは脳内変換お願いします。
```slim
main.container
    .ab-test-original
        | もともと表示されてるやつ
    .ab-test-pattern1
        | 新しく試したい要素

sass:
    .ab-test-original {
        display: block;
    }
    
    .ab-test-pattern1 {
        display: none;
    }
```

Google Optimizeの設定
![スクリーンショット 2022-09-13 10.34.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241708/03de5562-3ae7-b88b-6b5b-b5f69f730b06.png)

これは部分的に変えたい時に要素の表示を切り替える事で、見え方を変えてる例です。もっと細かく変えないといけなくなった場合対応しきれなくなりますが、概ねこの程度なら全てこれで片付きます

### パターン2

```slim
main#ab-test
    header
        | ヘッダーの背景色変えたいなぁ
    footer
        | ほげほげ

sass:
    header {
        background: aqua;
    }

    .ab-test-pattern1 {
        header {
            background: black;
        }
    }
```

Google Optimizeの設定
![スクリーンショット 2022-09-13 10.43.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241708/71842542-4a9f-3b34-4045-4e92ffb84fa9.png)

このパターンは汎用的に使ってるクラスで変更箇所多すぎるから上書きしたいけどページ全部変わっちゃうからきついって時に使います。

## まとめ
GoogleOptimizeはテストページに対してcssとjavascriptを仕込めるのでうまいことしましょう。それさえ知ってれば後はcssだったりのお話なんで割となんでもできるような気がします。

### 雑記
転職先を探しながら毎日生活してるのですが、エンジニア不足って本当？ってくらい難儀してます。というのも自分に自信はなくアッピル出来にくいのが原因なんですが、アッピルとは・・・？
【夏休み企画】#IT用語一問一答【毎朝投稿20日目】JIT Compiler

# この記事を読むと、、
- 「関連用語」を使って「JIT Compiler」を説明できるようになる
- 「JIT Compiler」がもっと好きになる(多分)

# 関連用語
バイトコード / バイナリコード / AOT / interpretation

[**復習用**] 記事の内容を見る前に上記の言葉で「JIT Compiler」を説明してみよう！

# 企画説明
- クラウドって何？って人に聞かれて説明してるけど俺もよく知らないや、、
- ドキュメント読んでみてるけど半分くらい何言ってるか分かんない、、
- 今日の夕飯はナスの炒めものにしよっかな〜、あれ、NASってなんだっけ？

みたいなことが結構あったので、知ったかしていたIT用語を毎日一個ずつちゃんと学んでいこうっていう企画です！

昨日の記事はこちら↓

https://qiita.com/acta/items/6e3ddcdf3ae6e3ff0c12

# JIT Compilerとは
JIT Compiler = Just-In-Time Compiler = 実行時コンパイラ = プログラム実行時にバイトコードを機械語にコンパイルするコンパイラ
- cf. **バイトコード** = 中間言語 = 仮想マシン上で解釈される環境(OSやCPUなど)に非依存の形式
- cf. 機械語 = マシン語 = **バイナリコード** = ネイティブコード = オブジェクトコード = 実機で解釈される環境依存の形式

- JIT CompilationはAOT Compilationとinterpretationを組み合わせた手法
    - cf. **AOT Compilation** = Ahead-Of-Time Compilation = プログラム実行前にソースコードを一括で機械語にコンパイルすること
    - cf. **interpretaion** = プログラム実行時にソースコードを一行ずつ機械語に変換すること
    - JIT Compilerはバイトコードの一部をコンパイルし、その他の部分を逐次実行することで起動時間と長期パフォーマンスの間でバランスを取っている
        - 例えば頻繁に呼び出されるメソッドは機械語にコンパイルしておいた方がパフォーマンスがよくなる
        - すべてのメソッドをコンパイルすると起動時間が長くなってしまう



# 参考資料
- https://www.ibm.com/docs/en/ztpf/1.1.0.15?topic=reference-jit-compiler
- https://en.wikipedia.org/wiki/Just-in-time_compilation
- https://en.wikipedia.org/wiki/Ahead-of-time_compilation
Elixir/Nervesのシリアルコンソールの設定と立ち上がり時のログの有効化

1. はじめに
　　通常、ネット経由で `ssh nerves.local`によりターミナルを開き、IExを使用しています。何らかの理由で接続がうまく行かない場合、ラズパイに直接つながるデバイスを使用し、IExの操作をします。
　　デバイスにはHDMIモニター(デフォルト設定)とシリアル通信によるものがあります。
　　ここでは、シリアル通信(コンソール)へ変更する方法と立ち上げ中のログを表示する方法を記述します。
　　現状、シリアル通信コンソールにはIExの表示のみで、立ち上げ中のログは表示されていません。

![consoleBlock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146500/063f3842-07c0-670d-0b93-bd9c662afc34.png)


1. 元にした資料
   ・ [@pojiroさんの資料](https://docs.google.com/presentation/d/1KQGRrgbLSzd6ukiKaWrpzx0VvrBLTeWXrEU61xp0rw0/edit#slide=id.ps)
   ・ [Nervesのドキュメント](https://hexdocs.pm/nerves/advanced-configuration.html)
   

   
2. コンソールをシリアル通信に設定
   コンソールの設定はVMが立ち上がる時に設定されます。そして、VMは `erlinit.config`のファイルを元に立ち上がります。
   ファイル内の`-c xxx`の設定を変える事により、HDMI(tty1)か、シリアル(ttyAMA0)かになります。

   1)`config/config.exs`の設定による方法
```
# config/config.exs

config :nerves, :erlinit,
   ctty: "ttyAMA0"
```

　　2) 直接、`erlinit.config`を変更する
    ・`nerves_system_rpi3`(rpi3の時)の`deps/nerves_system/rpi3/rootfs_overlay/etc/erlinit.config`をProjectの`rootfs_overlay/etc/.`にコピーします。
    ・コピーしたファイルを変更、`-c tty1`をコメントアウト、`-c ttyAMA0`を生かす

```
# Specify where erlinit should send the IEx prompt. Only one may be enabled at
# a time.
-c ttyAMA0     # UART pins on the GPIO connector
#-c tty1      # HDMI output
```

3.立ち上げ中ログ表示
　1) 立ち上がって、IExになった時に次のコマンドで過去のログが見れる。
```
iex> RingLogger.next
```

　2) 立ち上がり中のログを直接シリアルコンソール上で見る
    コンソールの設定情報は `cmdline.txt`にあります。そして、このファイルのpathが `fwup.conf`に設定されています。
    ログの表示ロックは`cmdline.txt`の`quiet`が設定されているか、どうかで出力あり、なしが決められます。
    ・まず、対象の二つのファイル `cmdline.txt`と `fwup.conf`を対象のrpix `deps/nerves_system_rpi3/`から `config/.`にコピー展開します。
    ・`cmdline.txt`の `quiet`を削除します。
```
# console=tty1 console=serial0,115200 fbcon=scrollback:1024k root=/dev/mmcblk0p2 rootwait consoleblank=0 quiet
console=tty1 console=serial0,115200 fbcon=scrollback:1024k root=/dev/mmcblk0p2 rootwait consoleblank=0
```
   `cmdline.txt`を参照している `fwup.conf`を変更します。
```
file-resource cmdline.txt {
     #host-path = "${NERVES_SYSTEM}/images/cmdline.txt"
     host-path = "${NERVES_APP}/config/cmdline.txt"
}
```
   最後に編集し他project内の `fwup.conf`を読む設定をconfig/config.exsにします。
```
# config/config.exs

config :nerves, :firmware,
  fwup_conf: "config/fwup.conf"
```


4. まとめ
   シリアルコンソールはハードの接続が厄介なので、あまり使用しませんが、立ち上がり中のログを確認する事により、その過程が見れ、有効な手段です。ハードコントロールが複雑なHDMIと違い、シリアルは単純な通信なので、立ち上がり時の処理を見るのに最適となります。

   現状、設定方法は複雑ですが、たぶん、もっと簡単にできるように改善されると思います。それまで、仮処理として、利用下さい。
vistaでandroid studio その21

# 概要
vistaでandroid studio 1.1.0やってみた。
jniやってみた。
練習問題やってみた。

# 練習問題
jniでzundokoを表示せよ。

# 写真

![device-2022-09-13-072513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/38177ab4-60e0-e69b-7e03-6674b2aa563a.png)


# サンプルコード

```
#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

JNIEXPORT jstring JNICALL Java_com_ohisamallc_ohiapp154_ohiapp154_MainActivity_hello(JNIEnv * env, jobject thiz) {
    char buf[456];
    const char * s0 = "ズン ";
    const char * s1 = "ドコ ";
    const char * s2 = "ドコ キヨシ！！";
    int i = 0;
    int n = 0;
    while (i == 0)
    {
        if ((rand() & 1) > 0)
        {
            strcat(buf, s1);
            n = 0;
        }
        else
        {
            strcat(buf, s0);
            n++;
        }
        if (n == 4)
        {
            strcat(buf, s2);
            break;
        }
    }
	return (* env)->NewStringUTF(env, buf);
}

```


以上。
vistaでandroid studio その20

# 概要
vistaでandroid studio 1.1.0やってみた。
jniやってみた。
練習問題やってみた。

# 練習問題
jniでfizzbuzzを表示せよ。

# 写真

![device-2022-09-13-065334.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6db18e07-53dc-bef7-af1a-751945f03f8e.png)


# サンプルコード

```

#include <jni.h>
#include <stdio.h>
#include <string.h>

JNIEXPORT jstring JNICALL Java_com_ohisamallc_ohiapp154_ohiapp154_MainActivity_hello(JNIEnv * env, jobject thiz) {
    char buf[456];
    char n[8];
    const char * s0 = "fizz ";
    const char * s1 = "buzz ";
    const char * s2 = "fizzbuzz ";
    int i;
    for (i = 1; i < 101; i++)
    {
        if (i % 15 == 0)
        {
            strcat(buf, s2);
        }
        else if (i % 5 == 0)
        {
            strcat(buf, s1);
        }
        else if (i % 3 == 0)
        {
            strcat(buf, s0);
        }
        else
        {
            sprintf(n, "%d ", i);
            strcat(buf, n);
        }
    }
	return (* env)->NewStringUTF(env, buf);
}

```



以上。
ServiceNow - インタラクティブフィルター実装手順

### 1.インタラクティブフィルターを作成する
[Homepage Admin] > [Interactive Filters]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/d827b87b-66a3-bd4b-fc1f-b05c57ff04dc.png)

### 2.Breakdown Sourceを作成する
[Performance Analytics] > [Sources] > [Breakdown Sources]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/a4540248-a142-9344-eaa4-c8b4f1af5037.png)

### 3.ダッシュボードに配置する
ダッシュボードプロパティを開き、Breakdown Sourceタブから設定を追加する
※Act as filterを設定するには、虫眼鏡🔍の列の！マークからOpen Recordを選択で展開したフォームから設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/5e36aa42-5b61-b854-e5db-9218854eb68d.png)

### 4.確認
* ダッシュボード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/ee964d66-50cf-4336-2aa5-d3d2a1a32173.png)

* Incidentチケットにダッシュボードへのリンクを設置し、遷移する
※チケットのステータスを引き渡してインタラクティブフィルターに設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/3b8a0648-083b-ed5f-d72c-bacf91790505.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/e1ca1b00-dc1d-11e3-09f7-d47132294cce.png)
確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/e18740de-2e33-d3dd-b558-f18510a2c4b4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/df8dc7cc-2d7b-5e3c-7ad2-90805c7ba8a8.png)
【メモ】BigQuery,  SQLとは？

# BigQueryとは？
BigQueryとはGoogleが提供するクラウドデータベースのことを指します。GCPに登録することで、利用することができます。
個人でアプリなどを開発しているユーザーにとってリーズナブルな価格で利用することが可能です。

BigQueryではデータ分析やPythonとAPIの連携などが可能であり、様々なログ情報のデータ解析などの膨大なデータを解析するのに向いています。 また、実行処理速度が高速なため、リアルタイムでデータ解析も可能です。

# SQLとは？
SQLはデータベース言語の一つで、データベースの定義や操作を行うことができます。

＜主な命令文＞
CREATE：新しいデータベースやテーブルなどのオブジェクトを定義する

JOIN：テーブル同士を結合する

DROP：定義したオブジェクトを削除する

ALTER：定義したオブジェクトの内容を変更する

TRUNCATE：データをすべて削除する
Cでsplit関数（改良版）

昨日からいろいろな方にアドバイスをもらったので
それを踏まえていろいろ改良してみました

## ソースコード


```C:split.c
#include <string.h>

size_t split2(char* str, char* regex, char** buf, size_t buflen){
    size_t len = 0;
    char* ptr = strtok(str, regex); 
    while(ptr!=NULL)
    {
        if(buflen <= len){
            break;
        }
        buf[len] = ptr;
        len++;
        ptr = strtok(NULL, regex);
    }
    return len;
}

```
引数や戻り値は前回とほぼ同じで

引数strが引用する文字列
引数regexが分割するための文字の引数（strtokを使うためcharからchar*に変更）
引数bufはその分割した配列を入れるためのバッファ
引数buflenは　そのバッファのサイズ

戻り値は、その配列の個数が返ってきます

## 変更点 

まず、新しく知ったstrtok関数というものを使ってみました
（これさえあればそれでいいじゃんとか言わない）
このおかげで前回の三倍ほどの速度で処理ができるようになりました

あとは、buflenに0などを代入してもbuf[0]に要素が入るっていう
割と致命的なバグを指摘されたので　容量があるかの判定を
要素を入れる前に持ってきました
これにより、ゼロやマイナスの値を代入されても大丈夫
（size_tは内部的にunsigned longだからマイナスは受け付けないけどね）

## 色々アドバイスをもらって

自分はほんとにまだまだ未熟だと感じました
まだまだstrtokのような便利な関数も知らなかったし
型とか揃えることや、潜在的なバグを見抜けなかったり…

しかし、そういうアドバイスをもらえることがqiitaの醍醐味だと思うので
これからもめげずに書いていきます
Cloud PubSub(pull) + Dataflow でDataflowが fail した場合の messageの acknowledeの仕組みについて

# 背景
- PubSub(pull) + Dataflow の Streaming パイプラインがある場合を想定します
- 例えば、message処理途中のDataflowのworkerプロセスが突然落ちたら、処理中だったmessageはどうなってしまうのでしょうか？
- dataflow のworkerのプロセスが落ちた後、再度、workerが復活したら処理中だったmessageは再配信されるのでしょうか？

# 結論
- dataflowの処理(データの永続化)が成功しない限りmessageはackされません
- なので、再度Dataflowをdeployすればmessageは再配信されて処理されます

# もう少し詳しく

PubSubのacknowledeについては公式ドキュメントや過去Qiitaを参照してください

https://cloud.google.com/pubsub/docs/subscriber?hl=ja#pull-subscription
  
https://qiita.com/munaita_/items/1149a4830361acbcbdf7

## Google Cloud　の動画

https://youtu.be/6_7nBReSpNM?t=561

こちらの動画のよくある質問コーナーで以下のように説明されていました

> Dataflow does not acknowledge until it has been successfully processed.

*dataflowの処理(データの永続化)が成功しない限りmessageはackされません.*

なので、failしたメッセージを書き込む別のside outputを用意するか、ちゃんとmessageを処理できるように修正して再度デプロイしてくださいね。と言っています。


さらに、タイトルとは関係ないんですが少し驚いたのが以下.

> While Dataflow is in procession of the message, Dataflow modifies the acknowledgement deadline of the message, and Pub/Sub does not re-deliver the message.

*dataflowはmessageを処理している間は、確認応答時間を修正(延長)するので、確認応答時間がすぎることによる再送信は行われません*

と言うことも言っています. 
PubSub + Dataflowを使う際は、確認応答時間のチューニングはあまり意味がないことがわかりました。
HTML5プロフェッショナル認定試験レベル1 試験対策

HTML5プロフェッショナル認定資格レベル1を受験し合格しました。
備忘録として本番までの対策を残しておきます。
## 試験概要
[HTML5プロフェッショナル認定試験 レベル1について（Ver2.5）](https://html5exam.jp/outline/lv1.html)

所要時間：90分（秘密保持契約5分、__試験80分__、アンケート5分）
試験問題数：約60問
受験料：￥16,500（税込）
試験実施方式：コンピュータベーストテスト（CBT）
認定の有意性の期限：5年間

この認定の取得を通じて、下記のスキルと知識を持つWebプロフェッショナルであることを証明できます。
- HTML5(HTML Standard、CSSなどのWeb技術)を使ってWebコンテンツを制作できる。
- ユーザ体験を考慮したWebコンテンツを設計・制作できる。
- スマートフォンや組み込み機器など、ブラウザが利用可能な様々なデバイスに対応したコンテンツを制作できる。
- HTML5(HTML Standard、 CSSなどのWeb技術)で何ができるか、どういった技術を使うべきかの広範囲の基礎知識を有する。

### Ver2.5
出題範囲改定により、マルチデバイス・オフライン・ストレージ系APIの出題範囲が一部変更となったようです。
[HTML5プロフェッショナル認定試験 レベル1 出題範囲 Ver2.5](https://html5exam.jp/outline/objectives_lv1.html)
## 学習方法
### 1\.対策テキスト&問題集
以下のテキストをKindleで購入しました。
要点がまとめられており図解などもされているので、初めに読む本としてはとても理解しやすいと思いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2747710/2484920e-1fdc-bc60-af82-491120ab4b9d.png)
 [HTML5プロフェッショナル認定試験 レベル1 対策テキスト＆問題集　Ver2.0対応版](https://www.amazon.co.jp/exec/obidos/ASIN/B07485SSV3/neos21-22/)
### 2\.学習サイト
アカウントを登録し（2400円/月額）、演習問題を解きました。
問題として500問近く用意されており、出題のされ方も本番に近いものとなっています。
間違えた問題や、お気に入り登録した問題は後から見直すことができるのもポイントです。

出題方式として
・ 正しいものを選びなさい
・ 正しいものを〇個選びなさい
・ 間違ってるものをすべて選びなさい 
etc...
と様々なので、慣れるためにも問題演習はやっておいたほうがいいと思います。
 [ping-t](https://mondai.ping-t.com/g)　
## 試験結果
結果：合格
得点：75点 （合格ラインは65点）

| セクション | 正答率 |
|:-:|:-:|
|  Webの基礎知識 |  75% |
|  CSS | 80%  |
| 要素  | 83%  |
| レスポンシブWebデザイン  |  85% |
| APIの基礎知識  | 37%  |

 
## 感想
問題演習を行ったおかげで「進〇ゼミでやったとこだ！」とスラスラ解くことができました。
APIの範囲は普段業務で扱わないためか、弱いなと改めて感じました。


次はレベル2の受験を考えています。出題範囲がさらに広がるのでゆっくり時間をかけて勉強したいと思います。
GraphQL設計アンチパターン

# はじめに
最近、GraphQL APIを作ることが多いです。最初の方に作ったスキーマを見ると、「なんでこんなことに...!」と自分ながら絶望することがよくあります。
今回はGraphQLの設計で「失敗したな〜」と個人的に思ったことをアンチパターンとしてまとめてみました。(随時更新)

# アンチパターン
大学の履修管理のシステムを考えます。学生(students)と履修科目(courses)のERDが下記です。多対多の関係の交差テーブル`student_courses`を作ります。

```mermaid
erDiagram

students ||--o{ student_courses: ""
courses ||--o{ student_courses: ""
students {
  ID id
  string name
}
student_courses {
  ID studentid
  ID course_id
}
courses {
  ID id
  string title
}

```
## 露出した交差テーブル

素朴にGraphQLスキーマを定義すると以下のようになります。
```graphql
type Student {
  name: String!
  studentCourses: [studentCourse]
}

type Course {
  title: String!
  studentCourses: [studentCourse]
}

type StudentCourse {
  student: Student
  course: Course
}
```
このスキーマはRDB上の関係に忠実ですが、交差テーブルが露出しています。
クライアントが必要な情報は「学生がどの履修科目を履修しているか、またはある科目をどの学生が履修しているか」であって学生と科目がどのように関連付けられているかではありません。

利用者にとって、テーブル構造や実装の詳細は関係ありません。交差テーブルのような実装の詳細に依存すことにより変更に弱くなります。

交差テーブルのような実装の詳細は隠蔽したほうが良いでしょう。

```graphql
type Student {
  name: String!
  courses: [Course]
}

type Course {
  title: String!
  students: [student]
}
```

## そのまんまカラム
studentsテーブルに在学、卒業を表すカラム`is_graduated`があるとしましょう（コレ自体はよくないテーブル設計)。

素朴なスキーマ定義は以下のようになります。
```graphql
type Student {
  name: String!
  courses: [Course]
  isGraduated: Boolean!
}

type Query {
  students: [Student]
}
```
これも実装の詳細が顕になっています。ビジネスドメインに関する知識が必要ですが、履修科目の管理システムなので卒業生と在校生を同じStudentと考えるのは危険です。

クライアントでは永遠に卒業すみかどうかをチェックする必要が出てきてしまいます。
基本的にはAPI側で卒業生データを渡さないように制限をかけるべきでしょう。
もしクライアントで卒業生のデータ必要な場合は、queryを分ける、もつfieldが違うのであればtypeごと分けてしまいましょう。

```graphql
type Query {
  graduatedStudents: [Student]
  students: [Student]
}
```

スキーマ設計時にDBに引っ張られて、カラム名をそのままfield名として使ってしまうことは良くあります。
往々にしてDBは技術的負債を抱えがちです。DBに引っ張られるのではなく、現状のドメイン知識に従ってGraphQLスキーマを定義することが大切です。

## nullableリスト
```graphql
type Student {
  name: String!
  courses: [Course]
}
```
StudentとCourseの関係を見てみると、生徒は0~n個までの科目を登録できます。上記の定義ではnull, [null], []のような値を取りうることになります。

基本的にリストはnull, [null]にドメイン上で意味があることは珍しいです。よってStudentは以下のようにすると良いでしょう。この場合だと、coursesは[]と値の入った配列を許容します。

```graphql
type Student {
  name: String!
  courses: [Course!]!
}
```
## CRUD依存症
mutationをDBのCRUDとして命名してしまうアンチパターンです。
例えば、新規に科目を登録するmutationを`createCource(courceId: ID!)`とします。一見、自然な命名に見えます。

しかし、動詞createは明らかに実装の詳細であるDBに依存してしまっています。クライアントにとって、科目を登録することがDBにレコードを作成するという知識は不要です。命名にはできるだけドメインの言葉を使いましょう。例えば`registerCource`などです。
(もちろん言葉として妥当ならばcreateを使っても問題ありません。)

## なんでもupdate mutation
更新関連の操作をすべて`updateHogeHoge`という１つのmutationで行ってしまうパターンのことです。
例えば、　科目を更新するmutation `updateCource(id: ID!, title: String)`があるとしましょう。最初は更新のユースケースが少ないのでこれでも問題ありません。

ところがあるとき、授業が実施される教室も変更できるようにして欲しいと要望を受けました。mutationは安易に`updateCource(id: ID!, title: String, className: String)`と変更されます。

もちろん教室を変更できるのは、その教室が同じ時間帯に別の科目で使われてない場合のみです。
よって`updateCource`は変更する属性によって条件分岐を余儀なくされます。

以降、同様にしてupdate mutationは様々なユースケースに対応しようとして、巨大かつ複雑なロジックを抱えるようになってしまいます。

mutationはユースケースごとにできるだけ小さくわけることをおすすめします。上記の例だと教室変更は`changeClass` mutationに分割するのが良いでしょう。

# おわりに
こう見るとアンチパターンは、既存のDBスキーマに引っ張られてしまうことが多い印象です。
GraphQLの設計をするときには、一度古い設計から離れて改めてドメインに向き合って設計するのが良いかもしれません。
paizaラーニング レベルアップ問題集 ソートメニュー応用編 JavaScript ペアソート

ペアソート (paizaランク C 相当)

https://paiza.jp/works/mondai/sort_advanced/sort_advanced__problems_speedup_step4


# 解答コード例(優先度が低い方からソートする)
２列目の方が優先度が低いので、先にソートします。
１列目の方が優先度が高いので、後にソートします。
```javascript:JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//数値 n
const [n] = lines[0].split(" ").map(Number);
// n 行 2 列の表 a 
const a = lines.slice(1).map(line => line.split(" ").map(Number));

//2 列目の数値に基づいて昇順でソート
a.sort((a, b) => a[1] - b[1]);
//1 列目の数値に基づいて昇順でソート
a.sort((a, b) => a[0] - b[0]);

//ソートした表を各列は半角スペース区切りで、各行は改行区切りで出力
console.log(a.map(row => row.join(" ")).join("\n"));
```

 # 解答コード例(比較関数自作)
比較関数(sortの中身)を自分で作ります。ifは先の方が優先度が高くなります。
```javascript:JavaScript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//数値 n
const [n] = lines[0].split(" ").map(Number);
// n 行 2 列の表 a 
const a = lines.slice(1).map(line => line.split(" ").map(Number));

a.sort((a, b) => {
    //a を行単位で、 1 列目の数値に基づいて昇順でソート    
    if (a[0] !== b[0]) {
        return a[0] - b[0];
    //1 列目の数値が等しい 2 つの行に関しては 2 列目の数値に基づいて昇順でソート
    } else {
        return a[1] - b[1];
    }
});

//ソートした表を各列は半角スペース区切りで、各行は改行区切りで出力
console.log(a.map(row => row.join(" ")).join("\n"));
```
EKSクラスタの作成者でないメンバーがkubectlでアクセスする設定

<!--
title: EKSクラスタの作成者でないメンバーがkubectlでアクセスする設定
tags: Kubernetes, AWS, eks
-->

# はじめに
KubernetesをAmazon EKSで動かすことが増えてきました。自分で調査や開発するときはeksctlでクラスタを生成してkubectlで操作していますが、先日その私が生成したクラスタを他の開発メンバーに操作してもらおうとしたとき、どうするんだっけとあたふたしたので、対応方法を備忘録的に残しておきます。

基本は[AWS ナレッジセンターの情報](https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-cluster-connection/)を基に進めました。


# 前提条件
- KubectlとAWS CLIがインストールされている。
- AWSのIAMユーザにEKSの権限が付与されており、`aws configure`でプロファイル設定がされている。


# 設定
以下の操作は、eksctlでクラスタを生成した自分（管理者）ではなく、そのクラスタにアクセスしてもらう開発メンバー側でやってもらった作業です。

まずは、Amazon EKS クラスターに対する許可がある認証情報か確認します。

```sh:開発メンバー
aws sts get-caller-identity
```


次に、kubectlの接続設定ファイル（kubeconfig）を生成するためのコマンドを実行します。

```sh:開発メンバー
aws eks --region region update-kubeconfig --name cluster_name
```
--regionオプションのリージョン名、--nameオプションのクラスタ名は各自のものに置き換えてください。

なお、我々が実行した時は、このコマンド実行時に`TypeError: 'NoneType' object is not iterable`というエラーが発生していました。kubeconfigファイルである`~/.kube/config`を開いてみても、殆ど何も記述されていない状態でした。  
そこで、kubeconfigファイルである`~/.kube/config`を手動で削除して、再度上記のコマンドを実行したらエラーが解消しました。正常終了すると、`~/.kube/config`は下図のような内容が記録されています。（塗りつぶしが多くてすみません。。）

![sub005-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724847/3faa7eda-f53a-2bf4-5bda-a77b5e1615eb.png)



次に、kubectlコマンドを実行してクラスタにアクセスできることを確認します。例えば以下のコマンドでdefaultの名前空間にあるServiceを確認します。

```sh:開発メンバー
kubectl get svc
```

なお、我々が実行したときは、このコマンド実行で認証エラーが発生していました。

そこで、aws-auth ConfigMapを編集しました。これは開発メンバーではなく、クラスターを作成した管理者が対応する必要があります。コマンドで以下を入力します。

```sh:管理者
kubectl edit configmap aws-auth --namespace kube-system
```

このコマンドを入力すると、viエディタが立ち上がりました。そこで、`mapUsers`に開発メンバーのIAMユーザの情報を入力します。

入力したのは下図の赤枠の部分です。`userarn`にIAMユーザのARN、`username`にIAMユーザ名を入力しました。

![sub005-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724847/bcbb91f8-5497-acfc-93ef-813d8b81a87e.png)



この設定後、再度開発メンバーの方から`kubectl get svc`コマンドを入力したら、認証エラーが発生せずに結果を取得することができました。


# おわりに
今回はIAMユーザをaws-auth ConfigMapに追加しましたが、IAMロールを追加することもできるようです。詳しくは[こちらのAWSの情報](https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-api-server-unauthorized-error/)を参照してください。
Jestのjest.fn()とjest.spyOn()関数について

# mockingとは
単独テストコードを作成する際、該当のコードが依存する部分を偽の動きをするもの（mock）に変更すること。テスト対象のコードが依存する部分を直接作成することが難しい場合mockingする。

# jest.fn()の使用方法
jestでは偽の関数を作成する`jest.fn()`関数を提供している。
```javascript:javascript
const mockFn = jest.fn()
```

この偽の関数は引数をもって呼び出すことも可能である。
```javascript:javascript
mockFn()
mockFn(1)
mockFn("a")
mockFn([1, 2], { a: "b" })
```

しかしこのままだと、偽の関数は何も設定してないため`undefined`をreturnする。
`mockReturnValue(return値)`を利用して偽の関数がどの値をreturnすべきかを設定することができる。
```javascript:javascript
mockFn.mockReturnValue("I am a mock!")
console.log(mockFn()) // I am a mock!
```

非同期処理をする偽の関数を作りたれば`mockResolvedValue(return値)`を利用することができる。
```javascript:javascript
mockFn.mockResolvedValue("I will be a mock!")
mockFn().then((result) => {
  console.log(result) // I will be a mock!
})
```

最後に、`mockImplementation(コールバック関数)`を利用すると、モックを丸ごと再構成することもできる。
```javascript:javascript
mockFn.mockImplementation((name) => `I am ${name}!`)
console.log(mockFn("John")) // I am John!
```

これらの偽の関数は、何回呼び出されて、どんな引数が与えられたかを検証することができる。
```javascript:javascript
mockFn("a")
mockFn(["b", "c"])

expect(mockFn).toBeCalledTimes(2)
expect(mockFn).toBeCalledWith("a")
expect(mockFn).toBeCalledWith(["b", "c"])
```

# jest.spyOn()の使用方法
あるオプジェクトの中にある関数をmock化せず、該当の関数が呼び出されたか、どのように呼び出されたかを監視する方法。`jest.spyOn(object, methodName)`を利用することで監視する。
```javascript:javascript
const calculator = {
  add: (a, b) => a + b,
}

const spyFn = jest.spyOn(calculator, "add")

const result = calculator.add(2, 3)

expect(spyFn).toBeCalledTimes(1)
expect(spyFn).toBeCalledWith(2, 3)
expect(result).toBe(5)
```

# テスト
ここでは以下のような非同期処理をする`findOne()`というメソッドをテストする。
```javascript:javascript
const axios = require("axios")
const API_ENDPOINT = "https://***.***.com"

module.exports = {
  findOne(id) {
    return axios
      .get(`${API_ENDPOINT}/users/${id}`)
      .then((response) => response.data)
  },
}
```

やり方としては以下の方法にする。
- テストコードでaxiosをインポートする。
- axiosのget関数がnetworkの影響を受けないようにモックかする。
- つまり、いつも同じ値を返す関数に変更する。

以上の方法でテストコードを書くと以下の通りである。
```javascript:javascript
const axios = require("axios")
const userService = require("./userService")

test("findOne returns what axios get returns", async () => {
  axios.get = jest.fn().mockResolvedValue({
    data: {
      id: 1,
      name: "John",
    },
  }) // axiosのgetメソッドを非同期でいつも成功する値を返すモック関数にする。

  const user = await userService.findOne(1)
  expect(user).toHaveProperty("id", 1)
  expect(user).toHaveProperty("name", "John")
})
```
Railsのアソシエーション（has_many、belongs_to）でハマったこと

RailsでWebアプリの開発をしていて、下記のようなテーブルを構築しました。（青線は外部キーの関係）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/91790aa6-e187-e159-7c4d-2b967d3a31f5.png)
この際、各モデルについては、アソシエーションを考慮して、下記のような設定にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/d4872d12-43fd-8182-df90-7a24a4117a69.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/426fbb57-fa29-f8f1-892e-24f74a8ea6fd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/ee881ded-2a8d-4b9e-4856-28c7e6ed8a5e.png)
しかし、この設定のままでshopsテーブルのレコードを削除しようとすると、次のエラーが発生しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/e49f54b3-e4f7-e328-da01-540b8db4bac6.png)
destroyの際に、no such columnのエラーが発生しています。
あれ・・・、reservesテーブルの項目は「Shops_id」のはずですが、「shop_id」を検索しています。。。
これを解決するのに少し時間がかかりましたが、
下記の方法でいけました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/a1194399-b9bd-deef-94a4-9f8422c3f112.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840927/043bfbda-29f7-dd65-e595-9581fb569295.png)

foreign_keyの設定が足らなかったようです。