OmniAICreator/Qiita-1.07M huggingface dataset:
履歴テーブルの作成とトリガーでの更新 Oracle と SQL Server での方法

## はじめに
### 検証環境
Oracle 9i
SQL Server Management Studio v18.10

### サンプルテーブル
次のようなテーブルをこのテーマで利用するサンプルとします。
ここでは各列の型や長さについての情報は省略します。

テーブル名：ITEM
|列名|PK|
|:--|:--|
|ITEM_CODE|PK|
|ITEM_NAME|  |
|PRICE|  |

## 履歴テーブルの作成と自動附番設定
#### 履歴テーブルの作成
以下のように履歴テーブルを作成しておきます。

履歴テーブル名：ITEM_HISTORY
|列名|PK|備考|
|:--|:--|:--|
|HISTORY_KEY|PK|履歴テーブルのプライマリキー |
|ACTION_MODE|  |"INSERT"/"UPDATE"/"DELETE" |
|PK_ITEM_CODE|  |SAMPLEのPKに対応する。更新前のPK格納用 |
|ITEM_CODE|  |SAMPLE.ITEM_COCEに対応する |
|ITEM_NAME|  |SAMPLE.ITEM_NAMEに対応する |
|PRICE|  |SAMPLE.ITEM_PRICEに対応する  |

#### HISTORY_KEY の自動附番のために
##### Oracle の場合
HISTORY_KEY はOracle では
```
"HISTORY_KEY" NUMBER(38,0) DEFAULT ITEM_SEQUENCE.NEXTVAL NOT NULL ENABLE
```

のように、SEQUENCEの値をセットします。
SEQUENCE は例えば以下のように事前に作成しておきます。
```
CREATE SEQUENCE "ITEM_SEQUENCE" MINVALUE 1 MAXVALUE 999999999999999 INCREMENT BY 1 CACHE 20 NOORDER NOCYCLE
```

##### SQL Server の場合
SQL Server では
```
[HISTORY_KEY] [bigint] IDENTITY(1,1) NOT NULL,
```
のように IDENTITY の指定を行います。

## トリガーの作成
### Oracle の場合
```
CREATE OR REPLACE TRIGGER "ITEM_TRIGGER"
AFT ER INSERT OR UPDATE OR DELETE ON ITEM
FOR EACH ROW
BEGIN
  IF INSERTING THEN
    INSERT INTO ITEM_HISTORY(
      HISTORY_KEY,
      ACTION_MODE,
      PK_ITEM_CODE,
      ITEM_CODE,
      ITEM_NAME,
      PRICE
      )
    VALUES(
      ITEM_SEQUENCE.NEXTVAL,
      "INSERT",
      NULL,
      NEW:ITEM_CODE,
      NEW:ITEM_NAME,
      NEW:PRICE
      )
    );
  ELSIF UPDATING THEN
    INSERT INTO ITEM_HISTORY(
      HISTORY_KEY,
      ACTION_MODE,
      PK_ITEM_CODE,
      ITEM_CODE,
      ITEM_NAME,
      PRICE
      )
    VALUES(
      ITEM_SEQUENCE.NEXTVAL,
      "UPDATE",
      OLD:ITEM_CODE,
      NEW:ITEM_CODE,
      NEW:ITEM_NAME,
      NEW:PRICE
      )
    );
  ELSIF DELETING THEN
    INSERT INTO ITEM_HISTORY(
      HISTORY_KEY,
      ACTION_MODE,
      PK_ITEM_CODE,
      ITEM_CODE,
      ITEM_NAME,
      PRICE
      )
    VALUES(
      ITEM_SEQUENCE.NEXTVAL,
      "DELETE",
      OLD:ITEM_CODE,
      OLD:ITEM_CODE,
      OLD:ITEM_NAME,
      OLD:PRICE
      )
    );
  END IF;
END;
```

### SQL Server の場合
INSERT / UPDATE / DELETE それぞれに対応するトリガーを作成します。
#### INSERT 用のトリガー
```
CREATE TRIGGER [ITEM_TRIGGER1]
ON [ITEM]
AFTER INSERT
AS
BEGIN
  INSERT INTO ITEM_HISTORY(
    ACTION_MODE,
    ITEM_CODE,
    ITEM_NAME,
    PRICE
    )
  SELECT
    "INSERT",
    ITEM_CODE,
    ITEM_NAME,
    PRICE
  FROM inserted
  ORDER BY ITEM_CODE
END 
```

#### UPDATE 用のトリガー
```
CREATE TRIGGER [ITEM_TRIGGER2]
ON [ITEM]
AFTER UPDATE
AS
BEGIN
  DECLARE @PK_ITEM_CODE;
  SELECT @PK_ITEM_CODE = ITEM_CODE FROM deleted;

  INSERT INTO ITEM_HISTORY(
    ACTION_MODE,
    PK_ITEM_CODE,
    ITEM_CODE,
    ITEM_NAME,
    PRICE
    )
  SELECT
    "UPDATE",
    @PK_ITEM_CODE,
    ITEM_CODE,
    ITEM_NAME,
    PRICE
  FROM updated
  ORDER BY ITEM_CODE
END 
```

#### DELETE 用のトリガー
```
CREATE TRIGGER [ITEM_TRIGGER2]
ON [ITEM]
AFTER DELETE
AS
BEGIN
  INSERT INTO ITEM_HISTORY(
    ACTION_MODE,
    PK_ITEM_CODE,
    ITEM_CODE,
    ITEM_NAME,
    PRICE
    )
  SELECT
    "UPDATE",
    ITEM_CODE,
    ITEM_CODE,
    ITEM_NAME,
    PRICE
  FROM deleted
  ORDER BY ITEM_CODE
END 
```
【帳票】Stimulsoft Report.jsでのファイル保存（PDF Excel Wordなど）

# はじめに
Stimulsoft report.jsを使い、帳票をプレビューなしでPDF、Excel、Wordなどのファイルで保存する方法について整理します。
特に拡張モジュールは不要で、JavaScriptのコードを記述するだけで、実現できます。

# 前提
stimulsoft report.js

# PDFで保存する場合
最初に結論を書きます。PDF形式で保存するケースになります。
必要な処理は、
**①レポート(帳票)を指定したファイル形式でエキスポート**
**②エキスポートしたデータをダウンロード保存**
となります。

```html
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>レポートをPDFにエクスポート</title>
    <script src="../scripts/stimulsoft.reports.js" type="text/javascript"></script>
</head>
<body>
    レポートをPDFにエクスポート<br><br>
    <script type="text/javascript">
        // 新しいレポートインスタンスを作成
        var report = new Stimulsoft.Report.StiReport();
        // URLからレポートを読み込む
        report.loadFile("../reports/SimpleList.mrt");
        // レポートレンダリング後にボタンを活性化
        report.renderAsync(function () {
            document.getElementById("savePdf").disabled = false;
        });
        // レポートをPDF形式にエクスポートし、ファイルに保存
        function saveReportPdf() {
            // PDFにエクスポート
            report.exportDocumentAsync(function (pdfData) {
                // レポートファイル名を取得する
                var fileName = report.reportAlias;
                // データをファイルに保存
                Stimulsoft.System.StiObject.saveAs(pdfData, fileName + ".pdf", "application/pdf");
            }, Stimulsoft.Report.StiExportFormat.Pdf);
        }
    </script>
    <button id="savePdf" onclick="saveReportPdf()" disabled>PDFファイル保存</button><br>
    <br><br>
    <div id="htmlContainer"></div>
</body>
</html>
```

# その他のファイル出力
### ファイルデータのエキスポート
以下のコードで、StiExportFormatで指定したファイル形式(PDF/Word/Excel/PowerPoint/Html/PNG/GIF/CSVなど多数)のデータをコールバック関数に渡すことができます。
```javascript
report.exportDocumentAsync(callback(data), Stimulsoft.Report.StiExportFormat.Excel2007)
```
[StiExportFormat列挙型](https://admin.stimulsoft.com/documentation/classreference-js/enums/stimulsoft.report.stiexportformat.html)


| 定数 | 列挙名 | 
|---|------------|
|0| None|
|1| Pdf|
|2| Xps|
|3| HtmlTable|
|4| HtmlSpan|
|5| HtmlDiv|
|6| Rtf|
|7| RtfTable|
|8| RtfFrame|
|9| RtfWinWord|
|10| RtfTabbedText|
|11| Text|
|12| Excel|
|13| ExcelXml|
|14| Excel2007|
|15| Word2007|
|16| Xml|
|17| Csv|
|18| Dif|
|19| Sylk|
|20| Image|
|21| ImageGif|
|22| ImageBmp|
|23| ImagePng|
|24| ImageTiff|
|25| ImageJpeg|
|26| ImagePcx|
|27| ImageEmf|
|28| ImageSvg|
|29| ImageSvgz|
|30| Mht|
|31| Dbf|
|32| Html|
|33| Ods|
|34| Odt|
|35| Ppt2007|
|36| Html5|
|37| Data|
|38| Json|
|1000| Document|


### ファイルデータの保存
```javascript
Stimulsoft.System.StiObject.saveAs({ファイルデータ}, "ファイル名", "MIMEタイプ");
```

# まとめ
いかがだったでしょうか。Stimulsoft製品は、ファイルに出力に関して多くのファイルタイプをサポートしています。これにより様々な要件に対応することが可能です。
【Typescript】isを使って型を絞り込む

# はじめに
typescriptで開発をしていると複数の型の可能性があるものを絞り込むことは多々あると思います。
その際に使えるユーザー定義型ガードの使用方法を紹介します。
早速使用例をみてみましょう

# 使用例

以下のようなコードがあるとします。
一見、コンパイルが通りそうな気配がしますが、これだとエラーになります。
以下のような例だと引数`foo`は`unknown`型のままです。

```typescript
const isBird = (animal: unknown): boolean => {
  return animal === "bird";
};

const example = (foo: unknown) => {
  if (isBird(foo)) {
    console.log(foo.length); // Error： Object is of type 'unknown'.
  }
};

example('bird')
```

ではどうすればよいのか？ 
ここで登場するのが`is`です。

```typescript
const isBird = (animal: unknown): animal is string => {
  return animal === "bird";
};

const example = (foo: unknown) => {
  if (isBird(foo)) {
    console.log(foo.length); // 4
  }
};

example('bird')
```
以下の部分が変わったところですが、引数animalの型を`is`を使用して明示的に定義しています。
こうすることで、`foo`の型は`string`となり、ちゃんとコンパイルして`4`というlengthが取れていることがわかると思います。
```typescript
const isBird = (animal: unknown): animal is string => {
```

ではもっと実践的な使い方を見てみましょう。
`is`はオブジェクトの型を絞る時にも使用できます。
以下例のように`Teacher`型と`Student`型の2種類型があり、
`Teacher型`の時はこういう処理`Student型`の時はこういう処理のように条件分岐をさせたいとします。
```typescript
type Teacher = {
  name: string;
  age: number;
  role: string;
};

type Student = {
  name: string;
  age: number;
};
```

# 案①
`typeof`で判定する。
そもそもtypeofはプリミティブな型を判定するので、オブジェクトに対してtypeof使用すると`object`型と認識されてしまいます
```typescript
const getPersonRole = (person: Teacher | Student) => {
  if(typeof person === 'Teacher') { // Error: This condition will always return 'false' since the types '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Teacher"' have no overlap.
      console.log(person.role)
  } 
}
```

# 案②
if文を使用してプロパティの有無を確かめる
これだとコンパイル時にStudent型にはroleがないのでエラーが出ます。
```typescript
const getPersonRole = (person: Teacher | Student) => {
  if(!!person.role) { // Error: Property 'role' does not exist on type 'Student'.
     console.log(person.role)
  } 
}
```

# 案③
`is`を使用して型ガードする。
`isTeacher()`関数は引数personのroleが`undefined`か判定してbooleanを返しています。
`person is Teacher`で明示的にpersonはTeacher型であることを示しています。
こうすることで無事personの型で条件分岐することに成功しています。
```typescript
const isTeacher = (person: Teacher | Student): person is Teacher => {
  return (person as Teacher).role !== undefined
}

const getPersonRole = (person: Teacher | Student) => {
  if(isTeacher(person)) {
    console.log(person.role) // personがTeacer型として推論される
  } else {
    console.log(person.age) // personがStudent型として推論される
  }
}
```

# おわりに
複数の型の可能性がある時に結構使えそうですね。
Railsのトランザクションとその例外処理

## トランザクションとは
一言で表すと、``[ここからここまでワンセット]な処理単位``のこと。
例えば買い物するときに、

1.代金を払う
2.商品を受け取る

最低限この２つの動作を行うが、仮にこの動作のうち１つだけしかしなかった場合、商品を受け取って代金は払わずにいたとき、それは「買い物」ではなく「物を貰う」行為になる。

２つの動作が合わさって初めて買い物という処理（トランザクション）と言える。

## 基本構文
```rb
ActiveRecord::Base.transaction do
  # 例外が発生するかもしれない処理
end
  # 例外が発生しなかった場合の処理
rescue => e
  # 例外が発生した場合の処理
```
``transaction``ブロック内で例外が発生した場合、ブロック内で行われたデータベース更新処理が全てロールバックされる。

``transaction``を機能されるためには**例外を発生させる必要がある**。
つまり **``save!``や``create!``などを使う必要がある**。

>**例外処理とは**
プログラムがエラーで異常終了するケースでもプログラムを中断させず、別の処理に切り替えるプログラムが例外処理。

``rescue``は、エラーによって生成された例外オブジェクトを``「rescue => e」``で受け取り、``「e.message」``に格納されたエラー内容を表示する。

また``rescue``にはエラータイプを指定できる。通常のプログラムで発生する可能性の高い例外クラスの``StandardError``が多く適用される。

## 使い方
こでは``Payment（入金）``、``PaymentHistory（入金履歴）``の``Model``が存在するとする。入金があると入金履歴も作成する処理を見ていく。
```rb
def create
  ActiveRecord::Base.transaction do
    payment = Payment.new(amount: 1000)
    payment.save! # まだコミットされない

    payment_history = PaymentHistory.new(
      amount: 1000,
      payment_day: Time.zone.now.strftime('%Y/%m/%d/%H時%M分%S秒')
    )
    payment_history.save! # まだコミットされない
  end
  true
  # transactionブロックを正常に抜けるとコミットされる
rescue StandardError
  false
end
```

## 参考記事
[トランザクション](https://wa3.i-3-i.info/word142.html)
[Rubyの例外処理とは？rescueの使い方を中心に徹底解説](https://style.potepan.com/articles/30566.html)
Laravel 特定の子ビューでのみ使用するJSファイルのインポート方法

# 目的
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607418/c7d3d005-8843-1702-8da5-74ffd0690da9.png)
共通レイアウト使用時に、子ビューの1つであるfuga.blade.phpのみでfuga.jsを読み込む。

# やり方
1．親ビューにスタックを定義する
```layout.blade.php
<head>
  @stack('scripts')
<head>
```
2．子ビューで親ビューのスタックにプッシュする
```fuga.blade.php
@push('scripts')
  <script src="{{ mix('js/fuga.js') }}" defer></script>
@endpush
```

# 参考
https://readouble.com/laravel/8.x/ja/blade.html#:~:text=message%20%7D%7D%3C/div%3E%0A%40enderror-,%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF,-Blade%E3%82%92%E4%BD%BF%E7%94%A8
Docker: VSCode上で完結

# Docker操作をVSCode上で完結させる環境構築

## やること
- Dockerのインストール（参考記事参照）

https://docs.docker.jp/docker-for-windows/install.html
  
https://qiita.com/bezeklik/items/a6a7335acaec12edda45

- VSCodeのインストール（参考記事参照）

https://miya-system-works.com/blog/detail/vscode-install/

- VSCodeでの拡張機能および設定（本記事で説明していく）

- 使いたいDockerfileの準備

https://qiita.com/Yuya-Shimizu/items/f0ace02062cc13e9d54b

※ここでは，VSCodeでの設定のみを記述する．

（理由：DockerのインストールもVSCodeのインストールも記述するほどでもなく，参考記事に従えばできる．）

## VSCodeでの拡張機能および設定
### Docker操作のために追加する拡張機能
- Docker
    - Dockerのイメージなどを管理できる

![Docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/75f84fb5-5da7-747c-6247-68f556cf0410.png)

- Remote Container
    - 起動させたコンテナを遠隔操作（アクセス）できる

![Remote_container.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/72efcbe6-173a-16ee-cb5f-21588b977476.png)

これらが完了すると，左下に><のようなマークが出現する

![mark.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/98c6441e-ea07-eade-2bf6-7c786f868ab0.jpeg)

### コンテナへのアクセス手順
1. VSCodeを起動
1. Dockerのリポジトリ（フォルダ）をVSCode上に開く
1. VSCodeの左下にある><マークをクリック（以下のような状態になる）

![reopen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/6cce369b-6c32-950e-1b06-b64fd99b8f0e.jpeg) 

4.reopen in Containerを選択

初めてDockerをVSCodeで扱う場合のみ以下のようにして設定していく必要がある．

```
From a predefined container configuration definition...
```
これを選択．

```
Show All Definitions...
```
を選択してすべての候補を参照

```
Docker from Docker
```
たくさんの候補の中からこれを選択．

```
Install zsh
```
を外す．ここの設定は個々で構わないが，個人的には特にzshが必要とは思わない．

あとは，OKを押すだけ．

### 細かな設定
先ほどまでの設定でとりあえず，DockerをVSCode上で扱うことができるようにはなったが，せっかくVSCodeを使う以上，便利な拡張機能をDocker上でも使いたい．

- 注意
    - ホストでインストールしている拡張機能すべてがDocker上での拡張機能に反映される訳ではない

    - Dockerは立ち上げるたびに，拡張機能がデフォルト設定に戻されて，毎回インストールが必要となる

これらの面倒さをなくすために，先ほどの設定によって生成された設定ファイルの中にあらかじめ，起動時にインストールしておく拡張機能を記述しておく．

- 設定ファイルは``.devcontainer``フォルダの``devcontainer.json``ファイルである．

![json.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/d3e7e163-843b-1373-47bb-1294e88c1a55.jpeg)

赤で示したところに，インストールしておきたい拡張機能のIDを記述する．IDは拡張機能インストールする画面で確認できる．

![Python.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/d3f9b794-76b8-f9b4-177f-ec1cd1d24f0c.jpeg)

赤枠で示したところがIDである．VSCodeを日本語化しているとIDではなく識別子と表記されている．

例えば，Pythonの拡張機能をインストールしておくとすると，以下のように追加する．

```json
"extensions": [
    "ms-python.python"
]
```

この変更を加えると，リビルドが必要となる．このリビルドはDockerfileのビルドもおこなうものであるため，Dockerfile変更時には使うことになる．

リビルドについてもクリック作業でできる．

![rebuild.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/9e3643b1-5cfa-dbff-596f-e2a10bb356f7.jpeg)

### 動作テスト
前回の記事でもテストしたが，ここでもRviz（ROS1）の起動を動作テストとする．

<iframe width="560" height="315" src="https://www.youtube.com/embed/zz6ZQO_3nF0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Rvizもうまく起動している．

## 感想
前まで，コードはVSCodeで書いて，Windows Terminal上でDocker起動させて動かしていたが，これでVSCode上ですべてが完結できるということで，非常に便利になった．VSCodeのGUIを用いてクリックでの作業ができるだけでなく，今までのようにVSCode上でのターミナルを用いてターミナル操作もできるということで環境が一層よくなったと思う．最後では，ちゃんとRvizを起動できることも確認でき，ここからの開発がよりスムーズになってくれると思っている．
React で利用可能なSVGファイルを Inkscape で作成する

# はじめに
React を利用する際に綺麗な画像を載せるためベクター形式のsvgファイルを利用する場合があると思います．画像作成ソフトの Inkscape を用いて作成したsvgファイルそのままだと React で利用できないため，利用可能は出力方法について書いておきます．

# やりたいこと
React で利用可能なsvgファイルを Inkscape によって作成する．今回は React でプロジェクト作成した際に生成される logo.svg に上書きし，動作を確認する．

# 手順
1. Inkscape によって通常通り画像を作成する．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/be3e00f8-917b-5b87-0ccd-bf20b809eb7e.png)
2. 名前をつけて保存の際に最適化svgを利用する．
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/da5cd794-5588-891c-7c7b-bc0f53e0ed93.png)
3. 出力オプションを設定する． 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/081b62c6-ecb1-2996-d917-051aa27f549d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/1c277323-19e9-8398-8753-f7a718d0ed08.png)
4. 実行する．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/1b49dad3-aad2-cde7-d980-6189b5514b86.png)

# 参考
https://stackoverflow.com/questions/62531190/create-icon-with-inkscape-and-import-it-with-material-ui-svgicon
ClickOnce逆引きメモ

必要に迫られた`ClickOnce`の逆引きメモです。

## ClickOnceにてインストールしたアプリケーションが「構成システムを初期化できませんでした」とメッセージダイアログが表示されて起動しなくなる問題

この問題は今まで正常に起動していたアプリケーションでも、ある時突然発生します。
また、対策として該当アプリケーションを再インストールしても同じ現象が発生します。

## 環境
* Windows 10 Pro 21H2

## 原因
* 直接の因子としてしては`user.config`ファイルが破損いてる場合が多いです。

## 対応策
* `user.config`を削除するか破損していないバックアップファイル等で上書きをすると正常に起動します。
* インストールされた`user.config`は環境に依存しますが`C:\Users\xxx\AppData\Local\Apps\x.x\Data\xxx.xxx\xxx.xxx\xxx..xxx_xxx_xxx.xxx_xxx\Data\x.x.x.x\`、`C:\Users\xxx\AppData\Local\xxx\xxx.xxx_xxx_xxx\x.x.x.x\`等のディレクトリに格納される事が多いです。

## 補足事項
* `user.config`ファイル破損以外の原因については明確な対応策がなく`.net framework`の再インストール、`システムスキャン`の実行等を試すしか有りません。
* 障害の遠因としては、ハードウェア障害、システムクラッシュ、ウィルス等でOSが不安定になっているため発生するようです。
* この症状が発生する端末は対策を行ったとしても再発する可能性が高く、継続使用は避けた方が無難です。

## 参考情報
[「構成システムを初期化できませんでした」とエラーが出てアプリが起動しなくなった。 - trapemiyaの日記](https://trapemiya.hatenablog.com/entry/20160127/1453885229)
MACでpyenvとvenvを使ってPython仮想環境構築

# この記事を書いた目的

自分は春から新社会人になる為, 会社で配布されるMacbookに対して, 
**開発環境を整えるのに時間を割いてしまうのではないか？**
と思ったのがきっかけでした。

**自分で新しく購入したMacbbok**, **会社で配布されたMacbook**を用いて, **Macの開発環境を整えてみたい**と思った方を想定しながら,**簡単**・**高速**・**再現性**の三つを意識して開発環境の手順を記していきます。


# 1:Homebrewのインストール

Homebrewは**Macのパッケージ管理ツール**です。
Homebrewを使うことで、**ターミナルからコマンドを実行するだけ**で、パッケージのインストールやアンインストールが簡単に行えます。

例えば、Homebrewを使わずにMacにPythonをインストールしようとすると, 以下の面倒な3手順が必要となる。
①Pythonの公式サイトにアクセス
②Pythonをダウンロード
③ダウンロードファイルを起動してインストーラに従ってインストールする


それがHomebrewを使うと、**たった１行のコマンドを実行**するだけでインストールできる！

## インストール方法
ターミナルを開いて, 以下のコマンドをコピペして実行。
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

## インストール確認方法
以下コマンドを実行することで, Homebrewがインストールされていることを確認。
(※バージョンは違っていても問題ありません。)
```
$ brew -v
Homebrew 3.2.14
```

## アップデート方法(おまけ)
Homebrew自体を最新化。
最新化することで、利用できるパッケージが増えたり、パッケージの最新バージョンが使用できたりします。

```
インストール済みのパッケージをすべて最新化する
$ brew upgrade

インストール済みの特定のパッケージのみ最新化する
$ brew upgrade パッケージ名
```

## インストール済みのパッケージ一覧の表示(おまけ)
これまでにインストールしたパッケージの一覧を表示します。
```
$ brew list
```

## パッケージの検索(おまけ)
Homebrewで使えるパッケージの検索を行います。
引数のパッケージ名を省略すると、Homebrewで使用できる全パッケージが表示されます。
```
Homebrewで使用できるパッケージを表示する
$ brew search

Homebrewで使用できるパッケージを表示する
$ brew search パッケージ名
```

# 2:pyenvのインストール
**異なるバージョンのPythonを簡単かつ高速にインストールする為のパッケージ**。

## インストール方法

```
$ brew install pyenv
```

## インストール確認方法

```
$ pyenv -v
pyenv 1.2.21
```

## 設定方法(このままではpyenvを簡単に扱えない)

### 手順1(シェルの確認)
自分のMacbbokの**シェルの種類**を確認。

```
echo $SHELL
```
上の実行結果が
・/bin/bashなら**bash**
・/bin/zshなら**zsh**
であることが分かります。

### 手順2(環境変数設定)

手順１で**bash**判定された方は以下のコードを１行ずつコピペして, 実行してください。
```
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
```
```
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
```
```
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
```
```
変数を反映
source ~/.bash_profile
```

手順１で**zsh**判定された方は以下のコードを１行ずつコピペして, 実行してください。
```
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
```
```
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
```
```
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
```



```
変数を反映
source ~/.zshrc
```

# 3:Pythonのインストール

**様々なバージョンのPythonをインストールする。**

## インストールできるPythonのバージョンリストを表示
```
pyenv install --list
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/56fae54c-ebfd-1c6d-b603-f950b7b19764.png)
現時点で最新のバージョンは3.10.3であることが分かります。
(※3.11.0a6や3.11.devは一部バグが含まれている可能性があるため, 指定していない。)

## 指定のバージョンをインストール
```
pyenv install 3.10.3
```

## インストール済みのバージョン確認
```
pyenv versions
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449715/a45f8a0e-5b5e-dcd9-d165-2e14f10ce82b.png)

## 指定したバージョンに変更
```
pyenv global 3.10.3
```

# 4:仮想環境の作成

仮想環境を作成しないと…
OSデフォルトのPythonは**パッケージ管理などで使っているのでユーザーの都合で変更できない**。
OSデフォルトのPythonは**古いバージョン**を使っている場合が多く、開発に使うとトラブルのもと。
といった問題が生じる。

## 仮想環境作成

```
python -m venv 仮想環境名
```

## 仮想環境内部に入る

```
source 仮想環境名/bin/activate
```

## 仮想環境から脱出

```
deactivate
```

## 仮想環境削除

```
rm -rf 仮想環境名
```

# おわり
以上で, Pythonのセットアップから仮想環境作成まで完了しました。
ぜひ, 個人・チームで開発案件に携わるときは, 仮想環境を作成の元行ってみてください。
アジャイル検定Lv1合格しました

先日アジャイル検定Lv1に合格したので備忘録として。

アジャイル検定は正式名称を「アジャイルソフトウェア開発技術者検定試験」といい
アジャイル開発のスキルを図る検定の通称です。
公式HP http://agilecert.org/

# はじめに
- 受験、勉強前の私の知識レベル
インフラ構築歴 6年
アプリ開発歴 無し
アジャイル開発歴 もちろん無し

- 受験の背景
社内環境：ウォーターフォール型開発で行ってきた社内の開発業務をアジャイル的開発に転換させていきたいという会社の意向
個人環境：アプリ開発SEとの関わりが多くなってき、今保持しているインフラ知識のみで対応が難しくなってきている

# 試験概要
試験時間 60分
4択問題
合格点 80/100点以上 (80%以上)
受験料 10,000円(税別) クレジットカード支払いでは手数料無しで税込み11,000円でした


出題範囲
| 大項目 | 中項目 |
|:--|:--|
|  アジャイル開発に対する基礎知識	 |  アジャイル・マニフェスト、アジャイル原則 |
|  開発チームの運営 |   コミュニケーション、自律性と協調、ルール、振り返り|
|  アジャイル開発プロジェクト管理 |  会議体、ロール（役割）、反復、ドキュメント、チーム編成、計画、見積り、ビジョン、品質 |
|  アジャイル開発の技能 | ペアプログラミング、リファクタリング、常時結合、テスト駆動開発  |

# 勉強方法
- アジャイル検定 公式テキスト(アジャイル検定のHPにAmazonリンクありました)
　勉強時間 8時間程度 (テキスト1周＋章末問題復習)

※隙間時間での受験勉強＋弾丸受験だったため合格点ギリギリでの合格でした。

# 受験した感想
アジャイルの基本的な考え方や、プロジェクトの進め方を学ぶことができた。
ただ、理想論なので、「現実的にこれ難しいのでは、、」と思う箇所もところどころ。

これからアジャイル開発をやる人や関わる人にはもってこいの資格だと思うので機会があればぜひ。
Javascrioptのvar、let、const【個人的なお勉強アウトプット】

いずれも変数や定数を宣言するときにつかうもの。
varは古株。letとconstはECMASScript2015から。
ECMAScript2015はJavascriptの標準仕様。
国際団体で標準かされたうえ、ブラウザで広く採用されている。

## 違い
- 再代入、再宣言が可能か
- スコープ

### 再代入、再宣言が可能か
varは再代入、再宣言が可能
letは再代入が可能
constは宣言したら変更不可

### スコープ
varはブロック外でも参照可能
let、constはブロック外では参照不可

## 推奨されている使い方
変数の内容が変わったり、ブロック外にいったりきたりするのは可読性を下げる。
不具合も生みやすくなる。
なので、できるかぎりconstをつかったほうがよい。
ただし、for文などで変数の中身を変えていくものはletで。
varはつかわなくてもよい。
数式を使った時にGMTになるのをローカルタイムに変更したい

Flowでも問題だけど、数式で使えないかな？ <--- 最終的には数式で逃げたような感じです。

[Simple question, should be easy for you geniuses! Displaying Date/Time in Flow](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000DwWXlSAN)


```
CASE( MOD(  DATEVALUE({!YOURDATETIMEFIELD__c} ) - DATE(1900, 1, 7), 7), 
0, "Sunday", 
1, "Monday", 
2, "Tuesday", 
3, "Wednesday", 
4, "Thursday", 
5, "Friday", 
6, "Saturday", 
"Error") 
& ", " &  
CASE(MONTH(DATEVALUE({!YOURDATETIMEFIELD__c})),  
1, "January",  
2, "February",  
3, "March",  
4, "April",  
5, "May",  
6, "June",  
7, "July",  
8, "August",  
9, "September",  
10, "October",  
11, "November",  
12, "December",  
"None"  )
& " " &  

TEXT(DAY( DATEVALUE({!YOURDATETIMEFIELD__c}))) 
& ", " & 
TEXT(YEAR(DATEVALUE({!YOURDATETIMEFIELD__c})))  
& " at " & 
TEXT(IF( OR( VALUE( MID( TEXT( {!YOURDATETIMEFIELD__c} 

+ $Setup.Custom_Settings__c.Time_Zone_GMT__c/24 ), 12, 2 ) ) = 0, VALUE( MID( TEXT( {!YOURDATETIMEFIELD__c} +  $Setup.Custom_Settings__c.Time_Zone_GMT__c/24  ), 12, 2 ) ) = 12 ), 12, VALUE( MID( TEXT( {!YOURDATETIMEFIELD__c}  + $Setup.Custom_Settings__c.Time_Zone_GMT__c/24 ), 12, 2 ) ) - IF( VALUE( MID( TEXT( {!YOURDATETIMEFIELD__c} 

+ $Setup.Custom_Settings__c.Time_Zone_GMT__c/24 ), 12, 2 ) ) < 12, 0, 12 ) )) & ":" & MID( TEXT(  {!YOURDATETIMEFIELD__c} 

+ $Setup.Custom_Settings__c.Time_Zone_GMT__c/24 ), 15, 2 ) & " " & IF( VALUE( MID( TEXT(  {!YOURDATETIMEFIELD__c} 

+ $Setup.Custom_Settings__c.Time_Zone_GMT__c/24), 12, 2 ) ) < 12, "am", "pm" )

```
フロー式に関する考慮事項

[Answersで回答する時に使う情報のまとめに戻る](https://qiita.com/Keiji_otsubo/items/9e6e0e946826133eddc7)
[関数一覧に戻る](https://qiita.com/Keiji_otsubo/items/05c918c17a2395b3c17e)

# フロー式ではサポートされていない関数の一覧

[Use ISCHANGED, ISNEW, and PRIORVALUE in Record-Triggered Flow Formulas](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_builder_record_triggered_flow_formula_functions.htm&type=5&release=232)

GETRECORDIDS
IMAGE
INCLUDE
 ~~ISCHANGED~~
 ~~ISNEW~~
PARENTGROUPVAL
PREVGROUPVAL
 ~~PRIORVALUE~~
REQUIRE SCRIPT
TIMENOW
TIMEVALUE
VLOOKUP

フローでは、CONTAINS 関数は括弧内のすべての文字をチェックします。クロスオブジェクトフィールド参照の場合CONTAINS、Salesforceの他の部分と同じように機能します。参照の最初の250文字のみをチェックします。
これが例です。varContract 契約レコードの値を含むレコード変数を参照します。この数式は、最初の250文字のみをチェックします。

```
CONTAINS({!varContract.Account.Description}, "description")
```

この数式式は、フィールド内のすべての文字をチェックします。

```
CONTAINS({!varContract.Description}, "description")
```

SUBSTITUTEは使える
[フロー式は文字列のフォーマットに役立ちます](https://salesforce.stackexchange.com/questions/301400/flow-formula-help-to-format-string)



# 数式のフローデータ

+ 数式でのグローバル変数への参照は検証されません。
+ 数式でプラットフォームイベントを参照するには、イベントデータをPause要素のレコード変数に渡します。次に、そのレコード変数の適切なフィールドを参照します。


# 注意点

+ フロー式には、**最大3,900文字**を含めることができます。
+ 数式を貼り付ける場合、アポストロフィーと引用符がストレート (") であり、カーリー (‘’) ではないことを確認してください。ストレートでない場合、フローを保存するときに構文エラーが発生します。

# エラー

式の評価時に次のようなエラーが発生した場合、数式は null を返します。
数式から返される値がそのデータ型と一致しない。
サポートされない関数が数式に含まれている。
たとえば、数式リソースのデータ型が数値である場合、出力は数値である必要があります。

フローに無効な数式リソースが含まれていると、フローを有効化できません。[表示テキスト] 画面コンポーネントに無効な数式リソースが含まれていると、実行時にフローに空の文字列が表示されます。

-----------------------------------
+ [フロー式に関する考慮事項(使えない関数がある)](https://help.salesforce.com/s/articleView?id=sf.flow_considerations_design_formulas.htm&type=5)


# サンプル、質問&回答

+ [Formula for Address to field (flow record trigger)](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FTbS3SAL)
Laravelのヘルパとは【個人的なお勉強アウトプット】

laravel内で使い回せる関数
特定のページのみで使うものであればコントローラ内で定義すれば問題ない。
だけど、処理を他の場所でも使い回す場合は、ヘルパとして登録していれば関数名を指定するだけでその処理を実行できるようになる。

## 参考記事
https://prograshi.com/framework/laravel/helper/
使用しているAPIバージョンの検索について

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)


+ [質問](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FxUYiSAN)
+ [Is the a tool available to determine this? ACTION REQUIRED: Update Unsupported Legacy API Version](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000KduQJ)

API 合計使用量イベントには、(API バージョン v30.0 以下の) Platform SOAP API、Platform REST API、Bulk API 要求に関する詳細が含まれています。
以下のAPIの項目にAPI_VERSIONというフィールドがありますね。これが使えるかもしれないです。
 

[API 合計使用量](https://developer.salesforce.com/docs/atlas.ja-jp.236.0.api.meta/api/sforce_api_objects_eventlogfile_apitotalusage.htm)


# ApexクラスだとSOQLで検索できそう

[How can I find the current API Version in the salesforce](https://developer.salesforce.com/forums/?id=9062I000000INCiQAO)

Apex class API version:

```
SELECT Name, ApiVersion FROM ApexClass
```


Lightning Component API version:

```
SELECT DeveloperName, ApiVersion FROM AuraDefinitionBundle
```

# データローダのバージョン

+ [使用されているデータローダのバージョンを調べる方法](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000E9mlZ)


データローダのユーザを特定する方法、ユーザが使用しているデータローダの

バージョンを確認する方法を教えて頂きましたので、共有致します。

--------------------------------------------------

【手順】

(1) ログイン履歴によるデータローダ使用ユーザの特定

　1. [設定] | [ID] | [ログイン履歴] をクリック

　2. ダウンロードオプションで以下の設定をして [今すぐダウンロード] をクリック

　　- ファイルの種類：CSV ファイル

　　- ファイルの内容：すべてのログイン

　3. ダウンロードした CSV ファイルを確認

　　→[アプリケーション] 列に「Dataloader Partner」と表示されているレコードの

　　　[ユーザ名] 列を確認することで、データローダを使用しているユーザを特定することができます。

 

(2) データローダ起動画面のスクリーンショットの収集

　データローダを起動すると、起動画面のウィンドウ上部に「Welcome to Data Loader XX.X.X」と

示されております。

　この「XX.X.X」がデータローダのバージョン情報です。

　よって、データローダ起動画面のスクリーンショットを (1) で特定したユーザから収集することで、

　どのユーザがどのバージョンのデータローダを使用しているか確認いただくことができます。

--------------------------------------------------

 

補足になりますが、データローダのバージョンがv53.0.0以降であれば

Summer'23で予定されているAPIバージョン30までの廃止の影響は受けないとのことでした。
Docker使用時にbyebugのブレークポイントをスルーしてしまう問題の解決方法

# 環境
OS：macOS Big Sur
Docker：version 20.10.12
Ruby：2.7.3
Rails：6.1.3.2

# 発生した問題
①Docker使用中にbyebugで設定したブレークポイントをスルーしてしまう
下記のように=>マークは付くがブレークポイントで止まらず、コマンド入力できない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428148/440339a3-d4db-3a68-2d83-1d2670f4d674.png)

②Dockerのコンテナからデタッチできない

# 原因
①、②のどちらもdockerの設定で標準入出力をコンテナに結びつけていなかったことが原因

# 解決方法
下記のようにdocker-compose.ymlファイルにstdin_open: true, tty: trueを追加し、Dockerをビルドし直して解決。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428148/996146ac-fbd2-c09b-2a8c-2e7af4cde84b.png)


# 参考記事
以下の記事を参考にさせていただきました。
- [docker-compose.yml個人的Tips集](https://qiita.com/yuki_0920/items/dc3f32667d004979cc5a)
- [DockerでRailsの開発環境を構築する](https://dev.classmethod.jp/articles/ruby-on-rails-on-docker/)
【メモ】ディープラーニングを直感的にイメージするポイント

# メモの趣旨
AIの主にディープラーニングのイメージを掴むのに必要と思ったポイントをメモ。

# 基本アイデア
あくまで基本アイデアとして理解。
以下、データから予測する（関係性を導く）ことを例にする。

## 古典的な予測とモデル
モデルとは数値計算で予測するためのフォーマット。
身長から体重を予測する場合、
⇒　身長と体重が比例しているだろう
⇒　まずは、１次関数（y=ax+b）をモデルとして選択するよね
⇒　係数調整すると、身長引く体重が100くらいとなる係数が一番誤差が少ないぞ
⇒　改良するなら、完全な直線関係じゃないから高次の関数にするかな～（モデルの限界１）
⇒　頑張ったけどやっぱ身長だけじゃアカンな～。年齢も変数に加えようか（モデルの限界２）
⇒　ターゲットごとのモデル探しキツいし、汎用的なモデルがないとやってられんわ！

人が思いつくモデルなんで表現できることはたかが知れ、本質はもっと複雑なので絶対こういった流れになる。

## DNN
より表現の幅が多いディープニューラルネットワーク（DNN）を使いたい。
構成は係数と活性化関数をもつセルがたくさん繋がっているだけ。

活性化関数が謎の存在だが、表現できることを増やしたいと思えば必要に思える。
⇒　活性化関数は非線形の関数という決まり
⇒　じゃあセルと共にこれだけ並ぶとめっちゃ複雑な計算になるね
⇒　複雑だからこそ、係数の調整次第で色々近似的に表現できるのでは？
　　（表現できるかもって思っているに過ぎないけど；）
※本来は線形結合を防ぐ意味もある

このあたりがブレイクスルーっぽい。
モデルとしては汎用性を狙えそうな雰囲気が出る。

## 学習
DNNで表現の幅は増えるのだろうが、調整（学習）すれば、、という前提がある。

⇒　DNNモデルをチューニングして予測してください
⇒　パラメータ多すぎて大変、あたりをつけることさえ無理っす
⇒　コンピュータで力づくでやらせようか
⇒　なんかやり方によって変な値に調整されてしまってハマってしまう
⇒　色々テクニックいるからそこも研究せな
※テクニックとは学習率とか、勾配法とかの界隈

学習することで様々な関係性を表現、予測していく → ＡＩ!!
でも本質は力づくでパラメータ探索してるだけ

## DNN構成、特徴量
＞オートエンコーダの例

⇒　ネットワークの中間が細くなり、最後に元の画像サイズのなっている
⇒　途中で情報量を減らしているのに入力画像を復元している
⇒　画像の大事な部分（特徴）は保持していたから復元できたのでは？
⇒　じゃあ最も少なくなったデータが“特徴”っていえそう

復元率を上げるようにオートエンコーダを学習するイコール
・オートエンコーダの前半は特徴を抽出するように係数調整される
・〃の後半は特徴から画像を復元するように係数調整される
ということになる。

オートエンコーダは異常検知にも使えるし、非常に分かりやすい好例に思える。

## 全体像
AIという言葉で煙にまかれがちだが、全体像をこのようにイメージする。

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝～∞　自然界の法則による事象
＝＝＝＝＝＝＝＝＝＝＝＝＝＝　　　　　　　　DNNで近似的に表現できるポテンシャル
＝＝＝＝＝＝＝　　　　　　　　　　　　　　　DNNの構成によってポテンシャル引き出せない
＝＝＝　　　　　　　　　　　　　　　　　　　学習方法やデータによってポテンシャル引き出せない

理想と現実はあり、なんでも予測するのはさすがに無理。
今も研究されているが、この手法に限界はあるのでは。
【Rails】bcryptを使ったパスワードのハッシュ化と認証


## やりたいこと

bcryptを使って、新規ユーザー登録時におけるパスワードのハッシュ化と、ログイン時におけるパスワードの認証を実現したい。

## 前提

・パスワードは平文で保存するのはNG。
・セキュリティ上、ハッシュ値に変換して保存する。

そもそも暗号化とハッシュ化の違いを理解できていなかったのでメモります。
その違いとは、**不可逆性があるかどうか。**

**暗号化は不可逆性がある。つまり、暗号化した後に元に戻せる。**
**ハッシュ化は不可逆性がない。つまり、一度ハッシュ化すると元に戻せない。**

## 方法

パスワードの生成には`BCrypt::Password.create`
パスワードの認証には`BCrypt::Password.new`
を利用する

## 新規ユーザー登録でやりたいこと

・入力した生パスワードをハッシュ化して保存する。
Railsには以下のGemがデフォルトで入っているのでそれを利用する。

```ruby
gem 'bcrypt', '~> 3.1.7'
```

パスワードの生成には`BCrypt::Password.create`を利用する。
以下のように使うと、入力値がハッシュ化された様子がわかる。

```ruby
使い方
BCrypt::Password.create('入力した生パスワード')

使用例
> hashed_password = BCrypt::Password.create('password')
=> "$2a$12$jA9fyFy1qfh379BEfaJM2uGPe9EnqrEZnREv1iaiX8nyCmQz69ERK"
```


## ログイン時にやりたいこと

パスワードの認証には`BCrypt::Password.new`を利用する。
「DBに保存されているハッシュ化されたパスワード」と
「打ち込んだパスワードをハッシュ化したもの」を比較（認証）する。

以下のように使う
```ruby
使い方
> BCrypt::Password.new(DBのハッシュ化されたパスワード) == '打ち込んだ生パスワード'

使用例
> BCrypt::Password.new(hashed_password) == 'password'
=> true
```
これにはエイリアス`is_password?()`が存在し、以下の書き方もできる。
```ruby
> BCrypt::Password.new(hashed_password).is_password?('password')
=> true
```

冒頭でも書いた通り、ハッシュ化されたパスワードは復元できないので、
入力値をハッシュ化させて比較する方法になります。


## 注意
面白いのは左辺と右辺を逆にした場合で結果が違うということ。（左右逆にすると通らない）
必ず、上記の順番で記述することがポイント

```ruby
> 'password' == BCrypt::Password.new(hashed_password)
=> false
```

なぜなら、

`BCrypt::Password.new(hashed_password) ==`の`==`はメソッドとして定義されているから。

BCryptのソースコードを見ると以下の記述があります。
入力した、パスワードをハッシュ化させて、ソルト（ランダムな文字列）を付加しています。

```ruby
def ==(secret)
  super(BCrypt::Engine.hash_secret(secret, @salt))
end
alias_method :is_password?, :==
```

## 認証の仕組みはどうやって行うのか

パスワードのハッシュ化はハッシュ関数を通すことで実現されています。

ハッシュ関数は「同じ値をこの関数に通すと同じハッシュ値を得られる」という性質を持ちます。つまり、**ハッシュ値に対してパスワードの総当たり攻撃をかけると力技で元のパスワードを特定できてしまう。**

そこで、その対策としてハッシュ値に対し、ソルトと言われるランダムな文字列を付加して、ハッシュ化パスワードとしてDBに保存される仕組みが生まれました。

認証の際には、DBのハッシュ化パスワードの中からソルトの部分を取り出し、入力した生パスワードのハッシュ値に連結させます。そして、DB上のハッシュ化パスワードと付き合わせる仕組みだそうです。

以下でわかりやすく解説されていました。
****[bcrypt-rubyについて調べたメモ](https://memorandums.hatenablog.com/entry/2018/10/12/001817)****



## 備考

パスワードの再設定が必要な理由は、パスワードの不可逆性にあります。

「あなたのパスワードは〇〇です。」と返してくれたらいいのになぁと思っていましたが、それは難しいそうです。復元できないからこそ再設定という機能が必要になったと・・・

## 参考

****[「ハッシュ化とは？」今さら聞けない！基本の『キ』](https://eset-info.canon-its.jp/malware_info/special/detail/211013.html)****

****[　bcrypt-rubyについて調べたメモ](https://memorandums.hatenablog.com/entry/2018/10/12/001817)****

****[【bcrypt】ユーザーパスワードを本当に安全に保存する方法](https://liginc.co.jp/377191)****
Windows PowerShellでgitのブランチを表示して、変更があったらブランチ名の色を変えるスクリプト

# 概要
PowerShellでgit操作する際に、ブランチ名や変更状況等をビジュアライズしたいので、スクリプトを作成しましたー

# 設定
Documents\WindowsPowerShellに配置するMicrosoft.PowerSHell_profile.ps1に下記のスクリプトを配置する。

[こちらの記事](https://kojinjigyou.org/24625/) を参考に改造。


```Microsoft.PowerSHell_profile.ps1
function prompt {
  $branch = ""
  $git_cahnge_count = 0
  $git_staged_count = 0

  if (git branch) {
    (git branch | select-string "^\*").ToString() | set-variable -name branch
    $branch = $branch.trim() -replace "^\* *", ""
    git diff --shortstat | %{ echo $_.Trim().Substring(0, $_.Trim().indexof(" ")) } | set-variable -name git_cahnge_count
    git diff --shortstat --cached | %{ echo $_.Trim().Substring(0, $_.Trim().indexof(" ")) } | set-variable -name git_staged_count
  }
  Write-Host("[") -NoNewline -ForegroundColor White
  $mylocal_path = $(get-location) -replace "C:\\Users\\yuya.yamaji", "~"
  Write-Host($mylocal_path) -NoNewline -ForegroundColor Cyan
  Write-Host("] ") -NoNewline -ForegroundColor White
  if ($branch -ne "") {
    Write-Host("(") -NoNewline -ForegroundColor White
    if ($git_cahnge_count -ne $git_staged_count) {
      if ($git_cahnge_count -ne "0") {
        Write-Host($branch) -NoNewline -ForegroundColor DarkRed
      } else {
        Write-Host($branch) -NoNewline -ForegroundColor DarkYellow
      }  
    } else {
      Write-Host($branch) -NoNewline -ForegroundColor DarkGreen
    }
    Write-Host(")`n") -NoNewline -ForegroundColor White
  }
  return "PS > "
}
```

# こんな感じで表示されるよ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94735/f7797952-b69d-f790-a78f-c7e03b4ad191.png)
GASでファイル一覧とフォルダ一覧取得

複数人でGoogleDriveを利用しているとファイルやフォルダの数が膨大になり管理が難しくなります。

**想定される課題**
1.目的の資料にたどり着くのに時間がかかる
2.せっかく作られた資料の存在が周知されない
3.資料が更新されない

このあたりをGAS等で改善できないか調査中で、この記事はその備忘録になります。

##ファイル一覧とフォルダ一覧取得
ひとまずはファイルの一覧とフォルダ一覧取得の備忘録です。さほど難しい事はありません。

```Javascript
function myFunction() {
  //ファイル一覧取得
  folder = DriveApp.getFolderById('フォルダID');
  files = folder.getFiles();
  while(files.hasNext()) {
    var buff = files.next();
    console.log(buff.getName()+' : '+buff.getId() + ' : ' + buff.getLastUpdated());
  }

  //フォルダ一覧取得
  folders = folder.getFolders();
  while(folders.hasNext()) {
    var buff = folders.next();
    console.log(buff.getName()+' : '+buff.getId() + ' : ' + buff.getLastUpdated());
  }
}

```

随時、記事を更新していきます。
【クエリビルダ】カスタム定義のデータセットを使ってみる

[Sharperlight](https://sharperlight.jp/)の**クエリビルダ**のデータソースは、データベースだけというわけではありません。
わざわざデータベースにテーブルを作成するほどのデータセットではないけれど、ちょっと欲しいなっという場合、[Sharperlight](https://sharperlight.jp/)には、**カスタム定義のデータセット**というものが用意されています。早速見てみましょう。
[Sharperlight](https://sharperlight.jp/)アップリケーションメニューから**クエリビルダ**を起動します。
[製品]には**システム**を選択します。
[テーブル]に、ここでは**カスタム定義のデータセット**を選択します。
![2022-03-26 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/90f15a75-5ee4-56fe-ec6e-eaabc627a7f5.png)
次に実際のデータセットを定義します。**データセットを定義**の値フィールドをダブルクリックします。
![2022-03-26 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d1bc7e98-145c-50db-1112-fe19ddf91c8b.png)
テンプレートが表示されるので、それを参考に作成します、カンマで区切られたデータセットになります。
```
"Column A::String","Column B::Period","Column C::Date","Column D::Number","Column E::Url","Column F::Icon"
"A100","2015/004","2015-04-04",1234.55,"http://www.sharperlight.com","_icon:Attribute"
"A200","2015/004","2015-04-01",1618.00,null,null
"A300","2015/005","2015-05-23",3141.00,"http://www.philight.com.au","_icon:Company"
"A400",,,13141.00,,
```
[グリッド編集]ボタンを押すと、データセットをグリッド形式で編集できます。
![2022-03-26 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/2569ab87-1296-32ae-562e-66be99260f3a.png)
ここではこのようなデータセットを作成します。
```
"コード::String" , "日付::Date" , "金額::Number"
"A100" , "2022/03/20" , 123.55
"A200" , "2022/03/21" , 180.00
"A300" , "2022/03/22" , 50
```
![2022-03-26 Figure 04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6b0a1fe7-447f-8eee-3824-abae7cf08e92.png)
[OK]を押して確定すると、[選択]階層表示領域に定義したフィールド名が表示されます。全て出力します。
![2022-03-26 Figure 05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/a424718b-c1d6-c2af-dcc6-daa49f747ba4.png)
[プレビュー]ボタンをを押すとこのような結果となります。
![2022-03-26 Figure 06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/08ec3a25-0422-77f2-c254-a6695fd66148.png)
:postbox:[Sharperlight](https://sharperlight.jp/)
Postman Collection Runnerの実行順序を動的に変えたりリトライする方法

WebAPIのテストに、Postmanを利用しています。Collection Runnerを使って、一連のAPIテストを流すのですが、テスト結果やEnvironmentの設定値によって、特定のAPIをリトライしたり、次のAPIをスキップしたり等、実行順序を動的に変更したくなったので、その方法を調べたメモ。

# Collection Runnerの実行順序
通常のCollection Runnerの実行順序は、単純で上から下にシーケンシャルに実行されていきます。
![スクリーンショット 2022-03-17 10.16.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/dafd0618-e7c8-ef1a-6ac8-1f93739c7d02.png)

## APIをリトライ（繰り返し実行）する
Testsを使って、繰り返し実行ができます。TestsはJavascriptで書きます。この例では、設定しておいたリトライ回数に達するまで15secおきにリトライします。APIのレスポンスが成功した場合は、その時点で次のAPI実行に移ります。

```Javascript:Tests
pm.test("matche string TEST", function () {
    //initialize
    const responseJson = pm.response.json();
    var count = pm.collectionVariables.get("retry_counter");
    const count_limit = pm.collectionVariables.get("retry_count_limit");

    if(responseJson.hoge.match("success") || count>=count_limit){
        //clear retry count
        pm.collectionVariables.set("retry_counter", 0);
    }
    else{
        //count up
        count++;
        pm.collectionVariables.set("retry_counter", count);
        console.log("リトライします:"+count+"回目");
        //retry after 15sec
        setTimeout(function(){}, [15000]);
        var title = pm.info.requestName;
        postman.setNextRequest(title);
    }
});
```

リトライ回数のカウント用変数、リトライの上限回数はCollection Variablesとして設定しておきます。Collection Variablesは、下記で設定できます。
![スクリーンショット 2022-03-17 10.32.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/148f852e-d740-beca-f5cc-d9c19a916c99.png)

## APIをスキップする
リトライと同じような方法で、テスト結果やenvironmentによってAPIをスキップすることができます。Testsの例では、environment variableの値によって次のAPIの実行是非を変えています。

```Javascript:Tests
//検証環境では、TEST5までスキップする
var stg_skip = pm.environment.get("stg_flag");
if(stg_skip == 1){
    console.log("skip document");
    postman.setNextRequest("TEST5")
}
```

実行順序はこのようになります。
![スクリーンショット 2022-03-17 11.23.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989777/adc94ba2-7a01-750a-e8dd-a218d269e1ec.png)

# おわりに
実行順序の変更は、API単体で実行した場合は影響がありません。Collection Runnerで実行した場合のみ有効です。Testsのテストをする時は、Collection Runnerで試しましょう。

[postman scripts 参考](https://learning.postman.com/docs/writing-scripts/intro-to-scripts/)
PySpark (Databricks) で使える３種類の DataFrame を相互変換する

Databricks(PySpark) を使っていると、以下の３種類の DataFrame が使える。

* pandas.DataFrame : 皆様ご存知いつもの DataFrame
* pyspark.sql.DataFrame : PySpark の DataFrame と言えばこれだった
* pyspark.pandas.DataFrame : PySpark 3.2 からこれも追加された

pandas.DataFrame は、お馴染みの DataFrame なので普通に使えるが、
もちろん Spark の恩恵は受けられない。

[pyspark.sql.DataFrame](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrame.html) は、pandas.DataFrame とは　API が違うのだが、
まぁ同じようなことも出来る。parquet 形式ファイルから（いつものように）データを読み出すと、普通はこの形式になるので、やはり使うことは一番多いのだろう。

pyspark.sql.DataFrame と言えば、[createOrReplaceTempView()](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrame.createOrReplaceTempView.html) で SparkSession　に貼り付けて、`pyspark.sql(query)` でクエリ発行して、その結果をまた pyspark.sql.DataFrame として受け取って、という処理が非常にやりやすくて泣ける。

ただ、やっぱり pandas.DataFrame みたいな処理もしたいよ〜と思う時もあり、そして逆に実際に pandas.DataFrame を使ってると Spark の恩恵も受けたいよね〜と思う時もあり。

そんな時は [pyspark.pandas.DataFrame](https://spark.apache.org/docs/latest/api/python/reference/pyspark.pandas/index.html) ですよ。

まぁ完璧に pandas.DataFrame じゃないんだけど、ほぼ Spark で動く pandas.DataFrame だと思って良い。

このように便利になってきているのだが、３種類も DataFrame があるとちょっとややこしいし、アレをコレに変換したいなんて時に「あれ？どうやるんだっけ？」とイソイソとググることになる。

なので、備忘録として３種類の変換方法をまとめておく。

# pyspark.sql.DataFrame から変換

## pyspark.sql.DataFrame → pandas.DataFrame

```python
df_pandas = df_sparksql.toPandas()
```

## pyspark.sql.DataFrame → pyspark.pandas.DataFrame

```python
df_sparkpandas = df_sparksql.to_pandas_on_spark()
```

# pandas.DataFrame から変換

## pandas.DataFrame → pyspark.sql.DataFrame

`spark` は SparkSession のインスタンス

```python
spark.conf.set('spark.sql.execution.arrow.enabled', 'true')
df_sparksql = spark.createDataFrame(df_pandas)
```

## pandas.DataFrame → pyspark.pandas.DataFrame

```python
import pyspark.pandas as ps

df_sparkpandas = ps.from_pandas(df_pandas)
```

# pyspark.pandas.DataFrame から変換

## pyspark.pandas.DataFrame → pyspark.sql.DataFrame

```python
df_sparsql = df_sparkpandas.to_spark()
```

## pyspark.pandas.DataFrame → pandas.DataFrame

```python
df_pandas = df_sparkpandas.to_pandas()
```

`toPandas()` と似ていて混乱する！

ちなみに parquet 形式ファイルからも直接 pyspark.pandas.DataFrame に読み込めるので、必ず pyspark.sql.DataFrame を経由するという訳でもない。
Mysqlからlogstashを使ってElasticsearchに同期させるをやってみた

詳細はこちらに記載しています。

MysqlからのデータをElasticsearchに同期させるのにlogstashを使う方法を自分でもやってみたものです。

=> https://nakaearth.hatenadiary.org/entry/2022/03/27/080856
SPSS Modeler ノードリファレンス 3-9 データ分類

# 3-9 データ分類ノード[フィールド作成]
<img width="200" alt="107_89データ分類.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/99ba837f-1d1a-01d5-4c96-a5ba5211c73b.png">

## 1.ノードの目的
カテゴリデータのメンバーを分類します。

以下のイメージを実現します。
![スクリーンショット 2022-03-14 16.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f83ee43c-1407-1252-9aa4-9c8fef531ab1.png)


## 2.解説動画（60秒）

<iframe width="560" height="315" src="https://www.youtube.com/embed/BoOsVwAfPJI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## 3.クイックスタート
[生産国]のデータにある[アメリカ]と[ヨーロッパ]を[輸入車]にまとめます。
＊入力データは[5.参考情報]からダウンロードできます。
![スクリーンショット 2022-03-14 18.12.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/66ae8f3e-60b2-1526-c4d2-5dff5c459bd5.png)

[可変長ファイル]に[データ分類]、[テーブル]を接続します。
![スクリーンショット 2022-03-14 18.15.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/48225619-7060-b72f-50e1-49389a8d6d41.png)

[可変長ファイル]の[データ型]タブで[値の読み込み]ボタンをおして、[生産国]のメンバーを確定します。
![スクリーンショット 2022-03-14 18.17.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/766f4bd6-d81b-2322-3323-252f0af50c71.png)

[データ分類]で次のように編集します。①[生産国]を選択し②で新規フィールド名を入力。③で値を読み込み④対応するあらたな名称を入力します。
![スクリーンショット 2022-03-14 18.20.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2fe70467-e47a-12c9-5d6a-f332921fed73.png)

[テーブル]を実行します。
![スクリーンショット 2022-03-14 18.26.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/13a3d31a-8e0a-1848-7e3a-a7dd18c979d7.png)

#### うまくいかない場合のヒント
[取得]ボタンでエラーになる場合は前方で[生産国]の認識ができていません。[可変長ファイル]の[データ型]タブまたは[データ型]ノードを配置して[値の読み込み]を実行します。
![スクリーンショット 2022-03-14 18.28.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/c2d50302-7db3-a4cd-5e28-83c731f6023c.png)

以下のメッセージがでる場合があります。
![スクリーンショット 2022-03-14 18.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/59674f58-930c-fccc-7549-fd0f7c0a3047.png)

元の値が空白なら新しい値に空白をいれるために１行ブランクになっていますが、それが複数あるとエラーが起こります。赤いバツのボタンで不要な行を消去します。
![スクリーンショット 2022-03-14 18.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3debd206-8e56-cc77-ec4f-e61b4b648ffd.png)

以下のようになっていればOKです。

![スクリーンショット 2022-03-14 18.33.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/20d706c0-ab48-0bec-37a6-681f68cfc646.png)

## 4.Tips

#### ナンバリングの反転
＊[データ分割]ノードで10分位に分割したあとで、[10]を[1]に、[1]を[10]に反転させたい場合は[自動]ボタンを押して以下のように設定します。
![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b1752ffd-ba27-a4ab-3c0c-3e084cb6b36a.png)

数字を反転させたい主な理由も含めて、このTipsを紹介している記事は以下です。

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-17/


## 5.参考情報

#### 利用データ

右クリックでリンク先を保存してください。

https://raw.githubusercontent.com/yoichiro0903n/blue/main/cars.csv

#### ノードのヘルプ

https://www.ibm.com/docs/ja/spss-modeler/18.3.0?topic=nodes-reclassify-node

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee
AWS ChatbotがAWS コスト異常検出アラート通知と連携可能に

# はじめに
2022年3月14日からAWS ChatbotとAWS コスト異常検出アラートの連携が可能となりました。
こんな方に向けた内容となります
* すでにChabot、コスト異常検出機能を利用されている
* チャットツール（Slack、Amazon Chime）を運用で利用されている
* コストの最適化方法を検討中

# AWS Chatbotとは
Slack,AWS Chimeをチャットツールとして運用されている方に便利なAWSサービスとなります。
> [AWS Chatbot](https://aws.amazon.com/jp/chatbot/)
>> AWS Chatbot は、チャットチャネルでの AWS ワークロードのモニタリング、運用、トラブルシューティングを簡単に行えるようにするインタラクティブなエージェントです。

良くあるユースケースとしては
* Amazon CloudWatch でのアラーム通知
* Health イベント通知
* Security Hub の検出結果通知

等があげられます。私はSlackにて運用していましたが、アラートの内容も見やすく重宝していました。

# AWS コスト異常検出アラート
こちらもすでに実装済みのサービスとなりますので簡単に紹介いたします。
閾値を超えるEC2等の利用料を検知するとEメールもしくはSNSトピックに対してアラートを通知できる機能となります。
>[AWS 異常検出で異常な使用料を検出する](https://docs.aws.amazon.com/ja_jp/cost-management/latest/userguide/manage-ad.html)
>>AWS コスト異常検出とは、機械学習を使用して、コストと使用量を継続的にモニタリングし、異常な支出を検出する AWS コスト管理機能です。

開発環境をチームに公開していて複数インスタンスを起動/停止している場合や
利用料を予算枠内に抑える必要がある場合に重宝するサービスとなります。

# 何がうれしいのか
実際にシステム運用をしているとアラートの通知先は集約したほうが効率がいいと思います。
運用しているSlack,AWS Chimeにコスト管理面でも通知を飛ばせるようになる事は利便性があがりますね。

# まとめ
AWS Chatbotへ通知可能な内容が拡張される事はうれしいですね。
それぞれのサービス自体は以前から利用できたものですが、サービスの組み合わせで痒い所に手が届くようになるのがAWSの良いところだと思います。
すでに利用しているCloudWatchAlarmのSNS通知先に追加と初期設定のみしてしまえばすぐに利用開始できますので通知用のコスト管理チャンネルを作成し利用してみては如何でしょうか。

# 参考
[AWS コスト異常検出が AWS Chatbot との統合をサポート](https://aws.amazon.com/jp/about-aws/whats-new/2022/03/aws-cost-anomaly-detection-integration-chatbot/)
[AWS コスト異常検出を開始する](https://docs.aws.amazon.com/ja_jp/cost-management/latest/userguide/getting-started-ad.html)
DatabricksとTIBCO Spotfire Analystの連携

[TIBCO Spotfire Analyst \| Databricks on AWS](https://docs.databricks.com/integrations/bi/spotfire.html) [2021/8/2時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

ステップバイステップの手順はこちらを参照ください。

https://qiita.com/taka_yayoi/items/e8c6c178169899f2d89a

# ステップ1: Databricks接続情報の取得

**クラスター**

1. [パーソナルアクセストークン](https://docs.databricks.com/dev-tools/api/latest/authentication.html#token-management)を取得します。
1. [お使いのクラスターのJDBC/ODBCタブ](https://docs.databricks.com/integrations/bi/jdbc-odbc-bi.html#get-server-hostname-port-http-path-and-jdbc-url)から**Server Hostname**、**Port**、**HTTP Path**フィールドの値を取得します。

**SQLエンドポイント**

1. [パーソナルアクセストークン](https://docs.databricks.com/dev-tools/api/latest/authentication.html#token-management)を取得します。
1. [お使いのSQLエンドポイントのConnection Detailsタブ](https://docs.databricks.com/integrations/bi/jdbc-odbc-bi.html#sql)から**Server Hostname**、**Port**、**HTTP Path**フィールドの値を取得します。

# ステップ2: TIBCO SpotfireでDatabricksクラスター接続を設定

1. TIBCO Spotfire Analystのナビゲーションバーで、プラス(**Files and data**)アイコンと**Connect to**をクリックします。
1. **Databricks**を選択し**New connection**をクリックします。
1. **Apache Spark SQL**ダイアログで、**General**タブの**Server**に、ステップ1の**Server Hostname**と**Port**フィールドの値をコロン区切りで入力します。
1. **Authentication method**で、**Username and password**を選択します。
1. **Username**に`token`を入力します。
1. **Password**にステップ1で取得したパーソナルアクセストークンを入力します。
1. **Advanced**タブの**Thrift transport mode**で**HTTP**を選択します。
1. **HTTP Path**にはステップ1で取得した**HTTP Path**を入力します。
1. **General**タブで**Connect**をクリックします。
1. 接続が成功したら、**Database**リストで使用したいデータベースを選択して**OK**をクリックします。

# ステップ3: Databricksで分析データを選択

**Views in Connection**ダイアログでデータを選択します。
![](https://docs.databricks.com/_images/tibco-image3.png)

1. Databricksで利用できるテーブルを参照します。
1. ビューとして使用したいテーブルを追加します。TIBCO Spotfireで分析するデータテーブルとなります。
1. それぞれのビューに含めるカラムを選択することができます。特定かつ柔軟性のあるデータの選択を行いたい場合には、以下に示すようにこのダイアログでパワフルなツールにアクセスすることができます。
    - カスタムのクエリー。カスタムのクエリーを用いることで、カスタムのSQLクエリーを用いて分析したいデータを選択することができます。
    - プロンプティング。ユーザーに分析ファイルのデータ選択を委ねます。好きなカラムに基づいてプロンプトを設定することができます。そして、アナリシスを開くエンドユーザーは、適切な値にデータを制限して参照することができます。例えば、特定の期間や特定の地域にデータを限定することができます。
1. **OK**をクリックします。

# ステップ4: Databricksやインポートデータにクエリーをプッシュダウン

分析したいデータを選択したのち、最後のステップはDatabricksからデータを取得する方法を選択することとなります。アナリシスに追加しようとするデータテーブルのサマリーが表示され、データロードの方法を変更するためにそれぞれのテーブルをクリックします。
![](https://docs.databricks.com/_images/tibco-image4.png)

Databricksのデフォルトオプションは**External**となっています。これは、データテーブルはDatabricksのデータベースに維持されることを意味し、TIBCO Spotfireはアナリシスにおける皆様のアクションに基づいて、適切なデータスライスに対する異なるクエリーをデータベースにプッシュします。

**Imported**を選択することも可能で、TIBCO Spotfireはデータテーブル全てを抽出し、ローカルでのインメモリ分析を可能とします。データテーブルをインポートする際、TIBCO Spotfireの埋め込みインメモリデータエンジンの分析関数を使用することも可能です。

3つ目のオプションは、**On-demand**(動的な`WHERE`句に対応)であり、アナリシスにおけるユーザーアクションに基づいてデータのスライスが抽出されます。評価指標として、データのマーキングやフィルタリング、ドキュメントプロパティの変更のようなアクションを定義することができます。オンデマンドのデータロードは**External**データテーブルと組み合わせることも可能です。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
すべての部分集合の数字の和を求める

以下のような問題を考えます。

### すべての部分集合の数字の和を求める問題

 **問題：** トランプの52枚の集合のすべての部分集合を作り各々の数字の和を求めたとき１の位の数で一番多いのはどれ？

1桁の数字の数をカウントする配列countを定義します。

```python 
import numpy as np
count = np.array([0]*10)
#[0 0 0 0 0 0 0 0 0 0]
```

部分集合はまず空集合$\{\}$から初めて、それまでの部分集合のすべてに、新たな要素加えたものを追加行くと考えられます。$1,2,..$と加えて行くと考えると以下のようになります。

```math 
\{ \{ \} \} \rightarrow \{ \{ \} \{ 1\}  \}  
 \rightarrow \{ \{ \} \{ 1\} \{ 2 \} \{ 1, 2\} \}  
```

これを数字の和のカウントを考えると、１を加えるということは右に１つ動くということなので、１つ右に回転して前のものと足せば良いことになります。

```
[1 0 0 0 0 0 0 0 0 0]    # 空集合（和は0が一つ）
---------------------------------
[0 1 0 0 0 0 0 0 0 0]    # 1を加える = 一つ右に回転
[1 1 0 0 0 0 0 0 0 0]    # 前のものと足す
---------------------------------
[0 0 1 1 0 0 0 0 0 0]    # 2を加える = ２つ右に回転
[1 1 1 1 0 0 0 0 0 0]    # 前のものと足す
```

これは$0,1,2,3$が一つずつあるということなので結果と一致しています。

従って元の問題はこの「countを次に加える数だけ回転して、足し合わせる」を繰り返せばよいので、以下のようなコードになります。結果は見づらいですが**2と7**が最大になります。

```python 
import numpy as np
import sympy
cards =[n for n in range(1,14)]*4

count = np.array([0]*10)
count[0] = 1

for n in cards:
  count += np.roll(count,n) # rotate and add 

print(count)
#[450359962737152 450359962736768 450359962737408 450359962736768
 450359962737152 450359962737152 450359962736768 450359962737408
 450359962736768 450359962737152]
```

このアルゴリズムはEuler Project: Problem 249, 250を解くのに役に立ちます。

（開発環境：Google Colab）