OmniAICreator/Qiita-1.07M huggingface dataset:
プロキシ関係のトラブル

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)




+ [LWC プロキシ関係のエラー reason: connect ETIMEDOUT](https://qiita.com/Keiji_otsubo/items/b57f8f9e885046d379c4)
+ [Warning: Deprecated environment variable: SFDX_JSON_TO_STDOUT. Please use SF_JSON_TO_STDOUT instead.](https://qiita.com/Keiji_otsubo/items/84d0733749d63597ad7b)
+ [403 エラー](https://qiita.com/Keiji_otsubo/items/662ea2866fb6dc43d31c)

# 設定の問題

+ [ローカルPCとサーバーでの挙動の違い](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XIc1z)

:::note alert
メッセージを受信できる https://test.salesforce.com/services/Soap/u/59.0 でリッスンしているエンドポイントがありませんでした。これは一般に、アドレスまたは SOAP アクションが正しくない場合に発生します。詳細については、InnerException を参照してください (もしあれば)。

要求した名前は有効ですが、要求された種類のデータは見つかりませんでした。 (test.salesforce.com:443) 
:::


:::note
本日やっと原因がわかりました。
当社ではプロキシを経由しないと外部へ接続できずで
プロキシはユーザに紐づいております。
ローカルPCのIISは私のユーザで動いており、私のユーザでプロキシ認証が済んでいる状況
サーバー のIISは administratorで 動いており、私のユーザでプロキシ認証が済んでいる状況 
そのため、サーバーのIISではプロキシ認証が済んでいない状況なので外部へ接続できない状態だったようです。
サーバーのIISのアプリケーションを私のユーザに変更することでAPIへの接続ができました。
:::
＜R2＞★最終チェック（勉強メモ）

https://qiita.com/nori83/items/095055bcaa812605960f
https://qiita.com/nori83/items/40921b1df17143f70d0b
・旧システム書き漏れ注意、俯瞰図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/0ba5fe35-62c6-6c18-4970-29a08213c001.png)
・決済サービス：決済をSF上の画面から行うAppExchange
・FSLのチェックイン時の位置情報は活動に入る
・作業指示品目＝作業指示のサブタスク（例：XXに相談など）
　必要商品＝作業指示を行うにあたって必要な在庫
・NextBestActionにEinstein予測ビルダーを入れられる。・・Einstein 予測ビルダーでは、コードを記述することなく、ビジネスで次に何が起こるかのカスタム予測を作成できます。 予測する内容、値を予測する項目、その項目を含むオブジェクトを決定したら、構築を開始できます。 予測の構築が完了したら、Einstein 予測ビルダーのスコアカードでその結果を確認します。


＜試験ポイント＞
・時間はかりながら90分のシナリオを解く
・時間かかりそうなものはスキップしてQAでリカバリ
・どう解釈したからこう回答したというプレゼン
・データモデルと移行要件、ガバナンスは飛ばし、アクセス要件は少し読む。（たまにトランスレーションワークベンチなどあるため）:zipper_mouth:
・Orgをどう決めたか、ざっくりER、俯瞰図、ソリューションに回答を書く :zipper_mouth:
・「どう解釈したから、こう回答したよ」と話すこと。
★重要★
https://qiita.com/nori83/items/921d3f1d56b84b4afe6c

＜その他＞
Einsteinディスカバリー：の統計モデリングと機械学習（ビジネスデータに関するインサイトを識別し、表面化して視覚化するための統計モデリングと機械学習により、ビジネスインテリジェンスを増強するものです）

＜WeakPoint＞
・データアーカイブの言及が足りない
・インテグレーションパターンの説明が弱い
　　★
・大規模でインポートウィザードは実態として厳しい
・ESBが解決する拡張性
　　★拡張性（疎結合・連携ポイントがシンプル）、ロギング、監視やセキュリティ統合
  　⇒ESBのほうが少量ニアリアルに向いている、キューイング
   　コンポーネントの再利用性、
    ⇒ETL：初期データ移行、LDV
・業務に即したソリューション

＜Canvas＞
・対向シスタムの【画面】をそのまま埋め込むケース。
・ただし対向が改修できること（CanvasのJavaScriptライブラリを読み込めるか）が条件
・認証方式はOAuth、ないしはSignedリクエスト（後者は、接続アプリケーションのように、Client_id、Client_Secretを対向に埋め込み、Salesforce側はその埋め込みが払い出したものかを確認して認証する）
https://qiita.com/nori83/items/05bf5be31c56244926ff

＜プラットフォームイベント＞
非同期のほうがUIUX考慮したときによい（画面にすぐ返す場合は同期）
非同期の中でもApexなどあるが、Apexは対向が落ちてた時にリトライができない。プラットフォームイベント＋ESBであればコンフィグだし、72時間バスにデータたまる。なのでＰＦイベントがよい。（ミドルウェアがないケースなどはプラットフォームイベントは使えない。対向がPubSubやストリーにングに対応していない。）

＜データアーカイブ＞
（１）1テーブルに100万件以上の場合、要件やパフォーマンスに応じてアーカイブを検討。
（２）別ストレージへのアーカイブは、
（a）履歴などDB構造が変わる可能性の低い履歴⇒BigObject（インデックスを貼りなおす場合、オブジェクトを作りなおしたりする必要があるので扱いづらい。なので項目が変わらない履歴など仕様変更が置きづらいものに適している。
（b）注文データなど項目が変わりやすいデータについては、例えば社内にストレージがある場合、そこにETLなど介して定期的にデータを投入。Salesforce側は削除することによりストレージを空かせる。
（c）社内にストレージがない場合、安価で実績/拡張性のあるAWSなど検討。同様にETLで定期的にアーカイブ、Salesforce側は削除
（d）Salesforc画面から上記のようなデータを見れるようにしたい、という場合はSalesforceConnectで関連リストからリアルに少量データを出す方針も検討（ただし1時間2万回のCallOutなど制限あり。）
（３）もし業務的に消していいものであれば、夜間バッチのタイミングで、例えばクローズしたデータを定期削除するケースも検討


★メモ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450298/81f9b9db-c000-6d18-b5e9-0b85e31bd3af.png)

NextBestActionにEinstein予想ビルダー
Einstien商談・リードのスコアリング（成功したものの強みを学習してスコアリング自動）
Einsteinで議事メモやチャットの返信、言語を生成AIが判断して、ナレッジ結果返す
バーチャルリモートアシスタント：Zoomみたいなの
Trusted URLs で保存ボタンが表示されない

[UI関係のトラブルに戻る](https://qiita.com/Keiji_otsubo/items/cc344223cfa02db6bed7)


#  Trusted URLs

+ [Hi Guys, I am getting issue while adding API in Trusted URLs. Can you please help me redarding this issues](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007YvP6j)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/73ea471c-3fbf-4f2e-71a0-4536046162f3.png)

:::note
 fix using Microsoft Edge and the issue was resolved!
:::


# [Where is the Save button for Link Images in Prompts>New Trusted URL form?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ZAuWY)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ada02547-13f4-4b70-b716-c18041a66549.png)

:::note
Try your browser's incognito mode.Or try it in a different browser.

fix using Microsoft Edge and the issue was resolved!

https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007YvP6j
:::

+ [Create Prompts in Lightning Experience - Can't find the button to Save the "Trusted URLs"](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmOnt)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c168e592-2775-16b5-70d1-89aa6589c3f7.png)


:::note
Try your browser's incognito mode.Or try it in a different browser.
:::
Googleフォームを毎日回答受付・終了する（その2）

## １ 目的
先日、[Googleフォームを毎日回答受付開始・終了する](https://qiita.com/freshcl/items/fbbe8e597bab21fc2654)というのを書きました。これを実行して放置していると使い終わったトリガーが毎日溜まっていきますが、トリガー数には1スクリプトあたり20という制限があるので適当に削除する必要があります。そこで、トリガーを設定する前に古いトリガーを削除するよう、書いてみました。
## ２ スクリプト
```JavaScript:script.gs
//開始後一定時間後（openHoursで指定）に終了する関数
function startAndClose1() {
  const formId = 'フォームID';
  const myform = FormApp.openById(formId);
  myform.setAcceptingResponses(true);
  const openHours = 1;
  const mytrigger = 'closeForm1';
  delTrigger(mytrigger); //古いトリガーの削除
  ScriptApp.newTrigger(mytrigger)
    .timeBased()
    .after(openHours * 60 * 60 * 1000)
    .create();
}

//終了時間を指定（closeDateTimeで指定）し、開始後、指定時間に終了する関数
function startAndClose2(){
  const formId = 'フォームID';
  const myform = FormApp.openById(formId);
  myform.setAcceptingResponses(true);
  const currentDate = new Date();
  const closeDateTime = new Date(
    currentDate.getFullYear(),
    currentDate.getMonth(),
    currentDate.getDate(),
    8, 30, 0, 0
  );
  const mytrigger = 'closeForm1';
  delTrigger(mytrigger); //古いトリガーを削除
  const triggerTime = closeDateTime.getTime() - currentDate.getTime();
  if (triggerTime > 0) {
    ScriptApp.newTrigger(mytrigger)
      .timeBased()
      .after(triggerTime)
      .create();
    Logger.log('回答受付を終了するトリガーが設定されました。');
  } else {
    Logger.log('指定の日時が過去のため、トリガーを設定できません。');
  }
}

function closeForm1() {
  const formId = 'フォームID';
  const myform = FormApp.openById(formId);
  myform.setAcceptingResponses(false);
}

//トリガーを削除する
function delTrigger(mytrigger2) {
  const mytriggers = ScriptApp.getProjectTriggers();
  for (let i = 0; i < mytriggers.length; i++) {
    if (mytriggers[i].getHandlerFunction() === mytrigger2) {
    ScriptApp.deleteTrigger(mytriggers[i]);
    }
  }
}
```
終わりの部分に、トリガーを削除する関数delTriggerを追加しました。この関数はstartAndClose1とstartAndClose2から使われ、削除するトリガー名を引数で受け取ります。ScriptApp.getProjectTriggers()でトリガーの一覧を取得し、該当するトリガー名（関数名）のものを削除します。
## ３ 参考
- [Google Apps Scriptの日毎のトリガーで時間をもっと細かく設定する](https://qiita.com/sumi-engraphia/items/465dd027e17f44da4d6a) @sumi-engraphia

- [Google Apps Script リファレンス](https://developers.google.com/apps-script/guides/services/quotas?hl=ja#current_limitations) 制限関係

- [Googleフォームを毎日回答受付開始・終了する](https://qiita.com/freshcl/items/fbbe8e597bab21fc2654) 前回投稿
初心者にお薦めするプログラミング言語3選

# 初心者にお薦めするプログラミング言語3選

## はじめに
プログラミングを初めて学習する方にお薦めするプログラミング言語を３つ紹介します。

## 1.VBA
Microsoft Office製品がインストールまたはOffice製品付きのPCを購入された方は特別なインストール作業なしに始められます。VBAに関するサイト、書籍が充実しているのでとっつきやすいと思い1番目に挙げます。

## 2.Python
インデントルールが明確で初心者でもソースコードを読むのが容易。Webサイト、書籍が充実し、初学者向けの書籍が多く出版されている。

## 3.JavaScript
ブラウザさえあれば、環境構築せずにプログラミングが始められる。書籍、Webサイトが充実している。

## さいごに
他にも挙げたいプログラミング言語がありますが、今回は3つに絞りました。
rocky linuxで日本語入力出来ない問題を解決した

## まず最初に
vmware等にrocky linuxを日本語モードでインストールされている事を前提とする。
次に、rocky linuxのデスクトップからアクティビティを選択→端末を開く

## 端末操作
コマンド入力
>ibus-setup

パネルが開くので入力メソッド→日本語(Anthy)を登録

## 実際の操作
キーボードの半角/全角のキーでアルファベット、日本語の切り替えができるようになる。

## chromeブラウザなど一部のアプリがこの方法で日本語入力できない
windowsキーとスペースキー同時押しで日本語、アルファベット切り替えができる

…何か気持ち悪いですね、早いうちにいい日本語入力メソッドがでてくればいいのですが。
C++ 多重配列(vector, array)

# source code
```c++

#include <iostream>
#include <array>
#include <vector>
#include <string>
#include "multi_array.hpp"

//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
void multi_array::exec()
{
    std::cout << __func__ << std::endl;

    const std::vector<std::uint8_t> var_vector{1, 2, 3, 4, 5};
    std::string str_msg = "*** var_vector : ";
    for(const std::uint8_t& var_vec_item : var_vector)
    {
        str_msg += " " + std::to_string(var_vec_item);
    }
    std::cout << str_msg << std::endl;

    const std::array<std::uint8_t, 5> var_array{6, 7, 8, 9, 10};
    str_msg = "*** var_array  : ";
    for(const std::uint8_t& var_arr_item : var_array)
    {
        str_msg += " " + std::to_string(var_arr_item);
    }
    std::cout << str_msg << std::endl;

    const std::vector<std::vector<std::uint8_t>> var_multi_vector{
        {11, 12, 13, 14, 15},
        {21, 22, 23, 24, 25},
        {31, 32, 23, 24, 25}
    };
    str_msg = "*** var_multi_vector : ";
    for(int ix = 0; ix < 3; ix++)
    {
        str_msg += "\n";
        for(int iy = 0; iy < 5; iy++)
        {
            uint8_t var = var_multi_vector.at(ix).at(iy);
            str_msg += " " + std::to_string(var);
        }
    }
    std::cout << str_msg << std::endl;

    str_msg = "*** var_multi_vector : for_range";
    for(const auto& vec : var_multi_vector)
    {
        str_msg += "\n";
        for(const std::uint8_t& var : vec)
        {
            str_msg += " " + std::to_string(var);
        }
    }
    std::cout << str_msg << std::endl;


    const std::array<std::array<std::uint8_t, 5>, 3> var_multi_array{{
        {16, 17, 18, 19, 20},
        {26, 27, 28, 29, 30},
        {36, 37, 28, 29, 40}
    }};
    str_msg = "*** var_multi_array : ";
    for(int ix = 0; ix < 3; ix++)
    {
        str_msg += "\n";
        for(int iy = 0; iy < 5; iy++)
        {
            uint8_t var = var_multi_array.at(ix).at(iy);
            str_msg += " " + std::to_string(var);
        }
    }
    std::cout << str_msg << std::endl;

    str_msg = "*** var_multi_array : for_range";
    for(const auto& arr : var_multi_array)
    {
        str_msg += "\n";
        for(const std::uint8_t& var : arr)
        {
            str_msg += " " + std::to_string(var);
        }
    }
    std::cout << str_msg << std::endl;
}
```

# outout
```
exec
*** var_vector :  1 2 3 4 5
*** var_array  :  6 7 8 9 10
*** var_multi_vector :
 11 12 13 14 15
 21 22 23 24 25
 31 32 23 24 25
*** var_multi_vector : for_range
 11 12 13 14 15
 21 22 23 24 25
 31 32 23 24 25
*** var_multi_array :
 16 17 18 19 20
 26 27 28 29 30
 36 37 28 29 40
*** var_multi_array : for_range
 16 17 18 19 20
 26 27 28 29 30
 36 37 28 29 40
```
QCoder #1 参加報告

## はじめに
量子プログラミングを対象とした競プロのコンテストが開催されました。今回は、その参加報告をしたいと思います。

  https://www.qcoder.jp/contests/QPC001

## 量子プログラミングとは
量子プログラミングは、量子コンピューティングを行うために、量子ビットを操作する量子回路（量子ゲートの集まり）の構成を記述するプログラミングのことです。
 
従来のコンピュータにおけるビットは、$0,1$の2状態のみを表現出来るのに対して、量子ビットは量子状態$\ket{\psi}$を表現できます。$\ket{0} = \left(\begin{eqnarray}1 \\\ 0 \end{eqnarray} \right)$, $\ket{1} = \left(\begin{eqnarray}0 \\\ 1 \end{eqnarray} \right)$とすると、量子状態$\ket{\psi}$は以下のようにベクトルで表現することが出来ます。

  $$\ket{\psi} = a \ket{0} + b \ket{1} = \left(\begin{eqnarray}a \\\ b \end{eqnarray} \right), 
　|a|^2+|b|^2 = 1 \ \  (a,b \in \mathbb{C})$$

　同様に、量子ゲートは行列で表すことが出来て、例えば1量子ビットに対する量子ゲートは、$Z = \left(\begin{matrix}1&0\\\ 0&-1 \end{matrix} \right)$などと表現されます。

　また、$n$量子ビットに対するゲート（$n$量子ゲート）というものもあり、そちらは$2^n \times 2^n$の行列で表されます。

　詳しくは、QCoderのQ&Aページにも紹介されている以下のページなどをご参照頂ければと思います。

- [初心者でもわかる量子コンピュータの計算の仕組み](https://www.r-staffing.co.jp/engineer/entry/20220210_1)
- [Basics of quantum information - IBM Quantum Learning](https://learning.quantum.ibm.com/course/basics-of-quantum-information)；こちらはIBMの公式ページです。

## 第一回コンテスト
2024年1月20日に第一回コンテストが行われましたので、参加しました。

問題の中で、個人的に面白かったのがB3とB4でしたので、感想のようなものを以下に記述してみました。

いろいろ割愛していますので、詳細はQCoderの解説をご参照頂ければと思います。

### 問題B3
- [問題B3](https://www.qcoder.jp/contests/QPC001/problems/B3)

自然数$n(\le 5), L(\le 2^n)$が与えられたときに、$\ket{0}, \ket{1} \dots \ket{L-1}$の振幅に$-1$を掛けるプログラムを作ることになる

いま、入力は$\ket{\psi} = a_0\ket{0}+ a_1\ket{1}+ \dots + a_{2^n -1}\ket{2^n -1}$で表される。ここで整数はリトルエンディアンに従ってエンコードされており、$\ket{0}= \ket{000 \dots 0}, \ket{1} = \ket{100 \dots 0},\ket{2^n -1}=\ket{111 \dots 1}$である。

『$\ket{2^n -1}$だけに$-1$を掛ける方法が存在する』ので、任意の$\ket{i}$を$\ket{2^n -1}$に変換して、また元に戻すことが出来るなら、それを$\ket{0}, \ket{1} \dots \ket{L-1}$で繰り返せば良い。この変換を写像と考えると、任意の$\ket{i}$に対して$\ket{2^n -1}$への全単射$f_i$を作ることが出来れば、逆変換しても係数は他と合算されることなく保たれるということである。実は、$f_i$は、全単射である$X$ゲートで構成出来る。

よって、$\ket{i}$に対して、（１）$f_i$を作用、（２）$-1$を掛ける、（３）$f_i^{-1}$を作用させれば、$\ket{i}$にだけ$-1$を掛けられるので、これを$i=0 \sim L-1$で繰り返せば良い。

### 問題B4
問題B4は、B3の同じ問題だが、回路の深さ（実行するゲート数）の上限が50に設定されている。B3は回路の深さが少なくとも$2L$以上になるので、$L > 25$のときに条件を満たせない。

B3では、『$\ket{2^n -1}$だけに$-1$を掛ける方法が存在する』と書きましたが、実は複数制御$Z$を用いて$-1$を掛ける方法があるから、《$n$ビット中の一部だけでも1で満たせれば$-1$を掛ける方法が存在する》ことを利用する。

アイデアとしては、B3のように$\ket{i}$に対して逐次で行うのではなく、いくつかの$\ket{i}$に対してまとめて$-1$を掛ける操作を行う。

あとは、$L$より小さい値の特定だが、上位桁からのビットを$\ket{L}$と比較すると同時に、複数制御$Z$の対象も準備出来るような分け方を行っている。めちゃくちゃテクニカルというか、トリッキーな方法に見えますが、面白いですね。

上のやり方を観ると、$L=2^m$だったら、$m \sim n-1$桁目（0桁目からカウント）を反転させて、複数制御$Z$（$m+1 \sim n-1$制御、$m$桁目に$Z$）を使えば一発で変換出来て楽しいですね。



### （余談）量子人材育成
量子コンピュータ界隈を眺めていると、実用的な量子コンピュータが意外と早く実現されるかも知れないという話もあるので、学生の方々などは今から勉強するのは丁度良い頃合いかも知れません。

量子コンピュータ界隈も、Cloudなどと同様に、人材育成からということで、ちょっと検索しただけでも様々なプログラムが見つかります。これから量子人材が徐々に増えていくことを期待しています。

https://nqc.nict.go.jp/news/230703_01.html

https://www.jst.go.jp/stpp/q-leap/jinzai/index.html

## さいごに
第1回目のコンテストは、何も準備せずに突っ込んだので、もう少し勉強して、次回に臨みたいと思います。

それではまた。
ラズパイ5 2023年10月更新 bookworm ⑦ VNC

　2023年10月にリリースしたbookworm から、画面周りに大昔からUNIXで使われていたウィンドウ・マネージャが X11 から Wayland に変更されました。最近まで使っていたReal VNCが、2023年末に確認したとき、使えなくなっていました。

　執筆時、2024年2月はじめのバージョンを確認します。

```shell 
$ wayvnc --version
wayvnc: v0.8-rc0-4c70b8c (pios)
neatvnc: **0.7.1**
aml: 0.3.0
```

　GUIで行ってもいいのですが、sshで接続しているので、

`$ sudo raspi-config`

　3のInterface Optionsを選択し、12のVNCで、enableにします。

```shell 
$ ssh-keygen -m pem -f $HOME/.config/wayvnc/rsa_key.pem -t rsa -N ""
Generating public/private rsa key pair.
/home/yoshi/.config/wayvnc/rsa_key.pem already exists.
Overwrite (y/n)? n
```

　もともと使っていたので、noで抜けます。

　

　Real VNCのサイト、

　 [RealVNC Viewer を使用して Wayland を実行している Raspberry Pi デバイス上の WayVNC に接続する](https://help.realvnc.com/hc/en-us/articles/14693032843293-Connecting-to-WayVNC-on-a-Raspberry-Pi-device-running-Wayland-using-RealVNC-Viewer#for-devices-using-a-wayvnc-version-prior-to-0-7-0-0-0)

には、wayvncが0.7以上であれば接続できるとあります。

　Windows10 クライアントにインストールしていたRealVNC Viewer から、問題なく接続できるようになっていました。

 ![ras1001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e2d5db51-7e15-cf36-b950-686e1ad68d90.png)


### 環境

- ハードウェア　Raspberry Pi 5（4GBモデル）
- OS　Raspberry Pi OS （64ビット）、リリース日December 5th 2023
- Windows10 22H2にてssh（OpenSSH_9.2p1 Debian-2+deb12u2, OpenSSL 3.0.11 19 Sep 2023）を動作させている


:::note info
この一連の話はこれで終わりです。
BLEを続けてプログラミングしていたのですが、どうも、アクセス権関係が変わったようで、うまく動きません。
いつか、解決できるはず
:::
SQLコマンドの種類と特徴

# はじめに
現在Oracleについて勉強中で、SQLコマンドの種類と特徴についてよく間違えるのでまとめようと思いました。
主に自分用のメモとして書きますが、ORACLE MASTER Bronze DBAの試験にも出るので、参考になれば幸いです。
# データ操作言語(DML:Data Manipulation Langage)
#### データの格納・取り出し・更新・削除などに使用する。
・insert →表への行の追加
`insert into テーブル名 values (値,値,...);`
`insert into テーブル名 (列名,列名,...) values (値,値,...);`
・update →表に格納された行の更新
`update テーブル名 set 列名=値 where 条件式;`
・delete →表に格納された行の削除
`delete from テーブル名 where 条件式;`
# データ定義言語(DDL:Date Definition Langage)
#### テーブルの作成・削除や、各種設定に使用する。
・create →オブジェクトの作成
`create table テーブル名 (列名 データ名 [オプション],...);`
・drop →オブジェクトの削除
`drop table テーブル名;`
・alter →オブジェクトの定義変更
`alter table テーブル名 変更操作;`
・truncate →表に格納された全ての行を一括削除
`truncate table テーブル名;`
# トランザクション制御
#### トランザクションの開始や終了に使用する。
・commit →トランザクションの確定
`commit;`
・rollback →トランザクションの取り消し
`rollback;`
・savepoint →セーブポイントの新規保存
`savepoint 新規セーブポイント名;`
# データ制御言語(DCL:Data Control Language)
#### DMLやDDLの利用に関する許可や禁止を設定する。
・grant →権限の付与
`grant 権限名 on オブジェクト名;`
・revoke →権限の取り消し
`revoke 権限名 on オブジェクト名;`
仮想通貨一覧

Polkadot

https://polkadot.network

https://polkadot.network/whitepaper/


Sui

https://sui.io

Sei

https://www.sei.io

https://docs.sei.io

Arbitrum

https://arbitrum.io

https://github.com/OffchainLabs



WLD

https://worldcoin.org

https://whitepaper.worldcoin.org/tokenomics

Fantom

https://fantom.foundation

https://fantom.foundation/fantomResearchPapers

Stepn

https://stepn.com

KASPA

https://kaspa.org

https://eprint.iacr.org/2018/104.pdf

Ripple

https://ripple.com

https://ripple.com/files/ripple_consensus_whitepaper.pdf


TRON
https://tron.network

https://developers.tron.network/docs/getting-start

Solana

https://solana.com

https://solana.com/solana-whitepaper.pdf

Avax

https://www.avax.network

https://www.avalabs.org/whitepapers

Chiliz

https://www.chiliz.com

https://www.chiliz.com/Chiliz_Corporate-Product-profile-V9.pdf

Flare

https://flare.network

https://flare.network/tokenomics-flr-updated/

Cardano

https://cardano.org

https://docs.cardano.org/introduction/

LiteCoin

https://litecoin.org

https://github.com/litecoin-project/litecoin

Ethereum

https://ethereum.org

Bitcoin

https://bitcoin.org/en/

サトシ論文

https://bitcoin.org/bitcoin.pdf 



## ゲーム系

Oasys

https://www.oasys.games

https://docs.oasys.games/docs/whitepaper/intro


## ミーム系
https://bonkcoin.com
FlutterでReleaseビルドをするとネットが繋がらなくなる問題への対処法

# 起こっていること

https://github.com/gadgelogger/kokorahenn_flutter

ワイ「Flutter使ってこんなアプリ作ってるんやけど、そろそろ完成しそうやな」

ワイ「せや！release buildしてAndoridでチェックしたろ」
↓
ビルドしてAPKで書き出し
↓
「無事にビルドできたわ。。。。。うん？？？なんか店舗情報取得できねぇ。。。どうなってんだこれ？？？」

みたいな状況が発生した。

| 正常な時 | 今回の現象 |
|:-:|:-:|
| ![Screenshot_1708617694.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1657253/4008052d-f5ac-553b-94f8-8433fbd47015.png)|  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1657253/61980595-f873-6362-7363-144ca4d0d3c7.png) |



# 対処法

https://minpro.net/socketexception-failed-host-lookup

パーミッションの設定漏れが原因でしたね。分かっている人なら
「初歩的なミスだなwwwwおいwwww」となるけど、意外と忘れがち。


```xml:/flutter_project/android/app/src/main/AndroidManifest.xml
<uses-permission android:name=”android.permission.INTERNET”/>
```

コレを追加しておこう。
テンプレートをIMG loading=lazyのような遅延読み込みさせる

## エレメントが画面内に入ったときにテンプレートを実行させる

Navboxのようなページ下部の巨大テンプレートを遅延読み込みさせて「参照読み込みの展開後のサイズ(Post‐expand include size)」を削減させる狙い。

ページ保存時、以下のテンプレートを使用すると&lt;div>...&lt;/div>のみが展開されて保存される。

```wikitext:テンプレート:LazyLoad
<includeonly><div class="lazyLoad" data-page="{{{page|}}}"></div></includeonly>
```

ユーザーがページを開いた時点では&lt;div>のまま読み込まれる。
そしてガジェットに仕込んだJavaScriptがエレメントを監視し、画面内に入った瞬間にテンプレートを動的に展開する。

```js:Gadget-lazyLoad.js
 mw.loader.using( ['mediawiki.util', 'mediawiki.Title'], function(){
    
    // IntersectionObserverを使用したエレメントの座標監視
    const intersectionObserver = new IntersectionObserver( function( entries ) {

        entries.forEach( function( entry ) {
            // 画面内に入った
            if ( entry.isIntersecting ){

                // エレメントの要素から引数を取得
                var page = entry.target.getAttribute( 'data-page' );
                
                if( page ){

                    // Apiへのリクエスト情報
                    var requestData = {
                        action: 'parse',
                        prop: 'text|modules|jsconfigvars|templates',
                        title: mw.config.get( 'wgPageName' )
                    };

                    // 対象ページがテンプレートか記事か調べてWikitextを生成
                    var title = new mw.Title( page );
                    var template = title.getNamespaceId() == 10;
                    if ( template ) {
                        requestData.text = '{' + '{' + page + '}}';
                    } else {
                        requestData.text = '{' + '{:' + page + '}}';
                    }

                    // Wikitextを動的にパーサーさせる
                    new mw.Api().get( requestData ).done(function ( data ) {
                        // VisualEditorのプレビューと同じ処理
                        // * ve.init.mw.ArticleTarget.js
                        //
                        if ( data.parse.jsconfigvars ) {
                            // mw.loader呼び出しのための引数の割当
                            mw.config.set( data.parse.jsconfigvars );
                        }
                        if ( data.parse.modules ) {
                            // mw.loaderの呼び出し
                            mw.loader.load( data.parse.modules.concat(
                                data.parse.modulescripts,
                                data.parse.modulestyles
                            ));
                        }
                        // できたHTMLの差し込み
                        var html = $( $(data.parse.text['*']).html() ).removeClass( 'noscript' );
                        $( entry.target ).append( html );

                        // 他のスクリプトへ読み込み完了通知
                        mw.hook( 'wikipage.content' ).fire( $(entry.target) );
                    });

                }
                // 監視対象から除外
                intersectionObserver.unobserve( entry.target );
            }
        });
    });

    // エレメントの監視を開始
    var observe_target = document.querySelectorAll( ".lazyLoad" );
    observe_target.forEach( function( element ){
        intersectionObserver.observe( element );
    });
});
```

使用例：[Minecraft Japan Wiki - ブロック/生物](https://minecraftjapan.miraheze.org/wiki/ブロック/生物)
Java オブジェクトの使い方

# はじめに

皆さん、初めまして俊一郎と言います。
Javaの開発を行いたく学習を始めました。

# 参考教材
- [初心者向けJava入門講座 2~6章](https://www.youtube.com/watch?v=dzy1ipa20Kk&list=PLru8-xuz0YvwoVRzBTX5jUcavM4Q8gZi9&index=6)

# 自分なりの言語化()

- 引数を指定しているメソッドの場合は、実行用クラスにオブジェクト名.メソッド名()というように記述して()内を設計用クラスで指定した引数の型や数に合わせる。

- returnを指定しているメソッドの場合は、実行用クラスにオブジェクト名.メソッド名()というように記述して戻り値を設計用クラスから受け取る。

- 引数と戻り値がないメソッドの場合は、実行用クラスでオブジェクト名.変数名 = リテラルのように記述する。
 
# 今後の目標
- JavaSilverを4月に取得する。
React Bootstrap でトースト通知に必要な CSS のみをインポートする方法

## 事象

`React Bootstrap` を使用してアプリケーションにトースト通知を実装する際、全ての `Bootstrap` スタイルを以下のコマンドでインポートすると、トースト以外のコンポーネントにもスタイルが適用され、意図しないデザインの変更が発生する可能性があります。

```ts
import 'bootstrap/dist/css/bootstrap.min.css';
```

この問題を解決し、トースト通知機能に必要な `CSS` のみを選択的にインポートする方法をご紹介します。

## 対処法

`SCSS` を使用して、トーストを実装するために最低限必要な `CSS` をインポートします。これにより、アプリケーションの他の部分に影響を与えることなく、トースト通知のスタイルを適用できます。

```scss:style.scss
// Configuration
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/utilities";
 
// Layout & components
@import "node_modules/bootstrap/scss/alert";
@import "node_modules/bootstrap/scss/close";
@import "node_modules/bootstrap/scss/toasts";
```

:::note warn
警告
下記のようなエラーが発生する場合には`@import "node_modules/bootstrap/scss/maps";
`を`@node_modules/bootstrap/scss/utilities";`の前に配置する必要があります。この手順は、Bootstrap v5.2.0以降で導入された新しい_maps.scssファイルが関連しています。
:::

```
[plugin:vite:css] [sass] Undefined variable.
    ╷
142 │       values: $utilities-border-colors
    │               ^^^^^^^^^^^^^^^^^^^^^^^^
    ╵
  node_modules/bootstrap/scss/_utilities.scss 142:15  @import
  your/path/to/style.scss 21:9  root stylesheet
```

## 参照

https://github.com/twbs/bootstrap/issues/36785

自らの備忘録のために投稿してますが、なにかお役に立てましたら幸いです！:clap:
また、なにか間違ってましたらご指摘いただけますと幸いです！:pray:
Laravel 11でコマンドラインアプリケーションを作成【コンソールアプリ】

# Laravel 11のインストール
Laravel 11はPHP8.2以上が必要です
```bash
composer create-project laravel/laravel:^11.0 example-app
cd example-app
```

# コマンドラインアプリケーションを作成

```php:routes/console.php
<?php

use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;

Artisan::command('inspire', function () {
    $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote')->hourly();
```

`$this->comment();`でコンソールに色を付けてくれます。`->hourly();`で毎時に実行されます！

# 実行

```bash
$ php artisan inspire

  “ Always remember that you are absolutely unique. Just like everyone else. ”
  — Margaret Mead
```

# コマンドラインアプリケーションを作成

```bash
php artisan make:command SendEmails
```

編集
```php:app/Console/Commands/SendEmails.php
<?php

namespace App\Console\Commands;

use Illuminate\Foundation\Inspiring;
use Illuminate\Console\Command;

class SendEmails extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:send-emails';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->comment(Inspiring::quote());
    }
}
```

# 実行

```bash
$ php artisan app:send-emails

  “ Simplicity is the consequence of refined emotions. ”
  — Jean D'Alembert
```

# スケジュール

Laravel 10以上なら1分未満の間隔を指定できます！便利！

```php:routes/console.php
<?php

use Illuminate\Support\Facades\Schedule;
 
Schedule::command('app:send-emails')->everySecond();
```

https://laravel.com/docs/master/releases

cronをインストール
```bash
sudo apt install -y cron
sudo service cron start
service cron status
crontab -e
```

:::note warn
`/path-to-your-project`と`php`のパスは適宜書き換えること
:::

```bash
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
```
MeshFilterのMeshを管理する際のメモ

# どういう記事？
ターゲット：既成のFBXを使わず、スクリプトからMeshをいろいろ変更したい人
内容：Meshの要素の変更をMeshFilterに反映する簡潔(だと思う)なコード
```c#
public class Model
    {
        private Material myMaterial;
        private Mesh myMesh;
        private Bounds myBounds;
        public Model(GameObject gameObject)
        {
            myBounds = new Bounds();
            myMesh = new Mesh();
            myMaterial = new Material();
            gameObject.GetComponent<MeshFilter>().mesh = myMesh;
            gameObject.GetComponent<Renderer>().material = myMaterial;
        }
        public void SetVertsAndIndices()
        {
            Vector3[] vertices = 頂点;
            int[] indices = インデックス配列;
            myMesh.vertices = vertices;
            myMesh.subMeshCount = 1;
            myMesh.SetIndices(indices, MeshTopology.なにか, 0);
        }
        public void OnMaterialChange()
        {
            myMaterial.SetBuffer("なんかのデータ", buffer_なんかのデータ);
        }

        public void CalculateBounds()
        {
            myBounds.SetMinMax(min, max);
            myMesh.bounds = myBounds;
        }

    }
 ```


 
# Meshについて
`meshfilter.mesh`で取得できるMeshはmeshfilterで使われるものコピーなので、コピーへの操作はmeshfilterに反映されない
```c#
meshfilter.mesh.vertices = newVertices; // meshfilterには反映されない
```
変更したいメッシュをメンバ変数として持ちながら、`meshfilter.mesh`に代入することで、メンバ変数への操作をmeshfilterに影響させることができる
```c#
myMesh = new Mesh(); // = meshfilter.meshで現在のコピーをメンバ変数にすることもできる
meshfilter.mesh = myMesh;

//myMeshに変更を加えたい時
myMesh.vertices = newVertices; // meshfilterに反映される
```





# Boundsについて
boundsは `mesh.bounds = newBounds` とする以外にmeshとmeshfilterに影響することができない(と思う)
```c#
myMesh.bounds.SetMinMax(min,max); //myMeshには変更が届かない
```
```c#
myBounds = new Bounds();
myMesh.bounds = myBounds; //この時のmyBoundsの値は設定されるけど…？

//Boundsの大きさが変わった時
myBounds.SetMinMax(min,max); //meshには変更が届かない
```

```c#
myBounds = new Bounds();

//Boundsの大きさが変わった時
myBounds.SetMinMax(min,max);
myMesh.bounds = myBounds; //myMeshのboundsが変更されるよ
```
【Vim】カーソルの移動

| キー | 説明                 |
|------|---------------------|
| h    | 左に移動            |
| j    | 下に移動            |
| k    | 上に移動            |
| l    | 右に移動            |
| w    | 単語分先へ移動      |
| b    | 単語分前へ移動      |
| e    | 単語の末尾へ移動    |
| W    | 空白区切りの単語分先へ移動 |
| B    | 空白区切りの単語分前へ移動 |
| E    | 空白区切りの単語の末尾へ移動 |
| 0    | 行頭へ移動          |
| ^    | 空白以外の行頭へ移動 |
| $    | 行末へ移動          |
| gg   | ファイル先頭に移動    |
| G    | ファイル末尾に移動    |
MediaWikiのApiを使ってファイルの実URLを取得する

## 画像のURLの取得
- 参照：https://www.mediawiki.org/w/api.php?action=help&modules=query%2Bimageinfo

```js
function getImageURL(filename){
    // スペース文字をアンダースコアに
    filename = filename.replaceAll(" ", "_");

    // Apiを呼び出す
    return $.Deferred().promise( function() {
		return new mw.Api().get( {
            action: 'query',
            titles: "File:" + filename,
            prop: 'imageinfo',
            iiprop: 'url'
        });
    }).then(function( data ){
        // 受け取ったのはオブジェクトか？
        if(typeof data === "object"){
            // クエリの結果からpageIDを取得
            var pageid = Object.keys( data.query.pages )[0];

            // ファイルが存在する場合はpageID > -1
            if (pageid > -1){
                // URLを返す
                return data.query.pages[ pageid ].imageinfo[0].url;
            }
        }
        return "存在しないファイル名です";
    }).fail(function(){
        return "APIの呼び出しに失敗しました";
    });
}
```

## オーディオファイルの情報を取得
オーディオファイルの場合imageinfoではなくvideoinfoクエリーを使用する。
こちらは&lt;audio/>タグで再生可能な必要情報も含める例。
- 参照：https://www.mediawiki.org/w/api.php?action=help&modules=query%2Bvideoinfo

```js
function getVideInfo(filename) {

    // メタデータ情報をObjectで返す関数
    function meta2obj(value){
        if(typeof value === 'object' && Array.isArray(value)){
            var obj = {}, idx = 0;
            value.forEach( function( v, i ){
                if(v.hasOwnProperty("name") && v.hasOwnProperty("value")){
                    if(typeof v.name === 'number'){
                        obj[idx++] = {
                            id: v.name,
                            data: meta2obj(v.value)
                        };
                    } else {
                        obj[v.name] = meta2obj(v.value);
                    }
                }
            });
            return obj;
        }
        return value;
    }

    // スペース文字をアンダースコアに
    filename = filename.replaceAll(" ", "_");

    // Apiを呼び出す
    return $.Deferred().promise(function () {
        return new mw.Api().get({
            action: 'query',
            titles: "File:" + filename,
            prop: 'videoinfo',
            viprop: 'url|mime|metadata'
        });
    }).then(function (data) {
        // 受け取ったのはオブジェクトか？
        if(typeof data === "object"){
            // クエリの結果からpageIDを取得
            var pageid = Object.keys( data.query.pages )[0];
            // ファイルが存在する場合はpageID > -1
            if (pageid > -1) {
                var info = data.query.pages[ pageid ].videoinfo[0];
                var metadata = meta2obj( info.metadata );
                return {
                    // URL
                    url: info.url,
                    // MIME-Type + Cordec
                    type: info.mime.replace(/application/, "audio") + "; codecs='" + metadata.streams[0].data.type + "'"
                };
            }
        }
        return { error: "存在しないファイル名です" };
    }).fail(function () {
        return { error: "APIの呼び出しに失敗しました" };
    });
}
```
Webclassの更新を調べるツール開発　vol.1

# はじめに
　開発未経験の私が大学の学習管理サイトのwebclassの更新を調べるツール開発を作るという話です。書き始めたら長文になったので、記事分けました。今回の話はプログラムの話はほとんどないです。適宜読み飛ばしてください。
 　拙い文章ですが、少しでも同じこと考えてる方の参考になれば嬉しいです。私の勘違い等があるかもしれないので参考程度にお願いします。
  
# 開発経緯
　私は学部生なのですが、大学がレポート提出やアンケートに使用しているWebClassという学習管理環境がなんとも使いにくく、課題が追加されたのかも分からない、未提出の課題のお知らせ機能もないということで、高校でGoogleのClassroomを使っていた身としては何ともWebClassは使い勝手が悪いのです。
　個人的に感じるWebClassのマイナスポイントをまとめるとこんな感じです。

* 通知機能がない
　基本ブラウザベースなので、締切通知とか課題の追加通知とかはなんも来ません。
　なぜかレポート提出をしたときだけ、メールで提出したファイルのファイル名だけを知らせるという謎仕様。
 <br>

* ログインが面倒
　大学側設定している統合認証とか言うフォームからログインした後、全く同じIDでWebClassのフォームからログインする2度手間。シングルサインオン[^1]なら一回のログインでいい感じにWebClassに入れればいいのに。。
　付け加えるとWebClassは同時に別端末でログインすると、セッション切れになる。(なんだこの仕様。見たことない。)
　ブラウザにパスワード保存すれば少しはマシになるが、iPhoneのパスワード保存はFaceID必須で面倒。

 [^1]: https://e-words.jp/w/シングルサインオン.html

* ファイルが常にダウンロードされる
　結構だるいポイント。課題に添付されたPDFを閲覧しようとするにはダウンロードしなくてはならない。ブラウザの新規タブでいいからシームレスな表示をしてくれ。(この辺は他大学であるがシームレスな表示をWebClassで標準化するChromeの拡張機能を提供している方がいた。)
 
👇仕組み

https://www.antenna.co.jp/pdf/reference/view-pdf-seamless.html

👇シームレスな表示の拡張機能

https://github.com/a01sa01to/WebClass-PreventDL

* UIが古臭い
 これは超個人的意見だが、UIが好みではない。そもそもスマホでの仕様がメインに考えられていないデザインであるし、デザインが今風ではない。

　口が悪く全然まとまっていないが、本当は書ききれないほどもっと言いたいマイナスポイントがあります。全ては今風のUIでスマホアプリにして通知機能があれば解決しそうな話だが... ちなみにGoogleの Classroomは動作が重いがUIと使い勝手が良い。あれでサクサク動けば最高だと思っています。


# 開発内容の決定
　そんなこんなの欠点を解消できるようなツールが作りたくなりました。GPT-4に既存のWebサイトをベースにそこから情報を取得して通知したい的なことを伝えたところ、Webスクレイピングをしたらどうかという提案をしてくれました。何“Webスクレイピング”状態だったが、どうやらWebページのデータを収集して扱いやすいデータ形式にすることらしい。
 
https://e-words.jp/w/スクレイピング.html

　相性が良さそうな言葉である。そこで”LMS スクレイピング“（LMSとはLearning Management Systemの略でWebClassみたいな学習管理システムを指す言葉）でリサーチすると何件か似たようなことを思って何らかのツールを作成している方が既にいらっしゃいました。これはかなり参考になりそうです。
　調べた感じだと一般的にスクレイピングはデータ解析が得意なPythonで行っている方が多そうなイメージだったの今回はPythonで機能を開発してみることにしました。
  スクレイピングについて勉強するとポジティブなものばかりではないようなので、注意深く勉強しました。
  
https://topcourt-law.com/internet_security/scraping-illegal#i-10

https://ja.wikipedia.org/wiki/岡崎市立中央図書館事件


  ***
##### ちょっと雑談
　本音を話すとできれば最終的にスマホのネイティブアプリにしたかったので、iOSアプリとAndroidアプリを同時進行で制作できるFlutter (言語でいえばDart)で開発したかったが、やはり最初はネット上のスクレイピングに関する資料の数を踏まえてFlutterは一旦断念しました。(C言語に近しく流行っていそうなので、近々やりたい。)
　もしFlutterでiOSアプリを作ってもAppstoreに出すには手数料$99/1yearがかかるので、ちょっとハードルが高い...
　App Storeを見ると他の大学でも、個人で学内ポータルへのログイン機能や通知機能実装した非公式アプリをリリースされている方がいるが、手数料払っているってことですよね。すご。
***

# 開発内容
　pythonでWebClassの更新を知らせるツールの作成(スクレイピングの使用)

# 開発環境構築
　Pythonと、コード全部ベタ打ちは嫌なので、Visual Studio Code をまずインストールしました。
　ちなみにPythonは公式配布版とAnaconda版があるが、記事数的に公式配布版を選択しました。VS Codeは日本語設定とPythonの開発環境設定をしました。Pythonスクレイピングで調べれば、スクレイピングライブラリのSelenium+Web driverの記事が溢れているので、最初は全然困らないです。
　Web driverは各ブラウザにありそうだったが、人口が多そうなChrome driverにしました。

 ここら辺のPython環境構築は記事が溢れているので省略...
 
***

 次記事に続きます。
 
https://qiita.com/Chronos/items/7f56898af25523d04598
安価な中華ガイガーカウンターをもうちょっと改良(放射線測定マップの作成 Ⅶ)

安価な中華ガイガーカウンターをIoT化(放射線測定マップの作成 Ⅰ)
https://qiita.com/nanbuwks/items/7ee0bf85be3ff3730405

では、中国製のガイガーカウンター BR-9B を改造して、 IoT化 しました。
その記事では最低限の加工で済ますようにしたために、いくつか使いでが悪いところがあります。


例えば、BR-9B は起動のためには手動操作で ON キーを押す必要がありますが、それより前に ESP32 モジュールの電源が入っていると、 BR-9B が起動するまでにカウンターがものすごい勢いで増えていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/aac284c5-68e5-54f5-bc0c-e87931805d8c.png)

この問題があるために、起動時にはタイミングよく ON キーを押すか、クラウドに上がった最初のデータはノイズとして除外する必要があり、運用テクでカバーするやりかたでした。

記事執筆時には、多くの方に改造してもらうために簡単な方法に特化しましたが、それでも敷居が高いという声があり、その後改造済みのガイガーカウンターをエンドユーザに供給するという方向にピボットすることにしました。

となると、手の混んだ改造ができるようになるので、それで使いづらいいくつかの問題を解消することにします。

# ものすごい勢いで増える件

改造を追加して、 BR-9B の起動を検出するようにしようかと思いましたが・・・これについては次の改造で、電源を強制的に ON にすることで解消することにしました。

# 電源を強制的に ON にする

BR-9B の回路は 3.3V で駆動しています。ON キーを押すと 3.3V リニアレギュレーターが作動を開始し、BR-9B がスタートするのですが、その回路とは別に、BR-9B の 3.3V 系にESP32 モジュールの 3.3V を供給するようにします。

それに伴い、本体側の USB コネクタ、電池ボックスは使えなくなります。共用するには、ダイオード追加する必要があります。

# 放射線測定機能をスタートする

BR-9B は電源 ON になってもラザフォードの恩顔が表示されて、しばらくしたあとにキーを押さないと放射線測定機能がスタートしません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d942f4cb-c604-1ebd-288f-877470bf7d2c.png)

L、M、R キーのいずれかを押すと測定が開始されます。

更に、測定中のキーの働きは以下のとおりです。


- L キー サウンドのOn/OFF
- M キー 平均値のリセット
- R キー バックライトOFF 
- L と R キー同時押し 累積値のリセット

なので電源ONになったしばらくあとにいずれかのキーを ESP32 から押すようにします。
今回は M キーを押すようにしました。

# 工作

BR-9B の  R4,T3,T2がつながっているいずれかへ から放射線検出信号を取り出します。


![IMG_20240222_220432.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a7e5406e-4ef0-5649-83e5-39b967ded0bf.jpeg)


3.3V 電源(オレンジ)とGND(黒)、Mキー(緑)はサービスポートから取り出します。ちなみにあと1つの端子はRキーです。

![IMG_20240222_220416.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3ecc5924-a097-6e92-27d5-c5bf9f2c881c.jpeg)

3.3V 電源は ESP32 モジュールの 3V3端子へ。
![IMG_20240222_221118.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/aa493a8b-aec9-8aea-bca3-be7d8f60c0ac.jpeg)

GND、放射線検出信号、Mキー は GND/D27/D26 に取り付けました。
![IMG_20240222_221015.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d0130821-17e7-aada-b234-98e7c980f66c.jpeg)

ESP32 モジュールに USB ケーブルをプラグすると BR-9B が電源が入ることを確認します。
![IMG_20240222_220904.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3fd7b95c-6c0e-00ba-b31c-fbf65fa63cfa.jpeg)

ちなみに、写真の黒いのは、液晶のダメージです。工具などと一緒にガラガラと運んでいたためです。割と弱い感じなので気をつけないと・・・

# サンプルプログラム

M キーをタイミング良く押すようにしてみました。

```
int count;
void setup() {
  Serial.begin(115200);
  pinMode(27, INPUT);
  delay(1000);
  Serial.println();
  Serial.print("waiting...");
  // BR-9B splash pass
  for( int i=7 ; i>0 ; i--){
    Serial.print(i);
    Serial.print(" ");
    delay(1000);
  }
  pinMode(26, OUTPUT);
  digitalWrite(26,LOW);
  delay(2000);
  pinMode(26, INPUT);
  Serial.println("start");
  
}

void loop() {
   int check=digitalRead(27);
   if ( 0 == check ) {
     count=count+1;
     Serial.println(count);
     delayMicroseconds(200);
   }
}
```

これで USB ケーブルをプラグして、ラザフォードが出たあとに放射線測定画面になれば OK です。

このスケッチの `setup()` をその他のスケッチに持っていけばいいですね。
【VSCode】MarkdownファイルからePubを作成する時に困った話

# この記事は...

VSCodeで執筆した.mdファイルを、出来るだけ簡単にePubファイルに変換したかった。
VSCodeに **Markdown Preview Enhanced** をインストールすれば良さそうだ。
首尾よく行けば、.mdファイルのプレビューから右クリックで「Export > eBook > ePub」を選択するだけで、.epubファイルを作成できるはず。

[公式ドキュメント](https://shd101wyy.github.io/markdown-preview-enhanced/#/?id=markdown-preview-enhanced)も丁寧だったので、挑戦してみた際のエピソードです。

# 実行環境

- MacOS 14.3.1
- Visual Studio Code 1.86.2

## Markdown Preview Enhancedの準備

普通のVSCodeエクステンションと同様に、検索してインストールしただけ。
似たような名前の偽物が多いので、注意（本物の発行者はYiyi Wang）。

.mdファイルをePubやPDFにエクスポートするには、Macに [**Calibre**](https://calibre-ebook.com/download) なるアプリケーションをインストールする必要があるとのこと。
実際にはCalibre自体ではなく、そこに含まれる **ebook-convert** が必要らしい（これのせいで1日中、試行錯誤する羽目になった）。

ともかく、MacにCalibreをインストールする。
そして、ドキュメントにも指示があるが、**シンボリックリンク** を作成しなさいという話になる。
「シンボリックリンク？」
よくわからないけど、ターミナルでコマンドを実行すれば良いと書いてあるので、素直に従った。

[Markdown Preview Enhancedの公式ドキュメント](https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/ebook?id=ebook-convert-のインストール)に表記されていたコマンドは以下の通り。

```terminal:公式ドキュメントのコマンド
$ sudo ln -s ~/Applications/calibre.app/Contents/MacOS/ebook-convert /usr/local/bin
```

上の通りに実行したら、パスワードの入力を求められたので成功したように見えた。

VSCodeのトップレベルに適当な.mdファイルを置いて、そこに`ebook front-matter`と呼ばれるメタデータを記載すれば準備完了。
その.mdファイルのプレビューで右クリックして、エクスポート！

`spawn ebook-convert ENOENT`

どうやら、「ebook-convertのエントリーがない」というエラーが発生したことを告げているらしい。

### シンボリックリンクとは？

何がどう間違っていたかわからないので、あやふやなまま進めてしまった手順を振り返ることにした。

シンボリックリンクは「Macでいうところのエイリアス」とか「PCでいうショートカット」みたいなものと理解しておけば良さそう。
そして、ターミナルで実行した`ln`コマンドは、リンクを作成するためのものだったようだ。


```terminal:lnコマンドの基本
ln -s 「シンボリックリンク元のパス」 「シンボリックリンクを作成する場所のパス」
```

`-s`は「シンボリックを指定するオプション」で、これがないと「ハードリンク」になるらしい。
「シンボリックリンク元」には、`~/Applications/calibre.app/Contents/MacOS/ebook-convert`を指定していた。
「作成する場所」には、`/usr/local/bin`を指定していた。

## やり直し

いろいろ調べたところ、`~`がいらないっぽい。
`~`はルートだかホームだかの意味だった気がしたけど、忘れたので誰か教えてください。
とにかくいらない。
ターミナルで実行すべきだったコマンドは、以下の通り。

```terminal:実際に成功したコマンドのコマンド
$ sudo ln -s /Applications/calibre.app/Contents/MacOS/ebook-convert /usr/local/bin
```

それでも、VSCodeでePubファイルを作成することは出来なかった！
絶望しつつも調べ漁ると、シンボリックリンクは上書きされないという事情が判明した。
間違って作成したシンボリックリンクは、明示的に削除する必要があるとのこと。

リンクの削除コマンドは以下の通り。

```terminal:シンボリックリンクを削除するコマンド
unlink /usr/local/bin/ebook-convert
```

上記の`unlink`コマンドを実行してから、再びVSCodeのプレビューでエクスポートを試したところ、成功！
ものの数秒で、同じフォルダに.epubファイルが作成されていました。

疲れた。
特定のpathに変更があった際にGithub Actionsを動作させる

## はじめに
個人開発でCI/CDをGithub Actionsで作成していた際に、ある特定のファイルやディレクトリに変更があった際にのみ実行する方法を調べたのでまとめていきます。

## 修正前のワークフロー
以下が実際に個人開発で使用していたワークフローです。
OpenAPIで定義したyamlファイルをhtmlに変換し、それを指定したサーバにホスティングするという内容です。この状態だと、yamlファイルの変更時だけでなくアプリケーションコードやその他のAPIドキュメントに関係のないコードが変更された場合にもこのワークフローが実行されてしまいます。

```yaml
name: API Document Hosting

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Convert YML to HTML
        run: |
          npm install -g redoc-cli
          redoc-cli bundle reference/devlocator.yaml -o ./docs/index.html
      
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs

      - name: Deploy to Hosting PC
        uses: appleboy/scp-action@v0.1.4
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          key: ${{ secrets.KEY }}
          passphrase: ${{ secrets.PASSPHRASE }}
          source: "index.html"
          target: "/var/www/html/api"
```

## 特定のpathsの変更のみ検知するには？
公式ドキュメントのワークフロー構文にありました。
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore

`paths`を使うことで指定したpathsでの変更のみがワークフロー実行のトリガーとなります。

## 修正後のワークフロー

```yaml
name: API Document Hosting

on:
  push:
    branches: [main]
    paths:
      - "reference/openapi.yaml"
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Convert YML to HTML
        run: |
          npm install -g redoc-cli
          redoc-cli bundle reference/devlocator.yaml -o ./docs/index.html
      
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs

      - name: Deploy to Hosting PC
        uses: appleboy/scp-action@v0.1.4
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          key: ${{ secrets.KEY }}
          passphrase: ${{ secrets.PASSPHRASE }}
          source: "index.html"
          target: "/var/www/html/api"
```

## 終わりに
`paths`を加えることでより効率の良いワークフローができたのではないでしょうか！
CI/CDは今やどこの開発現場でも目にするので、当たり前に導入してより効率の良い方法を学習していきたいですね。cacheなんかは高速化の代表的な方法なので別記事にまとめていきます💪
デジタル署名とデジタル証明書の違い

<h2>名前が似てるけど違う</h2>
資格の勉強してたら、混同してしまったので整理するために調べる。

ディジタル署名とデジタル証明書。名前は一文字違い。
紛らわしすぎるので、ざっくりまとめる。

<h2>デジタル署名</h2>
データの正当性を保証するために、データの送信者の署名を電子的施す。この一連の技術をデジタル署名と呼ぶ。(引用：2024年度版ITストラテジスト　オールインワンパーフェクトマスター)

 　

通信をする時に、送信者が自身の秘密鍵で送るデータを暗号化して、ハッシュ化したもの。

受信者は公開鍵でデータ本体を再度暗号化して、ハッシュ化。自分で暗号化したハッシュと送られてきたハッシュが同じかを比べて、データが送信者本人からのもので、改ざんされていないかを確認する。

詳しい仕組みは以下のサイトが分かりやすかったです。

https://www.infraexpert.com/study/security5.html

<h2>デジタル証明書</h2>
デジタル証明書とは、配送されてきた公開鍵の所有者の真正性を確認するために送付されてくるデータセットである。(引用：2024年度版ITストラテジスト　オールインワンパーフェクトマスター)

つまり、公開鍵が本物ですよと証明するもの。上のデジタル署名のところで、送信者の公開鍵を何らかの方法で入手した際、これが本当に送信者の物ですか？偽物じゃないですか？というものを確認するデータセット。

CA(認証局)という第三者機関があって、そこに公開鍵とデータセット(デジタル証明書)を持っていくと、CAが「正しいですよ！」と太鼓判を押してくれる(正しいとデジタル証明書に"署名"してくれる)。

<h2>違いは？</h2>
どちらも何らかの正しさを担保するものでありつつも、担保するものがデジタル署名では送信するデータで、デジタル証明書では公開鍵という違いがある。

”何を”正しいと担保するのかが違う。

資格の勉強用なので、覚え方としては、
デジタル署名：署名は自分の名前を書くもの→自分(送信者)が書くもの→自分自身のデータを担保する
デジタル証明書：証明するには第三者機関が必要→CAが必要→でも、データを第三者に証明してもらうのはおかしい→公開鍵を担保する

くらいで覚えることにします。

<h2>参考</h2>

https://www.infraexpert.com/study/security5.html

2024年度版ITストラテジスト　オールインワンパーフェクトマスター
読めば少し分かった気になれるLookMLの構成要素（前編）

## はじめに
こんにちは、カスヤです。
Lookerを触り始めることになったので、LookMLについて、そしてその反映結果について、公式の説明を基にしつつ、自身の解釈も加えて残しておこうと思います。前半ではLookMLオブジェクトの構成要素に焦点を当て、後半ではこれらの要素がビジュアライゼーションにどのように反映されるかについて詳しく解説していきます。

[後編はこちら（ビジュアライゼーションへの反映結果）](https://qiita.com/pull_request/private/dd611e5f2b6c80f345b2)
## LookMLとは
データモデリング言語。Googleのデータプラットフォーム製品、Lookerで使用される専用言語のこと。LookMLを書く目的は、データモデルの定義（データベースの情報をLookerに渡すための定義）をするためである。

### データモデルの定義レイヤーを持たせる理由
LookerはよくBIツールと比較されるけれど、ほかのBIツールと違いデータモデルを定義するレイヤーを持っている。


これの何が良いかというと、一般的にBIツールのデータソースとしてデータベースを選択した際、同じDBを参照しているはずの2つのレポートが謎の差を出して表示される場合がある。


これを調査していくと参照設定が少し違い、それが差分を生んでいることがある。

このように、レポート運用で問題になりがちなレポートデータの揺れはデータモデリング層を設けることで防ぐことができるよね、という理由。（これをデータのガバナンスが効くと言う。）


![LookML説明.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/8c532243-4630-e92a-c88f-a456c497402a.jpeg)[筆者図説]

### データモデリングを行うLookMLオブジェクトの構造

データモデリングを行うために計6つのオブジェクトで構成されていて、
関係性を図で表すとこのようになる。
これらの要素はすべてコードで構成されていて、
Lookerサービス内で提供されるGitリポジトリに管理することができる。

![スクリーンショット 2024-02-22 211939.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/a32d50d0-bb59-23c0-18bc-1e63d38dd6b8.jpeg)[筆者図説]

Big Queryにサンプルデータ（ecommerce）を用意し、それをLookMLで定義していきながら構成要素を説明していく。

#### Project
データモデリングを格納する場所。一番大きい要素。プロジェクト1個に対して以降の要素はN個 作成できる。例えば「2024_ecommerce」など任意の名前を付けられる。
#### Model
関連性を格納する場所。厳密にはズレるかもしれないが参照単位としては「Modelファイル1個≒DBのスキーマ1本」のようなイメージ。
- データベースの接続情報
- Exploreを複数定義した集合体
上記を含んだオブジェクトがModel。

例えばBig Queryに用意したデータセットを参照するとModelファイルはこのような見た目になる。

![model.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/3360d37e-b964-f864-4fb4-9623734662a9.jpeg)
#### Explore
上の図で見えているように、modelファイルに属する。1つあるいは複数のViewをjoinしたものがExploreになる。Viewのjoin種類は以下。
- left_outer（デフォルト）
- full_outer
- inner
- cross
ここで定義したものが後編のビジュアライゼーションでフィールドとして選択出来るようになる。
#### View
単位にすると「Viewファイル1個≒テーブル1本」このイメージが近い。
![View.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/7395122b-40fa-db28-fc22-96a6beb8da4c.jpeg)
Big Queryに7本のテーブルが存在する状態で参照すると7本作成された。
Dimensionの集合体がViewになる。
#### Dimensions
単位にすると「Dimension1個≒テーブルのカラム1個」このイメージが近い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/624af3c6-0733-67d7-5bc4-7e99080c3b91.png)

DBのどのカラムを取得するかを定義する。カラムは勿論そのまま参照することも出来るし、
計算したり関数でカラム同士を結合したり追加の定義をした上で参照することもできる。
#### Measures
関数定義を保持する。Dimensionと同じレベルに定義する。
![measure.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632589/15977fe2-b3da-1ac2-4fcb-691cb5132874.jpeg)

sumやaverage、countをしてLookerオブジェクトをレポートやダッシュボードに表示できるように定義する。さらに細かい条件でデータをフィルターしながら、カウントすることなどもできる。



以上、
とりあえず前編でした。
Macの不可視ファイル（ドットファイル）をFinderで見られるようにする

Macにはドットファイルと呼ばれる不可視ファイルがあります。
ファイル名、フォルダ名の頭に"."がついてると不可視ファイルになって、通常はFinderでは確認できず、ターミナルの ls -aで確認することができます。
※ .bash_historyや.zshrcなどがそうです。

Finderで操作したいときありますよねー

ということでFinderに表示させてみます。

# 可視化させるコマンド
普段Pythonの勉強に使っているフォルダです。
venv環境で作用しており、prac0005の下には.venvフォルダがありますが、標準では見えません。
<img width="90%" alt="スクリーンショット 2024-02-22 22.47.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456861/17f20d1f-0fe4-1f54-0de3-4b974aace3e3.png" >

ターミナルを起動して以下のコマンドを実行します。

```
% defaults write com.apple.finder AppleShowAllFiles TRUE
% killall Finder
```

1行目のdefaultコマンドを実行したのち、設定を反省させるためにkillallコマンドでFinderを再起動しています。

再起動したFinderを確認すると、parc0005の下に.venvフォルダ、更にその下にもフォルダ・ファイルが確認できます。
<img widht="90%" alt="スクリーンショット 2024-02-22 22.57.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456861/d4be90e0-8608-3618-a203-0a9cddac4762.png">

# もう一度不可視にする
一時的に可視状態にしたのち、もう一度不可視にしたい場合もあると思います。
その場合は可視化したときのコマンドをFALSEで実行します。

```
% defaults write com.apple.finder AppleShowAllFiles FALSE
% killall Finder
```

Finderを再起動してあげる必要があるのは同じです。
これでもう一度不可視になりました。
<img width="90%" alt="スクリーンショット 2024-02-22 22.47.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456861/17f20d1f-0fe4-1f54-0de3-4b974aace3e3.png" >

# コマンドを使わない方法
上記はターミナルからコマンドを使って不可視ファイルを表示させましたが、キーボードショートカットでも変更可能です。
```
command + shift + .
```
これでも可視・不可視を変更可能です。
こちらの方がスマートでしょうか。

ちなみにコマンドで変更した場合、可視状態にしていてもアプリケーション上のファイル・フォルダ選択時のウインドウでは相変わらずドットファイルが見えない場合があります。
そういった場合でもキーボードショートカットを使えば表示されるようになるので、ショートカットを憶えておいた方が利便性は高そうです。
【HTML】削除ボタン付きタグのサンプル

## 削除ボタン付きタグとは？

こういうの。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649673/25e849ec-9dde-1fbd-c27c-2c8aa8526412.png)

## コード

ChatGPT3.5くんがほぼ作ってくれました。
マジで便利。

```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tagged Select List</title>
<style>
  .tag-list {
    display: flex;
    flex-wrap: wrap;
    padding: 5px;
    border: 1px solid #ccc;
    border-radius: 5px;
  }
  .tag {
    display: flex;
    align-items: center;
    background-color: #f0f0f0;
    padding: 3px 6px;
    margin: 3px;
    border-radius: 3px;
  }
  .tag-name {
    margin-right: 5px;
  }
  .tag-close {
    cursor: pointer;
  }
</style>
</head>
<body>

<div class="tag-list" id="tagList">
  <!-- タグがここに追加されます -->
</div>

<select id="itemSelect" onchange="addItem()">
  <option value="item1">アイテム1</option>
  <option value="item2">アイテム2</option>
  <option value="item3">アイテム3</option>
  <option value="item4">アイテム4</option>
</select>

<script>
  function addItem() {
    const select = document.getElementById('itemSelect');
    const selectedItem = select.options[select.selectedIndex].text;

    const tagList = document.getElementById('tagList');

    const tag = document.createElement('div');
    tag.classList.add('tag');
    tag.innerHTML = `
      <span class="tag-name">${selectedItem}</span>
      <span class="tag-close" onclick="removeItem(this)">❎</span>
    `;

    tagList.appendChild(tag);
  }

  function removeItem(element) {
    element.parentNode.remove();
  }
</script>

</body>
</html>

```