OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】さくらインターネットの共有サーバーでFlaskを使ったWEBアプリケーションデプロイ

クライアントの指示でさくらインターネットの共有サーバー上でFlaskで作成したWEBサイトをデプロイする必要があって、かなり手こずったので備忘録も兼ねてやり方を解説します。

# 前提条件

- さくらのレンタルサーバー スタンダードプラン 以上を契約している
- ローカル環境でエラーなく実行できるFlask構築のWEBアプリがある状態

# デプロイの流れ

1. さくらサーバーにpip & flaskをインストールする
2. FTPソフトでwwwディレクトリにWebアプリケーションをアップロード
3. index.cgi & .htaccessの作成
4. デプロイの確認

## さくらサーバーにpip & flaskをインストールする

まず、sshでレンタルサーバーに接続する。ssh接続は、sshクライアントを使うか、もしくは windows備え付けの コマンドプロンプト（以下cmdと省略）で行います。

cmdで以下のコマンドを入力。

```bash
ssh ユーザー名@サーバードメイン名
```

ユーザー名とサーバードメインはさくらサーバーコントロールパネルから確認できます。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191791/c2c391a0-df12-5aba-b6cc-9101f30c5de3.png)

アカウントがユーザー名で、初期ドメインがサーバードメイン名。

パスワードの入力を求められるので、契約時に設定したパスワードを入力。

ssh接続ができたら、まずは以下のコマンドでpipのインストーラーをカレントディレクトリにダウンロード

```bash
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
```

次にインストーラーを起動

```bash
python get-pip.py
```

下記の画面が出てきたらインストール完了。
ただし、PATHは設定されてないので、そのままでは pipが使えません。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191791/c0349451-8370-53fe-5ff8-ec6cbe66fe53.png)

pipがインストールされたディレクトリに移動します。

```bash
cd .local/bin
```

pipでflask & 各種ライブラリをインストール

```bash
python pip install flask
```

Successfully installed … と表示されればインストール完了

## FTPソフトでwwwディレクトリにWebアプリケーションをアップロード

FTPクライアントソフトでサーバーとFTP通信を行いますが、FTPソフトのホスト名は`www○○○.sakura.ne.jp` であることに注意、コントロールのサーバー情報→サーバー情報で確認ができます。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191791/1ef66112-e7f9-dd16-60fb-56959ddfd6d5.png)

ローカルから`/home/username/www/` に各種ファイルを転送。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3191791/941c3e2a-a547-b4aa-709e-b478eea63488.png)

## index.cgi & .htaccessの作成

色んな文献や記事の通りに書いてもうまくいかなく、最終的にChatGPTの力も借りながら、色んな事を試して結果以下の内容となりました。

```python
#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import cgitb
cgitb.enable()

from wsgiref.handlers import CGIHandler
from app import app
from sys import path

class ProxyFix(object):
  def __init__(self, app):
      self.app = app
  def __call__(self, environ, start_response):
      return self.app(environ, start_response)
if __name__ == '__main__':
   app.wsgi_app = ProxyFix(app.wsgi_app)
   CGIHandler().run(app)
```

```
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cgi/$1 [QSA,L]
<Files ~ "\.py$">
  deny from all
</Files>
```

パーミッションはそれぞれ755

## デプロイの確認

最後にサイトのURLを叩いて、実際に表示されるか確認。表示されなければ、各ファイルや app.pyにエラーは発生してるか確認を行う。
【Ubuntu】 Anaconda Django環境構築 

# 自分のPCから運用サーバーへ
自分のPCから馬場研のサーバーへSSH接続をする。

```
ssh 名前@IPアドレス -p ポート番号
```

### 1. Anacondaをインストールする
下記サイトを参考にした。

https://phoenixnap.com/kb/install-anaconda-ubuntu

今回はAnaconda3-2023.09-0-Linux-x86_64.shをインストール。
```
cd /tmp
curl -O ダウンロードしたいバージョンのURL
```
次に下記コマンドを実行。
```
bash Anaconda3-2023.09-0-Linux-x86_64.sh
source ~/.bashrc
```
自分の場合、上記のコマンドを打ってもcondaコマンドが使えるようにならなかった。
つまりcondaのPATHが通ってない。

### 2.AnacondaのPATHを通す。
下記サイトを見つけた。

https://pa-kamedia.net/2020/08/20/%E3%80%90ubuntu%E3%80%91bash%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E5%BE%8Cconda%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E8%AA%8D%E8%AD%98%E3%81%97%E3%81%AA%E3%81%84/

```
sudo nano ~/.bashrc 
export PATH=/適切なPATH/anaconda3/bin:$PATH' #この行を.bashrcに追加
```
この方法で.bashrcに適切にPATHを加えると通った。
PATHが通ってるかの確認。
```
conda info -e
```

仮想環境を作ってみる。
```
conda create -n 環境名
conda activate 環境名
```
ここでconda initのエラーが出るので下記コマンドを実行。
```
conda init bash
```
以上でAancondaの環境構築は終了です。
並列で md5sum のチェックを行うのは簡単

ネットでググってもすぐに解答が出てこないが実は簡単なのでメモする。

```sh
md5sum -c md5sum.txt
```

`md5sum.txt` が `-c` オプションの引数に見えるが、そうではないのがポイント。
実は、標準入力から md5sum.txt をコマンドに渡すことも可能だ。

```sh
cat md5sum.txt | md5sum -c
```

これさえ理解すればあとは簡単である。`md5sum.txt` を分割して標準入力から渡してやればいい。あとは好きなUnixの並列化コマンドを使うだけである。ここでは `xargs` を使って `-P 4` を指定した。

```sh
cat md5sum.txt | xargs -I{} -P 4 sh -c "echo \"{}\" | md5sum -c"
```

`md5sum` の計算は高速である。だから並列数を増やしてもIOがボトルネックになりやすい。IOと計算のどちらがボトルネックになっているか `htop` などでモニターしながら調節すればいいと思う。

この記事は以上です。
DjangoテンプレートでQuerySetをJSに渡す

テンプレートでQuerySet型の値をjavascriptに渡したい

配列型や辞書型なら以下の通りで渡せるが、QuerySet型の場合はそのまま渡せない。
```javascript
const sample = {{ object|safe }}
```

テンプレートタグを自作して対策した。

## テンプレートタグの作り方
まずは独自のテンプレートタグの作り方
1. アプリフォルダにtemplatetagsフォルダを作成
1. templatetagsに `__init__.py` の空ファイルを作成
1. templatetagsに `my_tags.py` のファイル（名前は自由）を作成し、ここに独自のテンプレートタグを作成してく。

```
app
├── views.py
├── ...
└── templatetags
    ├── __init__.py
    └── my_tags.py
```
テンプレートタグの作り方
```python:templatetags/my_tags.py
from django import template  # 必須

register = template.Library()  # 必須

@register.simple_tag  # 必須
def double_number(number):
    return number * 2
```

テンプレートでの使い方
```django:sample.html
{% load my_tags %}  {# ← 呼び出し #}

<p>2倍にする {{ double_number num }}</p>  {# 「タグ名 引数」のように使用する #}
```

## QuerySetを配列に変換
QuerySet型を配列に変換するテンプレートタグを作成していく。
```python:templatetags/my_tags.py
from django import template

import json
from datetime import date, datetime, time
from decimal import Decimal
from django.utils.safestring import mark_safe

# date, datetime, time, decimalの変換関数
def json_serial(obj):
    if isinstance(obj, (datetime, date, time)):
        return obj.isoformat()
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError ("Type %s not serializable" % type(obj))

register = template.Library()

@register.simple_tag
def queryset_to_json(queryset):
    ary = list(queryset.values())  # 1
    json_ary = json.dumps(ary, ensure_ascii=False, default=json_serial)  #2
    return mark_safe(json_ary)  #3
```

1. list(queryset.values())
    クエリセット内のオブジェクトを辞書の配列に変換
1. json.dumps(ary, ensure_ascii=False, default=json_serial)
    ここでjsonに変換する。しかしデータの中にオブジェクト（datetimeやdecimalなど）が含まれていると、エラーが発生するので、`default=json_serial` で変換の定義を行っている。ここでは `date, datetime, time, decimal` の変換を定義しているが、必要に応じて記述していく
1. mark_safe(json_ary)
    HTMLエスケープを行わない

テンプレートでの使い方
```django:sample.html
{% load my_tags %}

<script>
const sample = {% queryset_to_json object %};
</script>
```
Google Drive から大きいファイルをリモートにダウンロードする

# Issue
モデルのチャックポイントのような巨大なファイルはGitHubなどには置いておけないため、普段はGoogle Driveに保存しているので、そこからリモートサーバなどにダウンロードする必要があった。

# Solution
## 1. ファイルを共有可能にする
Google Drive上で右クリックを押し、共有->共有->一般的なアクセスを”リンクを知っている人全員”に変更

## 2. ファイルIDを取得
上記で共有したファイルの共有リンクが以下の形式だとすると、
```
https://drive.google.com/file/d/<file_id>/view?usp=drive_link
```
file_idの部分がIDなのでローカルのどこかに控えておく

## 3. リモートでダウンロード
まずgdownをインストールする
```
pip install gdown
```
その後以下のfile_idを変更して入力し、プログレスバーが出ればダウンロード開始

```
gdown https://drive.google.com/uc?id=<file_id>
```

# Reference 
https://stackoverflow.com/questions/25010369/wget-curl-large-file-from-google-drive
RHEL9系でphp-memcachedが入らない

## 事象
RHEL9でphpのmemcachedモジュールを有効化しようとインストールを試みるも、上手くいかない。
依存解決でlibmemcachedというパッケージが必要だが、リポジトリ上に無い様子。

## 原因
RHEL9ではlibmemcachedがデフォルトで有効なリポジトリに存在せず、`CodeReady Linux Builder`というリポジトリを有効化しないといけないようだ。
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/package_manifest/codereadylinuxbuilder-repository

## 対応
リポジトリを有効化
```
dnf config-manager --set-enabled codeready-builder-for-rhel-9-rhui-rpms
```
確認
```
dnf repolist
repo id                                           repo name
codeready-builder-for-rhel-9-rhui-rpms            Red Hat CodeReady Linux Builder for RHEL 9 aarch64 from RHUI (RPMs)
```
再びインストール
```
dnf install php-memcached
```
無事にインストール出来た。

## 補記
上記リポジトリはRHELのサブスクリプションを有効化していないと利用できないようで、以下のような手順でインストールしている記事も見つけた。
https://qiita.com/chaoticcast/items/f9a2bfab9e52fc99a753
（記事中に筆者も記載の通り望ましい手段ではない為、パッケージで利用できるならそちらを使うべき。）

## あとがき
Qiita初投稿なので、おかしな点があればご指摘いただけると大変助かります！
`npm ERR! code ECONNRESET`が出たので対応した。

# 前置き
とても初歩的な内容ですが、初歩的過ぎて逆に情報が見つかりずらいやつでしたので、備忘録的にメモしておきます。
***
vueを使ってWebアプリを作っている際に、プロジェクト内にFirebaseをinstallしようとしたらエラーが出ました。
エラー文はこちら。
```
$ npm install firebase　//このコマンドに対して下記のエラー

npm ERR! code ECONNRESET
npm ERR! syscall read
npm ERR! errno ECONNRESET
npm ERR! network Invalid response body while trying to fetch https://registry.npmjs.org/@firebase%2fapp-types: read ECONNRESET
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network 
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'

npm ERR! A complete log of this run can be found in: C:\Users\**\AppData\Local\npm-cache\_logs\2024-04-18T02_18_43_271Z-debug-0.log
```

# 解説
ざっくりこのエラーの意味を解説します。
## ECONNRESET
このエラーコードは、TCP接続が相手側によって強制的にクローズされた、または「リセット」されたことを意味します。
つまり、データの送受信中に接続が失われたかもってことですね。
## syscall read、errno ECONNRESET
これはシステムコール read が、接続リセットのために失敗したことを示しています。
そりゃ接続切れたら失敗します。
## Invalid response body while trying to fetch [URL]
指定URLのパッケージをダウンロードしようとしたけど、接続問題により適切なレスポンスがなかったよってこと。
そりゃそう。
## network connectivity issues
「問題がネットワーク接続に関連してるっぽいよ」って教えてくれてます。優しい。
特にプロキシの設定やネットワークの設定が原因である場合が多いみたい。
# 結論
ネットワークの接続に問題があるよ！
です。
確認したら、そのinstallかけた時間だけブラウザもうまくページを読み込めてなかったです。
ネットの接続を再確認して、再度installをかけたらすんなり成功しました。
転載記事 量子計算機を用いた変分量子化学計算の動向・前編


注 : この記事は2021年一月初めに書いたものを転記したものです。

明けましておめでとうございます。

去年は量子計算機を用いた変分量子計算アルゴリズムが大幅に発展し、量子化学計算分野でも多くの成果が発表されました。

なので新年一稿目の記事では、変分量子化学計算とその発展について解説します。



VQE法：

変分量子化学計算に扱われるアルゴリズムはすべてVariational Quantum Eigensolver(VQE)とその発展型です。VQEは、第二量子化されたハミルトニアンはパウリ演算子に変換できることを利用して、量子計算機で量子系のエネルギー固有値を解くアルゴリズムです。

まず、第二量子化されたハミルトニアンは局在電子系(Hubbard model)の場合、あるサイトに局在する電子の生成、消滅演算子を用いて、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/495e4b12-c9f0-2eee-aab9-6fea2d616226.png)

と表されます。i,j,k,lにはスピンが含まれることもあるため注意が必要です。このハミルトニアンをJordan-WignerあるいはBravyi-Kitaev変換[1]することで、パウリ演算子で表される形に直します。

それのみならず、初期状態にもこの変換を掛けます。その変換行列も、それぞれの変換で異なります。



これだけではエネルギー固有値は求まらず、クラスターが必要です。この演算子は任意の固有状態を作るためのものです。これも様々なものがあり、計算時間と出せる最高精度には差があります。中でも、計算時間はかなりかかるのと引き換えに精度の高い方法がUCCSD[2]です。これは、一電子励起と二電子励起を起こすオペレーターとその共役演算子を付加するのです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/d053b844-8827-0c38-4d45-86c46251c133.png)

クラスターもパウリ演算子に変換します。和の形では量子状態に作用させることは出来ないため、鈴木・トロッター分解によって、係数は小さいと仮定して、 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/b1227c8e-ba36-fa12-15b6-2c84cac1cc22.png)

とします。ここで、﻿$ P _ { jk } $は変換されたクラスターにおける演算子、﻿$ t _ { jk } $ はその変数、﻿$ θ _ k $は最適化変数です。最適化変数は、クラスターの反復回数(深さ)Nを増やせばなくてもいいのですが、現実には4程度までしか増やせないので、付加されています。

これによって初期状態は、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/55c085ba-881f-bc25-0ef9-f5c8d78bcfc4.png)
 
と変換されます。一般的には、このように初期状態とする波動関数にクラスターを付加して試行状態を作り、ハミルトニアンのそれぞれの項に対して期待値を求めます。しかし場合によっては、変数を付加し鈴木・トロッター分解したハミルトニアンも試行状態に作用させます。

こうして作られた試行状態の評価関数、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/6c27d590-e56a-c064-1c71-3f076faeefd3.png)

を古典最適化し、その極小値を求めます。また、励起状態を計算する場合は、そこにデフレーション項、 

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/c77b49d4-cca6-7ab1-07ea-6d3342ad0b44.png)

を加えます。後編ではそれぞれのプロセスにおける工夫と、それによる発展形を紹介します。



[1] Andrew Tranter, and et. al., Journal of Chemical Theory and Computation, 14(11), 5617-5630(2018)

[2] Panagiotis K.L. Barkoutsos, and et. al., Phys. Rev. A.98(2).022322(2018)
レスポンス データの読み込みに失敗しました: No resource with given identifier found

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/27b3ffaa-2fbe-bef7-7aa7-38590393e769.png)

`<meta http-equiv="Refresh">`でリダイレクトするとエラーになるらしい、Firefoxを使おう

```html
<meta http-equiv="Refresh" content="3;URL=https://example.com/">
```

https://happynap.net/2023-04-15-081747/
グローバーのアルゴリズム


本記事は、親記事である"量子振幅増幅と量子数値積分"のために、その前提知識であるグローバーのアルゴリズムの解説を行うものです。このアルゴリズムは、量子重ね合わせを利用して、古典アルゴリズムには不可能な速度で無秩序データリストから特定のものを検索することが可能です。このアルゴリズムの基幹をなすのが、オラクル演算子です。この演算子は、目的とする状態にのみπの位相を与える演算子です。まず、全ビットが0の初期状態を用意し、最初のn量子ビットにWalsh-Hadamardゲートを、アンシラビットにXゲートを掛けます。その後、オラクルを掛けます。それは図1のようにn量子ビットを制御ビットにアンシラビットを標的ビットに解となる状態のみを反転させるn+1ビット制御NOTゲートを作用させることで実現できます。

![Figgrov1v.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/434fb5da-16de-1197-c314-43e5d9c5b786.jpeg)


図1 オラクル演算子の量子回路。〇と●は検索したい状態によって変わります。

その後、グローバーの反復演算子を作用させます。これは $ G=H_n(2\mid 0 \rangle \langle 0 \mid - I)H_n$となる演算子です。解となる状態を$\mid \Psi_0 \rangle$、そうでない状態を$\mid \Psi_1 \rangle$とすると、これによって状態は$sin\sqrt{2^n}/2\mid \Psi_0 \rangle + cos\sqrt{2^n}/2\mid \Psi_1 \rangle$と変換されます。従って、オラクルとグローバーの反復演算子の積を$\pi \sqrt{2^n}/4$回かけることで目的の状態の存在確率が1になります。



![Figgrov2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/5edeb423-f40b-0d2b-dffd-573fea3d06db.jpeg)

図2 グローバーのアルゴリズムにおける量子回路。 

主な流れは以下のようになります。

1, 作業用量子ビットn個、アンシラ量子ビット1個を用意します。
2, 操作$A=H_{n}X_{n+1}$をn+1量子ビットからなる初期状態$\mid 0 \rangle_{n+1}$に作用させます。
3, 解となる状態のみの位相を逆転させるオラクル演算子$O$、$G=H_n(2\mid 0 \rangle_n \langle 0 \mid _n  - I)H_n$の積$OG$を$\pi \sqrt{2^n}/4$回作用させます。
4, 観測します。

実際に6量子ビットからなる状態$\mid 101000 \rangle$を検索する際の存在確率の変化を図3に示します。均等な存在確率が目的とする状態に$OG$を掛けるほどに偏り、最終的にそれのみになるのがわかります。これは量子振幅増幅アルゴリズムのもとになっています。





![FigG3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844109/d7f2d9c2-0830-39b1-9170-410587544c09.png)
 
図3 $OG$を作用させた回数と存在確率の関係。
ffmpegが使えなくなった．

# TL;DR;
以下のコマンドを順番に実行することで， `ffmpeg` で `m4a` ファイルから `wav` ファイルへ変換できるようになった．
```
$ brew reinstall libvmaf
$ xcode-select --install
$ brew reinstall ffmpeg
```

# 経緯
1. m4aファイルをwavファイルに変換したかった． (`$ ffmpeg -i input.m4a -vn -ar 16000 -ac 1 -ab 192k -f wav output.wav`)
1. ffmpegコマンドを実行した．
1. 以下のエラーが出た．
```
Library not loaded: /opt/homebrew/opt/libvmaf/lib/libvmaf.1.dylib
  Referenced from: <xxx> /opt/homebrew/Cellar/ffmpeg/6.0/bin/ffmpeg
```

# 直した手順
:::note info
筆者の環境は以下のとおりです．
- macOSのM1チップ
- brewが導入されている．
:::
:::note warn
冗長な手順や，不適切な手順が含まれている可能性があります．
間違いなどがございましたら，ご指摘をお願いします．
:::

参照先 `libvmaf` がloadされてないと言われるが，自分の環境は既に入っていたので，以下のコマンドを実行する．
```
$ brew reinstall libvmaf
```

これでも， `ffmpeg` が実行できなかったので， `ffmpeg` も `reinstall` したが， `xcode-select --install` を実行しなければならないという旨のエラーメッセージが出た．
従って，以下のコマンドを実行する．
```
$ xcode-select --install
```
すると，以下のようなポップアップが出るので，インストールを行う．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534163/1b0e969e-46ef-d49c-7a1c-33d110e02a1d.png)

インストールが終了したら，以下のコマンドを実行する．
```
$ brew reinstall ffmpeg
```

すると，ffmpegコマンドが実行できた！！！
```
$ ffmpeg -i input.m4a -vn -ar 16000 -ac 1 -ab 192k -f wav output.wav
```
ETL/ELTについて（Google Cloud）ChatGPTさんに聞きながらイメージをつかんでみた

# ETL ELTについて
Dataprocを使ったETL、Dataflowを使ったETL、BigQueryを使ったELTなど、Google CloudのETL/ELTを学ぼうとしただけでも、頭がいたくなりました。各処理の違いをChatGPTさんに聞きながらまとめたいと思います。一考え方です。

# ChatGPTに聞いてみました

Dataprocを使ったETL: ハドゥープやスパークなどのオープンソースデータ処理フレームワークを利用して、大量のデータ処理や分析を行います。バッチ処理に適しています。

Dataflowを使ったETL: ストリーミングデータとバッチデータの両方を処理できるフルマネージドサービスです。リアルタイムデータ処理が必要な場合や、複雑なデータ変換が求められる場合に適しています。

BigQueryを使ったELT: ストレージと分析機能を兼ね備えたフルマネージドデータウェアハウスサービスです。データを先にロードし、BigQuery内で変換処理を行います。スケーラビリティが高く、SQLによる分析が可能です。

いまいちわかならい。。。

# 使い分け例をきいてみました

バッチデータ処理で大規模なデータセットを分析したい場合: Dataprocを使用して、HadoopやSparkのエコシステムを活用しましょう。データの前処理や分析に適しています。

リアルタイムデータ処理が必要な場合: Dataflowを選択して、ストリーミングデータとバッチデータの両方を効率的に処理します。リアルタイムでのデータ変換や加工が求められるシナリオに適しています。

データウェアハウスにデータを集約し、SQLを使用して分析したい場合: BigQueryのELTが最適です。データをロードしてから変換することで、スケーラビリティと分析のパフォーマンスを最大化できます。

# 質問してみました
**Q1**　バッチ処理でもDataflowを選択するのはどういうケースか？
**A1**　Dataflowはバッチ処理でも選択されるケースとして、複雑なデータ変換や複数のデータソースからの統合が必要な場合です。また、将来的にリアルタイム処理を導入する可能性がある場合にも適しています。

**Q2**　バッチ処理で小規模な場合は？
**A2**　小規模なバッチ処理の場合は、Cloud Functionsや簡易的なBigQueryの機能を利用することが考えられます。コストを抑えつつ、シンプルなデータ変換やロードが可能です。

**Q3**　ELだけしたい場合は？
**A3**　EL（Extract and Load）のみを行いたい場合は、Cloud StorageとBigQueryの組み合わせが適しています。データをCloud Storageに格納し、BigQueryに直接ロードすることで、高速かつ効率的にデータを分析用に準備できます。

**Q4**　どれか１つを選ぶのではなくて、複数を組み合わせて使うのか？複雑になりそうな場合は、最初からDataflowを使うのか？
**A4**　複数のツールを組み合わせて使用することは一般的です。例えば、データ収集と初期処理にDataflowを使い、最終的な分析やデータの保存にBigQueryを使用するなど、各ツールの強みを活かした構成が考えられます。プロジェクトの複雑性や将来のスケーラビリティを考慮して、必要に応じて複数のサービスを組み合わせることが推奨されます。プロジェクトの初期段階からDataflowを使用する場合は、その柔軟性とスケーラビリティが複雑なデータ処理要件に対応できるため、適切な選択となる場合があります。

**Q5**　複数のツールを組み合わせると、管理がむつかしくないか？
**A5**　複数のツールを組み合わせると管理が複雑になる可能性があります。しかし、クラウドプラットフォームはこれらのツールを統合しやすくする機能やサービスを提供しています。例えば、Google CloudのDataflow、BigQuery、Dataprocなどは相互に連携して動作するよう設計されており、一貫した管理インターフェースやAPIを通じて、効率的な管理をサポートします。適切な計画と設計により、複雑性を管理し、シームレスなデータ処理パイプラインを実現できます。


**Q6**　dbtを使う場合はどのれが置き換えられる？全部？
**A6**　dbt (Data Build Tool) は、データ変換（特にTransformの部分）に特化しています。そのため、DataflowやDataprocといったデータ処理ツールのTransform機能と一部重複しますが、dbtはSQLによるデータ変換とテストに焦点を当てています。BigQueryでのELTプロセスにおいて、dbtはTransformの工程を強化し、データモデリングとデータ品質保証をサポートします。dbtはETL/ELTパイプラインの全体を置き換えるものではなく、データ変換をより効率的かつ信頼性高く行うためのツールです。

**Q7**　BigQueryを使ったELTをdbtに置き換えるイメージ？
**A7**　dbtを使ったBigQuery上でのELTプロセスは、データ変換（Transform）の部分を強化する形でイメージできます。BigQueryでデータをロード（Load）した後、dbtを活用して高度なデータ変換、モデリング、テストをSQLで実行します。これにより、データの整合性を保ちながら、より効率的で再利用可能な分析基盤を構築できます。


# まとめ
データ変換（Transform）の部分はdbtをつかって、データはGoogle Cloud StorageにおいてBigQueryで加工をするのがシンプルでよさそう？

＜ChatGPTさんの回答＞
はい、そのアプローチはシンプルで効果的です。Google Cloud Storageにデータを保存し、BigQueryで必要な加工を行い、その過程でdbtを用いてデータ変換（Transform）を行うことで、効率的かつ柔軟なデータ処理が可能になります。この方法は、データの処理と分析の基盤を構築する際に、スケーラビリティと管理のしやすさを兼ね備えています。
Cursor Updater

# Cursor Updaterについて

## 経緯と概要

### 経緯
Cursorエディタが起動しなかったので、起動できる様にした際の足跡

### 対応した概要
- 起動しているCursorプロセスを全部、終了させる
- cursor-updaterを実行する

### 方法の考察
最初は再インストールを検討しようとしました。
そこでインストールフォルダの状況を確認しようとしました。

### 起動していない時の状況
環境はWindows10でCursorのバージョンは32.0
Cursorを起動しようとショートカットから実行しようとしても、画面にエディタが表示されない。
タスクマネージャ上だと、Cursor.exeは生きているので、どこかで止まっていると思われる。
通常、Cursorは以下にインストールされている。
```
%USERPROFILE%\AppData\Local\Programs\cursor
```
そのフォルダへ辿っているうちに偶然、とあるフォルダを発見する

```
%USERPROFILE%\AppData\Local\cursor-updater
```

名前からしてコレ、Cursorエディタがアプリ内でアップデートするためのモノですよね？
これでアップデートして上手くいったら、目的が楽に達成できるし、
「ダメなら結局、再インストールすればよい」と、cursor-updater 試してみることに。

## 実施手順

### アップデータ起動してみる
エクスプローラ上から以下のインストーラらしきexeを実行

```
%USERPROFILE%\AppData\Local\cursor-updater\installer.exe
```

Cursorプロセスが残っていると終了させる様に表示が出てくる。

### Cursorプロセスを削除
タスクマネージャからCursorをプロセス終了させる。
これは事前にプロセスを削除しておくのがスマートと思われる。

### アップデータの処理を継続
ダイアログを指示通り進める。
１分もかからずに完了する。

### 起動してみる
Cursorをショートカットから実行。
無事に起動した。
バージョンは32.1となった。
GitHub Actions リリースノートを自動生成する

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/dc87a54e-31e1-25e9-cd52-10473138829a.png)

## 概要

GitHubのリリースを自動生成するGitHub Actionsを紹介します。

### GitHub リリースって使ってる？

https://docs.github.com/ja/repositories/releasing-projects-on-github/about-releases

https://docs.github.com/ja/repositories/releasing-projects-on-github/managing-releases-in-a-repository

OSSなど公に公開しているソフトウェアではGitHubリリースはもちろんよく使われますが、クローズドなリポジトリでは周りに聞いた感じではあまり活用されていないように感じます。

GitHubリリースをしっかり書いているとどのバージョンでどの機能がリリースされたのか、まとめられて見やすくなります。

GitHubリリースには `Generate release notes` ボタンがあり、差分のPRを列挙してテンプレートを作成してくれます。
そのままで良ければサクっと作れますが、毎回整形しようとすると手間だし人の手で行うとやはり若干手間があります。

## Gitシリーズ記事まとめ

https://qiita.com/ucan-lab/items/33c63a402f533aa92f3e

## 利用ツール

リリースノートを生成するアクションが用意されています。

Release Drafter

https://github.com/release-drafter/release-drafter

## 実装

下記、2つのファイルを作成します。

- `.github/release-drafter.yaml`
	- Release Drafterの設定ファイル
- `.github/workflows/create-release-note.yaml`
	- Release Drafterのワークフロー

### .github/release-drafter.yaml

```yaml:.github/release-drafter.yaml
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
categories:
  - title: '🎉 リリース'
    labels:
      - 'release'
  - title: '🚀 機能追加'
    labels:
      - 'feature'
  - title: '🐛 バグ修正'
    labels:
      - 'bug'
  - title: '📝 その他'
exclude-labels:
  - 'ignore-for-release-note'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
version-resolver:
  major:
    labels:
      - 'major'
  minor:
    labels:
      - 'minor'
  default: patch
template: |
  $CHANGES
footer: |

  ## 🌱 すべての変更点

  https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
```

- name-template: リリースの名前(例: v1.2.3 など)
- tag-template: タグの名前(例: v1.2.3 など)
	- リリース名とタグ名は同じでわかりやすいのでそのままでいいと思います
- categories: PRのラベル毎にグループ分けして一覧表示してくれます
- exclude-labels: `ignore-for-release-note` ラベルが付いているものはリリースノートから除外する
  - 除外したいPRがあると思わないが一応除外設定もできるよって
- change-template: プルリクタイトルの表示テンプレート
- change-title-escapes: プルリクのタイトル文字のエスケープ
- version-resolver: ラベルに応じてバージョニングする
	- `major` ラベルが付いていた場合: `v1.2.3` => `v2.0.0`
	- `minor` ラベルが付いていた場合: `v1.2.3` => `v1.3.0`
	- ラベルがない場合: `v1.2.3` => `v1.2.4`
- template: `categories` 以外のプルリク一覧を表示する
	- `$CHANGES`: マージされたプルリクをマークダウン形式のリストで表示する
- footer: バージョン間の差分を見られるリンクを生成してる

ここにconfigのテストが置いてますが、書き方の例として使えるのでこちらを参考にすると良いです。

https://github.com/release-drafter/release-drafter/tree/master/test/fixtures/config

### .github/workflows/create-release-note.yaml

```yaml:.github/workflows/create-release-note.yaml
name: Create Release Note
on:
  push:
    branches: [main]
jobs:
  release-draft:
    permissions:
      contents: write
      pull-requests: read
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: release-drafter/release-drafter@v6
        with:
          config-name: release-drafter.yaml
          commitish: main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
【flutter】kIsWebの役割とは！？

こんにちは！
今回は最近flutterで作業する際に、知ったkIsWebについて紹介したいと思います。
今回も最後まで読んでいただけたら嬉しいです！

## 1,kIsWebの役割とは？
FlutterのkIsWebは、FlutterアプリケーションがWebブラウザ上で実行されているかどうかを判別するためのbool型のフラグです。このフラグは、プラットフォーム間でのコードの共有や条件分岐に使用され、開発者が特定のプラットフォームに依存したコードを回避するのに役立ちます。

kIsWebを使用する主な目的は、Web上でのみ必要な機能や設定を適切に実行することです。例えば、モバイルアプリとWebアプリではUIの外観やユーザーエクスペリエンスが異なる場合もあります。kIsWebを使用することで、これらの違いをプログラム内で動的に処理し、ユーザーに最適なエクスペリエンスを提供することができます。

さらに、kIsWebはクロスプラットフォームのコードの可読性と保守性を向上させます。プラットフォーム間でのコードの再利用と共有が容易になるため、開発者は同じコードベースで複数のプラットフォーム向けにアプリを構築することができます。これにより、開発時間の短縮と効率の向上が実現されます。

## 2,kIsWebの使い方
kIsWebの使い方とその具体的なコード内での条件分岐の例、そしてkIsWebを使ってWeb専用の機能を実装する方法について紹介します。
kIsWebはFlutterのfoundationパッケージに含まれています。これを使うには、まずfoundationパッケージをインポートする必要があります。
```php
import 'package:flutter/foundation.dart';
```

以下のようにkIsWebを使用してWeb上での実行を確認できます。
```php
if (kIsWeb) {
  // Web上での実行時の処理
} else {
  // Web以外での実行時の処理
}
```

### 実際のコード
```php
if (kIsWeb) ...[
              Container(
                height: 100,
                width: 250,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(10),
                ),
                child: const Center(
                  child: Text(
                    "これはweb側です",
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                      color: Colors.white,
                    ),
                  ),
                ),
              )
            ] else ...[
              Container(
                height: 100,
                width: 250,
                decoration: BoxDecoration(
                  color: Colors.red,
                  borderRadius: BorderRadius.circular(10),
                ),
                child: const Center(
                  child: Text(
                    "これはmobile側です",
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                      color: Colors.white,
                    ),
                  ),
                ),
              )
            ]
```
web表示
![スクリーンショット 2024-04-18 10.22.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/8b2f2b98-0190-a0fa-a243-3d18102c7d0e.png)


mobile表示
![スクリーンショット 2024-04-18 10.22.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/4007401a-add7-7c77-c752-a8e29a6cd0d5.png)


## 終わりに
今回の記事は以上になります。
今回も最後まで読んでいただきありがとうございました！
では、また次の記事で〜！
kaggleで日本語訳するための拡張機能

# はじめに
こちらの記事は [この記事](https://qiita.com/tabu_ichi2/items/9420b01f53c87a42abb3) と [この投稿](https://www.kaggle.com/discussions/general/245059) を基にTapermonkeyの実装まで細かく記載したものです。
動作環境はchromeを想定しています。

## 日本語訳できない理由
>kaggleのKernelはiframeで埋め込まれているためchromeで右クリック→日本語に翻訳を押しても翻訳されません。

引用：https://qiita.com/tabu_ichi2/items/9420b01f53c87a42abb3

iframeのページのソースページを開き直すことで、iframeではなくただのHTMLで表示することが出来るようです。それによって日本語訳が可能になるそうです。

# 実装方法など
## 使用するツール
拡張機能を簡単に実装できる[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=ja)を使用します。
あらかじめこの拡張機能をインストールしてください。

## コード
TampermonkeyはJavaScriptで動作するので、そちらを使用します。
ますはTampermonkeyをCOromeで実行し、「新規スクリプトを追加」を選択します。
以下のそれぞれのコードをTampermonkey内のコードに張り付けて、`Ctrl+S`で保存してください。これだけで完了です。
現在開いているkernelが更新されない場合には、もう一度開きなおすと動作します。

:::note Note
kaggleからのリダイレクトを承認していない場合、警告が出る場合があります。承認することで即座にソースページを表示することが出来ます。
:::

```JavaScript
// ==UserScript==
// @name         Kaggle kernel iframe表示
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  KaggleのKernelページを開いた3秒後にタブがポップアップする
// @author       You
// @match        https://www.kaggle.com/code/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=kaggle.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    setTimeout(function() {
        window.open(document.querySelector("#rendered-kernel-content").getAttribute("src"), '_blank');
    }, 3000);
})();
```

```JavaScript
// ==UserScript==
// @name         Kaggle kernel iframe表示2
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  ポップアップしたタブの処理
// @author       You
// @match        https://www.kaggleusercontent.com/kf/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=kaggle.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    document.querySelector("body").style.overflowY="visible"

    document.querySelectorAll(".input").forEach((element) => {
        element.classList.add("notranslate")
    })

    document.querySelectorAll(".output_wrapper").forEach((element) => {
        element.classList.add("notranslate")
    })
})();
```

2024年4月22日：スクロールできない問題を編集
Einstein ボットの困惑、混乱


+ [システムボットのダイアログについて](https://help.salesforce.com/s/articleView?id=sf.bots_service_system_bot_dialog.htm&type=5)

Einstein ボットは会話を目的として作成されています。設定を容易にするために、新規ボットにはそれぞれ最も一般的なダイアログが含まれます。これらのダイアログを使用すると、すばやく会話をエージェントに転送したり、整然とチャットを終了したりできます。各メッセージは会社の話し方や口調に合わせてカスタマイズできます。

### 困惑

[困惑] ダイアログは、ボットの範囲外の要求に対応するために役立ちます。このダイアログに表示されるメッセージは、インテントトレーニングと組み合わせて、ボットが顧客の入力を解決できなかったときの応答に使用します。

[困惑] ダイアログでは、[次のステップ] セクション内にリストされているアクションは認識されません。これは、[困惑] ダイアログが必ず別のダイアログ内からコールされるためです。


+ [Einstein ボットが初めて会話を混乱させるにはどうすればよいですか?現在、ユーザーは混乱したダイアログに進む前に 2 回入力する必要があるようです。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfUVbSAN)

:::note
初めて Einstein ボットに混乱した対話をさせるための最良の方法は、ボットが何を言ったらよいのか分からなくなる特定のトリガーまたはキーワードを作成することです。たとえば、ユーザーがボットが理解できない単語やフレーズを入力すると、混乱した応答が引き起こされる可能性があります。さらに、ボットが混乱を招くものとして認識する単語やフレーズのリストを定義し、それらを使用して混乱を招く応答をトリガーすることもできます。
:::

+ [Einstein ボット機能の「混乱」ダイアログを強制終了するにはどうすればよいですか?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000EACdGSAX)

 [チャットの終了] ダイアログに「さようなら」というメッセージが表示されます。しかし、ダイアログ上の「次のステップ」項目を削除できません。メッセージだけを伝えたいだけで、他には何も必要ありません。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/745e3239-2bd8-4ddb-80a3-dd079dd5a4c2.png)

:::note
チャットを終了するルール アクションを追加した場合、ボットが顧客の入力を待機する前にチャットが終了する必要があります。

https://help.salesforce.com/s/articleView?id=sf.bots_service_setup_dialog_rule.htm&type=5
:::


+ [「混乱」ダイアログ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLNltSAG)

1) Einstein ボットから「混乱」ダイアログを削除すると、どうなりますか?ゲストが意図に一致しないフリーテキスト入力に回答した場合、何が返されますか?

2) 混乱ダイアログが削除されてしまった場合、それを復元する方法はありますか?


# 関連資料

+ [Build a rules based Einstein bot](https://medium.com/@ruby.kandah/build-a-rules-based-einstein-bot-5101c7478c29)
Azure databricksのfunction


databricksのfuncsionはOracle等などのファンクションと異なり以下の制約があるので処理が複雑、長くなってしまうことがある。
- 変数が利用できない。そのため、加工した値を変数として使いまわすことができないため、それをしたい場合は随時同じ処理を書く必要がある
- 処理部は基本的に1節で書く必要がある。returnの位置が頭で決まっており、処理部の分岐により複数書くことができない？




ファンクションを利用するメリットの一つとして、ビューを作成の際にファンクションとして標準化した処理をかませることで追加テーブルの作成を省くことができる点にありますが、上記の制約があるため場合によってはファンクションではなくノートブックとして処理をかく、テーブルを追加することも考慮に入れるのもいいかも？
システムデザインの概念（part2 : ネットワーキング）

#### ネットワークの基礎知識

1. **ネットワークの概念**：ネットワークは、複数のデバイスが相互に接続し、特定のプロトコルを使用して通信する集合体です。各デバイスには固有のIPアドレスがあり、ネットワーク内で識別および通信に使用されます。

2. **IPアドレス**：IPアドレスは、ネットワーク内のデバイスの一意の識別子であり、IPv4とIPv6の2種類があります。IPv4アドレスは32ビットで表され、通常は4つの10進数で表されますが、IPv6アドレスは128ビットであり、通常は8組の16進数で表されます。

3. **プロトコル（protocols）**：データがネットワーク内で転送される際には、特定のプロトコルに従います。代表的なプロトコルには、IPプロトコルやTCPプロトコルがあります。IPプロトコルはデータパケットを送信元から宛先まで転送し、TCPプロトコルはデータパケットが順序通りに宛先まで到達するようにします。

4. **ネットワーク層構造（network layers）**：コンピューターネットワークのプロトコルは、異なる階層構造に組織され、段階的にデータを処理します。一般的な層には、ネットワーク層、トランスポート層、アプリケーション層などがあります。

5. **公開ネットワークとプライベートネットワーク（public & private network）**：公開ネットワークのIPアドレスはグローバルに一意であり、インターネットを介してアクセスできますが、プライベートネットワークのIPアドレスはローカルネットワーク内でのみアクセス可能です。

6. **動的IPアドレスと静的IPアドレス（static & dynamic ip address）**：動的IPアドレスはデバイスがネットワークに接続されるときにサーバーから動的に割り当てられますが、静的IPアドレスは手動で構成する必要があります。静的IPアドレスは通常、固定アドレスが必要なサーバーなどに使用されます。

7. **ポート（ports）**：ポートは異なるアプリケーションやサービスを区別する数字の識別子であり、同一デバイス上で複数のアプリケーションやサービスを同時に実行できます。一般的なポート番号には、HTTPの80番ポートなどがあります。

#### TCP＆UDP

TCP（Transmission Control Protocol）とUDP（User Datagram Protocol）の用途と特徴：

1. **TCPの用途**：TCPはデータの信頼性のある転送を確保し、双方向接続（つまり3ウェイハンドシェイク）を確立して信頼性のあるデータ転送を実現します。TCPはデータパケットを並べ替えて再送し、データの信頼性を確保します。その信頼性故に、TCPはファイル転送、ウェブページアクセスなどのデータの完全性と順序性が必要なアプリケーションに使用されます。ただし、TCPの信頼性には追加のオーバーヘッドと速度の低下が伴います。

2. **UDPの用途**：UDPはTCPほど信頼性はありませんが、転送速度が速いです。UDPは失われたデータパケットを再送したり、順序を再配置することはしません。UDPはデータ転送の速度と効率が重視される場面で使用されます。例えば、オンラインゲーム、ビデオストリーミングなどです。これらの場面では速度と効率が信頼性とエラー訂正よりも重要です。

総じて言えば、TCPは信頼性のある転送が必要な場面で使用され、UDPは速度が重視されるが信頼性が低い場面で使用されます。

#### DNS

1. **Domain Name System（DNS）**：DNSはインターネットの電話帳のようなもので、見やすいウェブサイト名を数字のIPアドレスに変換します。階層構造の名前システムを使用して、ドメイン名をIPアドレスにマッピングし、コンピューターがリクエストのルーティングを決定します。

2. **ICANNとドメイン登録業者**：ICANNは、DNSの全体的な調整、セキュリティ、運用を担当しています。ドメイン登録業者は、ショッピングセンターのリース提供業者のようなもので、ドメイン登録サービスを提供し、ICANNから認定を受けています。彼らはユーザーが使用可能なドメインを検索し、登録プロセスを完了するのを支援します。

3. **DNSレコード**：DNSレコードは、ドメインやサブドメインに関連する情報を保存します。その中で、Aレコードが最も一般的なDNSレコードの種類であり、ドメイン名をIPv4アドレスに関連付けます。DNSレコードの役割は、リクエストを正確なサーバーにルーティングすることです。

4. **URL（Uniform Resource Locator）の解剖**：URLには複数の部分が含まれており、プロトコル、ドメイン、サブドメイン、トップレベルドメイン、パス、ポートなどがあります。URLを解析することで、リソースへのアクセスに必要なプロトコル、サーバーの位置、リソースのパスを特定できます。

5. **ポート**：ポート番号は、同じデバイスで実行されている複数のアプリケーションやサービスを区別するための番号です。通常、HTTPプロトコルはデフォルトの80番ポートを使用し、HTTPSプロトコルはデフォルトの443番ポートを使用します。URLでポート番号を指定することができますが、通常は明示的に指定する必要はありません。
WSL2 Docker Laravel環境でPhpSpreadsheetを使うまでのメモ

# はじめに
WEBエンジニア２年目の初心者です。
仕事でlaravel内でPhpSpreadsheetを使うためにインストールしようとしたらエラーが出てインストールできない・・・
Dockerも使った経験が浅いので、いろいろ調べたため、自分用のメモ兼困っている人の手助けになれば幸いです。

# 1.Phpspreadsheetのインストールを試みる

以下のコマンドを打ってみると見事にエラーが出てさっそく困った

```
composer require phpoffice/phpspreadsheet
```
↓エラー内容
```
  Package phpoffice/phpspreadsheet has requirements incompatible with your PHP version, PHP extensions and Composer version:  
    - phpoffice/phpspreadsheet 2.0.0 requires ext-gd * but it is not present.                                                 
    - phpoffice/phpspreadsheet 2.0.0 requires ext-mbstring * but it is not present.                                           
    - phpoffice/phpspreadsheet 2.0.0 requires ext-zip * but it is not present.          
```

どうやらphp のext-gd ext-mbstring ext-zipの3つが足りないからインストールできないって言われている模様・・・
docker環境で入れる方法をGoogle先生に聞いてみると、以下の記載をdockerファイルに書き込むと動くらしい
[参考記事](https://perchrunway.com/blog/2017-01-19-getting-started-with-docker-for-local-development)

# 2.Dockerファイルを修正

とりあえず、Dockerファイルに書き込んでみる
以下PHPのDockerファイル
```
FROM php:8.1-fpm-alpine

# install composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer

# install packages
RUN apk update
RUN apk add git nodejs npm

# install php extensions
RUN docker-php-ext-install pdo pdo_mysql
RUN apt-get update -y && apt-get install -y libpng-dev
```

よし、`docker-compose up -d --build`でビルドしてみるか！
・
・
・
はい、エラーが出ました。
```
/bin/sh: apt-get: not found
```

apt-getなんてコマンドは存在しないらしいです。
[stackoverflow](https://stackoverflow.com/questions/45142855/bin-sh-apt-get-not-found)に同じ問題抱えた人が質問してました。
どうやら、alpineベースのイメージだからubuntuのapt-getコマンドは使えないと
`apt-get -> apk add`
に変えると動くよとのこと
ついでに調べていくと、dockerファイルって1つのRUNで実行したい場合は`\&&`でつなげられるようです。
最終的に変更したdockerファイルはこれ！
```
FROM php:8.1-fpm-alpine

# install composer
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer

# install packages
RUN apk update \
    && apk add git nodejs npm\
    #libpng-devとlibzip-devをイメージファイルに追加
    libpng-dev\
    libzip-dev \
    && docker-php-ext-install pdo pdo_mysql\
    #gdとzipのライブラリをphpに追加
    gd \
    zip
```

これでビルドすれば無事にPhpSpreadsheetをインストールしてLaravelで使えるようになりましたとさ
alpineベース・wsl2・ubuntuのあたりは今度調べることとしよう・・・
SQLの基本：DDL、DML、DCL違い

データベースを操作するためのSQL（Structured Query Language）には、主に3つの重要なカテゴリがあります。これらはDDL（Data Definition Language）、DML（Data Manipulation Language）、DCL（Data Control Language）です。これらのカテゴリは、データベースの異なるアスペクトを操作するために使用されます。

### DDL（データ定義言語）

DDLは、データベースの構造を定義するために使用されるコマンド群です。これには、テーブル、インデックス、ビューなどのデータベースオブジェクトの作成、変更、削除が含まれます。DDLコマンドは、データベースのスキーマを設定または変更する際に使用されます。

- CREATE: 新しいテーブルやデータベースオブジェクトを作成する
- ALTER: 既存のデータベースオブジェクトを変更する
- DROP: 既存のオブジェクトを削除する

```SQL
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);

ALTER TABLE users ADD COLUMN age INT;

DROP TABLE users;
```

### DML（データ操作言語）

DMLは、データベース内のデータを操作するために使用されるコマンドです。データの挿入、更新、削除などを行います。これらのコマンドは、アプリケーションがデータベースと対話する際に頻繁に使用されます。

- INSERT: テーブルに新しいデータを挿入する
- UPDATE: テーブルの既存のデータを更新する
- DELETE: テーブルからデータを削除する
- SELECT: テーブルからデータを選択する

```SQL
INSERT INTO users (id, name, email) VALUES (1, 'Taro', 'taro@example.com');

UPDATE users SET name = 'Jiro' WHERE id = 1;

DELETE FROM users WHERE id = 1;

SELECT * FROM users WHERE age > 20;
```

### DCL（データ制御言語）

DCLは、データベースのセキュリティとアクセス権限を管理するために使用されるコマンドです。これには、ユーザーへの権限付与や権限の取り消し、トランザクションの制御などが含まれます。

- GRANT: ユーザーに特定の権限を付与する
- REVOKE: ユーザーから特定の権限を取り消す

```sql
GRANT SELECT, INSERT ON users TO some_user;

REVOKE INSERT ON users FROM some_user;
```

これらのカテゴリを適切に理解して使用することで、データベース管理者や開発者はデータベースを効果的に管理し、アプリケーションのニーズに合わせてデータを正確に操作することができます。

参照

https://dev.mysql.com/doc/refman/8.0/ja/innodb-online-ddl-operations.html
pythonでリストを生成するときにlist()と[]どっちを使うか？

# はじめに
pythonでリストを生成するときの書き方としては以下の２つがあると思います。
```python
# []で生成
list_1 = []

# list()で生成
list_2 = list()
```
個人的には、前者の方がわかりやすいので`[]`を使っていたのですが、
同じチーム内に`list()`で書く人もいて、コードレビューのときに「結局どっちがいいんだっけ？」の議論になったので両者の違いをまとめようと思います。

# 結論
以下の観点から`[]`を使うルールにしました。

## 読みやすさ
- `[]`は他の多くのプログラミング言語（例えば JavaScript、C++、Java など）でも配列やリストを表すのに使われており、一般的に慣れ親しんだ表現であること。
    - Pythonの教育/学習資料でも、空のリストを生成する標準的な方法として`[]`が紹介されている印象。
- シンプルに`[]`の方が簡潔


一方で、`list()`はpython特有の記法であり、pythonに精通していない人は一瞬「？」となる。

## パフォーマンス
- `[]` は `list()` よりも生成が速い。

### 検証してみた
両方の書き方でそれぞれ空のリストを100万回作成する時間をtimeitを使って計測したところ、`[]`のほうが速いことが確認できました。

```python
In [1]: import timeit
   ...:
   ...: # `list()` を使って空のリストを生成する時間を計測
   ...: time_list = timeit.timeit('list()', number=1000000)
   ...:
   ...: # `[]` を使って空のリストを生成する時間を計測
   ...: time_brackets = timeit.timeit('[]', number=1000000)
   ...:
   ...: print(f"list()生成時間: {time_list} 秒")
   ...: print(f"[]生成時間: {time_brackets} 秒")
list() の生成時間: 約0.128秒
[] の生成時間: 約0.041秒
```

なお、1000万回の場合の結果は以下となり、大量にリストを生成するほど速度差が顕著に現れました。
```
list() の生成時間: 約1.291秒
[] の生成時間: 約0.486秒
```

### なぜ速度に差が出るのか？
以下の記事が参考になりました。
https://towardsdatascience.com/no-and-list-are-different-in-python-8940530168b0

前提として、両者の違いは以下になります。
- `[]`はリテラル値である
- `list()`は「リテラル値`[]`を返す関数」である

上記の記事でも紹介されていますが、両者の処理を`dis`モジュールを使ってバイトコードで確認すると一目瞭然でした。

```python
In [1]: from dis import dis

# list()の処理
In [2]: dis("list()")
  1           0 LOAD_NAME                0 (list)
              2 CALL_FUNCTION            0
              4 RETURN_VALUE

# []の処理
In [3]: dis("[]")
  1           0 BUILD_LIST               0
              2 RETURN_VALUE
```

上記の`dis`モジュールによる解析から、`list()`と`[]`における速度差の主な理由は、実行されるオペレーションの違いにあることがわかりました。具体的には以下の点です。

- リテラル`[]`
    - `[]`はリストを直接生成するリテラルであり、BUILD_LIST 命令を使用して空のリストを生成しているだけなので高速。


- `list()`
    - `list()`は関数であり、最終的には`[]`でリストを生成する。まず最初に関数`list` を LOAD_NAME 命令でロードし、その後 CALL_FUNCTION 命令で関数を呼び出している。この追加のステップによってオーバーヘッドが生じ、`[]`と比較して処理が遅くなっている。

### リストを作った後の操作も処理速度に違いってあるの？
リストを生成した後の操作（要素の追加や削除など）に関しては、リストが`list()`または`[]`で生成されたかによる処理速度の違いはないです。
これは、どちらの方法でも生成されたオブジェクトは同じPythonのリスト型であるためです。パフォーマンスの違いはあくまでも**リストの生成方法の違い**に起因するものです。


# さいごに
パフォーマンスの観点に関しては、大量のリストを頻繁に生成する必要がある場合に効いてくると思いますが、日常的なスクリプトや小中規模のアプリケーションの開発でこの差が顕著な違いを生むことは少ないのかなと思います。
なので、処理速度を気にしないのであれば、どっちを採用するのかはぶっちゃけ好みの問題なのかなと思っています。

私は今後も`[]`で書きますが、もしかしたらパイソニックな書き方は`list()`のほうかもしれないですね…
秋月の1.3インチカラー液晶で温度計を作って遊ぶ(ST7789V2)(StampS3)(MCP9701)


x 過去ログを見よ!!


目的
温度計を作って遊ぶ。

![o_coq043.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b59a9eac-a8ef-ce01-4396-5f063f1a00af.jpeg)


```c++


//spi_st7789_mcp9701_27o25_M5S3_1


//ヘッダーファイル
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>


//定義
#define TFT_CS    1
#define TFT_RST   3
#define TFT_DC    5
#define TFT_MOSI  7
#define TFT_SCLK  9

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

//100の割り算 0から30000までは、だいたい正しい
#define DIV100(in) ((in*(65536/100*64+24))>>22)
//25の割り算 0から30000までは、だいたい正しい
#define DIV25(in) ((in*(65536/25*16+8))>>20)
//MCP9701の温度を求める x100
#define TMP(so) ((((so)*270769)-134432821)>>16)
//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)


//初期化
void setup() {

  //240x240の液晶を使用する。
  tft.init(240, 240);           // Init ST7789 240x240

  //ピンの初期化
  pinMode(13, INPUT);

  // 画面表示をクリア
  tft.fillScreen(ST77XX_BLACK);

  // テキストサイズを設定
  tft.setTextSize(5);

}//setup


//一つ前の値
int f_bk = 0;
char i_bk[3] = "24";
char j_bk[3] = "25";

//メインループ
void loop() {

  // 一つ前の値で消す。
  // テキスト色を設定
  tft.setTextColor(ST77XX_BLACK);
  // テキストの開始位置を設定
  tft.setCursor(0, 10);
  if (f_bk == -1) {tft.print('-');}
  tft.print(i_bk); //整数部
  tft.print('.'); //ピリオドの表示
  tft.print(j_bk); //小数点以下


  // テキスト色を設定
  tft.setTextColor(ST77XX_WHITE);
  // テキストの開始位置を設定
  tft.setCursor(0, 10);

  //アナログ値の読み込み
  int s = analogRead(13); //7PIN センサーの読み取り値

  //センサーの値を温度に変換
  int t = TMP(s); //t = 2355;//debug
  int d1 =  (t < 0) ? DIV100(-t) : DIV100(t);
  int d01 = (t < 0) ? ((-t) - (d1 * 100)) : (t - (d1 * 100));
  d01 = (DIV25(d01)) * 25;

  //温度をデカ文字表示
  char bu[3] = {'2', '3', 0}; //文字列の一時領域
  f_bk = 0;
  if (t < 0 ) {tft.print('-');f_bk = -1;}
  bu[1] = '0' + d1 - ((DIV10(d1)) * 10);
  bu[0] = '0' + DIV10(d1);
  tft.print(bu); //整数部
  i_bk[0] = bu[0];
  i_bk[1] = bu[1];

  //ピリオドの表示
  tft.print('.');

  bu[1] = '0' + d01 - ((DIV10(d01)) * 10);
  bu[0] = '0' + DIV10(d01);
  tft.print(bu); //小数点以下
  j_bk[0] = bu[0];
  j_bk[1] = bu[1];

  delay(1000); //1秒待つ
  
}//loop



```
ITパスポート デジタル署名と認証局

・なりすまし
他人のふりをして、あたかもその人のように活動を行うこと

・デジタル署名（電子署名）
公開鍵暗号方式を使って電子文書の正当性を保証する仕組み
電子文書を作成したのは本人であること
電子文書の改ざんがされていないこと
送信者の秘密鍵（署名鍵）で署名を生成して、送信者の対の公開鍵（検証鍵）で署名を検出する

・ハッシュ関数
改ざんの検知に使われる関数
・ハッシュ化
元の電子文書から短い文字列のデータ（ハッシュ値）を作成すること
同じ電子文書をハッシュ化すると、常に同じ文字列が作成され、逆に一文字でも改ざんされていると同じ文字列は作成されない
作成されたハッシュ値から元の電子文書を復元できない

・認証局
申請に基づいて公開鍵と所有者の正当性を保証して、デジタル証明書を発行する第三者機関

・PKI
公開鍵暗号方式を利用して、インターネット上で安全な情報のやり取りができるインフラ
媒体　電子文書（紙文書）
第三者機関　認証局（役所）
正当性を証明する対象　公開鍵（印鑑）
発行する証明書　デジタル証明書（印鑑証明書）
本人確認に使うもの　デジタル署名（印影）

・SSL
Webサーバと利用者（Webブラウザ）間の通信を暗号化する仕組み

・S/MIME
電子メールを暗号化する仕組み

・タイムスタンプ
電子文書が「その日時に存在していたこと」と「その日時以降に改ざんされていないこと」を証明する仕組み

・セキュアブート
PCの起動時（ブート時）にOSやドライバのデジタル署名を検証し、許可された正当なものだけを動作させる技術
・TPM
PCのマザーボードに組み込まれた、データを暗号化するためのセキュリティチップ
・耐タンパ性
内部構造や内部データを解析されにくい性質
Connected App 接続アプリケーションのまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


+ [Amazon AppFlow](https://qiita.com/Keiji_otsubo/items/03bed8ce52e8d1544cf1)
+ [OAuth 2.0 Authorization Errors](https://qiita.com/Keiji_otsubo/items/5f1b42e46341469bc765)
+ [接続アプリケーションの信頼済み IP 範囲へのアクセス制限](https://qiita.com/Keiji_otsubo/items/198d27723b3ebec7b381)
+ [Connect REST API エンドポイント /connect/notifications を使用して空の通知リストを受け取りました。](https://qiita.com/Keiji_otsubo/items/5f52610bdd8d511b0953)
+ [コンシューマー鍵とコンシューマーの秘密](https://qiita.com/Keiji_otsubo/items/422c6cd8f40a5a9b0780)
+ [Hyperforce 移行時のエラー](https://qiita.com/Keiji_otsubo/items/33479ff358d651d843a0)


# We could not find an OAuth authorization for the connected app ‘Global Connected App’ or ‘Salesforce CLI’. Make sure to authorize your Dev Hub org with the Salesforce CLI.

+ [We could not find an OAuth authorization for the connected app ‘Global Connected App’ or ‘Salesforce CLI’. Make sure to authorize your Dev Hub org with the Salesforce CLI.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000LHZQn)

:::note
Thanks for provided the org access. It seem you didn't authorize the playground org using CLI command given in the unit steps which causes the error. I have authorized your org and now the challenge is working as expected. I request you to please verify the challenge and hopefully it works now.

組織へのアクセスを提供していただきありがとうございます。ユニットの手順で指定された CLI コマンドを使用してプレイグラウンド組織を承認しなかったため、エラーが発生したようです。私はあなたの組織を承認しました。現在、チャレンジは期待どおりに機能しています。チャレンジを確認してください。問題が解決することを願っています。
:::

#  First error: line 1:220 mismatched character '<EOF>' expecting 

+ [mismatched character '<EOF>' expecting '''](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JfLc4)

**We could not find an OAuth authorization for the connected app ‘Salesforce CLI’. Authorize your Dev Hub org with the Salesforce CLI**
【Figma】Arcを使ってプラグインなしで簡単に円形インジケーターのデザインを作成する方法

## はじめに
Figmaの標準機能であるArc（円弧）を使ってプラグインなしで円形のインジケーターのデザインを作成する方法についてご紹介します。
Figmaを使って以下のような円形インジケーターのデザインをプラグインなしで作成してみましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/08f78e48-98db-b32e-00b5-ac3a1473dfd4.png" width="400">

## 手順
### 1. 円形オブジェクトを配置
まず、`ツールバー → Shape tools → Ellipse`を選択して円形のオブジェクトを配置してください。
![スクリーンショット 2024-04-15 0.12.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/53f00cbc-b645-cb60-a93d-176a5c26771f.png)

### 2. 円形オブジェクトをクリック&ホバー
次に、配置した円形オブジェクトをクリックし、ホバーします。
すると、"Arc"という文字と共に小さな白丸が表示されます。
![スクリーンショット 2024-04-15 0.17.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/e380b7bd-5cc7-a666-1488-fa9ac6a2055a.png)

↓こんな感じ
![スクリーンショット 2024-04-15 0.19.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/ec7163a8-42d4-4f56-71bb-47ce9d292f2e.png)

### 3. Arcの白丸を円の中心に向かってドラッグ&ドロップ
Arcの白丸が表示されたら、その白丸を円形オブジェクトの中心に向かって白丸をドラッグ&ドロップします。
上手くいくと、円形オブジェクトがカットされたピザのような形になり、右サイドバーにArcのプロパティが追加されます。
![名称未設定.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/ef5d9fcd-aa2c-b804-c9bf-31eff8756f0a.gif)

↓右サイドバーに新しく追加されたArcのプロパティ
![スクリーンショット 2024-04-15 0.29.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/c7e4ee1d-d618-2499-5645-fd3831d4025a.png)

### 4. Arcのプロパティを調整
右サイドバーのプロパティを変更して円形オブジェクトの形を調整し、円弧インジケーターの形を変更します。
今回は、右サイドバーからSweepを64%、Ratioを80%に設定します。
すると、円形オブジェクトを以下のようなインジケーターの形に整形することができました。
![スクリーンショット 2024-04-15 0.42.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/b6b56eee-21dc-4cc7-0877-f26f543f30f2.png)

### 5. 色の変更
ここまでできれば、Arcの使い方自体はバッチリです。
最後にお好みでインジケーターの色を調整します。
色をグラデーションで設定したい場合は、`右サイドバー → Fill → Custom → Gradient`から設定できます。
![スクリーンショット 2024-04-15 0.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017091/47e42af9-de0c-e265-becf-62d0c54df375.png)

## さいごに
FigmaのArc機能を使うことにより、簡単に円形インジケーターを作成することができました。
Arcの使い方を覚えれば、円形インジケーター以外の様々な場面でも活躍してくれるはずです。

## 参考
- https://twitter.com/motomiya333/status/1619530776579608577
Windows11用のWindowsUpdate適用bat

# この記事はこれの応用です

https://qiita.com/waokitsune/items/4f280d76091960ab5247

# bat

```bat:
usoclient StartScan
usoclient StartDownload
usoclient StartInstall
usoclient StartInteractiveScan
start ms-settings:windowsupdate
```

Windows10のころと変わっているのは最後の1行。
```start ms-settings:windowsupdate-action``` だとWindowsUpdateの画面が開かなかったので変えています。

オプションの更新プログラムが適用されるかどうかは未検証です。

# バージョン

Microsoft Windows [Version 10.0.22631.3447]
動的型付言語(Python)と静的型付言語 (Java)の簡単な比較

動的型付言語と静的型付言語の違いを、Pythonを動的型付言語の例に、Javaを静的型付言語の例にしてコードで比較。

## 動的型付言語 (Python)

```python
# 変数の宣言時に型を指定する必要がない
x = 10
print(type(x))  # <class 'int'>

x = "Hello"
print(type(x))  # <class 'str'>

# 関数の引数や戻り値に型を指定する必要がない
def add(a, b):
    return a + b

print(add(1, 2))  # 3
print(add("Hello", "World"))  # HelloWorld
```

## 静的型付言語 (Java)

```java
public class Main {
    public static void main(String[] args) {
        // 変数の宣言時に型を指定する必要がある
        int x = 10;
        System.out.println(x);  // 10
        
        // x = "Hello";  // コンパイルエラー: 型の不一致
        
        // 関数の引数や戻り値に型を指定する必要がある
        int result1 = add(1, 2);
        System.out.println(result1);  // 3
        
        // String result2 = add("Hello", "World");  // コンパイルエラー: 型の不一致
    }
    
    public static int add(int a, int b) {
        return a + b;
    }
}
```

動的型付言語では、変数の宣言時や関数の引数・戻り値に型を指定する必要がありません。実行時に変数の型が決定され、同じ変数に異なる型の値を代入することができます。

一方、静的型付言語では、変数の宣言時や関数の引数・戻り値に型を指定する必要があります。コンパイル時に型チェックが行われ、型の不一致によるエラーを事前に検出できます。

このように、動的型付言語は柔軟性が高く記述が簡潔になる一方、静的型付言語は型の安全性が高くコンパイル時にエラーを検出できるという特徴があります。
BigQueryをつかってみた

ここでは私（データエンジニアリングを勉強中）が初めてBigQueryをつかったときに感じた疑問をまとめています。学習メモです。

# BigQueryについて
BigQueryはGoogle Cloud Platform（GCP）におけるフルマネージドのサーバーレスデータウェアハウスサービスです。これは大規模なデータセットに対してリアルタイムの分析を行い、SQLを使ってデータをクエリするための高速かつ高度にスケーラブルなツールを提供します。

## 主な特徴
- **サーバーレス**: ユーザーはサーバーの構成や管理に関わる必要がなく、クエリ実行に集中できます。リソースは自動的に割り当てられ、スケーリングします。
- **パフォーマンス**: BigQueryは、数秒から数分以内にペタバイト級のデータセットをクエリすることができます。
- **スケーラビリティ**: データ量の増減に関わらず、自動的にリソースをスケーリングしてパフォーマンスを維持します。
- **ストレージと分析の分離**: BigQueryでは、ストレージとコンピューティングリソースが分離されており、必要に応じてそれぞれを個別にスケールアップまたはスケールダウンできます。
- **SQLインターフェース**: BigQueryでは、標準SQLを使用してクエリを実行します。これにより、他のシステムでSQLを使用しているユーザーは容易に移行できます。
- **データ統合**: Google Cloudの他のサービスや、外部のソースからもデータを簡単にインポートできます。
- **セキュリティ**: データは自動的に暗号化され、Googleの厳格なセキュリティプロトコルによって保護されています。
- **機械学習統合**: BigQuery MLを使用することで、SQLクエリを用いて機械学習モデルを作成し、訓練し、予測することができます。

# BigQueryについての疑問に思ったこと

①SQLをたたいたら加工したデータを返してくれるものとイメージしていました。データウェアハウス（DWH)につかわれてるけど、スケーラビリティとか、サーバレスとかのイメージが強すぎて、データの保存のしてくれるの？

データほ保存もしてくれます。

②データ保存はしてくれるが、データレイクにはGoogle StorageとBigQueryどっちを使えばいいのか？

##### データ分析の頻度
- ***リアルタイムまたは頻繁な分析***: BigQueryはリアルタイムや頻繁なデータ分析に適しています。
- ***たまにしか行わない分析***: GCSにデータを保存し、分析が必要な時にBigQueryへロードします。
##### データの種類
- ***非構造化データ***: GCSは非構造化データを大量に保存し、必要に応じてアクセスするのに適しています。
- ***構造化データ***: BigQueryは構造化データに対する複雑なクエリ実行に適しています。
##### コストとパフォーマンス
- ***GCS***: 低コストでデータを保存できますが、分析のためにはデータの移動が必要になる場合があります。
- ***BigQuery***: 分析パフォーマンスは高いですが、ストレージのコストが高くなる可能性があります。
##### GCSとBigQueryの併用
実際の運用では、GCSを原始データの保管場所として利用し、分析を必要とするデータはBigQueryにインポートして利用するのが一般的です。これにより、データレイクとデータウェアハウスの利点を両方享受することができます。
Cloud Shellってなに

データエンジニアリングの勉強中にETL/ELTのサンプル実行でGoogle Cloud Shellが出てきたけど、Cloud Shellってなんやねん、無料でつかえるか不安になったので調べてみました。

# Cloud Shellとは

Cloud Shell は、ブラウザから場所を問わずにアクセスできる、オンラインの開発および運用環境です。gcloud コマンドライン ツールや kubectl などのユーティリティがプリロードされたオンライン ターミナルを使用して、リソースを管理できます。また、オンラインの Cloud Shell Editor を使用して、クラウドベースのアプリの開発、ビルド、デバッグ、デプロイを行うこともできます。

> Cloud Shell  |  Google Cloud より引用

なんか思たよりいろいろできそうですね。


# 疑問への回答
Google Cloud Shellは無料で提供されるオンライン開発環境です。利用者には5GBの永続ディスクが割り当てられ、DebianベースのLinux OS上で動作します。GCPのコマンドラインツール（gcloud、bq、gsutil）、各種エディタ（Emacs、Vim、Nano）、ビルドツール、ソース管理（Git）、Docker、Terraformなど多数の開発ツールとプログラミング言語が予めインストールされており、すぐに使用可能です。ただし、利用には週50時間の制限があり、120日間アクセスがないと$HOMEディスクが削除されるなどの制限があります。詳細はGoogle Cloudの公式ドキュメントで確認してください。


# 結論
無料で使えるので、学習用につかっても大丈夫。もう少し内容充実させたいですが、いったん投稿します。