OmniAICreator/Qiita-1.07M huggingface dataset:
Digital Multi Meter (KEYSIGHT 3458A) を GPIB(コムテック製GPIB通信マイクロコンバータ-USB2．0対応) を用いて PC側から制御する

---
**はじめに**
KEYSIGHT 3458A を CONTEC社製 GPIBケーブルを用いて WindowsPC から 最小限の制御が出来たので
メモ書きを兼ねて記述をする

--
**1.API-PAC(Win32)のインストール**
以下のページより ドライバライブラリ API-GPIB(WDM) for USB GPIB通信ドライバ 開発環境(フルセット) Ver. 4.xx をダウンロードする
[https://www.contec.com/jp/download/donwload-list/?itemid=311d6ea4-124f-400c-a55d-daa01a477c90](https://www.contec.com/jp/download/donwload-list/?itemid=311d6ea4-124f-400c-a55d-daa01a477c90)

Zip File を解凍後に "LYAS06GPIB_4xxF\APIPAC\GPIBWDM\Disk1" より Setup.exe を実行することで以下の様な構成でファイルが置かれる。
GPIBのツールとして ConRec.exe / Master.exe / Slave.exe があり、それぞれのソースコードが存在する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/dffdc31f-776d-abdb-d8e1-a4593aa205ef.png)

**2.ソースコードの修正**
KEYSIGHT 3458A と コンテック製 GPIBケーブル[GPIB通信マイクロコンバータ(USB2．0対応)] を接続しても　ConRec.exe / Master.exe / Slave.exe は、
正常動作しない。 原因は、ConRec.exe などのツールは、IEEE 488.2標準 に準拠しているのに対して 3458A は、独自コマンドなのが原因であった。

そこで、ソースコードを修正することにした。私がトライしたのは、ConRec.exe のソースコードで

C:\Program Files (x86)\CONTEC\API-PAC(W32)\GPIBWDM\Sample\Vc2013\ConRec

に置かれた Microsoft Visual C++ (MFC) を用いた。
開発環境は、Microsoft Visual Studio 2022 (64 ビット) であり 提供されているソースコードを開くと 2022用に更新され問題無くコンパイルされ
作成された ConRec.exe も動作した。

ソースコードの具体的な変更箇所は、以下の通り
368行目～404行目にかけて
※共通コマンド *IDN? を独自コマンド ID? に変更するだけ！！

~~~C
//機器情報問い合わせ（送信）
//wsprintf(szSendBuf, _T("*IDN?"));	//送信データ

/* KEYSIGHT 3458Aは、IEEE488.2規格でなく 独自*/
wsprintf(szSendBuf, _T("ID?"));	//送信データ
endif
~~~

~~~c
//受信データがIEEE488.2規格か確認
/* (strstr(RecBuf, ",") > 0) {
   //アドレス情報を結合
   wsprintf(EqpInforBuf, _T("Address:%d %S"), AddrArray[ArrayCount], RecBuf);
   }
   else {
   //受信データがIEEE488.2規格でない場合、アドレス情報のみ
   wsprintf(EqpInforBuf, _T("Address:%d"), AddrArray[ArrayCount]);
   }*/
/* KEYSIGHT 3458Aは、IEEE488.2規格でなく 独自*/
wsprintf(EqpInforBuf, _T("Address:%d %S"), AddrArray[ArrayCount], RecBuf);
~~~

以上の結果、下記の制御画面で
①初期化 -> ②相手機器検索 (HP3458Aと表示)
③TEMP? とデータを 3458Aに送信する
④上記に対する応答 (現在の温度 25.7℃) が受信できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/85eeadd5-0e1d-c2ae-d760-636fbf6fcecd.png)

尚、SRQ(Service Request)イベント受信データについては その使い方が不明で タイマーを利用して現在の測定出力値を取得出来る様に改造した。

---

☆2021年12月21日(火) 午前12時00分 初版(Ver1.00) 作成

---
[py2rb] deque

# はじめに
移植やってます
# deque (Python)
```python
cleavage_sites = deque([0], maxlen=ml)
```
デックは分かるのですが、`maxlen`は曲者
> 長さが制限された deque がいっぱいになると、新しい要素を追加するときに追加した要素数分だけ追加したのと反対側から要素が捨てられます

https://docs.python.org/ja/3.7/library/collections.html#collections.deque
# どうする？ (Ruby)
```ruby
class Deque
  attr_accessor :que
  def initialize(*args)
    @que = args[0]
    @maxlen = args[1]
  end

  def push(args)
    @que.push args
    while @maxlen.nil?.! && @que.size > @maxlen
      @que.shift
    end
  end

  def unshift(args)
    @que.unshift args
    while @maxlen.nil?.! && @que.size > @maxlen
      @que.pop
    end
  end
end

deque = Deque.new([1, 2], 3)
deque.push 3
deque.push 4
deque.push 5
p deque.que
deque.unshift 6
deque.unshift 7
deque.unshift 8
p deque.que
deque.que.clear
p deque.que

# [3, 4, 5]
# [8, 7, 6]
# []
```
このような感じでクラスを作成する。
# メモ
+ Python の deque を学習した
+ 道のりは遠そう
【Typescript】型を強制的に変換するダブルアサーション

typescriptには「ダブルアサーション」というものがあります。
できるだけ使うことを避けた方が良いですが、テクニックとして知っておくのが良いかと思います

## アサーションとは

アサーション自体が型を強制的に変換する機能です。
以下の例を見てください。

```typescript
type User = {
    id: string;
    name: string;
    isAdmin?: boolean;
}

type AdminUser = User & {
    isAdmin: true;
}

function userToAdminUser(user: User): AdminUser {
  user.isAdmin = true;
  // Type 'User' is not assignable to type 'AdminUser'.
  return user;
}

```

`userToAdminUser`は`user`を`AdminUser`にして返します。

しかし、`return user;`でエラーが出ています。
`User`型から`AdminUser`型に変換することはできないからです。

このエラーを解決するのが、アサーションです。

```typescript
  return user as AdminUser;
```

`as AdminUser`を追加することによって userを`AdminUser`型に変換することができます。


## ダブルアサーションとは

上のようなパターンはエラーを消すことができました。
しかし、以下の例はどうでしょうか。

```typescript
type User = {
    id: string;
    name: string;
    isAdmin?: boolean;
}

type AdminUser = {
    id: string;
    adminName: string;
    isAdmin: true;
}

function numberToString(hoge: User): AdminUser {
  hoge.isAdmin = true
  // Conversion of type 'User' to type 'AdminUser' may be a mistake because neither type sufficiently overlaps with the other.
  return hoge as AdminUser;
}
```
アサーションしているはずなのに、エラーが出ました。
上の例と違うところは`AdminUser`型が`User`型のサブタイプではないということです。

実はtypescriptのアサーションは何でもかんでも型変換できるわけではなく、型変換したい型がサブタイプもしくはスーパータイプである必要があります。

サブタイプでない型へ変換するにはどうすれば良いでしょうか？
ここで、ダブルアサーションの出番です。

```typescript
return hoge as unknown as AdminUser;
```
これでエラーが出なくなりました。
ダブルアサーションは一度unknown型にアサーションしてから、本来型変換したい型に変換します。
全ての型はunknown型のサブタイプなので、どんな型に変換してもエラーが出ません。
any型でも大丈夫です。
2回アサーションをしているため、ダブルアサーションという呼び方になってます。

## なぜ、ダブルアサーションは避けるべきなのか
ダブルアサーションを避けた方が良い理由を一言で述べると、型安全が守られないことです。
例に挙げたコードでも`hoge`はAdminUser型なのに`adminName`を持っていません。

```typescript
function numberToString(hoge: User): AdminUser {
  hoge.isAdmin = true
  // adminNameを設定していないのにエラーが出ていない
  return hoge as unknown as AdminUser;
}
```
Webフォントのちらつきを改善したい

# はじめに
自分のアプリのフォントに、[Google Fonts](https://fonts.google.com/)さんのWebフォントを使用させてもらいました。
しかしWebフォントがダウンロードされて表示されるまでに、フォールバックのフォントが表示されることによるちらつき(FOUT)がはっきり確認できるレベルになっておりましたので、改善したいと思います。

# 今回使用予定のWebフォント
1. Noto Sans JP
1. kameron

# 実行環境
1. React
1. TailwindCSS

# Noto Sans JPのFOUTを改善
まずは日本語フォントであるNoto Sans JPのFOUTを改善していくことにします。

今回は[North Detail](https://www.northdetail.co.jp/blog/1324/)さんのブログを参考に行っていきます。
1. Noto Sans JPをダウンロード
2. ファイルフォーマットの変更
3. サブセット化
4. TailwindCSSからファイルを読み込む

### Noto Sans JPのダウンロード
Noto Sans JPのページにアクセスし、ダウンロードをする。
ダウンロードすると拡張子がotfファイルのフォントファイルをGETできました。

### ファイルフォーマットの変更
> 2021年5月現在、Web Open Font Format 2.0（woff2）がWebフォント用の最小かつ最も効率的なファイルフォーマットです。

[coliss](https://coliss.com/articles/build-websites/operation/work/optimizing-the-display-of-web-fonts.html)さんより引用

どうやら拡張子はwoff2がよさそうです。
ただしIE11には対応してないので注意です。

下記サイトからotf→woff2に変換しました
[OTF to WOFF2 Converter](https://cloudconvert.com/otf-to-woff2)

### サブセット化
サブセット化というのは不必要な文字はフォントファイルから削除するというもので、ファイルサイズが小さくなるので行っていきます。

[サブセットフォントメーカー](https://opentype.jp/subsetfontmk.htm)

上記のアプリを使用して必要な文字を追加していきます。
必要な文字は[JIS第一水準、JIS第二水準](https://qiita.com/gonshi_com/items/b54736d2e0e0f4586f6e)を参考に追加していきました。

ここまでの作業でダウンロードしてきた際にはファイルサイズが4000kb以上あったサイズが650kbまで小さくなりました。

### TailwindCSSから読み込む
```css:app.css
@font-face {
    font-family: "Noto Sans JP";
    src: local("Noto Sans JP")
        url("../src/components/utils/fonts/NotoSansJP-Thin.woff2");
}
```

以上でNoto Sans JPのFOUTを改善することが出来ました。

# kameronのFOUTを改善
続いてkameronフォントのFOUTを改善します。
こちらの問題に関してはWebフォントではなくWebセーフフォントを使用することにしました。
> Webセーフなフォントとは？
異体字も含めるとインターネット上には650,000種類以上のフォントが存在します。その中でも、大半のWebブラウザとOSが対応しているフォントはWebセーフとみなされています。フォントファイルがOSに含まれているため、サイト訪問者はサーバーからフォントをダウンロードする必要がありません。

[KINSTA](https://kinsta.com/jp/blog/web-safe-fonts/)さんのブログより引用

上記を参考にしてkameronに近いGeorgiaを使用しました。


# おわりに
以上でアプリのFOUTが認識できなくなりました。
ちなみにLighthouseのPerformance値が20近く上昇していて、
パフォーマンスが良くなり、ちらつきも改善したのでめでたしめでたし。
何か誤っていることやより良い改善策があれば是非コメントしていただけるとありがたいです。


# 参考
https://coliss.com/articles/build-websites/operation/work/optimizing-the-display-of-web-fonts.html
https://www.northdetail.co.jp/blog/1324/
https://kinsta.com/jp/blog/web-safe-fonts/
Laravel8でSELECT LAST_INSERT_ID()をやる方法



##insertではなくinsertGetIdメソッド？を使えばいい。

##今まで


```

$LastId = DB::table('table_name2')->insert(
    --処理処理--
);
```

##これから
```

$LastId = DB::table('table_name2')->insertGetId(
    --処理処理--
);
```

$LastIdに最後に挿入したAIの値が入る。
オートインクリメントの値しか取れないらしい？です。

普通のsqlで最後にINSERTされたIDを取得する場合は

```
	
SELECT LAST_INSERT_ID();
```

を使う様です。
でわ。
FirestoreのCollectionをExport＆Importする

# はじめに

開発環境と本番環境でデータ移行する際に、FirestoreのCollectionを丸ごとExport＆Importしたいと思ってスクリプトを書きました。

# 準備

firestore-export-importを使います。
https://www.npmjs.com/package/firestore-export-import

```
npm install firestore-export-import
OR
yarn add firestore-export-import
```

jqコマンドがなければインストール

```
brews install jq
```

Firebase コンソールでserviceAccountKey.jsonをダウンロードして、任意の場所に保存します。

# Export用スクリプト

```js:exportCollection.js
const jsons = {
  'prd': './serviceAccountKey_prd.json',  // Prd用のKey
  'dev': './serviceAccountKey_dev.json',  // Dev用のKey
};

if (process.argv.length < 4) {
  console.log(`Usage: node exportCollection.js <dev|prd> <target_collection>`)
  return -1;
}
const env = process.argv[2];
const targetCollection = process.argv[3];
if (!jsons[env]) {
  console.log(`Usage: node exportCollection.js <dev|prd> <target_collection>`)
  return -1;
}

const serviceAccount = require(jsons[env]);
const firestoreService = require('firestore-export-import');
firestoreService.initializeApp(serviceAccount);

firestoreService
  .backup(targetCollection)
  .then((data) => console.log(JSON.stringify(data, null, 2)));
```

jsonを整形して出力するためのシェルスクリプト

```sh:ExportCollection.sh
#!/bin/sh

cd `dirname $0`
node exportCollection $1 $2 | jq . --sort-keys
```

```
chmod +x ExportCollection.sh
```

## 使い方

```
$ ./ExportCollection.sh dev collectionName > collectionName.json
```

# Import用スクリプト

```js:importCollection.js
const jsons = {
  'prd': './serviceAccountKey_prd.json',  // Prd用のKey
  'dev': './serviceAccountKey_dev.json',  // Dev用のKey
};

if (process.argv.length < 4) {
  console.log(`Usage: node importCollection.js <dev|prd> <importDataFile>`)
  return -1;
}
const env = process.argv[2];
const importDataFile = process.argv[3];
if (!jsons[env]) {
  console.log(`Usage: node importCollection.js <dev|prd> <importDataFile>`)
  return -1;
}

const serviceAccount = require(jsons[env]);
const firestoreService = require('firestore-export-import');
firestoreService.initializeApp(serviceAccount);

firestoreService.restore(importDataFile, {
  autoParseDates: true, // timestamp → Date変換
});

```

何もしないけど、Export側と使い方を合わせるためのシェルスクリプト

```sh:ImportCollection.sh
#!/bin/sh

cd `dirname $0`
node importCollection $1 $2
```

```
chmod +x ImportCollection.sh
```

## 使い方

```
$ ./ImportCollection.sh prd collectionName.json
```
rbenvで2.0.0-p648のインストール時にビルドに失敗する

## 現象

超久々にRubyを触っているんだが、
配備する環境に合わせて、Rubyの2.0.0-p648を利用しようとしたが、

```shell
$ brew install rbenv
$ rbenv install -L | grep p648
2.0.0-p648
```

ビルドでエラーになる。

```shell
$ rbenv install 2.0.0-p648
Downloading openssl-1.0.2u.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16
Installing openssl-1.0.2u...
Installed openssl-1.0.2u to /Users/mitsuaki1229/.rbenv/versions/2.0.0-p648

Downloading ruby-2.0.0-p648.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p648.tar.bz2
Installing ruby-2.0.0-p648...

WARNING: ruby-2.0.0-p648 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: using readline from homebrew

BUILD FAILED (macOS 11.6 using ruby-build 20211203)

Inspect or clean up the working tree at /var/folders/s3/r4ql7qd12b38x0jbvlnh92n40000gn/T/ruby-build.20211221103119.10821.PPrkEu
Results logged to /var/folders/s3/r4ql7qd12b38x0jbvlnh92n40000gn/T/ruby-build.20211221103119.10821.log

Last 10 log lines:
thread.c:4835:20: note: did you mean 'rb_frame_this_func'?
./include/ruby/intern.h:369:4: note: 'rb_frame_this_func' declared here
ID rb_frame_this_func(void);
   ^
1 warning and 1 error generated.
make: *** [thread.o] Error 1
make: *** Waiting for unfinished jobs....
12 warnings generated.
6 warnings generated.
12 warnings generated.
```

## 原因

Xcode12から、Cのビルド時に宣言無しで関数を利用すると、エラーを吐くようになったらしい。

https://developer.apple.com/documentation/xcode-release-notes/xcode-12-release-notes

> Clang now reports an error when you use a function without an explicit declaration when building C or Objective-C code for macOS (-Werror=implicit-function-declaration flag is on). This additional error detection unifies Clang’s behavior for iOS/tvOS and macOS 64-bit targets for this diagnostic. (49917738)

## 解決

エラーを無視するようにフラグを設定する。

```shell
$ export optflags="-Wno-error=implicit-function-declaration"
```

再ビルド。

```shell
$ rbenv install 2.0.0-p648
Downloading openssl-1.0.2u.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16
Installing openssl-1.0.2u...
Installed openssl-1.0.2u to /Users/mitsuaki1229/.rbenv/versions/2.0.0-p648

Downloading ruby-2.0.0-p648.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p648.tar.bz2
Installing ruby-2.0.0-p648...

WARNING: ruby-2.0.0-p648 is past its end of life and is now unsupported.
It no longer receives bug fixes or critical security updates.

ruby-build: using readline from homebrew
Installed ruby-2.0.0-p648 to /Users/mitsuaki1229/.rbenv/versions/2.0.0-p648
```
開発から信頼を得るためのQAの取り組み

#はじめに
メリークリスマス:xmas-tree::xmas-wreath1::xmas-wreath2:

今回の記事は「開発から信頼を得るためのQAの取り組み」というテーマを書きたいと思います！
（あくまで一例ですのでこういうやり方もあるよ的な感じで読んでいただけたら幸いです）
12/24担当ということで大事な日に自分が記事を書いていいのか若干戸惑っておりますがよろしくお願いいたします！！

その前に軽く自己紹介をさせてください！

私は主にモバイルゲームの品質管理を担当しています。
市場不具合の再発防止のための傾向分析やテスト業務の効率化に日々頭を悩ませながらなんとかやっています！ｗ
QA歴は5年目でとても経験豊富とは言えないですが、ゲームの仕様把握や開発とのコミュニケーションで個人的に大切だと考えていることを纏めていますのでこういったアプローチの仕方もあるよっていうのが少しでも皆さんに伝われば幸いです！

#概要
まず、今回紹介する事例について、自分はリリース時からかかわっていたメンバーではないです。
前任の担当者から引き継ぎという形で現在は自分が担当しています。
一応、この案件の状況については軽く自分の耳にも入っていて、聞く感じでは運用の安定期に入っていた印象でした。

#課題
引継ぎ作業もほとんど終わりこれからやっていくぞ！っていうときに一つ課題がありました。
それは**開発とQA双方が仕様書に書いていないものについて全く考慮できていない点**です。
どういうことかというと、テストするときに仕様書を参照してテストケースを作成しますが、仕様として記載されていない箇所や変更点の影響範囲が考慮されていないことが判明しました。
結果として、仕様書に書かれていることしかテストできず、**開発内部で確認するのと変わらない結果になるのでは？**といった厳しい意見をいただくこともありました。

それに加え、仕様書以外のことをテストしていない状況だとかなり初歩的なミスも起きがちです。
実例でいうと、達成が難しいミッションAと簡単なミッションBがあるとします。
それぞれの達成報酬として、Aは入手しやすいアイテムが、Bは入手困難なアイテムがそれぞれ設定されていたことがありました。
ミッション難易度に対しての報酬設計が間違っていることに気づけなかったというものです。
（テスター側にナレッジがないとそのアイテムの価値がわからない事象が発生します）

こういった少しでも**ナレッジがあれば防げるような不具合**を検知することができず、
それと比例して品質面も低下していったので、開発からの信頼も少しずつ失ってしまいました。


#取り組み
かなり絶望的な状況からスタートしましたが、当然投げ出すわけにもいかないので、改善するために以下の取り組みを行いました。

##①ゲームをプレイ##
ゲーム本来の遊び方や仕様を知らない人が、そのゲームをよくすることはできないと思っているので、まずゲームをプレイすることから始めました。

日頃からプレイすることはもちろん、QAチームでナレッジシートを作成して共有するなど、とにかくゲームに触れる機会を多くしました。
そのゲームがどういうサイクルでイベントを開催しているのか、エンドコンテンツは何かを理解することで仕様把握を早く進めるよう心掛けていました。
ゲームのナレッジが溜まっていくことで、普段のテスト設計やテスト実施にあたり、
各機能の影響範囲を纏めやすく、時には開発側ですら気づかないバグを検知するなど品質面で大きく貢献することができました。
ここで信頼をググっと手繰り寄せることができたのではないかなと思ってます。

余談ですが、私自身、ゲーム内のイベントをかなりやりこみました。
そのイベントではPtを獲得できるのですが、開発チームの中で一番多くptを獲得して
開発の方からは**すごい！！**、**猛者がいる！**などお褒めの言葉もいただけましたし、
ゲームに対しての本気度をアピールできたのと、開発の方との距離感も縮めることもできました。
ここまでやる必要はないですが、やって損することはないので今ではやってよかったと思っています。

##②探索的テストの導入##
開発の信頼が落ちた大きな理由として仕様書以外の不具合を検知できなかったところなので、
仕様書・設計書から読み取ることのできない不具合を検知するため、探索的テストの導入を行いました。
簡易的なテストチャーターを作成することで、経験やスキルが少ないテスターでも進めやすくなるようにしながら、同時に細かすぎても探索範囲が狭くなってしまうのでバランスを意識しながら進めました。
多くはないですが、不具合もいくつか見つけることができたので良かったと思います。

##③開発とのコミュニケーション##
品質改善といってもQAだけで行うには限界があります。
QAで解決が難しいものに関しては、プロダクトにも協力をお願いしながら進めていきました。
仕様書に記載してほしい情報やデバッグツールなど、テストで必要なものに対して、それがなぜ必要なのか、どういうメリットがあるのかを明確にし、互いに利点が生まれるように説明する必要はあるのでその辺は腕の見せ所でもあります。

ただ、プロダクトに協力を仰ぐことは一定の信頼があってこそのものだと思ってます。
知らない人からお願いされてもなぜやらなければならないのかとなるだけなので、
協力を仰ぐ際の順序は気を付けたほうがいいと思います。

#まとめ
取り組みとしては目新しいものはなく、当たり前のように感じるかと思いますが、
その当たり前の作業を地道に続けてきたことで少しずつ信頼を回復させることができました。
信頼を獲得することでQAとしても動きやすくなるので、現状に満足せずこれからも続けていきたいと思います。

以上となります。ありがとうございました。
それでは良い年末を！
別ブックの値参照　.Cells(1, 1) = "='C:\Users\User\Desktop\TEST\[TEST.xlsx]Sheet1'!$A$1"

結構忘れるのでメモ失礼します。

[https://daitaideit.com/vba-workbooks-reference/](https://daitaideit.com/vba-workbooks-reference/)
記載の

```vba
Sub TEST3()
    With ActiveSheet
        '数式を使って、別ブックを参照
        .Cells(1, 1) = "='C:\Users\User\Desktop\TEST\[TEST.xlsx]Sheet1'!$A$1"
        '数式を値に変換
        .Cells(1, 1).Value = .Cells(1, 1).Value
    End With
End Sub
```

結構忘れるのでコチラもメモ失礼します。
アメブロの記事をまとめて引っこ抜く

# つば九郎のブログを

https://ameblo.jp/2896-blog/

- URLからここだけ抽出する

>2896-blog

```bash
getAmeblo.py "2896-blog" 200 #URL/取得記事数
```

## 結果

>おは。 みなさん、しんぶんみた～ むらかみくん～ごいごいす～ですね～ でも、それだけのかつやくですね。 みなさん、きょう、らじおＮＩＫＫＥＩ１１：３５～１２：０５『こづかあなの～ほめたいむ』きいてくださいね！radikoでもきけま 
すので～ぜんこくのみなさん～よろしく～ぱちり。   にん。 うちあわせむしで、ありまきねんのよそうも～。 ↓くりっく～↓小塚アナの褒めタイム！ | ラジオNIKKEIwww.radionikkei.jpらじおにっけいさんの、Twitterも、ちぇけら～！です。  
ではきいてください。  m.c.Ａ・Ｔで～ＢＯＭＢ Ａ ＨＥＡＤBOMB A HEADm.c.A・T · Song · 1994open.spotify.com  みんなえみふる。 ひょうばんよかったら、またよんでね～。おは。 みなさん、しんぶんみた～ むらかみくん～ごいごいす～ 
ですね～ でも、それだけのかつやくですね。 みなさん、きょう、らじおＮＩＫＫＥＩ１１：３５～１２：０５『こづかあなの～ほめたいむ』きいてくださいね！radikoでもきけますので～ぜんこくのみなさん～よろしく～ぱちり。   にん。 う 

## コード

```python:getAmeblo.py

import requests
import re
from bs4 import BeautifulSoup
import sys

# タグの除去
def cleanhtml(raw_html):
    cleanr = re.compile("<.*?>")
    cleantext = re.sub(cleanr, "", raw_html)
    return cleantext

# 記事の取得
def scraping(html):
    html = requests.get(html).content
    soup = BeautifulSoup(html, "lxml")
    text = soup.find("div", {"class", re.compile("skin-entryBody*")})
    return cleanhtml(str(text)).strip()

# メイン処理
def main():
    getTxt = ""
    for i in range(int(sys.argv[2])):
        url = f"https://ameblo.jp/{sys.argv[1]}/page-{i}.html"
        str_list = scraping(html=url).splitlines()
        text = "".join(str_list)
        getTxt += text
    print(getTxt)


if __name__ == "__main__":
    main()

```

## 拡張オプション
- あなただけのオリジンを作ってクローン作ろう

https://qiita.com/dialoguedaisuki/items/5135032faa1a1119f3de

https://qiita.com/dialoguedaisuki/items/a6cb28d0105e94f38bf9
個人的作業効率化

プロジェクトが多くなってきてどの環境がどのプロジェクトかわからなくなった時は、案件名でリンクを作って、リンク先を環境にしておく

```
ln -s 「シンボリックリンク元のパス」 「シンボリックリンクを作成する場所のパス」
```
[py2rb] import

# はじめに
移植やってます
# import (Python)
```utils.py
def parse(s):
    return s.upper()
```
```main.py
import utils

print(utils.parse('abs'))

# ABS
```
外部ファイルのモジュールを読み込みます。
しかし、この時点でかなりの違和感があります。
# require_relative (Ruby)
```utils.rb
def parse(s)
  s.upcase
end
```
```main.rb
require_relative 'utils'

puts parse('abs')
```
`Ruby`で同様に書いた場合、いきなり関数名のみで呼び出します。
`Python`の場合、ファイル名＋関数名での呼び出しになっています。

名前空間的には、関数名のみでの呼び出しはあまり喜ばしくないので、`Ruby`の場合、例えば次のようになります。

```utils.rb
module Utils
  def self.parse(s)
    s.upcase
  end  
end
```
```main.rb
require_relative 'utils'

puts Utils.parse('abs')
```
どちらが良いなどと言うつもりはないのですが、移植に手間がかかります。
# メモ
+ Python の import を学習した
+ 道のりは遠そう
バッチ処理の結合テストについて

#テスト仕様書を作成する時に下記の項目をチェックしておく。
・0件テストは行ったか。
・エラー時は適切な処理（中断、スキップ等）を行っているか。
・処理件数等、ログは出力されるようになっているか。
・無駄なログは出力されていないか。
・ジョブの処理順序は正しいか。
・パフォーマンスに問題はないか。

#各種APIのドキュメントを元にテストマップ図を作成

バッチ起動～バッチ正常終了まで

その他取得できなかった場合のリトライ処理など
VSCodeのPHP Intelephenseで構文エラーが消えない問題

## 環境

- MacBook Pro（Catalina 10.15.7）
- VSCode（1.63.2）
- PHP（8.0）
- Docker Desktop（4.3.1）

## はじめに

普段はフロントエンドメインの開発を行なってますが、Laravel で API 周りの実装もしないといけなくなったので、使い慣れてる VSCode にいくつか PHP の Extension を入れてみました。
その中で、ハイライト、コード補完、構文チェックなどなど、開発にあたり一通りの機能が揃ってて、評価の良い [PHP Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client&ssr=false#overview) も導入しました。
機能としては申し分なく期待通りだったんですが、なぜか、PHP8.0 から導入されたであろう名前付き引数で、変数名が補完されるにも関わらず構文エラーが発生。

![スクリーンショット 2021-12-21 9.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/a4260573-0a0d-7e2c-6d99-672b912a2828.png)

また、複数の戻り値の型を指定すると同じくエラー。

![スクリーンショット 2021-12-21 9.52.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/4ff38618-d88e-0639-3a8e-d15be11ebef9.png)

当初は、ツールの問題だろうと思い disable/enable してみたり、再インストールしてみたり、いろいろ試行錯誤しましたが解消されず。。。

諦めてしばらく使ってたんですが、どうしても気持ち悪かったので、本腰入れて解決することにしました。
もし同じ問題に悩まされている人の手助けになれば幸いです。

## 結論

前置きが長くなってしまったので、結論から言うと、VSCode にビルトインされている PHP の Extension があって、そいつが悪さ（ではないのだろうけど）をしていたようです。
なので、その機能を無効にし、PHP Intelephense の機能だけを使うことで問題が解消されるはずです。

## 解決手順

1: VSCode の Extensions を開き、検索ボックスに `@builtin php` を入力する

![スクリーンショット 2021-12-21 9.28.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/973090bb-b962-0358-e64b-9e8f6f22c7ba.png)


2: 表示された Extension の `PHP Language Features` の設定アイコンをクリックし、`Disable` を選択して無効にする

![スクリーンショット 2021-12-21 9.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/d069803d-a71b-b01e-db38-e563221ae20a.png)

3: `Reload Required` が表示されるのでクリックして VSCode を再起動する

これで二箇所の構文エラーが無事に消えるようになりました :tada:

| 名前付き引数 | 複数のリターンタイプ宣言 |
| :---: | :---: |
| ![スクリーンショット 2021-12-21 9.29.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/ff54f9c7-384d-dc0f-75e1-234ae970b7dd.png) | ![スクリーンショット 2021-12-21 9.53.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35509/756d2329-fec1-9d1d-803c-2fa13099d0a1.png) |

## 終わりに

やっと気持ち悪さから解放されてガッツリ開発に集中できそうです！
そもそもこの手順は、マーケットプレイスのクイックスタートに書かれているんですが、それをノールックしてしまったのがいけなかったです :sweat_smile:
何か問題が発生した時はあらためて公式のドキュメントを読むべきですね。。。
WordPressの特定の投稿タイプ、特定の固定ページでグーテンベルグ自体を非表示にする

#結論
カスタムフィールドを使っていると特定の投稿タイプ、または特定の固定ページではグーテンベルグ自体がいらないということがあります。
そんなときは以下のコードを`functions.php`に記述することで実現します。

``` functions.php
function disable_block_editor( $use_block_editor, $post_type ) {
  if( get_the_ID() == 20 ) {
    remove_post_type_support( 'page', 'editor' );
    return false;
  }
  return $use_block_editor;
}
add_filter( 'use_block_editor_for_post_type', 'disable_block_editor', 10, 2 );
```

#解説
まずは2行目の`if( get_the_ID() == 20 )`です。
ここでどの投稿タイプ、固定ページなどに対して処理を実行するか指定します。
ここでは投稿IDが20の投稿記事、または固定ページを対象にしています。
使える条件はおよそ以下が使えるので、`||`で区切って複数指定もできます。

```
$post_type === 'post'
$post_type === 'page'
$post_type === 'カスタム投稿タイプ名'
get_the_ID() === '投稿ID'
```

次に3行目の`remove_post_type_support( 'page', 'editor' );`です。
グーテンベルグを無効化しただけではグーテンベルグの前身であるビジュアルエディタが表示されてしまうので、先にこちらを無効化します。

最後はfalseと`$use_block_editor`を返しておしまいです。
mysqlコマンドでcreate databaseしたDBがadminerから見えない

## 環境
- Docker Desktop 4.2.0
- adminer:4.8.1
- mariadb:10.1.16

## 問題
開発用にdockerでmariadbを立てて、adminerで中身を確認していました。
ターミナル上でmysqlで接続しcreate database TEST_DB;を実行しました。
mysql上でshow databases;コマンドを実行するとちゃんとTEST_DBができていることが確認できました。
しかし、adminer上でTEST_DBが見えない！

## 解決方法
Adminer画面上の「リフレッシュボタン」を押せば解決しました。
![スクリーンショット 2021-12-20 10.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222048/21e30731-c50c-48ba-188b-686c28412b22.png)
AWSで共通機能を開発する時に考えたこと

##背景
AWS上に個別のシステムをガシガシ開発していくと、あれ？この機能って先日構築したシステムでも作ったよな？的な事って多々あると思います。だったら、各システムが共通で利用する機能をまとめて、共通機能として提供すれば効率がいいんじゃね。と思い。その際に考えた事をつらつら書いていこうと思います。

##共通機能を開発する際に考えた事（考えないといけない事）
- 提供機能
    - 何の機能をどこの範囲まで共通化するのか？
    - データ保全とか非機能面も十分に検討し機能提供するべきだよね？
    - 暗号化等、利用者により機能要件はまちまちだから、利用して頂けるであろう機能（汎用的な機能）にターゲットをしぼり提供する事になった場合、抜け落ちた機能や、要件に合わない機能は個々の利用者で実装してもらうの？
    - この共通機能の障害で利用者側に影響を及ぼさない設計にしないといけないね。
    - 利用者側のシステムとは疎結合が大原則。
    - 利用者が増えたら共通機能はスケールするの？どの程度のユーザ数を見込むの？
    - 誰に提供するのか？同一企業内のユーザのみなのか？関連企業まで含めるのか？
    - どこから、どういった方式で提供するのか？実現性はあるのか？
    - 提供機能のDRとかどうする？
    - 共通機能を作ったは良いけど、利用してくれるユーザはどの程度いるのか？
    - この共通機能を提供する事により、利用者にどのようなメリットをどの程度提供できるのか？
    - 利用者側のメリットもそうだけど、開発者側（共通機能提供側）のメリットはどの程度あるのか？
- セキュリティ
    - 複数システムから利用される機能だけど、利用者データの混濁とかセキュリティは大丈夫？
    - 利用者の認証、認可は大丈夫？
    - そもそも、共通機能の基盤そのもののセキュリティは大丈夫？
- 運用 
    - 共通機能の面倒は誰が見るの？運用設計もしっかりするべきだよね。作って、利用者に提供して終わりじゃないよね。
    - 共通機能を提供したは良いけど、責任分界点はあやふやになってないよね？
    - 機能を提供する分けだからSLAって定めた？
    - 共通機能で問題が発生した場合、障害対応手順や利用者側へのエスカレーション方法って定まっている？
    - 共通機能で利用しているAWSサービスにアップデートが入った場合等、その検証や影響範囲の確認ってどうやってする？提供機能に影響のない方法でできるの？
    - 個々システムから監査対応のために、ログ提供依頼等あれば対応できる状態？
    - 共有機能を提供した後は、それ以降、この共通機能をあてにして、個々のシステムを開発していく事になるから、利用者側への利用手順や前提、制約などの条件を漏れなく伝えないといけない。
    - 利用者側、共通機能提供側で負担するコストって整理できている？

##まとめ
複数システムに提供する共通機能であるが故に考えないといけない事は多々あります。また、各システムの機能の一部を担うという意味では、障害等が発生すると影響が広範囲に及ぶ事が予想され、慎重に緊張感を持って検討したいものです。
脱初心者を目指すなら知っておきたいasyncとawaitを使った非同期処理

# はじめに
awaitの理解がしっかりできていなかったので非同期処理の復習も込めてアウトプット
※個人ブログから技術的アウトプットはQiitaへ引っ越ししたので、こちらは過去に書いたブログとなります。


# JavaSciptの非同期処理について

- JavaSctiptはシングルスレッド。
- 同時に扱えるタスクは1個だけ。
- プログラムを順番に**前から**1個ずつ処理する（下記のように）

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210225/20210225172404.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210225/20210225172404.png)

しかし、これでは時間のかかる処理が途中にあった場合に困る。

例えば

- データベースへの問い合わせ（FirebaseならFirestoreのドキュメント取得等）
- 重たい画像処理

などは、完了にどれくらい時間がかかるかわからないものもある。

順番に1個づつ処理している途中で、急に処理が止まってしまい、それより後はいつ再開されるかわからない。

**そこで、『非同期』が出てくる。時間のかかる処理は一旦飛ばして（後回し）、**

**すぐ完了できる他の処理から実行していける。それが非同期処理の特徴。**

![https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210225/20210225172431.png](https://cdn-ak.f.st-hatena.com/images/fotolife/h/hiroism0329/20210225/20210225172431.png)

# Promise について

「**時間のかかる処理は一旦飛ばして**」と書いたが、ちゃんとその処理が戻ってきてくれるのか不安です。

そこで登場するのが「**Promise**」。

例えば、「Firestoreのドキュメント取得してるから待っててね」と約束しているのです。

:::note warn
「まじごめん、処理重いけど、終わるまで待ってほしい、すまんな」
:::


という**「約束」というより「お願い」**と考えた方が個人的にわかりやい！

# Promiseが処理されるタイミング

非同期処理を使うときは**実行されるタイミング**かが大事。

```js
function hoge (){
  console.log('①おはよう')

  Promise.resolve('②こんにちは')
    .then(result => console.log(result));

  console.log('③こんばんは');
 }

function fuge () {
  console.log('④深夜')
}

hoge();
fuge();

>  "①おはよう"
>  "③こんばんは"
>  "④深夜"
>  "②こんにちは"
```

Promiseがあるのは2番目なのに、処理は最後なる。

一体Promiseのログが一番最後になるのか？

ここは別途記載するが、**コールスタック**、**キュー**、**イベントループ**という3つの概念が影響しているため。

# async / await について

**「書いた順番通りに実行してほしい！」**

これを叶えるのがasync / await。

以下のようにasync と awaitを書き足すだけで、順番通り出力される。

```jsx
async function hoge (){
  console.log('①おはよう')
  await Promise.resolve('②こんにちは').then(result => console.log(result));
  console.log('③こんばんは');
}

async function hoge () {
  await console.log('④深夜')
}

hoge();
fuge();

>  "①おはよう"
>  "④深夜"
>  "②こんにちは"
>  "③こんばんは"
```

# awaitはasync関数を一時停止する

- **awaitは、その時点でプログラムの実行を一旦止める**
- Promiseが解決されたら次に進むようにするキーワードの役割
- つまり、Promiseが解決されるのを待っていてくれる
- awaitの後に記述された処理は、Promiseが解決されるまで実行されない

したがって、上から順に処理を実行することができる。

# 実務で間違ったポイント

```jsx
async function hoge : Promise<boolean> {  
  const test = await ~~
}

async function main(): Promise<Ok> {
  hoge().then(result => {
    if ( !result ) {
      throw new functions.https.HttpsError('internal', 'Error Message',);
 }

(*中略*)

await function fuga ().then(()=>{
  return ~~~~
});
```

業務では、上記のような感じで書いてて

```jsx
hoge().then(
 result => {~~
```

の中のエラー処理が上手く動かないな〜と悩んだ。

結果的には、

```js
await hoge().then(
 result => { ~~
```

をつけて中の処理が走るようになった。

普通だったらVscodeで「asyncあるのにawaitないで？」と

忠告がでますが、上記の（*中略*) 以下でawaitが使われていたので出なかった。。

これからは、**Promiseでラップされてる関数を呼び出すときは、エラーが出てる関係なく、しっかりawaitで待ってあげるなど意識をしてあげることが大事**と学んだ**。**

# まとめ

- Promiseは、**時間のかかる処理は一旦飛ばす**
- Promiseは「まじごめん、処理重いけど、終わるまで待ってほしい、すまんな」という「約束」というより「お願い」
- **処理を飛ばさずに、**書いた順番通りに実行してほしいのが**async / await**
- awaitは、その時点でプログラムの実行を一旦止め、Promiseが解決されたら次に進むようにするキーワードの役割
- Promiseでラップされてる関数を呼び出すときは、エラーが出てる関係なく、awaitで待ってあげるなどの意識をしてあげることが大事
JavaScript（Nuxt.js）のeventオブジェクトとは

## 概要
JavaScript(Nuxt.js)におけるeventオブジェクトについて学習したので備忘録として記載します。

## eventオブジェクトとは
eventオブジェクトとは、ユーザーによってイベント（クリックイベントなど）が発生した際に
そのイベントの情報が格納されたものです。
プロパティを呼び出すことや、メソッドを使用することができます。

#### プロバティ例
`Event.target`: イベントが発生した要素
`Event.type`  : イベントの名前
...etc

#### メソッド例
`Event.preventDefault()`: イベントのデフォルトの挙動をキャンセル
...etc

### 使用例
使用方法は関数に第一引数を取るだけです。
引数名は何でもいいのですが、慣例的に`e`や`event`とすることが多いです。

index.vue

```vue
<template>
  <v-btn
    @click='type'　　 <!-- clickされた際にtype関数を呼び出す -->
  />
</template>

<script>
export default {
  methods: {
    type(event) { // 第一引数にeventを設定
      console.log(event.type)  // コンソールにイベント名のclickが表示される
    }
  }
}
</script>
```

その他のプロパティやメソッドは下記参考文献を参照ください。

## 参考文献
[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/API/Event)
【VB.NET、C#】エントリーポイントの作成方法

VB.NET、C#におけるエントリーポイントの作成方法です。
#エントリーポイントとは？
エントリーポイントとは、そのプログラムにおいて一番最初に実行される場所のことです。
オブジェクト指向言語でポピュラーなJavaで言うとMainメソッドのことです。
それのVB.NETおよびC#バージョンを紹介します。
#VB.NETのエントリーポイント
VB.NETにおけるエントリーポイントは、何も考えずにVisual Studioでコーディングするとフォームクラスに作成されてしまいます。
そのため、少し準備してあげる必要があります。
手順としては、

1. エントリーポイント用のモジュールを作成する
2. Mainメソッドを記述する
3. MyProjectでMainメソッドをエントリーポイントに指定する

となります。
##1.エントリーポイント用のモジュールを作成する
まずは、Mainメソッドを記述するエントリーポイント用のモジュールを作成します。
Visual Studioでプロジェクトを開き、ソリューションエクスプローラーからモジュールを追加します。
![20211221_001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/a1eb1513-7ad2-68ce-513f-24aa2da6b4aa.jpeg)
![20211221_002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/c1da1c98-5c7d-64a3-cdd5-68b37282fe49.jpeg)
![20211221_003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/fcd5c1ec-26e9-b6b2-77d0-1410a5ede041.jpeg)

これでエントリーポイント用のモジュール作成はOKです。

##2.Mainメソッドを記述する
次に、エントリーポイント用のモジュールにMainメソッドを記述します。

```vb
Module StartMod
    Sub Main()
        MessageBox.Show("Mainメソッドテスト")
    End Sub
End Module
```

これだけです。
動作確認用にメッセージボックスを作成しておきました。

ここにどの様なコードを書くのかというと、例えばMutexクラスを用いた二重起動チェックの処理です。
また、アプリケーションの各種初期処理をMainメソッド直下、もしくはMainメソッドから呼び出したり、コマンドライン引数をMaimメソッドで受け取ったり等、記述するコードは色々とあります。

##3.MyProjectでMainメソッドをエントリーポイントに指定する
最後に、MyProjectの設定を変更します。
MyProjectを開き、アプリケーションから次を設定します。
1. 「アプリケーションフレームワークを有効にする」のチェックを外す
2. 「スタートアップオブジェクト」のプルダウンから「Sub Main」を選択

下の画像を参考に設定して下さい。
![20211221_004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/2e9fa76e-1321-ef96-ab7f-ddbc49071539.jpeg)

これで実行すると、メッセージボックスの「Mainメソッドテスト」が表示されます。
![20211221_005.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2162017/ed937663-0760-8af1-e314-7a8902a5c2b3.jpeg)


#C#のエントリーポイント
C#におけるエントリーポイントは、Visual Studioのプロジェクト作成の際に自動で作成されます。
そのため、「エントリーポイントを作成する」というよりも、「どこにMainメソッドが作られるか」を知っていた方が良いです。
例えば、フォームアプリケーションを作成してみてください。すると、Program.csというファイルも勝手に作成されます。
このProgram.csの中を覗いてみると、Mainメソッドが作成されています。

```cs
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form_CS_Substring());
}
```
なので、とりあえずProgram.csファイルを開いてみて下さい。そこにMainメソッドがあるはずです。

#補足
何故、C#では自動で作成されるのに、VB.NETで準備の手順を踏む必要があるかと言うと、VB.NETではアプリケーションを動かす制約が緩いため、フォームでもエントリーポイントとして認識されるからです。
Javaの場合、アプリケーションを動かす場合、「public static void main(String[] args)」と記述する必要があるという制約がありますが、VB.NETにはJavaやC#の様な制約はありません。
#参考
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/program-structure/main-procedure

https://dobon.net/vb/dotnet/programing/makeentrypoint.html
Wordpressの管理画面で簡単に条件分岐


Wordpressの管理画面で簡単に条件分岐をする方法をまとめます。
使用したプラグインは「Advanced Custom Fields」

<h2>Advanced Custom Fields</h2>
https://ja.wordpress.org/plugins/advanced-custom-fields/


<h2>Advanced Custom Fieldsの設定</h2>
条件判定を「はい」にして、表示する条件を設定します。![資料1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322744/cfadb8b4-9350-4c5a-c5a6-aad12eb048cd.jpeg)

<h2>管理画面、投稿ページの見た目</h2>
ラジオボタンの選択内容によって、入力欄が変動するようになります。
2パターンを選んだ場合は入力欄が増えます。

<h3>1パターン</h3>
![資料2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322744/f5a81ff2-a557-a10c-80b3-cc8d9fad8b0e.jpeg)

<h3>2パターン</h3>
![資料3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322744/be592737-14aa-2313-10dc-f47d352d9330.jpeg)


<h2>テーマ側の出力例</h2>
```
<?php if(get_post_meta($post->ID, '時間1', true)): ?>
<?php
 $check = get_field_object('曜日1');
 $checkmeta = get_post_meta($post->ID,'曜日1');
 $checkmeta = $checkmeta[0];
 if($check) {
 foreach($checkmeta as $v) {
 echo '<span>' . $check['choices'][$v] .'</span>';
 }
 }
 ?>
<p><?php echo post_custom('時間1');?></p>
<?php endif;?>

<?php if(get_post_meta($post->ID, '時間2', true)): ?>
<?php
 $check = get_field_object('曜日2');
 $checkmeta = get_post_meta($post->ID,'曜日2');
 $checkmeta = $checkmeta[0];
 if($check) {
 foreach($checkmeta as $v) {
 echo '<span>' . $check['choices'][$v] .'</span>';
 }
 }
 ?>
<p><?php echo post_custom('時間2');?></p>
<?php endif;?>
```
lazygit入門

## tigではできないこと

git操作する際 [tig](https://github.com/jonas/tig) を使っていますが、[tig](https://github.com/jonas/tig) ではできないことがいくつかあります。

例えば

- git branch
- git pull
- git push

実はデフォルトではできないが、~/.tigrc に設定を書くとできるようになるみたいです。
[Tig で Git を自由自在に操作するための .tigrc 設定例](https://qiita.com/sfus/items/063797a1dd8fdc7d032f#fetch--pull--push)

pullやpushをするために設定を書くのは面倒なので、lazygitに入門しました。


## lazygitの概要

lazygitとはGoで作られたCLIのgitツールです。

https://github.com/jesseduffield/lazygit


## install

いろいろな環境に対応していますがMacだと、`brew install lazygit` で一発でした。

https://github.com/jesseduffield/lazygit#installation


install後 `alias lg="lazygit"` とエイリアスを貼るのが推奨されています。

https://github.com/jesseduffield/lazygit#usage


## 基本操作

`lg` か `lazygit` でこのような画面になります。

![スクリーンショット 2021-12-21 9.17.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/7c7a0ca1-196b-db40-da4b-d272fed74044.png)


### branch作成

`l` や `h` でタブを移動できるので、Local Branchesまで移動して `n` とするとブランチ名を入力するスペースが出てきます。

ブランチ名入力後エンターで作成できます。

![foo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/2b96ce41-e931-412a-7c8e-cad34edac168.gif)

### checkout

Local Branchesタブで移動したいbranchで `space` とすると `git checkout` できます。

![checkout.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/efa85c4b-9216-dc94-97d2-170915b6bd6f.gif)


### addとcommit

Filesタブに移動して `a` でファイルを全部 `git add -A` して、 `C` で `git commit` できます。


![addcommit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/fd2197af-4924-96b6-3d99-b6296f62be4b.gif)

spaceでファイルを個別に `git add` できます。

![stage_space_a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/06478c03-7dc8-1d2d-82ff-65d707775eb0.gif)


### push

`P` でpushできます。

![push.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2414266/378307fb-0bb4-ce45-b18d-5f00355c30cc.gif)

力尽きたのでここいらで終わりにします。

lazygit作者によるtutorial動画もあるみたいです。よかったらどうぞ。
https://www.youtube.com/watch?v=CPLdltN7wgE
Reactとsymbol-sdkでアカウント作成、残高確認、送金できるサンプルアプリを作ってみた


## はじめに
この記事は「[nem Advent Calendar 2021](https://qiita.com/advent-calendar/2021/nem)」の12/21の記事として書かれています。

今回は少し前に[React](https://ja.reactjs.org/)と[symbol-sdk](https://docs.symbolplatform.com/ja/sdk.html)を用いてアカウントの作成、残高確認、送金ができるサンプルアプリを作りましたのでアプリの利用方法を紹介したいと思います。

本記事の読者としてはsymbol-sdkを用いてアプリを作ってみたい初心者向けになります。
symbol-sdkの基本機能の一部の動作の確認ができます。
動作を確認しつつコードも合わせて読み解くことで、実際にアプリを作る際の参考になるかと思います。

自身で実装したGitHubリポジトリは[こちら](https://github.com/Matsushin/symbol-sdk-wallet-react-sample)になります。

## symbol-sdkとは
仮想通貨Symbolの機能をシステムに組み込むために、用意されたライブラリになります。
現在は開発言語としてはJavascript&Typescript、Javaで提供されています。


## 参考にしたコードについて
元々はsymbol-sdkを用いた実装方法についてコードの解説を本記事にてしても良かったのですが、以下の参考リポジトリと解説記事を実装時に大いに参考にさせて頂いたので、そちらを見てもらう方と早いですしとても分かりやすいです。
記事：[Symbol を使って爆速で仮想通貨決済を導入しよう](https://blog.opensphere.co.jp/posts/dapps004)
GitHubリポジトリ：[symbol-sample](https://github.com/OPENSPHERE-Inc/symbol-sample)


## サンプルアプリのの利用方法
完成したサンプルアプリへのアクセスは[こちら](https://matsushin.github.io/symbol-sdk-wallet-react-sample)になります。
**サンプルアプリではSymbolのテストネットを利用するため、実際の金銭のやりとりが発生することは一切ありません。**あくまでテストです。

### アカウント作成
まずはアカウントの作成をします。
![matsushin_github_io_の内容_と_Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/36e560c9-d478-381e-f3e4-233caa3aa638.jpeg)

作成が完了すると画面にアドレスと秘密鍵が表示されるのでコピーして手元で保管をします。
**アドレス**は残高確認の際に、**秘密鍵**は送金の際に利用します。
![Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/adfa5a58-b920-37f2-5c3c-4ebe0e5c39ae.jpeg)


### 残高確認
次に作成したアカウントの残高を確認します。
![Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/265f53dd-ff7f-7a0a-30cd-a12a0c99ed7c.jpeg)


アカウントを作成した際に10XYM付与されるようにしていますのでXYM残高の表示が10になっていればOKです。
アカウント作成時のXYMの付与には少し時間がかかるので、表示が10になっていない場合は数分待ってみてください。
![Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/1290c37e-3186-8d61-7d30-23a798ec3bbe.jpeg)


### 送金
次に送金をしてみましょう。
「宛先」「金額」「秘密鍵」を入力して送金を実行します。「メッセージ」は未入力でかまいません。
宛先はアカウントを別で作成するか下記のテストアドレスをご利用ください。

テストアドレス↓↓
TBINMFJ2UJNBG3ZTV2GEVLW4JTMXJUBT2JMH4NY

![Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/47d6a62c-f8bd-c16a-d0e5-10dd4e9285fd.jpeg)

送金後に画面に「送金完了しました」の表示が出てこればOKです。
最後に送金されたことを確認してみましょう。
宛先に指定したアドレスを利用して残高を確認して送金した分増えていれば完了です。
着金にも少し時間がかかりますので、残高が反映していない場合は数分お待ちください。
また送金元の残高は送金時に指定した金額以上に残高が減っているかと思いますが、送金時に手数料がかかっているためになります。

![Symbol_Sample_App.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41362/b9d8e6c1-8b0d-797e-db79-cbc6eb17627c.jpeg)

## テストネットでのXYMの入手について
もし作成したアカウントにXYMを付与したい場合は以下のURLで自由に行えます。
[https://testnet.symbol.tools/](https://testnet.symbol.tools/)

## おわりに
今回Reactとsymbol-sdkを連携させて実装をしたのですが、比較的簡単にサンプルアプリを実装することができました。
是非開発者の方は時間をかけずにブロックチェーンアプリを作ることができますのでトライしてみると良いかと思いました。

最後にSymbolのテストネットが稼働しているノードは[Opening Line](https://www.opening-line.co.jp/)さんのものをお借りさせて頂きました。ありがとうございました。

## その他の参考リポジトリ
[redux-symbol](https://github.com/kazumasamatsumoto/redux-symbol)
【Watson Assistant 教えてもらった♪】ダイアログの基本

私は社内異動したばかりの新米エンジニアです。テクニカルなスキルはありません。
そこで、まずはチャットボット構築のスキルを身につけるため、Watson Assistantを初めて使ってみています。
どんなチャットボットにするか悩みどころですが、観光ガイドにしました。川崎に観光客を呼び込むための観光地・名所紹介チャットボットを作成します。
紹介したい5項目はこちら。
![全体像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/deefa1a4-b82e-f4a2-db99-71488cc3b99c.png)
それに対して、質問および期待する応答を以下のとおり設定しました。
![質問と回答.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/4835ab6a-6b2f-a2a7-0d93-fe4c938016bb.png)
こちらが自力で何とか作ったインテント、エンティティ、ダイアログの構造です。
![初期作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/942e4120-0a93-be7e-3a56-c52fca4c463a.png)
ダイアログは、ノード「観光地（Tourist spot）」の子ノードとして、全スポット（Full spots）、イベント（Event）、無料（Free entrance）、雨（Rain）、カップル（Couple）を並列配置。
結果がこちら。
![初期結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/4fb249e0-74ec-8561-6a17-5203b3aab877.png)
このダイアログでは、無料で行けるスポットは？、雨でも楽しめるスポットは？、カップルで楽しめるスポットは？と尋ねると、条件付きにもかかわらず全スポットが回答されてしまいました。
このままだと、ゴルフ場に行って予期せぬ料金を払ってお金がなくなったり、海っぺたの公園で雨に打たれて風邪をひいたり、競馬場に行って喧嘩になって別れたりしてしまうかもしれません・・・。

この時点での疑問。前提条件がつくときってどう作るの？
　■ インテントの作りが影響を与えている？
　■ 全スポットと個別条件のスポットを親ノードで分けてみる？

よく分からないので、同じ部門のエキスパートに相談に乗ってもらいましたところ、ささっと分かりやすいアドバイスをいただきました。
![スクリーンショット 2021-12-21 9.22.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/90fe285d-1b83-9eaf-9a2f-b0321f526d1b.png)
アドバイスのとおりに修正したダイアログの構造はこちら。
![修正作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/ee353acc-7d13-c2aa-44c7-c8042891f107.png)
今度はしっかりと回答をもらえました！　これで川崎の観光客増加に貢献間違いなし！？
![修正結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2411813/65ca2f8d-7f7a-bbde-76f9-288ef22c8fb8.png)
これからもWatsonを学んでいくので、Hint & Tipsを投稿します。
ActiveRecordにおける楽観的ロックと悲観的ロックの使い方

# 環境

- Rails 7.0.0
- Ruby 2.7.5
- MySQL 5.7


# 楽観的ロック

`lock_version` というカラムを用意するだけで利用できます。

```
$ rails g model user name:string lock_version:integer
$ bundle e rails b:migrate
$ bundle e rails c
```

```ruby
irb(main):001:0> User.create!(name: 'Taro')
   (0.9ms)  SELECT sqlite_version(*)
  TRANSACTION (0.1ms)  begin transaction
  User Create (0.5ms)  INSERT INTO "users" ("name", "lock_version", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Taro"], ["lock_version", 0], ["created_at", "2021-12-20 23:14:45.459194"], ["updated_at", "2021-12-20 23:14:45.459194"]]
  TRANSACTION (3.7ms)  commit transaction
=> #<User:0x00007fe7449a47b8 id: 1, name: "Taro", lock_version: 0, created_at: Mon, 20 Dec 2021 23:14:45.459194000 UTC +00:00, updated_at: Mon, 20 Dec 2021 23:14:45.459194000 UTC +00:00>
```

`lock_version` カラムが自動で更新されています。


# 悲観的ロック

```
$ rails g model user name:string
$ bundle e rails b:migrate
$ bundle e rails c
```

## lock

発行するクエリに `FOR UPDATE` 句をつけてくれます。

```ruby
irb(main):001:0> User.create!(name: 'Taro')
irb(main):002:0> User.lock.find(1)
  User Load (0.9ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 FOR UPDATE
```

引数にデータベース固有のクエリを与えることもできます。

```ruby
irb(main):003:0> User.lock('LOCK IN SHARE MODE').find(1)
  User Load (0.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 LOCK IN SHARE MODE
```

## lock!

`id` カラムで行ロックをかけます。

```ruby
irb(main):004:0> user = User.first
irb(main):005:0> user.lock!
  User Load (0.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 FOR UPDATE
```

## with_lock

トランザクションを開始してロックをかけます。

```ruby
irb(main):006:1* user.with_lock do
irb(main):007:1*   user.name = 'Jiro'
irb(main):008:1*   user.save!
irb(main):009:0> end
  TRANSACTION (0.6ms)  BEGIN
  User Load (0.7ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 FOR UPDATE
  User Update (0.9ms)  UPDATE `users` SET `users`.`name` = 'Jiro', `users`.`updated_at` = '2021-12-21 00:30:04.024824' WHERE `users`.`id` = 1
  TRANSACTION (1.5ms)  COMMIT
```

## 参考

https://api.rubyonrails.org/v6.1/classes/ActiveRecord/Locking.html
FlutterでiOSのネイティブ部分のテストを追加したら error: Multiple commands produce '/パス/GoogleUtilities.framework':

FlutterアプリでiOSネイティブ部分の実装が複雑になってきたので、単体テストを追加してテスト用のTargetを追加したところ、以下のエラーが出力されipaの生成ができなくなってしまいました。

```
    Multiple targets match implicit dependency for linker flags '-framework GoogleUtilities'. Consider adding an explicit dependency on the intended target to resolve this ambiguity. (in target 'Runner' from project 'Runner')
    Multiple targets match implicit dependency for linker flags '-framework GoogleUtilities'. Consider adding an explicit dependency on the intended target to resolve this ambiguity. (in target 'Runner' from project 'Runner')

❌  error: Multiple commands produce '/パス/GoogleUtilities.framework':
```

# 原因
テストではFlutterは不要かと思い、Podfileは以下の状態になっていました。

```
target 'Runner' do
  platform :ios, '13.0'
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

  pod 'RealmSwift'
  pod 'GoogleMaps', '5.1.0'
  # 他必要なライブラリ郡
end

target 'myTests' do
  platform :ios, '13.0'
  use_frameworks!
  use_modular_headers!

  pod 'RealmSwift'
  pod 'GoogleMaps', '5.1.0'
  # 他必要なライブラリ郡
end
```

しかし以下の行も必要だったようで、この行を追加したら無事にArchiveできるようになりました。

```
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
```

根本的な理由は調べきれていません。
Sequel Aceでsshや多段接続を使ったDB接続ができないときに確認するべきこと

Sequel Proと同じ設定だけではSequel Aceからデータベースにアクセスできなかったので、アクセスできるようにする対処法をまとめたものです。

```
既知のホストエラー、選択された既知のホストファイルは書き込み可能ではありません。
```
というエラーメッセージが表示された場合の対処法となります。

![スクリーンショット_2021-12-21_9_20_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251765/9e671714-b4c0-cb05-2ad4-aa9f9a10af70.png)


## この記事で説明すること

- 多段接続ができる環境においてSequel Ace経由でDBに接続できない場合に、接続できるようにする方法

## この記事で説明しないこと

- ssh認証の設定方法
- 多段接続の設定方法

## Sequel Aceとは？

MacOSで使えるデータベースクライアントです。
Sequel Proというクライアントはご存じの方も多いかと思いますが、そのMySQL8.0対応版です。

[GitHub](https://github.com/Sequel-Ace/Sequel-Ace)
[App Store](https://apps.apple.com/us/app/sequel-ace/id1518036000?ls=1)

非常にサクサク動きますし、業務でやりたいことはほとどカバーできているので、MacでDB GUIクライアントの決定版と言っても過言ではないと思います。

## 結論

以下の2点を対応すれば接続できるようになりました。

1. ネットワークタブのSSH Config, Known Hostsに明示的にファイルパスを指定する

![Preferences_と_Sequel_Ace_on_the_App Store.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251765/04f0c040-dfcb-8a89-6878-2cb608dc48fa.png)

(※`~/.ssh/config` に多段接続設定がされていることが前提）

2. ファイルタブの Accessible Files に`~./ssh`フォルダを設定

 ![Cursor_と_Preferences_と_Sequel_Ace_on_the_App Store.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251765/2025c676-be15-0361-95f3-a576d24cfcbf.png)

## 公式ドキュメント

[A Quick Introduction To App Sandbox](https://sequel-ace.com/ref/bookmarks.html#a-quick-introduction-to-app-sandbox)
大手企業にエンジニア採用で勝つ方法　-多くの企業が苦戦する理由3選と解決策-


#多くの企業がITエンジニアの採用に苦戦する理由3選と解決策


「優秀なエンジニアの方を採用したい！」と日ごろから考えている人事や採用担当者も多いのではないでしょうか？
本記事では、エンジニア採用の際のちょっとしたコツをご紹介します👀✨


####理由① ITエンジニアの採用が上手くいかないのは、貴社の問題ではありません

そもそも優秀なエンジニアほど、転職市場には現れません。

* 2019年のITエンジニアを含む技術系(IT/通信)人材の転職求人倍率は7.96倍にまで上昇
* 転職サイトを利用するITエンジニアには多くの企業からアプローチがかかる引く手多数の状態
* そして、実は優秀なITエンジニアほど、転職サイトを使うことなく次の転職先を決めている



####理由② 優秀なITエンジニアほど、転職サイト・求人を利用する必要がありません
![理由②_ITエンジニアの転職活動の活用手段.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902516/038a1990-9aa8-8ad6-1da2-28e240509fff.png)
ITエンジニアは他業種に比べて、知人経由で転職活動を行う方が多い傾向にあります。

####理由③ なぜ、せっかくITエンジニアの採用候補者を集めても面接をクリアできるエンジニアが少ないのか？
![理由③_ITエンジニアの転職サイト・エージェント活用状況.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902516/cc862dec-f728-9f90-f8e0-ae0aadc5b28c.png)

* 優秀なITエンジニアの6割は転職サイトに登録していない
* また、転職サイトを利用した場合でも、十社もの企業からスカウトメールが届くため、1件1件のメールを確認する余裕がない状況になりやすい
* 優秀なITエンジニアに自社を認知してもらう段階から困難になるが、採用基準を下げることも難しい


上記の状況を踏まえると、転職サイトを利用して候補者を集めても、良い人材を獲得できる可能性は低いと言えます。

<br>

####〇優秀なITエンジニアは、週2~3日程度の案件に複数参画している
独立を視野に入れたITエンジニアは、自宅での受託開発の案件を請け負ったり、エージェントを活用して週2～3日の案件を探す傾向があります。
また、優秀なエンジニアほど週5日常駐勤務できるだけのリソースが残っている可能性が低く、企業側は優秀なエンジニアを集めるために、レックス制やリモートワーク等のエンジニアが働きやすい制度の導入が増えてきています。
 
これらの要因もあり結果、週5日常駐勤務の条件で優秀なITエンジニアを集めることが難しい

#解決策
**〇実は穴場のフリーランスエンジニア！**
優秀なITエンジニアには先ほども記載していたように、「週2～3日で働きたい」,「リモートワークで複数案件をこなしたい」といったニーズがあります。
<br>

![総務省_2020~2021までのリモートワーク導入率の推移.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902516/2a6cd2d5-2b4a-62d9-ea27-dda6d0532822.png)
出典：(総務省 | 令和3年版 情報通信白書 | テレワークの実施状況『https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r03/html/nd123410.html』)

上図を見ていただくと日本のリモートワークの導入率は一時的に普及したものの現在では38.4%と低く、フリーランスにとっての環境づくりをいち早く進めることで、優秀なITエンジニアの採用できる可能性が高いことが見受けられます。

コロナの影響によってテレワークが推進されつつありますが、データの管理や紙媒体での業務のやり取りなど様々な観点から導入できていない企業も多くあると思います。
そのため、フリーランスにとって魅力的な環境づくりを進めることで、他社よりも優秀なITエンジニアを採用できる可能性が高まります。



**〇副業を禁止にしている割合は大手企業が多数を占める**
![2019年企業規模別副業許可状況.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902516/a160eab0-214a-251f-94a3-4912dbdd084b.png)


将来的に転職する可能性が高い優秀なエンジニアを副業社員として仕事をお願いし、リレーションを高めることで貴社に転職する可能性が高くなる。

企業側も正社員で応募してくる人材にこだわらなければ、応募が来なかった副業人材を活用しつつ、将来的に正社員に打診することも可能です。

#最後に、、、
本記事のまとめは
**優秀な正社員エンジニアの獲得は競争が激しいため
業務委託（副業含む）のエンジニアを正社員にする方法を検討してみるのも1つの選択肢になり得る**です。
事実、アーリーステージのベンチャー企業ではハイクラス層のエンジニアを副業社員として囲い、その中から正社員として入社する流れができつつあります。
既存の開発環境の中で、週2日程度の稼働でお願いするタスクの切り出しが難しい等の問題はございますが、採用の可能性として検討いただければ幸いです。


エンジニア採用担当の皆様のお役に立てれば幸いです。
私自身、エンジニア採用担当としてまだまだ駆け出しでございます。皆様とともに日々インプットとアウトプットを繰り返しております。お気軽にTwitterのDM宛にご連絡くださいませ。エンジニアついて語り合えれば嬉しいです。

Twitterはこちら⇒:https://twitter.com/selva_okada
BlackをPython 3.10で使う

# tl;dr

* コマンドライン `black 〜 --target-version py310`
* pyproject.toml

```pyproject.toml
[tool.black]
target-version = ['py310']
```

# はじめに：Blackはデフォルトだとmatch文のparseに失敗する

Python 3.10になりmatch文が追加されました。
Blackも21.11b1から対応しましたが、デフォルトだとmatch文のparseに失敗するようになっているため、match文を含むソースコードファイルのフォーマットに失敗します。

# 解決：実行時オプション `target-version` をつける

target-versionをつけましょう。

```bash
black 〜 --target-version py310
```

Poetryを使っていてpyproject.tomlに設定値を書いている場合は


```pyproject.toml
[tool.black]
target-version = ['py310']
```

としましょう。

# おわりに

以上です。
わかりそうでわかりにくいCitrix Virtual Apps and Desktopsのライセンスモデル

Citrix Virtual Apps and Desktops(通称CVAD)には、異なる2つのライセンスモデルがあります。
一つはユーザー／デバイスライセンス(UD)で、もう一つは同時接続ライセンス(CCU)です。
価格も異なっており、CCUとUDの間には2倍ほどの差があります。
CCUは、その名の通り同時に利用できるライセンス形態で100人が同時で利用したい場合には、
CCUライセンスが100必要になります。
一方、よく意味の分からないのがUDライセンスです。
「ユーザー？デバイス？…。なんのこと？？？」
どのような仕組みでライセンスが計算されるのかを見ていきましょう。

まず、登場人物から(明治安田生命　名前ランキング2021より)。
利用者：ハルト、ミナト、リク、ソラ、ソウタ
端末：PC01、PC02、PC03

①ハルトがPC01より接続
→　ハルトにユーザーライセンスが発行されるので1ユーザーライセンスを消費。

②ミナトがPC02より接続
→　ミナトにユーザーライセンスが発行されるので1ユーザーライセンスを消費

③リクがPC01より接続
→　PC01を利用したハルトに1ユーザーライセンス、PC02を利用したミナトに1ユーザーライセンス。
　　PC01から接続したリクに1ユーザーライセンスが発行されると思った方は大間違い。
　　ハルトとリクは同じPC01から接続しているのでPC01に対して1デバイスライセンスが発行されます。

④ソラがPC01より接続
→　ソラが利用したPC01にはデバイスライセンスが発行されているのでライセンスは新たに消費されません。
　　この時点でユーザー１、デバイス１の計2ライセンスが消費されます。

⑤ソウタがPC02より接続
→　今までの流れから考えると、PC02から2人のユーザーが接続しているので新たにユーザーライセンスを割り当てるよりも
　　PC02にデバイスライセンスを割り当てた方がライセンスの消費が少なくなります。
　　結果、PC02へデバイスライセンスが発行されます。

この時点でどのライセンスがそれぞれいくつ発行されているでしょうか・・・・・・・・・・・。
正解は、デバイスライセンスが2個消費されています。

UDライセンスは、ユーザーとデバイスのいずれかでライセンス消費の少ない方でライセンスを発行します。
10台の端末を100人で利用する場合、UDライセンスは10必要になる計算です。1つの端末を複数人で利用する場合や、
1ユーザーが複数の端末からアクセスするシーンが多い場合には、UDラインセンスでOKです。
100人のユーザーがそれぞれ自身の端末から利用する場合には、100UDライセンスが必要になるのですが、同時利用が
10人だと10CCUライセンスでOKです。

ここで疑問が。結局どっちがお得なの？

1UDライセンスを1000円。1CCUライセンスを2000円として考えてみます。
あかさたな運送は、100名の従業員がおり、それぞれの社員にPCが配布されています。CVADで公開されている事務処理用アプリケーションを
最大で同時60ユーザーが利用するライセンスを必要としています。

ケーズ１：UDライセンスを選択した場合
→　従業員個々に1台以上の端末が与えられているので1,000円 × 100 = 100,000

ケース2：CCUライセンスを選択した場合
→　最大で60ユーザーが同時に利用するので 2,000 × 60 = 120,000

この場合、CCUを60購入するよりもUDを100購入したほうが安くなります。単純計算でCCUライセンスがUDの50%以上の場合、
UDライセンスの方が安くなります。

ライセンスを購入する際、利用者数、端末数、同時接続数を元にどちらのライセンスがお得になるかを計算してください。