OmniAICreator/Qiita-1.07M huggingface dataset:
URBAN HACKSの広告(試験時間90分)のPuLPを使った解法

#### きっかけ

通勤の電車の中で次のような広告を見かけました。
([また](https://qiita.com/EliotNapa/items/21a07e5ce9b5f1053647)かよ！）

>限られた試験時間90分の中で、どの問題に取り組めば効率的よく最も高い点を撮れるか。
>問題1  6点 所要時間12分
>問題2 11点 所要時間26分
>以下略

ようするに、問題を解くのに必ず所要時間がかかって部分点は存在しないという条件です。

前回は10パズルでしたが、今回は見た瞬間にpulpかよと思いました。
しかも、一時期話題になったマクドナルド（だっけ？）メニュー最適化問題。

こういうの、いわゆるナップサック問題というらしいです。
しかも、マクドナルドのメニューよりずいぶん簡単です。

これ、言っちゃあ悪いけど出題者が応募者を測っているつもりで、出題者の程度が見極められてますよっと。

文句言っててもしょうがないので、ちゃちゃっとコード書きます。
手抜きモードなので所要時間と点数で配列分けたのはすんまそん。
結果が1.0のの問題を解くのが解となります。

### 解法(コード)

```py
import pulp
import sys

limit_time = 90  # 問題の制限時間
points  = [ 6, 11, 20, 12, 10, 19, 14, 8]  # 問題の点数
minutes = [12, 26, 48, 28, 25, 45, 31, 15]  # 問題の所要時間

if len(points) != len(minutes):
    print("問題設定ミスってまっせ！")
    sys.exit(1)

# 問題を定義。pulp.LpMaximizeで点数が最大になる条件を指定
prob = pulp.LpProblem('examination', sense=pulp.LpMaximize)

# 変数の定義。問題を解くかどうかを0,1で示す
vars = [pulp.LpVariable('{}'.format(x), cat='Binary', lowBound=0, upBound=1) for x in range(len(points))]
prob += pulp.lpDot(points, vars)  # values(係数),vars(変数)の内積を目的関数として登録
prob += pulp.lpDot(minutes, vars) <= limit_time  # 試験の制限時間を制約条件として追加

# 実行
status = prob.solve()

#結果表示
print([x.value() for x in vars])
```
SageMaker Studio abalone （df is not defined ）

# TL ; DR
SageMaker Studio習得のため[abalone](https://docs.aws.amazon.com/sagemaker/latest/dg/define-pipeline.html)を使い自分のデータでやってみたところ、使いこなすのに物凄い時間がかりました。解決法がネットになく、色々勉強しかなり遠回りしてしまったので、もし同じ境遇の方のお役に立てば幸いです。数回に分けて、エラーをどうやって解消したかを記載しています。

# エラー
```preprocess.py
df is not defined
```
preprocess.pyで上記エラーが発生しました。


# 解決法
processing.pyでもdfを定義する必要があります。

# 背景
最初の方でしっかりとdfを読込し、df.head()も表示されたのにprocess.pyでなぜエラー発生するのか？
何が原因が全くわからず、途方に暮れました。。。

# 補足
SageMaker Studioでは3つの異世界？が存在します。
1つ目はgetcwd()で表示される世界（EFSのこと）
2つ目はopt/mlのコンテナの世界
3つ目はs3の世界

1つ目の世界でdfを定義していても、それが2つ目の世界では定義されてないんです。
だからpreprocess.pyがあるコンテナの世界ではエラーが出たみたいです。
まあ、そう言われたらその通りですが、そこに自力で気づくのに物凄く悩みました。。。

# 関連
[SageMaker Studio abalone （Missing optional dependency 'fsspec'）](https://qiita.com/Blahrmy/items/f2b77ed0001b056205a3)
[Amazon SageMaker Pipelines を実際に使ってみた【前編】[re:Invent 2020]](https://qiita.com/knt078/items/73d4f94286238bd1077c)
[Amazon SageMaker Pipelines を実際に使ってみた【後編】[re:Invent 2020]](https://qiita.com/knt078/items/5b862d4539e7fa1c16df)
[Amazon SageMaker Pipelineを動かしてみた](https://qiita.com/niwashing/items/6a148787a7faf3cad0b3)
[メモ]PythonでYYYY-MM-DD

### 説明

年月日をログファイル名にしたい時に好きな形に成型するにはstrptimeなど必要だがYYYY-MM-DDに限って言えば楽な方法があるのに記述が見つからなかったためメモ。

```python:YYYY-MM-DD.py
from datetime import datetime

nengappi = str(datetime.now())[:10]
print(nengappi)

>>> '2023-02-15'
```
これだけ
React初学者のつまづきポイント、勉強法

## 概要

phpは書き慣れていたのですが、reactを学ぶにあたってつまづいたポイントまとめ。
言い換えると、下記については、それぞれちょ～～～っと腰を据えて学習する必要があった。
※ほんとのプログラミング初学者がreactから入るのは本当につらい

## つまづきポイント

### Javascript特有の記法

* アロー関数
* スプレッド構文（配列名の前に...をつけるやつ）
* if else を ? で書くやつ
* map関数、filter関数（要素を繰り返し表示したり、特定の要素の削除）


### ◆React特有のもの

#### 　ざっくり理解
* App.jsがレンダリング（もろもろ変換）されて丸々クライアント（ブラウザ）に渡される
* （↑を細かくいうと）最近pcもスマホも高機能なので、バックエンドでやってたようなな処理をでかいファイル（App.js）でまるまるクライアント側に渡してやってしまおうという思想
*  そのためバックエンドとは基本非同期処理
* 一つの関数の塊をコンポーネントとして扱う。その中に処理（javascript）とhtmlとかまとめちゃう


* コンポーネントのreturnの中にhtml（画面）を書く
* returnの{}の中にjavascriptを書く（jsx）

#### 　つまづきポイント 
* 変数、関数のcomponent間の受け渡し
* hooks（React特有のライブラリみたいなもの。これを使わないと始まらないが、必須のはそう多くない）

#### 　JSXにおける記法
* htmlなのかjsなのかわからなくなる（タグの関数を"submithanndle"でいいのか{submithandler}でいいのかとか）


## 対策、勉強法

1. youtubeのTODOアプリなどをとりあえずいわれるがままにクローン、全体感を理解。わかる個所とわかんない箇所を出して、理解
   ※[sandbox](https://codesandbox.io/)で十分。環境構築でごみファイルをローカルに増やしたくない...

2. 基本的な機能について、chatGDPで例を出力→[sandbox](https://codesandbox.io/)で実行してみる
　 ※chatGDPで（react input）など打つと、コードの例を作ってくれる
3. Javascriptが全然慣れていないなら、[paizaのスキルチェック問題集](https://paiza.jp/challenges/info)も参考になる

4. アプリ作る。
   
簡単な機能の例：
* cookieの操作
* ナビゲーション
* 画面遷移
* formタグ、inputの操作
* 表示非表示
* 配列による要素の動的CRUD
Prefect2で、リソース確保・クリーンアップのタスクをwith構文で実行する


Prefectを使って、「EC2インスタンスを立ち上げて、シェルスクリプトを実行し、処理が終わったらシャットダウンする」ようなflowを実行しています。

[こちらの記事を書いたPrefectの導入時点](https://qiita.com/ninomiyt/items/b68ac43206760f44354c)では、次のように`try ~ finally` で実行し、「シェルコマンドでエラーが起きた場合でもEC2インスタンスをシャットダウンする」ような処理を実現していました。


```python
from tasks import run_ec2_instance, execute_commands, terminate_ec2_instance

@flow
def sample_flow():
    instance_id = run_ec2_instance(
        image_id="ami-******", # 自作のAMI
        instance_type="t2.micro",
        instance_profile='SSMInstanceRole', # ssmで接続するため、最低限この権限が必要
    )

    try:
        execute_commands(
            instance_id=instance_id,
            commands=["echo 'hello task1'"],
            terminate_after=30,
        )
        ...

    finally:
        terminate_ec2_instance(instance_id)

if __name__ == "__main__":
    sample_flow()
```

ただ、「[How to clean up resources used in a flow?](https://discourse.prefect.io/t/how-to-clean-up-resources-used-in-a-flow/84)」にある通り、こういうリソースの確保、解放の処理は、Pythonの通常の関数（`open`等）のようにコンテキストマネージャ（`with`文）で大幅に簡略化できるようです。（ドキュメントから見つけられずにできないと思いこんでいただけでした）

次のようなコンテキストマネージャーを用意すると、

```python
import contextlib

@contextlib.contextmanager
def setup_ec2_instance(image_id: str, instance_type: str, instance_profile: str):
    """EC2インスタンスのリソースを準備する。

    Args:
        image_id (str): AMIのID
        instance_type (str): インスタンスタイプ
        instance_profile (str): インスタンスプロファイル

    Yields:
        str: 起動したEC2インスタンスのID
    """
    instance_id = run_ec2_instance(image_id=image_id, instance_type=instance_type, instance_profile=instance_profile)
    try:
        yield instance_id
    finally:
        terminate_ec2_instance(instance_id=instance_id)
```

次のように、いつものPythonで見かける感じにスッキリできます。これで毎回`try~finally`を書く必要が無くなりました🙌

```python
from tasks import run_ec2_instance, execute_commands, terminate_ec2_instance

@flow
def sample_flow():
    with setup_ec2_instance(
        image_id="ami-******", # 自作のAMI
        instance_type="t2.micro",
        instance_profile='SSMInstanceRole', # ssmで接続するため、最低限この権限が必要
    ) as instance_id:
        execute_commands(
            instance_id=instance_id,
            commands=["echo 'hello task1'"],
            terminate_after=30,
        )

if __name__ == "__main__":
    sample_flow()
```

「[How to clean up resources used in a flow?](https://discourse.prefect.io/t/how-to-clean-up-resources-used-in-a-flow/84)」を読むと、Prefect 1の時点ではコンテキストマネージャ用の専用の機能が用意されていたのですが、Pythonの標準的な方法(`contextlib`)で実装できるように変更されたようですね。
react-bootstrapのForm.Check要素を中央に配置する方法

`<div>` で要素を囲み、`style` を以下のように指定すると中央寄せになる。

```react:sample.tsx
<div style={{ display: 'flex', justifyContent: 'center' }}>
    <Form.Check
      //...
    />
</div>
```

もっと良い方法があれば教えてください。。。
Pythonの仮想環境でpip installして「ValueError: check_hostname requires server_hostname」が出たときのプロキシ設定


## 問題
Windows10でPythonを使って仮想環境を構築し、pip install xxx したら以下のエラーが出て悩みました。
```
ValueError: check_hostname requires server_hostname
```

## 解決方法
プロキシを使用しているPCでGit Bashでpip installしていたので、`~/.bash_profile`ファイルに以下を追加したらインストールできました！

```bash:.bash_profile
# プロキシ設定
export http_proxy="[プロキシアドレス]:[ポート番号]"
export https_proxy="[プロキシアドレス]:[ポート番号]"
```

プロキシを使っているPCだと設定がないと、いろんな場面でコマンドエラーが出るので注意が必要ですね。
AnsibleでHPE Comware機器を設定する

# 目的：HPE Comwareスイッチを設定するAnsible-playbookを作成する

# 問題：
* Ansible及びAnsible-galaxyにはHPE Comware用のモジュールがない
* Githubにあるhpe-cw7-ansibleモジュールは次の欠点がある
① NETCONFを利用するために遅い
② VRFを必須とする

# 対策：
rawモジュールを利用する。
rawモジュールを利用する場合は次の2点に注意する。
①ansible_connectionを指定しない。指定するとエラーになる
②1つのコマンドしか受付ないため、複数のコマンドを実行する場合はvarでコマンドを定義してrawでは定義して変数を指定する。
<pre>
- name: execute command (comware)
  vars:
    command_string: "system-view\ninfo-center loghost 192.168.10.10"
  raw: "{{ command_string }}"
</pre>

参考：
(https://stackoverflow.com/questions/30375301/ansible-raw-multiple-commands "ansible raw multiple commands")

以上
Excelでpivotテーブルの値フィルタやスライサーに古い値が表示される

ExcelのPivotテーブルでは値フィルタとして選択できる項目欄やスライサーに、現在存在しない値が表示される場合があります。

Pivotテーブルを作り直す事で不要なデータを消す事はできましたが、それ以外にオプション設定でクリアする方法があったので忘備録。

## 事象

下記のようなPivotテーブルでcolumn1項目の値フィルタを確認すると、存在しない値がフィルタ値として登録されていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/c201e79d-95ba-dbdb-8f0c-a2aa1a597b1b.png)

column1項目の値フィルタを確認すると、column1には現在`foo`しか存在していないのに、登録されていない値が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/b3e37aaa-cd7e-ecca-de50-54c5815e72b5.png)

## なにが起きていたか

pivotテーブルでデータソースを更新した際に、ピボットテーブル分析の更新からデータ更新を行っても、データソースから削除されたアイテムを保持しているようです。

このため、pivotテーブルを更新しても値フィルタやスライサーには古い情報が残ってしまいます。

上記の例は、下記のようにデータソースを編集すると再現します。

変更前（元々のデータソース）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/4be265de-0b00-a394-9179-b3533e87b07e.png)

変更後（データソースを一行目の foo bar 以外削除）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/ae8d9e54-0f96-2744-df15-56fb2465e5e9.png)

データソースを上記のように編集した後に、pivotテーブルを更新すると、値フィルタやスライサに古い状態が保持される状況となります。

## 値フィルタのリストを更新するには

ピボットテーブルオプション　＝＞　データ　＝＞　1フィールドに保持するアイテム数　＝＞　「自動」 から 「なし」　に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/da4382c3-a1dc-ac1f-78d9-d76378ebe891.png)

「自動」から「なし」に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/68ca0a56-f256-5430-fb5f-708f52a75359.png)

「なし」に設定してOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/d23eb765-4150-d79f-59f1-6b88fc49468e.png)

設定保存後にpivotテーブルの更新を実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/25a81e52-d1f2-785e-2d5c-b169b71fd71f.png)

値フィルタのリストが更新されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/4eb9f516-46d1-43c9-7b09-7b128dc73877.png)

## スライサーの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/194f9d5b-f279-fcd1-b7c6-31b528769d7d.png)

スライサーでも古い状態が残ると記載しましたが、上記画像のようなります。
こちらも値フィルタと同様の手順で古い情報をクリアできます。

## 参考

[PivotTable options](https://support.microsoft.com/en-us/office/pivottable-options-27c02eb7-27de-4b3f-9677-c48e3fe7637b)

[Pivot table; remove old values from slicer](https://stackoverflow.com/questions/38146984/pivot-table-remove-old-values-from-slicer)

## 総評

pivotテーブルを作り直して対応していましたが。　作り直さないでもクリアする方法があるので覚えておくと捗るかと思います。
mysqldumpslowの使い方

MySQLのパフォーマンスをチューニングするためには、クエリの実行時間やクエリの使用頻度を把握する必要があります。そのために、MySQLには「slow query log」という機能があり、slow query logを使うことで、実行時間の長いクエリや頻繁に実行されているクエリを特定することができます。

また、mysqldumpslowというツールを使用することで、slow query logの解析や集計が容易になります。本記事では、mysqldumpslowの使い方について説明します。

## mysqldumpslowとは
mysqldumpslowは、MySQLが出力するslow query logを解析し、クエリの使用頻度や実行時間などの情報を抽出するためのツールです。slow query logを分析することで、パフォーマンスの問題を把握し、解決することができます。

## mysqldumpslowの使い方
まずは、slow query logを有効にする必要があります。MySQLの設定ファイル(my.cnf)に以下の設定を追加します。

```
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
```
上記の設定では、slow query logを有効にし、ログの出力先を/var/log/mysql/mysql-slow.logに設定し、実行時間が2秒以上のクエリをログに出力するように設定しています。

次に、mysqldumpslowを使用してslow query logを解析します。以下のコマンドを実行します。

```
mysqldumpslow /var/log/mysql/mysql-slow.log
```
上記のコマンドでは、/var/log/mysql/mysql-slow.logに記録されたslow query logを解析し、クエリの使用頻度や実行時間などの情報を出力します。

## mysqldumpslowのオプション
mysqldumpslowには、以下のようなオプションがあります。

```
-sオプション: クエリのソートキーを指定します。例えば、-s cを指定すると、クエリの使用回数が多い順にソートされます。
-rオプション: クエリのソート順を逆にします。
-tオプション: 最初のn件の結果だけを出力します。
-gオプション: 正規表現に一致するクエリだけを出力します。
```

これらのオプションを使うことで、より詳細な解析や集計が可能になります。

`-s` オプションはクエリのソートキーを指定します。以下はよく使われるソートキーです。

```
c: クエリの使用回数が多い順にソートします。
t: クエリの実行時間が長い順にソートします。
l: クエリのロック時間が長い順にソートします。
```

以下は、クエリの使用回数が多い順にソートする例です。

```
mysqldumpslow -s c /var/log/mysql/mysql-slow.log
```

`-g` オプションは正規表現に一致するクエリだけを出力します。以下は、クエリの内容に"SELECT"が含まれるクエリだけを出力する例です。

```
mysqldumpslow -s c -g "SELECT" /var/log/mysql/mysql-slow.log
```

## まとめ
mysqldumpslowを使うことで、MySQLのslow query logを解析することができます。クエリの使用頻度や実行時間を把握することで、パフォーマンスの問題を解決することができます。また、mysqldumpslowには、様々なオプションがあり、より詳細な解析や集計が可能になります。
neosでlogix その114

# 概要
neosでlogixやってみる。
練習問題、やってみた。

# 練習問題
パーティクルな箱を作れ。

# 手順

- DevToolTipを装着
- 新規作成
- パーティクルシステムをクリック
- 新規作成
- 3Dモデル>Boxをクリック
- インスペクターを開く
- ParticleSystemをBoxの下に入れる。


# 写真

![2023-02-15 01.58.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3b7ae8c4-0ce4-3108-725d-a4fc3172c018.jpeg)


以上。
Ruby sliceメソッド

# sliceメソッド
配列や文字列から、指定した要素を取り出すことができるメソッドです。

```ruby:例
# 配列を作成します
array = [0,1,2,3,4,5,6]

# 配列から引数で指定した要素を取得します
ele1 = array.slice(1)
puts ele1
#=> 1  # 0番目から始まるため、1が取り出されました

# 配列番号-4から4つ分の要素をsliceします
ele2 = array.slice(-4,4)
puts ele2
#=> 3, 4, 5, 6

# 配列はもとのままです
puts array 
#=> [0,1,2,3,4,5,6]
```

# sliceメソッドを使って指定した文字列を取り出すプログラムを作成します

条件は以下です。
- 条件1:対象の文字列から末尾にある2文字を取得すること
- 条件2:取得した2文字を3回繰り返して出力すること


```ruby:模範解答
def extra_end(str)
  right2 = str.slice(- 2, 2)
  puts right2 * 3
end

# 呼び出し例
extra_end('Hello') 
```
```ruby
lololo
# ターミナル出力
```
## 解説
今回、末尾にある２つの文字について取得し、それを3回出力させるという内容でした。
「末尾にある２つの文字」の取り出す方法は、sliceメソッドを使います。
取り出す範囲を(-2, 2)としましたが、こうすることで文字列の末尾２番目から２つ要素を取得することができます。
そして、* 3と記述することで、3回連続出力することに成功しました。

私は、この問題を解くときに以下のように記述しました。
模範解答の方が丁寧...かな？うーん。
```ruby
def extra_end(str)
  puts (str.slice(-2, 2) * 3)
end

# 呼び出し例
extra_end('Hello')
```
ChatGPTを使ったシナリオ記法の考察

# 以前より考案中であった「シナリオ記法」の考察をChatGPTを利用してさらに進めてみた

今流行りのChatGPTを利用して「シナリオ記法」の開発を進めてみた。
以前のバージョンではSASS的な記法を模索していたが、その後JSONとなりJSONCへと変化していた。
今回、ChatGPTとのブレインストーミングを進める中で、YAMLでの記述が適していてそうとの感覚を得た。

https://qiita.com/buzzlyhan/items/2368e29c6b69865c3c8d

# とりあえずSPES（スぺス）のYAMLコード

3時間程度ChayGPTとブレインストーミングした結果、以下のYAMLコードが得られた。
これがPremiere ProやFinal Cut Proの xmlにパースできればシナリオ➡絵コンテ➡プリビス（動画編集）の流れがスムーズに完成する。

```yaml
# キーの凡例:
# - name: シーン名
# - duration: シーンの時間 (秒)。nullの場合は未定義。
# - time_of_day: シーンの時間帯。nullの場合は未定義。
# - se: シーンで使われるサウンドエフェクト。nullの場合は未定義。
# - description: シーンの説明。
# - actor: シーンに登場するキャラクターのリスト。
# - cuts: シーンを構成するカットのリスト。
# - id: カットの一意な識別子として使用されます。同じシーン内の異なるカットを区別するために使用されます。
# - transition: カット間の遷移方法を指定するために使用されます。例えば、次のカットが直接前のカットと重なり合うようになる場合は "オーバーラップ"、フェードイン/フェードアウトのようにシーンの切り替わりをスムーズにするために使用されます。transition が null である場合、前のカットと直接切り替わります。
 
title: "都会の恋"
 
# 都会の男女の恋物語
# 登場人物: アリス (女性), ボブ (男性)
 
scene1:
  - name: "初デート"
    duration: null
    time_of_day: 8:00
    se: null
    description: "都会のトレンディなカフェ"
    actor:
      - "アリス (女性)"
      - "ボブ (男性)"
    cuts:
      - id: 1
        camera: "アリスがカフェに入ってくる中編"
        se: "背景にソフトな音楽"
        action: "アリスはカフェを見回してボブを探す"
        dialogue: []
        transition: "オーバーラップ"
      - id: 2
        camera: "ボブがテーブルに座って時計を見ているクローズアップ"
        se: null
        action: "ボブは時計を確認して周りを見まわす"
        dialogue: []
        transition: null
      - id: 3
        camera: "アリスがボブを見つけたクローズアップ"
        se: null
        action: "アリスはにっこり笑ってボブに向かって歩く"
        dialogue: []
        transition: null
      - id: 4
        camera: "アリスとボブのツーショット"
        se: null
        action: []
        dialogue:
          - "アリス: こんにちは！アリスです。"
          - "ボブ: こんにちはアリス！ようやく会えて嬉しいです。"
          - "アリス: 私もそう思います！"
        transition: null
 
scene2:
  - name: "アイスクリーム冒険"
    duration: null
    time_of_day: 8:00
    se: null
    description: "アイスクリームショップ"
    actor:
      - "アリス"
      - "ボブ"
    cuts:
      - id: 1
        camera: "アリスとボブがアイスクリームショップに入ってくる中編"
        se: "ハッピーな背景音楽"
```
SAP License key取得時に必要となる情報

SAPのライセンスキーは、SAP社サイトから取得する。（過渡期なので両方記載)
Support Portalの場合: https://launchpad.support.sap.com/#/licensekey/wizard
SAP for Meの場合、https://me.sap.com/licensekey/wizard

取得時に必要となる情報は以下の通り。
下記情報を添付して依頼するとスムーズに取得していただくことが出来る。

| 項目 | 説明 | 備考 |
| -- | -- | --|
| Installation Number| SAP社との契約に基づき発行される番号<br>不明な場合は営業に確認|https://launchpad.support.sap.com/#/installation/management|
|Product|製品名：S/4HANA、Solution Manager、SAP HANA, platform editionなど。|
|Version|上記製品のバージョン|
|System ID|インストール時に指定したSID。３文字のやつ|
|System Name|SAPサイト上に登録する名称。あとで変更可能。文字化けするので英数で入れる。|
|System Type| 利用用途に応じて以下から選ぶ<br>Archive System, Backup system, Demo system, Development system, Production System, Test system, Training system| |
|Database| 利用するデータベース製品を選ぶ| |
|Operating System|利用するOSを選ぶ |
|Infrastructure| 利用するインフラ基盤を選ぶ| 2952748 - What is the Infrastructure drop-down in System Data and License Keys? - SAP ONE Support Launchpad|
|License Type:|NetWeaverの場合以下から選ぶ<br>Standard, J2EE-Engine, Maintenance Entitlement<br>HANA DBの場合は以下から選ぶ<br>SAP In-memory Appliance platform, SAP HANA dynamic tiering, SAP HANA Maxhine Manufacturing Analytics, SAP HANA smart data streaming, SAP HANA remote data sync| 
|Hardware Key|英字から始まる11ケタ<br>NetWeaverの場合、ASCS/SCS上で、"saplicense -get"または、T-cd:SLICENSEから確認<br>HANA DBの場合、備考参照|2943032 - How to Find SAP HANA Hardware License Key From OS Level
|Quantity| HANA DBの場合、有効となるメモリ量を入力。GB単位|スケールアップする場合、あらかじめ大きめでとっておくと取り直し不要となる。
|Valid until| デフォルト31-12-9999だが、検証用など意図的に短くしたい場合は変更


--
2620737 - How to request license key for SAP Business Suite Applications or Analytics Solutions on SAP HANA System - Guided Answers
2213293 - How to request SAP HANA Platform or Enterprise Edition license keys - SAP ONE Support Launchpad
2952748 - What is the Infrastructure drop-down in System Data and License Keys? - SAP ONE Support Launchpad
2943032 - How to Find SAP HANA Hardware License Key From OS Level
https://support.sap.com/content/dam/support/en_us/library/ssp/my-support/help-for-sap-support-applications/license-key-help/new-request-license-keys-business-suite.pdf
CommonJSとESModuleの設定ミスでSlackアプリを実行できなかった話

`@slack/bolt`と`chatgpt`を組み合わせて、Slackアプリを開発しようとしていた。

https://github.com/transitive-bullshit/chatgpt-api


このときの**tsconfig.json**では、`module`は`CommonJS`を示していて、`target`は`ES2017`を指していた。


```tsconfig.json
{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES2017",
    ...
  },
  ...
}
```

そして、`tsc`を使って**src/index.ts**のビルドを行い、`node`を使って生成された**build/index.js**を実行しようとした。

ビルドは通ったものの、`node`での実行に失敗した。

```shell
> tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json

/Users/takagimeow/example/build/index.js:9
const chatgpt_1 = require("chatgpt");
                  ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/takagimeow/example/node_modules/chatgpt/build/index.js from /Users/takagimeow/example/build/index.js not supported.
Instead change the require of /Users/takagimeow/example/node_modules/chatgpt/build/index.js in /Users/takagimeow/example/build/index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/takagimeow/example/build/index.js:9:19) {
  code: 'ERR_REQUIRE_ESM'
}
```

具体的にいうと、生成された**build/index.js**はCommonJSモジュールなのに、ESModuleである**node_modules/chatgpt/build/index.js**を使おうとしているために発生したエラーだった。

そこで今度は、`module`を`ESNext`に設定してみることにした。

```tsconfig.json
{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ES2017",
    ...
  },
  ...
}
```

今度は、ESモジュールではない**build/index.js**で、`import`を使っていたがためにエラーが発生した。

```shell
import bolt from "@slack/bolt";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1149:20)
    at Module._compile (node:internal/modules/cjs/loader:1190:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
    at Module.load (node:internal/modules/cjs/loader:1089:32)
    at Module._load (node:internal/modules/cjs/loader:930:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47
```

これは、`chatgpt`のリポジトリにもIssueとして上がっていたが、これは`chatgpt`特有の問題ではない。

https://github.com/transitive-bullshit/chatgpt-api/issues/207

この問題を解消するには実行対象のJavaScriptファイルの拡張子を**js**から**mjs**に変更しないといけない。

なので、ビルド対象の**src/index.ts**の拡張子を**src/index.mts**に変更した。これにより、生成される**build/index.js**は**build/index.mjs**として生成されることになる。

そして、もう一度実行してみた。

```shell
$ tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && node ./build/index.mjs

...
[INFO]  socket-mode:SocketModeClient:0 Going to establish a new connection to Slack ...
⚡️ Bolt app is running!
[INFO]  socket-mode:SocketModeClient:0 Now connected to Slack
```

今度は成功した。

このあと、**tsconfig.json**の`target`も`ESNext`に変更したが、きちんと動くことを確認できた。

---

https://github.com/slackapi/bolt-js

https://github.com/transitive-bullshit/chatgpt-api

https://github.com/MarkusGalant/chatgpt-slackbot-serverless

https://github.com/NessunKim/slack-chatgpt/

https://github.com/transitive-bullshit/chatgpt-api/issues/207
お問い合わせフォームのレイアウト


input, textarea
- input 要素は１行のテキスト入力を受け取るための要素。
- textarea 要素は複数行のテキスト入力を受け取るための要素。
- input 要素は終了タグが不要な点に注意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/c30f4dfd-b024-d7c6-fb08-82ef0f933b4e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/1c565f10-ca27-2fe4-0f1c-e65e06a28e1c.png)
#### 送信ボタンを作ろう
- 送信ボタンにも、<input>要素を用いる。
input 要素にはtype属性を指定することができ、type属性にsubmit を指定すると、入力欄ではなく、下の図のような送信ボタンになる。
ボタンに表示されるテキストは、日本語のブラウザではデフォルトで「送信」になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/bad56039-2ddb-a16a-f15a-30be461cdd48.png)

- value属性

ボタンに表示されるテキストを変更することも可能。
value 属性に任意の値を指定することで、ボタンに表示されるテキストを変更することができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/564a8004-8db8-b203-85a8-dbb99851704e.png)

#### 複数のセレクタに同じCSSを指定する

- 複数のセレクタをコンマ（,）で区切ることで、それらに同じCSSを適用することができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/304e35b3-8376-b7d7-6c69-4fde5acc7813.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/5e994627-63b0-5e10-30ad-882731930acf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123154/8b80fc84-0ec8-9a05-81de-941a77be92f3.png)
Node.jsではmysqlよりmysql2を使うべき理由

mysql2が一番Weeklyダウンロードが多い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/1b2a339a-a99a-6b47-34ec-8c622bda733d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/2528898b-49d3-bac5-ea35-63214f68e3e5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3127414/06c341f9-d4c0-3b60-30ea-c5d874181d50.png)
[初心者向け] [GitHub Actions] Cacheを使ったNode.jsのパッケージのインストールの方法と仕組みについて徹底解説

## 概要
Node.jsの必要なパッケージをインストールする際はワークフローを実行するたびに新しいrunnerを使用する関係でパッケージを1からインストールします
パッケージが少ないうちはいいものの、プロジェクトが大きくなるにつれてパッケージが多くなるとパッケージのインストール時間分ワークフローの実行時間が長くなってしまいます
そこでパッケージをインストールする際はCacheを使うとパッケージがどんなに多くてもインストール作業を数秒以内に終わらせることができます
今回はGitHubの公式で公開されている
- actions/cache
- actions/setup-node

について解説していきます

## actions/cache
公式が出しているActionで今回使用するNode.js以外の言語やDockerのCacheも扱うことができます
詳細は以下の公式ドキュメントに記載されています

https://github.com/actions/cache

以下を例に説明します
```yml
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: '**/node_modules'
          key: node-modules-${{ hashFiles('**/package-lock.json') }}
      - name: Install dependencies
        run: npm ci
```

### path
今回Cacheするのはnode_modulesで`**`をつけるとソースコード内にある全てのnode_modulesのCacheを作成します
`**`をつけることでnode_modulesのパスが変更したとしてもCacheを作成してくれるので便利です

### key
Cacheを参照する際に一意のkeyが必要です
```
key: node-modules-${{ hashFiles('**/package-lock.json') }}
```
`node-modules`の箇所はどんなCacheか判別できさえすれば任意の値で大丈夫なのですが
```
${{ hashFiles('**/package-lock.json') }}
```
で一意のkeyを作成します
package-lock.jsonを指定しているので必ずGit管理下に置く必要があります

### hashFiles関数
ワークフロー内で使用できるGitHub Actions独自のメソッドです

>path パターンに一致するファイル群から単一のハッシュを返します。

>この関数はマッチしたそれぞれのファイルに対するSHA-256ハッシュを計算し、それらのハッシュを使ってファイルの集合に対する最終的なSHA-256ハッシュを計算します。

簡単に説明するとpackage-lock.jsonの内容をもとに一意のハッシュ値を作成しています
以下のように`node-modules-<package-lock.jsonのハッシュ値>`がCacheを参照する際のkeyとして使用されます
2回目以降のパッケージのインストールはkeyをもとに該当するCacheを探します
該当するCacheがあればそれを使用するのでパッケージのインストールが高速化されます

![スクリーンショット 2023-07-05 8.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625980/a978e9dd-527a-525f-a51c-3e2e69e3994f.png)

新たなパッケージがインストールされるとpackage-lock.jsonが変更、つまりkeyの値が変わるのでインストール作業を1から行い、新たなkeyをもとにCacheを生成します
そのため、package-lock.jsonなど頻繁に変更されないファイルを使ってCacheを生成するのが一般的です

詳細は以下の公式ドキュメントに記載されています

https://docs.github.com/ja/actions/learn-github-actions/expressions#hashfiles

## npm ci
CI/CDではパッケージをインストールする際はnpm installではなく、npm ciを使用します
npm ciを使用するとパッケージの依存関係の解消は行わずに常に package-lock.json を見てnode_modulesを削除してからパッケージのインストールを行います
仮に依存関係が間違っている場合はnpm installのように依存関係を解決せずに実行するのでエラーを出してくれます
そのため、actions/cacheの公式ドキュメントでもnpm installではなく、npm ciを推奨しています

https://docs.npmjs.com/cli/v8/commands/npm-ci

## actions/setup-node
setup-nodeでも同様のことができます
```yml
    - name: Cache Dependencies
      uses: actions/setup-node@v3
      with:
        node-version: '16'
        cache: 'npm'
      - name: Install dependencies
        run: npm ci
```
actions/cacheと比べて記述が楽な上にNode.jsのセットアップも同時にできます
しかし、複数ワークフローで使用するとワークフローの数だけCacheが生成されてしまうのでactions/cacheの使用を推奨しています

https://github.com/actions/setup-node/issues/409

setup-nodeの詳細は以下の公式ドキュメントに記載されています

https://github.com/actions/setup-node

## 参考
https://github.com/actions/cache

https://github.com/actions/setup-node

https://docs.github.com/ja/actions/learn-github-actions/expressions#hashfiles

https://qiita.com/mstssk/items/8759c71f328cab802670
デバックの考え方

◎デバッグとは
意味：バグを無くす
デバックは、プログラミングに問題があった時にそれを解決すること。

○初心者にとって特に重要！！→なぜ重要なのか？
・自走力を身につけるため
　　プログラマーとして仕事をするには、自分で問題を解決するのが重要
・学習効率を向上させる
　　一般的なデバッグの知識は付け焼き刃の知識ではない。
　すべてのプログラミングの学習に通じる考え方なので応用が効く。

○どうやってやるのか？
　STEP1
　　証拠集め（情報収集）
　STEP2
　　証拠を解釈（情報の意味を把握）
　STEP3
　　犯人を推理（原因を推測）

・具体的に
　STEP1
　　証拠集め（情報収集）
　　・エラーが、出ている確認！　<font color="red">一番大事</font>
　　エラーは、最大のヒントです。ダイイングメッセージみたいなもの
　　読まないのはもったいない！！

　　・どういう場合に動かなくなるのか？
　　何をした時に動かなくなるのか？

　　どこまで動いている？
　　ブレークポイントなどを使いどこまで確実に動いているのか確認する

※もし証拠がない場合でも、証拠がないことが証拠と言えます👍


　実際はどうするのか？
　　・HTML・CSSなら現状確認
　　どういうCSSが適用されているのかまずは確認する。
　　computedの欄を見る。
　　
  　・サーバーサイド、フロントエンドなら
　　まずは、エラーがでていないかチェック
　　サーバーサイドだならターミナル　フロントエンドならコンソールを確認する。

STEP2
　証拠を解釈（情報の意味を把握）
　①エラーメッセージの意味は？
　エラーメッセージに答えが書いている場合
　がほとんど。だが、エラーメッセージを読んでその意味を理解しないといけない。

翻訳ツールを使おう！
　それでも意味が分からなければググって意味を調べよう
　Deeplという翻訳ツールがおすすめ‼️

②同じ状況に陥っている人を探す
　エラーメッセージもなくて動かない場合もある。そういうときは同じことが起こっている人がいないかググって確認しよう。

○具体例
　undefind method 〇〇 nil:NilClassと出たとする

　まずは翻訳する
　未定義メソッド 〇〇 nill:NIllClass

　ググる
　エラー文を見た時に、エラーの上の方に書いてある undefind method name’ for nil:NilClass
　という文言が原因究明のヒントになる。この文は何の値も入っていない空のメソッドに対してnameが適用されているから。エラーになっているということを意味している。

※ライブラリを読むのも良いです👌
STEP3
　犯人を推理（原因を推測）
　問題のある箇所をよく見てみよう
　状況が把握できている状態で問題の箇所をよく見れば正解がわかるかも？

　ブレークポイントで怪しいところを確認
　原因と思われるところをブレークポイントで値を確認する。犯人はお前だ！と言いつける気分でやること。

○具体例
　undefind method 〇〇 nil:NilClassと出た場合

　まずはエラーが起こってる箇所を見直す
　エラーメッセージの意味がわかっている状態で見れば意外にわかったりする。
　何行目で起こっているかも出ている。

　なぜNillになっているのか確認する
　ブレークポイントを設定して、該当するインスタンスの値を確認する。そして、なぜそれがNillになっているのか考える。


○まとめ
　デバックは、謎解きです！

　証拠集め（情報収集）　証拠を解釈（情報の意味を把握）　犯人を推理（原因を推測）
　初め二つは初心者でもできる！！間違えても大丈夫👍

　この二つをやると、推理がよりできるようになる。

　初心のうちは、<font color="red">最低３０分！！！！</font>は考えて悩もう！それでも分からなければ人に聞こう🙆
SageMaker Studio abalone （Missing optional dependency 'fsspec'）


# TL ; DR
SageMaker Studio習得のため[abalone](https://docs.aws.amazon.com/sagemaker/latest/dg/define-pipeline.html)を使い自分のデータでやってみたところ、使いこなすのに物凄い時間がかりました。解決法がネットになく、色々勉強しかなり遠回りしてしまったので、もし同じ境遇の方のお役に立てば幸いです。数回に分けて、エラーをどうやって解消したかを記載しています。

# エラー
```
ImportError: Missing optional dependency 'fsspec'.  Use pip or conda to install fsspec.
```

prepsocess.pyの中で、上記エラーが発生。
簡単にpip install fsspecで解決かと思ったら、全然解決しない。。。
情報を探すも、どうもぴったりなものがなく、多くは英語なので途方に暮れました。。。

# 解決法
preprocess.pyで以下を訂正

誤：df = pd.read_csv("s3://MyDirectory/MyDataset.csv")
正：df = pd.read_csv(f"{base_dir}/input/MyDataset.csv")


MyDirectory：S3の保存場所
MyDataset：自分のデータセット（csv形式）
base_dir = opt/ml/processing

# 背景
preprocess.pyの中で、S3に直接データセットを取りに行ったのが原因のようでした。
色々と調べた結果、opt/ml/processingはコンテナにあるので、そこからS3に直接取りに行くのはNGと理解しました。

# 補足情報
別途、記述しますがSageMaker Studioでは3つの異世界？が存在します。
1つ目はos.getcwd()で表示される世界（EFSのこと）
2つ目はopt/mlのコンテナの世界
3つ目はS3の世界
そこが最初はなかなか理解できずに、混乱しました。
1つ目の世界でdfとして読込したのに、2つ目の世界ではdf not definedとエラーが出るので？？？状態でした。


# 参考


[Amazon SageMaker Pipelines を実際に使ってみた【前編】[re:Invent 2020]](https://qiita.com/knt078/items/73d4f94286238bd1077c)
[Amazon SageMaker Pipelines を実際に使ってみた【後編】[re:Invent 2020]](https://qiita.com/knt078/items/5b862d4539e7fa1c16df)
[Amazon SageMaker Pipelineを動かしてみた](https://qiita.com/niwashing/items/6a148787a7faf3cad0b3)
エンドポイントって、一体なにを指している？

## 困っていること
**エンドポイント**って用語が、問題集や公式ドキュメントに散在しています。

AWS では、あんまりルータとか、L3スイッチとか、L2スイッチとかを見かけません。
代わりに何かが何かと接続する場合は、このエンドポイントという用語がよく登場します。

## 一言で簡単明瞭に
- **VPC** エンドポイント
AWS のサービスは、各々独立して存在しており、接続するコンポーネントがなければ、互い通信できません。そのため VPC エンドポイントが必要になります。

- **グローバルアクセラレータ**エンドポイント
- **API** エンドポイント
MATLABでargmax

MATLABでargmax, argminをするときはmax, min関数を使う。

# max, min
行列から最大値・最小値を取得する、いわゆるフツーのmax, min
```matlab
>> values = [93, 47, 102, 39];

>> max(values)
ans = 102

>> min(values)
ans = 39
```

# argmax, argmin

max, min関数で戻り値を２つ指定すると、１つ目の戻り値に最大値、２つ目の戻り値に最大値のインデックスが返される。

```matlab
>> values = [93, 47, 102, 39];

>> [max_value, max_index] = max(values);
max_value = 102
max_index = 3

>> [min_value, min_index] = min(values);
min_value = 39
min_index = 4
```
🐣【Ruby入門】ファイル読み込みから採点する簡易機能実装

Rubyを使って、ファイル（txt）を読み込んで、採点できるような簡易機能を実装してみました。:writing_hand:

## 前提
- ファイル構成
  - scoring.rb
  - test.txt（問題の回答を改行して記載したとする）
- 考慮していない点（簡易版なので。。:angel_tone2:）
  - ファイルの存在チェック
  - 回答が不十分の場合（回答が３つ未満、４つ以上の場合）
  - 全問正解しか判断できない、不正解があった時に何個不正解なのか、何個正解なのか分からない
  - エラーハンドリング
  - etc..

## ファイル
```ruby:scoring.rb
answer_arrays = ['1', '2', '3'] # 答えを配列で管理する
index = 0
is_incorrect_answer = false # 不正解があった場合 true にする

filename = ARGV[0] # コマンドラインからデータを入力する　ex. ruby scoring.rb test.txt
file = File.open(filename) # ファイルを読み込む
file.each_line do |line| # ファイルの中身を１行ずつ読み込む
    unless line.chomp.eql?(answer_arrays[index]) # 答えと比較し間違っていたら true にする
        is_incorrect_answer = true
        break # 一個でも不正解あれば繰り返し処理終了
    end

    index += 1 # 次の answer_arrays を取得する為に+1する
end

file.close # ファイルを閉じる

if is_incorrect_answer
    print '不正解があります'
else
    print '全問正解です'
end
```

```text:test.txt
1
2
3
```

## 実行
```terminal:Console
ruby scoring.rb test.txt
# => 全問正解です
```

## 所感
- rubyには、加算子（++）が無いので、「+= 1」は何か嫌だな。。
- `line.chomp.eql?`に関して、`chomp`が無い`line`には改行コードが含まれてしまう為、`chomp`を使って改行コードを取り除いた文字列で判断している。
  - [String#chomp(Ruby 3.0)](https://docs.ruby-lang.org/ja/3.0/class/String.html#I_CHOMP)
🐣【Ruby入門】Arrayを使っておみくじを実装してみる

[class Array(Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/class/Array.html)を用いておみくじを作ってみよう。:pencil2:


```ruby:sample.rb
omikuzi_array = ['大吉', '吉', '中吉', '小吉', '末吉', '凶', '大凶']

p omikuzi_array.sample
# => "大吉"
p omikuzi_array.sample
# => "小吉"
```

## 解説
- Arrayの[sampleメソッド(Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/class/Array.html#I_SAMPLE)を使用しました。
  - ランダムに要素を取得してくれる。（[Kernel.#srand(Ruby 3.0)](https://docs.ruby-lang.org/ja/3.0/class/Kernel.html#M_SRAND)が有効）
  - `Arrayの#sample(n)`のように要素を指定して取得することもできる。


---

```ruby:sample.rb
omikuzi_array = ['大吉', '吉', '中吉', '小吉', '末吉', '凶', '大凶']

p omikuzi_array.shuffle.first
# => "大吉"
p omikuzi_array.shuffle.first
# => "小吉"
```

## 解説
- Arrayの[shuffle(Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/class/Array.html#I_SHUFFLE)を使用しました。
  - `Arrayの#shuffle`で配列の要素をランダムにシャッフルします。
   - `first`で配列の先頭の要素を返します。要素がなければ`nil`を返します。


## 所感
- if文やeachなど使用せず、シンプルに書けたのが良かった。
- Randomも指定できるので、sample(random: Random)、shuffle(random: Random)色々調整できそう。
🐣【Ruby入門】puts、print、p、ppメソッドの違い


「puts、print、p、pp」は出力用のメソッドで使用されますが、改めて違いに関して整理したいと思います。:pencil2:

## puts
- オブジェクトを出力後に**改行**する。
- [Kernel.#puts（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Kernel/m/puts.html)

```ruby:sample.rb
puts 'hellow', 'world'
# => hellow
# => world
```

## print
- オブジェクトを出力後に**改行**しない。
- [Kernel.#print（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Kernel/m/print.html)

```ruby:sample.rb
print 'hellow', 'world'
# => hellowworld
```

## p
- オブジェクトを出力後に**改行**する。
- 引数で渡されたオブジェクトがそのまま戻り値になる。
- [Kernel.#p（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Kernel/m/p.html)

```ruby:sample.rb
puts '1' # => 1
p '1' #  => "1"

puts 1 #  => 1
p 1 #  => 1

puts '' #  => （空行）
p '' #  => ""
```

## pp
- オブジェクトを出力後に**改行**する。
- 引数で渡されたオブジェクトがそのまま戻り値になる。
- pメソッドとは違い、オブジェクトの構造を表示する際に、適当に改行を補って見やすく整形してくれる。
- [Kernel.#pp（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Kernel/m/pp.html)

```ruby:sample.rb
p [{ a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }]
# => [{:a=>"aaa", :b=>"bbb"}, {:a=>"aaa", :b=>"bbb"}, {:a=>"aaa", :b=>"bbb"}, {:a=>"aaa", :b=>"bbb"}]

pp [{ a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }, { a: 'aaa', b: 'bbb' }]
# => [{:a=>"aaa", :b=>"bbb"},
#     {:a=>"aaa", :b=>"bbb"},
#     {:a=>"aaa", :b=>"bbb"},
#     {:a=>"aaa", :b=>"bbb"}]
```

## 所感
- 何気なく使用していたメソッドを改めて見ると、用途に合わせて使い分けた方が良いと思った。
- 他にも戻り値が「nil」か「引数のオブジェクト」の違いがあり、呼び出すメソッドも「to_s」か「inspect」の違いもあったが、入門としてはここまで良いかなと思う。
  - [Object#to_s（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Object/i/to_s.html)
  - [Object#inspect（Ruby 3.0）](https://docs.ruby-lang.org/ja/3.0/method/Object/i/inspect.html)
クロス集計表を作成する2＊2_度数(SPSS Modeler データ加工逆引き11-10)

# クロス集計表を作成する（2＊2_度数の集計表）

![スクリーンショット 2023-02-06 18.12.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/dd98067d-3704-64b9-1674-841d2927d855.png)

## 1.想定される利用目的

・データ理解のためのレコード度数分布確認
・固定帳票の作成


## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/cross_tabulation2_2f.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2023-01-23 10.29.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6e6b1a14-02c6-3d38-3f09-7462a640a2bc.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2023-02-06 18.13.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2f9ce077-1c1d-cba7-8880-a6174b27b8ea.png)

b.　[フィールド作成]ノードを編集します。[血液型]と[年代]を　[ >< ]で文字列結合します。　
![スクリーンショット 2023-01-23 10.33.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ebfc37da-4ec7-3b1d-8de1-64b5c5f193c2.png)

[プレビュー]します。
![スクリーンショット 2023-02-06 18.26.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7bbd94e0-f163-3a59-0ccd-35d6baa3e166.png)


c.[データ型]ノードで　[値の読み込み]ボタンを押して後続dのために合成変数の値を認識します。

d.[再構成]ノードを以下のように編集します。[合成変数]を[再構成フィールド]に移して[値フィールド]はブランクのまま[数値フラグを作成]を選択します。
![スクリーンショット 2023-01-23 10.34.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e70da876-296c-a766-7c8c-d52e1c991351.png)

[プレビュー]します。
![スクリーンショット 2023-02-06 18.17.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3fb59ad7-69a4-bd2d-2771-6f19699a9137.png)

e.[レコード集計]ノードを以下のように編集します。
![スクリーンショット 2023-02-06 18.15.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/15fcbf46-d004-55dd-6faa-2127292f18e6.png)

f.[ソート]ノードで[年代]を[昇順]ソートします。

g.[フィルター]ノードで集計の過程で各フィールドに自動付与された[_Sum]を取り除きます。

h.[フィールド順序]ノードで適宜表示する列の順番を変更します。

[デーブル]ノードを実行します。
![スクリーンショット 2023-02-06 18.20.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cf43017e-755b-fa2d-2f4c-7b493479512a.png)

#### 注意事項

[再構成]ノードで列に展開するメンバーが表示されないときは前方でデータ型の[値の読み込み]を実行します。
Excelで表頭・表側を入れ子にすると表が見やすくなります。

## 4.参考情報

####  SPSS Statistics Custom Tablesと連携して多重クロス集計を作成する

https://www.ibm.com/blogs/solutions/jp-ja/spss-stats-tips-06/

####  カテゴリ値を列に展開してIDで集約　縦持ちを横持ちへ

https://qiita.com/416nishimaki/items/2519553c7cce0fc0b0e0

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

https://qiita.com/416nishimaki/private/503037195081d3323eee

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Rubyのdigをpythonでやる

## 課題
ネストされたdictから特定の値を取り出したいとき

## Rubyの場合
以下のように、nullチェックをしながらいい感じに取り出してくれる
```rb
data_a = { 'name': { 'first_name': 'yamada', 'last_name': 'taro' } }
data_b = { 'name': { 'last_name': 'taro' } }

p data.dig('name', 'first_name')
# => yamada

p data.dig('name', 'first_name')
# => nil
```

## Pythonの場合
digのようなメソッドはないので愚直にやると以下のような方法になる。
```py
data_a = { 'name': { 'first_name': 'yamada', 'last_name': 'taro' } }
data_b = { 'name': { 'last_name': 'taro' } }

if 'name' in data_a and 'first_name' in data_a['name']:
    print(data_a['name']['first_name'])
else
    print(None)
# => yamada

if 'name' in data_b and 'first_name' in data_b['name']:
    print(data_b['name']['first_name'])
else
    print(None)
# => None
```


`get()`演算子を使うとスマートになる。

```py
print(data_a.get("name", {}).get("first_name", None))
# => yamada

print(data_b.get("name", {}).get("first_name", None))
# => None
```

python3.10以降では`>|`演算子を使った書き方もできるらしいが、個人的にはスマートには見えなかったので割愛
wiresharkで保存したデータをpysharkで扱う

# はじめに
WiresharkでキャプチャしたデータをPythonで使いたい。
そんなあなたに「pyshark」。
結構探しても出てこなかったのでまとめておきます。
# インストール
インストールはこれだけ
```:コンソール
 $ pip install pyshark
```

# 使ってみる
Wiresharkで保存したデータを読み込んで一つ目のパケットを覗いてみる。
```python:main.py
import pyshark
capture = pyshark.FileCapture("Wiresharkで保存したファイル.pcapng")
print(capture[0])
```
上記のコードを実行すると、
```
Layer ETH:
        Destination: 00:00:00:00:00:00:00
        Address: 00:00:00:00:00:00
        ...
Layer IP:
        0100 .... = Version: 4
        .... 0101 = Header Length: 20 bytes (5)
        ...
Layer TCP:
        Source Port: ~~~
        Destination Port: ~~~
        ...
```
パケットの情報がいろいろ表示される。
```python
print(capture[0].layers)
```
でレイヤーの種類が見れる。

# フィルターを使う
引数にdisplay_filterを追加する
```python
capture = pyshark.FileCapture("Wiresharkで保存したファイル.pcapng",
                                display_filter='ip.src == xxx.xxx.xxx.xx')
```

# 暗号化されたデータを復号化する
wiresharkで復号化したときのSSLKEYLOGFILEを引数に使う。
```python
capture = pyshark.FileCapture("Wiresharkで保存したファイル.pcapng",
                                override_prefs={'tls.keylog_file':"SSLKEYLOGFILEに保存したファイル")})
```

# リアルタイム処理したいときは
リアルタイム処理したいときはLiveCaptureを使う。
```python
capture = pyshark.LiveCapture ('イーサネット', bpf_filter='フィルター')
```
※注意：pythonコードを実行する前にSSLKEYLOGFILEを更新しないとうまくいかない。

# うまくいかない場合は
引数のdebugをオンにして頑張る。
裏ではtsharkが動いているのでtsharkの実行コードなどが覗ける。
```python
capture = pyshark.FileCapture("Wiresharkで保存したファイル.pcapng",
                                display_filter='ip.src == xxx.xxx.xxx.xx',
                                override_prefs={'tls.keylog_file':"SSLKEYLOGFILEに保存したファイル")},
                                debug=True)
```

# 参考文献
https://milestone-of-se.nesuke.com/nw-basic/tls/decrypt-tls-at-executing-packetcapture/

https://www.mieruka.link/2021/06/06/%E3%80%90python%E3%81%A7%E3%83%AA%E3%82%A2%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E5%88%86%E6%9E%90%E3%80%91pyshark-livecapture%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/

https://github.com/KimiNewt/pyshark/issues/417

https://qiita.com/tamolab/items/9892be82e92efc603a21
顧客分析の手順 - 分析フォーマットの適用例:関連性分析 特定セグメント支持商品の理解

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


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


# 顧客分析の手順

## 第21回： 特定セグメント支持商品の理解
関連性分析を利用した分析例として、今回は「優良顧客の育成」をテーマとした分析例をご紹介します。今回の分析例では、特定商品を購入した顧客群の、他の購入商品を理解します。

### 分析の前提
この分析では、商品分類毎の購入顧客数構成比を指標値として用います。計算方法としては顧客数を分母に、特定商品分類に属する商品を購入した顧客数を分子に算出しています。言わば商品分類毎の顧客支持度合いです。図31A は家電商品の中でも特定の商品分類をいくつかピックアップし、それぞれの購入顧客数構成比を把握しています。1つは顧客数全体を対象とした分析、そしてもう 1つは携帯音楽プレイヤーを購入した顧客を対象セグメントとした分析結果です。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/93da0704-78b0-f6d7-d908-c76e8d17c8bb.png">



2つのグリッドチャートを見ると、共に合計が 100% を超える数値となっているのがわかります。これは、1人の顧客が、いくつかの商品を購入しているために発生しています。また一方、1人の顧客が特定商品分類配下の商品を複数購入しても、分子の数字としては 1 とカウントされます。これにより、1人の顧客が当該商品をどの程度購入しているかは集約の過程で埋没して見えなくなりますが、その顧客が当該商品に対して「購入」という行動を起こしたか否かを理解することが可能となります。

### 購入支持傾向の比較
図31A をグラフにしたのが図31B と図31C です。図31B では顧客数全体を対象としており、ほぼ（会員カードを提示しない非会員の買上を除く）この家電チェーンの支持状況を捉えています。ヘッドフォンを購入した顧客は全体の 12.4% で、表示された商品の内では最も低く、最も支持率が高いのは携帯ゲーム機の 45.2% となっています。ついでノートパソコン、デスクトップパソコン、そしてオーディオ機器、ヘッドフォンの順です。したがって全体の陳列や品揃えという意味からすると、このような構成比に準じた割合で各商品をプッシュする必要があります。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/190e409f-1ece-429d-b156-7945bc0397fa.png">

これに対して図31C は、対象顧客セグメントとして、携帯音楽プレイヤーを購入した顧客群を設定しています。したがって図31B よりも顧客数は少なくなり、したがって分母となる値も少なくなります。仮に携帯音楽プレイヤーの購入顧客数構成比を算出すれば、この値は 100% となります。

<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/5bef6d98-efa7-2432-76d0-3de9f9ce51e4.png">

そしてこの図31C に図31B と同じ商品を配置させて、同じ購入顧客数構成比を算出すると、異なる結果が表れます。順番は変化し、ヘッドフォンはトップで 49.8% の購入顧客数構成比を示しており、これに続いて、ノートパソコン、携帯ゲーム機、そして大きく差が開いて、デスクトップパソコンとオーディオ機器が続きます。

これは携帯音楽プレイヤーを購入した顧客群が、他にどのような商品を購入したのかを意味しています。このような商品間の関連性を理解することにより、その顧客の生活シーンを類推することが可能な場合があります。例えばこのケースでは、携帯音楽プレイヤーに加えて、ヘッドフォンを購入する顧客は音楽を聴く顧客と想定できます。また、ノートパソコンや携帯ゲーム機も含めて考えた場合、「携帯性」、「持ち運びに便利」といったキーワードを思い浮かべることと思います。ヘッドフォンに関してももしかしたらそのような特性(軽くて携帯性に優れているモデル、周りのヒトに迷惑とならないよう音漏れの少ないモデルが選ばれているなど)の商品が良く買われているかもしれません。

このような顧客は外出の用事が多く、その中でなんらか情報にアクセスをしたり、暇つぶしをしなければならなかったりするセグメントとして想定できます。

### アプローチの方向性
したがって、特定されたこのような「移動の多い顧客セグメント」に対しては、新型、軽量、頑丈なミニノートパソコンをご案内することが望ましいかもしれませんし、ワイヤレスアクセスといったサービスを販売する機会があるかもしれません。そして携帯ゲーム機、ノートパソコン、携帯音楽プレイヤー共に、流行り廃りが存在し、買い換えのサイクルもあります。これらを理解できれば、顧客毎の最適なタイミングで買い替えを促すメッセージを案内することも考えられます。

逆に、携帯ゲーム機を何か買ったばかりの顧客に、別メーカーのゲーム機を案内しても無視される可能性は高く、それよりは付属するゲームソフトを案内したほうが好ましい反応を得られる可能性が高いといえます。そして何年か経過し、新しい携帯ゲーム機の販売開始タイミングであれば、顧客も買い換えに応じるかもしれません。このように、同一／類似の顧客をセグメントで切り取ることによって、支持の高い商品群を理解し、加えて購入タイミングを考慮して案内タイミングを非同期化できれば、「最適な顧客に」、「最適な商品を」、「最適なタイミングで」案内することが可能となります。


#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
Netplanでパスワード無しのWifiに接続する方法

# これは何？
Ubuntuなど、ネットワーク設定でNetplanを使用するディストリビューションで、パスワード無しの無線LANに接続したい場合の設定内容です。

なかなかこういうキーワードで検索できなかったので、ここにメモしておきます。

# 本記事のポイント
SSIDの設定として、下記のようにすることで、パスワード無しで接続します。
```
auth:
  key-management: none
```

# 設定方法

/etc/netplan/Netplan に、設定ファイルを作成します。

下記の例では、ファイル名を「90-PublicWifi.yaml」としましたが、お好みでどうぞ。
「FreeWifi」の部分は、接続先のSSIDに置き換えてください。
「wlp1s0」の部分は、お使いのPCのWifiデバイス名に置き換えてください。

```90-PublicWifi.yaml
network:
  wifis:
    wlp1s0:
      dhcp4: true
      access-points:
        FreeWifi:
          auth:
            key-management: none

  version: 2
```

Wifiデバイス名は「ip a」コマンドなどで確認してください。

# 参考資料

https://netplan.io/reference
[備忘録][python][競プロ]Leet文字のプログラムを６通りで書いてみた。

# はじめに
競プロとかアルゴリズムのお勉強をしていると、文字列をleet文字列に変換するプログラムを書く機会がありました。ちょっと調べてみるだけでも6通りほどの書き方を見つけて、結構知らない知識を得られたので備忘録として記事に残します。

# leet文字とは
以下の表の変換規則に則って文字列を書き換えるものです。簡単にいうとアルファベットを似た形の別の文字に置き換えることです。

入力文字|変換後文字
:--|:--
O|0
I|1
Z|2
E|3
A|4
S|5
G|6
T|7
B|8
P|9

# 実装
## 実装１ : 力技
```python
s = str(input())

ans = ''

for i in s:
  if i == 'O':
    ans += '0'
  elif i == 'I':
    ans += '1'
  elif i == 'Z':
    ans += '2'
  elif i == 'E':
    ans += '3'
  elif i == 'A':
    ans += '4'
  elif i == 'S':
    ans += '5'
  elif i == 'G':
    ans += '6'
  elif i == 'T':
    ans += '7'
  elif i == 'B':
    ans += '8'
  elif i == 'P':
    ans += '9'
  else:
    ans += i

print(ans)

```
多分一番最初に思いつくであろうif文でゴリ押す方法です。

## 実装2 : リストとreplaceを用いる。
```python
s = str(input())

leets = [['O', '0'],['I', '1'],['Z', '2'],['E', '3'],['A','4'],['S', '5'],['G', '6'],['T', '7'],['B','8'],['P','9']]
for leet in leets:
  s = s.replace(leet[0], leet[1])

print(s)
```
リストに対応関係を入れてそれをreplaceを用いて入力された文字列に対して適応していく方法です。
僕が最初に書いたのはこれでした。


## 実装3 : 辞書とtranlateを用いる。
```python
s = str(input())

leets = {'O': '0', 'I': '1', 'Z': '2', 'E': '3', 'A':'4', 'S': '5', 'G': '6', 'T': '7', 'B':'8', 'P':'9'}

s = s.translate(str.maketrans(leets))

print(s)
```

## 実装4 : joinとget、内包表記
```python
s = str(input())

leets = {'O': '0', 'I': '1', 'Z': '2', 'E': '3', 'A':'4', 'S': '5', 'G': '6', 'T': '7', 'B':'8', 'P':'9'}
s = ''.join(leets.get(i, i) for i in s)

print(s)
```
get(a, b)はaで指定したものがkeyとして存在していればvalueを、存在していなかったらbの値を返す辞書型のメソッドです。

## 実装5 : mapと自作関数
```python
def make_leet(c):
  leets = {'O': '0', 'I': '1', 'Z': '2', 'E': '3', 'A':'4', 'S': '5', 'G': '6', 'T': '7', 'B':'8', 'P':'9'}
  return leets.get(c, c)

s = str(input())
s = ''.join(list(map(make_leet, s)))

print(s)
```

## 実装6 : lambda式を使う方法
実質５番と同じ。
```python
s = str(input())

leets = {'O': '0', 'I': '1', 'Z': '2', 'E': '3', 'A':'4', 'S': '5', 'G': '6', 'T': '7', 'B':'8', 'P':'9'}
s = ''.join(list(map(lambda c: leets.get(c, c), s)))

print(s)

```

# 最後に
他にも実装方法はあるかと思うので、面白いものがあればコメント等で教えてください〜！！
List と LINQ と params object[]

`params object[]` でなんでも受けようとすると、配列以外の配列っぽいものはソレそのものが単一の `object` として入ってきます。

```csharp
void PrintToConsole(params object[] values) => string.Join(", ", values);


var array = new string[] { "A", "B", "C" };
var list = new List<string>(array);
var linq = array.Where(x => true);
var linq2 = array.FirstOrDefault();

PrintToConsole(array);  // A, B, C
PrintToConsole(list);   // System.Collections.Generic.List`1[System.String]
PrintToConsole(linq);   // System.Linq.Enumerable+WhereArrayIterator`1[System.String]
PrintToConsole(linq2);  // A
```

ココから `ToArray()` が必要な LINQ と List だけを選ぶには 👇


|`values[0] is`|`IEnumerable`|`IEnumerator`|`ICollection`|   |
|---:|:---:|:---:|:---:|---|
|`string`|〇|×|×| 文字列が IEnumerable
|`List<string>`|〇|×|〇| お前 IEnumerator 無いんか
|`LINQ (Where)`|〇|〇|×| モノによって型が違う問題


`IEnumerator` か `ICollection` のどちらか。  
ただし、これらを実装した List/Linq 以外の何かが来たら終わる。`IToArrayable` の登場が待たれる。

--

見直すと `IEnumerable` で `string` では無いものは `foreach` なり何なりが一番良さそう。


--


そもそも `params object[]` なんて使わない方が良いんでしょうね。でも雑で良い部分で使うには便利なんだよなー。

以上です。お疲れ様でした。
マネージメント職で知らない人アウト！ダニエルキムの成功循環モデルについて考えてみた

# ダニエルキムの成功循環モデルご存知ですか？
ダニエルキムの成功循環モデルの言葉やモデル自体をマネージメント職で知らない人はいるかもしれません。
でもモデルの中身の意味を知らないマネージメント職の人が居たらアウトです！
言葉は知らなくても経験上やってる人は沢山いると思います。
体系立てて説明しているのがこのモデルです。

# ダニエルキムの成功循環モデルとは
下の図の左側の赤である結果の質から始めると失敗しますよという話で、右側の赤である関係の質から始めると成功しまうよという話です。

## 失敗の例
先ず売上目標を決めて全員で目標に向かって仕事をする。エンジニアの場合は、採用人数とか、バグ発生数とかデプロイ数とかがあると思います。
最近の企業だとKPIやKGIを決めてそこに向かうマネージメントは一般的です。

これが失敗の循環モデルだとダニエルキムさんは言います。

関係値がしっかり気づかれてないのにいきなり結果を求められても誰もついていかない。
１．結果の質を求める：ゴールを決めて目標を決めて結果を求める　
２．関係の質を求める：仲良くしようとしても、結果がでないので関係に亀裂がおこる　
３．思考の質を求める：思考を合わせようと話し合うが関係値が壊れているので疑心暗鬼になる
４．行動の質を求める：疑心暗鬼なので行動も消極的になる
５．結果の質を求める：更に結果がでなくなる

よくある悪循環です。

![スクリーンショット 2023-02-15 7.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/fa9700c4-2712-bba2-e5c3-0774cd19156e.png)

## 成功の例
先ず関係値を良くする。相手を知って自分をしってもらうプロセスから初めて、思考をあわせていけば、行動に関してディスカッションしても前向きな議論が出来ます。
これによって自然と結果がよくなります。

これが成功の循環モデル。

１．関係の質を求める：先ず関係値を良くする。相手を知って自分をしってもらう
２．思考の質を求める：関係地が出来たので、思考について話あって、高い思考レベルで合意する。フレームワークについて話たり、アーキテクチャについて話あう
３．行動の質を求める：テストをしっかりやろうとか、納期は守ろうとか、勉強会をやろうとか行動の質を高める
４．結果の質を求める：自然と納期が守れて、バグもなく、採用も結果が出る
５．関係の質を求める：良い結果と良い仲間が増えて、更に関係値がよくなる　

最高な組織の出来上がりです。

![スクリーンショット 2023-02-15 7.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/fa9700c4-2712-bba2-e5c3-0774cd19156e.png)

# 実際はどうなのか？
CTOとして１０社、２０年、技術顧問として２０社以上見てきた森川からすると、これは正しくその通りです。
結果から話しても誰もついていかない。余計に関係がわるくなるのは、よくある悪い組織事例の典型例です。
良く会議が始まる前にアイスブレイクがあります。これは、最初に関係値を良くするためです。先ずはお互いをしる事や緊張をなくす方法です。

お互いを知らない状態で結果の話をしても空気悪くなるだけです。1on1とか、飲み会とか、遊びとかで関係値を構築しておくとその後がとても仕事がやりさすい。
上司でも冗談を言ってもらえれる状態になることが実がとっても重要。
これは心理的安全性とも言われる事です。
別途、心理的安全性について記事にしたいと思います。

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
PowerApps ポータルで一時保存機能を実現する

# はじめに
PowerApps ポータルで試したことを備忘録として残していきたいと思います。
今回はポータル画面で入力途中でデータを保存する一時保存機能の実現方法です。入力項目の多い画面で一時的に保存する方法で、一時保存ボタンを配置してクライアント側の入力チェックをバイパスしてデータを保存するための方法です。

# 前提
+ ポータルの基本フォームで指定しているモデル駆動のフォームに一時保存を判定する項目を含める（以下のコードでは test_app_draft が該当の項目になります）
+ JavaScriptのコードは基本フォームのカスタム JavaScriptに記述
# コード
ポイントは draftSubmit 関数で、一時保存ボタンをクリックしたタイミングで該当項目を一時保存の状態にしてクライアント側の検証なしでサブミットしています。この関数をクリックで実行するボタンを画面上にJavaScriptで配置します。
あとは、今回は一時保存する項目(test_app_draft)はサブミットさせる必要があるのでフォームに含めて画面ロード時に非表示しています。JavaScriptのみで操作する項目に対してよく利用するテクニックです。
```javascript
$(document).ready(function () {
    $("#test_app_draft).val("100000001"); //送信済状態のステータス
    $("#test_app_draft").hide();
    $("#test_app_draft_label").hide();
    draftSubmit = function() { 
        $("#test_app_draft").val("100000000"); //一時保存状態のステータス
        var buttonName = $("#UpdateButton").attr("name");
        WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(buttonName, "", true, "", "", false, true)); 
    };
    var button ="<input type='button' class='btn btn-primary button submit-btn' value='一時保存' onclick='draftSubmit();'/>";
    $(".form-action-container-left").append(button);
});
```
# おわりに
WebForm_DoPostBackWithOptions関数はASP.NET WebFormで用意されたものなのでポータルはASP.NET WebFormは構築されているようですね。