OmniAICreator/Qiita-1.07M huggingface dataset:
Power BI（クラウド）のスライサー機能を使う

##期間スライサーを使って推移を見やすくします
先日、曜日ごとの[推移（折れ線）グラフ](https://qiita.com/text_owleyes_0214/items/a53ba6256e93386d9200)を作りました。
約1年と2カ月の期間の日毎推移なので、このままでは直近の変化がわかりにくい状態です。
右パネルから**「スライサー」**をクリックします。

<img width="500" alt="スライサー1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/b3e90392-e36d-cb7a-2c27-ab93369c02ac.png">

折れ線グラフ上に**「スライサー」**が表示されます。

<img width="700" alt="スライサー2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/0365b73f-0c78-9c64-5cd7-2de98c8f3518.png">

**「スライサー」**を選択状態にし、右側の**「日付」**をその左側の**「フィールド」**にドラッグします。

<img width="300" alt="スライサー3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/be000e53-3fa9-2486-23b9-de9fd2a2a70e.png">


期間を調整できる**「スライサー」**に切り替わります。

<img width="500" alt="スライサー4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/c688bd63-39cd-4dca-72c9-0f61fe8ba320.png">

**「スライサー」**の左側の**〇**を右側に移動すると、表示期間が短くなります。

<img width="700" alt="スライサー5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/ac2efe82-9734-c41b-f283-194d6f263297.png">

##カレンダーパネルから日付指定もできます
**スライサー**の日付分をクリックすると、カレンダースタイルの選択画面が表示され、月と日の指定ができます。

<img width="700" alt="スライサー6" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/4564d047-4396-7987-ea87-5800a4fc0bf3.png">

##相対日付の指定も可能です
**スライサー**の右上をマスオーバーすると、下向き矢印の先端部分状のアイコンが表示されます。
クリックすると、期間指定の複数の手段が選択できます。

<img width="500" alt="スライサー7" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/ea8b0f09-e39d-f99b-8eaf-b604bebd70e8.png">

例えば、**「相対日付」**を選択します。
**「最近」の「1」「カ月」**を選ぶと、その期間のグラフと変わります。

<img width="500" alt="スライサー8" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/e7ebe025-1b2e-6b87-ed92-6a5350ba83e8.png">

<img width="700" alt="スライサー9" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/a93e7cf4-84de-b60a-743a-976d963e0a6d.png">
**「スライサー」**の文字が小さいので、大きさを変えたり、場所を変えたりして調整します。
文字の大きさは右パネルの**「視覚化」→「テキストサイズ」**で変更します。

<img width="300" alt="スライサー9" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/64685081-0187-cd67-5e7f-4dc58da1856b.png">

<img width="800" alt="スライサー10" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/5140d038-72df-0133-f506-ebb237266f60.png">

区切りのいいタイミングで保存します。

**了**
DockerでRails開発時に，画像の保存先をAWS S3にする

先日，Rails, Dockerでの開発時に画像の保存先をローカルからS3に変更した際の手順を記録した．

## 開発環境
WSL2 (ubuntu 18.04 LTS)
Docker
- Ruby (2.7.1)
- Rails (6.0.3)

## 画像をS3に保存する手順

Active Storageがインストールされており，S3バケット作成まで完了していることを想定

Active Storageのインストールは以下のコマンドでできる

```sh:terminal
docker-compose run コンテナ名 rails active_storage:install
docker-compose run コンテナ名 rails db:migrate
```



#### 用意するもの

- S3バケット情報
  - バケット名
  - リージョン

- IAMユーザー情報
  - アクセスキー
  - シークレットアクセスキー



#### 手順
##### 1. root dirにて以下のコマンドを実行

```sh:terminal
docker exec -it コンテナID sh
/app # EDITOR=vi rails credentials:edit
```

コンテナIDは以下のコマンドで確認できる

```sh:terminal
docker ps
```

##### 2. credentialsを編集

credentialsをターミナル上で編集する

awsは最初コメントアウトされているので外す (それに気付かずハマってしまいました)

```
aws:
 access_key_id: 取得したアクセスキー
 secret_access_key: 取得したシークレットアクセスキー
```

入力し保存する．

Esc→:wqでセーブして保存する．

```
:wq
```



##### 3. config/storage.ymlの編集

regionとbucketを作成したものに書き換える．

```yml:config/storage.yml
amazon:
 service: S3
 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
 secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
 region: "リージョン"
 bucket: "bucket名"
```


##### 4. aws-sdk-s3というgemをインストールする

Gemfileを編集

```ruby:Gemfile
gem 'aws-sdk-s3', require: false
```



Gemfileを書き換えたので，コンテナをbuildし直す．

```sh:terminal
docker-compose build コンテナ名
```



##### 5. config/environments/development.rbでActive Storageの参照先を:localから:amazonへと変更

```ruby:config/environments/development.rb
config.active_storage.service = :amazon
```

以上で，S3のバケットに画像が保存された．
Next.jsでStripeのWebhook（payment_intent.succeeded）を受け取る

Striep + 各言語の実装例は[公式ドキュメント](https://stripe.com/docs/webhooks/signatures)に載っています。
Next.jsの場合はbody-parserでbodyをrawにする設定ができず、`StripeSignatureVerificationError`というエラーが発生しました。
公式ドキュメントとは少し違う実装でうまくいったので紹介します。

## StripeからローカルサーバーにWebhookを受け取るための外部公開設定

ローカルサーバーを起動した状態でngrokで外部からも叩けるようにします。（Stripe CLIを使っても実現可能ですが今回はngrokで。）

```
$ yarn dev
$ ngrok http 3000
```

発行されたURLはStriepの管理画面の設定で使用します。

## StripeのWebohook設定

Stripeの管理画面に入ります。
テストデータの表示中にチェックを入れてで 開発 > Webhook に移動します。

今回、送信イベントには`payment_intent.succeeded`を使用しています。

![スクリーンショット 2021-03-01 0.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510204/84abb0a1-d547-fce3-46ab-2c86f0ae94e0.png)

## コード例

``` pages/api/stripe-webhook.ts
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
// Webhookの署名シークレットキー
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET_KEY;

// bodyParseを無効
export const config = {
  api: {
    bodyParser: false,
  },
}

export default async(req: any, res: any) => {
  const rawBody = await webhookPayloadParser(req);
  const stripeSignature = req.headers['stripe-signature'];

  let event = null;
  try {
    event = stripe.webhooks.constructEvent(rawBody, stripeSignature, endpointSecret);
  } catch (err) {
    // invalid signature
    res.status(400).end();
    return;
  }

  let intent = null;
  switch (event['type']) {
    case 'payment_intent.succeeded':
      intent = event.data.object;
      // 購入情報の書き込み処理など
      await createUserCheckoutPostByAdmin();
      console.log("Succeeded:", intent.id);
      break;
    case 'payment_intent.payment_failed':
      intent = event.data.object;
      const message = intent.last_payment_error && intent.last_payment_error.message;
      console.log('Failed:', intent.id, message);
      break;
  }
};

const webhookPayloadParser = (req: any): Promise<any> =>
  new Promise((resolve) => {
    let data = "";
    req.on("data", (chunk: string) => {
      data += chunk;
    });
    req.on("end", () => {
      resolve(Buffer.from(data).toString());
    });
  }
);
```

## 参考

- [Check the webhook signatures](https://stripe.com/docs/webhooks/signatures)
- [RFC - add rawBody to NextApiRequest · Discussion #13405 · vercel/next.js · GitHub](https://github.com/vercel/next.js/discussions/13405)
- [API Routes: API Middlewares \| Next.js](https://nextjs.org/docs/api-routes/api-middlewares)
Python から gimp を操作する pgimp のインストール（失敗編）

Python から gimp を操作する pgimp のインストール（失敗編）の紹介です。

ことの発端

[GIMP python-fu の不満点 - やってみる ](http://ytyaru.hatenablog.com/entry/2019/12/28/222222#step1)

これを見て、コマンドラインでも python と gimp で遊べたらなあってことでインストールしようとしたときの議事録です。インストールできてません。

まずは Ubuntu に python 2と3 、pip 2と3 をインストールします

python 2と3のインストール

~~~~bash
sudo apt update ;
sudo apt install python3-pip ;
pip3 --version ;
sudo apt update  ;
sudo apt install python2 ;
~~~~

pip 2と3のインストール

~~~~bash
curl https://bootstrap.pypa.io/2.7/get-pip.py --output get-pip.py ;
sudo python2 get-pip.py ;
curl https://bootstrap.pypa.io/get-pip.py --output get-pip.py ;
sudo python3 get-pip.py ;
~~~~

pgimp が必要とするライブラリのインストール

~~~~bash
pip install setuptools ;
pip install psutil ;
pip2 install numpy ;
pip2 install typing ;
~~~~

gimp と gimp を起動なしで実行するようにする xvfb のインストール

~~~~bash
sudo apt-get install gimp ; 
sudo apt-get install xvfb ;
~~~~

メインの pgimp のインストール

~~~~bash
pip3 install pgimp ;
~~~~

これで一見うまく行きそうですが、コンパイルエラーがでます。
[公式のissuesにも同じ人](https://github.com/mabu-github/pgimp/issues/12) がいるので、公式の修正待ちかと思います

個人的には python2 系はもうサポートが終わりなので、python3 系で統一をしてほしい感じです。
#### 参考リンク

- [mabu-github/pgimp: Call gimp routines from python3 code. ](https://github.com/mabu-github/pgimp)
- [GIMP python-fu の不満点 - やってみる ](http://ytyaru.hatenablog.com/entry/2019/12/28/222222#step1)
- [How to Install Python Pip on Ubuntu 20.04 | Linuxize ](https://linuxize.com/post/how-to-install-pip-on-ubuntu-20.04/)
- [Python pgimp包_程序模块 - PyPI - Python中文网 ](https://www.cnpython.com/pypi/pgimp)
Intellijの使い方

# 目次
- ダウンロードとインストール
- 新規作成について
- プロジェクトを開く
- Intellijの設定
- プロジェクトの構成について

# ダウンロードとインストール
https://www.jetbrains.com/idea/download/#section=windows

# 新規作成について
- File > New から色々新規作成出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/4b67af2f-03cb-873c-d5fb-59842bb5b772.png)


# プロジェクトを開く
- 既存プロジェクトを開く事が出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/95860a4d-c5f8-b2dd-289f-f8ccc04fc63a.png)

# Intellijの設定
- File > Settingsから設定情報の参照・変更等が出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/fbf0632f-917d-37c8-a834-50a3dd182701.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/4ded7a87-c6f2-9e53-2422-8fb0b2047784.png)

# プロジェクトの構成について
- File > Project Structureからプロジェクトの構成について、参照・変更等が出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/8bf27725-aea5-3f99-8215-d77329c7e0a4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/84bc6ece-eb89-8e17-1e8f-db5409688d38.png)
[React] ネストされた入力、配列のある入力フォーム

**参考URL**

https://dev.to/hussainsafwan/handling-nested-inputs-in-react-1gj3

こういうネストされたオブジェクトの入力フォーム

```xxx.js
{
      name: "",
      branches: [
        {
          location: "",
          contacts: [""]
        }
      ]
}
```
VSCode でC++の開発環境構築（Windows / MacOS）

## ことの発端

前々から VSCode で C++ の開発環境を作りたいと思って、やってみたら拍子抜けするくらい簡単[^1] だったのでメモ。

[^1]: コンソールアプリで簡単なテストコードを書きたいという動機なので、XcodeとかAndroid Studioとか既存の開発環境に導入するとなると、それはもういばらの道です。

## Windows

### 方針

VisualStudio や Mingw-w64 でも良いけど、個人的には WSL で環境構築した方がUbuntsuだし簡単かもと思い今回はこちらを選択します。
WSL じゃなくて VirtualBox の Ubuntu イメージがあるなら、VSCodeからリモート接続でも良いかもですが、共有フォルダとかファイル権限とか案外面倒なので、この説明は WSL ってことにします。


### WSL をインストール

https://docs.microsoft.com/ja-jp/windows/wsl/

VirtualBox や Docker Desktop for Windows みたいな VT-x を使っているミドルウェアをインストールしていないなら WSL2 に更新しても良いかもです。[^2]

[^2]: 過去に、VT-xを使っている VirtualBox と Docker Desktop for Windows のネットワークドライバがコンフリクトして大変な目に遭ったのだが、WSL2もVT-xに対応したので同じことが起きそうで躊躇しているが、他に VT-x を使うミドルウェアがインストールされていないなら、WSL2の方が良いかと。

### 開発ツールのインストール

ターミナル（wsl）を起動して下記のコマンドを実施します。

```sh
sudo apt update
sudo apt upgrade -y
sudo apt install build-essential -y
sudo apt install gdb -y
sudo apt install cmake -y
```

### VSCode に拡張機能をインストール

* [Remote-WSL: ms-vscode-remote.remote-wsl](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl)

こいつで、WSLにリモート接続した状態でVSCodeが使えるようになります。[^3]

[^3]: 姉妹品で [Remote - SSH: ms-vscode-remote.remote-ssh](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh)があって、サーバにリモート接続して作業する際に大変重宝しています。

## MacOS

### 方針

Xcode が入っている前提なので Clang になるけど、簡単なテストコードの開発環境という前提なので、これで良しとします。（今後問題が出たら考える）

### 開発ツールのインストール

標準では cmake が入っていないので、　[Homebrew](https://brew.sh/index_ja) から下記コマンドを実施してインストールします。

```sh
brew install cmake
```

## 開発作業

CMake を使う場合```CMakeLists.txt```を作りますが、```CMakeTools```が良い仕事をしてくれるので、作る手間は省けます。

1. 開発作業を行うフォルダを作成
2. VSCodeを起動
3. 1で作成したフォルダを開く
4. 【Windowsのみ】 VSCodeの左下の ![リモートウィンドウを開きます](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038343/f79c79f0-5a21-f5de-1459-a7822eb6659c.png) をクリックすると、コマンドパレットが表示されるので「Remote-WSL: Reopen Folder in WSL」を選択
5. 拡張機能をインストール（インストールしていない場合）[^4]
  * [C/C++: ms-vscode.cpptools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
  * [CMakeTools: ms-vscode.cmake-tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools)
6. ソースコード（main.cpp）を作成
7. [F1]でコマンドパレットを表示して```CMake: Configure```を選択
8. 続けて ```CMakeLists.txt``` を作るか聞いてくるので```Create```を選択

```cpp:main.cppp
#include <iostream>
int main(void) {
  std::cout << "hello" << std::endl;
  return 0;
}
```

* ```CMakeTools```が反応してビルド準備までやってくれる。（初回は通知が表示される）
* 手動で行う場合は、[F1] でコマンドパレットを表示して```CMake: Configure```を選択して、キット（```gcc```や```Clang```）や最適化（デバッグが目的なので```Debug```）の設定を行います。
* この一連の作業で```build``` フォルダが作成されるので、 ```build``` フォルダは ```.gitignore``` に追加しときましょう。

[^4]: VSCodeはリモート接続毎に拡張機能をインストールするため WSL にリモート接続後にインストールする必要があります。

## ビルドとデバッグ

* [F7] でビルド
* [CTRL] + [F5] でデバッグ開始
* 大概のデバッガと同じようにブレークポイントとかスタックトレースとか普通に使える
M5Stack Core2でバッテリー関連の情報を得る時

M5Stackで電源関連は

```
#include <M5Stack.h>

void setup(){
  M5.begin();
  M5.Power.begin();
}
void loop(){
  if(M5.Power.canControl()){
    M5.Lcd.printf("%3d \%",M5.Power.getBatteryLevel());
  }
}
```
もしくは

```
#include <M5Stack.h>

void setup(){
  M5.begin();
  Wire.beginTransmission(0x75);
  Wire.begin();
}
void loop(){
  int battlevel = -1;
  byte retval;

  Wire.beginTransmission(0x75);
  Wire.write(0x78);
  Wire.endTransmission(false);
  if (Wire.endTransmission(false) == 0 && Wire.requestFrom(0x75, 1)) {
    retval = Wire.read() & 0xF0;
    if (retval == 0xE0) battlevel = 25;
    else if (retval == 0xC0) battlevel = 50;
    else if (retval == 0x80) battlevel = 75;
    else if (retval == 0x00) battlevel = 100;
  }
  M5.Lcd.printf("%3d \%",battlevel);
}

```

のようなコードで取得できます。
ですがCore2にはM5.Powerというものがありません。
なので以下のようにして取得します。
※残量のパーセンテージなどでは取得できないので要注意

```
#include <M5Core2.h>
#include <Wire.h>
#include <AXP192.h>
AXP192 power;

void setup(){
  M5.begin();
}
void loop(){
  M5.Lcd.printf("%3.4f V",power.GetBatVoltage());
}
```
ラズパイWHで作るネットワークレシーバー

ふとオーディオシステムを揃えたくなりいろいろ見てみると
プレイヤーはラズパイで作れそうなのでやってみることにしました。
この記事では具体的なオーディオ機器との接続方法はほかに譲り、
wi-fiの接続で詰まったのでそちらを書こうと思います。

PC環境
Windows10 Home

準備したもの：ハード
Raspberry Pi　Zero　WH
micro SDカード
micro USB-USBのコード
電源プラグ

準備したもの：ソフト
volumio
https://volumio.org/get-started/
balena Etcher
https://www.balena.io/etcher/

前提
インストール～volumioがwifiで確認されるまでは完了しているものとする。
※volumio立ち上がりが遅いので、１分程度待つ必要があった。

記事本文
諸々設定終わって、wi-fiの設定も完了したので見てみるも、明らかにネットが繋がっていない。
いろいろ調べてみるとSSHで接続してどーたらこーたらと書いてある。

参考URL：
CLIでVolumioのWi-Fi設定で解決！とある
https://blog.bnikka.com/raspberrypi/volumio-wi-fi.html

上記のサイトはMac環境なので残念ながらWindowsでは出来ない。
そこで、今回紹介するのは下記のような手順。

手順
①micro SDを読み込む
②右クリックして、新規作成→新規テキストドキュメント
③中身はhttps://qiita.com/mascii/items/0d1a280ac58ed8f6f999 を参考に記入して、
　wpa_supplicant.confという名前にして完了
※予想ですが本文中にあるssidのpassを暗号化する場合は
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="test"
　　scan_ssid=1
    psk=899f089ca767f38265424c83ce83193ab145571c0a71e1aca4487d615c411f34
}
としないとダメな気がするけどどうなんでしょうか・・・。

ちなみにSSHでやりたい場合は、
http://volumio.local/dev/ にアクセスの上、SSHをENABLEにしてやるとよい。
※これをしないと一生SSHで接続できなくて辛い。
なお接続する際は、TeraTermとかが情報出てましたのでそちらをDLのうえ使えばよい。
一応、Windows環境でも最近はSSH接続できるらしい。
参考URL:
Windows10でsshする
https://qiita.com/TukamotoRyuzo/items/7bd4ff6810421bdc9924


参考URL:
基本的なインストール～設定はこの2サイトが丁寧
https://www.jh4vaj.com/archives/25191
https://hirofun.com/computer/18128/
データベースのスキーマとは何か。（三層スキーマ、PostgreSQL/SQLServer/OracleDB/MySQL）

## 記事を書いた経緯

これまで色々なDBを利用し開発を行ってきましたが、「スキーマ」の言葉がよく出てきました。
出てくる度に、調べてはなんとなーく理解して、を繰り返し結局毎回頭に残らないので、記事に残すことにしました。


## 「スキーマ」とは

まず、データベースに限らない広い意味での「スキーマ」という言葉の意味は、「**おおまかな概念（状態）や構造**」と理解しました。

[wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E)によると
スキーマとは、もともと図や図式や計画のことを指す言葉で、今では様々な分野で広く用いられる言葉。「スキーム」と「スキーマ」はほぼ同じ意味であるが、一般にスキームが具体的にほとんど完成された計画や図を意味するのに比べて、スキーマはその手前のおおまかな（概念）状態を指すことが多い。


## データベースの概念的な意味で使われる「スキーマ」とデータベース個々で使われる「スキーマ」は別

OracleDBを利用したシステムの開発時に、同じデータベース内に同名のテーブルを2つ作成し、WEBアプリからとバッチからで参照先を変えたい事象が発生しました。
「**スキーマ分けたら大丈夫だから**」と上司に言われ、スキーマってなんだっけ？どう使うんだっけ？と思い【スキーマ　データベース】で調べました。

するとでてきたのは「三層スキーマ」等の概念的な言葉で、なんか知りたいのと違う・・使い方が書いてない・・もやもや。という状態に。

データベースの概念的な「スキーマ」と、個々のデータベースでの「スキーマ」は別だと認識して調べた方が良さそうです。
上記のように、開発でスキーマを利用する必要がある場合は【スキーマ データベース】ではなく【スキーマ OracleDB】のように、データベース名を指定して調べるべきでしたね。


## データベースの概念的な意味で使われる「スキーマ」

データベースの概念的な意味で使われる「スキーマ」は**データベースの構造**のことであり、設計時に利用される言葉かなと思います。
三層スキーマはその「スキーマ」を3階層に分けて定義する考え方です。

* 外部スキーマ … ユーザからみたデータの定義。ビュー等。
* 概念スキーマ … テーブルを作成するための定義。
* 内部スキーマ … 物理的なデータの定義。（実際にデータベースのデータはファイルで管理されるため、物理的なデータ＝ファイルについての定義）


## データベース個々で使われる「スキーマ」

### PosgresSQL

PostgresSQLにおけるスキーマはデータベースに作成されるテーブルや関数といったオブジェクトをグループ化するものです。

* データベースを作成すると、デフォルトでpublicという特別なスキーマが作成される
* public以外にも任意な名前でスキーマを作成できる
* テーブル作成時にスキーマを指定しない場合はpublicスキーマに作成される
* スキーマには、テーブル以外にデータ型、関数および演算子などの他の名前付きオブジェクトも含まれる
* ユーザは、デフォルトでは所有していないスキーマのオブジェクトをアクセスすることはできないため、そのスキーマの所有者からスキーマのUSAGE権限を付与してもらう必要がある

[PosgresSQL参考1](https://www.dbonline.jp/postgresql/schema/index1.html)
[PosgresSQL参考2](https://www.postgresql.jp/document/10/html/ddl-schemas.html)


### OracleDB

OracleDBにおけるスキーマはユーザが所有するオブジェクトの論理集合、とのことです。
スキーマを使うことで「1 つのデータベースを多数のユーザが互いに干渉することなく使用できる」「ユーザにスキーマへのアクセス権限を与えることで、セキュリティを高める」のメリットがあります。

* 作成されたユーザは、自身と同じ名前の単一スキーマを所有する
* ユーザは複数のスキーマを所有できないため、**ユーザ=スキーマ**の理解で問題ない
* スキーマ内のオブジェクトをスキーマオブジェクトと呼び、表（テーブル）/索引（インデックス）/ビュー/順序（シーケンス）/ストアド・プログラムがそれに該当する
* 自身のスキーマ以外にはデフォルトでアクセスすることはできないため、そのスキーマの所有者からスキーマのSELECT権限やUPDAT権限を付与してもらう必要がある

[OracleDB参考1](https://www.oracle.com/technetwork/jp/ondemand/db-basic/0413-1330-oracle-beginner-overview-366289-ja.pdf)


### MySQL

MySQLにおけるスキーマは「１つのDB=１つのスキーマ」の理解でよさそうです。
（DB=スキーマなら「スキーマ」の言葉必要ないよね？と思いましたが、どのサイトにも、「DBとスキーマはほぼほぼ等しいです」みたいなことしか書いてなかった。。。）

[MySQL参考1](https://www.oracle.com/technetwork/jp/ondemand/db-basic/0413-1330-oracle-beginner-overview-366289-ja.pdf)


### SQL Server

SQL Serverでのスキーマとは簡単に言い換えるとデータベースにおける名前付きコンテナ。…らしいです。
私はこの言葉の意味をきちんと理解することができませんでした(^^;）ただ、使い方などを調べてPostgreSQLやOracleDBとほぼほぼ同じかなと私は思います。

* 新しく作成されたデータベースに使用される既定のスキーマは「dbo」
* データベースに複数のスキーマを作成することができる
* スキーマを作成する際に、所有者（ユーザ）を指定する。スキーマ名は所有者と同じにするのが一般的。


[SQL Server参考1](https://style.potepan.com/articles/26466.html)
[SQL Server参考2](https://www.fenet.jp/dotnet/column/tool/1634/)


## 最後に

データベースについて仕組みや概念など深く理解しなくても、アプリケーション開発って出来ちゃいますよね。
今回調べてみて、もっとデータベースについて深く理解する必要があると思いました。精進します。
[Python] Slack APIを使用してチャンネル内のメッセージを一件だけ残して一括削除してみた

## はじめに
社内で使用している#generalチャンネルの運用を変更することになったため、メッセージを一括で削除してほしいと依頼されました。一件だけ残したいメッセージがあるとのことだったので、一件残しで削除するコードを作成しました。

## 環境
Visual Studio Code
Python3.9.1

## 準備
* python-slackclientのインストール
	ターミナルで以下のコマンドを実行します。

	```
    pip install slackclient
    ```

* ユーザートークンの取得方法
	ユーザートークンを取得するには、アプリを作成する必要があります。
	アプリ作成は下記の記事を参考にしました。
        [Slack API 推奨Tokenについて](https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21)  
アプリ作成後、ユーザートークンを取得できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002088/b0101e53-1201-a925-f483-19f507982da9.png)
	※**xoxp**から始まるユーザートークンを使用します。

* チャンネルID・タイムスタンプの取得方法
	対象チャンネルのメッセージのリンクからチャンネルIDとタイムスタンプを取得できます。

	例：https\://xxxxxx.slack.com/archives/**AAAAAAAAA**/**p1111111111000000**
	"AAAAAAAAA"がチャンネルID、pを除いた"1111111111000000"がメッセージのタイムスタンプになります。
※APIで取得するタイムスタンプのフォーマットは"**1111111111.000000**"なので合わせる必要があります。  

## 使用APIの説明
* [chat.delete](https://api.slack.com/methods/chat.delete)
	受け取ったタイムスタンプのメッセージを削除します。

* [conversations.history](https://api.slack.com/methods/conversations.history)
	メッセージのタイムスタンプを取得します。

* [conversations.replies](https://api.slack.com/methods/conversations.replies)
	スレッドのタイムスタンプを取得します。


## ソースコード

```Python		
import time	
from slack import WebClient	
	
# slackのユーザートークン	
SLACK_CLIENT = WebClient('xoxpから始まるユーザートークン')	
# メッセージ削除対象のチャンネル名	
CHANNEL_ID ="AAAAAAAAA"	
# 削除したくないメッセージのタイムスタンプ	
NOT_DELETE_TS = "1111111111.000000"	

def main():
    while True:	
        # 最新のメッセージ100件を取得する
        channel_history = SLACK_CLIENT.conversations_history(channel=CHANNEL_ID)
        print('メッセ－ジ取得件数: {}'.format(len(channel_history['messages'])))
        if len(channel_history['messages']) <= 1:
            print('メッセ－ジが1件になったので終了')
            break
        for messages in channel_history['messages']:
            print(f'対象メッセ－ジ: {messages}')
            if messages['ts'] == NOT_DELETE_TS:
                print(f'スキップ対象メッセ－ジ: {messages}')
                continue
            SLACK_CLIENT.chat_delete(channel=CHANNEL_ID, ts=messages['ts'])
            time.sleep(0.5) # 連続実行をさける
	
            if 'thread_ts' in messages:
                thread_replies = SLACK_CLIENT.conversations_replies(channel=CHANNEL_ID, ts=messages['ts'])
                for thread in thread_replies['messages']:
                    # メッセージのタイムスタンプは削除済みのためスキップする
                    if messages['ts'] == thread['ts']:
                        continue
                    SLACK_CLIENT.chat_delete(channel=CHANNEL_ID, ts=thread['ts'])
                    time.sleep(0.5) # 連続実行をさける

if __name__ == '__main__':
    main()
```

## 苦労した点
"conversations.history"だけではメッセージのタイムスタンプしか取得できなかったので、スレッドの削除に苦労しました。API一覧からスレッドのタイムスタンプを取得できるものはないかなと探していたら"conversations.replies"を見つけて解決できました。

## 終わりに
今回初めてPythonとSlack APIを使用してコードを書いてみました。Pythonに興味はあったのですが業務では使う機会がなかったので書いてて楽しかったです。

## 参考資料
[APIメソッド一覧](https://api.slack.com/methods)
初心者の行動

取り敢えずググる。

でも分からない、解らない、何か書いてあるけど判らない。

この辺で、興味本位の人は止めてしまうのではないか？

もし、仕事にしたいなら、怒られようが嫌われようが誰かつかまえて訊かないといけませんね。

日付変わりましたのでもう寝ます。また訊こう。
VS Code ショートカット　チートシート


      

操作概要                 |	Windows          |	macOS
-----------------------|-------------------------|-------------------------------
                       |          **全般**        |
すべてのコマンドの表示       |	Ctrl+Shift+P, F1 |	⇧⌘P, F1
クイックオープン	       |          Ctrl+P         |	⌘P
キーボード ショートカットを開く  |	Ctrl+K Ctrl+S    |	⌘K ⌘S
直近で開いたファイルを表示   |	Ctrl+Tab	 |       ⌃Tab
                       |          **編集**            |
コードの整形	       |        Shift+Alt+F      |	⇧⌥F
（選択範囲なしで）行の切り取り |	Ctrl+X	         |      ⌘X    
（選択範囲なしで）行のコピー   |	Ctrl+C	         |      ⌘C
行を下へ移動             |	Alt+↓ 	         |      ⌥↓ 
行を上へ移動             |	Alt+↑	         |      ⌥↑
行を下へコピー            |	        Shift+Alt+↓      |	⇧⌥↓
行を上へコピー            |	        Shift+Alt+↑      |	⇧⌥↑
行の削除                |	Ctrl+Shift+K     |	⇧⌘K
行を下に挿入             |	Ctrl+Enter       |	⌘Enter
行のインデント追加         |	Ctrl+]	         |      ⌘]
行のインデント削除         |	Ctrl+[	         |      ⌘[
名前を変更              |	              F2         |	F2
補完候補を開く           |	          Ctrl+Space     |	⌃Space
                       |          **選択**        |
矩形選択(マウス選択)        |	Shift+Alt+ドラッグ	 |     ⇧⌥+ドラッグ
矩形選択(キーボード選択)     |	Ctrl+Shift+Alt+方向キー|	⇧⌥⌘+方向キー
選択範囲と同じ文字列の複数指定|	Ctrl+D               |	⌘D
                        |        **移動**             |
行の先頭に移動             |	Home                 |	Home
行の最後に移動             |	End                  |	End
ファイルの先頭に移動         |	Ctrl+Home            |	⌘↑
ファイルの末尾に移動         |	Ctrl+End             |	⌘↓
行コメントの切り替え          |	Ctrl+/               |	⌘/
指定行へ移動              |	Ctrl+G               |	⌃G
ファイルに移動              |	Ctrl+P               |	⌘P
前に戻る                  |	Alt+←                |	⌃-
次に進む                 |	Alt+→                |	⌃⇧-
                        |         **検索**            |
ファイル内検索             |	Ctrl+F               |	⌘F
ファイル内置換             |	Ctrl+H               |	⌥⌘F
次を検索                 |	F3                   |	⌘G
前を検索                 |	Shift+F3             |	⇧⌘G
プロジェクト内検索          |	Ctrl+Shift+F         |	⇧⌘F
                       |        **パネル操作**         |
サイドバーの表示/非表示     |	Ctrl+B               |	⌘B
ターミナルの表示/非表示     |	Ctrl+@               |	⌃@
新しく統合ターミナルを表示   |	Ctrl+Shift+@         |	⌃⇧@
エクスプローラーの表示      |	Ctrl+Shift+E         |	⇧⌘E
Herokuのアップロードサイズの上限を変更する方法

Herokuとその他諸々で画像共有サービスを作ろうとしたときに、ファイルをアップロード出来なくて詰まったのでメモ

#やること
Herokuはデフォルトだと2MB未満のファイルしかアップロードできないようなので、いろいろやって上限を20MBまで引き上げたい。

##.user.iniファイルを作成
設定を反映させたい対象のphpファイルと同じディレクトリ内に`.user.ini`を作成する。

##upload_max_filesizeを記述
.user.iniに`upload_max_filesize = 20M`、
今回の場合はformからアップロードしたかったので`post_max_size = 20M`とも書き込んでおく。
Scipyで処理時間の分布を確かめる

# はじめに

処理時間の計測を行ってみると、その値にはバラツキがあることがわかります。
正規分布とは違って、処理時間の長い値もそれなりにあり、ぱっと見では指数分布に従っているようにも見えます。
今回はpingの応答時間を計測して、処理時間(応答時間)の分布がどうなっているか確かめてみたいと思います。

# pingのデータを収集

まずはpingの応答時間の収集です。Yahoo!Japanに対してpingしてみました。

```sh
ping www.yahoo.co.jp
```

収集したデータは下記のような感じになりました。省略していますが、ぜんぶで2485行あります。

```
64 bytes from 182.22.25.124: icmp_seq=0 ttl=55 time=3.673 ms
64 bytes from 182.22.25.124: icmp_seq=1 ttl=55 time=4.663 ms
64 bytes from 182.22.25.124: icmp_seq=2 ttl=55 time=3.395 ms
64 bytes from 182.22.25.124: icmp_seq=3 ttl=55 time=15.306 ms
64 bytes from 182.22.25.124: icmp_seq=4 ttl=55 time=12.701 ms
64 bytes from 182.22.25.124: icmp_seq=5 ttl=55 time=4.376 ms
64 bytes from 182.22.25.124: icmp_seq=6 ttl=55 time=3.259 ms
64 bytes from 182.22.25.124: icmp_seq=7 ttl=55 time=5.859 ms
64 bytes from 182.22.25.124: icmp_seq=8 ttl=55 time=4.249 ms
64 bytes from 182.22.25.124: icmp_seq=9 ttl=55 time=3.378 ms
```

ここから応答時間だけを抽出します。

```python
import re
import numpy as np

pattern = re.compile(r"time=([\d\.]+) ms")

with open("ping.log") as f:
    lines = f.readlines()

times = []
for line in lines:
    match = pattern.search(line)
    if match:
        time = float(match.groups()[0])
        times.append(time)
times = np.array(times)
```
処理時間のヒストグラムを作ってみます。

```python
import matplotlib.pyplot as plt

plt.hist(times, bins=100)
plt.show()
```

指数分布っぽく見えますね。

![ping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106967/a38312c5-ecf7-be80-1ab5-f62b97e9e474.png)

# 指数分布でフィッティングしてみる

では、Scipyを使用して指数分布にフィッティングしてみます。

```python
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# timesは上で求めた値を使用
loc, scale = stats.expon.fit(times)
x = np.arange(0, max(times))
y = stats.expon.pdf(x, loc=loc, scale=scale)
weights = np.ones(len(times))/float(len(times))
plt.hist(times, bins=100, weights=weights)
plt.plot(x, y)
plt.show()
```

ヒストグラムの表示でweightsを調整してヒストグラムの面積が1になるようにしています。これは確率分布と比較するためです。

![ping1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106967/60d36571-b41a-c691-d467-0d286402fa30.png)

あらら？指数分布では、ずれがあります。

# 対数正規分布でフィッティングしてみる

ロングテールを持つ分布としては対数正規分布もあります。
対数正規分布は、身長や体重、市町村の人口、個人所得などで見られる分布です。
では、対数正規分布でフィッティングしてみます。

```python
shape, loc, scale = stats.lognorm.fit(times)
x = np.arange(0, max(times))
y = stats.lognorm.pdf(x, shape, loc=loc, scale=scale)
weights = np.ones(len(times))/float(len(times))
plt.hist(times, bins=100, weights=weights)
plt.plot(x, y)
plt.show()
```
うまくフィッティングできたようです。

![ping4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106967/2af5746e-4420-6661-2b9d-2da8d237303d.png)

# 最後に

今まで処理時間は指数分布に従っていると思っていましたが、実際は対数正規分布にフィットしていることがわかりました。今回はpingの応答時間から求めたものですが、処理する内容によっては違う結果になるかも知れません。とりあえずScipyでのフィッティング方法がわかったので、今後活用していきたいと思ってます。
LINE botでプッシュ通知機能を作る

今までSlack botでプッシュ通知機能を利用してきました。
昔ちょろっと記事を書いてます。
[Slack の bot を自作する（AWS Lambda + API Gateway）](https://qiita.com/landwarrior/items/dfac36a1aadac9ab0cd5)
ただ、やっぱSlackは試しに作ってみただけで全然使ってないので、なじみやすいLINE botでプッシュ通知機能を実装したいな、とかねてから思っていました。
そこで、頑張って実装しました。

# 概略

LINE botは、いわゆるLINE公式アカウントという形で利用します。
※ 以前は自分が作ったものを公開していましたが、LINE公式アカウントの料金改定に伴い公開を中止しました。

https://developers.line.biz/ja/news/2023/06/02/revised-subscription-plans/

# 仕組み

まず、LINE Developersにてログインします。

https://developers.line.biz/ja/

ログインしたら、プロバイダ→チャネルの順番で作成していきます。
何の知識もなくポチポチと作成したので、私は

- プロバイダ： 僕のプロバイダ
- チャネル： 僕のチャネル

という名前で作りました。
最終的に、以下のような感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179043/d97965a5-2573-1f73-9df7-6e336f6f2844.png)

チャネルでは、WebhookとしてAWS Lambda（API Gateway）を指定しています。

1. 友達追加すると、そのイベントがAWS Lambdaに飛ぶのでDynamoDBにユーザーIDを保存します。
3. 定期実行を有効にしたら、DynamoDBからどのニュースをプッシュ通知するかを取得して必要なものを毎日12時にプッシュ通知します。
4. ブロックしたら、そのイベントがAWS Lambdaに飛ぶのでDynamoDBからユーザーIDを削除します。

ユーザーIDは友達追加のタイミングで保存しておかないと管理できないのでこうなりました。

# ソースコード

というわけで、実装は全部AWS Lambdaなので、そのソースコードをご紹介。
手っ取り早く、GitHubにて公開しました。
なんかまずい情報が載っていたら教えていただけると大変助かりますm(_ _)m

https://github.com/landwarrior/linebot2

ちなみに、応答メッセージ用のメソッドも載せてあります。

# 終わり

どこまで書けばいいのか分からなかったのと、色々と書けるほど自分が理解していないのでこの程度です。
箇条書きで補足すると。

- LINE botは利用が一定数を超えると課金される
  - つまり、個人でちょろっと使う分には無料で使える
- LINE botの応答メッセージはAWSのAPI Gatewayで受けてAWS Lambdaを実行する
  - LINE Messaging APIの応答メッセージを使ってユーザーに返信する
- プッシュ通知はAWSのAmazon CloudWatch Eventsを使ってAWS Lambdaを実行する
  - LINE Messaging APIのプッシュ通知を使ってユーザーに通知を送る
- AWSの方が課金開始までの無料枠が大きいので、LINE botだけ注意すればいい

こんなところでしょうか。

ユーザー情報の保持にDynamoDBを初めて使ってみましたが、最初は癖のあるデータ構造に戸惑いましたが慣れれば使いやすいですね。
アクセス方法も最初からコードが示されていたので、それを修正して使えばOKでした。
ただし、AWS LambdaからDynamoDBにアクセスするためには実行ロールの設定でDynamoDBへのアクセス権限を付けないといけなかったりするので、そのあたりが難しいですね。
公開しているソースコードだとusersテーブルへアクセスしてデータを取り出していますが、そもそもAWS Lambdaはどうやってusersテーブルへアクセスしているのかよく分かっていません。
AWS Lambdaの所有者（つまり私）とusersテーブルの所有者（つまり私）が同じだからテーブル名だけでいけるのだろうか・・・

とまあ、DynamoDBに関してはまだまだ理解か浅いので、勉強していきたいところです。
【Java】AtCoderのABC-196に参加しました（レート：251→220）。

こんばんは。

2021/3/20に、AtCoderのABC-196に参加しました。
レートは以下の通りとなっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402487/ab6cc4f3-dec0-c7cd-d0aa-362baf008a20.png)

https://atcoder.jp/users/ishikawaryou

A,B問題は解けました。
家の都合で40分ほど遅れて参加し、C問題は間に合いませんでした。
すると、、レートは251→221に低下！ぐあっ。
遅れて参加するのは止めた方が良いのか、A,Bをミスなしで解くだけでは下がってしまうのか、どうなのかな。


###A問題
a,b,c,dの4つの数字を入力。
a<x<b、c<y<d　が成り立つとき、x-yの最大値を求める。

```java

import java.util.Scanner;

public class Main{
public static void main(String args[]){
  Scanner sc = new Scanner(System.in);
  int a = sc.nextInt();
  int b = sc.nextInt();
  int c = sc.nextInt();
  int d = sc.nextInt();
  int x = 0;
  int y = 0;
  if(a<b){
    x = b;
  }else{
    x = a;
  }
  
  if(c<d){
    y = c;
  }else{
    y = d;
  }
  
  System.out.println(x-y);  
}
}
```

###B問題

整数または小数 X が与えられるので、小数点以下を切り捨てて整数で出力。
doubleをlong型にしたり、色々考えたのですが、String型にして、'.'が現れるまで1文字ずつ読む方法をとることに。

```java
import java.util.Scanner;
import java.math.BigDecimal;

public class Main{
public static void main(String args[]){
  Scanner sc = new Scanner(System.in);
  String x = sc.next();
  char flg = '0';
  String xs = "";
  for(int i=0;i<x.length();i++){
  if(x.charAt(i)=='.'){
    flg = '1';
    break;
   }else{
     xs = xs + String.valueOf(x.charAt(i));
   } 
  }
System.out.println(xs);
}
}
```


###感想

レートが落ちてしまい、気持ちも落ち込んでいますが、次回もがんばるぞ！！
[メモ] @each辺り


outline: none !important;

ボタンのアウトラインがデフォルトで設定されている（青色の線）
ので、これで打ち消せる

---

cursor: pointer;

クリック要素にhoverするとポインターになる

---

＠each

＠each $key, $value in $（ループさせたい変数名） {
}

---

background-size: cover;

div要素に合わせてサイジングされる

---

background-position: center;

画像のセンターがポジショニングされる

---

background-size: contain;

画像がトリムされなくなる

---

object-fit: cover;

imgタグでもサイジングをカバーできる

---

画像表示方法

imgタグ
background-image: url(images/400x250.png);
pictureタグ

---

メディアクエリの条件式

@media screen and (min-width: 600px) {
}

---

vertical-align: bottom;

displayのインラインブロックを上下で移動させるときに使う

---

transform: scale(1.5);

画像がパンする

---

pointer-events: none;

設定された要素はマウスの操作を受け付けないようになる
[メモ] ハンバーガーメニュー

[![Image from Gyazo](https://i.gyazo.com/87dcbfc561c09aaa8b6e6569fe2533fc.gif)](https://gyazo.com/87dcbfc561c09aaa8b6e6569fe2533fc)

###HTML

```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <button class="hamburger"
  onclick="document.querySelector('body').classList.toggle('menu-open');">
    <span></span>
    <span></span>
    <span></span>
  </button>
</body>
</html>
```

###CSS

```
$cBlack: black;
$cWhite: white;
.hamburger {
  background-color: transparent;
  border: none;

  & > span {
    background-color: $cBlack;
    width: 35px;
    height: 2px;
    display: block;
    margin-bottom: 9px;
    transition: transform 0.7s;

    &:last-child {
      margin-bottom: 0;
    }
  }
}

.menu-open {
  background-color: $cBlack;

  & .hamburger {

    & > span {
      background-color: $cWhite;

      &:nth-child(1) {
        transition-delay: 70ms;
        transform: translateY(11px) rotate(135deg);
      }
      &:nth-child(2) {
        transform: translateX(-18px) scaleX(0);
      }
      &:nth-child(3) {
        transition-delay: 140ms;
        transform: translateY(-11px) rotate(-135deg);
      }
    }
  }
}
```

nth-child(1)　
nth-child(2)
nth-child(3)
PowerShellで起動時に複数スクリプトを読ませる

## 概要
タイトルそのまんま
Win10で、PowerShellが起動したときに自前の関数であったりエイリアスなどを自動的に読み込む
ただし、そのスクリプトは複数ファイルで分割管理したい
ということを解決する

## 前提
PowerShell起動時にスクリプトを読み込ませる方法自体は
`~\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`
にスクリプトを書くだけである。

なお、スクリプトを読み込ませるためにはPowerShellのスクリプト実行の設定を変える必要がある。
そのためには
`PowerShell Set-ExecutionPolicy RemoteSigned`
というコマンドを管理者権限で実行することでできる。
詳しい説明については
「PowerShell Script 有効化」
等でぐぐってもらいたい

## 実装
``` Powershell
$PSScriptDirectory = "C:\Users\{USER_NAME}\Documents\WindowsPowerShell\Scripts\"
$files = (Get-ChildItem ($PSScriptDirectory + "*.ps1")).Basename

foreach ($file in $files) {
	Write-Host -NoNewline ("Loading") -ForegroundColor Yellow
	Write-Host -NoNewline (" {0,-20}" -f $file)
	try {
		. ( $PSScriptDirectory + $file)
		Write-Host "Done" -ForegroundColor Green
	} catch{
		Write-Host "Abort" -ForegroundColor Red
	}
}

Write-Host "Configure Loading Complete" -ForegroundColor Green
```

このコードさっきの起動時に読み込まれるスクリプトに書き、分割したスクリプトを適当なディレクトリに置く。
（ここでは、PSScriptDirectoryという名前の変数に代入しているのを見てもらえればわかるが、起動時に読み込まれるスクリプトのあるディレクトリに新しくScriptsというディレクトリを作成し、そこにスクリプトを配置している）

以上


## 実装の説明
特段難しいことはしておらず
スクリプトを配置したディレクトリを変数に代入  
ディレクトリにある拡張子`ps1`のファイル一覧を取得し、ファイル名のみ抽出（ここではロードされたファイル名を表示する機能のためにファイル名のみを抽出している。ファイル名を表示する必要がなければ、Basenameを外すことでフルパスのファイル名を取得できるため、読み込み時の処理でディレクトリ名を合体させる必要がなくなる）
ファイル名を表示し
読み込み
完了時に"Done"と表示する
また、エラーが検出されると"Abort"を表示する
（このあたりは完全なこだわりである）

スクリプトの外部読み込みは
`. ScriptFile.ps1`
と書くことでできる
vue3でchart.jsを使いたい（Vue3 ChartJS Wrapper）


こちらの記事に助けられたのでメモです。
A Simple ChartJS wrapper for Vue3

https://vuejsexamples.com/a-simple-chartjs-wrapper-for-vue3/


Vue3 ChartJS Wrapper　を使う。

```zsh
yarn add @j-t-mcc/vue3-chartjs

npm install @j-t-mcc/vue3-chartjs
```

***

メモ：

Chart.js公式
https://www.chartjs.org/

Chart.jsについて日本語訳してくれているサイト
https://tr.you84815.space/chartjs/
https://tr.you84815.space/chartjs/axis/cartesian/time.html
Notionのページをpdfで出力したい！

#はじめに
NotionのページをPDFなどに出力できることを知ったので、紹介します。
今日まで気づかなかった…

##ページをpdfで出力できる

###方法
1. ページの右上の`・・・`をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/513de543-666e-5435-f54f-953ca35d6afc.png)


2. `Export`を選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/e96226e0-63c1-3b46-25a3-c539971351ed.png)

3.`Export format`をPDFにし、ページのサイズを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/dfaa393b-5ff0-05af-5177-73926d019af4.png)

4.保存先のファイルを選択する。


###注意
下に長くなってもpdfで出力できるが、変なところで区切れたり、データベースや横並びにブロックを配置していると、若干レイアウトが崩れたりすることがあるので、お気をつけください。

##最後に
Notionをpdf化出来るなら、
GoodNotes5との相性も良さそう！！また、可能性が広がりました。
AtCoder Beginner Contest 196 参戦記

# AtCoder Beginner Contest 196 参戦記

誤読で爆死して、8回連続単調増加で記録がストップしました.

## [ABC196A - Difference Max](https://atcoder.jp/contests/abc196/tasks/abc196_a)

1分半で突破. 書くだけ.

```python
a, b = map(int, input().split())
c, d = map(int, input().split())

print(b - c)
```

## [ABC196B - Round Down](https://atcoder.jp/contests/abc196/tasks/abc196_b)

2分で突破. 書くだけ.

```python
X = input()

if '.' in X:
    print(X.split('.')[0])
else:
    print(X)
```

## [ABC196D - Hanjo](https://atcoder.jp/contests/abc196/tasks/abc196_d)

20分くらい?で突破. Cがぱっと見では分からなくて、Dの問題文を眺めたら簡単だったのでこちらへ. HW≤16 なので、再帰関数で全て試せばいいですね.

```python
H, W, A, B = map(int, input().split())

placed = [[False] * W for _ in range(H)]


def proceed(p):
    y, x = p
    if x + 1 < W:
        return (y, x + 1)
    return (y + 1, 0)


def f(p, a, b):
    y, x = p

    if y == H:
        return a + b == 0

    if placed[y][x]:
        return f(proceed(p), a, b)

    result = 0
    if a >= 0:
        # right
        if x + 1 < W and not placed[y][x + 1]:
            placed[y][x] = True
            placed[y][x + 1] = True
            result += f(proceed(p), a - 1, b)
            placed[y][x + 1] = False
            placed[y][x] = False
        # down
        if y + 1 < H and not placed[y + 1][x]:
            placed[y][x] = True
            placed[y + 1][x] = True
            result += f(proceed(p), a - 1, b)
            placed[y + 1][x] = False
            placed[y][x] = False
    if b >= 0:
        placed[y][x] = True
        result += f(proceed(p), a, b - 1)
        placed[y][x] = False
    return result


print(f((0, 0), A, B))
```

## [ABC196C - Doubled](https://atcoder.jp/contests/abc196/tasks/abc196_c)

50分くらい?で突破、RE1、WA2. 何故か123321みたいに回文になっているものと問題を誤読して死んだ. その誤読状態でも入出力例は通るという……. N<10<sup>12</sup> なので前半部はせいぜい最大でも6桁なので、*O*(*N*) ループでも通る.

```python
N = input()

if len(N) % 2 == 1:
    N = '9' * (len(N) - 1)
if len(N) == 0:
    print(0)
    exit()

a = N[:len(N) // 2]
b = int(N)
result = 0
for i in range(1, int(a) + 1):
    if int(str(i) * 2) > b:
        break
    result += 1
print(result)
```

追記: なんでこんなに難しく考えてたんだろうと反省した.

```python
N = int(input())

result = 0
for i in range(1, 1000000):
    if int(str(i) * 2) > N:
        break
    result += 1
print(result)
```

## [ABC196E - Filters](https://atcoder.jp/contests/abc196/tasks/abc196_e)

突破できず. 問題を解くのにあまり時間が使えなかったので脳筋メモ化再帰で高速に実装しましたが TLE でした. やっぱりそうか…….
ActivityResultContracts.RequestMultiplePermissions チートシート

最近はパーミッション関連の処理が随分と簡潔に書けるようになったのは嬉しいのだけれども、なにが困るってJavaで書かなければならない時に少し混乱することがあるのでチートシートとして :scroll:


- [ActivityResultContracts.RequestMultiplePermissions  |  Android Developers](https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts.RequestMultiplePermissions)
- [Getting a result from an activity  \|  Android Developers](https://developer.android.com/training/basics/intents/result)


## Java

```java
private final ActivityResultLauncher<String[]> requestPermissionsLauncher =
        registerForActivityResult(
                new ActivityResultContracts.RequestMultiplePermissions(),
                (Map<String, Boolean> grantStates) -> {
                    for (Map.Entry<String, Boolean> grantState : grantStates.entrySet()) {
                        Timber.d(grantState.getKey() + " - " + grantState.getValue());
                    }
                });

private void requestPermissions() {
    requestPermissionsLauncher.launch(new String[]{
            Manifest.permission.Foo,
            Manifest.permission.Bar
    });
} 
```

## Kotlin

```kotlin
private val requestPermissionsLauncher =
        registerForActivityResult(RequestMultiplePermissions()) { grantStates: Map<String, Boolean> ->
            for ((permission, granted) in grantStates) {
                Timber.d("$permission - $granted")
            }
        }

private fun requestPermissions() {
    requestPermissionsLauncher.launch(arrayOf(
            Manifest.permission.Foo,
            Manifest.permission.Bar
    ))
}
```
【初心者でもわかる】パンくずリストのデザインをスマホに最適化させる方法

# どうも7noteです。スマホだと長すぎて不細工になってしまうパンくずリストをスッキリさせる方法

PCなら多少長くなってもたいして問題ないパンくずリストでも、レスポンシブサイト化させたときに、スマホだとダサくなってしまうのをスッキリさせます。


×【ダサい例】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/956b97d7-b2a8-5ba5-51c2-c3509dd627a9.png)


〇【スッキリさせた例】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/6cf2be85-abe4-d1fc-6059-0110b7b6d433.png)

---

## スッキリさせるパンくずリストの書き方

```index.html
<!-- (仮)金持ちブログのパンくずリスト例 -->
<ul class="breadcrumb">
  <li><a href="/">トップ</a></li>
  <li><a href="../../">超絶お金持ちになるブログ</a></li>
  <li><a href="../">お金持ち理論</a></li>
  <li>年収300万円でも超絶スーパーお金持ちになれる方法</li>
</ul>
```

```style.css
.breadcrumb {
  background: #eee; /* 背景色をグレーに指定 */
  padding: 5px;     /* 余白を指定 */
  white-space: nowrap; /* 改行（行送り）を禁止させる */
  overflow-x: scroll;  /* 横スクロールを可能にする */
}

.breadcrumb li {
  display: inline-block; /* インラインブロック要素にする */
}

.breadcrumb li:not(:last-child)::after {
  content: '>';    /* 間の矢印を設定 */
  margin: 0 0.5em; /* 左右に余白をとる */
}
```

## 解説

重要なのはこの2行。

```
white-space: nowrap; /* 改行（行送り）を禁止させる */
overflow-x: scroll;  /* 横スクロールを可能にする */
```

この2行を入れることで、**行送りになるのを禁止させ、かつ横にはみ出た部分を非表示にして横スクロールを可能にさせます。**

パンくずリストだけでなく、CSSだけでスライドショー風なものを作るのにも使えます。

![carousel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/cda25852-d9cf-b859-f520-16332c495b38.gif)

過去記事より引用：[【初心者でもわかる】cssだけでスライドショー風の横スクロールできるカルーセルの作り方](https://qiita.com/7note/items/b004551e996c75185674)

## まとめ

いっそパンくずリスト自体を非表示にしてしまうのもできますが、SEO的にもパンくずリストは残しておいた方が無難らしいのでせめてスッキリ見せる方法で対応できればいいかなと思います。
ほかの方法などもあるかもしれませんので、オススメの方法などあればぜひコメントください。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
#2,環境作り

#ターミナル動かしてみた
自分のMacにはpythonが入ってるそう。
ターミナルと呼ばれるノートブック的なのを起動して指示されるがままに打ち込んでみた
##pythonのバージョンの確認
ターミナルを起動してとりあえずpythonのバージョンの確認をしてみた
ターミナル（Windowsだと呼び方が違うらしい）を起動すると『％』表記があり、そこに続けて『python --version』と打って見るとpythonのバージョン番号が出てきます。
最初は何だったか覚えてないけど、なんか使いづらいやつらしくて結局『Anaconda』と呼ばれるいわゆるスターターパックをダウンロード。
##どっかいった
アナコンダで入れたpythonがどこかに消えてしまう事件が発生
ここでも大活躍のターミナル先生の登場
『ls』と打つと住所のノリでどこにあるのかがわかるそう
確認できたので改めて『python --version』と打って見るとpythonのバージョン番号が3.8.5と確認できました。まあ十分らしいので次に進みます

##jupyterを起動してみる
名前が『prog』に設定されているので『cd prog』とターミナルで打ってみるとディレクトリ的なのが開いたようです。（初心者すぎて何が起きてるのかもわからない）続けて『jupyter-notebook』と打つとターミナルに文字が羅列したのち、サイトのページが開きます
開いたページは「jupyter」と呼ばれるnoteで、パイソンを実行したり、マークダウンでメモったりできるようです

#まとめ
1.ターミナルを開いてpythonを確認
2.バージョンが足りないのでアナコンダをインストール
3.ターミナルから『cd prog』でディレクトリに移動
4.『jupyter-notebook』でjupyterを開く
5.pythonやmarkdownでメモったりできるようになった
RubyでFizzBuzz問題を書こう（改良版）

## はじめに
この記事は
[RubyでFizzBuzz問題のコードを書く（初心者用）]
(https://qiita.com/Okisen/items/5288a054fce67ba7d094)
[Ruby の while の使い道]
(https://qiita.com/scivola/items/575570d46252d381af78)
の記事を参考にした、初歩的なプログラミングのアウトプットを目的とした記事です。
見辛い点、分かりづらい点などあったらご指摘いただけると幸いです。

## FizzBuzz問題について
FizzBuzz問題は、プログラミングの初歩的な問題です。内容は
"1~100の数字を表示させる"
ただしこの時、
"3の倍数の数字の代わりにFizz"
"5の倍数の数字の代わりにBuzz"
"３と５の倍数の数字の代わりにFizzBuzz"
と表示させる。
と言う問題です。

## 方針
まず1~100の数字を表示させることから考えます。次に表示させる元の数字によって処理を変えていきましょう。

ここからが参考元と異なる部分です。
[Ruby の while の使い道]
(https://qiita.com/scivola/items/575570d46252d381af78)
を参照していただければ分かりやすいのですが、
>Ruby では while の出番は少ない，と言い切ってよいと思います。
>…
>値をすこしずつ変えてループを回すような場合，たいがいそれに適したメソッドがあります.

と言うことで、ここでは、uptoメソッドを利用して1~100の数字を表示させることを考えます。

## 1~100の数字の表示

```ruby

1.upto(100) do |count|
  puts count
end
```
この記述で、1から100までの数字を表示させることができるようになります。また、このメソッド内ではcountと言う変数に1から100までの値がそれぞれ用意されます。countの値に応じて、FizzやBuzzと言った文字を表示させましょう。

## 条件分岐
参考元の説明も含めると分かりやすいかと思います。
[RubyでFizzBuzz問題を書こう（初心者用）]
(https://qiita.com/Okisen/items/5288a054fce67ba7d094)
表示を変更する条件について、最も縛りがきついのは15の倍数についてです。数学の集合の分野で扱うべん図を考えていただければ分かりやすいです。15の倍数は、他2つの条件を常に満たしているのです。すなわち、15の倍数であると言うことは、3の倍数であることも示し、同時に5の倍数であることも示します。
Rubyのプログラムは上に記述されているものから読み込まれます。つまり題意を満たすためには、countが15の倍数の場合の処理について先に記述することが重要と言えます。それに留意したプログラミングを以下に示すと、

```ruby

if count % 15 == 0
  puts "FizzBuzz"
elsif count % 5 == 0
  puts "Buzz"
elsif count % 3 == 0
  puts "Fizz"
else
  puts count
end
```
となります。

## 感想・まとめ
1~100の数字の表示と条件分岐をまとめると、コードは

```ruby

1.upto(100) do |count|
  if count % 15 == 0
    puts "FizzBuzz"
  elsif count % 5 == 0
    puts "Buzz"
  elsif count % 3 == 0
    puts "Fizz"
  else
    puts count
  end
end
```
となります。while文を使っているときより、何がしたいか分かりやすいコードになったのではないかと思います。

自分は初心者ですのが、万人にとって分かりやすい表現を考えながらコードを書いていったつもりです。分かりにくい表現があったら申し訳ありません。この記事が初心者の方の少しの助けにでもなれば幸いです。
[Kotlin] Result型

KotlinのResult型の存在を知ったので、勉強メモ
公式は[こちら](https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.md)

##Result型とは

Kotlin1.3からstdlibに登場した型です

RustやScalaにも同じ名前の方がありますが、Kotlinのものは特殊で、**メソッドの戻り値にすることができない**という特徴があります
したがって、「例外を返すかもしれないからなんとかして！」というメッセージをメソッド間で伝える、という使い方はできません[^reason]

例えば、Rustではこんな使い方ができます
Result型を使えば、呼び出し元にエラーハンドリングを強制できます

```rust
/**
 * 引数が偶数ならば2で割った数、奇数ならばエラーを返す
 */
fn devideBy2(x: i32) -> Result<i32,&'static str> {
    if x % 2 == 0 {
        Ok(x / 2)
    } else {
        Err("error message")
    }
}

fn main() {
    let x = // 何かしら代入

    match devideBy2(x) {
        Ok(result) => println!("number: {}", result),
        Err(msg) => println!("error: {}", msg),
    }
}
```

残念ながらKotlinではこのような使い方ができません
理由は、将来の拡張でResultのセマンティックが変わる可能性が高いからだそうです。ぜひ早く対応して欲しいですね！

...が、なんとList<Result<T>>など、単なるResult型でなければ関数の返り値にすることができます
失敗したやつを呼び出し元でまとめて処理したい場合に使えます

他にも

- 非同期処理のコールバックの引数
- 関数内で失敗時の処理を強制する

などのユースケースがあるようです
ApacheでJavaアプリとNodeアプリを動かす

# はじめに
もともとApatch + TomcatでJavaアプリケーションを稼働しているサーバーがあり、
そこにReact + Node + Typescriptで作ったアプリケーションを稼働させたいという要望があり(私の要望)それを実現するためにやったことを書いていこうと思います。

参考にしたサイトは[こちら](https://ja.stackoverflow.com/questions/38818/apache-%E3%81%A8-node-js-%E3%81%AE%E9%80%A3%E6%90%BA%E3%81%A7url%E3%83%91%E3%82%B9%E3%82%92%E4%BB%98%E5%8A%A0%E3%81%97%E3%81%9F%E3%81%84 "Apache と node.js の連携でURLパスを付加したい")

#前提条件
- Javaのアプリケーションは稼働済み
- Javaアプリケーションは`xxx.xxx.xxx`でアクセス可(ルート)
- Nodeアプリケーションは`xxx.xxx.xxx/node/`でアクセス可にする
- Nodeアプリケーションの稼働ポートは`3000`
- localhost:3000/node/でNodeアプリケーションが稼働している

#設定値
特定のURLにアクセスした場合に違うパスにアクセスさせる。(ブラウザで見えるアクセスURLは変わりません。)

xxx.xxx.xxx/node/
↓
localhost:3000/node/


```conf/httpd.conf
#コメントを外して有効にする
LoadModule proxy_http_module modules/mod_proxy_http.so

```
`LoadModule proxy_http_module modules/mod_proxy.so`もコメントで無効の場合は、
コメントを外して有効にする。


```conf/extra/httpd-proxy-ajp.conf 

# 以下を追記
<Location /node/>
  ProxyPass http://localhost:3000/
  ProxyPassReverse http://localhost:3000/
  Require all granted
</Location>

```

アクセスのパスを変更したい場合は`Location /node/`の`/node/`を変更することで実現できます。


元々は`httpd-proxy-ajp.conf`のファイルにajpに関する設定があり今回は同じファイルに書いていますが、おそらく上記参考サイトのように`httpd-proxy.conf`のようなファイルを作ってそちらに書いたほうがわかりやすいと思います。
Laravelでリアルタイムのログを流すコマンド(ログモードdaily版)


#Laravelのログをリアルタイムで流す。
毎回ログフォルダまでcdしてからtail -f していたが、移動するのが面倒臭いのでコマンドを考えました。

Laravelプロジェクトのルートフォルダで以下のコマンドを流す。

```bash
tail -f ./storage/logs/log-$(date "+%Y-%m-%d").log
```

アプリケーションルートにでも.shファイル作って上のコマンド貼り付けておいとくと便利です。

## Makefileを使う

```
cd {project_root や docker-compose.ymlのあるディレクトリなど}
touch Makefile
vim Makefile
```

以下を貼り付け ２行目の頭のスペースはタブ一つ。

```
log-error:
	tail -f backend/storage/logs/error/log-$(shell date "+%Y-%m-%d").log
```

使用

```
cd {project_root や docker-compose.ymlのあるディレクトリなど}
make log-error
```
yamlをインタラクティブに絞り込みできるCLIを作った

## 初めに
最近仕事ですこしk8s周りを触っています。k8sのマニフェストはyamlですが、
kustomizeなどを使ってリソースをまとめたりすると、どうしても長くなってしまい可読性が下がってしまう問題があります。

そこで、[jid](https://github.com/simeji/jid)のようなインタラクティブに絞り込みできるツールがほしいなと思って調べたんですが、
見つからなかったので[yd](https://github.com/skanehira/yd)というCLIを作りました。

![](https://i.gyazo.com/521400d0740ed12c1606a8ab9b618632.gif)

## 使い方
`yd`ではパイプ、ファイル、URLからyamlを読み込めます。

```sh
$ yd file.yaml
$ yd https://sample.com/file.yaml
$ yd < file.yaml
$ yd -f file.yaml
```

CLI実行後、画面上部にクエリを入力する箇所があるので、そこにクエリを入力してyamlをインタラクティブに絞り込んでいきます。
例えば次のようなyamlがある場合`.tags`と入力すると画像のように絞り込めます。
使用できるクエリは[こちら](https://mikefarah.gitbook.io/yq/operators)を参照してください。

```yaml
swagger: "2.0"
info:
  description: "This is a sample server Petstore server.  You can find out more about Swagger at <a href=\"http://swagger.io\">http://swag
ger.io</a> or on irc.freenode.net, #swagger.  For this sample, you can use the api key \"special-key\" to test the authorization filters"
  version: 1.0.0
  title: Swagger Petstore YAML
  termsOfService: "http://swagger.io/terms/"
  contact:
    email: "apiteam@swagger.io"
  license:
    name: Apache 2.0
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
basePath: /v2
tags:
  - name: pet
    description: Everything about your Pets
    externalDocs:
      description: Find out more
      url: "http://swagger.io"
  - name: store
    description: Operations about user
  - name: user
    description: Access to Petstore orders
    externalDocs:
      description: Find out more about our store
```

![](https://i.gyazo.com/8ad89ace76266d196ecfca29cd1c5a81.png)

## 仕組み
`yd`は内部で[yq](https://github.com/mikefarah/yq)を使っています。`yq`ではコア処理を`yqlib`として切り出されているためCLIでは内部でそれを使っています。
そのため、クエリのパースや絞り込みの処理は実装せずフロントの部分の実装のみとなっています。

`yqlib`に関するドキュメントは見つからなかったんですが、
`yq`の実装ではクエリ(`expr`)を式としてパースしたあとに評価(`eval`)するようになっているので直感的でわかりやすかったです。
`yd`ではパーサーと評価器を使って入力するたびにパースして評価して、その結果を描画しています。

```go
node, err := ui.Parser.ParseExpression(expr)
if err != nil {
	return
}

...

if err := ui.Evaluator.Evaluate("-", &in, node, ui.Printer); err != nil {
	return
}

ui.View.SetText(tview.TranslateANSI(ui.Out.String())).ScrollToBeginning()
```

`yd`自体の実装はとてもシンプルなので詳細な実装が気にいなる方はリポジトリを気軽に覗いてみてください。

## 最後に
`yd`はとりあえず雑に作って仕事で最低限使えるレベルになったので公開しましたが、ツールとしての完成度については全然満足していないのでちょいちょい改善していきたいと思います。

動かないところもあるかもしれないんですが、興味ある方は使ってみてください。
Effect callbacks are synchronous to prevent race conditions.

useEffectで非同期処理を実行したかった時に怒られたのでメモ。

# 起こったこと

こういうふうにasync関数をuseEffectの第一引数に設定したところ

```jsx
const getAllBlogs = async () => {
	if (user) {
		blogService.setToken(user.token)
		const blogs = await blogService.getAll()
		setBlogs(blogs)
	}
}
useEffect(getAllBlogs, [user])
```

以下のようなエラーが出てしまいました。
![スクリーンショット 2021-03-20 22.09.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329016/2b910a28-35da-304a-3a7f-56e267330227.png)


Put the async function inside らしいです。丁寧にサンプルコードまで提示してくれています。

# 修正

useEffectの第一引数の関数内に新しくfetchBlogsというasync関数を定義し、その中でawait getAllBlogs()としました。

```jsx

const getAllBlogs = async () => {
	if (user) {
		blogService.setToken(user.token)
		const blogs = await blogService.getAll()
		setBlogs(blogs)
	}
}
useEffect(() => {
	const fetchBlogs = async () => {
		await getAllBlogs()
	}
	fetchBlogs()
}, [user])

```

が、まだエラーが出ています。
![スクリーンショット 2021-03-20 19.59.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329016/7d537f29-fb2b-d384-df9a-aa91078c54db.png)

fetchBlogsの中に全部入れるとエラーは出なくなりました。

```jsx

useEffect(() => {
	const fetchBlogs = async () => {
		if (user) {
			blogService.setToken(user.token)
			const blogs = await blogService.getAll()
			setBlogs(blogs)
		}
	}
	fetchBlogs()
}, [user])

```