OmniAICreator/Qiita-1.07M huggingface dataset:
Express＋Typescriptプロジェクトのひな形をささっと作る

普段Angularを書いていて、CLIに任せることが多いので1からTypescriptプロジェクトを作ったメモ。
ExpressのAPIサーバが急遽必要になったので、ささっと作ってみました。

# 環境
* Windows10 + WSL2
* Node v18.14.0

# 手順
#### プロジェクト作る
```
mkdir my-app
cd my-app
npm init
```

#### 必要なものインストール
```
npm install express
npm install -D typescript @types/express rimraf@3.0.2 @types/rimraf@3.0.2 cpx @types/node
npm install -D ts-node nodemon
```
rimrafはちゃんと調べてないですがバージョン指定せずに入れるとbuildでエラー吐いたためバージョンを落としてます。
ts-nodeはトランスパイルせずTypescriptのまま実行したいために。
nodemonはソースコードの変更を検知してホットリロードしたいために入れてます。

#### Typescript化
```
./node_modules/typescript/bin/tsc --init
```

#### tsconfig.jsonの修正
```tsconfig.json
{
  "include": ["src"], // 追加。buildの対象をsrc配下にする
  "exclude": ["dist", "node_modules"], // 追加。distをoutDirに指定するので除外
  ...
  "outDir": "./dist", // コメントアウト外して修正。トランスパイルしたのをdist配下に出力
  ...
}
```

#### ビルド周り修正
```package.json
{
  ...
  "scripts": {
    "start": "nodemon", // 追加。nodemonで起動するようにする
    "build": "rimraf ./dist && tsc && cpx -C ./src/resource/** ./dist/resource" 
    // 追加。build時にdistを消してからbuild
    // src/resource配下に.ts以外のファイルを配置したいため、cpxでbuild時にコピーするようにしておく
  }
  ...
}

```
```nodemon.json
{
  "watch": ["src"], // src配下の変更を検知してホットリロードする
  "ext": "ts",
  "exec": "ts-node ./src/app.ts" // 実行時はトランスパイルせずts-nodeでそのまま.tsを実行
}
```

サンプル実装して稼働確認だけします。
express-generator使ってもよかったですが、ts化するのがめんどかった&ESModuleで実装したかったので手動で
```
mkdir src
mkdir src/resource
touch src/app.ts
touch src/resource/hoge.json
```
```src/app.ts
import express from "express";
import http  from 'http';

export const app = express();
const port = 3000;
app.set('port', port);
const server = http.createServer(app);
server.listen(port);

app.use('/', express.Router().get('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
    res.send("Tomoyan is genius.");
}))
```

#### 稼働確認
```
npm run start

> my-app@1.0.0 start
> nodemon

[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts
[nodemon] starting `ts-node ./src/app.ts`
```
```
curl http://localhost:3000/
Tomoyan is genius.
```

試しにapp.tsを少し変えると、nodemonによってホットリロードされます
```src/app.ts
app.use('/', express.Router().get('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
    // res.send("Tomoyan is genius.");
    res.send("Tomoyan is ikemen.");
}))
```
```
> my-app@1.0.0 start
> nodemon

[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts
[nodemon] starting `ts-node ./src/app.ts`
[nodemon] restarting due to changes... // ここ！
[nodemon] starting `ts-node ./src/app.ts`
```
```
curl http://localhost:3000/
Tomoyan is ikemen.
```
再起動なしで変更反映されたのでOK

#### buildもやってみる
```
npm run build

> my-app@1.0.0 build
> rimraf ./dist && tsc && cpx -C ./src/resource/** ./dist/resource

ls -R dist/
dist/:
app.js  resource

dist/resource:
hoge.json
```
resource配下のjsonもちゃんとdist配下にコピーされてますね。

#### 一応、JSでも動くよね
```
node ./dist/app.js
```
特にエラーなければOKです。
eslintとかも設定しなきゃ。。。
エンジニアインターン14日目

今日はlambdaのfunction urlを使ってDBから条件に当てはまる情報を取得する仕組みを構築した。lambda_handleの関数を構築する際に、sql文のミスが目立ってしまった。サニタイズの仕方も間違っていて、時間をかけてしまった。sql = "select * from list where id = (%)"% id と入力したら直った。しかも先輩エンジニアがエラーの場所のヒントをくれたおかげだった。時間をかけすぎて自分が情けなかった…まだまだ成長できる！がんばろ！
【Python3】S3のファイルをメモリ上でZIP化しSFTPでファイルを転送する。

```
import os
import traceback
from io import BytesIO
import zipfile
import socket

import paramiko
import boto3

AWS_PROFILE = 'XXXXXXXX'

host = 'XXX.XXX.X.X'
port = 22
username = 'XXXXXX'
sshkey_path = 'XXXXX.pem'


def s3_object_to_zip_obj(bucket, key):
    session = boto3.Session(profile_name=AWS_PROFILE)
    s3 = session.resource('s3')
    s3_bucket = s3.Bucket(bucket)
    filecols = s3_bucket.objects.filter(Prefix=key).all()

    archive = BytesIO()

    with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as zip_archive:
        for s3_obj in filecols:
            with zip_archive.open(s3_obj.key, 'w') as zip_f:
                zip_f.write(s3_obj.get()['Body'].read())

    archive.seek(0)
    return archive



if __name__ == '__main__':
    try:
        host_key = paramiko.RSAKey.from_private_key_file(sshkey_path)
        sshcon = paramiko.SSHClient()
        sshcon.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        sshcon.connect(host, port, username, pkey=host_key)
        sftp = sshcon.open_sftp()

        bucket = 'XXXX'
        key = 'XXXX/XXX.txt'
        zip_obj = s3_object_to_zip_obj(bucket, key)

        sftp_to = 'XXXX/XXXX.zip'
        sftp.putfo(zip_obj, sftp_to)
        zip_obj.close()

        sftp.close()
        sshcon.close()
    except:
        print('# error')
        print(traceback.format_exc())
```
wslでledger その6

# 概要
wsl(wsl2じゃない)でledgerやってみた。
勘定科目を整理してみた。

# 勘定科目

|勘定科目|内容|
|:--|:--|
|	Income	|収入、収益、売上
|	Expense	|経費、費用
|	Assets	|資産、銀行口座、株券など
|	Liabilities	|債務、負債、借金
|	Equitiy	|純資産、資産と負債の差額、初期費用

# 家計簿の勘定科目


Income:Baito
Income:Salary:Base
Income:Salary:Overtime
Income:Work:Commute
Expenses:Cash
Expenses:Grocery
Expenses:Fun:Game
Expenses:Travel
Expenses:Commission
Expenses:Tax:Social Security
Expenses:Tax:Wellfare
Expenses:Tax:Social Security
Expenses:Tax:Income
Expenses:Tax:Local
Assets:Banks:Okane
Assets:Banks:Mizuho
Assets:Wire:Mizuho
Assets:Wire:Salary
Liabilities:Wire:Yellow
Liabilities:Card:Yellow
Equity:Opening


以上。
Excelでクリップボードにコピーした情報はImageに変換できる

Excelでクリップボードにコピーした情報は、`Windows PowerShell`の`Get-Clipboard`コマンドレットの`Format`オプションで`Image`を指定すると`Image`として取得できる事をしりました。

エクセルでコピー処理を行うと、クリップボードには書式情報等含めて引き渡される？　ため、これが`Image`に変換できるって話な気がします。

この動きについてちょっと確認してみます。

## Get-ClipboardのFormatオプションはWindows PowerShellにしか存在しない

今回利用する`Get-Clipboard`コマンドレットについては、PowerShellのバージョンが関係してきます。

`Get-Clipboard`コマンドレットに`Format`オプションが用意されているのは、`Windows PowerShell`のみとなり、クロスプラットフォームな`PowerShell`には`Format`オプションは用意されていません。

[Feature Request: Restore -Format option in Get-Clipboard #12290](https://github.com/PowerShell/PowerShell/issues/12290)

クロースプラットフォームな`PowerShell`の`Get-Clipboard`コマンドレットはあくまでプレンテキストな情報を取り扱うコマンドレットとなるようです。

## Windows PowerShellで試してみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/76eb2da9-633c-3e24-dacd-5124160ae8b6.png)

上記のようにテーブルを`CTRL - C`からクリップボードにコピーした状態で下記のコマンドを実行すると、画像イメージが`c:\temp\excel.png`に保存されます。

```PowerShell
$(Get-Clipboard -Format Image).Save("c:\temp\windows-poershell-excel.png")
```

Excelでコピー時にクリップボードに渡された情報を　[Clipboard.ContainsImage メソッド](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.clipboard.containsimage?view=windowsdesktop-7.0#system-windows-forms-clipboard-containsimage)　で確認してみると、`True`と返却されるため。


Excelからクリップボードに引き渡される情報は、Imageに変換できる形式のもののようです。

```PowerShell
# エクセルでコピーしたあとに下記のコマンドを実行するとTrueが返却される。
# ContainsImage()メソッドは　Bitmap 形式のデータ、またはその形式に変換できるデータがクリップボードに存在するかどうかを示す

Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.Clipboard]::ContainsImage()
```


## 【余談】PowerShell 7で実行したい場合

PowerShell 7 では、2023年2月現在。

`Get-Clipboard`に`Format`オプションは実装されておらず、プレーンテキストのみを扱うようなコマンドレットとなっています。

このため、Excelでクリップボードに渡された情報をイメージとして出力するためには`Get-Clipboard`コマンドレットは利用できず。下記のように`.NET`を利用することで出力できます。

```PowerShell
$clip = $([System.Windows.Forms.Clipboard , System.Windows.Forms]::GetDataObject())
if ( $clip.ContainsImage() ) {
    [System.Drawing.Bitmap]$clip.getimage().Save("c:\temp\excel.png", [System.Drawing.Imaging.ImageFormat]::Png)
}
```

## そもそもExcelには図として保存がある

Excelだとそもそも`図としてコピー｀という機能があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/ab12e11b-8c4e-16c1-0084-e9c1d49dd237.png)

上記のようにテーブルを`図としてコピー`すると、下記のような画像イメージをクリップボードにコピーする事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/78524982-997f-cab3-da01-ba61655193ca.png)

ExcelってImageに変換できる形式でなんか持ってるような気がします。

## 総評

Excelでクリップボードにコピーされる情報はImageに変換できるようです。

Excelにはそもそも`図としてコピー`機能があるため、このような情報をスクリプトとして何か利用用途があるかといわれると微妙ですが。

Excel上でコピーした時に渡されるクリップボードのデータってこんな感じなんだって忘備録。
TypeScript入門：初心者がわかりにくいところ

TypeScriptはJavaScriptの上位互換言語で、多くのWeb開発者が使用しています。しかし、初めてTypeScriptを学ぶとなると、慣れない概念や仕組みに遭遇することがあります。この記事では、TypeScriptで初心者がわかりにくいところを紹介します。

## 1. 型の定義
TypeScriptでは、変数や関数の引数に型を定義することができます。型の定義をすることで、プログラムを実行する前に型の不一致などのエラーを検出することができます。

### 例:

```typescript
const message: string = "Hello, World!";
console.log(message);
```

## 2. 型推論
TypeScriptでは、変数の型を明示的に定義しない場合でも、変数の値から型を推論することができます。これを型推論と呼びます。

### 例:

```typescript
const message = "Hello, World!";
console.log(message);
```

この例では、message変数に代入された値から、型が文字列であることが推論されます。

## 3. オブジェクトの型定義
TypeScriptでは、オブジェクトの型定義には複数の方法があります。例えば、以下のようにインターフェースを使って定義することができます。

### 例:

```typescript
interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Doe",
  age: 30
};

console.log(user);
```

## 4. インターフェース
インターフェースは、オブジェクトが持つプロパティやメソッドを定義するためのものです。インターフェースを使うことで、関数やクラスに対して渡すオブジェクトの型を指定することができます。

### 例:

```typescript
interface Person {
  firstName: string;
  lastName: string;
}

function greet(person: Person) {
  console.log(`Hello, ${person.firstName} ${person.lastName}!`);
}

const person = { firstName: "John", lastName: "Doe" };
greet(person);
```

この例では、Personインターフェースを使って、greet関数に渡すオブジェクトが持つプロパティを定義しています。greet関数では、このインターフェースを使ってオブジェクトの型を判別することができます。




## 5. 関数の型定義
TypeScriptでは、関数にも型を定義することができます。関数の型定義には、引数の型と戻り値の型を指定することができます。

### 例:

```typescript
function add(a: number, b: number): number {
  return a + b;
}

const result = add(1, 2);
console.log(result);
```

## 6. 配列の型定義
TypeScriptでは、配列にも型を定義することができます。配列の型定義には、配列内の要素の型を指定することができます。

### 例:

```typescript
const numbers: number[] = [1, 2, 3, 4, 5];
console.log(numbers);
```

## 7. Generics
Genericsは、型を一般化するための概念です。Genericsを使うことで、関数やクラスをより汎用的に作ることができます。

### 例:

```typescript
function identity<T>(arg: T): T {
  return arg;
}

const result = identity<string>("Hello, World!");
console.log(result);
```

この例では、identity関数を使うことで、任意の型の値を受け取り、同じ型の値を返すことができます。

以上が、TypeScriptで初心者がわかりにくいところの一部です。TypeScriptは、JavaScriptの上位互換言語であり、慣れることでより高機能な開発ができるようになります。初めてのTypeScript学習には少し時間がかかるかもしれませんが、継続することで有用なスキルを習得することができます。

## まとめ
- TypeScriptはJavaScriptの上位互換言語であり、より高機能な開発を行うことができます
- 変数や関数には型を定義することができ、型定義によってエラーを早期に検出することができます
- クラスやインタフェースを使ってオブジェクト指向のプログラミングを行うことができます
- Genericsを使うことで、関数やクラスをより汎用的に作ることができます

TypeScriptを学ぶことで、より質の高いコードを書くことができるようになります。初めは少し難しいかもしれませんが、継続することで身に付けられるスキルは大きいです。
顧客分析の手順 - 分析フォーマットの適用例:クロスセグメント分析 クロスセル機会と対象顧客の発見

:::note
この本書は2017年4月1日にTeradata Japanのブログに掲載された内容を、再掲載したものです。
掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::

著者 山本 泰史 （やまもと やすし）


# 顧客分析の手順

## 第18回： クロスセル機会と対象顧客の発見
クロスセグメント分析を利用した分析例の 2回目、今回は「優良顧客の育成」をテーマとした分析例をご紹介します。顧客からの支出を増加する際のアプローチとして、今まで購入いただいている商品／サービスとは異なる商品を購入いただく「クロスセル」というアプローチがあります。これを検討するための分析例をご紹介します。


### 分析の前提
クロスセグメント分析は、縦軸と横軸の両方に複数のセグメントを配置しますが、この際のセグメントは、互いに重複していても構いません。分析の対象となるのは縦と横のセグメントで、これらが互いに重複していることは当然として、横と横、縦と縦のセグメントに関しても重複していることが可能です。図27 をご覧ください。横軸は互いに重複無しのセグメント配置ですが、縦軸はそれぞれが重複しています。たとえば定期預金の残高が 500万円以上の会社員も、自営業もいらっしゃることでしょう。これらの重複がこの分析では許容されています。

<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/6db0c1fb-39aa-ab67-f211-acce0b8fa587.png">

この分析例は、図27 でご覧になれるとおり、金融機関を想定したデータ、分析例を用意しています。考え方として、横軸にクロスセルとそのベースとなる商品購入顧客をセグメントとして配置し、縦軸に対して、購入と関係のありそうな顧客属性の候補をそれぞれセグメントとして配置しています。以下にそれぞれを整理します。

### 対象セグメント：
・ 地域A に居住する顧客。この条件は以下の縦軸セグメント／横軸セグメントの上位条件として作用する。

### 横軸セグメント：
・ [総合口座のみ] 総合口座を保有しているが、住宅ローンを契約していない顧客

・ [総合口座＋住宅ローン] 総合口座と住宅ローンの両方を契約している顧客

・ [住宅ローンのみ] 住宅ローンを契約しているが、総合口座は保有していない顧客

### 縦軸セグメント：
・ [定期預金残高 > 500万円以上] 定期預金の残高額が 500万円より高い顧客

・ [会社員] 職業欄の記入が会社員、会社勤めの顧客

・ [自営業] 職業欄の記入が自営業、自営業を営んでいる顧客

・ [ローン(住宅ローン以外)商品契約中] 学資ローン、自動車ローン等のローン商品を契約している顧客、ただし住宅ローンは含まない

・ [投資商品契約中] 投資信託や国債等の商品を契約している顧客

このような各セグメントに対して、縦軸と横軸で両条件に合致する顧客群をマトリックス表示させています。そして表示させる指標として顧客数と顧客数構成比（対象セグメントを分母）を表示させています。また、各セグメントの単独条件に合致する顧客数と顧客数構成比に関しては、各セグメント名称の隣（縦軸セグメント）、真下（横軸セグメント）に表示しています（紺色部分）。

（母集団と合計の顧客数は同じ値とはなりません。理由は、地域A居住の顧客でも総合口座、住宅ローン以外の商品を契約している顧客がいるためです。）



### 顧客セグメント毎の傾向
ここで最終的に期待する結果としては、総合口座を保有している顧客群から、住宅ローンを案内する候補としての顧客群を理解することとします。例えば、持家区分が「賃貸」の顧客を対象にして案内するのが適切と想定できますが、ここではそれに追加する絞込条件として適切な条件を探していきます。もちろん、[会社員]や[投資商品契約中]といったセグメントレベルで案内するのではなく、最終的な選定条件は様々に検討して住宅ローンを案内しなければなりませんが、ここでは、その条件を構築するための要素属性を拾い上げるため、以下の点を整理することにします。

・ そもそもの母集団が大きい層

・ 総合口座＋住宅ローンの割合が高い層

データを見ていくと、当該地域においては会社員が半数以上を占めています。また、住宅ローンと総合口座両方保有している割合は、定期預金が 500万円以上の顧客、そして会社員で相対的に高く、ともに 3.3％となっています。従って、まずは会社員で定期預金が 500万円以上の顧客を対象とする、もしくはこの顧客群向けにキャンペーンの案内メッセージを考えるのが最初の方向性といえます。

また、3.3％に相当する　20万名の会社員は既に住宅ローンを契約済みです。この顧客群が契約をした年齢、その時の年収、預金残高等が把握できれば、会社員、定期預金残高に加えた対象顧客の条件として活用できそうです。


### アプローチの方向性
このような分析によって、アプローチしたい商品やサービスに対して、支持を与えてくれている顧客群はどのような顧客群で、どの程度のボリューム存在しているのかを理解することが可能となります。これによって対象顧客の絞込み条件を適切に設定することが可能となりますし、案内メッセージを対象顧客（今回の例であれば会社員）にとってより魅力的なものとすることが可能となります。今回は金融商品と、図27 に示したようなセグメント条件で実施しましたが、他の様々な商品やサービス、そして他の様々なセグメントにも適用できる分析です。



#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
Chrome拡張機能をハックしてみる

## はじめに

Chrome Web Storeなどで配布されているChromeの拡張機能に、コードを埋め込んで任意のコードを実行させる方法を紹介します。
配布されている拡張機能がどんな動きをするのかを知るために使えるかもしれません。

## Chrome拡張機能ディレクトリ

OSによって微妙に異なりますが、Chrome Web Storeからインストールした拡張は、macOSの場合はこの位置に保存されます。

```
/Users/user/Library/Application Support/Google/Chrome/{Profile name}/Extensions/
```

今回は実験用として [Dark Reader](https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?hl=ja) をインストールしてみました。

この拡張機能はWebstoreでのIDが `eimadpbcbfnmbkopoojfekhnkhdbieeh` なので、この名前のディレクトリで保存されています。

```
$ ls -l ~/Library/Application\ Support/Google/Chrome/Profile\ 4/Extensions/
total 0
drwx------@ 4 user  staff  128  2 10 16:48 eimadpbcbfnmbkopoojfekhnkhdbieeh # ←これ
```

## 直接改変するとエラー

場所を特定できたので動きを分析したいだけであればもう十分ですが、実際にコードに変更を入れてそれを読み込ませてみます。
直接変更を加えるとブラウザ側でエラーが発生する仕様になっているので、一旦適当な作業用ディレクトリにコードを退避してから作業します。

直接改変した際に発生するエラー：
![スクリーンショット 2023-02-10 17.00.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210904/c98a18ba-2dd2-2518-af1a-7e828413e04a.jpeg)

## 改変してみる

ということでデスクトップにコピーして作業します。

```
$ cp -r ./eimadpbcbfnmbkopoojfekhnkhdbieeh ~/Desktop
```


今回は作業ディレクトリ直下のmain.jsに `Hello chrome!` と表示させるコードを追加してみました。

```javascript
console.log('Hello chrome!');
```

今回はこれだけです。
コードの編集が終わったら [拡張機能のページ](chrome://extensions/) の「デベロッパーモード」から「パッケージ化されていない拡張機能を読み込む」と進みます。
するとディレクトリの選択が求められるので、先程コピーした作業用ディレクトリの `manifest.json` が含まれれるディレクトリを選択します。
これで準備完了です！

## ページを開いてみる

準備が整ったので、実際に改変した拡張機能のコードが実行される様子を見てみます。
今回は試しにブラウザコンソールに 'Hello chrome!' と出力するコードを追加してみました。

ブラウザコンソールを開いた状態で適当なページを開いてみます。

![スクリーンショット 2023-02-10 17.20.11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/210904/e90d0b69-7e65-7942-4005-192894e25651.jpeg)

きちんと出力されているのが確認できますね。

気になった拡張機能をデバッグしてみるのに使えそうですね。
以上、拡張機能にコードを埋め込む方法でした。
Oracle Analytics Cloud：フィルタ、式フィルタを利用したOR条件のセット

はじめに
---
フィルタペインに配置したフィルタはAND条件になり、たとえば日付範囲で、2/6から2/12と3/6から3/12までといった異なる２つの期間の販売実績を一緒に参照したい場合などには利用できません。下図に加えて日付を条件に追加した場合はAND条件で追加されていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/d7fffefc-3487-76b0-6427-ddaaffbf82f1.png)

そのため、OR条件をセットしたい場合では、式フィルタを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/bc55a720-7f58-2ac2-a335-0a3eca840b32.png)

式フィルタのセット
---
式フィルタを追加する場合、＋アイコンをクリックし、式フィルタの追加をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/58edcd2a-3dba-30ec-ff3d-fc8b1d57f199.png)

式フィルタに式を記述し、記述内容が正しいか検証をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/12c7454e-ccf3-d735-d5e2-4e7796494e9a.png)

OKであれば、適用をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/b47da2a7-e801-029e-21f7-ec25c069800f.png)

OR条件で結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/817e5869-0262-a5fc-7441-d2268552fc16.png)

式フィルタを使うときは、自身で日付を入力します。
例えば、日付を直接入力するのではなくカレンダーなどを使って利用したい場合は、ダッシュボードプロンプトおよびAnswersを利用することでも実現できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/0ee98aa4-1dba-e8f7-37d3-aeccca54c360.png)

以上
Vue3でコンポーネントを作るときは、ネイティブイベントをいちいちemitしなくて良い。

Nuxt3もRC版になったということで、勉強も兼ねて自分のWebサイトを作っている途中に遭遇した問題(その2)について。

# 環境
node.js v18.13.0
Typescript v4.7.4
Nuxt v3.0.0-rc.14
TailwindCSS v3.2.4
vue-gtag-next v1.14.0
※Vueは3.0系（ここ大事）
開発環境はWSL(Debian)だったりChromeOS(Crostini)だったり色々。

# 発端
## ボタンだけのコンポーネントを作った。
せっかくTailwindCSSやVueを使っているのだから、要素単位でコンポーネントを作って使いまわそうと考え早速ボタンを作った。
```html:AppBtn.vue
<template>
  <button :disabled="props.disabled" @click="$emit(`click`)">
    <slot />
  </button>
</template>
```
コンポーネント内でclickイベントが発火したら、親コンポーネントにイベントをemitする割とよくあるコンポーネント。
早速組み込んで動作確認してみると以下の症状が出た。

# 症状
## clickが2度発火する。
親コンポーネントでボタンコンポーネントをクリックしたらconsole.log()で"click"と表示してみると、何故か2回Clickと表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425022/8dc9f35b-a2b0-1602-55d0-04f54c6a81aa.png)
ちなみにVueDevToolではイベントは1回だけ発火している事になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425022/8546f637-07e9-1f56-5797-6027b286152f.png)
外部APIを叩くときなど非同期処理を実行するようなときには割と面倒なことが起きそうなので、できれば解決したいところ。

### stop()を使っても効果なし
調べてみると「stopつけろ」という情報が出てきた。Vueのイベント修飾子の一つで、イベントの伝播を止める事ができる。
```html
  <button :disabled="props.disabled" @click.stop="$emit(`click`)">
    <slot />
  </button>
```
しかし効果なし。


# 原因
拙い英語力で色々調べていると、1周回って[日本語の情報](https://github.com/webdino/lyceum-pokemon/pull/76)が出てきた。曰く「Vue3はネイティブイベントをフォールスルーしてくれる」らしい。

# 解決策
emitを消して何も書かない。
```html
  <button :disabled="props.disabled">
    <slot />
  </button>
```
不安だったが実際console上でも1回しか表示されていないのでこれが正解らしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425022/dde57ece-7b83-ddb8-f17e-c99ffbf55f5c.png)
そういえばVue3ではV-modelのイベントが"update:modelValue"に変わったが、この辺の変更と関係があるのかもしれない。

# 参考資料
- [fix: clickがネイティブイベントとカスタムイベントの2回呼ばれている by knokmki612 · Pull Request #76 · webdino/lyceum-pokemon](https://github.com/webdino/lyceum-pokemon/pull/76)
- [イベントハンドリング — Vue.js](https://jp.vuejs.org/v2/guide/events.html#%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E4%BF%AE%E9%A3%BE%E5%AD%90)
初学者が、一番最初に覚えるべきk8sコマンド

#### 自分は今何のclusterの状態を見てるのか?

```
k config current-context
```
#### 自分のkubeconfigに登録されているcluster一覧
```
k config get-clusters
```

#### 確認したい閲覧したいclusterを切り替える

```
k config use-context <cluster名>
```


### よく実務中、調査で使用するモジュール

#### k9s

この人が、使い方をまとめてくれている。

https://qiita.com/t0m0ya/items/15ee4d43dcda4701946c
わかるようでわからない。"方針"ってなんでしょうか？

# １．お話の概要
これは私がコンサル時代に実体験から学んだお話し。
クライアントに「データ移行計画をたててー、まずは移行方針からもってきてね」といわれサクッとつくってみると、先輩やクライアントからダメ出しをうけました。「方針」ってわかるようでわからなくてけっこうはまりました。
方針は数行レベルでpptに表現されてて、数分でできちゃうみたいに思いがちですが、けっこう奥が深かった。

# ２．私がやったこと
移行方針計画の作成自体が初めてだったので私がやったことは、以下2点です
* ネットで移行計画とか移行方針とか調べる
* 社内の他PJでの移行計画書を拝借する

上記を調べると、移行方針ってのは以下のようなことをお題目として書きましょうと出てくる。
* 移行対象（スコープ）
* 移行方法（一括移行か段階移行かとか、手動かツール作るのかとか）
* 移行スケジュール
* 移行体制

なるほどーと思って私がやったことは上記のお題目に対する穴埋め。専門コンサルじゃない人がやりがち。

# ３．ダメ出し
そして以下のようなダメ出しを受けました。
* 移行対象にXXっていうデータを移行しますとしか書いてないけど、そんなの当たり前じゃん。逆にどういうのが移行対象外なのか？
* 移行方法が一括移行ってこの規模なら当たり前じゃん。。。
↓
* 要するに「教科書に載ってるようなこと拾って、穴埋めしただけで、全然考えてないじゃん」って言われた感じです。

# 4．学んだこと。「方針」ってどう考えて何を書くんだろう。
そもそも方針って何のためにあるんでしょうか。
私は**方針とは**実際にもっと具体的な方法を考えるときの指針であり、要するに「**具体的な方法論に落とし込むときに迷わないようにするための**」だと考えます。
だから**あとでやり方に迷ったり、揉めそうなこと**を方針に書くのです。逆にいうと**そんなの当たり前じゃんみたいなことは方針にはいらない**のです。

例えば上記でいうと移行スコープで後で迷ったり揉めたりするのは、過去分のデータって大量にあるし移行するにはツールとか作る必要があってコストかかるけど移行するか？とかだったりするので、何を移行しないのかという対象外にする線引きがとても重要だったりします。
あと一括移行か段階移行かなんてある程度システム規模が大きくないと迷わないことで、当時のPJはシステム規模が大きくなかったため、一括移行ってことで誰も迷わないんですよね。

ということで、”方針”って一番最初の方に検討することなんですけど、プロジェクトとかシステムの特徴捉えつつ、最後の最後の方まで見通し作らないといけないので、奥が深いなあ（難しいなあ）というお話でした。

ちなみにそんなの当たり前じゃんという品質のことを当たり前品質と呼び、狩野モデルというモデルの中で説明されているのでご参考までに。
参考：https://ja.wikipedia.org/wiki/%E7%8B%A9%E9%87%8E%E3%83%A2%E3%83%87%E3%83%AB
[Rails]コントローラ、ルーティング、ビュー、モデルの記述ルール

## はじめに
コントローラ、ルーティング、ビュー、モデルを作る際のルールをざっくりまとめてみようと思う

## コントローラでの命名規則
- コントローラ名は全て複数形かつ全て小文字
- Railsはコントローラ作成と同時に、必要なviewファイルの作成や記述の追加ができる
```rb
$ rails g controller コントローラ名 アクション名
```

## ルーティングのルール（基本編）
```rb
HTTPメソッド 'URL' => 'コントローラ#アクション'
```
URLと'コントローラ名#アクション名'の形が同じ場合は省略可能↓
```rb
get 'homes/top'
```

#### 代表的なHTTPメソッド
- GET（リソースの取得、画面表示）
- POST（リソースの更新、リソースへのデータ追加 など）
- DELETE（リソースの削除）

## ビューでの命名規則
- ビューファイルの名前は、アクション名と同じ名前にする

## モデルでの命名規則
- モデル名 → 先頭は英大文字/単数形
- モデルのファイル名 → 先頭は英小文字/単数形
- テーブル名 → 先頭は英小文字/複数形

```rb
$ rails g model モデル名
```
　
#### テーブル作成
migrationファイルはモデルを作成した際に自動生成されている。
```rb
def change
  create_table :テーブル名 do |t|
    t.データ型 :カラム名
  end
end
```
テーブルを作成するコマンド↓
```rb
username:~/environment/first_app $ rails db:migrate
```

#### カラムの追加と消去方法
①追加コマンド↓
```rb
$ rails g migration Addカラム名Toテーブル名 カラム名:型名
```
②忘れずに↓
```rb
$ rails db:migrate
```


①消去コマンド↓
```rb
$ rails g migration Removeカラム名Fromテーブル名 カラム名:型名
```
②こちらも忘れずに↓
```rb
$ rails db:migrate
```


## まとめ
作成の流れをスムーズに行いたかったのでポイントをまとめてみました。
特定のWindowsエディションでNASにゲストログオンできない場合の対処

## 問題
Windows10のProやEducationなどのエディションでは、NASへのゲストログオンがデフォルトではブロックされるようになり、以下のようなエラーが出るようになりました。
`組織のセキュリティポリシーによって非認証のゲストアクセスがブロックされているためこの共有フォルダーにアクセスできません`

何らかの理由でゲストログオンを必要とする場合の対処法をまとめる。

## 解決法
1. Windows + Rを押して`gpedit.msc`と入力し、ローカルグループポリシーエディターを開く
2. コンピュータの構成→管理用テンプレート→ネットワーク→Lanmanワークステーション を開く
3. 安全でないゲストログオンを有効にする を開く
4. 有効を選択し、OKボタンを押す
5. PCを再起動する
React js 複数の入力情報を１つの変数で管理

![ReactJS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/0c984b5c-20f7-e66a-92d1-dd3cc660de41.png)


# 複数の入力情報を１つの変数で管理

https://youtu.be/8ly39na3LLM?t=2801


```javascript:App.js
    import "./App.css";
    import { useState } from "react";
    
    const initialState = {
      name: "",
      email: "",
      contact: "",
    };
    
    function App() {
      const [state, setState] = useState(initialState);
    
      const { name, email, contact } = state;
    
      const handleInputChange = (e) => {
        const { name, value } = e.target;
        setState({ ...state, [name]: value });
// setState((prev) => ({ ...prev, [name]: value }));
      };
    
      console.log(state);
    
      return (
        <div className="App">
          <form
            action=""
            style={{
              display: "flex",
              flexDirection: "column",
              margin: "auto",
              padding: "15px",
              maxWidth: "400px",
              alignContent: "center",
            }}
          >
            <label htmlFor="name">Name</label>
            <input
              type="text"
              id="name"
              name="name"
              placeholder="Your name ..."
              value={name || ""}
              onChange={handleInputChange}
            />
    
            <label htmlFor="email">Email</label>
            <input
              type="email"
              id="email"
              name="email"
              placeholder="Your email ..."
              value={email || ""}
              onChange={handleInputChange}
            />
    
            <label htmlFor="contact">Contact</label>
            <input
              type="number"
              id="contact"
              name="contact"
              placeholder="Your contact No..."
              value={contact || ""}
              onChange={handleInputChange}
            />
          </form>

          <pre>{JSON.stringify(state, null, "\t")}</pre>
        </div>
      );
    }
    
    export default App;

```

# ブラウザ表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/20d0d127-bc15-1b41-59f0-f76d4c3b9cb5.png)
2023-CES参加体験記

CESに出展者側としてラスベガスで営業してきたので、その体験記を以下に載せてあります。


![スクリーンショット 2023-02-10 17.53.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/f68d1deb-d596-7db2-801b-d8ce586818d1.png)

https://www.ces.tech/


## 準備編

https://note.com/osaka_heat_cool/n/n2a1b6565b155


## Eureka Park ②出展レポート・前半 

https://note.com/osaka_heat_cool/n/n2a1b6565b155


## Eureka Park ②出展レポート・後半 

https://note.com/osaka_heat_cool/n/n7e288a9a5a6e


## ラスベガス編

https://note.com/osaka_heat_cool/n/n8505956af454

---

http://www.stin.kobe-u.ac.jp/info2/2023_01_30_01.html
gitのstashを使いこなせるようになりたい

## はじめに
チーム開発などをしていると、他メンバーの進捗によってコンフリクトなどを恐れて先に進めないなんてことがあるとのこと。
そんなときに役立つのがgitの`stash`。
そんなstashを使いこなせるようになりたい。少しずつ慣れていけるようにしていく。

## shashとは
stash は退避するという意味を持つそう。
今とあるブランチで作業してるけど、急にやりたいことができた。でもコミットしたくない。→ そんなときに使えるのがStashとのこと。
stashを使用すると、コミットしていない変更を退避することができる。
stashで現在の変更を退避して、今すぐやりたい作業をして、退避させていた変更を戻して作業を再開することができる。

## 実際の使い方
### 現在の作業を一時的に退避したい
```
$ git stash save
```
- save は省略できる。 また、 save の後に内容を表すメッセージを指定することができる。
- 下記のようにメッセージ指定して書くことができる。

```
$ git stash save "◯◯を修正中"
```

### 退避した作業の一覧を表示
```
$ git stash list
```
- 退避した作業の一覧を見ることができる
- 下記のような感じでStashしたリストを確認できる

```
stash@{0}: On be-webtest: ◯◯を修正中
```

複数Stashした場合は下記の様な感じで出る
```
stash@{0}: On be-webtest: ◯◯を修正中
stash@{1}: On be-webtest: Admin/UserControllerTest作成途中
```

### 退避した作業を戻す
```
$ git stash apply stash@{0}
```
- stashを`stash@{0}`で指定してあげて`apply`を使って戻す

### 退避した作業を消す
```
$ git stash drop stash@{0}
```
- `stash@{0}` をstashのリストから削除することができる

### 退避した作業を元に戻すと同時に、stashのリストから消す
```
$ git stash pop stash@{0}
```

- `stash@{0}` の作業をもとに戻すと同時に、退避作業の中から削除する
- `apply`とは違い退避リストからも消してしまうため、間違えて操作してしまうと戻れなくなるため、不安な人は`apply`で操作したほうが良いかも

## まとめ
慣れるまで時間がかかりそうだが、慣れたらすごく便利そうなStash
待機時間を作らないためにも覚えていきたいですね。以上
Flutterのin_app_purchaseのProductDetails,PurchaseDetailsをMap<String,dynamic>から変換する

## この記事を書こうと思った経緯

以下の記事を書き、どうせなら逆もやろうと感じたから。

https://qiita.com/nR9h3kLy/items/e14f01168bc34f3bab24

# 結論
```from.dart

import 'package:in_app_purchase/in_app_purchase.dart';

ProductDetails productDetailsFromJson(Map<String, dynamic> json) =>
    ProductDetails(
      id: json['id'] as String,
      title: json['title'] as String,
      description: json['description'] as String,
      price: json['price'] as String,
      rawPrice: (json['rawPrice'] as num).toDouble(),
      currencyCode: json['currencyCode'] as String,
      currencySymbol: json['currencySymbol'] as String,
    );

PurchaseDetails purchaseDetailsFromJson(Map<String, dynamic> json) =>
    PurchaseDetails(
      purchaseID: json['purchaseID'] as String,
      productID: json['productID'] as String,
      verificationData: _purchaseVerificationDataFromJson(json['verificationData'] as Map<String, dynamic>),
      transactionDate: json['transactionDate'] as String,
      status: PurchaseStatus.values.byName(json['status'] as String),
    );
    
PurchaseVerificationData _purchaseVerificationDataFromJson(
        Map<String, dynamic> json) =>
    PurchaseVerificationData(
      localVerificationData: json['localVerificationData'] as String,
      serverVerificationData: json['serverVerificationData'] as String,
      source: json['source'] as String,
    );
```
Oracle Analytics Cloud：関数を使う。日付変換する

はじめに
---
文字列を日付型に変換してみます。文字列を日付型に変換するには、関数を利用します。To_DateTimeと、Castの関数があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/e6da41c4-e8a2-821e-ddc7-becc4ded3665.png)

記事記載時のOAC ver：Jan 2023 Update

To_DateTimeの利用
---
To_DateTime('20180206','YYYYMMDD')のように利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/d285c5a8-c664-58ec-c234-636c9e0dd359.png)


Castの利用
---
Cast('06/Feb/18' as Date)のように利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/104baae5-d8b1-0b3c-7050-9a381f86b52e.png)



'06/Feb/18'のところはOACにログインしているユーザーの属性でデフォルトの表示形式を利用します。日付型をテキスト型に変換すると確認できます。
マイ計算で以下の計算式列を追加します。
cast(TIME_ID as char)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/adb6d480-c4b4-22e7-351f-171a854a8a59.png)

追加した列で、表示形式を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516153/b770a8ec-294e-d482-db16-e6d9c34bf11e.png)


## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [Converting Columns to DateTime in Oracle Analytics Cloud](https://blogs.oracle.com/analytics/post/converting-text-columns-to-datetime-in-oac)


以上
ESP32: BlueTooth でシリアル通信

ESP32 から Ubuntu 24.04 にデータを送信してみました。
ESP32-WROOM-32E と M5StackCore2 で確認しました。

Ubuntu 24.04 上の Arduino IDE 2.3.2 を使いました。
ボードは、 ESP32 Dev Module です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1401e5b5-0ab5-2c0a-1b10-ee697fe5a17d.png)


## ESP32 のプログラム

```text:bluetooth_serial.ino
// ---------------------------------------------------------------------
//	bluetooth_serial.ino
//
//					Feb/10/2023
// ---------------------------------------------------------------------
#include "BluetoothSerial.h"
#define	PROGRAM	"bluetooth_serial.ino"
#define	VERSION	"2023-2-10 PM 17:19"

BluetoothSerial SerialBT;

int count = 0;

// ---------------------------------------------------------------------
void setup()
{
	SerialBT.begin("ESP32test_01"); //Bluetooth device name
}

// ---------------------------------------------------------------------
void loop()
{
	SerialBT.printf("count = %d\r\n",count);
	delay(1000);
	SerialBT.println("Good Morning!");
	delay(1000);
	SerialBT.println("Good Afternoon!");
	delay(1000);
	SerialBT.println(PROGRAM);
	SerialBT.println(VERSION);
	SerialBT.println();
	delay(1000);
	count++;
}
	
// ---------------------------------------------------------------------
```

## Ubuntu の操作

デバイスのスキャン

```text
$ hcitool scan
Scanning ...
	8C:4B:14:16:B8:6E	ESP32test_01
```

デバイスに対して ping をうつ

```text
$ sudo l2ping -c 3 8C:4B:14:16:B8:6E
Ping: 8C:4B:14:16:B8:6E from 3C:21:9C:50:7C:46 (data size 44) ...
0 bytes from 8C:4B:14:16:B8:6E id 0 time 7.63ms
0 bytes from 8C:4B:14:16:B8:6E id 1 time 5.84ms
0 bytes from 8C:4B:14:16:B8:6E id 2 time 5.89ms
3 sent, 3 received, 0% loss
```

デバイスの確認

```text
$ sdptool browse 8C:4B:14:16:B8:6E
Browsing 8C:4B:14:16:B8:6E ...
Service Name: ESP32SPP
Service RecHandle: 0x10000
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0102
```

ポートの割りつけ

```bash
sudo rfcomm bind 1  8C:4B:14:16:B8:6E
```

ポートの状態の確認

```text
$ sudo rfcomm
rfcomm1: 8C:4B:14:16:B8:6E channel 1 clean
```

シリアル接続

```text
$ cu -l /dev/rfcomm1 -s 115200
Connected.
bluetooth_serial.ino
2023-2-10 PM 17:19

count = 9
Good Morning!
Good Afternoon!
bluetooth_serial.ino
2023-2-10 PM 17:19

count = 10
Good Morning!
Good Afternoon!
bluetooth_serial.ino
2023-2-10 PM 17:19
```

ポートの開放

```bash
sudo rfcomm release 1
```
Logの送信をやさしくしてくれるPuree

# Logの送信をやさしくしてくれるPuree

- logを収集するもので下記の機能をもつオープンソース。
  - filter: ログに共通パラメーターを追加する
  - buffer: バッファに入れる
  - patch: 複数のログを１つにまとめて送る
- 現在はPuree-Swiftに移行されている模様。
- [githubページ](https://github.com/cookpad/puree-ios "puree-ios")

![overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123134/43733bc0-97b7-4b8d-9950-e7a8c163a7f1.png)


## インストール方法

```Shell
pod "Puree"
```

## 使い方

1. filter, outputなどの動きを定義するクラスを作る

    ```Swift
    class ActivityFilter: PURFilter {
        override func logs(object: Any, tag: String, captured: String?) -> [PURLog] {
           let currentDate = logger.currentDate()
            return [PURLog(tag: "activity.tap", date: currentDate, userInfo: ["an event": object])] 
        }
    }

    class ConsoleOutput: PUROutput {
     override func emit(log: PURLog) {
         // ここにLogを送るロジックを描く
        }
    }
    ```

2. configurationを生成してfilter, outputなどの設定を行う。loggerを生成する

    ```Swift
    let configuration = PURLoggerConfiguration.default()
    configuration.filterSettings = [
        PURFilterSetting(filter: ActivityFilter.self, tagPattern: "activity.**"),
        // filter settings ...
    ]
    configuration.outputSettings = [
        PUROutputSetting(output: ConsoleOutput.self,   tagPattern: "activity.**"),
        PUROutputSetting(output: ConsoleOutput.self,   tagPattern: "pv.**"),
        PUROutputSetting(output: LogServerOutput.self, tagPattern: "pv.**", settings:[PURBufferedOutputSettingsFlushIntervalKey: 10]),
        // output settings ...
    ]

    let logger = PURLogger(configuration: configuration)
    ```

3. postメソッドを使ってログを送信する

    ```Swift
    logger.post(["recipe_id": "123"], tag: "pv.recipe_detail")
    ```
Flutterのin_app_purchaseのProductDetailsの例

## この記事を書こうと思ったわけ
App StoreやGoogle Play Storeで作成したアイテムを取得するには、アプリをビルド、ストアにアップロード、デバイスにダウンロードする工程を踏む必要があり、面倒だから。

# 結論
```items.dart
import 'package:in_app_purchase/in_app_purchase.dart';

List<ProductDetails> myProductList = [
  ProductDetails(id: kAnnualSubscriptionId, title: "年額プラン", description: "一年使えます", price: "¥10000", rawPrice: 10000, currencyCode: "JPY"),
  ProductDetails(id: kMonthSubscriptionId, title: "月額プラン", description: "一月使えます", price: "¥1000", rawPrice: 1000, currencyCode: "JPY"),
  ProductDetails(id: kWeekSubscriptionId, title: "週額プラン", description: "一週間使えます", price: "¥500", rawPrice: 500, currencyCode: "JPY")
];
```
kWeekSubscriptionId,kMonthSubscriptionId,kAnnualSubscriptionId

の三つの変数には各自のアイテムのIDを入れて実際に使ってみてください
特許データのバブルチャートを考える。

# はじめに
特許マップではバブルチャートがよく用いられます。しかし、Excelでバブルチャートを作成するのは面倒という問題があります。

一方、下記リンク先の記事にもありますように、Pythonでもバブルチャートは書けるようですので、初心者でもバブルチャートを書けるか挑戦してみました。

・[【特許分析】Pythonでお金を掛けずにパテントマップを作ってみた](https://qiita.com/kon2/items/5966dea076c349aecbaf)
# 使用するデータ
最初から特許データを処理するのはハードルが高いので、今回は、下の2×5の仮データを使って、バブルチャートを書いてみたいと思います。プログラムがうまく動きそうでしたら、次回特許データを処理したいと思います。

甲列はAとBのみ含み、乙列はXとYのみ含みますので、うまくゆけば２×２のバブルチャートが完成するはずです。


| 甲 | 乙 |
|:-:|:-:|
| A | Y |
| B | Y |
| A | X |
| B | X |
| B | Y |

# 使用する関数
今回はgroupbyを使用してバブルチャートが書ける形式にデータを集計したいと思います。

groupbyは、Pythonのpandasライブラリに含まれている関数で、同じ値を持つ要素をグループ化することができます。グループ化には、特定の列を基準としてグループ化することができます。その後、グループ化された各グループに対して計算を実行することができます。

今回は、甲列、乙列でグループ化して、各グループのサイズを size で取得します。
# プログラム
## データフレーム化
まずは、上記の表をデータフレーム化します。

```python
import pandas as pd
import matplotlib.pyplot as plt

# DataFrameを作成するためのデータを作成
data = {'甲': ['A', 'B', 'A', 'B', 'B'],
        '乙': ['Y', 'Y', 'X', 'X', 'Y']}
# DataFrameを作成
df = pd.DataFrame(data)
```
## groupbyの使用
グループバイ関数を使い、出力を確認してみます。
```python
# 「甲」と「乙」の列でグループ化し、グループ内の要素数を数える
result = df.groupby(['甲', '乙']).size().reset_index(name='Counts')
# resultを確認
print(result)
```
出力は以下のようになります。A,B,X,Yのグループとそのサイズがカウント数として抽出されております。あとは、甲と乙を軸とし、カウント数に対応する大きさのバブルを配置すれば、バブルチャートとなるはずです。
```:result
   甲  乙  Counts
0  A  X       1
1  A  Y       1
2  B  X       1
3  B  Y       2
```
## リスト化
x,y,sizeのリストを作成します。sizeについては、countsをバブルチャートをみながら適当な倍数（ここでは300）で補正したものをリスト化します。

```python
# 「甲」と「乙」の列からなる値をリスト形式に変換
x = result['甲'].tolist()
y = result['乙'].tolist()
# 「Counts」列からなる値を元に、散布図のすべての点の大きさを示すリストを作成
sizes = [size * 300 for size in result['Counts'].tolist()]
# xとyとsizesを確認
print(x)
print(y)
print(sizes)
```
リストはこのような感じとなりますので、これをmatplotlibで散布図を書けばよいこととなります。
```:リスト
['A', 'A', 'B', 'B']
['X', 'Y', 'X', 'Y']
[300, 300, 300, 600]
```
## カラーマップの使用
バブルの色は同じでも構わないのですが、ここでは勉強がてらバブルの色をカテゴリーで変えてみます。色を変えるにはカラーマップを使用します。
```python
import numpy as np
import matplotlib.cm as cm

# 「乙」列からなる値を元に、カテゴリーのリストを作成
categories = list(set(y))
# 色マップを作成
colors = cm.rainbow(np.linspace(0, 1, len(categories)))
colors = {categories[i]: colors[i] for i in range(len(categories))}
colors = [colors[item] for item in y]
```
## 散布図作成
最後に、matplotlibで散布図を書けば完成です。
```python
# 散布図を作成
fig, ax = plt.subplots()
ax.scatter(x, y, s=sizes, c=colors)
# X軸とY軸のレンジを設定
plt.xlim(-0.5,1.5)
plt.ylim(-0.5,1.5)
# 図を表示
plt.show()
```
出力は、以下となります。一応、バブルチャートはかけているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3110569/fec0fd4b-7e8e-3150-2870-686b7a086670.png)
# 感想
とりあえずバブルチャートは書けましたが、matplotlibの出力については、人間が目で見ての調整となりますので、慣れないうちは面倒に感じました。数値だけでよいなら、前回のクロス集計で十分と思います。

また、バブルチャートを作成するにあたり、クロス集計は不要ということがわかり、意外に感じました。

次回は、実際の特許データを使用してバブルチャートを書いてみたいと思います。
Flutterのin_app_purchaseのProductDetails,PurchaseDetailsをMap<String,dynamic>に変換する

# この記事を書こうと思った経緯

ProductDetails,PurchaseDetailsをMap<String,dynamic>に変換して、Cloud Firestoreに保存しようと思ったから

# 結論
```convert.dart
import 'package:in_app_purchase/in_app_purchase.dart';

Map<String, dynamic> purchaseDetailsToJson(PurchaseDetails instance) =>
    <String, dynamic>{
      'purchaseID': instance.purchaseID ?? "",
      'productID': instance.productID,
      'verificationData': _purchaseVerificationDataToJson(instance.verificationData),
      'transactionDate': instance.transactionDate ?? "",
      'status': instance.status.name,
    };

Map<String, dynamic> _purchaseVerificationDataToJson(
        PurchaseVerificationData instance) =>
    <String, dynamic>{
      'localVerificationData': instance.localVerificationData,
      'serverVerificationData': instance.serverVerificationData,
      'source': instance.source,
    };

Map<String, dynamic> productDetailsToJson(ProductDetails instance) =>
    <String, dynamic>{
      'id': instance.id,
      'title': instance.title,
      'description': instance.description,
      'price': instance.price,
      'rawPrice': instance.rawPrice,
      'currencyCode': instance.currencyCode,
      'currencySymbol': instance.currencySymbol,
    };
```

# 使用例

ListTileをtapしたら、productsをCloud Firestoreに保存する場合
```.dart
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';

ListTile(
  title: const Text('Products'),
  onTap: () async {
    for (final p in _products) {
      final colRefName = Platform.isAndroid ? "android_products" : "ios_products";
      await FirebaseFirestore.instance.collection(colRefName).doc(p.id).set(productDetailsToJson(p));
    }
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Productsの保存成功です')));
  }
);
```

ListTileをtapしたら、purchasesを全てCloud Firestoreに保存する場合
```.dart
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';

ListTile(
  title: const Text('Purchases'),
  onTap: () async {
    for (final p in _purchases) {
      final colRefName = Platform.isAndroid ? "android_purchases" : "ios_purchases";
      await FirebaseFirestore.instance.collection(colRefName).doc(p.purchaseID).set(purchaseDetailsToJson(p));
    }
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Purchasesの保存成功です')));
  }
);
```

# 最後に
逆バージョンも書きました

https://qiita.com/nR9h3kLy/items/0cf3433241aaeda73b6e
学習やスキリングに参考にしている書籍やサイトまとめ





## Python実践データ分析１００本ノック 
![61CMdZ403aL.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124100/b3f96c93-bbce-4c20-18cd-956e97007a34.jpeg)
> 下山 輝昌 (著), 松田 雄馬 (著), 三木 孝行 (著)
[Amazon](https://www.amazon.co.jp/Python%E5%AE%9F%E8%B7%B5%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF-%E4%B8%8B%E5%B1%B1-%E8%BC%9D%E6%98%8C/dp/4798058750)

私が今お世話になっているスクールの講座は、E資格対策のための講座で（私の費用の関係上でこの講座を受講しています）、データクレンジングなどの手法は独学で学ぶ必要があったためこの書籍でデータクレンジングの手法を学びました。


## kaggleで勝つ　データ分析の技術
![711RnOZp-6L.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124100/b68bcfcc-5a4e-1a90-fb05-109628a3a025.jpeg)
> 門脇 大輔 (著), 阪田 隆司 (著), 保坂 桂佑 (著), & 1 その他
[Amazon](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94/dp/4297108437)

kaggleの練習コンペ”Titanic”にエントリーする際に参考にさせていただいた書籍です。

## スッキリわかる　SQL入門
![9160JJpexVL.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124100/8fefa601-5c58-011b-98a8-371956e93c6e.jpeg)

> 中山 清喬 (著), 飯田 理恵子 (著), & 1 その他
[Amazon](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB256%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8B%E5%85%A5%E9%96%80%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1/dp/4295013390/ref=asc_df_4295013390/?tag=jpgo-22&linkCode=df0&hvadid=553968464768&hvpos=&hvnetw=g&hvrand=17249925556572290950&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009775&hvtargid=pla-1598950080935&psc=1&th=1&psc=1)

イラストが直感的にわかりやすくてとても参考になります。

## 入門統計学
![71Wjb5JMO0S.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124100/8f7216dc-fea7-da90-0fbd-5609d6af9476.jpeg)
> 栗原伸一 (著)
[Amazon](https://www.amazon.co.jp/%E5%85%A5%E9%96%80-%E7%B5%B1%E8%A8%88%E5%AD%A6-%E7%AC%AC2%E7%89%88-%E6%A4%9C%E5%AE%9A%E3%81%8B%E3%82%89%E5%A4%9A%E5%A4%89%E9%87%8F%E8%A7%A3%E6%9E%90%E3%83%BB%E5%AE%9F%E9%A8%93%E8%A8%88%E7%94%BB%E6%B3%95%E3%83%BB%E3%83%99%E3%82%A4%E3%82%BA%E7%B5%B1%E8%A8%88%E5%AD%A6%E3%81%BE%E3%81%A7-%E6%A0%97%E5%8E%9F%E4%BC%B8%E4%B8%80/dp/4274227383/ref=asc_df_4274227383/?tag=jpgo-22&linkCode=df0&hvadid=454308455743&hvpos=&hvnetw=g&hvrand=2057290520710981828&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009775&hvtargid=pla-1301607246928&psc=1&th=1&psc=1)

こちらの書籍は何度も読み込みたいと思います。
今はこの４冊を軸にスキリングや学習を進めています。



### データサイエンスとビジネス関連の記事
以下のサイト様も非常に参考にさせていただいています

[DX MAGAZINE](https://dxmagazine.jp/tags/%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88)
[DX SQUARE](https://dx.ipa.go.jp/dx-news)




私が学習のため参考にさせていただいている書籍や情報サイトをまとめてみました。ほかの方と比べて情報量が少ないと思いますがご容赦ください、、、。

私と同じようにITエンジニア未経験から業界に飛び込みたい！というどなたか一人にでも参考になれば幸いです。
【Python】自作モジュールのimport時にパスが通らない問題を解決



## 環境
Python 3.8.10

## 初めに
研究で自作モジュールのimportが上手くいかなった時の記録をメモ。
ディレクトリ構成は以下。

![スクリーンショット 2023-02-10 16.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3131671/f450bb0f-50bc-0eed-c869-1bbaf053baac.png)

## 先に結論
自作モジュール自体が他の自作モジュールをimportする場合、実行したいファイルにおいて、利用する全ての自作モジュールのパス(実行したいファイルからの相対パス)を通す必要がある。

反対に、他の自作モジュールをimportしている自作モジュールでは、パスを通す必要はない。

## パスが通らない様子
再掲
![スクリーンショット 2023-02-10 16.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3131671/f450bb0f-50bc-0eed-c869-1bbaf053baac.png)


`clustering.ipynb`の最初のセルは以下のようになっていて、上位ディレクトリの`clustering_util.py`をimportしたい。
```python
import sys
sys.path.append("../")
import clustering_util as cutils

sys.path.append("../../utils/")
from util import * 
```

また、`clustering_util.py`のimportは以下のようになっていて、`util.py`をimportしたい。
```python
import sys
sys.path.append("../utils/")
from util import *
```

つまり、`clustering.ipynb`の最初のセルを実行すると、`clustering_util.py`が読み込まれ、`clustering_util.py`は`util.py`を読み込むことを期待している。

ただ、このまま`clustering.ipynb`の最初のセルを実行すると
```python
Cell In[1], line 13
---> 13 import clustering_util as cutils

File clustering_util.py:13
---> 13 from util import *
ModuleNotFoundError: No module named 'util'
```
となる。

## 原因
原因は至ってシンプルで、実行する`clustering.ipynb`の最初のセルにおいて、`util.py`にパスが通っていない状態で`clustering_util.py`が読み込まれ、`clustering_util.py`で`util.py`の読み込みに失敗していることである。

つまり、`clustering_util.py`では`util.py`に対してパスを通す必要はなく、実行したい`clustering.ipynb`においてパスを通してあげる必要がある。

## 解決策
`clustering.ipynb`の最初のセルにおいて、`clustering_util.py`をimportする前に`util.py`へのパスを通す。

```python
import sys
sys.path.append("../")
sys.path.append("../../utils/") # 先にパスを通す
import clustering_util as cutils
from util import * 
```

また、`clustering_util.py`では`util.py`に対してパスを通す必要はない。
```python
import sys
#sys.path.append("../utils/") 必要ない
from util import *
```

## 最後に
初めて書く記事で大変見づらいと思いますが、誰かの助けになれば幸いです。
また研究で困ったことがあれば書いていこうと思います。
Chromebook　自作コマンドの作成（XAMPP）

Chromebookも他のLinuxと同じだったので一応残しときます。

今回はxamppのコマンドを作ります。
```
cd /usr/bin
sudo nano xampp
```
中身はこんな感じ。$1が引数ですね。
```
#!/bin/sh
sudo /opt/lampp/lampp $1
```
権限の変更をお忘れなく。
```
sudo chmod 755 xampp
```

以下のコマンドで起動（停止）できます。
```
xampp start(or stop)
```

お疲れ様でございました。
IAMユーザーの作り方

# そもそもIAMとは
IAMとは、「認証」と「認可」の設定を行うことができるサービス。
「認証」と「認可」を正しく設定することで、AWSの利用者や、AWSのサービスがアクセスできる範囲を制御することができる。

# じゃあIAMユーザーとは
AWSリソースの操作をするユーザー。
IAMユーザーを使用して、AWSマネジメントコンソールにログインしたり、AWSの様々なサービスにアクセスできる。

# いよいよ作り方
#### ①「IAM」と検索して、クリック
![スクリーンショット 2023-02-10 12.32.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/a60efecb-a33a-517d-3fb7-8c5625925249.png)

#### ②画面左側の「ユーザー」をクリック
![スクリーンショット 2023-02-10 12.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/30d863cf-01e1-56c1-e17d-c25bf6587616.png)

#### ③「ユーザーを追加」をクリック
![スクリーンショット 2023-02-10 12.27.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/1f66182d-7db8-4371-0fff-7d0015ee514c.png)

#### ④ユーザーの詳細を指定して、「次へ」をクリック
![xtQmPldBMkt6aei1676012604_1676012883_auto_x2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/53284ea6-c8f6-aeac-3a4b-1e88d96558a2.jpeg)
コンソールパスワードに関しては、「自動生成されたパスワード」を選択していただいても大丈夫です！

#### ⑤許可を設定して、「次へ」をクリック
![kUgsegG5IF1cuQM1676006285_auto_x2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/b1710d56-b8bf-1f4a-ef1c-936903be021b.jpeg)
許可のオプションは、どれを選択していただいても大丈夫です！
今回は、「ポリシーを直接アタッチする」を選択していますが、その場合はアタッチしたいポリシーを選択してください！

#### ⑥確認をして、「ユーザーの作成」をクリック
![jKkRmoYIfhqz28W1676010445_1676010510_auto_x2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/c7bc4c03-ca45-ee69-eb52-894574bb0ac8.jpeg)
タグは、使用したい場合は作成してください！

#### ⑦パスワードを取得して、「ユーザーリストに戻る」をクリック
![スクリーンショット 2023-02-10 15.41.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/c6e7ad19-ce43-284f-dacb-5272a7b3a820.png)
「Eメールでのサインイン手順」をクリックすると、以下のような画面からメールを送信できます！
IAMユーザーを誰かと共有するときなどに使用します！
![スクリーンショット 2023-02-10 16.12.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/a93e2f3e-986c-6b8a-2354-810831afe503.png)
また、「.csvファイルをダウンロード」をクリックすると、サインインの詳細についての内容をダウンロードすることができます！
もし、パスワードを自動で生成されるように設定した場合は、csvをダウンロードするなどして、パスワードを確認してください！
パスワード情報を確認できる画面はここだけなので、注意してください！

#### ⑧IAMユーザーが作成されていることを確認
![スクリーンショット 2023-02-10 16.39.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871906/a3bff668-77e4-5e20-625f-249c7c76e85f.png)

# さいごに
今回は、IAMユーザーの作り方についてまとめてみました！
簡単なので、ぜひ作ってみてください！
YOLOv5 detect.py のコードを読んでみる

# はじめに
:::note warn
Python、機械学習ともに初心者の筆者が書いた記事です。
誤りがあるかもしれないのでご注意ください。
:::
　`yolo`の`train.py`によって生成した学習済みモデル（`best.pt`）を使って、画像認識をトリガーとしたプログラムを作成したくなったので、`detect.py`のコードリーディングから始めてみようと思いました。今回は、`yolov5`のコードを用います。

https://github.com/ultralytics/yolov5/blob/master/detect.py

　なんとなく、`yolo`のバージョンの中でコードが一番シンプルそうだなと思ったためです。また、Usageが最初に記述されており、使い方がわかりやすかったのも理由です。

# `yolov5/detect.py`の構成
　detect.pyは、2つの関数（`run`、`parse_opt`）とメイン関数（`main`）から成り立っています。`if __name__ == "__main__"`から見ていくと呼び出される順番は、
```python:
def main(opt):
    check_requirements(exclude=('tensorboard', 'thop'))
    run(**vars(opt))

if __name__ == "__main__":
    opt = parse_opt()
    main(opt)
```
　`parse_opt`⇒`main`⇒`run`となっています。
　その順にコードブロック内にコメントのカタチで説明を入れていきます。

### ※`if __name__ == "__main__"`について

https://www.sejuku.net/blog/60315

https://note.nkmk.me/python-if-name-main/


## `parse_opt`

```python:
def parse_opt():
    # 引数解析のためのArgumentParserインスタンスの生成
    parser = argparse.ArgumentParser()

    # 引数（オプション引数）の追加
    parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s.pt', help='model path or triton URL')
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    parser.add_argument('--vid-stride', type=int, default=1, help='video frame-rate stride')

    # .parse_args()で引数の解析結果を取得し、代入
    opt = parser.parse_args()
    
    # 三項演算子を使用している
    # オプション引数の imgsz について、
    # if len(opt.imgsz) == 1　がtrueならば opt.imgsz *= 2 、falseならば opt.imgsz *= 1 が実行される
    opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expand
    
    # opt に保持されているオプション引数の値をdict（「キー」と「値」の組）として出力
    print_args(vars(opt))
    return opt
```

:::note
`parse` ⇒「解析する」
`opt` ⇒ `option` ⇒「オプション」
`args` ⇒ `arg` ⇒ `argument` ⇒「引数」
:::

### 参考

https://qiita.com/kzkadc/items/e4fc7bc9c003de1eb6d0

https://qiita.com/taashi/items/400871fb13df476f42d2

https://gotutiyan.hatenablog.com/entry/2020/09/28/003910

https://note.nkmk.me/python-if-conditional-expressions/

## `main`
```python:
def main(opt):
    # check_requirementsは何やってるのかわからない
    check_requirements(exclude=('tensorboard', 'thop'))

    # opt に保持されているすべてのオプション引数の値をrunの引数として代入？
    # **var()の意味が分からない
    run(**vars(opt))
```
`**`の意味はこれ？↓

https://qiita.com/LouiS0616/items/1bbe0a9bb93054f6c380

# 終わりに
メイン関数の`check_requirements(...)`や、`**var(...)`の意味が調べてもわからなかったのが心残りです。おそらく、本記事の目的とはあまり関係ないでしょうが...
`run`だけ分けて次にやります。コード量が多すぎて疲れました。

[~~runへ続く~~]()