OmniAICreator/Qiita-1.07M huggingface dataset:
[初学者向け] 今話題のFletのいっちばん最初のチュートリアルのカウンターアプリをサクッと解説！！！！！！

## 目的
Fletに慣れていない方がチョ〜っとだけFletの書き方について理解を深める

## そもそも"Flet"ってなんだよ？
FletはPython（現状では）でWebアプリケーションを開発するためのライブラリです。
Googleによって開発されたクロスプラットフォームのアプリケーション開発フレームワークであるFlutterを元に開発されています。
FlutterのUI部分をWeb上で動作するように拡張し、Webアプリケーションの開発を簡単にすることを目的に開発されています。
Fletを使用すれば、バックエンドエンジニアはPythonでWebアプリケーションの開発に慣れているため、仕組みを理解しやすくなります。
Webアプリケーションの開発に必要なHTML、CSS、JavaScriptを自動生成してくれるため、フロントエンドの技術を習得しなくても、一定の範囲ではユーザフレンドリーなシステムを開発することができます。

:::note warn
ただし、高度なデザインやインタラクティブな機能を実装するには、フロントエンドの技術の知識が必要になる可能性があります。
:::
## 早速やってみよう
今回のカウンターアプリは公式ドキュメントの一番最初の例として挙げられているものです。
[Flet Introduction 公式ドキュメント](https://flet.dev/docs/)

```counter.py
import flet as ft


def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)

    def minus_click(e):
        txt_number.value = str(int(txt_number.value) - 1)
        page.update()

    def plus_click(e):
        txt_number.value = str(int(txt_number.value) + 1)
        page.update()

    page.add(
        ft.Row(
            [
                ft.IconButton(ft.icons.REMOVE, on_click=minus_click),
                txt_number,
                ft.IconButton(ft.icons.ADD, on_click=plus_click),
            ],
            alignment=ft.MainAxisAlignment.CENTER,
        )
    )


ft.app(target=main)
```

### こんな感じの動きですねぇ
1. ft.app(target=main)でアプリケーションを起動し、main関数が呼び出されます。
1. main関数では、新しいPageオブジェクトを作成し、titleプロパティに"Flet counter example"という文字列を設定し、vertical_alignmentプロパティにft.MainAxisAlignment.CENTERを設定します。
1. そして、TextFieldオブジェクトを作成し、valueに"0"を、text_alignにft.TextAlign.RIGHTを、widthに100を設定します。
1. 次に、minus_click関数とplus_click関数を定義し、それぞれ、TextFieldのvalueを1つ減らす、1つ増やす処理をします。最後に、pageに、IconButtonのrowを追加し、それぞれminus_click関数、plus_click関数を呼び出します。
1. それによって、ユーザが「+」「-」ボタンをクリックすると、TextFieldのvalueが増減することができるアプリケーションが完成します。

最後に`python counter.py`とすることでアプリ画面が起動しますで。

## んん？...  粒度を細かくして再度解説しますね！

- import flet as ftでfletライブラリをインポートしています。
- def main(page: ft.Page):でmain関数を定義しています。引数には、fletのPageクラスのインスタンスが渡されます。
- page.title = "Flet counter example"で、アプリのタイトルを設定しています。
- page.vertical_alignment = ft.MainAxisAlignment.CENTERで、アプリの縦方向のアライメントを中央寄せに設定しています。
- txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)で、0が入力されたテキストフィールドを作成しています。右寄せに設定し、幅は100に設定しています。
- def minus_click(e):で、マイナスボタンがクリックされた時のイベントハンドラを定義しています。
- txt_number.value = str(int(txt_number.value) - 1)で、テキストフィールドの値を1減らしています。
- page.update()で、画面を更新します。
- def plus_click(e):で、プラスボタンがクリックされた時のイベントハンドラを定義しています。
- txt_number.value = str(int(txt_number.value) + 1)で、テキストフィールドの値を1増やしています。
- page.update()で、画面を更新します。
- page.add(ft.Row(で、アイコンボタンとテキストフィールドを横に並べるft.Rowを追加しています。
- ft.app(target=main)で、main関数を実行し、アプリを起動します。

## いやぁ、すごく便利ですねぇ。。。
私はバックエンドエンジニアですが、サクッとフロントのUI部分もいじることができるようになるんですね。
せめてJavaScriptくらいはちゃんと読めるようになっておきたいが。。。w
また引き続きFletについての記事を投稿していきますね〜🐰

## 参考
[Flet document](https://flet.dev/)
CURLMOPT_MAX_TOTAL_CONNECTIONS curl_multi_exec の使い方

```php
<?php

function curl_multi($urls)
{
    // マルチcURLハンドルを作成します
    $mh = curl_multi_init();

    // 同時にオープンする接続の最大数を指定します
    curl_multi_setopt($mh, CURLMOPT_MAX_TOTAL_CONNECTIONS, 6);

    $chs = array_map(function ($url) use ($mh) {
        // cURLリソースを作成します
        $ch = curl_init($url);
        // その他適切なオプションを設定します
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // ハンドルを追加します
        curl_multi_add_handle($mh, $ch);
        return $ch;
    }, $urls);

    // ハンドルを実行します
    do {
        $status = curl_multi_exec($mh, $active);
        // 少し待ちます
        if ($active) curl_multi_select($mh);
    } while ($active && $status == CURLM_OK);

    $contents = array_map(function ($ch) use ($mh) {
        curl_multi_remove_handle($mh, $ch);
        return curl_multi_getcontent($ch);
    }, $chs);

    // ハンドルを閉じます
    curl_multi_close($mh);

    return $contents;
}

$contents = curl_multi(['http://httpbin.org/delay/1', 'http://httpbin.org/delay/1']);
var_dump($contents);
```

以下のサンプルプログラムを統廃合しました

https://qiita.com/mpyw/items/f011e28638c43c974e7a

https://www.php.net/manual/ja/function.curl-multi-exec.php#refsect1-function.curl-multi-exec-examples
ニフクラのコンピューティングAPIをbashスクリプトでリクエストする

ニフクラのコンピューティングAPIをbashスクリプトでリクエストするための
スクリプトを書きました。

`params` パラメーターを変更することで、任意のAPIをリクエストできます。

```bash
#!/bin/sh

urlencode() {
    # https://qiita.com/ik-fib/items/cc983ca34600c2d633d5
    echo "$1" | nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n'
}

HOST="jp-east-1.computing.api.nifcloud.com"
ACCESS_KEY="<YOUR ACCESS KEY>"
SECRET_KEY="<YOUR SECRET KEY>"
TIMESTAMP="`date -u +'%FT%T.%2NZ' | sed -e 's/:/%3A/g'`"

declare -A params=(
    ["Action"]="DescribeVolumes"
    ["VolumeId.1"]="VolumeId"
    ["SignatureMethod"]="HmacSHA256"
    ["SignatureVersion"]="2"
    ["Timestamp"]=${TIMESTAMP}
)

# https://pfs.nifcloud.com/api/rest/authenticate.htm
STR="GET\n"
STR+="${HOST}\n"
STR+="/api/\n"
STR+="AccessKeyId=${ACCESS_KEY}"

params_index=( ${!params[@]} )

# パラメーター名でソート
_IFS=$IFS
IFS=$'\n'
sorted_params_index=($(echo "${params_index[*]}" | sort))
IFS=$orig_ifs

# パラメーター名と値をイコール/アンパサントで連結
QUERY_STR=""
for idx in "${sorted_params_index[@]}"; do
    QUERY_STR+="&${idx}=${params[${idx}]}"
done

STR+=${QUERY_STR}

SIGNATURE=$(urlencode $(echo -en ${STR} | /usr/bin/openssl dgst -sha256 -binary -hmac ${SECRET_KEY} | /usr/bin/openssl base64));

curl "https://${HOST}/api/?AccessKeyId=${ACCESS_KEY}${QUERY_STR}&Signature=${SIGNATURE}"
```
横スクロール　右スワイプ処理

前提：onScroll($event)でスクロールイベント検知して、
    const scrollLeft = event.srcElement.scrollLeft;
    const windowWidth = event.srcElement.clientWidth;
    const scrollwidth = event.srcElement.scrollWidth;を取得。


if(windowWidth -windowWidth - scrollLeft >=0){の時に、Date配列に過去日を1ヵ月分追加する処理↓↓↓
```
  /**過去日スワイプ時にpush */
  onSwipeRigth(){
    /**現在保持の最古月を取得 */
    let now0day = new Date(this.dateObj[0].year, this.dateObj[0].month -1);
    /**最古月から1ヵ月前の月を取得*/
    let prevDate = new Date(now0day.getFullYear(), now0day.getMonth()-1);
    /**prevDateの年をnumberで取得 */
    year = prevDate.getFullYear();
    /**prevDateの月をnumberで取得 */
    month = prevDate.getMonth()+1;
    /**月の末日を取得 */
    lastDay = new Date(year,month,0).getDate();
    /**一時保管用のobjectArray */
    let TemporaryStorage= [];
    /**最古月から1ヵ月前の月の日付分保持する */
    for(let i =1; i <= lastDay; i++){
      TemporaryStorage.push({
        year,
        month,
        day:i,
      })
    }
    /**日付を昇順に並び替える */
    TemporaryStorage.sort((a:any,b:any) => a.day - b.day);
    /**画面表示(dateObj)のObjectArrayと結合する */
    this.dateObj = [...TemporaryStorage,...this.dateObj];
  }

```


記事作成中。。。。
【Kotlin基礎】スコープ関数

## 概要
Kotlinを勉強する機会があったのでスコープ関数についてです。

## スコープ関数
スコープ関数とは、ラムダ式を受け取る関数です。
受け取ったラムダ式内で、オブジェクトを名前無しで呼び出し可能な一時スコープが生成されます。

## thisとit
各スコープ関数では、オブジェクトにアクセスする方法として、ラムダレシーバー 「this」とラムダ引数 「it」 の２つのうちどちらかを使用します。

## スコープ関数の種類
Kotlinの標準関数には、 apply、also、let 、 run 、 withの5つのスコープ関数が存在します。

### apply
applyは主にプロパティ設定用関数として使えます。
・呼び出し元を「this」で参照(thisは省略可能)
・戻り値は呼び出し元のインスタンス

以下のようなコンストラクタと２つのプロパティを持つクラスの場合
```kt
class Book(val name: String){
    var price = 0
    var author: String? = null
}
```
applyを使用すると以下のようにプロパティを設定できます。
```
val book = Book("エンジニアの本").apply {
    price = 2000
    author = "エンジニア"
}
println(book.author)　//=> エンジニア
```
また、戻り値が呼び出し元のインスタンスであるため以下の例だと`helloworld`は小文字のままです。
```
val str = "helloworld".apply { toUpperCase() }
println(str) //=> helloworld
```

### also
alsoはapplyと似た使い方をします。
applyと比較すると、ラムダ式の内外でthisの意味が変わらないというメリットがあります。
・呼び出し元を「it」で参照(省略不可)
・戻り値は呼び出し元のインスタンス
```kt
val book = Book("エンジニアの本").also　{
    it.price = 2000
    it.author = "エンジニア"
}
```
元のレシーバをitとして参照できますが、以下のように`book`と命名することでコードの可読性向上に繋がります。
```kt
val book = Book("エンジニアの本").also　{ book ->
    book.price = 2000
    book.author = "エンジニア"
}
```

### let
letはレシーバに対してメソッドを実行するといった使い方をします。
・呼び出し元を「it」で参照(省略不可)
・戻り値はラムダの結果(↓の例だとtoUpperCaseされたもの)
```kt
val str = "helloworld".let {
    println(it) //=> helloworld
    it.toUpperCase()
}
println(str) //=> HELLOWORLD
```

主な用途として、以下のようにnullチェックで使用されます。
null許容型のweightプロパティを呼び出し、nullでなければラムダの結果が出力されます。
```kt
val person = Person("Alice")
person.weight?.let {
    println("体重: $it")
}
```

元のレシーバをitとして参照できますが、以下のようにpersonと命名することでコードの可読性向上に繋がります。

```kt
val person = Person("Alice")
person.weight?.let { person ->
    println("体重: $person")
}
```

### run
letと出来ることはほぼ同じですが、レシーバを「this」として扱うところが異なります。
・呼び出し元を「this」で参照(thisは省略可能)
・戻り値はラムダの結果
```kt
val str = "helloworld".run { toUpperCase() }
println(str) //=> HELLOWORLD
```

### with
withは通常の関数のように呼び出し、2つの引数を取ります。第一引数にレシーバ、第二引数にラムダ式を記述します。
・呼び出し元を「this」で参照(thisは省略可能)
・戻り値はラムダの結果
```kt
val str = with("helloworld") { toUpperCase() }
println(str) //=> HELLOWORLD
```

## まとめ

| 関数  | 呼び出し元の参照 | 戻り値                   | 
| ----- | ---------------- | ------------------------ | 
| apply | this             | 呼び出し元のインスタンス | 
| also  | it               | 呼び出し元のインスタンス | 
| let   | it               | ラムダの結果             | 
| run   | this             | ラムダの結果             | 
| with  | this             | ラムダの結果             | 

## 参考資料
・[Scope functions](https://kotlinlang.org/docs/scope-functions.html)
・[Kotlin スコープ関数 用途まとめ](https://qiita.com/ngsw_taro/items/d29e3080d9fc8a38691e)
・[[Kotlin]スコープ関数 apply,also,let,run,withの使い分け](https://pouhon.net/kotlin-sfunction/1392/)
Java ユーティリティクラス

開発の現場で〇〇Util.javaというのがあり、どのような役割があるのか疑問に思ったので調べました。

## ユーティルティクラス
Utilとはユーティルティクラスを指していたことが分かりました。
ユーティルティクラスとは、多くのクラスで使いそうな共通の処理をstatic領域にまとめて、簡単に処理を呼び出すためのクラスらしいです。
例えば、オブジェクトがnullや空文字なのか判定するメソッド、バリデーションチェックをするメソッドなどは多くのクラスで使いそうなのでユーティルティクラスに保存しておく実装になります。

## 使用例
```java
class MsnUtil {
    private MsnUtil(){}; //インスタンス化させないようにコンストラクタをprivate
    public static boolean isempty(String msn) {
        if(msn == null || msn.equals("")) {
            return true;
        } else {
            return false;
        }
    }
}

class Phone {
    private String msn;

    public void setMsn(String msn) {
        this.msn = msn;
    }

    public String getMsn() {
        return this.msn;
    }
    
    public void method() {
        if(MsnUtil.isempty(this.msn)) {
            System.out.println("入っていません");
        }
        //何らかの処理が続く
    }
}
```
staticにすることで、インスタンスを生成せずに簡単にメソッドを呼び出せるのが特長です。
サービス間を連携してタスクを1元管理する方法　with Zapier

こんにちは。
今日はタスク管理が苦手な僕が発見したとても素敵なサービスを共有します。

ところでみなさんこんなお悩みありませんか？

タスク管理アプリを使っているけど、様々なチャネルからタスクがふってくるから一箇所で管理するのが難しい！！

使いやすいのはGoogle Tasks だけど、自分の所属している会社内ではSlackからもタスクがふってくる。
これはあるあるですよね。特に社外の人とやりとりする人であればGmailを開いたその脇で開けるのでGoogle Tasksはとても便利ですし、Slackは依頼があったらそのままブックマークすればタスクリストが出来上がるので、それぞれに良いところがあってどちらかを選ぶのは難しいです。

結果下記二つのどちらかが高確率で起きると思います。
* 複数タスクリストの2重管理することによってどちらかを確認し忘れ、タスクを漏らすという事態
* どちらかのタスクリストにタスクを書込み直すという転記作業で工数がかかるという事態

さて、そんな方々に是非ご紹介したいサービスがあります！！！
それが　「Zapier」!!!! ( https://zapier.com/)

どんなサービスかというと複数のサービス間のAPI連携ができるサービスです！！
上に記したようなお悩みのある方、もう大丈夫です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/574ebc62-337f-2b0a-f072-834ab78b7fd7.png)
Zapierは画像のように、「このサービスでこういうことが起きたら(トリガー)、別のこっちのサービスでこういう処理をする(アクション)」という一連のフロー(Zapと呼びます。)を作れるサービスです。

上の画像で組んでいるzapは「slackでブックマークをしたら、google tasksでタスクを作るという処理をしています。

この処理を作る中で、slackのメッセージのどの要素(送り主なのかテキスト本文なのか)をgoogle tasksのどの要素(タイトルなのか詳細項目なのか)に反映させるかを選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/061bf7cc-0cfd-5b04-92af-a00f2303c55b.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/910f1893-cfab-b7fc-3e63-8da9c982762f.png) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/9a3d1169-bd0f-3a9f-6d6f-46c25eefb9e5.png)

上のフローを組む場合はslackのテキスト本文と送り主を(だいたい左記二つの要素で重要度わかると思うので)、google tasksのタイトルに(視認性大事なので)流し込んで、
slackのメッセージリンクをgoogle tasksの詳細項目に入れる(リンク押してすぐslack覗きに行けるようにする)のがおすすめです。


それでは動かしてみましょう！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/541e696a-57f1-bbfe-96a4-09559cf760bf.png)

テストでメッセージを送って

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/c9c30d10-8897-370a-c9b9-ea64abf99a88.png)

ブックマークしました。すると？？？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227633/589eb33e-3645-d152-1b1f-b85b3c3eeac0.png)

google tasksにslackのメッセージリンクと共に連携されています！！


とても便利ですね！！

是非お試しあれ！！
C# でコードをシンプルに書く定石

## はじめに

同じ処理でも書き方次第でシンプルに書けます。
1つずつのTIPSの中は、極力、バージョンに依存する書き方は避けて書くようにしています。
但し、TIPそのものが.NET のバージョンによっては書けないものもありますでご了承ください。


## if 条件の処理をシンプルに書く

### 条件に応じて true / false を設定する
→「条件そのものを変数に設定する」
``` C#
int a = 8;
// aが1～10ならばtrue。それ以外はfalse
bool b = (a >= 1 && a <= 10);
```
### null だったら空文字にする
→「フォーマット出力する」
``` C#
object? o = null;
// フォーマット出力
string s = string.Format("{0}", o);
// この書き方ができるバージョンからはこっちの方がシンプル
// string s = $"{o}";
```
### 一定値以下だったら一定値にする
「値が0より小さい場合は0にする」「現在値より計算値の方が大きい場合は計算値を採用する」など。
→「値と条件値の大きい方(小さい方)」を採用する」
``` C#
int a = -5;
// マイナスだったら0にする
a = Math.Max(a, 0);
```

### 指定文字数以上だったら指定文字数まで、それ未満なら指定文字数になるまで末尾を空白で埋める
→「条件値の末尾に指定文字数分の空白をくっつけて指定桁数でぶった切る」
``` C#
string s = "abcd";
// 10文字以上だったら10文字まで、10文字未満なら10文字になるように末尾を空白で埋める
s = (s + new String(' ', 10)).Substring(0, 10);
```

### 条件に一致した場合に2つ目以降の値の前に特定値を付与して連結する
「2つ目以降の条件の場合はandを前につける」「文字列をカンマで連結する」など
→「リストに値を入れてセパレータを指定して結合する」
``` C#
var ss = new List<string>();
string s1 = "abc.txt";
if (!string.IsNullOrEmpty(s1))
{
    ss.Add(s1);
}
string s2 = "def.txt";
if (!string.IsNullOrEmpty(s2))
{
    ss.Add(s2);
}
string s = string.Join(", ", ss);
```
- where 条件で and を付ける/付けないの処理については、最初の条件を「1 = 1」にして、以降の条件には必ず「and」を付けるという手もあります。
- セパレータの値をわざわざ定数にする必要もないので、極力、セパレータの記載が少ない書き方にしました。


## イマドキの書き方

### null だったらデフォルト値を設定する
``` C#
object? o = null;
string s = o?.ToString() ?? "";

int? i = null;
i = i ?? 0;
```
- o? の部分は、o が null だった場合に後続のメソッドは処理されずにnullを返します。
- ?? の部分は 前部分が null だった場合の 後部分を返します。 
- 空文字変換以外にも使えるので応用範囲は高いです。

### WHERE や IN の条件判定式
``` C#
string s = "a";
if (s is "a" or "b")
{
    // s が "a" もしくは "b" の場合
}

int i = 3;
if (i is >= 1 and <= 10)
{
    // i が 1 以上 10 以下 の場合
}
```

## おわりに

「この書き方は、このバージョンからできるよ」「このバージョン以降ならもっとシンプルに書ける」「他にこんなもある」とかあれば、ぜひコメントください。

追記：
一つずつへのお礼コメントは省略させていただいていますが、コメントくださった皆様ありがとうございます。本文にもフィードバックさせていただきます。
SharePoint Webhook検証(1): Webhook作成＆通知フロー

### はじめに

SharePointでドキュメントが更新されたら、すぐ検知し特定アクションを行いたい場合があります。
Webhookの仕組みを用いて、SharePointにイベントトリガーを設定し、イベント通知するフローを、
シーケンス図を使って理解してみました。

### Webhook(ウェブフック)とは

- Webアプリケーションで特定のイベントが発生したら別のWebアプリケーションに通知を発行する仕組み
- Web開発でカスタムコールバックを用いてWebアプリケーションの動作を追加または変更するための方法
- リクエストは、HTTP POSTリクエストとして行われる
- フォーマットには通常JSONが利用される

### SharePoint Webhookとは

※ 引用元: https://learn.microsoft.com/ja-jp/sharepoint/dev/apis/webhooks/overview-sharepoint-webhooks

- SharePointで発生した特定イベントの通知を受け取るための仕組み
- イベントがトリガーされると、SharePointからHTTP POSTペイロードが送信される
- Webhookは標準のHTTP サービス(Web API)で、簡単に使用することができる
- WebhookはSharePointリストアイテムに対してのみ有効
    - SharePointリストやドキュメントライブラリのリストアイテムの変更イベントを扱う 

### まずは、Webhook作成フロー

```plantuml
@startuml

actor "管理者" as admin #lightskyblue
control "Webhookレシーバー" as recv #lightgreen
participant "SharePoint" as sp #hotpink

|||
activate admin
admin -> admin : サブスクリプション作成に必要な情報を用意します
|||
admin -> sp : Header:\n "Content-Type":"application-json"\nBody:\n{\n "changeType":"updated",\n "resource":"対象リソース",\n "notificationUrl":"通知先URL",\n "expirationDateTime":"有効期限(最大6ヶ月)",\n "clientState":"検証文字列"\n}\nHTTP POST リクエスト(サブスクリプションを作成したいです)
deactivate admin
|||
activate sp
sp -> recv : Query Parameter:validationToken={ランダム文字列}\nHTTP POST リクエスト(検証トークンを送ります)
deactivate sp
|||
activate recv
recv --> sp : Header:"Content-Type":"text-plain"\nPayload:{validationTokenの値}\nHTTP/1.1 200 レスポンス(5秒未満で同じ検証トークンを返します)
deactivate recv
|||
activate sp
sp --> admin : Payload:\n{\n "id":"サブスクリプションID",\n "changeType":"updated",\n "resource":"対象リソース",\n "notificationUrl":"通知先URL",\n "expirationDateTime":"有効期限(最大6ヶ月)",\n "clientState":"検証文字列"\n}\nHTTP/1.1 201 レスポンス(サブスクリプションを作成しました)
deactivate sp
@enduml
```

### つぎは、Webhook通知フロー

```plantuml
@startuml

actor "ユーザ" as user #lightpink
actor "管理者" as admin #lightskyblue
control "Webhookレシーバー" as recv #lightgreen
participant "SharePoint" as sp #hotpink
|||
activate user
user -> sp : SharePointのドキュメントライブラリのドキュメントを更新します
deactivate user
|||
activate sp
sp -> recv : Header:\n "Content-Type":"application-json"\nBody:\n{\n "subscriptionId":"サブスクリプションID",\n"changeType":"updated",\n "resource":"対象リソース",\n "notificationUrl":"通知先URL",\n "expirationDateTime":"有効期限(最大6ヶ月)",\n "clientState":"検証文字列"\n}\nHTTP POST リクエスト(ドキュメントが更新されました、通知を送ります)
deactivate sp
|||
activate recv
recv --> sp : HTTP/1.1 200 レスポンス(5秒未満で通知受け取りましたと返事)
deactivate recv
recv -> admin : Webhook変更通知が管理者に届く
activate admin
admin -> admin : 変更通知に対して、必要なアクションを行います
|||
@enduml
```

### おわりに
SharePointのWebhook仕組みをシーケンス図で理解しました。
次回は、Webhookレシーバーの設定方法を検証してみます。
お楽しみに。
プログラムでDatabricksワークスペースのファイルを操作する

[Programmatically interact with Workspace Files \| Databricks on AWS](https://docs.databricks.com/files/workspace-interact.html) [2022/12/21時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

Databricks Reposに格納されている任意のファイルをプログラムで操作することができます。これによって、以下のようなタスクを行えるようになります。

- ノートブックやコードと一緒に小規模なデータファイルを格納する。
- Gitと同期されるディレクトリにログファイルを書き込む。
- 相対パスを用いてモジュールをインポートする。
- 環境設定ファイルを作成、修正する。
- ノートブックから出力を書き込む。
- Tensorboardのようなライブラリの実行結果を書き込む。

Databricksランタイム8.4以降において、Databricks Reposを用いてワークスペースファイル(Workspace File)の読み込み、インポートが可能となります。Databricksランタイム11.2以降において、プログラムからワークスペースファイルを作成、編集、削除することができます。

:::note
**注意**
ワークスペースファイルへの書き込みを無効化するには、環境変数`WSFS_ENABLE_WRITE_SUPPORT=false`をクラスターに設定します。詳細は[環境変数](https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)をご覧ください。
:::

# ワークスペースファイルからのデータ読み込み

ノートブックのコードから`.csv`、`.json`のような小規模なデータファイルからプログラムを用いて読み込みを行うことができます。以下の例では、プロジェクトのrepoのルートからの相対パス`/data `に格納されているファイルにクエリーを行うためにPandasを使用しています。

```py:Python
import pandas as pd
df = pd.read_csv("./data/winequality-red.csv")
df
```

データファイルの読み込みにSparkを使用することもできます。Sparkには完全修飾パスを指定しなくてはなりません。Reposのファイルでは、パス`file:/Workspace/Repos/<user_folder>/<repo_name>/file`を使用します。

ファイルの隣のドロップダウンメニューから絶対パス、あるいは相対パスをコピーすることができます。
![](https://docs.databricks.com/_images/file-drop-down.png)

以下の例では、フルパスを取得するためにどのように`{os.getcwd()}`を活用しているのかを示しています。

```py:Python
import os
spark.read.format("csv").load(f"file:{os.getcwd()}/my_data.csv")
```

Databricks上のファイルの詳細に関しては、[How to work with files on Databricks](https://docs.databricks.com/files/index.html)をご覧ください。

# プログラムによるファイルやディレクトリの作成、更新、削除

Databricksランタイム11.2以降では、Databricks Reposのワークスペースファイルを直接操作することができます。以下の例では、ファイルやディレクトリを作成、操作するために標準的なPythonパッケージを使用しています。

```py:Python
# Create a new directory

os.mkdir('dir1')

# Create a new file and write to it

with open('dir1/new_file.txt', "w") as f:
    f.write("new content")

# Append to a file

with open('dir1/new_file.txt', "a") as f:
    f.write(" continued")

# Delete a file

os.remove('dir1/new_file.txt')

# Delete a directory

os.rmdir('dir1')
```

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
Googleで検索するだけで使える便利なツールを見つけた


Googleで「カラーピッカー」で検索すると
https://www.google.com/search?q=カラーピッカー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/72df80b8-288d-e742-3ff0-b4db159a2f84.png)
みんなで遊ぼうGPT3スプレットシート実験室（クイズ生成呪文例

GPT3がGoogleスプレットシートで使えるのをハズってるのを見ながら「それChatGPTじゃないし！」とか「結果が間違ってるし！」とか心の叫びを上げてるみなさまこんにちは。ツッコミどころ満載ですよね。ChatGPTが出た直後にStackOverflowが嘘っぱちコードのアップを禁止したけど、カジュアルにスプレットシートでGPT3が使われる事で同じようなことが起こらないことを願いします。

さて、それはさておき、みんなで同じスプレットシートでGPT関数使えたらおもしろいんじゃないかと思ってシート作ってみました。よかったらイケてる呪文を晒してみてください。例としてクイズ生成呪文を書いときました。

https://docs.google.com/spreadsheets/d/11SGT4Tc5jnIpU3jiJb2jQhPsZSMm5lw9DMgtfPJir24/edit?usp=sharing

![GPT3の実験室 - Google スプレッドシート - Google Chrome 2023-01-28 16.29.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/47821b30-6075-e849-a054-8e7f82ffb7f5.png)

GPT関数の引き数は３つで

```
prompt	質問文
max_tokens	返答の最大文字数
temperature	返答の正確度。0にすると毎回同じ。1にすると変化が大きい。
```

となってます。


![GPT3の実験室 - Google スプレッドシート - Google Chrome 2023-01-28 16.30.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/5a76c7f7-874e-5b31-0378-a376b843bdaf.png)

```
=GPT("ごにょごにょ", 1000, 0.1)
```

みたいな感じでつかってください。

18ドルがなくなると終わります（キーの提供者がいたら続くのか？）

実装はこちらのサイトを参考にしました。スプレットシートの Apps Script という機能を使ってます。

https://liquidjumper.com/google-sheets/googlespreadsheet_connect_to_gpt_3

これだけだと temperature の設定がなかったので追加しました。

```js
const SECRET_KEY = "ここにopenaiのキーがはいるねん";
const MODEL_NAME = "text-davinci-003";

function GPT(prompt,max_tokens=30,temperature=0.1) {
    const url = "https://api.openai.com/v1/completions";
    const payload = {
        model: MODEL_NAME,
        prompt: prompt,
        temperature: temperature,
        max_tokens: max_tokens
    };

    const options = {
        contentType: "application/json",
        headers: {
            Authorization: "Bearer " + SECRET_KEY
        },
        payload: JSON.stringify(payload),
    };

    const res = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
    return res.choices[0].text.trim();
}
```

OpenAI の API はこっちに説明があります。

https://beta.openai.com/docs/api-reference/files
【Builtin web server】php -S 0.0.0.0:8000をマルチスレッドで並列処理【PHP_CLI_SERVER_WORKERS】


# PHP_CLI_SERVER_WORKERS=16 php -S localhost:8000
16スレッドで並列処理する場合
```bash
PHP_CLI_SERVER_WORKERS=16 php -S 0.0.0.0:8000
```

https://man.plustar.jp/php/features.commandline.webserver.html
github-profile-summary-cardsのGitHub Actionsではまった事と解決策

GitHubのプロフィールページにリポジトリのサマリーカードを生成する [github-profile-summary-cards
](https://github.com/vn7n24fzkq/github-profile-summary-cards)のGitHub Actionsの設定ではまったこととその解決策について

## 1. .github/workflows/profile-summary-cards.yml がpushできない
### エラー
```bash
 ! [remote rejected] feature-profile-summary-cards -> feature-profile-summary-cards (refusing to allow a Personal Access Token to create or update workflow `.github/workflows/profile-summary-cards.yml` without `workflow` scope)
error: failed to push some refs to 'https://github.com/AkioYokoyama/AkioYokoyama.git'
```
### 原因
Personal access tokens に workflowの権限がなかった。

### 解決策
1. [Settings > Developer settings > Personal access tokens > Tokens(classic)](https://github.com/settings/tokens) へアクセス。
2. Select scopes の workflow のチェックボックスを `ON` にする

## 2. GitHub Actionsが失敗する
### エラー
```bash
Run vn7n24fzkq/github-profile-summary-cards@release
  with:
    USERNAME: AkioYokoyama
    UTC_OFFSET: 9
  env:
    GITHUB_TOKEN: ***
Start...
Username: AkioYokoyama
UTC offset: 9
Remove old cards...
Creating ProfileDetailsCard...
Creating ReposPerLanguageCard...
Creating CommitsPerLanguageCard...
Creating StatsCard...
Creating ProductiveTimeCard...
Creating preview markdown...
Commit file...
Warning: Commit failed. Retry...
Warning: Commit failed. Retry...
Error: Error: git push 
  
 Invalid status code: 128
Error: git push 
```

### 原因
リポジトリの Workflow permissions に write権限がなかった
### 解決策
1. リポジトリのSettings > Actions > General へアクセス
1. Workflow permissions を `Read and write permissions` へ変更する
大きな整数の階乗の剰余を求める

### math.factorialを使う

pythonでは整数Nの階乗の剰余は以下のようにmath.factorialを使えば簡単に求まりますが、Nが大きくなると非常に大きな数を一旦生成するのであまり効率が良くありません。(計算量は$O(\frac{1}{2}n^2)$)

```python 
from math import factorial
M = 10**9+7
N = 10**6
print(N, factorial(N)%M)
# 1000000 641102369
```

### Nの階乗の素因数分解を求める

そこでまずNの階乗の素因数分解を行います。考え方は、例えば10の階乗の場合、2の倍数が5個、$2^2=4$の倍数が2個、$2^3=8$の倍数が1個、なので素因数2は計8個あることが分かります。これをN以下のすべての素数について行うとNの階乗の素因数分解が求まります。

```python 
from sympy import primerange
def fact2fct(n):   # nの階乗の素因数分解
  ret = dict()
  for p in primerange(2,n+1):
    ret[p], pp = 0, p
    while pp <= n:
      ret[p] += n // pp
      pp *= p
  return ret

N = 10
print(N, fact2fct(N))
#10 {2: 8, 3: 4, 5: 2, 7: 1}
```

### 各素因数に対してpow関数で剰余計算を行う

素因数分解の形になればpow関数が使えます。(計算量はほぼ$O(n)$)

```python
def factmod(fct,M):
  ret = 1
  for p in fct.keys():
    ret *= pow(p,fct[p], M)
    ret %= M
  return ret

M = 10**9+7
n = 10**6
stime = time.time()
print(n, factmod(fact2fct(n), M))
#1000000 641102369
```

### (応用) １からNまでの数の最小公倍数の素因数分解

この考え方を使うと１からNまでの数の最小公倍数の素因数分解も同様に実装できます。

```python 
from sympy import primerange
def lcmall(n):   # 1からnのすべての数の最小公倍数の素因数分解
  ret = dict()
  for p in primerange(2,n+1):
    pp, i = p, 0
    while pp <= n:
      pp *= p
      i += 1
    ret[p] = i
N = 10
print(N, lcmall(N))
# 10 {2: 3, 3: 2, 5: 1, 7: 1}
```

（開発環境：Google Colab）

この考え方は以下のProject Eulerの問題を解くのに役に立ちます。

* Problem 429: Sum of squares of unitary divisors.
* Problem 772: Balanceable k-bounded partitions.
M5: VSCode で UIFlow MicroPython による開発

M5Stack に UIFlow が動作するファームウェアを焼くことで、UIFlow のサイトでビジュアルプログラミングするほか、MicroPython によるプログラムを動作させることができます。

- [MicroPython](https://docs.micropython.org/en/latest/index.html)
- [UIFlow-Code - GitHub](https://github.com/m5stack/UIFlow-Code/wiki) (UIFlow ファームウェアに含まれる MicroPython でハードウェアを制御するライブラリ)

※UIFlow に含まれる MicroPython は [M5Stack Micropython Base Lobo MicroPython - GitHub](https://github.com/m5stack/M5Stack_MicroPython) がベースになっているようなのですが、`buttonA` でなく `btnA` という名前になっているので注意。

## Prerequisite

- [M5Stack](https://m5stack.com/) デバイス
- シリアルドライバー ([公式のダウンロードページ](https://docs.m5stack.com/en/download))
- [M5Burner](http://docs.m5stack.com/) (M5Stack デバイスに UIFlow ファームウェアを焼くプログラム)
- [Visual Studio Code](https://code.visualstudio.com/) + [vscode-m5stack-mpy](https://marketplace.visualstudio.com/items?itemName=curdeveryday.vscode-m5stack-mpy)

## Prepare

 1. PC にシリアルドライバーをインストールして接続する

 1. M5Burner を使って M5Stack に UIFlow ファームウェアを焼く

    ![Burn](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2023/01/08/e0193c5a-ab1c-42e8-836a-717d500223a5.png)

 1. UIFlow を USB モードに設定する (設定は本体上でおこなうこともできます。)

   ![Configurate](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2023/01/08/511ee8a3-aed3-4e8c-bb5f-7e50e406dd8b.png)

## Howto

[vscode-m5stack-mpy](https://marketplace.visualstudio.com/items?itemName=curdeveryday.vscode-m5stack-mpy) を参考。

 1. 「Add M5Stack」で、M5Stack のシリアルポートを選択して接続
 1. 「M5STACK DEVICE」に M5Paper 内のファイル一覧が表示されるので、適当な場所にプログラムファイルを保存して「Run in M5Stack」

## Sample

### Hello world

M5Stack の場合

```python
from m5stack import lcd

lcd.clear()
lcd.setColor(lcd.WHITE)
lcd.setCursor(0, 0)
lcd.print("Hello, M5Stack")
```

M5Paper の場合 (E Ink ディスプレイのためか、若干方法が異なるようです？)

```python
from m5stack import lcd

lcd.fillScreen(15)
lcd.font(lcd.FONT_DejaVu24)
lcd.setTextColor(0, 15)
lcd.text(30, 450, "Hello, M5Paper")
lcd.show()
```

### M5Stack Core のハードウェアボタン(A/B/C)からの入力

`buttonA` でなく `btnA` という名前になっているので注意。

```python
from m5stack import btnA

def on_wasPressed():
    lcd.print("Pressed")

btnA.wasPressed(on_wasPressed)
```

### 温湿度センサー(SHT30)から値を取得する

[ENV II Unit (SHT30+BMP280)](https://shop.m5stack.com/products/env-ii-unit) を接続します。M5Paper には SHT30 が内蔵されていますが、外気温の計測用途ではないと思います。

```python
from machine import I2C, Pin
from sht30 import SHT30

def get_temp_hum():
    i2c = I2C(freq=100000, scl=Pin(22), sda=Pin(21))
    sht30_sensor = SHT30(i2c)
    return sht30_sensor.measure()
```

温度の単位は℃です。

### 気圧センサー(BMP280)から値を取得する

```python
from machine import I2C, Pin
from bmp280 import BMP280

def get_pressure():
    i2c = I2C(freq=100000, scl=Pin(22), sda=Pin(21))
    bmp280_sensor = BMP280(i2c)
    return bmp280_sensor.values[1]
```

値の単位は hPa です。
M5Stack: 環境センサーから計測値を取得する

M5Stack で、各種環境センサーから計測値を取得する方法を整理しました。

使用したセンサーは以下のものです。

- [ENV III Unit with Temperature Humidity Air Pressure Sensor (SHT30+QMP6988)](https://docs.m5stack.com/en/unit/envIII)
- [ENV II Unit with Temperature Humidity Environment Sensor (SHT30+BMP280)](https://docs.m5stack.com/en/unit/envII)
- [TVOC/eCO2 Gas Sensor Unit (SGP30)](https://shop.m5stack.com/products/tvoc-eco2-gas-unit-sgp30)

これらのセンサーは I2C ポート(Port.A) に接続する必要があります。[I2C 拡張ハブユニット](https://www.switch-science.com/products/5696) を使用することで、複数のセンサーを併用することもできます。

## ENV III: 温湿度センサー (SHT30) / 気圧センサー (QMP6988)

ENV III に実装されている SHT30 から温度・湿度、QMP6988 から気圧を取得します。SHT30 は M5Paper では内蔵されています。(本体内部にあるので外気温の計測には適さないと思いますが。)

### 使用したライブラリ

- [M5Unit-ENV](https://registry.platformio.org/libraries/m5stack/M5Unit-ENV) by M5Stack
  - ソース) [M5Unit-ENV - GitHub](https://github.com/m5stack/M5Unit-ENV)
  - サンプル) [M5Unit-ENV/examples/ - GitHub](https://github.com/m5stack/M5Unit-ENV/tree/master/examples)

### 実装例

```c
#include <SHT3X.h>

void getSHT30()
{
  SHT3X sht30;
  if (sht30.get() != 0) return;
  float temp = sht30.cTemp; // 温度 (℃)
  float humidity = sht30.humidity; // 湿度 (%)
}

void getQMP6988()
{
  QMP6988 qmp6988;
  if (!qmp6988.init()) return;
  float pressure = qmp6988.calcPressure() / 100; // 気圧 (hPa)
}
```

## ENV II: 気圧センサー (BMP280)

ENV II に実装されている BMP280 から、温度・気圧を取得します。SHT30 は ENV III と同様です。

### 使用したライブラリ

- [adafruit/Adafruit BMP280 Library](https://registry.platformio.org/libraries/adafruit/Adafruit%20BMP280%20Library) by Adafruit
  - ソース) [Adafruit BMP280 Driver - GitHub](https://github.com/adafruit/Adafruit_BMP280_Library)
  - サンプル) [Adafruit_BMP280_Library/examples/ - GitHub](https://github.com/adafruit/Adafruit_BMP280_Library/tree/master/examples)

### 実装例

```c
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>

void getBMP280()
{
  Adafruit_BMP280 bme;
  if (!bme.begin(0x76)) return;
  float temp = bme.readTemperature(); // 気温 (℃)
  float pressure = bme.readPressure() / 100; // 気圧 (hPa)
}
```

## ガスセンサー (SGP30)

SGP30 から、値を取得します。

### 使用したライブラリ

- [adafruit/Adafruit SGP30 Sensor](https://registry.platformio.org/libraries/adafruit/Adafruit%20SGP30%20Sensor) by Adafruit
  - ソース) [Adafruit SGP30 Gas / Air Quality I2C sensor - GitHub](https://github.com/adafruit/Adafruit_SGP30)
  - サンプル) [Adafruit_SGP30/examples/sgp30test/ - GitHub](https://github.com/adafruit/Adafruit_SGP30/tree/master/examples/sgp30test)

### 実装例

```c
#include <Adafruit_SGP30.h>
#include <Adafruit_Sensor.h>

void getSGP30()
{
  Adafruit_SGP30 sgp;
  gpe.begin();
  if (!gpe.IAQmeasure()) return;
  float tvoc = sgp.TVOC; // TVOC (Total Volatile Organic) : 総揮発性有機化合物量 (ppb = 0.000000001%)
  float eCO2 = sgp.eCO2; // 二酸化炭素濃度 (ppm = 0.000001%)
}
```
|2x+1|−x≦8「22年 茨城大 後 工2 (3)」をWolframAlpha とsympyで計算してみたい。

オリジナル

https://kamelink.com/blog/2022/12/11/1-3-22-ibarakidai-kou-kou-2-3/

上と同じです。大学入試数学問題集成＞

https://mathexamtest.web.fc2.com/2022/202210161/2022101610200mj.html#top-0212



# 計算

標準的な場合分けをしないで、計算しました。(-1/2)からの距離です。
答えは一致しました。

```
｜2x+ 1｜−     x≦8
｜x+1/2｜+(1/2)x≦4
｜x-(-1/2)｜    ≦4+(1/2)x
-1/2-(4+(1/2)x)≦x≦-1/2+(4+(1/2)x)

-1/2-(4+(1/2)x)≦x,      x≦-1/2+(4+(1/2)x)
-1/2-4         ≦3/2x,1/2x≦-1/2+4
             -3≦x,      x≦7
```


# wolframで

https://www.wolframalpha.com/input?i=%7C2x%2B1%7C-x%E2%89%A68&lang=ja

# sympyで
勉強中
AppleSilicon搭載のmacOSでFedora WorkstationのUSBブートメモリを作成する方法

# 前置き

Fedora公式では、「Fedora Media Writer」を用意してくれてはいるが、執筆時点ではRosetta2が必要となっており、なるべくネイティブで動かしたいと思った。

# やり方

1. [Fedora公式サイト](https://getfedora.org/en/workstation/)から、Fedora WorkstationのISOファイルをダウンロードする。
2. Mac端末にUSBメモリを接続させる。(執筆時点では、2GB以上が必要)
3. diskutilコマンドで、USBメモリのパスを確認する。
   ```bash
   diskutil list

   # 以下は、実行結果。今回では、/dev/disk4 (external, physical)が該当する。
   /dev/disk0 (internal, physical):
      #:                       TYPE NAME                    SIZE       IDENTIFIER
      0:      GUID_partition_scheme                        *500.3 GB   disk0
      1:             Apple_APFS_ISC Container disk1         524.3 MB   disk0s1
      2:                 Apple_APFS Container disk3         494.4 GB   disk0s2
      3:        Apple_APFS_Recovery Container disk2         5.4 GB     disk0s3

   /dev/disk3 (synthesized):
      #:                       TYPE NAME                    SIZE       IDENTIFIER
      0:      APFS Container Scheme -                      +494.4 GB   disk3
                                    Physical Store disk0s2
      1:                APFS Volume Macintosh HD - Data     98.4 GB    disk3s1
      2:                APFS Volume Macintosh HD            8.9 GB     disk3s3
      3:              APFS Snapshot com.apple.os.update-... 8.9 GB     disk3s3s1
      4:                APFS Volume Preboot                 4.8 GB     disk3s4
      5:                APFS Volume Recovery                784.3 MB   disk3s5
      6:                APFS Volume VM                      20.5 KB    disk3s6

   /dev/disk4 (external, physical):
      #:                       TYPE NAME                    SIZE       IDENTIFIER
      0:      GUID_partition_scheme                        *250.1 GB   disk4
      1:                        EFI EFI                     209.7 MB   disk4s1
      2:       Microsoft Basic Data USB                     249.8 GB   disk4s2
   
   ```

4. 下記コマンドを実行し、USBメモリをフォーマットする。(データが消えるので、消しても良いか確認して実施)

   ```bash
   diskutil unmountDisk /dev/disk4 # フォーマット前にアンマウントを行う
   diskutil eraseDisk MS-DOS FEDORA /dev/disk4 # MS-DOS(いわゆるFAT)
   ```

5. ダウンロードしたFedora WorkstationのISOファイルを、USBに書き込む。

   ```bash
   diskutil unmountDisk /dev/disk4 # 書き込み前にアンマウントを行う
   # /dev/diskX と /dev/rdiskX の違いは、参考文献を拝読されたし。
   sudo dd if=Fedora-Workstation-Live-x86_64-37-1.7.iso of=/dev/rdisk4 bs=8M
   ```

# 参考文献

- [Fedora 公式ドキュメント](https://docs.fedoraproject.org/en-US/quick-docs/creating-and-using-a-live-installation-image/index.html)
- [ddコマンドにおける/dev/diskXと/dev/rdiskXの違い](https://www.junk-works.science/disk-and-rdisk/)
- [macOSにおけるdiskutilの使い方](https://qiita.com/sira/items/0e7cc588276b8bec35ac)
New Relic: NerdGraph API を使ってデータを取得する

New Relic に送信したデータは、[NerdGraph API](https://docs.newrelic.com/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph/) という GraphQL を採用した API で参照することができます。こちらは参照用で、データ送信用とは区別されているようです。

## API へのアクセス例

GraphQL API に対する一般的な方法になりますが、参考まで。

### Altair GraphQL Client を使ってアクセスする

 1. Chrome に [Altair GraphQL Client](https://chrome.google.com/webstore/detail/altair-graphql-client/flnheeellpciglgpaodhkhmapeljopja?hl=en) 拡張機能をインストールする
 1. Altair GraphQL Client を開き、URL に `https://api.newrelic.com/graphql` と入力する
 1. 左のナビゲーション内にある「Set Headers」アイコンをクリックし、以下のヘッダを追加する
    - Header key: `Api-Key`
    - Header value: (API キーを入力)

Query ペインにクエリを入力して「Send Request」でリクエスト、「Docs」を押すと API ドキュメントを参照することができます。

### Curl でアクセスする

以下のようにします。

```shell
NEW_RELIC_USER_KEY=(API キー)
QUERY="{requestContext { userId apiKey }}"
curl -X POST "https://api.newrelic.com/graphql" \
    -H "Content-Type: application/json" \
    -H "Api-Key: ${NEW_RELIC_USER_KEY}" \
    -d "{\"query\":\"${QUERY}\"}"
```

## クエリ例

上記 query の部分に、GraphQL としてのクエリを指定します。

### アカウント情報を取得

```json
{
  actor {
    organization {
      accountManagement {
        managedAccounts {
          name
          id
          regionCode
        }
      }
    }
  }
}
```

![アカウント情報を取得](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2023/01/28/aebbbe3b-a6a9-4005-a85d-c77381ef1f7d.png)

### 最新の値を取得

アカウント ID には、上で取得した `id` を指定します。

```json
{
   actor {
      account(id: (アカウントID)) {
         nrql(query: "SELECT latest(temperature) AS temperature FROM Metric WHERE name = 'M5Stack-test'") {
            results
         }
      }
   }
}
```

![最新の値を取得](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2023/01/28/ea4aab30-de88-4e6b-abb0-df6aab6ba792.png)

### チャートの画像を取得

```json
{
   actor {
      account(id: (アカウントID)) {
         nrql(query: "SELECT min(temperature), max(temperature) FROM Metric WHERE name = 'M5Stack-test' SINCE 1 DAY AGO TIMESERIES") {
            staticChartUrl(width: 640, height: 320)
         }
      }
   }
}
```

![チャートの画像を取得](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2023/01/28/bb7620e2-a95b-4fee-a6bb-f4aa1ca5c47f.png)
SQLAlchemy×Alembicでマイグレーション

# はじめに
よくFastAPIのマイグレーションしようとしたときに、接続先を
`sqlalchemy.url = mysql+pymysql://root:root-password@host:port/database`
こんな感じにすると非同期とか考えなくていいらしく正常に行くが、
接続先を下のような感じにすると、asyncが～とかawait～がとか怒られうまくいかない。
`mysql+asyncmy://root:root-password@host:port/database`

日本語で検索しても今回のように`asyncmy`の場合の情報が出てこなかったので参考までにどうぞ・・・

### 流れ
※ライブラリのインストール後の流れになります。。。
```
alembic init migrations
```
上記コマンドを対象のapp直下で実行（場所はどこでもいいはず・・・）
すると下のような感じになります。
```
app
├── migrations
│   ├── versions
│   ├── env.py
│   ├── README
│   └── script.py.mako
└── alembic.ini
```

そうしたら、`env.py`を修正してコマンドを実行したらOK

#### コード
```python:env.py
import asyncio
from logging.config import fileConfig

from alembic import context
from sqlalchemy import engine_from_config, pool
from sqlalchemy.ext.asyncio import AsyncEngine

config = context.config
config.set_main_option("sqlalchemy.url", "mysql+asyncmy://root:root-password@host:port/database")

fileConfig(config.config_file_name)

# ここに作成したModelクラスをimport
# from models.manager import Sample

target_metadata = Base.metadata

def do_run_migrations(connection):
    context.configure(connection=connection, target_metadata=target_metadata)
    with context.begin_transaction():
        context.run_migrations()

async def run_migrations_online():
    connectable = AsyncEngine(
        engine_from_config(
            config.get_section(config.config_ini_section),
            prefix="sqlalchemy.",
            poolclass=pool.NullPool,
            future=True,
        )
    )
    async with connectable.connect() as connection:
        await connection.run_sync(do_run_migrations)

    await connectable.dispose()

if context.is_offline_mode():
    run_migrations_offline()
else:
    asyncio.run(run_migrations_online())
```

#### 実行コマンド
※今回はDockerで環境構築しているので、コンテナ内に入って実行

```
docker compose exec {app名} alembic revision --autogenerate -m "create tables"
docker compose exec {app名} alembic upgrade head
```
Cannot find module 'firebase-functions/lib/encoder' from ...というエラーが出た話

`firebase-functions-test`を使ってテストを実行しようとした結果、次のようなエラーが発生しました。

```shell
Cannot find module 'firebase-functions/lib/encoder' from 'node_modules/firebase-functions-test/lib/providers/firestore.js'
```

色々調べてみると、次のような投稿が見つかりました。

> After stumbling on Farid's suggestion for this problem, I realized that, for some reason, npm i firebase-functions-test does not install the latest version of the module.
> Try npm i firebase-functions-test@latest.

https://stackoverflow.com/questions/72332941/cannot-find-module-firebase-functions-lib-encoder-from-node-modules-firebase

しかし、`npm install --save-dev firebase-functions-test@latest`を実行しても次のようなエラーが発生しました。

```shell
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: functions@undefined
npm ERR! Found: firebase-functions@3.24.1
npm ERR! node_modules/firebase-functions
npm ERR!   firebase-functions@"^3.18.0" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer firebase-functions@"^4.0.0" from firebase-functions-test@3.0.0
npm ERR! node_modules/firebase-functions-test
npm ERR!   dev firebase-functions-test@"3.0.0" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
...
```

最新バージョンの`firebase-functions-test`をインストールするためには、`firebase-functions`のバージョン自体も最新版にする必要があるようです。

それでは、`firebase-functions`と`firebase-functions-test`のバージョンを最新にします。

もし現在、僕と同じように`3.x.x`系の`firebase-functions`を使っている場合は新しい環境を要してから最新版にアップデートして正しく動作するかの検証を行なってからコミットすることをお勧めします。

- ローカルにリポジトリを新しいディレクトリ名を使ってクローンする
- `functions`ディレクトリ内で`npm install`を実行す
- `npm instal firebase-functions@latest`を実行する
- `npm install --save-dev firebase-functions-test@latest`を実行する


この手順を踏んだ結果、バージョンの内容は次のようになりました。

| パッケージ | 古いバージョン | 新しいバージョン |
|---|---|---|
| firebase-functions | "^3.18.0" | "^4.2.0" |
| firebase-functions-test | "^0.2.3" | "^3.0.0" |

そして、テストを実行した結果、上記で発生したエラーは発生しなくなりました。

念の為、エミュレーターを起動して今まで実行できるかを検証したところ、無事起動しました。

```shell
npm run build && firebase emulators:start --only firestore,auth,functions,storage
```
データエクスプロラトリー　データの全体像を把握する

# はじめに
今日学んだことの備忘録
内容については目次を参考にしてほしい

# 本文
## 全体像　データエクスプロラトリー
* データを分析する
* データの特徴を抑える
* 本格的な分析に入る前に概要を把握するイメージ
* やったらいいこと
    * 記述統計
    * グループ分け
    * 相関
    * カイ二乗検定
* 

# memo
+ 言語を切り替えるのが面倒くさい
    + Courseraは英語、こっちは日本語だから

# 参考文献
Coursera IBM data Science course, analysis data with python
HTML/CSS　項目の横並べ

ホームページを作るうえで必ず出る項目の横並べ

よく使われるコードを記載します

<h1> flexbox

これが一番良い

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="poZZjVP" data-user="spite400k" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/spite400k/pen/poZZjVP">
  Untitled</a> by はーと (<a href="https://codepen.io/spite400k">@spite400k</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

<h1> float

これが一番不便。。。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="KKBBdRW" data-user="spite400k" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/spite400k/pen/KKBBdRW">
  Untitled</a> by はーと (<a href="https://codepen.io/spite400k">@spite400k</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

+ floatを指定した要素の親要素に高さ反映されなくなってしまう
    →heightを50pxに指定
+ 幅が大きくなって３つ目が次行に回される
    →子要素にbox-sizing: border-boxを指定して、borderを含めて幅計算するようにする
　　　ただしmarginは考慮されないため、marginを減らすか、widthの33%→30%に減らす必要あり
 
<h1> display:table-cell


<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="QWBBjBd" data-user="spite400k" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/spite400k/pen/QWBBjBd">
  Untitled</a> by はーと (<a href="https://codepen.io/spite400k">@spite400k</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


+ display: table-cellの場合、marginが効かない
　→「border-collapse」「border-spacing」で間隔をあける
インペインティングモデル  LBAM_Pytorch

# 画像の一部を修復するモデル
![birdimage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/23790858-595b-ef81-bbb2-3c250df01ebb.jpeg)![birdmask.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/fc3e30e3-b9d2-8e30-2c80-af684419ebed.jpeg)![r.png (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/567f91f7-aa31-971b-7762-2448743cb6e4.png)

https://github.com/Vious/LBAM_Pytorch

# 使い方

リポジトリからPreTrainedモデルをダウンロードして入力とマスクと出力先を指定して実行します。

```bash
git clone https://github.com/Vious/LBAM_Pytorch.git
cd LBAM_Pytorch
pip install --upgrade gdown
gdown https://drive.google.com/u/0/uc?id=1blybD3ptixSmYI01lV_pWwRcO_dfYHPp

python test.py --input input.png --mask mask.png --output result.png --pretrain LBAM_NoBN_Places10Classes.pth
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

機械学習、ARアプリ（Web/iOS）を作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
20230129_python_スクレイピング

# はじめに
昨日呼んだ本の備忘録
加藤耕太さん「Python クローリング＆スクレイピング」

# 本文
* Requests
    * 内容をゲットしてくる
    * 基本的な情報を閲覧することが出来る
* パース
    * 人間が扱いやすいように情報を変換する
* HTTPで受信する時、内容自体はバイトで表される
* 文字コードを出来たら取得しよう
    * タグやchsetを確認したいね
* スクレイピングの流れ
    * 情報を取ってくる
    * 情報をパースする
    * スクレイピング　要は抜き出すことをする
    * 保存する
* HTMLのスクレイピング
    * Beautiful Soup
    * pyquery
        * jQuery的な感じで操作できる
* XMLのスクレイピング
    * lxml
* RSSのスクレイピング
    * feedparser
* データベースへの保存
    * いろいろあるから保存の仕方や接続の方法はその都度調べよう
    * 接続－処理ー切断　この流れなようだ
* 

# memo
* プログラミングの勉強をするとき、頭の中にインデックス（索引）を作るようにして勉強するって言っていた人がいた。
* それって、頭の中に「問題の解法」を記憶するってことじゃないかな。
* 問題の解法　＝　方針

# 参考文献
加藤耕太さん「Python クローリング＆スクレイピング」
TOPPERSカーネルのコンフィギュレータをHomebrew最新版のBoostでビルドする

[TOPPERSカーネルをビルドするときに必要なコンフィギュレータ(バージョン1.9.6)](https://www.toppers.jp/cfg.html)をApple Silicon Macでビルドしたときに，つまづいてしまい，@mitsu48さんに助けていただきました．

https://github.com/toppers/users-forum/discussions/98

コンフィギュレータのビルドにはBoostを必要とするのですが，今回私はHomebrewでインストール済みのBoostを使おうとしたところ，Boost 1.67.0 以降では`boost/utility.hpp`に`boost::next`と`boost::prior`が含まれておらず，`boost/next_prior.hpp`をインクルードする必要があるというのが原因でした．

他にも，C++11でコンパイルするというオプションをつける必要があります．

というわけで，手順をまとめてみました．

1. `cfg-1.9.6.tar.gz` (2023年1月現在最新版)を　https://www.toppers.jp/cfg.html からダウンロード
1. `tar xvfz cfg-1.9.6.tar.gz`
1. `cd cfg`
1. `./configure`の改行コードを`CR/LF`から`LF`に変更
    1. ファイルの文字コードがISO-8859-1である点に注意
1. `./configure`の31行目と48行目を`configure`の`diff`のように変更
1. `./configure`を実行
1. `Makefile.config`の末尾の`OPTIONS=`の部分を`OPTIONS="-std=c++11"`に変更
1. `toppers/cpp.hpp`の47行目に`#include <boost/next_prior.hpp>`を追記(`toppers/cpp.hpp`を参考にしてください)
1. `toppers/text.hpp`の57行目に`#include <boost/next_prior.hpp>`を追記(`toppers/text.hpp`を参考にしてください)
1. `make -j$(nproc)`

これでビルドできると思います．

```diff:configure
@@ -28,7 +28,7 @@
 done
 
 # Boost C++ Libraries?Υإå??ե????뤬????ǥ??쥯?ȥ?򥵡???
-for dir in $include_path "/usr/local/include" "/opt/local/include" "/opt/include" "/usr/include" "/mingw/include"
+for dir in $include_path "/usr/local/include" "/opt/local/include" "/opt/include" "/usr/include" "/mingw/include" "`brew --prefix boost`/include"
 do
 	ls $dir/boost* 2> /dev/null > /dev/null
 	if test $? -eq 0
@@ -45,7 +45,7 @@
 done
 
 # Boost C++ Libraries?Υ饤?֥??ե????뤬????ǥ??쥯?ȥ?򥵡???
-for dir in $library_path "/usr/local/lib" "/opt/local/lib" "/opt/lib" "/usr/lib" "/lib" "/mingw/lib"
+for dir in $library_path "/usr/local/lib" "/opt/local/lib" "/opt/lib" "/usr/lib" "/lib" "/mingw/lib" "`brew --prefix boost`/lib"
 do
 	ls $dir/libboost* 2> /dev/null > /dev/null
 	if test $? -eq 0
```

```diff:toppers/cpp.hpp
@@ -44,6 +44,7 @@
 #include "toppers/codeset.hpp"
 #include "toppers/diagnostics.hpp"
 #include <boost/utility.hpp>
+#include <boost/next_prior.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/filesystem/operations.hpp>
 #include <boost/filesystem/exception.hpp>
```

```diff:toppers/text.hpp
@@ -54,6 +54,7 @@
 #include "toppers/text_line.hpp"
 #include "toppers/misc.hpp"
 #include <boost/utility.hpp>
+#include <boost/next_prior.hpp>
 #include <boost/iterator/iterator_facade.hpp>
 #include <boost/format.hpp>
```
MLMultiArrayをconcatする

# torch.catを代替
機械学習モデルの入力の前処理で二つのtensorを任意の軸に沿って連結することがある。

```python
import torch
a = torch.ones(1,3,512,512)
b = torch.ones(1,1,512,512)
c = torch.cat((a,b),dim=1)
print(c.shape)
# > torch.Size([1, 4, 512, 512])
```
CoreMLでモデルを使う際にこれをSwiftで代替したい。

# MLMultiArrayのconcatenateで可能

CoreMLのMLMultiArrayでconcatenate初期化がある。

```swift
let a = try MLMultiArray(shape: [1, 3, 512, 512], dataType: .int32)
let b = try MLMultiArray(shape: [1, 1, 512, 512], dataType: .int32)

let c = MLMultiArray(concatenating: [a, b],
                               axis: 1,
                               dataType: .int32)

print(c.shape)
// > [1,4,512,512]
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

機械学習、ARアプリ（Web/iOS）を作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
picoCTF Writeup picoGym Practice Challenges Mind your Ps and Qs (注意<spoiler>)

素因数分解は
http://factordb.com/index.php?id=1100000002524332351
から
~~~
# solve.py
from Crypto.Util.number import *
p = 1899107986527483535344517113948531328331
q = 674357869540600933870145899564746495319033
c= 62324783949134119159408816513334912534343517300880137691662780895409992760262021
#n= 1280678415822214057864524798453297819181910621573945477544758171055968245116423923
e= 65537
n = p * q
phi = (p - 1) * (q - 1)
d = pow(e, -1, phi)
print(long_to_bytes(pow(c, d, n)))
~~~
Unity "XXX" is missing the class attribute 'ExtensionOfNativeClass'!

# 現象
ビルド時に上記のエラーが発生する

# 解決
プレハブにMonoBehaviourを継承してないスクリプトがアタッチされていたので消す

# 補足
ググって見ると
「シーン上に」MonoBehaviourを継承したスクリプトをアタッチしたゲームオブジェクトがあり
そのアタッチされたスクリプトがMonoBehaviourを継承しなく変更した場合
それを取り除けばエラーが解決する。
と書いているが
シーン上に限らない。プロジェクト上にMonoBehaviourを継承していないプレハブがあってもビルド時にエラーになる