OmniAICreator/Qiita-1.07M huggingface dataset:
C言語の構造体が分からなかったがなんとなくわかった話

結構初歩的な話ですが、自分用メモ。
個人的に、C→Javaは入りやすいイメージですがJava→Cはなんとも。。。
構造体はJavaのクラスのように、構造体の中で定義されたデータ型はメンバ変数のように扱うのです。

※ここではアロー演算子については触れません。

##Javaソース
クラスHogeをインスタンス生成することで、Hogeクラスのint型変数の値を出力、書き換えができます。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Hoge hoge = new Hoge();
        System.out.println(hoge.num);
        hoge.num = 6;
        System.out.println(hoge.num);
    }
}
class Hoge{
    int num = 5;
}
```

##C言語ソース
**実体**を持つ構造体に限るのでそこだけ注意です。

```
#include <stdio.h>
int main(void){
    struct student{
        int num;
    };
    struct student student_hoge;
    
    student_hoge.num = 5;
    printf("%d\n", student_hoge.num);

    return 0;
}

```
Add custom header to S3 CreateBucket request

Sample code for adding custom header to CreateBucket request.
AWS-SDK's  [CreateBucket](https://docs.aws.amazon.com/sdk-for-go/api/service/s3/#S3.CreateBucket "CreateBucket") does not let you add custom headers so you have to create your own http request.

```golang

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/aws/aws-sdk-go/aws/credentials"
	v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
)

func createBucket() {

	endpoint := "https://xxx.xxx.xxx/"
	region := "region-1"
	bucketName := "bucket-name"

	// Specify accesskey secretkey or read from env with NewEnvCredentials()

	cred := credentials.NewEnvCredentials()

	// cred := credentials.NewStaticCredentialsFromCreds(credentials.Value{
	// 	AccessKeyID:     akey,
	// 	SecretAccessKey: skey,
	// })

	signer := v4.NewSigner(cred)

	httpClient := &http.Client{}

	// Create a PUT request

	req, err := http.NewRequest(http.MethodPut, endpoint+bucketName, nil)
	if err != nil {
		fmt.Print(err)
	}

	// Now add whatever header you want

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("HEADER-TO-BE-ADDED", "HEADER-TO-BE-ADDED")

	// Sign it

	signer.Sign(req, nil, "s3", region, time.Now())

	// Send the request
	res, err := httpClient.Do(req)
	log.Println(res.Status)

}```
SQL のトランザクションについて

# SQLトランザクションとは
複数の SQL 文によるデータ更新を1つの処理としてまとめてデータベースに反映させることです。

---

# トランザクションブロック

```sql
BEGIN TRANSACTION;

-- Code


END TRANSACTION;
```

```sql
BEGIN;

-- Code


COMMIT;
```

---
# トランザクションの実際の動き(普通の動き)
- トランザクションでcommitしないと、DBに反映されない

- Tab1

```sql
BEGIN TRANSACTION;
INSERT INTO public.companies (
  uuid, name
) VALUES
  ('test_com')
;

```

- Tab2

```sql
SELECT * FROM public.companies
```

- Tab1

```sql

COMMIT;

```

- Tab2

```sql

SELECT * FROM public.companies

```


# トランザクションの実際の動き(同時に追加 / uuidしてしない)

- Tab1

```sql
BEGIN TRANSACTION;
INSERT INTO public.companies (
  uuid, name
) VALUES
  ('test_com')
;
SELECT * FROM public.companies;

```

- Tab2

```sql
BEGIN TRANSACTION;


INSERT INTO public.companies (
  name
) VALUES
  ('test_com2')
;
SELECT * FROM public.companies;

```

- Tab1

```sql

COMMIT;

```

- Tab2

```sql

COMMIT;
SELECT * FROM public.companies

```

---

# トランザクションの実際の動き(同時に追加 / プライマリーuuid指定する)

- Tab1

```sql
BEGIN TRANSACTION;
INSERT INTO public.companies (
  uuid, name
) VALUES
  ('33333333-3333-3333-3333-333333333334','重複com')
  ON CONFLICT DO NOTHING
;
SELECT * FROM public.companies;

```

- Tab2

```sql
BEGIN TRANSACTION;
INSERT INTO public.companies (
  uuid, name
) VALUES
  ('33333333-3333-3333-3333-333333333334','重複com')
  ON CONFLICT DO NOTHING
;
SELECT * FROM public.companies;

```

- Tab1

```sql

COMMIT;

```

- Tab2

```sql

COMMIT;

```

---

# ストプロ注意
- ストプロ準備

```
DROP TYPE IF EXISTS type_create_campaign CASCADE;
CREATE TYPE type_create_campaign AS (
  company_uuid UUID
);
CREATE OR REPLACE FUNCTION create_campaign(
  p_company_uuid UUID
  ,p_name TEXT
) RETURNS SETOF type_create_campaign AS $FUNCTION$
DECLARE

BEGIN
  --チェックキャンペーン存在
  PERFORM 1 FROM public.campaigns
  WHERE 
    name = p_name
    AND 
    company_uuid = p_company_uuid
  ;
  IF FOUND THEN
    RAISE SQLSTATE 'U0003' USING MESSAGE = 'campaign name has exist';
  END IF;

  -- キャンペーン追加
  INSERT INTO public.campaigns (
    company_uuid, name
  ) VALUES
    (p_company_uuid,p_name)
    ON CONFLICT DO NOTHING
  ;

  RETURN QUERY SELECT p_company_uuid;
END;
$FUNCTION$ LANGUAGE plpgsql;

```

## 試す1

```sql


BEGIN TRANSACTION;
SELECT * FROM create_campaign(
	p_company_uuid := '33333333-3333-3333-3333-333333333333',
	p_name := 'com_3_cp_3'
);
SELECT * FROM create_campaign(
	p_company_uuid := '33333333-3333-3333-3333-333333333333',
	p_name := 'com_3_cp_3'
);
COMMIT;


```

## 試す2

```sql

-- Tab1
BEGIN TRANSACTION;
SELECT * FROM create_campaign(
	p_company_uuid := '44444444-4444-4444-4444-444444444444',
	p_name := 'com_4_cp_4'
);

-- Tab2
BEGIN TRANSACTION;
SELECT * FROM create_campaign(
	p_company_uuid := '44444444-4444-4444-4444-444444444444',
	p_name := 'com_4_cp_4'
);


-- Step2
-- Tab1
COMMIT;
-- 結果を見る

-- Tab2
COMMIT;
-- 結果を見る

```
Flutter :   TextFormFieldでUIを描画できない

#はじめに
現在flutterでアプリを作成中(カレンダーアプリ的なやつ)超初心者で勉強中
アカウント機能　ログイン機能を作成中に本事象に遭遇してなるほどーと思ったのでメモ程度に

#開発環境
・使用言語：dart(flutter)
・AndroidStudio 4.1.2
・iOS シミュレーター(iOS14.5)

#事象
TextFormFieldを使用して入力フォームを作成しようと思ったが、以下のエラーが表示され対象画面へ遷移した際にUIが描画されない

```
The following assertion was thrown during layout:
A RenderFlex overflowed by 99164 pixels on the bottom.

The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
```

以下の記載がつかまってそう。。。

```kotlin
children: <Widget>[
  const Padding(
  padding: EdgeInsets.fromLTRB(25.0, 0, 25.0, 30.0),
  child: Text(
  "新規アカウント作成",
  style: TextStyle(
    color: Colors.blueGrey,
    fontSize: 20,
    fontWeight: FontWeight.bold,
  )
),),
 Padding(
   padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
   child: Form(
   key: key,
   child: TextFormField(
     decoration: const InputDecoration(hintText: "メールアドレス"),
     onChanged: (String value){
       _newEmail = value;
     },
   ),
 ),
),
```

#解決方法
TextFormFieldの制約がないためにエラーになっているそう！
Expandedで括って最大の大きさにしたり、Containerでサイズを指定すると解決しました！

```flutter
Expanded(
  child: Container(
    padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
      child: Form(
        key: key,
        child: TextFormField(
          decoration: const InputDecoration(hintText: "メールアドレス"),
          onChanged: (String value){
            _newEmail = value;
          },
        ),
      ),
    ),
  ),

```
Ruby を使って気軽に LTSV 形式のログをパースしたい

```bash
$ cat access.log
time:2015-09-06T05:58:05+09:00  method:POST     uri:/foo/bar?token=xxx&uuid=1234        status:200      size:12 apptime:0.057
time:2015-09-06T06:00:43+09:00  method:GET      uri:/foo/bar    status:400      size:15 apptime:-
time:2015-09-06T06:00:43+09:00  method:GET      uri:/foo/bar/5xx        status:504      size:15 apptime:60.000

# Ruby 2.6 より前でも動くように Hash#to_h にブロックを渡さない書き方をする。
$ cat access.log | ruby -e 'ARGF.read.each_line { |line| hash = line.split("\s").map { |item| item.split(":", 2) }.to_h; puts hash.values_at("method", "uri", "status").join(" ") }'
POST /foo/bar?token=xxx&uuid=1234 200
GET /foo/bar 400
GET /foo/bar/5xx 504
```
macOS Monterey の出力音質を引き上げる設定

macOS Monterey の出力音質を引き上げる設定についてメモします。
Monterey はデフォルト設定では最高音質にはならないことがあり、以下のように設定変更が必要です。

## 前提条件

このメモは以下の環境で確認および記述しました。

* `macOS` `Monterey` (MacBook Pro)
* `Roland Rubix22` (USB接続オーディオインタフェース)

# macOS Monterey の設定

## Audio MIDI 設定

### Audio MIDI の起動

Launchpad から `Audio MIDI 設定` を起動します。
![AudioMIDI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105739/4dddcc69-087d-c9e3-f831-0d1a98af4a1f.png)

### オーディオ装置の設定

対象となるオーディオ装置の設定を変更します。
このメモでは Rubix22 を利用しているため、`Audio MIDI 設定` の `オーディオ装置` の一覧から `Rubix22` を選択して設定を更新します。
`出力` のフォーマットは Rubix22 の最高音質である `192,000 Hz` (2 ch 24ビット整数) が選択可能ですが、普段聞く音源の最高音質への変更が良いでしょう。画像は最高音質のものでスクショとりました。
![AudioMIDI-Rubix22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105739/f0669ab0-cf08-84f8-4fb5-9e63d90b2e41.png)

これにより、デフォルトの出力音質の挙動が指定のフォーマット（画像の例では 192 kHz / 24bit）に更新されました。

# Apple Music の設定

macOS で音楽を聴く場合に `Apple Music` を利用している人も多いことでしょう。
その場合は、Apple Music のメニュー `ミュージック` | `環境設定...` で設定のダイアログを開き、`再生` タブをクリックして設定を変更します。
オーディオの品質の設定を以下のように変更します。

* `ロスレスオーディオ` をチェック済み
* ストリーミングを `ハイレゾロスレス (最大24ビット /192 kHz のALAC)` に変更
* ダウンロードを `ハイレゾロスレス (最大24ビット /192 kHz のALAC)` に変更
* 「音量を自動調整」について OFF（チェックなし） に変更

![AppleMusicSettings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105739/3865f92d-00ff-692e-34eb-49a5731ff418.png)

これにより、Apple Music の再生が最高音質に変わり、前述の macOS の設定変更と合わせ技で高音質な再生環境を得ることができました。
Apple Music の中から ハイレゾ対応コンテンツを再生してみると、圧倒的な差が感じられるかもしれませんね。

※「音量を自動調整」についてOFFのほうが音質が良いのですが、音源ごとの音量の差が大きい場合には都度音量を変更をするのが辛いので、利用形態によっては ON で妥協する必要があることでしょう

# おまけ: 再生装置の音質を上げる

出力再生音質があがったので、あとはスピーカーやヘッドホンの再現性を高められれば、高品質な再生環境が得られることが期待できます。

## ヘッドホン

高品質なモニターヘッドホンやハイレゾヘッドホンを Rubix22 のヘッドホン端子につなげることにより、高音質再生環境を得られることでしょう。

## アンプおよびスピーカー

Rubix22 の出力先に、以下のいずれかを選択することにより、高音質再生環境を得られることでしょう。

* ハイレゾ対応アンプおよびハイレゾ対応パッシブスピーカーを Rubix22 の出力に接続する
* ハイレゾ対応アクティブスピーカーを Rubix22 の出力に接続する

# 処理音質をソース音源に揃える

ソース音源の音質が高くない場合は、ソース音源の音質に合わせて DAC の音質設定を下げた方が高音質な再生を得られる場合があります。
例えば、ソース音源がCD音質である場合は、`オーディオ音質` のフォーマット設定を `44,100 Hz` まで下げるのです。

# プロパティ

* 初出: 2021-11-09

## 関連リンク

* [iPhone iOS 15.1 の出力音質を引き上げる設定](https://qiita.com/igapyon/items/72906e056262a0d5e89d)
* [macOS Monterey の出力音質を引き上げる設定](https://qiita.com/igapyon/items/b01f06917759fa783ac8)
* [Windows 10 の出力音質を引き上げる設定 (UR44C版)](https://qiita.com/igapyon/items/b93dd4a51b098f292169)
* [Windows 10 の出力音質を引き上げる設定 (Rubix22版)](https://qiita.com/igapyon/items/000ceb2961b88ff185be)
Reactで無限スクロールを実装する

Intersection ObserverAPIを使用して、無限スクロールを実装します。
取得するAPIはTMDBというものを使用します。

### Intersection ObserverAPIとは
簡単に言うと、ユーザーが画面上をスクロールなどした時、特定の要素が、ブラウザ上の表示されている領域に対してどの位置にあるかを監視して教えてくれる機能を持っている交差監視APIです。

下記が詳しいです
https://ics.media/entry/190902/

### API取得のロジック
```
import { useEffect, useState } from 'react'
import axios from 'axios'

export default function SearchMovies(query: any, pageNumber: any) {
  const [loading, setLoading] = useState<any>(true) // ローディングの判定
  const [error, setError] = useState<any>(false) // エラーを検知したらセットする
  const [movies, setMovies] = useState<any>([]) // 検索結果をセットする
  const [hasMore, setHasMore] = useState<any>(false) // 検索結果が残っているか判定する

  useEffect(() => {
    setMovies([])
  }, [query])

  // api呼び出し
  useEffect(() => {
    setLoading(true)
    setError(false)
      let cancel: any
      const apikey = 'hogehoge'
    axios({
      method: 'GET',
      url: 'https://api.themoviedb.org/3/search/movie',
      params: { api_key: apikey, query: query, page: pageNumber },
      cancelToken: new axios.CancelToken(c => cancel = c)
    }).then(res => {
      setMovies((prevMovies: any) => {
          return [...new Set([...prevMovies, ...res.data.results.map((b: any) => b.title)])]
      })
        setHasMore(res.data.results.length > 0)
        setLoading(false)
        console.log('then 成功です')
    }).catch(e => {
      if (axios.isCancel(e)) return
        setError(true)
        console.log('catch errorです')
    })
    return () => cancel()
  }, [query, pageNumber])
  return { loading, error, movies, hasMore }
}

```


### 画面描画
```
import React, { useState, useRef, useCallback } from 'react'
import SearchMovies from "./components/SeachMovies"


export default function App() {
  const [query, setQuery] = useState('') // 検索ワードをセットする
  const [pageNumber, setPageNumber] = useState(1) // ページ番号をセットする

  const {
    movies,
    hasMore,
    loading,
    error
  } = SearchMovies(query, pageNumber)

    // ref対象を監視して表示終わったら、ページ番号を増やす
  const observer: any = useRef()
    const lastMovieElementRef = useCallback(node => {
    if (loading) return
    if (observer.current) observer.current.disconnect()
        observer.current = new IntersectionObserver(entries => {
        if (entries[0].isIntersecting && hasMore) {
        setPageNumber(prevPageNumber => prevPageNumber + 1)
        }
    })
    if (node) observer.current.observe(node)
  }, [loading, hasMore])

    // 入力値をセットする
  function handleSearch(e: any) {
    setQuery(e.target.value)
    setPageNumber(1)
  }

  return (
    <>
        <input type="text" value={query} onChange={handleSearch}></input>
        {movies.map((movie: any, index: any) => {
          if (movies.length === index + 1) {
            return <div ref={lastMovieElementRef} key={movie}>{movie}</div>
          } else {
            return <div key={movie}>{movie}</div>
        }
      })}
      <div>{loading && 'Loading...'}</div>
      <div>{error && 'Error'}</div>
    </>
  )
}

```

上記を実装すると、入力値をqueryとして受け取り、検索結果を返してくれます。
スクロールすると、1ページ分ごとにAPIの結果が読み込まれて画面に描画されると思います。
WidgetツリーにWidgetが存在しない!?

#Flutterで高速画面遷移した時に出るエラー

おはこんにちは、今日も今日とてFlutterをいじっている人です。 
今回はFlutterの非同期処理やsetState()を利用してると出てくるエラーについて解説していきます。
####Widgetツリーにそんなものはないよ
さて本題に入ります。 
Flutterをいじっているとこのようなエラーに出くわしたことはないですか？
```This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
```
上記のエラーは任意的に出そうとしないと出現しないと思います。つまりFlutterが仕掛けた罠です!!（個人的意見です異論は認めます） 
私は英語がよわよわなのでGoogle先生に翻訳は丸投げです。 
内容を要約する**とWidgetツリーに存在していないWidgetを呼び出している**ということらしいです。

####解決法
このエラーが出てくる理由は
画面Aを開く 
↓
画面Aから画面Bに遷移する 
↓
画面Bで非同期処理を行なう。 
↓
画面Bで行われている非同期処理で得られる値を待たずに画面Aに遷移する。この時点で画面BのWidgetツリーはなくなる。 
↓
画面Aを開いていると、画面Bで得られた値が返り、存在していないWidgetに対して値を返そうとしているからエラーが出る。 
という流れになります。 

####サンプルコード
```dart
Future<void> _hoge() async{
  Image _hogeimg = await loadUiImage('assets/images/hogehoge.png');

  setState(() => {
    _barImage = _hogeimg
  });
}
```
上記のコードが画面Bだとすると、画面Bで画像をロードする前に画面Aに行ってしまうと画面BのWidgetツリーが既に無くなっているためエラーを吐きます。
解決法としてはmountedの追加があります。

```dart
Future<void> _hoge() async{
  Image _hogeimg = await loadUiImage('assets/images/hogehoge.png');
 
  if(mounted){ // 追加
    setState(() => {
      _barImage = _hogeimg
    });
  }
}
```
mountedを追加することによりsetStateを呼ぶ前に対象のWidgetがそのWidgetツリーにあるかどうかを判断してくれます。この解決法もFlutterさんが親切に教えてくれてますね
```Another solution is to check the “mounted” property of this object before calling setState() to ensure the object is still in the tree.
```
以上で今回の記事は終わりにしたいと思います。皆様よいFlutterライフを！！
"ssh: Could not resolve hostname" IPアドレスを固定せずにホスト名でSSH接続したい

# やりたいこと
IPアドレス管理が面倒くさいから固定せずにSSH接続したい

# 環境
windows10　→　Ubuntu 20.04.3 LTS
windowsからUbuntuへのSSH接続


# 何もせずホスト名でSSHしようとすると
```
> ssh [user名]@[host名]
```
↓

```
ssh: Could not resolve hostname ***
```

# 対処法
Ubuntuにsambaをインストールしてください
NetBIOSによる名前解決が可能になるそうです
詳しくは

https://tech-note-meeting.com/2020/08/14/post-316/

# sambaインストール方法
以下のリンクを参考に

https://qiita.com/k-Mata/items/8bee9e02e74565b6c147

ファイアウォールの設定も

https://sasaplus1.hatenadiary.com/entry/20120920/1348146388


# どうなる
IPアドレスを調べなくてもホスト名だけで接続できる！！
【GCP入門】TerraformでGCPのVPCとサブネットを作成

GCPも少し触り始めたので、まずはVPCとサブネットをTerraformで作成してみました。

# provider
`credentials` で認証情報を持つjsonファイルのパスを指定しています。
AWSの場合、IAMユーザーを作成し、プログラムアクセス用の `access_key_id` と `secret_access_key` をcredentialファイルにセットしますが、GCPの場合はサービスアカウントを作成し、キーファイルのパスを指定するようです。今回は、`key.json` という名前でホームディレクトリに配置してみました。（`GOOGLE_APPLICATION_CREDENTIALS`の環境変数でパスを指定してもOKです）

なお、providerで指定する `project` はGCPのアカウントに紐付けられるプロジェクトIDです。
業務の計画やチームの意味で使う一般的な「プロジェクト」ではありません。（最初わからなくて自由に名付けることができるのかと思ってしまった）

```terrraform:provider.tf
terraform {
  required_version = ">= 1.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 4.0"
    }
  }
}

provider "google" {
  project     = var.gcp_project
  region      = var.region
  zone        = var.zone
  credentials = file("~/.gcp/key.json")
}
```

# variables
とりあえず使いそうな変数を `variables.tf` に宣言。
prefix に環境、プロジェクト名を入れたい派なので、ローカル変数で書いています。

```terraform:variables.tf
variable "gcp_project" {
  default = "Your GCP Project ID"
}

variable "project" {
  default = "Your Project Name"
}

variable "env" {
  default = "dev"
}

variable "region" {
  default = "asia-northeast1"
}

variable "zone" {
  default = "asia-northeast1a"
}

locals {
  prefix = "${var.env}-${var.project}"
}

```

# VPCとサブネットを作成
サブネットを2つ作成してみました。
なんと、VPCにはCIDRブロックを指定するパラメータはありません。
また、以下では指定していませんが、`secondary_ip_range` でセカンダリのIPレンジを指定することもできます。公式ドキュメントを読んでも、プライマリ、セカンダリの使い分けがまだピンときていません。。

```terraform:vpc.tf
resource "google_compute_network" "vpc" {
  name                    = "${local.prefix}-vpc"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
  mtu                     = 1460
}

resource "google_compute_subnetwork" "public" {
  name          = "${local.prefix}-public-subnet"
  ip_cidr_range = "10.0.11.0/24"
  network       = google_compute_network.vpc.id
}

resource "google_compute_subnetwork" "private" {
  name          = "${local.prefix}-private-subnet"
  ip_cidr_range = "10.0.21.0/24"
  network       = google_compute_network.vpc.id
}
```

コンソール画面を確認するとこんな感じで作成されていました。
public、privateと名付けていますが、AWSみたくルートテーブルで用途を変えれるのかなと勝手に想像しています。次はファイアウォールとルートテーブルあたりを確認してみたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402286/f43f3a3d-cfdd-b53d-85ee-424a8b34de23.png)


# 参考リンク
- [Getting Started with the Google Provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/getting_started)
- [VPC ネットワークの使用 ](https://cloud.google.com/vpc/docs/using-vpc?hl=ja)
[VBA]VBAの制御ステートメントは一行にまとめられる。

VBAにおける制御ステートメントというと、If 〜 Then 〜 Else ステートメント、Select Case ステートメントがある。書き方としては次のとおり。

```vb:ifthenelse.vba
'If 〜 Then 〜 Else ステートメント
Sub IfThenElse()
    Dim digits As Long : digits = 3
    Dim msg As String
    If digits = 1 Then
       msg = "一桁です。"
    Else
       msg = "二桁以上です。"
    End if
End Sub
```

```vb:selectcase.vba
'Select Case ステートメント
Sub SelectCase()
    Dim rank As String: rank = "優"
    Dim msg As String

    Select Case rank
        Case "優"
            msg = "すごいですね！"
        Case "良"
            msg = "頑張りましたね"
        Case "可"
            msg = "ギリギリでしたね"
    End Select
End Sub
```

これはこれで読みやすいができれば簡単なものは一行にまとめてしまいたい。RubyとかではなんでもワンライナーにすることができるがVBAではそういうニーズには答えるようなものはないと思いこんでいた。

ところが、そういうワンライナー化のニーズに答える関数がVBAの標準ライブラリに存在した。それが、```Interaction```モジュールの```IIf(Expression, TruePart, FalsePart)```と```Switch(expr-1, value-1, [, expr-2, value-2, ・・・])```という関数である。

ざっと書くと、上の制御ステートメントで記述したプログラムは次のような形に置き換えることができる。

```vb:IIf.vba
Sub IIfFunction()
    Dim digits As Long : digits = 3
    Dim msg As String
    msg = Interaction.IIf(digits = 1, "一桁です。", "二桁以上です。")
End Sub
```

```vb:Switch.vba
Sub SwitchFunction()
    Dim rank As String: rank = "優"
    Dim msg As String
    msg = Interaction.Switch(rank = "優", "すごいですね！", rank = "良", "頑張りましたね", rank = "可", "ギリギリでしたね")
End Sub
```

非常に記述がスッキリした形にすることができる。短い条件分岐であれば使用する価値はある。問題は、これは条件分岐のステートメントではなく関数であるので、引数に関数を入れた場合、全ての引数の関数を評価してしまうという弱点がある。

例を出して説明しよう。

```vb:sample.vba
Function Hello()
    MsgBox "Say Hello"
    Hello = "Hello"
End Function

Function World()
    MsgBox "Say World"
    World = "World"
End Function

Sub SideEffect()
    Dim msg As String
    msg = Interaction.IIf(True, Hello(), World())
End Sub
```

Say Helloという文字をメッセージボックスに表示させたあと"Hello"という文字列を返す関数```Hello```と同じくSay Worldという文字をメッセージボックスに表示させた後に"World"という文字列を返す関数```World```を事前に定義しておく。

IIfで条件分岐させるステートメントとしては、

```Interaction.IIf(True, Hello(), World())```

という常にTrueパートの部分のみを返す条件分岐となっている。期待される動作としては、これを実行すれば、メッセージボックスに"Say Hello"と出たあとに"Hello"という文字が返り、msg変数にその"Hello"という文字列が格納される、というものである。ところが、これは実際の動作とは異なる。実際に実行してみると、TrueパートのHello関数が評価されるところまでは正しいが、FalseパートのWorld関数も評価されて"Say Hello"とメッセージボックスに表示された後、"Say World"というメッセージボックスが条件がTrueであるかFalseであるかに関わらず表示されてしまうのである。

つまり、引数に入れた関数が内容として副作用を伴うものであると、条件がTrueかFalseであるかに関わらず副作用が評価されてしまうのである。なお、普通のIf 〜 Then 〜 Elseステートメントであればこういうことにならない。

以上を踏まえて、機械的にIf 〜 Then 〜 Elseステートメント、Select Casedステートメントを一行関数ステートメントに置き換えるのはおすすめできないが、使い方によっては、今までのVBAプログラムが結構スッキリと簡略化できるでしょう。
M1 Macのターミナルに現在の環境［Arm or Rosetta］を常に表示する（powerlevel10k）


はじめまして。
M1 Macを導入して環境構築している際に、ターミナルが現在どの環境で動いているか認識しないまま色々入れた結果、1日かけた作業をやり直す羽目になったので、常に現在の環境が表示されるようにしました。

（わざわざ記事にするほどのことではないかもしれませんが、プログラミング初心者の私は、調べる時間含めてこの作業に2時間かかったので、メモとして残しておきます。）

![スクリーンショット 2021-11-09 23.02.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2267699/9efdd27f-75b6-0ffc-00d5-130eb56fc1be.png)
![スクリーンショット 2021-11-09 23.05.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2267699/bf103b85-86fa-4e16-7273-a210ed2aef19.png)

#環境
・macOS Monterey 12.0.1
・iTerm2
・prezto + powerlevel10k

#設定
ホームディレクトリにある”.p10k.zsh”に以下のコードを追記します。

```shell:.p10k.zsh
function prompt_arch_type() {
  arch_type=`uname -m`
  p10k segment -i '' -t "${arch_type}"
}

typeset -g POWERLEVEL9K_ARCH_TYPE_FOREGROUND=232
typeset -g POWERLEVEL9K_ARCH_TYPE_BACKGROUND=1
```

上のfunctionが'uname -m'の結果を取得するコードです。
下2行は表示する際の色設定なので、末尾の数字を変えてお好みの色にしてください。



その後、”.p10k.zsh”の最初の方にあるPOWERLEVEL9K_LEFT_PROMPT_ELEMENTSに"arch_type"を追記します。
(下記サンプルのarch_type前後にあるコマンドは、設定によって異なります。)

```shell:.p10k.zsh
  typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
    # =========================[ Line #1 ]=========================
    os_icon                 
    arch_type  # 今回追加した行
    dir                     
    vcs                     
    # =========================[ Line #2 ]=========================
    newline                
    prompt_char            
  )
```

あとはファイルを保存して、ターミナルを再起動してください。



#参考にしたサイト

https://github.com/romkatv/powerlevel10k#extensible

#あとがき
Twitterで上記のことやりたい〜って呟いたら、作者の方からリプライをいただきました。
めっちゃいい人なのでみんなpowerlevel10k使おう！

https://twitter.com/romkatv/status/1457783974638411783?s=21
課題を修正するステップ

* 課題を自覚すること
* 課題を修正する気があること
* 課題を修正する必要性を認識すること
* 課題を修正する手段を検討すること
* 課題を修正する手段を実施すること
* 手段によって課題が解決されたことを確認すること
エビデンス作成支援？Excelアドイン

筆者がいてるような~~貧乏な~~エコノミーなプロジェクトでは、テストのエビデンスを作成する際に
・PrintScreenキーで画面をキャプチャ
・ペイントでトリムやマーキング
・Excelベースの資料に貼り付け
とやっているんですが、加工した画像をExcelに貼り付けようとするとまずA1セルに貼りついてしまうため、いちいち貼りなおさねばなりません:pensive:

そのあとも、倍率調整したり枠線に色付けて・・・と細かい作業が続くので、この辺の一連の作業をワンクリックでできるようExcelのアドインマクロ化してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/991c1f7d-f0d8-bc96-7a7d-84a05401efea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/30d0f18a-c879-5b15-7191-1bbb6ffc232f.png)


***
1. Excelでアドイン形式のファイルを作成し、VBAに次のコードを記載します。
※Excel2013で半年ほど、2021で１ヶ月ほど使って問題は起こってませんが、不具合など気づかれた方はお知らせください:bow_tone1:

```VB
Option Explicit
Public VPb_前回倍率 As Integer    ' 前回入力値を覚える
Sub ShapeResize()

    On Error GoTo ErrTrap

    Dim vPr_縮小サイズ As Variant, vPr_倍率 As Single
    If IsNull(vPb_前回倍率) Or _
       vPb_前回倍率 = 0 Then
        vPb_前回倍率 = 70
    End If
    vPr_縮小サイズ = InputBox("縮小倍率（パーセント）は？", "倍率指定", vPb_前回倍率)
    If Trim(vPr_縮小サイズ) = "" Or _
       Not IsNumeric(vPr_縮小サイズ) Then
        Exit Sub
    Else
        vPb_前回倍率 = vPr_縮小サイズ
        vPr_倍率 = Clng(vPr_縮小サイズ) / 100
    End If

    Application.ScreenUpdating = False
    ' ***** クリップボード内容をペースト⇒カット⇒位置指定して再ペースト *****
    Dim vPr_カレント位置 As String
    vPr_カレント位置 = Activecell.Address        ' 貼り付け指定したセル位置を記憶
    ActiveSheet.Paste
    Selection.Cut
    Range(vPr_カレント位置).Select
    ActiveSheet.Paste

    ' 以下、お好みで調整ください
    With Selection.ShapeRange
        .ScaleHeight vPr_倍率, msoFalse, msoScaleFromTopLeft    ' 画像のリサイズ
        .ZOrder msoSendToBack                                   ' 画像の配置：最背面
        With .Line                                              ' 外枠を黒の細線で
            .Visible = msoTrue
            .ForeColor.RGB = RGB(0, 0, 0)
            .Transparency = 0
            .Weight = 0.5
        End With
    End With

ErrTrap:
    Application.ScreenUpdating = True
    Exit Sub

End Sub
```

2. 作成したアドインファイルを既定のフォルダ（一般にはC:\users\（ユーザー名）\AppData\Roaming\Microsoft\AddIns）配下に保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/984b2e0b-b74a-c613-9af4-e4f29acdbc9a.png)

3. Excelのオプション設定画面から「アドイン」－「管理：Excelアドイン」を選択して「設定」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/54da64ab-9a49-2441-0b04-98c5a231e343.png)
　追加可能なアドインの一覧に、先ほど作成した処理（この場合Myconfig）が表示されるので、チェックを入れて「OK」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/994c8267-c283-ec94-ab0f-2c815b105c72.png)

4. 同じくExcelのオプション設定画面の「リボンのユーザー設定」で、「マクロ」を選ぶと先ほど記述したマクロ（この場合"ShapeResize"）が一覧に表示されます。
　これをリボンに追加すると、ボタンのワンクリックで指示した位置に、指定した倍率でetc.の画像を貼り付けることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/fe959d47-2c36-5d27-42f2-bb4c55f93e4f.png)
C# PictureBoxのメモリをdisposeする


C# .NET Frameworkを利用してスライドショーなど複数の画像を切り替えながら継続的に表示する場合、適切にDisposeしてあげないとメモリリークを起こしてしまいます。過去にこの件を調べたところDisposeを書く場所を間違えたことがあったのでここに書き残します。今回は手っ取り早く多くの画像の切り替えを行うためOnPaintに入れて画像を切り替えていきます。
pathlstには画像のpathが入っていてcurrentの数値を変えることで画像を切り替えます。

###なにもDisposeしない場合
```CS:Form1.cs
protected override void OnPaint(PaintEventArgs e)
        {
            if (current >= pathlst.Count())
            {
                current = 0;
            }           

            Image img =  Image.FromFile(pathlst[current]);
            pictureBox1.Image = img;            
            pictureBox1.Update();

            current++;
            Invalidate();
        }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64828/a28699ba-28ab-a6d5-140b-f7fab5d9ddb7.png)
9秒4GB使いメモリ不足を起こしました。

###Image.FromFileの代わりにFileStreamを使う
```CS:Form1.cs
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current],
                                        System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64828/0e87a739-6f47-f70d-521a-999987ca67f5.png)
たまにGCが呼ばれたりしているのでひどいリークは起こしていないように思えます。

###PictureBoxのImageをDisposeする
```CS:Form1.cs
if (pictureBox1.Image != null)
{
      pictureBox1.Image.Dispose();
}
Image img =  Image.FromFile(pathlst[current]);
pictureBox1.Image = img;
```

PictureBoxに前の画像が入っていた場合その画像をDisposeしてあげればリークを起こしません。はじめは22MB程度で、18秒経過後も30MBあたりに収まっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64828/9419aad4-188d-1072-c932-cd6b3a926b3d.png)


Disposeは後に書いてはダメで

```CS:Form1.cs
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current], System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();
pictureBox1.Image.Dispose();
```

前に書いてもnullかどうか調べてからではないとエラーを起こします。

```CS:Form1.cs
pictureBox1.Image.Dispose();
System.IO.FileStream fs1 = new System.IO.FileStream(pathlst[current], System.IO.FileMode.Open, System.IO.FileAccess.Read);
pictureBox1.Image = System.Drawing.Image.FromStream(fs1);
fs1.Close();
```
PowerShellでディレクトリ比較（Compare-Object）

PowerShellでディレクトリ間の `diff` をしてみたかった。ちなみにPowerShellで `diff` と言えば、 `Compare-Object` の別名です。

# ディレクトリ下のファイル構成比較

一方のディレクトリのみに存在するファイルの有無を確認する。
まず対象フォルダ、比較用の参照フォルダのフルパスをそれぞれ変数に格納しておく。

```powershell
$targetDir = 'C:/new'
$refDir = 'C:/old'
```

対象フォルダ内のファイルリストを相対パスで取得。ファイルの取得に[Get-ChildItem](https://forsenergy.com/ja-jp/windowspowershellhelp/html/4b270d63-c995-45b8-b5b4-3f8887efbfcc.htm)を、相対パスへの変換に[Resolve-Path](https://forsenergy.com/ja-jp/windowspowershellhelp/html/69809773-ce6e-4128-9526-3eaf4b5dc6d5.htm)を使う。カレントディレクトリからの相対パスになるので、対象フォルダに移動してから左記を行う。

```powershell
Set-Location $targetDir
$targetFiles = Get-ChildItem -File -Recurse | Resolve-Path -Relative
```

参照フォルダ内のファイルリストを相対パスで取得。

```powershell
Set-Location $refDir
$refFiles = Get-ChildItem -File -Recurse | Resolve-Path -Relative
```

比較。[Compare-Object](https://forsenergy.com/ja-jp/windowspowershellhelp/html/0159df5c-db69-48c1-90c8-2a89c686a116.htm)を使う。


```powershell
Compare-Object $targetFiles $refFiles
```

# ディレクトリ下の各ファイル内容の比較

両方のディレクトリのファイル内容を比較する。
まず対象フォルダ、比較用の参照フォルダのフルパスをそれぞれ変数に格納しておく。

```powershell
$targetDir = 'C:/new'
$refDir = 'C:/old'
```

対象フォルダ内のファイルリストを相対パスで取得。

```powershell
Set-Location $targetDir
$targetFiles = Get-ChildItem -File -Recurse | Resolve-Path -Relative
```

相対パスを参照対象フォルダ下のファイル群の絶対パスに変換する。結果は対象ファイルと対応が付くように、ハッシュ `$refFiles` に格納しておく。

```powershell
Push-Location $refDir
$refFiles = @{}
$targetFiles | %{ $refFiles[$_] = Resolve-Path $_ }
Pop-Location
```

比較。 `$targetDir` で実行する必要があるが、すでに `Pop-Location` により戻ってきているはず。

```
$targetFiles | %{ Write-Host $_; Compare-Object @(Get-Content $_) @(Get-Content $refFiles[$_]) | ft }
```

# 終わりに

ファイル構成に差分があると「ディレクトリ下の各ファイル内容の比較」の「相対パスを参照対象フォルダ下のファイル群の絶対パスに変換する」ところでエラーになるかもしれない。いまは困らないので、保留というか将来に積み残しておく。
ハードコピーされた pdf ファイルを HyperEstraier を使って検索する


# はじめに
[HyperEstraier](https://dbmx.net/hyperestraier/index.ja.html) は全文検索エンジンです．私は，手元にかき集めた論文なんかを検索するのに利用しています．近年はあまりアップデートされていませんし，各 Linux Distribution のレポジトリにも見つからない場合もありますが，長らく愛用しています．

HyperEstraier は，普通のテキストファイルの検索だけではなく，いくつかのフィルタ機能を用いて MS Word ファイルや PDF ファイルなどを検索対象とすることも可能です．HyperEstraier に予め同梱されているフィルタはシェルスクリプトで書かれており，ちょっといじれば他の形式の文書を検索することができます．

最近のプリンタはスキャン機能を搭載していて，紙に印刷された文書をPDFファイルに変換して取り込めますが，（勤め先のプリンタと同様に）OCR機能が備わっていなければ，いわゆるハードコピーだけが保管されます．論文のPDFファイルではテキスト情報も保管されているため，HyperEstraier で本文検索をすることができますが，このような"写真PDF"ではそのまま検索することができません．
そこで，Tessarect を使って，ハードコピーされたPDFファイルを検索できるようにしました．

# ハードコピーPDFを検索する方法

## 準備するもの

- HyperEstraier (いうまでもない)
- [Tesseract](https://github.com/tesseract-ocr/tesseract)
- [Poppler](https://poppler.freedesktop.org)

## ハードコピーPDF検索用のフィルタ

```shell:estscannedpdftotxt
#! /bin/sh

#================================================================
# extscannedpdftotxt
# Convert Scanned PDF into plain text.
#================================================================


# set variables
PATH="$PATH:/usr/local/bin:$HOME/bin:." ; export PATH
progname="estscannedpdftotxt"


# check arguments
if [ $# -lt 1 ]
then
  printf '%s: usage: %s infile [outfile]\n' "$progname" "$progname" 1>&2
  exit 1
fi
infile="$1"
outfile="$2"
if [ -n "$ESTORIGFILE" ] && [ -f "$ESTORIGFILE" ]
then
  infile="$ESTORIGFILE"
fi


# check the input
if [ "!" -f "$infile" ]
then
  printf '%s: %s: no such file\n' "$progname" "$infile" 1>&2
  exit 1
fi


# initialize the output file
if [ -n "$outfile" ]
then
  rm -f "$outfile"
fi


# function to output
output(){
  if [ -n "$outfile" ]
  then
    cat >> "$outfile"
  else
    cat
  fi
}


# limit the resource
ulimit -v 262144 -t 10 2> "/dev/null"


# output the result
TMPNAME=`mktemp`
PDF_PAGE_LIMIT=10

pdftoppm -l $PDF_PAGE_LIMIT -png $infile $TMPNAME
for fn in $TMPNAME*png
do
tesseract $fn stdout -l jpn | output
rm $fn
done
rm $TMPNAME

# exit normally
exit 0



# END OF FILE
```

"# output the result" までは他のスクリプトと同内容です．pdftoppm により PDF ファイルの各ページを png ファイルに変換します．色々な文書を変換している際に，100ページを超えるファイルを処理しようとして hung up したので，念のため PDF_PAGE_LIMIT でページ数の制限を設けることにしました．

/tmp 以下に出力された各 png ファイルに対し，tesseract を用いてテキストに変換し，output に加えていきます．処理の済んだ png ファイルは順次消します．最後に /tmp 以下に作成されたディレクトリを削除して，PDFファイル1つが処理されたことになります．

estscannedpdftotxt を HyperEstraier の filter ディレクトリに配置したら，res ディレクトリに検索対象のPDFファイルを移動し，以下のスクリプトを実行します．HyperEstraier は仮に /home/user に置いてあるものとしています．

```shell:update.sh
estcmd gather -lf -1 -cm -sd -fx ".pdf" "T@/home/user/hyperestraier/filter/estscannedpdftotxt" casket res
```
起動時ボリュームアタッチできない

現象：
AWS上Windowsのあるボリュームをオフラインにした後にデタッチし、
再起動したら、他のボリュームがオフラインにしてしまった。

原因：
NVMe ドライバーを使用するインスタンスタイプ において、過去に OS 上でディスクをオフラインにした情報がレジストリに残ることが原因で、インスタンスの停止・起動を行う際、アタッチされたディスクがそのレジストリ情報を参照することでディスクがオフラインとなることがございます。
※https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/instance-types.html#ec2-nitro-instances

対策：
. デタッチしたらデバイスマネージャー (devmgmt.msc) を起動
. "表示" -> "非表示デバイスの表示" にチェック
. "Storage controllers" を開く
. アイコンの色が薄くなっている "AWS NVMe Elastic Block Storage Adapter" を右クリックし、"場所" の番号が起動時オフラインであったディスクのものと同じであることを確認し "削除" をクリック
　　※"このデバイスのドライバーソフトウェアを削除する" にはチェックを入れないでください。
. Windows の再起動を実施
MySQL / DATE_FORMAT関数で同一日付をカウント、順位付けする

#まえがき
MySQL-DATE_FORMAT関数の挙動確認です。

#前提条件

[MySQLで簡単にランダムなテストデータを作成する方法](https://qiita.com/tayasu/items/c5ddfc481d6b7cd8866d)
こちらの記事にランダムデータを作成する方法が載っていましたので、同様の手順でテーブルを作成しておきます。

```php:20210801024646_ChangeUsers.php
# id, name, description, price, created_at
1, 商品1, 8a44ac7a37f7bd69a7db99d3fe937b, 8595, 2014-04-18 09:12:02
2, 商品2, 493b3579d0986774aed5dab8dd8ca4, 5489, 2014-02-28 23:28:33
3, 商品3, a022f42410b9bd6ec080c3e5112be3, 6452, 2014-03-28 10:54:58
4, 商品4, 2be6c9822811b7586c46e86417e466, 8356, 2014-04-29 18:44:42
6, 商品6, cf2151b45afa9c148f2260df480617, 3202, 2014-05-25 01:16:46
7, 商品7, 452fcde3e7130a92e51015240d8af2, 1319, 2014-01-16 00:35:53
```
こんな風にあっという間に数十万レコードのダミーデータが作成されます。

#DATE_FORMAT関数

>DATE_FORMAT 関数を使うと引数に指定した日付を表す値を指定のフォーマットで整形した文字列を取得します。また TIME_FORMAT 関数を使うと時刻を表す値を指定のフォーマットで整形した文字列を取得できます。
[DATE_FORMAT関数 / TIME_FORMAT関数 (日付または時刻を指定したフォーマットで整形する)](https://www.dbonline.jp/mysql/function/index49.html)

PHPでいうところのdate関数やstrtotime関数のような事が可能という事ですね。

<h3>・日時情報の変換</h3>
日付 - スラッシュ区切り

```
select created_at as bef,date_format(created_at, '%Y/%m/%d') as aft  from item 
```

```
# bef, aft
'2014-04-18 09:12:02', '2014/04/18'
'2014-02-28 23:28:33', '2014/02/28'
'2014-03-28 10:54:58', '2014/03/28'
'2014-04-29 18:44:42', '2014/04/29'
'2014-05-25 01:16:46', '2014/05/25'
```

<br>

日付 - 英語月名 / 英字曜日 / AM・PM表記

```
select created_at as bef,date_format(created_at, '%Y/%m/%d') as aft  from item 
```

```
# bef, aft
'2014-04-18 09:12:02', 'Apr-18(Friday) AM 09'
'2014-02-28 23:28:33', 'Feb-28(Friday) PM 11'
'2014-03-28 10:54:58', 'Mar-28(Friday) AM 10'
'2014-04-29 18:44:42', 'Apr-29(Tuesday) PM 06'
'2014-05-25 01:16:46', 'May-25(Sunday) AM 01'
```




#こんな事も可能です。

SELECT文でgroup関数と併用する事で指定フォーマットの日付による絞り込みを行う事ができます。

created_atカラムの値を日付までの値でフォーマットし、
日付が等しいレコード数を集計する。

```
select count(*) as C, date_format(created_at, "%Y-%m-%d") as D from item group by D order by  C DESC limit 10;
```

```
# C, D
'8', '2014-04-24'
'8', '2014-01-25'
'7', '2014-05-25'
'7', '2014-01-29'
'7', '2014-02-16'
'7', '2014-05-17'
'6', '2014-03-12'
'6', '2014-06-14'
'6', '2014-03-13'
'6', '2014-05-07'
```



created_atカラムの値を月までの値でフォーマットし、
月内のレコード数を集計、priceカラムの合計値を返す。

```
select CONCAT(CAST(SUM(price) as char(20)),' yen') as P,count(*) as C, date_format(created_at, "%Y-%m") as D from item group by D order by  P DESC;
```

```
# P, C, D
'491773 yen', '94', '2014-06'
'479018 yen', '97', '2014-01'
'453588 yen', '82', '2014-04'
'424187 yen', '79', '2014-03'
'418671 yen', '86', '2014-05'
'368871 yen', '74', '2014-02'
```


#あとがき

調べている時はgroup関数と何が違うのかあまりわかりませんでしたが、
フォーマットできるだけで色々できて非常に便利だな～と思いました。
Laravel バリデーション requiredIfを用いて、requiredをかけたい時とかけたくない時の条件分岐を簡単にする！

# はじめに
登録処理では、バリデーションのrequiredを使いたいけど、更新処理ではrequiredをかけたくない場合があるかと思います。
そんな時に可読性をなるべく落とさずに簡単に条件分岐できる方法を紹介します。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [バリデーションをかけるフォーム](#バリデーションをかけるフォーム)
2. [リクエストファイル](#リクエストファイル)
 
<!-- 各チャプター -->
# バリデーションをかけるフォーム
例によってショボいフォームを書いてみました。(分かりやすさ重視でシンプルに作ってます)
・更新の際は画像のみバリデーションのrequiredをかけたく無いのを想定しています。
・登録処理では画像は必須にしたいので、リクエストメソッドがpostの時のみrequiredをかけたいところです。

```
<form 
  action="{{ route('user.post.update', ['post' => $post]) }}" 
  enctype="multipart/form-data" 
  method="POST">
    @csrf
    @method('PUT')

  <div>
    <p>タイトル</p>
    <input type="text" name="title" 
     value="{{ old('title', optional($post)->title) }}">
  </div>
   
  <div>
    <p>投稿内容</p>
    <textarea type="text" name="content">
      {{old('content', optional($post)->content)}}
    </textarea>
  </div>

  <div>
    <p>画像</p>
    <input type="file" name="image_url">
  </div>
</form>
```

# リクエストファイル
・<font color="blue">__requiredIfの中がtrueならrequiredを適用__</font>となります。
・$request->isMethod('post')
リクエストメソッドがpostであれば、trueを返します。違う場合はfalse。
・$request->isMethod('post')によってpostメソッドの時だけ、'image_url'フィールドがrequiredになります。


```
// 下記2行を追記
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;


                     // Requestクラスを追記
public function rules(Request $request)
{
        return [
            'user_id' => [省略],
            'title' => [省略],
            // Rule::requiredIfメソッドを追記
            'image_url' => [Rule::requiredIf($request->isMethod('post'))],
        ]
}
```
CDP 7.1.7に、CFM(NiFi)をインストール

# Download information:
https://docs.cloudera.com/cfm/2.1.2/download/topics/cfm-download-locations.html

## Parcel Repositories % Network Setting ボタンをクリックし、ParcelのURLを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/ecebb8a1-307b-eabc-5ece-4ce14a1779ed.png)


ダウンロード中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/bcaf0c1b-d05e-cd69-1e79-a51e85b9a2c2.png)


もう少しで完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/3d3cb226-844a-c90c-6754-6f392131aa8a.png)

ダウンロード完了したら、Distributeボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/4137f0c9-e1e4-3508-27ad-744737b608dd.png)


Distribute開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/1c23e3cb-d6af-7138-1521-54c203662a3c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/de947d18-656c-ca9b-bcda-dbf9715a6ba7.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/5609daec-97bc-cfe2-00dd-9439007a3b0e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/296402e6-b50e-cf15-ec6e-7fb7f7f35a9c.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133516/82b22e65-30ee-db41-5807-18efe5619c4a.png)



# Download the CFM Custom Service Descriptor files
https://<userid>:<password>@archive.cloudera.com/p/cfm2/2.1.2.0/redhat7/yum/tars/parcel/NIFI-1.13.2.2.1.2.0-283.jar

```bash
wget https://<userid>:<password>@archive.cloudera.com/p/cfm2/2.1.2.0/redhat7/yum/tars/parcel/NIFI-1.13.2.2.1.2.0-283.jar
sudo mv NIFI-*.jar /opt/cloudera/csd
cd /opt/cloudera/csd
sudo chown cloudera-scm:cloudera-scm ./*
sudo chmod 644 ./*
sudo service cloudera-scm-server restart

```
Seleniumでajax(xhr)のデータをとる

## SeleniumでajaxでリクエストしてるJSONとか取りたい
いろいろ調べるとgithubで公開してくれているページがヒット。
https://gist.github.com/lorey/079c5e178c9c9d3c30ad87df7f70491d#file-selenium_xhr_requests_via_performance_logging-py

ただ今のバージョンだとこれが少し違うくて、

https://stackoverflow.com/questions/27644615/getting-chrome-performance-and-tracing-logs

こちら参照

``` get_log.py
import json
from time import sleep

from selenium import webdriver
from selenium.webdriver import DesiredCapabilities

# make chrome log requests
capabilities = DesiredCapabilities.CHROME
# caps['goog:loggingPrefs']
capabilities["goog:loggingPrefs"] = {"performance": "ALL"}  # newer: goog:loggingPrefs
driver = webdriver.Chrome(
    desired_capabilities=capabilities
)

# fetch a site that does xhr requests
driver.get("https://ja.reactjs.org/docs/faq-ajax.html")
sleep(5)  # wait for the requests to take place

# extract requests from logs
logs_raw = driver.get_log("performance")
logs = [json.loads(lr["message"])["message"] for lr in logs_raw]

def log_filter(log_):
    return (
        # is an actual response
        log_["method"] == "Network.responseReceived"
        # and json
        and "json" in log_["params"]["response"]["mimeType"]
    )

for log in filter(log_filter, logs):
    request_id = log["params"]["requestId"]
    resp_url = log["params"]["response"]["url"]
    print(f"Caught {resp_url}")
    print(driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id}))

```

でちゃんとJsonレスポンスが取れるようになりました。

### 一言
chromedriverの仕様はよく変わる…
capabilityとかドキュメントに載ってないものありそうだし。
TSUBAMEでAiZynthFinder用のConda環境を構築したい

# 本記事の概要
また環境構築ログ．Qiitaのことコードをかけるメモ帳だと思ってるから許して欲しい



# やったこと

## 環境構築
Conda環境に必要なパッケージをぶち込む

```bash
conda create --name aizynthfinder python=3.7
conda activate aizynthfinder
conda install -c rdkit "rdkit=>2019.09.1" -y
conda install -c anaconda "tensorflow>=2.1.0" -y
conda install -c anaconda graphviz -y
python -m pip install https://github.com/MolecularAI/aizynthfinder/archive/v3.0.0.tar.gz
```

まあまあ時間がかかる．

## 実行に必要なファイルのダウンロード
リポジトリのクローンと，実行に使うらしいファイルのダウンロード

```bash
git clone https://github.com/MolecularAI/aizynthfinder.git
cd aizynthfinder
mkdir model
python aizynthfinder/tools/download_public_data.py model
```

## 実行用スクリプト類の作成

試しに逆合成してみる化合物のSMILES

```bash:smiles.txt
C1=C(N=C(C(=O)N1)C(=O)N)F
```

逆合成し，その結果を`output.hdf5`として出力するジョブスクリプト（tsubameに投げるやつ）

```bash:aizynth_test.sh
#!/bin/bash
#$ -cwd
#$ -N Aizynth_test
#$ -l f_node=1
#$ -l h_rt=0:10:0
#$ -V


. /etc/profile.d/modules.sh
module load cuda/11.2.146 cudnn/8.1

source  ~/.bashrc
conda activate aizynthfinder
export PYTHONPATH="/home/0/{学籍番号}/aizynthfinder:$PYTHONPATH"

aizynthcli --config /home/0/{学籍番号}/aizynthfinder/model/config.yml --smiles /home/0/{学籍番号}/aizynthfinder/smiles.txt
```

hdf5ファイルを可視化するコード

```python:gen_image.py
import pandas as pd
from aizynthfinder.reactiontree import ReactionTree

data = pd.read_hdf("output.hdf5", "table")
all_trees = data.trees.values
trees_for_first_target = all_trees[0]

for itree, tree in enumerate(trees_for_first_target):
    imagefile = f"route{itree:03d}.png"
    ReactionTree.from_dict(tree).to_image().save(imagefile)
```

上のコードを走らせるジョブスクリプト．
うまくいくとカレントディレクトリに`route000.png`，`route001.png`，．．．というのがいくつかできる

```bash:view_smiles.sh
#!/bin/bash
#$ -cwd
#$ -N View_smiles
#$ -l q_core=1
#$ -l h_rt=0:10:0
#$ -V


. /etc/profile.d/modules.sh
module load cuda/11.2.146 cudnn/8.1

source  ~/.bashrc
conda activate aizynthfinder
export PYTHONPATH="/home/0/{学籍番号}/aizynthfinder:$PYTHONPATH"

python3 /home/0/18B03528/aizynthfinder/gen_image.py                                  
```

そのほか有用そうな情報
* `aizynthcli`するときのオプションに`--output hogefuga.hdf5`をつけるとファイル名が`hogefuga.hdf5`として保存されるらしい


## 複数のSMILESを一気に走らせたい

準備

```bash:
cd aizynthfinder
mkdir SMILES
mkdir OUTPUTS
```

```python:make_scripts.py
## 目標は，'/home/0/{学籍番号}/aizynthfinder/SMILES'内に複数あるSMILES_(id).txtに対し，output_(id).hdf5を作ってくれるよう>なスクリプトの自動生成

import os

DIR='/home/0/{学籍番号}/aizynthfinder'

with open(DIR+'/auto_script.sh', mode='w') as sh:
    sh.write('#!/bin/bash\n')
    sh.write('#$ -cwd\n')
    sh.write('#$ -N Auto_test\n')
    sh.write('#$ -l f_node=1\n')
    sh.write('#$ -l h_rt=0:10:0\n')
    sh.write('#$ -V\n')
    sh.write('\n')
    sh.write('. /etc/profile.d/modules.sh\n')
    sh.write('module load cuda/11.2.146 cudnn/8.1\n')
    sh.write('\n')
    sh.write('source  ~/.bashrc\n')
    sh.write('conda activate aizynthfinder\n')
    sh.write('export PYTHONPATH="/home/0/{学籍番号}/aizynthfinder:$PYTHONPATH"\n')

    for filename in os.listdir(DIR+'/SMILES'):
        sh.write(f'ayzinthcli --config {DIR}/model/config.yml --output {DIR}/OUTPUTS/{filename}.hdf5 --smiles {DIR}/{filename}\n')
```
Kotlin, Swiftで小数点以下の四捨五入をする方法

# 概要

Kotlin, Swiftで小数点以下の四捨五入をしたいときがあった。
調べればやり方はすぐ出てくるが、自分用の忘備録としてまとめておく。
ちなみにKotlin, Swiftどちらでもコードはほぼ同じ。

# 小数点以下の四捨五入をする方法

## Kotlin

```Kotlin
val number:Float = 1.23456
val num1 = Math.round(number)                     // 小数第1位四捨五入 : 1
val num2 = Math.round(number * 10.0) / 10.0       // 小数第2位四捨五入 : 1.2
val num3 = Math.round(number * 100.0) / 100.0     // 小数第3位四捨五入 : 1.23
val num4 = Math.round(number * 1000.0) / 1000.0   // 小数第4位四捨五入 : 1.235
```

## Swift

```swift
let number:Float = 1.23456
let num1 = round(number)                     // 小数第1位四捨五入 : 1
let num2 = round(number * 10.0) / 10.0       // 小数第2位四捨五入 : 1.2
let num3 = round(number * 100.0) / 100.0     // 小数第3位四捨五入 : 1.23
let num4 = round(number * 1000.0) / 1000.0   // 小数第4位四捨五入 : 1.235
```
パケットトレーサーでネットワーク学習1109

・スタティックルートの設定
(config) # ip route network mask ip-address 
（例）コマンド：Router(config)#ip route 192.168.3.0 255.255.255.0 10.0.0.2


・descriptionコマンド：各インターフェースの説明文
コマンド：Switch#show interfacesで、説明文を確認することができる。
pandas 辞書にバリュー(値)を追加する

#やりたいこと
決まったキーを持つデータをfor文で回して1つのデータにしたい。
APIで毎分データを取得する。それを1つのデータにしたかった。

#方法

```python
df_all = pd.DataFrame([])

def func(year,month,day,hour,minute):
    #引数により、取得するデータを指定
    object_key_name = f'{year}/{month}{day}/{hour}/{minute}.json'
    #アクセスキー入力
    s3 = boto3.resource(
                    's3',
                    region_name='ap-northeast-1',
                    aws_access_key_id = 'xxx',
                    aws_secret_access_key = 'xxx',
                )

    bucket = s3.Bucket(bucket_name)
    obj = bucket.Object(object_key_name)
    response = obj.get()
    body = response['Body'].read()
    #取得したデータを格納
    data = json.loads(body.decode('utf-8'))

    df = pd.DataFrame.from_dict(data,orient='index').T
    global df_all
    df_all  = df_all.append(df)
```
【Unity】GameObjectに自動で連番の名前をつけるエディタ拡張

#概要
Hierarchy View から右クリックでGameObjectに自動で連番の名前をつけるエディタ拡張を作成しました。

AAA
BBB
CCC

みたいなゲームオブジェクトを複数選択で

AAA
AAA (1)
AAA (2)

というUnityの複製（Deplicate）に即した名前に自動で変更してくれます。

配置作業をしていると

AAA
AAA (13)
AAA (2)
AAA (4)
AAA (1)

みたいな感じで名前がバラついてきてイライラすることありますよね。
あります。

#機能
ばんごうをふってくれる

#使い方
- ScriptableObjectCreator.csをAssets/Editorに入れてください
- Editメニューに`NameConsecutiveNumber`が追加され、これを選択すると勝手に番号を振ります。大体御坂妹みたいな感じです。

```ScriptableObjectCreator.cs
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.Linq;
using System.Collections.Generic;

public class NameConsecutiveNumberEditor : Editor
{
    [MenuItem("Edit/NameConsecutiveNumber", false)]
    static void SetNames()
    {
        Undo.RecordObjects(Selection.objects, "ApplyNameConsecutiveNumber");

        string baseName = string.Empty;
        foreach (var item in Selection.objects.Select((value, index) => new { value, index }))
        {
            if(item.index == 0)
			{
                var fullName = item.value.name;

                baseName = fullName;

                // 末尾の(n)を削除.
                Regex regex = new Regex(@"\(.+?\)");
                var matches = regex.Matches(fullName);
                if (matches != null)
                {
                    var matchList = new List<string>();
                    foreach (var match in matches)
                    {
                        matchList.Add(match.ToString());
                    }

                    if (matchList.Any())
                    {
                        var lastMatch = matchList.Last();
                        int lastIndex = fullName.LastIndexOf(lastMatch);
                        baseName = fullName.Remove(lastIndex);
                    }
                }

                // 末尾の空白を削除.
                for (int i = baseName.Length - 1; i >= 0; i--)
                {
                    var c = baseName[i];
                    if (!char.IsWhiteSpace(c))
                    {
                        if (i != baseName.Length - 1)
                        {
                            baseName = baseName.Remove(i + 1);
                        }
                        break;
                    }
                }

                item.value.name = baseName;
            }
			else
			{
                // 名前を形成.
                item.value.name = string.Format("{0} ({1})", baseName, item.index);
            }
		}
    }
}

```
#補足
あんまりないと思いますが

AAA (13) (たなか)  (5)
AAA (2) (6)
AAA (4)     (2)
AAA (1)

みたいな状態で使うと

AAA (13) (たなか)
AAA (13) (たなか) (1)
AAA (13) (たなか) (2)
AAA (13) (たなか) (3)

という感じで整理してくれるように作りました（説明雑）
要はいっちばん後ろの(n)だけを変更します。

ご拝読、ありがとうございました。
【Vue.js】キー修飾子

#はじめに
こんにちは！
今回は【Vue.js】キー修飾子についてアウトプットしていきます！

#キー修飾子とは
キーイベントをフックに、特定のキーボードのキーを指定することができそれが押された時のみ、記述したイベントハンドラを呼び起こすことができる。

#書き方・解説
今回は`escキー`が押されたらテキスト内の文字が空になるプログラムを記述していきます。

```HTML:HTML
  <input type="text" v-on:keyup.27="clear" v-model="message">
　　　　　　　　　　　                      　　<!--⏫escのキー番号は27番なのでこのような感じで記述している-->
```
```Vue.js
   data: {
     message: ''
   },
   methods: {
     clear: function() {
       this.message = ''
     }
   }
```
dataに空のmessageを用意し、clearメソッドでmessageの中身を空にする処理を記述する。
＜テンプレート側＞
テキストボックスを用意し、input　タグの中に`v-on:keyup.27="clear"`と記述する。処理内容は**キー番号27番（esc）が押されたらclearメソッドの処理が実行される**というものである。それをmessageと双方向バインで双方向バインで紐付けているというふうになる。

![スクリーンショット 2021-10-26 6.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/663391dc-414d-113e-9ace-3142ae2d8f3d.png)

![スクリーンショット 2021-10-26 6.30.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/a58cc44b-517a-edce-8a59-c3af92203ae8.png)

また、キー番号ではわかりにくいので`esc`とキー名を記述してもOKです。

```HTML:HTML
  <input type="text" v-on:keyup.esc="clear" v-model="message">
```

また、複数のキーを選択することも可能です。

```HTML:HTML
  <input type="text" v-on:keyup.esc.space.up="clear" v-model="message">
```

これで`esc`,`space`,`↑`キーも押されると処理が実行されるようになりました。
※書き方は、`.〇〇`という風にかく。


#まとめ
・`v-on:keyup.〇〇="メソッド名"`という形で記述する。
・〇〇のところはキー番号でもキー名称どちらでも可。
・`.〇〇.△△.□□`という風に複数の指定も可。

#最後に
今回はキー修飾子についてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！