OmniAICreator/Qiita-1.07M huggingface dataset:
AthenaでTGWのフローログをクエリする【備忘】

# 前提

- 既にTGWのフローログ設定や、Athenaの設定は完了していること
- Parquet形式で格納していること

# テーブル作成

Athenaで下記のSQLでクエリを行います。
★部分は環境に合わせて変更を行ってください。（★を忘れずに消してね）

```sql
CREATE EXTERNAL TABLE IF NOT EXISTS `tgw_vpc_flow_logs_parquet` (
  `version` int, 
  `resource_type` string, 
  `account_id` string, 
  `tgw_id` string, 
  `tgw_attachment_id` string, 
  `tgw_src_vpc_account_id` string, 
  `tgw_dst_vpc_account_id` string, 
  `tgw_src_vpc_id` string, 
  `tgw_dst_vpc_id` string, 
  `tgw_src_subnet_id` string, 
  `tgw_dst_subnet_id` string, 
  `tgw_src_eni` string, 
  `tgw_dst_eni` string, 
  `tgw_src_az_id` string, 
  `tgw_dst_az_id` string, 
  `tgw_pair_attachment_id` string, 
  `srcaddr` string, 
  `dstaddr` string, 
  `srcport` int, 
  `dstport` int, 
  `protocol` bigint, 
  `packets` bigint, 
  `bytes` bigint, 
  `start` bigint, 
  `end` bigint, 
  `log_status` string, 
  `type` string, 
  `packets_lost_no_route` bigint, 
  `packets_lost_blackhole` bigint, 
  `packets_lost_mtu_exceeded` bigint, 
  `packets_lost_ttl_expired` bigint, 
  `tcp_flags` int, 
  `flow_direction` string, 
  `pkt_src_aws_service` string, 
  `pkt_dst_aws_service` string
)
PARTITIONED BY (
  `aws-account-id` string, `region` string, `day` string
)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  ★'s3://<ログが格納されているバケット名>/AWSLogs/'
TBLPROPERTIES (
    "skip.header.line.count"="1",
    "projection.enabled" = "true",
    "projection.region.type" = "enum",
    "projection.region.values" = "ap-northeast-1",
    "projection.day.type" = "date",
    ★"projection.day.range" = "<取得したい日付の範囲、例：2021/10/01, NOW>", 
    "projection.day.format" = "yyyy/MM/dd",
    'projection.aws-account-id.type'='enum', 
    ★'projection.aws-account-id.values'='<アカウントID>',
    ★"storage.location.template" = "s3://<ログが格納されているバケット名>/AWSLogs/${aws-account-id}/vpcflowlogs/${region}/${day}"
)
```

# 終わり

後はSELECT文とか投げれば取れます！
フローログは容量が多いので、日付は短めにとって少しずつクエリすることをお勧めします。

Parquet形式でやってる方がぱっと見当たらなかったので、簡単に記事にしました。
よかったら使ってみてください～
eccube-4.2.1 を symfony/cli でインストール (PostgreSQL)

こちらのページを参考にしました。
[EC-CUBE 4.0 開発者向けドキュメント:インストール方法](https://ryo-endo.github.io/doc4.ec-cube.net/quickstart_install)

こちらのページのように、sqlite3 でインストールして動作の確認をし、MariaDB に切り替えます。
[eccube-4.2.1 を symfony/cli でインストール (sqlite3)](https://qiita.com/ekzemplaro/items/d96186bc863c66eb8a36)

Ubuntu 22.10 で確認しました。

## データベースの用意

>ホスト　localhost
>ユーザー　dbuser
>パスワード　secret
>データベース　eccubedb

SQL

```text
CREATE ROLE dbuser login password 'secret';
create database eccubedb;
alter database eccubedb owner to dbuser;
```

インターアクティブに作成

```text
$ sudo -u postgres psql
psql (14.7 (Ubuntu 14.7-0ubuntu0.22.10.1))
Type "help" for help.

postgres=# CREATE ROLE dbuser login password 'secret';
CREATE ROLE
postgres=# create database eccubedb;
CREATE DATABASE
postgres=# alter database eccubedb owner to dbuser;
ALTER DATABASE
postgres=# exit
```

## インストール

```bash
bin/console eccube:install
```

次のように入れます。

```text
Trusted hosts. ex) www.example.com, localhost ...etc [localhost]:
 > 

 Database Url []:
 > postgresql://localhost/eccubedb?user=dbuser&password=secret

 Mailer Dsn [null://null]:
 > 

 Auth Magic [qaMx5l1c1k1VrH2U]:
 > 
```

.env が次のように書き換えられます。

```text
（省略）
DATABASE_URL=postgresql://localhost/eccubedb?user=dbuser&password=secret
DATABASE_SERVER_VERSION=14.7
DATABASE_CHARSET=utf8
（省略）
```

## サーバーの起動

```bash
symfony server:start
```

## フロント画面
http://localhost:8000/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/07e5c00f-d9bb-d8dd-8ed8-d8278d777de4.png)

## 管理画面
http://localhost:8000/admin/
ユーザー　admin
パスワード　password
でログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/543ea07a-2ea2-0793-077f-5984eeda4c6e.png)
DB サーバー: PostgreSQL 14.7 (Ubuntu 14.7-0ubuntu0.22.10.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 12.2.0-3ubuntu1) 12.2.0, 64-bit
macOSをアップデートしたらRailsアプリのpostgresqlが Library not loaded: /usr/local/opt/postgresql/lib/libpq.5.dylib となった話


macOSのCatalinaからVenturaにアップデートしたら、全部のプロジェクトではないのですが、一部のRailsアプリをローカルで動かせなくなりました。

エラー内容はこちらです。

```terminal
$ rails db:create       
rails aborted!
LoadError: dlopen(/Users/<ユーザー名>/.anyenv/envs/rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pg-1.1.4/lib/pg_ext.bundle, 0x0009): Library not loaded: /usr/local/opt/postgresql/lib/libpq.5.dylib
  Referenced from: <BBF0820F-B9B8-31CF-BC14-4B622DDC2077> /Users/<ユーザー名>/.anyenv/envs/rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pg-1.1.4/lib/pg_ext.bundle
  Reason: tried: '/usr/local/opt/postgresql/lib/libpq.5.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/postgresql/lib/libpq.5.dylib' (no such file), '/usr/local/opt/postgresql/lib/libpq.5.dylib' (no such file), '/usr/local/lib/libpq.5.dylib' (no such file), '/usr/lib/libpq.5.dylib' (no such file, not in dyld cache) - /Users/<ユーザー名>/.anyenv/envs/rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pg-1.1.4/lib/pg_ext.bundle
/Users/<ユーザー名>/dev/stock-bancho/config/application.rb:7:in `<main>'
/Users/<ユーザー名>/dev/stock-bancho/Rakefile:4:in `<main>'
/Users/<ユーザー名>/dev/stock-bancho/bin/rails:9:in `<top (required)>'
/Users/<ユーザー名>/dev/stock-bancho/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
(See full trace by running task with --trace)
```

`LoadError: dlopen(/Users/<ユーザー名>/.anyenv/envs/rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/pg-1.1.4/lib/pg_ext.bundle, 0x0009): Library not loaded: /usr/local/opt/postgresql/lib/libpq.5.dylib`
ここがメッセージぽいので読み解きたい。

[dlopen](https://linuxjm.osdn.jp/html/LDP_man-pages/man3/dlopen.3.html)というのは動的に読み込むファイルを開くよっていう意味らしい。

dlopenコマンドで開こうとしていた`pg_ext.bundle`は、gem`pg`の拡張機能の一種らしい。
RubyからPostgreSQLデータベースにアクセスするために必要なものなのだとか。`pg_ext.bundle`のビルドには`libpq.5.dylib`ファイルが必要で、これを開こうと思って`/usr/local/opt/postgresql/lib/libpq.5.dylib`を見に行ったらなかったから怒ってたのでしょう。macでディレクトリを確認してみると、確かに`/usr/local/opt/postgresql/`というディレクトリがありませんでした。

macOSがアップデートされて、ディレクトリ構造が変わったのかな？
パスを正しくしてあげる必要がありそうです。

結論としては、以下の通り、一度pgのgemをアンインストールして、bundle installし直したら戻りました。

```terminal
gem uninstall pg

bundle install
```

こちらが参考になりました。

https://stackoverflow.com/questions/9023482/library-not-loaded-usr-local-lib-libpq-5-4-dylib
Power Platformメモ1(Power Appsでアプリを作っていく)

<p><b>Power Appsでアプリを作成していく</b></p>

個人用メモ

<p><b>アクションタブが出てこない？</b></p>

近々Microsoft365を導入する事になり、Power Apps使ってみよう！
という事で、いじり始めました。

参考書も買って色々試していましたが、色々躓いてます。

![app1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190073/66b85aff-86d5-6f6c-726f-b4eaa5c5aa20.jpeg)

画面を二つ作って、ボタンで遷移させようと思ったのですが...
参考書には「アクション」から「移動」でと書いてあるのですが
どこにも見当たりません...

試しに
![app2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190073/74572664-0448-7660-8b3c-a18d33fc846c.jpeg)

「移動」アイコンを追加したら<b>「アクション」</b>タブが現れました！
喜び勇んでアクションの「移動」を選択してみましたが...

![app3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190073/0a9f4725-d369-cb88-87ad-e24375f0252e.jpeg)

あれ？特にアクションが追加されたように見えない...
右端のアクションも「false」のまま...

<p><b>もういい！自前でベタ打ちする！</b></p>

埒が明かないので、右端のボタンのプロパティから、アクションをベタ打ちしてみます。

マイクロソフトのヘルプから
https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-navigate

Navigate関数
Back関数
を試してみました。

![app4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190073/35308544-4437-29b3-eaed-ee44cee4a55a.jpeg)

ちゃんと画面遷移した！

![app5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190073/30698b8e-e2c8-1885-aa71-7d2cbf36af86.jpeg)

原因は良くわからない...
UIに頼らず、とりあえずOnSeletプロパティにベタ打ちする事で画面遷移は出来た...
同様にBack()で、戻るも出来るみたいです。

他のアクションもベタ打ちじゃないと出来ないのか？それはアホすぎるよな...
今後も、色々試してみます。
[Go]配列 or スライスからランダムに要素を選択する

# 経緯
スマホゲーの開発やってると、「決められた範囲からランダムに選択する」みたいな実装にあたることが多い。
で毎回ちょっと調べて納得して実装して忘れて・・・を繰り返しがちで時間もったいないのでまとめておく。

# ランダムに1つ選択
※ [math/rand](https://pkg.go.dev/math/rand)パッケージ使う前提

```random_sample.go
	// ランダムに選択する対象を配列に詰めておく
	targetList := []int{100, 67, 31, 45, 87}

	// 乱数生成器のインスタンスを生成(シード値は現在日時)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	// 乱数を生成(0 〜 len(targetList) - 1の範囲で)
	randIdx := r.Intn(len(targetList))

	// 対象から1つランダムに選択
	randVal := targetList[randIdx]

	fmt.Printf("randVal: %v\n", randVal)
```

(Go Playgroundで何回実行しても同じになってしまう。これはGo Playgroundでは、time.Now()が固定値で返ってくるから)

**補足**

- シード値を変えないと毎回同じ乱数列になってしまうので注意

- ``Intn(n int)``メソッドは、0 〜 n - 1の整数をランダムにかえしてくれるメソッド 

- 生成される乱数の予測を困難にして安全性を高めたい場合には、``crypto/rand``を使用した方がいいらしい(※でもmath/randに比べて遅くはなるらしい)。

> This package's outputs might be easily predictable regardless of how it's seeded. For random numbers suitable for security-sensitive work, see the crypto/rand package.

# ランダムに複数選択(重複許さない)
重複を許して複数選択するなら↑の処理を繰り返せばいいだけだけれども、重複を許さない場合は、配列をシャッフルして前から複数個取り出すようにしてしまうのが楽。(``Shuffle(n int, swap func(i, j int))``メソッドを利用。↓の処理だと配列が破壊的に変更されることに注意)


```random_sample2.go
	// ランダムに選択する対象を配列に詰めておく
	targetList := []int{100, 67, 31, 45, 87}

	// 乱数生成器のインスタンスを生成(シード値は現在日時)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	// 配列を破壊的にシャッフル
	r.Shuffle(len(targetList), func(i, j int) {
		targetList[i], targetList[j] = targetList[j], targetList[i]
	})

	// 前から3個取得
	randVal, randVal2, randVal3 := targetList[0], targetList[1], targetList[2]

	fmt.Printf("randVal: %v\nrandVal2: %v\nrandVal3: %v\n", randVal, randVal2, randVal3)
```

注意点として、↑のコードのままだと要素数が0 or 1の場合には index out of range エラーが発生するため対策が必要

# 参考
https://pkg.go.dev/math/rand#Source

https://maku77.github.io/p/graq8o5/
【クエリ最適化/SQL】クエリを最適化する方法

# 今回の課題
クエリ最適化の英語の記事があったので、
英語の勉強も含めて要約した。

※参考：[SQL Query Optimization Techniques](https://www.kdnuggets.com/2023/03/sql-query-optimization-techniques.html?utm_source=rss&utm_medium=rss&utm_campaign=sql-query-optimization-techniques)


## 1,テーブルの中から特定の要素を見つける場合、`COUNT()`の代わりに`EXISTS()`を使う
`COUNT()`を使用すると、全量スキャンになってしまい非効率。
一方、`EXISTS()`は、特定の要素を見つけた段階でスキャンが止まる。
そのため、クエリの実行時間を節約することができる。
### ⭕推奨
```sql
select
    exists(
        select
            *
        from
            table
        where
            element_column = 'val'
    )
```

### ❌非推奨
```sql
select
    count(*)
from
    table
where
    element_column = 'val'
```


## 2,`Char`の代わりに`Varchar`を使用する
`char`と`varchar`はテーブルの文字列の型として使われる。
しかし、`varchar`は`char`よりもメモリ効率がかなり良い。

`char`型は指定した固定長の文字列のみを格納できる。もし、指定した文字列よりも短い文字数だった場合、指定した文字数との差分の量、メモリに無駄が生じる。
一方`varchar`型は、指定された最大長以下の可変長の文字列を格納できる。格納された文字数に応じてメモリを消費するので、メモリに無駄が生じない。

## 3,WHERE句ではサブクエリを避ける
サブクエリが大量の行を返す場合、コストが高くなり実行が困難になる。
サブクエリを使用する代わりに、JOINを使って同じ結果を得ることができる。

### ⭕推奨
```sql
select
    orders.*
from
    orders
    join customers -- customersテーブルと、顧客idをキーにしてinner join結合
        on orders.customer_id = customers.id
where
    customers.country = 'INDIA'
;
```
### ❌非推奨
```sql
select
    *
from
    orders
where  -- サブクエリでcountryがINDIAの場合の顧客のidを抽出している
    customer_id in (select id from customers where country = 'INDIA')
;
```

### 4,大テーブルから小テーブルに向ってJOIN(結合)するようにする
そのように結合するとSQLの実行が速くなる。
理由としては、小テーブルから大テーブルに結合すると、SQLエンジンは大テーブルからマッチする行を探さなければいけない。
一方、大テーブルから小テーブルに結合すると、小テーブルからマッチする行を探すため効率が良い。

### ⭕推奨
```sql
select
    *
from
    BigTable as b
    left join SmallTable as s
        on b.id = s.id
```

## 5,`Like`句の代わりに`regexp_like`(正規表現での曖昧検索)を使用する
`Like`句は特定の値を探すのにデータベースを全量スキャンしなければならなく、大きいテーブルだと時間がかかってしまう。
一方、`regexp_like`は効率的で、正規表現を使って複雑なパターンの値を探すことができる。`Like`のようなシンプルなワイルドカードマッチングよりも正確に特定の値を見つけられるので、検索すべきデータ量が減り、クエリの実行速度が速くなる。

### ⭕推奨
```sql
select
    *
from
    table
where
    regexp_like(name, '^[AB].*')
;
```
### ❌非推奨
```sql
select
    *
from
    table
where
    (
    name like 'A%'
    or name like 'B%'
    )
```
【Laravel9】Laravel UIを使ってログイン機能を実装する

## Laravel UIをインストールする
```
composer require laravel/ui
```
そうすると僕の場合は下記のようなエラーが起きてしまったので、
```
Root composer.json requires laravel/ui ^4.0 -> satisfiable by laravel/ui[v4.0.0, v4.0.1, v4.0.2, 4.x-dev].
```
どうやらバージョンを指定してあげないといけないそう。
なので、
```
composer require laravel/ui:3.*
```
今回は3系を指定してインストールしてみました。(成功)

バージョンに関しては、
https://packagist.org/packages/laravel/ui#3.x-dev
を参照。

## ログイン機能を実装させる
```
php artisan ui bootstrap --auth
```
そうすると、僕の場合は、
`yes`,`no`をいくつか求められたので、全て`no`にして進みました。
また下記のように出力がされるので、求められている通り、
`npm install && npm run dev`を入力する。
```
※これは入力しない※
Bootstrap scaffolding installed successfully.
Please run "npm install && npm run dev" to compile your fresh scaffolding.
```

そうすると僕の場合、`node`をインストールしていなかったので、
`bash: npm: command not found`が吐かれてしまったので、nodeをインストールしてあげます。

nodeのインストール方法は下記サイトが非常に役立ったので、そちら参照です。
https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09

インストールできたら、
改めて、下記を打ち込む。

```
$ npm install && npm run dev
```

そうすると下記のような出力がされるので、
```
$ npm install && npm run dev 
//略
Additional dependencies must be installed. This will only take a moment.
 
Running: npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
 
Finished. Please run Mix again.
```

指示通り、`npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps`を打ち込む。

```
$ npm install resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps
```

再度`npm run dev`コマンドを打ち込みビルドさせる

```
$ npm run dev

webpack compiled successfully
```

これから、メール認証やSNS認証だったりとログイン周りでも追加したいことが多いので
色々と調べながら進めていきます。

以上。
c++ で split

```
#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

int main(){
    std::string note_str("72,74,76,77,76,74,72,0");
    std::vector<int> notes;
    std::stringstream ss(note_str);
    std::string item;
    while (std::getline(ss, item, ',')) {
        if (!item.empty()) {
            int noteno = atoi(item.c_str());
            std::cout << noteno << std::endl;
        }
    }
}


```
Firebase Hostingを使って簡単なサイトを公開しよう。ついでにCDも設定しよう

htmlとcssのみを使用して簡単なwebサイト構築を行います。

大まかな流れとしては

1. Firebaseにデプロイ
1. FirebaseにデプロイするCDの設定

となります。

# Firebaseにデプロイ

## Nodeのインストール
https://nodejs.org/en/

## firebaseの設定


### ローカル側その1

```shell:
npm install -g firebase-tools
```
サイトを構築したいフォルダに移動して
```shell:
npm install firebase
```

### Firebase側
Firebaseのホームページに移動してプロジェクトの作成をします。
ここで使用するプロジェクト名はmypageとします。

### ローカル側その2
ログインと初期化をします。

```shell:
firebase login
firebase init
```
ここで選択をせまられるため以下の部分にカーソルで移動してスペースで選択します。
Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys

次に出てくる選択肢はyで大丈夫です。
ここで既存のプロジェクトを選び、deployするフォルダを初期状態のpublicを選択します。


## deploy
つぎにpublicフォルダ以下にhtmlやcss、javascriptを作成してください。
```shell:
firebase deploy
```
これによりFirebase上に公開されます。
変更をした際はブラウザのキャッシュをクリアしないと変更が反映されないことがあります。

# FirebaseにデプロイするCDの設定
GitHubへpush→firebaseへデプロイの操作を自動化します。

## GithubへのFirebaseのtokenの登録

### token生成

```shell:
firebase login:ci
```
を入力して生成されたtokenを保存してください。
successの文字の下にあるのがtokenです。

### token登録
Githubのリポジトリ→Settings→SecurityのSecrets and variablesのタブ→Actionsをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2302637/ceca7ef7-88a8-7af5-9cb1-e00d4fc6e075.png)
New repository secretをクリックして
Nameに任意の名前、Secretに保存したtokenを貼り付けてください。
ここでNameをMYPAGEFIREBASEにしておきます。

### CD用ymlの作成
ローカル環境において
/.github/workflowsフォルダ以下にymlファイルを作成してください。ここでの名前はdeploy.ymlとして以下の内容を記述します。

```yml:deploy.yml
name: deploy-firebase

on:
  push:
    branches:
      - 'main'
jobs:
    FrontDeploy:
        name: FrontDeploy
        runs-on: ubuntu-latest
        steps:
            - name: Checkout Repo
              uses: actions/checkout@v2
            - name: setup Node
              uses: actions/setup-node@v2
              with:
                  node-version: 18.x
                  registry-url: "https://registry.npmjs.org"
            - name: deploy to Firebase Hosting
              run: | 
                    npm install -g firebase-tools
                    firebase deploy --token ${{ secrets.MYPAGEFIREBASE }}
                    
```

mainブランチにpushされたときにfirebaseにデプロイしています。
Firebaseにdeployしているときにsecretにあるtokenを使用しています。
おれおれ PowerShell PROFILE


`$PROFILE`作成
```powershell
Set-ExecutionPolicy RemoteSigned # 適宜
if (!(Test-Path -Path $PROFILE)) {
  New-Item -ItemType File -Path $PROFILE -Force
}
code $PROFILE # 適宜
```

お好きなものをコピペ
```powershell
# bashと同様のキーバインドでシェル操作
Set-PSReadLineKeyHandler -Key "Ctrl+d" -Function DeleteChar
Set-PSReadLineKeyHandler -Key "Ctrl+w" -Function BackwardKillWord
Set-PSReadLineKeyHandler -Key "Ctrl+u" -Function BackwardDeleteLine
Set-PSReadLineKeyHandler -Key "Ctrl+k" -Function ForwardDeleteLine
Set-PSReadLineKeyHandler -Key "Ctrl+a" -Function BeginningOfLine
Set-PSReadLineKeyHandler -Key "Ctrl+e" -Function EndOfLine
Set-PSReadLineKeyHandler -Key "Ctrl+f" -Function ForwardChar
Set-PSReadLineKeyHandler -Key "Ctrl+b" -Function BackwardChar
Set-PSReadLineKeyHandler -Key "Alt+f" -Function NextWord
Set-PSReadLineKeyHandler -Key "Alt+b" -Function BackwardWord
Set-PSReadLineKeyHandler -Key "Ctrl+p" -Function PreviousHistory
Set-PSReadLineKeyHandler -Key "Ctrl+n" -Function NextHistory

# Current Git branchをプロンプトに出力
function prompt {
    $branch = ""
    if (git branch) {
        (git branch | select-string "^\*").ToString() | set-variable -name branch
        $branch = $branch.trim() -replace "^\* *", ""
        " [ $branch ] $(get-location) >>> "
    } else {
        " $(get-location) >>> "
    }
}
```
私の使ってるGitエイリアスまとめ

GitをCLIで使っていく場合、`git pull origin master`とか、`git commit -m "some feature"`とか、キーボードで打つ文字量は意外にも多いです。

そこで、gitにはエイリアスと呼ばれる、特定のコマンドに別のコマンドを割り当てる機能があります。
これによって、地味に面倒なコマンド入力を効率化することができます。

今回は私が設定しているエイリアスを設定したいと思います。

## 設定方法
```
$ git config --global alias.fo 'fetch origin'
```

一個一個設定するのが面倒なら、.gitconfigに直接書き込んでもOKです。

## 私が設定しているエイリアス
前提として、私が所属しているチームでは開発の軸がmasterブランチなのでこれに最適化しています。（リリース用のブランチが別にあります）
ブランチ運用に合わせて、適宜変えるといいと思います。

```
[alias]
	unstage = reset HEAD --
	pom = pull origin master
	cm = commit -m
	s = status
	ss = switch
	nb = switch -c
	sm = switch master
	p = push
	l = log
	b = branch
	aa = add .
	fo = fetch origin
```

ポイントとしては、キーボードでの押しやすさを重視しています。
たとえば、`switch`を`sw`としていないのは、swが単純に押しにくいからです。
FPSゲーム Rustのプラグイン開発を始めるための環境作り

## 注意
これはRust（言語）ではなく、Rust（FPSゲーム）のプラグイン開発についての記事です。
また、前提を満たしていないとだめかもしれません。
VSCodeで書いているとコードの自動補完とかが効かなくて捗らないな～っていう人向けの記事です。説明はかなり雑なので、適宜脳内補完してください。

## 前提
 - OxideMODを導入済み
 - RustDedicatedサーバーにプラグイン入れる方法とかわかっている


# 開発環境づくり
## VisualStudioをインストール&プロジェクト作成

https://visualstudio.microsoft.com/ja/downloads/

↑のリンクからVisualStudioをダウンロードしてください。
インストーラーを実行し、下みたいな感じの画面になったらC#で開発するための `.NET デスクトップ` にチェックを入れておいてください。
もしVisualStudioを既にインストール済みだけど、C#が入っていないっていう人は `Visual Studio Installer` というのがあると思うので
そこから再度インストールするワークロードを編集し、新たに追加できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281879/0feca2e1-1753-bacc-16e3-b424698d8db0.png)


上記が終わったらVisualStudioを開いて、 `新しいプロジェクトの作成` を押して、空のプロジェクトを作成します。
プロジェクト名とかを適当に設定し終えたら、終わりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281879/3a8bb01f-2704-a2ee-5e17-cc157afbb76b.png)

## 自動補完機能が効くようにする

1⃣右側にある(はず)のソリューションエクスプローラーの中にある `参照` を右クリックし、参照の追加を押してください。

2⃣開いたウィンドウの右下にある、 `参照(B)...`ボタンをクリックしてください。

3⃣出てきたファイル選択ウィンドウで、Rustサーバーがインストールされているディレクトリに移動してください。

4⃣その中にある、`RustDedicated_Data/Managed`ディレクトリに移動してください。


そしたら、中にある
```
・Assembly-CSharp.dll
・Facepunchってついてるdll全部
・Oxideってついてるdll全部
・Rustってついてるdll全部
・UnityEngine.CoreModule.dll
```
を選択して追加ボタンを押してください。

これで終わりです。

## プラグインファイルをプロジェクトに追加する

> 自動補完機能が効くようになったので、あとはVisualStudioからコードをいじれるようにするだけです。

Rustのプラグインフォルダを開いて、プラグインファイルをコピーしてください。
もし新規作成している場合は、空白のファイルを適当に作成しそれをコピーしてください。

そしたら、VisualStudioのソリューションエクスプローラーの中のプロジェクトを右クリックして、リンクとして貼り付けてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1281879/6c867a7c-dd5d-39a0-c205-9ae253897a02.png)

# おわり
あとは追加されたファイルを好きなようにするだけです。
自動補完が効いてるはずなので、変なエディタでいじるより数倍やりやすいと思います。
お疲れ様でした。


## みんなでひろげよう、Rustプラグイン開発の輪

上記の説明に不明点や問題点があればコメント欄で指摘お願いします。
[Python].envファイルで環境変数を設定する[python-dotenv]

### 前書き
自分用のちょっとしたツールをPythonで作ることが増えてきたため、Tipsを記していきます。

Python3 環境構築手順は↓

https://qiita.com/shown_it/items/51ef6bcb36869863c59b

今回は環境変数を.envファイルに切り出し、実行ファイル(main.py)で変数として呼び出すところまでを試します。

### 環境変数としてコード管理から切り出すべきもの

+ 環境（local/dev/test/production）によってvalueが異なる項目
+ その他外部への接続情報等、公開するべきではない項目



### 設定方法

今回はpython-dotenvを使用します。まずはインストールを行いましょう。

[python-dotenv(GitHub)](https://github.com/theskumar/python-dotenv)

```
$ pip install python-dotenv
```

.envファイルに環境変数を定義します。
簡単なサンプルのため、以下のファイルは全てProjectのrootディレクトリに置いています。
```.env
CLIENT_ID=hogehoge
CLIENT_SECRET=fugafuga
```

.envファイルに設定した項目をconfig.pyで読み出します。
```config.py
from dotenv import load_dotenv
load_dotenv()

import os

CLIENT_ID = os.getenv('CLIENT_ID') //hogehoge
CLIENT_SECRET = os.getenv('CLIENT_SECRET') //fugafuga
```

config.pyで読み出した項目を実行ファイル内で呼び出します。
```main.py
import config

client_key = config.CLIENT_ID //hogehoge
client_secret = config.CLIENT_SECRET //fugafuga
```

### .gitignoreに.envを追加

.gitignoreへの追記を忘れないように！！
```.gitignore
+ .env 
```
Googleデジタルマーケティング＆Eコマース：ソーシャルメディア戦略のゴールを定義する

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24ea32fb-2fb3-bdb2-462a-4ffc4d60a96f.png" width="800">

# ゴールを定義する理由

- 責任を持つことができます。ゴールを設定したら、それを達成するために必要な行動を定義し、それぞれの予算を決定することができます。
- ゴールは成功の度合いを測るのにも役立ちます。ゴールに関連するデータを分析することで、取り組みの効果を測定し、改善すべき点を特定することができます。

# ソーシャルメディアのゴール

一般的なソーシャルメディア・マーケティングのゴールには、

- ブランド認知度の向上
- ブランドレピュテーションの管理
- 売上とリードの創出
- コミュニティエンゲージメントの増加
- Webトラフィックの増加
- 顧客と競合の洞察の獲得

などがあります。

これらのゴールのうち、どれを優先して戦略を立てるべきかは、ビジネス・ゴールによって決まります。

ソーシャルメディアの目標は、企業全体のマーケティング・ゴールと一致させる必要があります。そうすることで、自分の仕事の価値を証明し、ステークホルダーからの支持を得ることができます。

# SMARTゴール

ソーシャルメディア・マーケティング戦略の大まかなゴールが決まったら、それをSMARTにする必要があります。SMART目標設定法は、キャンペーンのゴールを定義し、その成功を測定するのに役立ちます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/4d4a74e9-8bab-aa92-6301-ae645af84196.png" width="600">

SMARTは

- **S**pecific（具体的）
- **M**easurable（測定可能）
- **A**ttainable（達成可能）
- **R**elevant（適切性）
- **T**ime-bound（期限）

の頭文字をとったものです。

### <font color="MediumBlue">Specific（具体的）</font>

何を達成したいのかを具体的に示すことで、いつ達成したのかを判断しやすくなります。

例えば、ソーシャルメディア上であなたのビジネスのブランド認知度を向上させたいとします。この場合、何を達成したいのかを明確にするのは難しいでしょう。

- フォロワー数を増やすのか？
- 「いいね！」や「シェア」、「メンション」を増やすのか？
- どのプラットフォームをターゲットにするのか？

このような質問に答えることで、ゴールをより具体的にすることができます。

### <font color="MediumBlue">Measurable（測定可能）</font>

ゴールが達成されたことを客観的に判断できる場合、そのゴールは測定可能であると言えます。

測定可能かどうかは、

- どれくらい
- いくつ
- いつ

達成されたかを答えられるかどうかで判断できます。

ゴールを測定可能なものにするには、どのような指標を使うかを決めます。ブランド認知の目標に戻りますが、追跡したい指標をInstagramのフォロワー数としましょう。例えば、

- ***「Instagramのフォロワーを前四半期比で15％増加させる」***

というのが、関連する測定可能な目標かもしれません。


### <font color="MediumBlue">Attainable（達成可能）</font>

達成可能な目標とは、どんな制約があっても現実的であることです。時間や予算、その他のリソースが不足しているなど、Instagramのフォロワーを15％増やすことを邪魔するものはないでしょうか？

成長を促すためには、少しチャレンジングな目標を設定したいことを忘れないでください。


### <font color="MediumBlue">Relevant（関連性）</font>

そのゴールは、

- あなたの会社の他のマーケティング・ゴール
- 優先順位
- 価値観

とどのように整合するか考えてください。

関連性のあるゴールは、あなたのビジネスに利益をもたらします。例えば、若い層を取り込みたい企業であれば、

- ***「25歳から34歳が最も多いInstagramのようなプラットフォームでフォロワーを増やそう」***

とするのは理にかなっていると言えます。


### <font color="MediumBlue">Time-bound（期限）</font>

ゴールを期限付きにすることで、スケジュールを計画し、マイルストーンを設定することができます。

つまり、あなたの最終的なブランド認知ゴールは、

- ***「四半期末までに、Instagramのフォロワーを前期比15%増加させる」***

というようなものでしょう。
ARC158回答メモ

0.はじめに
　最近レギュラーでレートを上げてビギナーで下げるという
　傾向に陥っていますが今回もそんな感じになりました。
　ABくらいはなんとか行けそうかな感があったのですが
　Aでいっぱいいっぱいでした。一応レートは+28でした。

1.A - +3 +5 +7
　ぱっと見、差が2個ずつしか詰まらないくらいはわかりましたが
　そこから先に展開できずに悩みました。
　出力例の、”10 100 1000”をEXCELで手動で解いてみて
　解法の方針を得ました。

　【考え方】
　　1.3つの数字を昇順に並べ、小さい方からA、B、Cとする。
　　2.変数BA（B-A）と変数CB（C-B）を求める。
　　3.BAとCBの小さい方（差が少ない方（以下SA））を0にする。
　　　3-1.SAが偶数のとき
　　　　3-1-1.SAを0にするための操作回数変数ans1=SA//2を求める
　　　　3-1-2.Aに7*ans1を、Bに5*ans1を、Cに3*ans1をそれぞれ加算。
　　　　　　　→A=B＜C、もしくはA<B=Cとなる。
　　　3-2.SAが奇数の時、差は0にならないので、-1を出力して終了
　　4.差を0にした2つの数字ともう一つの数字の差(以下SA2)を0にする。
　　　※小さい方の数字に、3と5を一回ずつ、大きい方に7を一回足して
　　　　差を詰めていくことになるので、2回の操作で6の差が詰まることとなる。
　　　　→逆に6ずつしか詰められない。
　　　4-1.SA2が6の倍数の時、
　　　　4-1-1.SA2を詰めるための操作回数変数ans2=(SA//6)*2を求める
　　　4-2.6の倍数でない時は、差が詰まらないので、-1を出力して終了　　　　
　　5.ans1とans2を足した数を出力して終了

　細かい実装は若干異なりますが、上の考えに基づき実装しACでした。
　テストを通った後、提出したらREが出てしまい悩みましたが
　よく見たら、変数名がBAのところABと書いている所がありました。
　それが無ければ20分強ACまでの時間を縮められたのに・・・。

　https://atcoder.jp/contests/arc158/submissions/39680223

2.B - Sum-Product Ratio
　テスト時は総当たりしたら時間足りないだろうなという思いと
　あと30分じゃ解けないなという思いであきらめて、解説をみて
　解きました。

　解説を読んで正負の組み合わせを考えても、1/Xの小さい方から３つ
　大きい方から3つを組み合わせた6つを組み合わせれば
　ありうる最大値と最小値が求められることを理解しました。

　1/Xのソートも、解説を読んで理解できましたが、ここら辺の
　考え方の気づきが出てこないとタプルで組にして～とか
　遠回りな解決方法しか出てこないなーと思いました。

　素直に　6つの組を20通り試してもよかったのですが
　解説にあった、4パターンでmax、minを求めて
　出力してACでした。
　
　自分で解いた感は皆無ですが、解法を聞いてみればすっきりしたので
　満足しました。

　https://atcoder.jp/contests/arc158/submissions/39691305


以上
[SOQL]バインド変数の使用方法

## バインド変数とは
Apex内の変数をクエリ条件として使用したいときがある。
そんな時に便利なのがバインド変数。
SOQLやSOSLに変数値を使用することができる！

[動的SOQL|Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.232.0.apexcode.meta/apexcode/apex_dynamic_soql.htm)

## 使用方法① Database.Quey()
まずString型でクエリを準備、クエリをDatabase.query()に渡す。
バインド変数は変数名の前に ':' をつけるだけ。
```
String bindValue = 'テスト';
String query = 'SELECT Id, Name FROM Account WHERE Name = :bindValue';
List<Account> accList = Database.query(query);
```

ただし、sObject型の変数.項目APIというやり方はだめらしい。

```
// sObject.項目API のやり方はうまくいかない
Account acc = new Account(Name = 'テスト');

String query =  'SELECT Id, Name FROM Account WHERE Name = :acc.Name'; // NG
List<Account> accList = Database.query(query);
```
## 使用方法② インラインSOQL
バインド変数の書き方は①と同じで変数の前にコロンをつけるのみ
```
String bindValue = 'テスト';
List<Account> accList = [SELECT Id, Name FROM Account WHERE Name = :bindValue]:
```
インラインSOQLの場合はsObject.項目APIのやり方でもOKみたいです。

***
何が違うのか私にはわかりません
paiza.ioでelixir その211

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
ハノイの塔の解を求めよ。

# サンプルコード

```


defmodule Hanoi do
  def hanoi(n, a, b, c) do
    if n > 0 do
      hanoi n - 1, a, c, b
      IO.puts "#{n}を #{a} -> #{b}"
      hanoi n - 1, c, b, a
    end
  end
end

#Hanoi.hanoi 4, "A", "B", "C"
Hanoi.hanoi 4, "0", "1", "2"

defmodule Hanoi do
    def hanoi(n, x, y, z) do
        if n > 0 do
            hanoi(n - 1, x, z, y)
        end 
        IO.puts "#{x} -> #{y}"
        if n > 0 do
            hanoi(n - 1, x, z, y)
        end
    end
end

Hanoi.hanoi(4, "a", "b", "c")



```

# 実行結果

```
1を 0 -> 2
2を 0 -> 1
1を 2 -> 1
3を 0 -> 2
1を 1 -> 0
2を 1 -> 2
1を 0 -> 2
4を 0 -> 1
1を 2 -> 1
2を 2 -> 0
1を 1 -> 0
3を 2 -> 1
1を 0 -> 2
2を 0 -> 1
1を 2 -> 1
a -> b
a -> c
a -> b
a -> b
a -> b
a -> c
a -> b
a -> c
a -> b
a -> c
a -> b
a -> b
a -> b
a -> c
a -> b
a -> b
a -> b
a -> c
a -> b
a -> b
a -> b
a -> c
a -> b
a -> c
a -> b
a -> c
a -> b
a -> b
a -> b
a -> c
a -> b

```

# 成果物

https://paiza.io/projects/l3UKquyAPVQZJa7tfEBqxg


以上。
paiza.ioでelixir その210

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
入れた順と逆順で返せ。

# サンプルコード

```

defmodule Stack do
	def start_link do
		Agent.start_link(fn ->
			[]
		end, name: __MODULE__)
	end
	def drop do
		Agent.update(__MODULE__, fn stack ->
		    po = length(stack) - 2
			stack = List.delete_at(stack, po + 1)
		end)
	end
	def get do
		Agent.get(__MODULE__, fn stack ->
			stack
		end)
	end
	def rev do
		Agent.get(__MODULE__, fn stack ->
			Enum.reverse(stack)
		end)
	end
	def push(v) do
		Agent.update(__MODULE__, fn stack ->
			stack ++ [v]
		end)
	end
end

Stack.start_link
Stack.push("a")
Stack.push("b")
Stack.push("c")
Stack.get
|> IO.inspect
Stack.rev
|> IO.inspect
Enum.map(Stack.rev, fn v ->
    IO.puts v
end)

```

# 実行結果

```
["a", "b", "c"]
["c", "b", "a"]
c
b
a

```

# 成果物

https://paiza.io/projects/w2rBHK76LtqwiE7PF_s1-Q?language=elixir


以上。
eccube-4.2.1 を symfony/cli でインストール (MariaDB)

こちらのページを参考にしました。
[EC-CUBE 4.0 開発者向けドキュメント:インストール方法](https://ryo-endo.github.io/doc4.ec-cube.net/quickstart_install)

こちらのページのように、sqlite3 でインストールして動作の確認をし、MariaDB に切り替えます。
[eccube-4.2.1 を symfony/cli でインストール (sqlite3)](https://qiita.com/ekzemplaro/items/d96186bc863c66eb8a36)

Ubuntu 22.10 で確認しました。

## データベースの用意

>ホスト　localhost
>ユーザー　dbuser
>パスワード　secret
>データベース　eccubedb

SQL

```text
create user 'dbuser'@'localhost' identified by 'secret';
create database eccubedb;
grant all on eccubedb.* to 'dbuser'@'localhost';
```

インターアクティブに作成

```text
$ sudo mysql -uroot
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 32
Server version: 10.6.12-MariaDB-0ubuntu0.22.10.1 Ubuntu 22.10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> create user 'dbuser'@'localhost' identified by 'secret';
Query OK, 0 rows affected (0.004 sec)

MariaDB [(none)]> create database eccubedb;
Query OK, 1 row affected (0.000 sec)

MariaDB [(none)]> grant all on eccubedb.* to 'dbuser'@'localhost';
Query OK, 0 rows affected (0.004 sec)

MariaDB [(none)]> exit
Bye
```

## インストール

```bash
bin/console eccube:install
```

次のように入れます。

```text
Trusted hosts. ex) www.example.com, localhost ...etc [localhost]:
 > localhost

 Database Url [mysql://dbuser:secret@localhost/eccubedb]:
 > mysql://dbuser:secret@localhost/eccubedb

 Mailer Dsn [null://null]:
 > null://null

 Auth Magic [qaMx5l1c1k1VrH2U]:
 > qaMx5l1c1k1VrH2U
```

.env が次のように書き換えられます。

```text:.env
（省略）
DATABASE_URL=mysql://dbuser:secret@localhost/eccubedb
DATABASE_SERVER_VERSION=10.6.12-MariaDB-0ubuntu0.22.10.1
DATABASE_CHARSET=utf8mb4
（省略）
```

## サーバーの起動

```bash
symfony server:start
```

## フロント画面
http://localhost:8000/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b4b93af6-f292-0f00-357b-456105fe61e0.png)

## 管理画面
http://localhost:8000/admin/
ユーザー　admin
パスワード　password
でログイン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1c4e2bd0-2873-f33a-4e23-3cfb7a3b730a.png)

DB サーバー:  MySQL 10.6.12-MariaDB-0ubuntu0.22.10.1
EIP2981 対応について

# はじめに

2022年末、OpenSeaにおけるロイヤリティについての大幅な変更が議論されました。
しかしながら、コミュニティなどを主体とした議論によって、最終的には、EIP2981に対応することで、ロイヤリティの担保が行われるということになりました。
https://twitter.com/opensea/status/1600913315576049669
今回は、EIP2981の対応についての覚書です。

# 環境

https://remix.ethereum.org/
+ OpenZeppelin

# 手順

## 1.OpenZeppelinのERC2981を読み込み


```
import "@openzeppelin/contracts/token/common/ERC2981.sol";
```

## 2.ERC2981を継承したNFTクラスの作成

```
contract DemoNFT is ERC721Enumerable, ERC2981, Ownable {
```

## 3. ERC721とERC2981のサポートインタフェースを指定
```
  function supportsInterface(bytes4 _interfaceId) 
    public 
    view 
    virtual 
    override(ERC721, ERC721Enumerable, ERC2981)
    returns (bool)
  {
    return super.supportsInterface(_interfaceId);
  }
```

## 4. デフォルトのロイヤリティ設定用の関数を生やす
```
  function setDefaultRoyalty(
    address _receiver, 
    uint96 _feeNumerator
  ) external onlyOwner {
    super._setDefaultRoyalty(_receiver, _feeNumerator);
  }
```

## 5. NFT個別のロイヤリティ設定用の関数を生やす
```
  function setTokenRoyalty(
    uint256 _tokenId,
    address _receiver,
    uint96 _feeNumerator
  ) external onlyOwner {
    super._setTokenRoyalty(_tokenId, _receiver, _feeNumerator);
  }
```

## 6.deployする

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/4447b251-1573-eb0a-20eb-91eba8f99df7.png)

![a2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/da7c9c13-43df-6f47-d30c-49765a6cd063.png)

## 7.デフォルトのロイヤリティをセットする

![a4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/ea87885f-ef8d-68bf-7c8e-6fc6cd5fdaf7.png)

## 8.mintする

![a3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/23362ed3-5694-ca86-c513-06243a206e45.png)

## 9.OpenSeaでリセール

![スクリーンショット 2023-03-13 15.36.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/d19e3108-a712-e988-1c2a-fda59f622020.png)
共通鍵暗号（AES：128bit）をpythonで実装

# 実装する共通鍵暗号について
暗号化方式には共通鍵暗号と公開鍵暗号の2つがあります。
共通鍵暗号では、暗号化と復号に同じ鍵を使用します。暗号化と復号の両方を1つの鍵で可能にするのが特徴です。
現在主流な暗号化方式は「AES」で、無線LANのWPA2でも採用されている暗号化方式です。今回はAESをpythonで実装します！

## 0, 動作環境
<dl>
<ul>
<li>windows 11</li>
<li>vscode 1.75.1</li>
<li>python 3.11.0</li>
<li>cryptography 38.0.4</li>
</ul>
</dl>


## 1, pyca/cryptographyとは
暗号化機能にはLow-levelとHigh-levelという概念があります。Low-levelのインターフェースを誤って使用すると、セキュリティ的なリスクが大きいです。暗号化についてよくわからないのであれば、High-levelの方を使うと良いと思います。
pyca/cryptographyでは<strong>Fernet</strong>という規格を採用しています。<strong>Fernet</strong>において、暗号化はCBCモードのAES128で実施されます。
↓詳細
・https://cryptography.io/en/latest/fernet/
・https://timesaving.hatenablog.com/entry/2020/12/31/110000

## 2, pipコマンドでpyca/cryptographyをインストール
```python
pip install cryptography
```
ちなみにインストールやバージョンの確認は
```python
pip list
```
からできると思います。

## 3, 実装
新しいクラスAESにまとめ、自分なりに
・鍵生成
・暗号化
・復号
の機能を関数にしました。
注）下記の<strong> 4,実行結果</strong>にありますが、それぞれの関数内のprint内の「.decode()」を消すとbyte長になった結果がなります。byte長というのは（'\xe3\x81...'）こういうやつです。
<details><summary><strong>コード</strong></summary><div>

```python
#use "cryptography"
#共通鍵暗号
from cryptography.fernet import Fernet

class AES:
    def __init__(self):
        #鍵生成
        self.key = Fernet.generate_key()
        print(f"共通鍵:{self.key.decode()}")
        self.f = Fernet(self.key)
    
    def get_key(self):
        return self.key
    
    #暗号化
    def encode(self,i):
        self.token = self.f.encrypt(i.encode("utf8"))
        print(f"暗号文:{self.token.decode()}")
    
    
    #復号化
    def decode(self,kagi:str):
        result = Fernet(kagi).decrypt(self.token)
        print(f"復号(byte):{result}")
        
        # utf8 でデコード
        re_str = bytes(result).decode("utf8")
        print(f"復号(str):{re_str}")
    
aes = AES()
message = "こんにちは、平文です。"
decode_str = aes.encode(message)
aes.decode(aes.key)
```
</div></details>

## 4, 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632237/f8f77bd7-4be9-ca26-0b88-c5af6b2bfe62.png)
順を追って
・共通鍵：鍵サイズは選べますが、デフォルトは<strong>128bit</strong>です。たしか。
・暗号文：平文の<strong>「こんにちは、平文です。」</strong>を共通鍵を用いて暗号化します。
・復号(byte)：コンソールには「b'\xe3\x81...'」とありますが、これは復号結果がbyte長になっています。
・復号(str)：utf-8で読めるように直したものです。

## 5, 感想
案外簡単に実装できちゃいました。共通鍵の安全性や理論については触れていませんが、ライブラリを使うことで簡単に実装できることが今回分かりました！
Googleデジタルマーケティング＆Eコマース：Earned, owned, and paidメディア

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24ea32fb-2fb3-bdb2-462a-4ffc4d60a96f.png" width="800">

# デジタルメディアの分類

アーンドメディア、オウンドメディア、ペイドメディアをどのようにソーシャルメディア戦略に取り入れるかを検討しましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/7a087458-5022-c3c6-a26e-f2149c690cb4.png" width="700">

# アーンド・メディア（Earned media）

***<font color="MediumVioletRed">『ブランドや製品の個人的、または公的なプロモーションのこと』</font>***

アーンドメディアは、顧客によって生み出されるマーケティングです。

- 顧客が友人に話す
- ソーシャルメディアやブログに投稿する
- 製品についてレビューを書く

など、彼らはあなたのブランドのためにアーンドメディアを作り出していることになります。ソーシャルメディアは、アーンドメディアを生み出す最も強力なマーケティング・チャネルの一つです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/965328d3-ca35-570b-8283-e3a49381ad49.png" width="500">

ソースとしては、

- 顧客のレビューや証言
- ソーシャルメディアプラットフォームでの言及やコメント
- あなたの投稿のシェア、リツイート、「いいね」
- 第三者のサイトでのあなたのビジネスに関するコンテンツ
- あなたのビジネスに関するブログ投稿
- あなたのビジネスに関連するユーザー生成コンテンツ

があります。

#### <font color="MediumBlue">ユーザー生成コンテンツ（UGC）</font>

UGCは、ブランドではなく、人々によって作成されたすべてのコンテンツです。ユーザーが作成したコンテンツには、テキスト、ビデオ、画像、レビューなどがあります。
- 例えば、靴下を販売する会社のソーシャルメディアキャンペーンを実施するとします。もし、顧客があなたの会社の靴下を履いている写真をソーシャルメディアに投稿すれば、これはユーザー生成コンテンツであり、アーンドメディアの一例となります。<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/372b53b5-e39b-fb14-c7a9-a76ce637f06e.png" width="600">

:::note info
アーンドメディアの利点の1つは、オーガニックであることです。オーガニック・ソーシャルメディアとは、有料のプロモーションを必要としないあらゆるソーシャルメディア活動のことです。
:::

# オウンド・メディア（Owned media）

***<font color="MediumVioletRed">『ブランドが完全にコントロールするすべてのデジタルコンテンツのこと』</font>***

ソースとしては、

- ブログサイト
- ブランド
- FacebookやInstagramのプロフィール
- コミュニティフォーラムなどのソーシャルメディアプロフィール

があります。

#### メリット

- ソーシャルメディア上で自社ブランドを取り巻く会話をコントロールできます。貴社ブランドがメディアの資産を所有する場合、どのような種類のコンテンツを公開し、どのくらいの頻度で公開し、ユーザーがどのように交流できるかを決定します。
- 特定の製品やサービスをソーシャルメディア上で販売することもできます。
- 魅力的なオウンド・メディアを継続的に公開することで、より多くのアーンド・メディアを生み出すこともできます。

# ペイド・メディア（Paid media）

***<font color="MediumVioletRed">『ブランドがお金を払ってオンラインに掲載するあらゆる形態のデジタルプロモーションのこと』</font>***

ソーシャルメディア・マーケティングの5つ目の柱は、ペイドメディアであることを覚えておいてください。

ソースとしては、

- 画像広告
- 動画広告
- ストーリー広告
- インフルエンサーマーケティング

があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/88f4dff9-8b44-c80a-e94d-7b26030c29b5.png" width="500">

#### メリット

- あなたのブランドが積極的に検索していない顧客にリーチすることを可能にします。
- 製品やサービスに関心のある特定のグループをターゲットにすることも可能です。
- アーンド・メディアを増やすためにコンテンツを宣伝し、オウンド・メディアのプロパティにトラフィックを誘導することができます。

:::note info
これら３つのメディアを戦略的に組み合わせることで、ブランド認知度の向上、リードの生成、売上の増加を実現することができます。
:::
【備忘録】railsでアプリを作る流れについて

# 初めに

railsでウェブサイトを作る流れを書いていきます
ruby等の環境が構築されている前提で進めさせていただきます。
備忘録も兼ねて投稿いたします！
よろしくお願いします。

# アプリの雛形を導入する

まず、雛形を作ります。
ターミナルに
```
rails new アプリ名
```
これで雛形が入ります。

その後
```
cd アプリ名 #ディレクトリ移動する
```
config/development/development.rbのendの上に追加。
```
 config.hosts.crear
end #ここの上に書く事↑
```
この意味は、どんなホストからでもアクセスを可能にするということです。

これで雛形が完成し、ブラウザが立ち上がるようになります！


# モデル追加

まずはモデルを追加していきます。
設計書がある場合はそれを見ながら追加するのがいいと思います。

```
rails g model モデル名　　#モデル名の１文字目は大文字である事
```
これでモデルが作成されます。
次のステップです。

db/migrate/作成日時_create_モデル名.rb
を開きます。
そして
```
 t.データ型: カラム名
end #ここも必ずendの上に書く事↑
```
これでカラムを定義します。
カラムの例

:::note info
t.string: title
t.string: body
:::
こんな感じです！
全部書き終えたらターミナルで
```
rails db:migrate
```
をしてください！

:::note warn
必ず全部のカラムを書き終えてrails db:migrateしてください！
先にrails db:migrateをすると次はまた別の方法ですることになります。
:::

https://qiita.com/azusanakano/items/a2847e4e582b9a627e3a

参考記事です、こちらを確認してください！


# コントローラー作成

次はコントローラーを作成していきます
ターミナルで
```
rails g controller コントローター名　#小文字且つ複数形で書く事
```
これでコントローラーは作成されます。



# ルーティングを設定する

```
get '/' => 'homes#top'
```

このようにrouteを設定します。
routeの命名規則です↓
```
HTTPメソッド（例get） `URL名' => 'コントローラー名#アクション'
```

お次はトップのビューを作っていきます。
コントローラーに追記します。
```
def top
end
```
次にviewにhomesフォルダ配下にtop.html.erbを追加し、
```
<h1>ここはトップページです</h1>
```
このようにすると、画面上に
「ここはトップページです。」
と表示されることになります。

## おわりに
ここまでがrailsの流れですね。あとは、モデルを追加したりコントローラーを追加したりビューを追加したりMVCモデルを追加していく感じで肉付きを増やしていく感じです。
gemファイルを追加したり色々やることはありますが、まずは今回作った型を作るところから始まります。初級の内容ですが、基本的な事なので再度学習も込めてアウトプットしました！

ご視聴ありがとうございました！
String.split(regExp, limit)を使用したときに発生する"Regex too complex"

# 前置き
CSVデータを改行コードやカンマで分割してListに収めようとすると、
データサイズが大きすぎる場合に以下エラーが発生しました。

> System.Exception:Regex too complex

[Error 'Regex too complicated' in Apex - Salesforce Help](https://help.salesforce.com/s/articleView?id=000325937&type=1)

上記サイトにも記載があるように、
正規表現が入力シーケンスにアクセスできる回数には制限があるらしいです。

# 対処方法
以下に対処方法が記載してありました。

https://developer.salesforce.com/forums/ForumsMain?id=906F00000008xTLIAY


Pattern オブジェクトと Matcher オブジェクトを使用している場合は、Matcher をリセットすることで、この制限を定期的にリセットできます。
とのこと

```apex:ApexClass
/**
* Split a string of any size, while avoiding the dreaded 'Regex too complicated'
* error, which the String.split(String) method causes on some large inputs.
*
* Note that this method does not avoid other errors, such as those related to 
* excess heap size or CPU time.
*/
List<String> safeSplit(String inStr, String delim)
{
    Integer regexFindLimit = 100;
    Integer regexFindCount = 0;
    
    List<String> output = new List<String>();
    
    Matcher m = Pattern.compile(delim).matcher(inStr);
    
    Integer lastEnd = 0;

    while(!m.hitEnd())
    {
        while(regexFindCount < regexFindLimit && !m.hitEnd())
        {
            if(m.find())
            {
                output.add(inStr.substring(lastEnd, m.start()));  
                lastEnd = m.end();
            }
            else
            {
                output.add(inStr.substring(lastEnd));
                lastEnd = inStr.length();
            }
            
            regexFindCount++;
        }

        // Note: Using region() to advance instead of substring() saves 
        // drastically on heap size. Nonetheless, we still must reset the 
        // (unmodified) input sequence to avoid a 'Regex too complicated' 
        // error.
        m.reset(inStr);        
        m.region(lastEnd, m.regionEnd());
        
        regexFindCount = 0;
    }
    
    return output;
}

// Testing code
///////////////////

Integer numRepeats = 50000;
String bigInput = 'All work and no play makes Jack a dull boy.\r\n'.repeat(numRepeats);

// This generates a 'Regex too complicated' exception.
//
// List<String> a = bigInput.split('\r\n');

// This avoids a 'Regex too complicated' exception.
//
String[] a = safeSplit(bigInput, '\r\n');

System.assertEquals(numRepeats+1, a.size());
```
特定フォルダー以下にあるプロジェクトで参照しているライブラリの一覧を取得する(.NET)

# はじめに

特定ディレクトリ以下にある複数のプロジェクトで使っているライブラリの一覧とそのバージョンが知りたいといわれた。


# プロジェクトファイルの構成
C#で利用しているライブラリの一覧は*.csprojファイルに記載されているので、この子を探してXMLをパースすればよいはず。
プロジェクトファイルはこんな感じで、ItemGroup/PackageReferenceを探して列挙すればよさそう。

```xml
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="6.0.14" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.3">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Identity.Web" Version="2.5.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
    <PackageReference Include="NSwag.AspNetCore" Version="13.18.2" />
  </ItemGroup>

  以下略
</Project>
```

# 取得スクリプト

特定フォルダー以下のプロジェクトファイルを再帰的に探して、Referenceの一覧を取得する。

```powershell
$csprojList = ls *.csproj -Recurse
$referenceList = $csprojList | % { 
   $xml = [xml](Get-Content($_.FullName))  
   @{ 
     File = $_.FullName
     Reference = $xml.Project.ItemGroup.PackageReference | select Include, Version
   }
 }
$referenceList | ConvertTo-Json
```

適当なディレクトリで実行したらこんな感じの結果になった
```json
[
  {
    "Reference": [
      "@{Include=AngleSharp; Version=0.14.0}",
      "@{Include=Microsoft.VisualStudio.Azure.Containers.Tools.Targets; Version=1.10.9}"
    ],
    "File": "C:\\localrepo\\SandBox\\ConsoleApp5\\ConsoleApp5\\ConsoleApp5.csproj"
  },
  {
    "Reference": [
      "@{Include=Microsoft.NET.Test.Sdk; Version=16.7.1}",
      "@{Include=xunit; Version=2.4.1}",
      "@{Include=xunit.runner.visualstudio; Version=2.4.3}",
      "@{Include=coverlet.collector; Version=1.3.0}"
    ],
    "File": "C:\\localrepo\\SandBox\\ConsoleApp5\\XUnitTestProject1\\XUnitTestProject1.csproj"
  },
  以下略
]
```

# おわりに
本当はNugetAPIを使って依存ライブラリやライセンスまで取りたかったんだけれど、使い方が悪いのかことごとく空のデータが返ってくるので今回はここまでで断念。
htmlに画像を表示させる(Go)

Goで作ったアプリケーションのhtmlに画像を表示させる試み

app/views/src/画像名.png
と画像があり、
```
<img src="/app/views/src/画像名.png" alt="Google_login">
```
パスも間違っておらず、画像ファイルも存在したが表示されず。

静的ファイルを扱う時には
```
	files := http.FileServer(http.Dir(config.Config.Static))
	http.Handle("/static/", http.StripPrefix("/static/", files))
```
とstatic（静的ファイルのURL）の設定を行って
```
[web]
port = 80
logfile = webapp.log
static = app/views
```
このようにconfig.iniに設定することで

```
go run main.go
```
でビルドしたときに表示される。
Vue でコントロールキーなどの押下を判定する。

# Vue でコントロールキーなどの押下を判定する。
下のような感じでリスナーを登録

```
  data() {
    return {
      keyCode: [], // 押されたキーコードの配列

    },
  },
  methods: {

    /**
     * キーが押されたら呼ばれる
     * @param Object event イベント
     */
    onKeyDown(event) {
      // 配列に値がなければ
      if (-1 == this.keyCode.indexOf(event.keyCode)) {
        this.keyCode.push(event.keyCode); // キーコードを追加
      }
    },
    /**
     * キーが離されたら呼ばれる
     * @param Object event イベント
     */
    onKeyUp(event) {
      i = this.keyCode.indexOf(event.keyCode);
      if (i != -1) { // 配列にキーコードがあれば
        this.keyCode.splice(i, 1); // その要素を削除
      }
    },

  },

  mounted() {
    // イベントリスナーの登録
    document.addEventListener('keydown', this.onKeyDown);
    document.addEventListener('keyup', this.onKeyUp);
  },

  beforeDestroy() {
    // イベントリスナーの削除
    document.removeEventListener('keydown', this.onKeyDown);
    document.removeEventListener('keyup', this.onKeyUp);
  },
```

```
  // 使用例
  if (this.keyCode.indexOf(16) != -1
   && this.keyCode.indexOf(17) != -1) {
    // Shift と Ctrl　が同時に押されている。

  } else {
    // Shift と Ctrl　が同時に押されていない。

  }
```

# キーコード一覧

キー|コード|キー|コード|キー|コード|キー|コード
:--|--:|:--|--:|:--|--:|:--|--:
F1|112|BackSpace|8|End|35|英数|240
F2|113|NumLockOFFのT5|12|Home|36|カタカナ/ひらがな|242
F3|114|Enter / T Enter|13|←|37|Esc|243
F4|115|Shift|16	|↑	|38	|半角/全角|	244
F5|116|Ctrl|17|	→	|39	|Tab|	9
F6|117|Alt / Option|18	|↓	|40		
F7|118|Pause|19|	Insert	|45		
F8|119|変換|28|	Delete	|46		
F9|120|無変換|29|	Win / ⌘|	91		
F10|121|スペース|32|	Apps|	93		
F11|122|PageUp|33|	NumLock	|144		
F12|123|PageDown|34|ScrollLock	|145
毎日30分勉強しただけでTOEIC800点超えた話

# はじめに
現在プログラマ人口がインドや中国、アメリカなどで増加しているのは言うまでもありません。それに伴いBSE(ブリッジシステムエンジニア)と呼ばれる海外プログラマと日本プログラマとの橋渡しをするエンジニアの需要も高くなりつつあります。
企業によっては社内言語を英語に統一するといった企業もちらほら見受けられるようになってきました。
もちろん、プログラムを書くにあたり英語のドキュメントを読むのもエンジニアとしては必ず経験することかと思います。
そういった英語の需要に対応すべく私はTOEICをとろうと思いました。
現在はスコア830なのですが、その勉強法とは毎日たったの30分勉強するだけです。その過程を今回はメモとして残しておこうと思います。
## なぜ毎日30分なのか
まず、なぜ毎日30分なのか？
それはTEDでのスピーチ動画を見て1日の時間の使い方を改めなおしたからです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/UNP03fDSj1U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
このスピーチの内容として30日間新しいことを始めてみよう！というものでした。この30日を30分と誤解した私は、英語の勉強を毎日30分やったらTOEICどれだけとれるんだろう？と思うに至ったわけです…

## 英語勉強を始める前の私の英語力
TOEICの勉強を始める前の私の英語力はほぼ皆無でした。
haveとhasの違いや第5文型などの意味が一切わからないレベルです。
単語力は高校を卒業できるレベルでした。
そもそもこの英語勉強を始めたのが大学3年生からだったため、大学に入ってからの3年間英語の勉強などしてこなかった、むしろいらないだろと思っていたほどでした。

## 教材
私は[abceed](https://www.abceed.com/)というアプリを使って、毎日30分の英語を勉強してきました。
このアプリは人工知能が学習者のレベルに合わせて人気の教材200冊以上(使い放題)の中から問題を抽出してくれる機能があり、現時点での自分の予想TOEICスコアを算出してくれます。<font color="red">無料でも学習できますが、基本月額1650円~かかります。私は年間契約をしています。</font>
## 勉強法
勉強法はいたって簡単。abceedにて「おすすめの問題」を選択して、part1からpart7を一回ずつやるだけです。
* part1,part2はリスニング5問
* part3,part4は長文リスニング1問
* part5は文法問題5問
* part6,part7は読解問題1問
の構成なので、これら1回ずつやると大体30分になります。
**リスニング問題に関してはイヤホンを使わないことをお勧めします。**
なぜなら、TOEICの会場に行くと席があらかじめ指定されているので、スピーカーから遠かったり、試験監督の雑音がうるさかったりするので勉強する際も周囲の雑音と混ぜながらリスニングをするのがおすすめです。
実際に私も勉強を始めた初期のころはイヤホンを用いてリスニングをしていたのですが、本番だとまったく聞き取れず、思うような点数を取れませんでした。
もちろん通学中や大学で勉強をすることもありましたので、外出時はイヤホンで今もリスニングは勉強しています。
## 期間
この勉強法を始めたのが2020年の5月で、毎日の30分を継続して何回かTOEICを受けました。
その受験した月とスコア、勉強開始からの期間を下記に示します。
**2020年10月　TOEIC 650取得(勉強期間5カ月)**
**2021年3月　TOEIC 710取得(勉強期間10カ月)**
**2021年4月　TOEIC 765取得(勉強期間11カ月)**
**2022年6月　TOEIC 830取得(勉強期間2年と1カ月)**
この流れからわかる通り、毎回50点以上点数が増加しています。
もちろん個人差はあると思いますが、たったの30分を毎日継続することがどれほど大事かがわかるかと思います。
特に2021年3月の受験が710点でたったの1か月しか経っていないのに2021年4月の受験が765点取れたのが自分でも驚きました。

## 総勉強時間
次に今現在までに至る総勉強時間を示します。
現在(2023年3月)の総勉強時間はアプリで確認すると25975分(約432時間)になります。
最後に受験したのが9カ月前なので、次の受験で点数が上がるか下がるか楽しみです(笑)

## 最後に
毎日30分勉強するだけでTOEIC800点超えるなんて余裕じゃん！と思うかもしれませんが、本記事で一番言いたいことは
毎日30分を継続できるのか？？？という点です。
雨の日も風の日もとよく言いますが、その通りで体調が悪い日や勉強したくない日、旅行などの一日中縛られる日など
今日は休みたいなと思う日は何度もありました。それでもやらないと気が済まない、一日が始まった気がしないと感じるほどに
継続を続けるのはとても大変でした。
しかし、この継続を通して私はこれから何か新しいことに挑戦するとなったときに、自分には無理だと考えるのではなく、
毎日30分継続すれば何にでも挑戦できる、力がつくんだという自信を得ることが出来ました。
(この経験を就職活動でもアピールしたら内定が決まったというメリットもありました)
この記事を読んで1人でも僕の自信を共感できる人が増えてくれることを切に願います。
以上、ここまで見てくださりありがとうございました。
データベースを基本からまとめてみた【A5:SQL Mk-2　SQLの実行】

## SQLの実行方法
##### 1.データベースの選択
 ① 左側のメニューから実行したいSQLをクリックし接続する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/3f65136c-e764-f242-dc61-1ff64caecc61.png)

 ② 上部のプルダウンから接続したデータベースを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/c6249d75-e62f-1e2c-e4d8-9548c9bf4282.png)

## SQLの実行
 ①赤枠箇所にSQLを記述する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/3bedc864-c78c-eabf-7e94-a904f4091da6.png)

②上部赤枠のマークをクリックすれば実行可能です。SELECT文の場合画面下部に実行結果が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/1d972f40-26b4-15dd-122e-4f302beeb6b9.png)

## SQL実行時の便利機能

#### SQLの一部実行
SQLを複数記述した場合など、実行したいSQLを範囲指定し、実行ボタンをクリックすれば、選択したSQLのみ実行可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/ecf9e9fc-9c3e-7eb4-8807-154978bea6f1.png)

#### コマンド（Ctl + Enter）で実行
実行したいSQLを範囲指定し、Ctl + Enter を押せばSQLを実行可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/d21ec43d-e255-91db-c03c-ad5b8b82dd8d.png)

#### SQL実行結果の出力
#### SELECT文の場合、結果の出力ができます。
左から「CSV」「TSV」「XML」「EXCEL」[EXCEL(全結果)]「HTML」になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/c4ba4c0a-3cbc-416a-6f56-0b28aafb00b3.png)








## 参考サイト
[【A5:SQL Mk-2】SQLの実行など基本操作方法](https://yureport.com/entry/a5sql/)