OmniAICreator/Qiita-1.07M huggingface dataset:
python maya luncher

```lunch_maya2019.bat
set target_dir=%userprofile%\documents\maya\2019
if not exist %target_dir% mkdir %target_dir%%target_dir%\scripts\userSetup.py%USERPROFILE%\Documents\maya\2019\scripts\ /it
robocopy J:\s\tool\tools\pipeTool\tdAsset\pipeline\maya\setup  %target_dir%\scripts\ /it
robocopy J:\s\work\project_tools\shelves  %target_dir%\prefs\shelves\ /it
set MODULE_FOLDER=%userprofile%\documents\maya\2019\modules
if not exist %MODULE_FOLDER% (
    mkdir %MODULE_FOLDER%
)
robocopy J:\s\work\project_tools\modules\mod  %MODULE_FOLDER%\ /it
```

```ueserSetup.py
mel.eval('loadPlugin pgYetiMaya;')
```

```pgYetiMaya.mod
+ yeti any J:/s/work/project_tools/modules/yeti/3.5.0/deploy
PATH +:= bin;plug-ins
MTOA_EXTENSIONS_PATH +:= plug-ins
MTOA_PROCEDURAL_PATH +:= bin
ARNOLD_PLUGIN_PATH +:= bin
RFM_PLUGINS_PATH +:= bin
REDSHIFT_MAYAEXTENSIONSPATH +:= plug-ins
peregrinel_LICENSE=s@localhost
```
VS Codeで定義元に移動するショートカットキーを動作させる ～PHP編～

## はじめに
VS Codeを使い始めて数時間、クラスや関数、変数が定義されているコードにジャンプしたくなり、ショートカットキー「F12」を押すも反応なし。
File > Preferences > Keyboard Shortcutsを見ても`Go to Definition`には「F12」が設定されているはず…
![keyboard shortcuts](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348786/d891d2dd-79cf-5457-0ecf-3b0456a1ead9.jpeg)

## 環境
- Windows 10 Home 22H2
- Visual Studio Code 1.78.1

## 解決策
いきなりですが、拡張機能の「PHP Intelephense」をインストールすることで解決です。
![PHP Intelephense](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348786/62897af8-2e82-5b36-0b70-8eb44ecc05e5.jpeg)

:::note warn
PHPの場合です。他の言語に対応させるには、それぞれの言語ごとの拡張機能をインストールする必要があります。
:::

公式を見たところ「言語サポートがある場合」と記述がありました…
> If a language supports it, you can go to the definition of a symbol by pressing F12.
> If you press Ctrl and hover over a symbol, a preview of the declaration will appear:

引用：[Code Navigation in Visual Studio Code](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition)

## おわりに
いままでIDEはPHPはPHPStorm、PythonはPyCharm、AndroidはAndroid Studioと言語ごとに最適化された開発環境を使っていたので気づきませんでしたが、VS Codeは初期状態ではまっさらな単なるエディタだということですね。
それぞれの言語ごとに動作させるには、拡張機能のインストールが必要そうです。（むしろ拡張できることが利点なのだと思いますが）
【C++Builder】SQLQueryを使ってuser_versionを取得する方法

データベースはSQLiteを使用
DBアクセス用のコンポーネントはSQLConnectionでconnectして、SQLの実行はSQLQueryを使用。

## やりたかったこと
アプリ開発中にテーブルの構成を変更することになり、DBのversionを取得して、バージョンに応じてALTER TABLEを実行するようにするため、user_versionをDBから情報を取りたかった。のだけど、情報取得の際のキー名がわからなかった。

## SELECTした情報を参照する方法

		SQLQuery1->SQL->Text = "SELECT * FROM Stock;";
		SQLQuery1->Active = true;
		if (!SQLQuery1->IsEmpty()) {
			SQLQuery1->First();
			while(!SQLQuery1->Eof){
				Ansi state = SQLQuery1->FieldByName("productname")->AsAnsiString;
				SQLQuery1->Next();
			}
		}
		SQLQuery1->Active = false;

通常はこんな感じでFieldByNameでカラム名を指定するのだけど、
SQLQuery1->SQL->Text = "PRAGMA user_version;"
として、SQLQuery1->FieldByName("productname")->AsInteger;
としても、「そんなもんはねぇ」と言われてしまい、取得できませんでした。

## "pragrama user_version"の場合
で、結論。

		SQLQuery1->SQL->Text = "PRAGMA user_version;";
		SQLQuery1->Active = true;
		if (!SQLQuery1->IsEmpty()) {
			TStrings *sl = new TStringList();
			SQLQuery1->First();
			if(!SQLQuery1->Eof){
				SQLQuery1->GetFieldNames(sl);
				AnsiString str = sl->Strings[0];
				ret = SQLQuery1->FieldByName(str)->AsInteger;
			}
			delete  sl;
		}
		SQLQuery1->Active = false;


のように、GetFieldNamesでフィールド名を取得して使えばいけました。
それだけ。
VMのWindows11にPowershell7とAZモジュールを入れてみた

まえがき
---
私が使っているMacには仮想OSとしてWindows11が載っているのですが、そこにPowershellの新バージョンであるバージョン7とAZモジュールを入れてみたので備忘録として記載していきます。
試す際は自己責任でお願いします。

※参考にしたページ
https://tomoh1r.github.io/blog/2016/11201_how_to_make_psgallery_trusted_repository.html

目次
---
- まえがき
- 試した環境
- Powershell 7のインストール
- AZモジュールのインストール
- あとがき

試した環境
---
・HostOS: macOS Ventura13.3.1
・VM: Pararelles Desktop バージョン 18.2.0
・GuestOS: Windows11
・M365アカウントは既に作成済み


Powershell 7のインストール
---
以下にインストール時の手順を記載します。

- VMのWindows11を起動
→検索ボックスに「　Powershell」　と入力しEnter
→表示された「Powershell 7」　をクリック

[Powershell画面]
- 以下を実行
> winget search Microsoft.PowerShell

→ すべてのソース契約条件に同意しますか?　の質問に「Y」　と入力
→以下を実行
> winget install --id Microsoft.Powershell.Preview --source winget

- 以下リンクより自分の環境に合わせインストールパッケージをダウンロード（弊環境ではPowerShell-7.3.4-win-x64.msiの方を使用）
https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/PowerShell-7.3.4-win-x64.msi
https://github.com/PowerShell/PowerShell/releases/download/v7.3.4/PowerShell-7.3.4-win-x86.msi

→VM（Windows11）の上部メニューより　「ファイル」をクリック
→「エクスプローラー」をクリック
→「ダウンロード」をクリック
→「PowerShell-7.3.4-win-x64」（ダウンロードしたファイル）をダブルクリックして実行
→「Next」をクリック
→インストール先を指定して「Next」をクリック（私は初期値であるC:\Program Files\PowerShell\を指定）
→画面指示に従い数回「Next」をクリック
→「Finish」をクリック
→インストール完了

- 以下を実行
> $PSVersionTable.PSVersion　を実行

→Powershellのバージョンが表示されるので7がインストールされていることを確認


AZモジュールのインストール
---
続けてAZモジュールをインストールします。

[Windows11ウィンドウ]
→検索のボックスに「powershell 7-preview」と入力
→表示された「powershell 7-preview」をクリック

[Powershell 7-preview　画面]
- 以下を実行
> Install-Module -Name Az -AllowClobber

→実行の許可が求められるため「A」（All）を入力
→画面に表示されるメッセージにて、複数のモジュールがインストールされていることが確認できる
→インストール完了

[Azureに接続する]
- 以下を実行
> Connect-AzAccount -DeviceCode

→表示されたメッセージ内のURL部分をコピーしブラウザURL欄にペースト
→認証コードが求められるため、同様にメッセージ内のコード部分をコピーしブラウザにペースト
→ブラウザのM365ログイン画面に遷移するため、アカウント情報を入力
→認証を求められる場合は認証用スマートデバイスにて「承認」をタップ
→「Microsoft Azure PowerShell にサインインしますか?」と質問されるため「続行」をタップ

[Powershell 7-preview画面]
- TenantIdが表示されAzureCloudへの接続が完了
→以下を実行
> Get-AzVM

→サブスクリプション内のすべての仮想マシンを確認できる

> Get-InstalledModule -Name Az

→Azureモジュールがインストールされていることを確認し今回の目標完了

あとがき
---
以上でPowershell７とAZモジュールのインストールが完了となりました。
仕事で扱うため、Azure関連の投稿頻度が増えてくるかもしれません。
本当はWebデザイン系に全振りしたいところですが、今勤めている会社ではそちらはスコープ外のため止むなし・・・

前向きに捉えて覚えていくしかないですね。
また何か学んだ際には備忘として投稿していくので、もし気に入っていただけたらいいねやお気に入り登録等、よろしくお願いします！
yumの後継、dnfについて（Linux2023）

# 概要
インスタンス作成時のデフォルトAMIが2023になり、yumの後継であるdnfを使う機会も多くなりそうですね。
既に知られているdnfですが、yumばかり使っていたので勉強がてらまとめてみようかと思います。
（以下、Linux2=AL2、Linux2023=AL2023と記載します）

# dnfとは
yumの後継となるパッケージ管理コマンド。
dnfとは、Fedora Linuxディストリビューションで使用されるパッケージマネージャーの一つです。
dnfは「Dandified Yum」の略であり、以前のFedoraバージョンで使用されていたYumパッケージマネージャーの改良版になります。

# 何故yumではいけないのか
端的にいうとyumは廃止となります。
yumはサポート終了となったpython2 系で、yum後継のdnfはpython3 系となり、今後も継続して使い続ける事は出来ないという事です。
AL2023では、yumとdnfどちらも使用する事が出来るようになっています。

# dnfコマンドを実行
例として、以下のようなものがあります。

```
パッケージのインストール: dnf install <package_name>
パッケージのアップデート: dnf update
パッケージの削除: dnf remove <package_name>
パッケージの検索: dnf search <keyword>
```

上記にある通り、パッケージに関するコマンドを実行する上ではyumと変わりはないように思えました。
実行は単純で、yumをdnfに変換するのみとなります。

# 何故yumとdnfで差がないのか

下記に記載するサイトでも紹介されていますが、yumとdnfではシンボリックリンクが同一であるので実行される中身は同じだという事になります。
これはAL2023でも同様でした。↓

```
# ls -l /usr/bin/yum /usr/bin/dnf
lrwxrwxrwx. 1 root root 5 Jan 31 01:01 /usr/bin/dnf -> dnf-3
lrwxrwxrwx. 1 root root 5 Jan 31 01:01 /usr/bin/yum -> dnf-3
```

https://blog.apar.jp/linux/16100/

# /etc/yum.repos.d/以下
AL2と同じくリポジトリの設定は「/etc/yum.repos.d/」に存在します。
/etc/dnfもあるんですがそっちではないんですね〜

AL2、AL2023の/etc/yum.repos.d/以下を比べてみます。
この辺りに差はありそうです。

```
AL2
-rw-r--r-- 1 root root 1003 Oct 26  2021 amzn2-core.repo
-rw-r--r-- 1 root root 2150 Apr 20 18:30 amzn2-extras.repo
```

```
AL2023
-rw-r--r--. 1 root root 968 Apr 11 22:27 amazonlinux.repo
-rw-r--r--. 1 root root 689 Apr 11 22:27 kernel-livepatch.repo
```

# dnfのメリット
結局yumもdnfも同じものを実行しているなら、とりあえずは「yum」で良くない…？という感情にもなりそうです。
しかし、モジュールという概念が追加された事により、運用での実用性があがったように思われます。

「dnf module」というコマンドの実行により、特定の機能や目的に関連するパッケージのグループを定義します。
例えば、phpと指定するのみで必要なパッケージ群も同様に準備してくれるというものです。
これにはアップグレードやリムーブにも対応されており、バージョンの管理等にとても活躍してくれそうです。

# AL2023のdnf module list
上記の通り、モジュールはとても便利そうなのですが、「dnf module list」どんなモジュールがあるのだろうと見てみた所以下の結果でした。
(2023/05/10現在)

```
# dnf module list
Last metadata expiration check: 0:18:47 ago on Wed May 10 02:39:33 2023
```

下記の記事に関連するようで、モジュールのリストは空になっているみたいです。
すべてをモジュール化したけど良くなかったとかで、結局はいつも通りにモジュールインストールする必要があるそうで…

AlmaLinux 9 - “dnf module list” is empty
https://almalinux.discourse.group/t/almalinux-9-dnf-module-list-is-empty/1181

# 最後に
いずれはyumは消えゆくコマンドとなりそうなので、早めの移行を意識したいですね
それと運用目線だとmodule機能は期待大です。
Laravel マイグレーションコマンド集

# マイグレーションのコマンド

Laravelのマイグレーションには以下のコマンドがあります。

***まだ実行されていないマイグレーションを実行***
```
php artisan migrate
```
***マイグレーションファイルを作成***
```
php artisan make:migration create_users_table
```
***マイグレーションファイルを作成して実行***
```
php artisan migrate:make create_table_name --create=table_name
```
***DBにマイグレーションを格納するためのテーブルを作成***
```
php artisan migrate:install
```
***特定のマイグレーションファイルのみを実行***
```
php artisan migrate --path=/database/migrations/my_migration.php
```
***最後に実行されたバッチのすべてのマイグレーションをロールバック***
```
php artisan migrate:rollback
```
***直前のマイグレーションをロールバック***
```
php artisan migrate:rollback --step=1
```

***すべてのマイグレーションをロールバックし、DBを空にする***
```
php artisan migrate:reset
```
***データベースをリセットし、すべてのマイグレーションを再実行***
```
php artisan migrate:refresh
```
***データベースを空にし、すべてのマイグレーションを再実行***
```
php artisan migrate:fresh
```
***マイグレーションの状態を確認する***
```
php artisan migrate:status
```
マイグレーションを実行せずに、実行されるSQL文を表示
```
php artisan migrate --pretend
```

# 注意コマンド
***DB内のすべてのテーブルを削除し、新しいマイグレーションファイルを実行してDBを再構築***
```
php artisan migrate:fresh --seed
```
シーダーを実行してDBに初期データを挿入
DBを完全にリフレッシュし、初期状態に戻せます。
ただし、実行する前に注意が必要であり、
***データベース内のすべてのデータが削除されるため、必要なバックアップをしてから実行***した方がいいです。

# オプション
以下はオプションです。

|オプション|説明|
|--|--|
|--path|特定のマイグレーションディレクトリを指定する。|
|--database|マイグレーションを実行するデータベース接続を指定|
|--pretend|マイグレーションを実行せずに実行されるSQLを表示|
|--force|マイグレーションの実行中に質問をスキップ|
|||
|||

他にもオプションはありますので、公式ドキュメントを見てみてください。




# 資料
ChatGptで調べる

https://qiita.com/mikakane/items/6ed937b4904be0f0a5cf

https://qiita.com/esu_eichi/items/0cf9dba2c694c8a6b099

https://zenn.dev/hdmt/scraps/e20979a31a73da
【Streamlit】PythonフレームワークStreamlitのインストール

# Streamlitとは

Pythonのフレームワーク。
アプリケーションの構築から公開まで素早くできる。
フロントエンドもpythonで記述。

公式

https://streamlit.io/

どのような物が開発いけるかは、公式サイトにも実用例がでています。

# 事前準備

### pythonのインストール

https://pythonlinks.python.jp/ja/index.html

参考

https://www.python.jp/install/windows/install.html


pipも自動的にインストールされます。
不具合が起こったらこちらを参考にしてください。

https://www.python-izm.com/tips/pip/

# Streamlitインストール

```
pip install streamlit
```

インストールが完了したら、起動するか確認します。
```
streamlit hello
```
ブラウザで以下の画面が自動表示されればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/fdd1b386-e1cc-0aec-384f-a50cf88ad430.png)
Laravelでの検索機能の実装で検索ボタンを押すとログイン画面に遷移して困っていた時に解決した方法

# この記事の背景
Twitterのクローンアプリを作っていました。
その時に投稿の検索をする機能を作っていました。その時のことです。

# 苦労した点
前提として***検索機能は未ログインユーザーでも検索できるようにする***必要があります。
***検索機能は動くようになりましたが、ログインしていない状態で検索ボタンを押すとログイン画面に遷移***してしまいました。投稿の検索はログインしていなくもできるようにしなくてはいけません。そしてついに原因がわかりました。

# 解決のヒントになったChatGpt

まずは「Laravelで検索機能を作っていて検索ボタンを押すとログイン画面に行くのはなぜ？」
と聞きました。

> ChatGptの回答   
検索ボタンを押したときにログイン画面に遷移する原因は、検索フォームのアクションがログインが必要なページに設定されていることが考えられます。まず、ログインが必要なページであるかどうかを確認してください。もし、ログインが必要である場合は、検索フォームのアクションをログイン画面に遷移するように設定されている可能性があります。その場合、検索フォームのアクションを検索結果が表示されるページに変更することで、問題を解決することができます。また、検索処理を実行するコントローラーのアクションでログイン認証が必要である場合は、ログイン認証が行われていないとリダイレクトされる仕組みになっているため、ログイン認証が必要である旨を表示するメッセージを表示するか、ログインが必要である旨を示すエラーページにリダイレクトすることで、問題を解決することができます。

```welcome.blade.php
<h5 class="description text-center">何か投稿してください</h5>
    <div class="text-center mb-3">
        <form method="get" action="{{ route('post.index') }}" class="d-inline-block w-75">
            <div class="form-group ">
                <div class="input-group">
                    <input type="text" name="keyword" class="form-control" placeholder="検索"  autocomplete="off">
                    <div class="input-group-append">
                        <button type="submit" class="btn btn-success">検索</button>
                    </div>
                </div>
            </div>
        </form>
    </div>
```

>ChatGptの回答 このコードからは、ユーザーがログインしていない場合に、検索フォームを送信すると、ログイン画面にリダイレクトされるようになっています。これは、アプリケーションに認証機能が実装されている場合に起こります。検索フォームが送信されたとき、Laravelはリクエストを認証されていないと見なし、ログインが必要であると判断します。この問題を解決するには、検索フォームのルートを、ログインが必要なルートではなく、誰でもアクセス可能なルートに変更する必要があります。または、認証されていない場合にリダイレクトせず、検索結果を取得することもできます。

# 解決した方法
問題はルーティングでした。下のコードは認証機能で、検索機能に関係するルーティングを認証の
グループの中に書いてありました。これだと検索ボタンを押すとログインしていないと検索ができない状態になっています。

```web.php
// ログイン後
Route::group(['middleware' => 'auth'], function () {
  // 投稿
Route::prefix('post')->group(function () {
      Route::get('','PostController@index')->name('post.index');
      Route::post('/search', 'PostController@search')->name('post.search');
    #省略
  });
```

検索機能のルーティングを***Route::group(['middleware' => 'auth']のグループの外に移動***したら
ログインしなくても検索できるようになりました。

```web.php
 Route::get('','PostController@index')->name('post.index');
 Route::post('/search', 'PostController@search')->name('post.search');

// ログイン後
Route::group(['middleware' => 'auth'], function () {
  // 投稿
Route::prefix('post')->group(function () {
    #省略
  });
```

# まとめ
環境は人それぞれ違うので参考程度でお願いします。
Using GPT to Analyze Cloud Security Issues for K8s

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/5474d34b-6eef-3603-60f9-bfe45945f63d.png)

### ****Intro****

Kubernetes security is an essential task in today's digital landscape. With countless K8s security issues emerging every day, it can be difficult to manually analyze and resolve them quickly. This is where Selefra comes in - a Policy-as-code product that incorporates GPT functionality to help users perform efficient K8s security analysis, cost analysis, and architecture analysis on their Kubernetes clusters.

The GPT feature in Selefra allows users to analyze Kubernetes products for security issues, similar to how ChatGPT works. In this article, we will use K8s Pod security issues as an example to demonstrate how to use Selefra for security analysis on Kubernetes clusters. With the help of Selefra's GPT functionality, users can identify and resolve K8s security issues on their clusters more efficiently, improving their overall security posture.

## ****Running Selefra****

### Install

First, installing Selefra is very simple. You just need to execute the following command:

```bash

brew tap selera/tap
brew install selefra/tap/selefra
mkdir selefra-demo & cd selefra-demo & selefra init
```

### Choose provider

Then, you need to choose the provider you need in the shell, such as K8s:

```bash

[Use arrows to move, Space to select, and enter to complete the selection]

[ ] AWS 
[ ] azure
[ ] GCP 
[✔] K8s # We choose K8s installation

```

### ****Configuration****

**configure K8s:**

You can configure your K8s information in advance by referring to our detailed configuration document available at [Document](https://www.selefra.io/docs/providers-connector/k8s).

**configure Selefra:**
After initialization, you will get a selefra.yaml file. Next, you need to configure this file to use the GPT functionality:

```yaml

selefra:
  name: selefra-demo
  cli_version: latest
  openai_api_key: <Your Openai Api Key>
  openai_mode: gpt-3.5
  openai_limit: 10
  providers:
    - name: k8s
      source: k8s
      version: latest

```

### Running

You can use environment variables to store the openai_api_key, openai_mode, and openai_limit parameters. Then, you can start the GPT analysis by executing the following command:

```bash

selefra gpt "Help me to query pods in kubernetes that are privileged to true"
```

Finally, you will get results similar to the animated image below:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3286109/75f3a3e8-92aa-deea-cff3-64dbebd2b5b7.png)

## T**hanks for reading**

We highly recommend trying Selefra to experience a faster and more efficient cloud security analysis and resolution.

For more information on Selefra：

Website: **[https://www.selefra.io/](https://www.selefra.io/)**

GitHub: **[https://github.com/selefra/selefra](https://github.com/selefra/selefra)**

Twitter: **[https://twitter.com/SelefraCorp](https://twitter.com/SelefraCorp)**

Slack: [https://selefra.io/community/join](https://selefra.io/community/join)
gasでスプレッドシートを差分比較するコード

```javascript
  function compareSheets() {
  // 比較する2つのスプレッドシートを指定
  var sheet1 = SpreadsheetApp.openById('スプレッドシート1のID').getSheetByName('シート名');
  var sheet2 = SpreadsheetApp.openById('スプレッドシート2のID').getSheetByName('シート名');

  // 2つのスプレッドシートのデータを取得
  var data1 = sheet1.getDataRange().getValues();
  var data2 = sheet2.getDataRange().getValues();

  // 2つのスプレッドシートの行数と列数を取得
  var numRows1 = sheet1.getLastRow();
  var numRows2 = sheet2.getLastRow();
  var numCols1 = sheet1.getLastColumn();
  var numCols2 = sheet2.getLastColumn();

  // 差分を格納する配列
  var diff = [];

  // スプレッドシート1にしか存在しない行を検索
  for (var i = 0; i < numRows1; i++) {
    var row1 = data1[i];
    var found = false;
    for (var j = 0; j < numRows2; j++) {
      var row2 = data2[j];
      if (row1.toString() == row2.toString()) {
        found = true;
        break;
      }
    }
    if (!found) {
      diff.push(["-"].concat(row1));
    }
  }

  // スプレッドシート2にしか存在しない行を検索
  for (var i = 0; i < numRows2; i++) {
    var row2 = data2[i];
    var found = false;
    for (var j = 0; j < numRows1; j++) {
      var row1 = data1[j];
      if (row2.toString() == row1.toString()) {
        found = true;
        break;
      }
    }
    if (!found) {
      diff.push(["+"].concat(row2));
    }
  }

  // 2つのスプレッドシートに共通する行で値が異なる行を検索
  for (var i = 0; i < numRows1; i++) {
    var row1 = data1[i];
    for (var j = 0; j < numRows2; j++) {
      var row2 = data2[j];
      if (row1.toString() == row2.toString()) {
        var rowDiff = [];
        for (var k = 0; k < numCols1; k++) {
          if (row1[k] != row2[k]) {
            rowDiff.push(k);
          }
        }
        if (rowDiff.length > 0) {
          var diffRow = ["*"].concat(row1);
          for (var k = 0; k < rowDiff.length; k++) {
            var col = rowDiff[k];
            diffRow[col + 1] = row2[col];
          }
          diff.push(diffRow);
        }
      }
    }
  }

  // 差分を出力するスプレッドシートを作成
  var diffSheet = SpreadsheetApp.create('差分').getActiveSheet();
   
  // 差分を出力するスプレッドシートにヘッダーを追加
  diffSheet.appendRow(["種類"].concat(sheet1.getDataRange().getValues()[0]));
  
  // 差分を出力するスプレッドシートに差分データを追加
  for (var i = 0; i < diff.length; i++) {
    diffSheet.appendRow(diff[i]);
  }

```
このコードはGoogle Apps Scriptで書かれたスプレッドシート上で動作するものです。
スプレッドシート1とスプレッドシート2のデータを比較し、異なるデータを含む新しいスプレッドシートを作成します。

このコードを実行するには、次の2つのスプレッドシートのIDを置き換える必要があります。

```javascript
var sheet1 = SpreadsheetApp.openById('スプレッドシート1のID').getSheetByName('シート名');
var sheet2 = SpreadsheetApp.openById('スプレッドシート2のID').getSheetByName('シート名');
```
また、スプレッドシートのアクセス権限によっては、このコードを実行することができない場合があります。スプレッドシートのアクセス権限を確認し、適切な権限を与える必要があります。
Cognos Analytics レポートで特定の領域の展開/省略機能を実装する

# 概要
レポート内の特定の領域の展開・省略を簡単に実装する手順です。

**省略状態**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/a0a11c53-c7b7-85e5-2abe-22072b4fa9a4.png)

**展開状態**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/3ac79a38-88c1-a3d0-b805-02a7554c76ec.png)

# 実装手順
このようなレポートを例にします。この中で、値のプロンプトと終了ボタンの領域を展開・省略対象にしたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/20191ad2-4f47-9443-9c86-2b809631556e.png)

展開・省略したい領域にテーブルを配置し、値のプロンプトとボタンを移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/d450e471-25fa-cedf-5304-a146e725f1c2.png)

図のようにテーブルを囲むようにHTMLアイテムを3つ配置します。
※「完全な双方向性で実行」は「はい」のままで大丈夫です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/0a2a1850-d7f4-12da-5680-3245643146cc.png)


それぞれのHTMLアイテムに以下を記載します。
HTMLアイテム①
```html
<div style="width:1570px;">
<details>
```

HTMLアイテム②  ※color等の色は自由に指定してください。
```html
<summary style="
background-color:#1f5fa8;
color:white;
padding:2px;
font-size:xlarge;
">
プロンプト領域
</summary>"
```

HTMLアイテム③
```html
</details>
</div>
```

# 実行イメージ
**省略された状態**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/837b9a7f-0450-ac4e-bee0-f9ece01443c5.png)

**展開している状態**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/b0111f16-7cb4-0bff-d5a8-c06c8fc3ba9f.png)
日本語の入ったURLをわかりやすい形でコピペする

# 日本語の入ったURLをそのままコピーする場合
頭のhを抜いてコピーとか後ろにスペースを付けてコピー、consoleを使うとかいろいろあるけど、動線的にどうもしっくりこない。
私は以下のようにしている

## 私の場合の対処

1. 適当な捨てブックマークを準備
1. 該当ブックマークの名前を「URLdecode」に変更
1. URLに以下のJavascriptを登録

```js
javascript:(function(){
  var t = prompt('Input Uri','');  
  m = t ? t : location.href;  
  prompt(%27Decoded%27,decodeURIComponent(m).replace(/ /g,%27%2520%27));
})();
```
半角スペースをそのままURLdecodeすると、Teamsに張り付けたときとかにリンクがうまく張られなくなることがあるのでそこだけは`%20`にしているところがちょっとしたポイント。

## 使いかた

URLをコピーしたら、ブックマークのURLdecodeをクリック、出てきたダイアログにURL貼り付け、出てきたダイアログのURLをコピーする。
ダイアログを空白のままにしておくと現在のページのURLをデコードする。
やってることはまったく大したことないが、動線的には一番早い＆シンプルだと思ってる。
特定の日時にマーカーをつける

## 例

```c
//@version=5
indicator('plot date', overlay=true)

p(t) => 
    if time < timestamp(t) + 60*60*18*1000 and timestamp(t) + 60*60*18*1000 < time + 60*60*24*1000
        label.new(bar_index, high, "", color=color.new(color.white, 90))

p("2023-05-02")
p("2023-05-03")
```

* マウスカーソルをのせたときにツールチップを表示する場合

```c
//@version=5
indicator('plot date', overlay=true)

p(t, tooltip) => 
    if time < timestamp(t) + 60*60*18*1000 and timestamp(t) + 60*60*18*1000 < time + 60*60*24*1000
        label.new(bar_index, high, "", color=color.new(color.white, 90), tooltip = tooltip)

p("2023-05-08", "ツールチップ１")
p("2023-05-03", "")
```

* 矢印の形を変える

```c
indicator('plot date', overlay=true)

p(t, buysell, hovermessage) => 
    if time < timestamp(t) + 60*60*18*1000 and timestamp(t) + 60*60*18*1000 < time + 60*60*24*1000
        if buysell == "L"
            label.new(bar_index, low, buysell, color=color.new(color.lime, 80), textcolor=color.new(color.white,90), tooltip = hovermessage, yloc=yloc.belowbar, style=label.style_arrowup)
        else
            label.new(bar_index, high, buysell, color=color.new(color.red, 80), textcolor=color.new(color.white,90), tooltip = hovermessage, yloc=yloc.abovebar, style=label.style_arrowdown)

p("2023-05-08", "L", "ロングの根拠")
p("2023-05-03", "S", "ショートの根拠")
```


## 配列を使う場合

```c
//@version=5
indicator('plot date', overlay=true)

t(my_array) => 
    for i = 0 to array.size(my_array)-1 by 1
        if time < array.get(my_array,i) and array.get(my_array,i) < time + 60*60*24*1000
            label.new(bar_index, high, '', color=color.new(color.white, 95))

my_array = array.new_int(10, timestamp("2023-05-02"))
array.push(my_array, timestamp("2023-05-03"))
array.push(my_array, timestamp("2023-04-03"))
array.push(my_array, timestamp("2023-05-01"))

t(my_array)
```
java初心者が行く～設計のキホン_変数～

# はじめに
java初心者が備忘録的に書いています。
今回は設計の基礎の基礎について備忘録的にまとめてみました。
参考文献：https://amzn.asia/d/9wxye1Y

# 変数
プログラムを書くときに必ず使う変数ですが何気なく変数命名していた
以下のコードが何の処理を行っているか考えてみる

```java
int a = 100;
int b = 1.08;
int ans = a * b;
```
このコードを見た感じよくわからないaとbが掛け算されてansに入っているということがわかるが、具体的に何の処理が行われているかがわからない。
そこで変数名を書き換えてみる。

```java
int price = 100;
int taxRate = 1.08;
int includingTaxPrice = price * taxRate;
```
これで税率の計算をしていることがわかった。
上記のように変数命名一つでコードの可読性は変わる。

では次に以下のコードを見てみる。
このコードは100円のものが税込み後に30円割引されるコードである。
```java
int price = 100;
int discount = 30;
int taxRate = 1.08;
int includingTaxPrice = price * taxRate;
includingTaxPrice = includingTaxPrice - discount;
```
このコードには問題点が一つある。それは変数の再代入である。
今回includingTaxPriceは税率を含む商品の値段を代入する目的で作成した。にもかかわらず割引後の値段が再代入されている。
再代入をしてしまうと本来の意図と違う値が変数に入ってしまいバグを引き起こす恐れがあるらしい。
そのため割引後の値段はpayAmountなど新たなint型の変数を作成して代入すべきである。
Mac: クリップボードの内容をブラウザで開くショートカットキーを作ると便利

# やりたいこと
どのアプリがアクティブであってもショートカットキー一発でChromeを開き、クリップボードの内容がURLならそのページを表示、そうでないならGoogleで検索。

# 設定手順

## 1. スクリプトを作成
下記のスクリプトを `openurl` として任意の場所に保存、 `chmod +x` しておく。

```sh
#!/bin/sh

# ブラウザでURL or キーワードを開く

if [ $# = 0 ]; then
    arg=`pbpaste`
else
    arg="$1"
fi

case "$arg" in
    *://*)
        open "${arg}"
        ;;
    *)
        open "https://www.google.co.jp/search?q=${arg}"
        ;;
esac
```

## 2. クイックアクション作成
Automatorを起動→クイックアクション→選択→シェルスクリプトを実行→下記内容を入力
（スクリプトのパスは保存した場所にすること）
![スクリーンショット 2023-05-10 10.46.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79394/f7f6b4f6-20ad-870d-b556-3e6e8256f2de.png)

※ワークフローが受け取る項目を「入力なし」にしている。「テキスト」にするとサービスの種類が「一般」でなくなり、常に実行可能でなくなるため。

## 3. ショートカットの割当

システム環境設定→キーボード→キーボードショートカット→サービス→一般→openurlにキーを割り当て。
キーは何でもいいが、自分は左手だけで入力したいので `Cmd+F1` にしている。
【React】クラスコンポーネント vs 関数コンポーネント【初心者に分かりやすく】


Reactには、コンポーネントを構築する際に選択できる**クラスコンポーネント**と**関数コンポーネント**の2つの方法があります。この記事では、これらの違いを初心者向けに分かりやすく解説していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/d64e95c8-c429-7a49-dc9b-9de61bcfd692.png)

## クラスコンポーネント

クラスコンポーネントは、Reactの古典的な方法で、JavaScriptのクラスを使って定義されます。クラスコンポーネントでは、`render()`メソッドを用いてUIを返します。また、`state`や`lifecycle`メソッドを利用できます。

**例:**

```javascript
import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
      </div>
    );
  }
}

export default MyComponent;
```

## 関数コンポーネント

関数コンポーネントは、よりシンプルで簡潔な構文でコンポーネントを定義できます。通常、アロー関数を使って定義され、UIを直接返します。`state`や`lifecycle`メソッドは利用できませんが、React Hooksを使って同様の機能を実現できます。

**例:**

```javascript
import React from 'react';

const MyComponent = () => {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <p>Count: {count}</p>
    </div>
  );
};

export default MyComponent;
```

## どちらを使うべきか

一般的に、関数コンポーネントが推奨されています。シンプルで簡潔な構文により、コードが読みやすくなります。また、React Hooksの導入により、以前はクラスコンポーネントでしかできなかったことが関数コンポーネントでも可能になりました。

ただし、既存のプロジェクトでクラスコンポーネントが多用されている場合や、特定の理由でクラスコンポーネントを使う必要がある場合は、クラスコンポーネントを選択することもあります。

## まとめ

Reactには、コンポーネントを作成するための2つの方法があります。クラスコンポーネントは古典的で、`state`や`lifecycle`メソッドを利用できます。一方、関数コンポーネントはよりシンプルで簡潔な構文を持ち、React Hooksの導入により、`state`や`lifecycle`メソッドに相当する機能を持つことができます。

現在では、新しいコードを書く場合、関数コンポーネントを使うことが推奨されています。それは、簡潔で読みやすいコードを書くことができ、Hooksを通じて多くの機能を利用できるからです。

しかし、既存のプロジェクトではクラスコンポーネントもまだ広く使われています。そのため、クラスコンポーネントの理解と使用法も重要です。

最終的にどちらを使用するかは、プロジェクトの要件、チームの経験、そして既存のコードベースに大きく依存します。どちらの方式も理解していれば、最適な選択ができるでしょう。

この記事が、Reactのクラスコンポーネントと関数コンポーネントの理解に役立つことを願っています。
pycデコンパイル

# pycデコンパイル

pyinstallerで実行ファイルにしたpython3.9.13のスクリプトをデコンパイルしたかったが、uncompyle6だのdecompyle3だのunpycだのpython-exe-unpackerだのごちゃごちゃしてる上にできなくて苦しんだので成功した方法をメモする。

## 結論

[pyinstxtractor](https://github.com/extremecoders-re/pyinstxtractor)と[pycdc](https://github.com/zrax/pycdc)を使う。

## やり方

pythonの実行ファイルをデコンパイルするには以下の二段階の手順を行う必要がある。

1. バイトコード(.pycのやつ)を抽出する
2. バイトコードをpythonコードにデコンパイルする

### バイトコード抽出

抽出自体は問題なかったが先頭にあるべきマジックナンバーが欠如するものがあり、そのままだとデコンパイルが失敗することがある。

[pyinstxtractor](https://github.com/extremecoders-re/pyinstxtractor)だと欠如していない正当なpycファイルとして抽出できた。
欠如している場合は、[こちらのサイト](https://kagasu.hatenablog.com/entry/2019/03/26/211203)に記載されているやり方で補完すれば問題ない。

### デコンパイル

ここがまったくうまくいかなかった。
pycのデコンパイルで一番有名であろうuncompyle6、decompyle3では、3.9のバイトコードに対応していないらしく失敗してしまう。
[pycdc](https://github.com/zrax/pycdc)だとうまくいった。
llamaをdalaiを用いて簡単にローカルマシンで実行する。

# はじめに

ローカル環境でllamaを実行したのでその備忘録
モデルは英語に対応しているようです。

# 環境

Ubuntu(Linux) -> wsl
node.js = 19.8.1
python3 =3.10.9


# モデルのインストール

```
npx dalai llama install 7B
```
その他モデルは、
```
13B 30B 65B
```
がある。

# 実行

```
npx dalai serve
```

`http://localhost:3000/`　等のリンクが表示されるのでブラウザでアクセス


# まとめ

```
wsl

sudo apt install -y curl
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs

sudo apt install python3

npx dalai llama install 7B
npx dalai serve
```
Nuxt3でDocumentDB（MongoDB）を使う方法

Nuxt3のserverで、AWSのDocumentDBに接続するのに手間取ったので、私の環境でうまく行った方法を公開します。
## 仕様
以下のようにローカルでは、MongoDBに接続し、AWSではDocumentDBに接続する。

ローカル：Docker, MongoDB, Nuxt3
AWS：ECS Fargate, DocumentDB, Nuxt3

## コード
```javascript:server/database.ts
import mongoose from 'mongoose';
import fs from 'fs';
import path from 'path';

const connection: {
  isConnected: any;
  db: mongoose.Connection | undefined;
} = {
  isConnected: false,
  db: undefined,
};

async function connectDB() {
  if (connection.isConnected) {
    return connection.db;
  }

  let db = undefined;
  console.log('connecting');
  const username = encodeURIComponent(process.env.MONGODB_USERNAME || '');
  const password = encodeURIComponent(process.env.MONGODB_PASSWORD || '');
  const host = process.env.MONGODB_HOST;
  if (process.env.IS_DEV) {
    db = await mongoose.connect(`mongodb://${host}/`, {
      "authSource": "admin",
      "user": username,
      "pass": password,
    });
  } else {
    const caBundlePath = path.resolve(process.cwd(), './public/rds-combined-ca-bundle.pem');
    try {
      db = await mongoose.connect(`mongodb://${username}:${password}@${host}/`, {
        tls: true,
        sslValidate: true,
        tlsCAFile: caBundlePath,
        replicaSet: 'rs0',
        readPreference: 'secondaryPreferred',
        retryWrites: false,
      });
      console.log('MongoDB Connected');
    } catch (err) {
      console.log('MongoDB Connection Error: ', err);
    }
  }
  if (!db) return;
  console.log('connected');
  connection.isConnected = db.connections[0].readyState;
  connection.db = db.connections[0].useDb('YOUR_DB_NAME');
  return connection.db;
}

export default connectDB;

```

## pemファイル設置
DocumentDBは、TLSで認証しているので、その対応をする。
publicディレクトリに `rds-combined-ca-bundle.pem` を設置する。
ダウンロード方法は以下の通り。

```terminal
$ wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
```

## 最後に
TLS認証でめちゃくちゃ時間かかった。。。
イベントモニタリングAnalytics設定方法

## 前提
Salesforce Shieldの契約が必要。
Salesforce Shieldの契約でEvent Monitoring Analyticsが10ライセンス付帯するが、このライセンスだけではAnalyticsに5000万行しか保存することができない。CRM Analyticsを契約することで上限を増やすことができる。

## 設定手順
1. イベントモニタリングの有効化
    - 設定 > セキュリティ > イベントモニタリング > イベントモニタリング設定
        - 「Analyticsアプリケーションでイベントログデータを表示」をオンに設定
        - 「イベントログファイルを生成」をオンに設定
2. 権限セットの割り当て
    - イベントモニタリングAnalyticsを使用するユーザに下記の権限セットを付与。
        - Event Monitoring Analytics ユーザ
        - Event Monitoring Analytics 管理者
3. CRM Analyticsの有効化
    - 設定 > 機能設定 > 分析 > Analytics > 始めましょう
        - 「CRM Analyticsを有効化」をクリック。
4. Analytics Studioの起動
    - ここまでの設定でアプリケーションランチャーに「Analytics Studio」が表示されるようになるので、クリックする。表示されない場合は画面の再読み込みを行う。
5. Event Monitoring Analyticsのアプリケーションを作成する。
    - 作成ボタンから「アプリケーション」を選択する。テンプレートから「Event Monitoring Analytics App」を選択する。画面の指示に従って設定を行う。
    - CRM Analyticsの契約がないとすぐにレコード数上限に達するので、ログ保持期間の設定には注意。
    - 作成されるのに30分ほど時間がかかる。
6. Event Monitoring Analyticsのスケジュールを設定する
    1. 「Analytics Studio」の右上の歯車アイコンをクリックして、「データマネージャ」を選択。
    1. 左下の「データフローを管理」をクリック。
    1. 「データフローとレシピ > データフロー > EventMonitoring eltDataflows」の▼をクリックし、スケジュールの設定をクリックする。
    1. スケジュールモードをイベントベースに設定し、「Salesforceローカル接続の同期」を設定した状態で保存する。
    1. 接続タブをクリックし、SFDC_LOCALの▼からスケジュールを設定。

## エラー対応
### Something went wrong while executing the FlattenRole node: parent_field does not have any data (all rows have null value): ParentRoleId
ロール階層が0または1階層しかないと発生する。2階層のダミーのロールを作成することで回避可能。
詳細は下記のKnown Issueを参照。

- [CRM Analytics - Event Monitoring Analyt | Known Issues](https://issues.salesforce.com/issue/a028c00000gAwL6AAK/crm-analytics--event-monitoring-analytics-app-creation-fails-when-at-least-two-levels-of-role-hierarchy-is-not-defined)


## 参考
- [Event Monitoring Analytics アプリケーションの Salesforce 権限の設定](https://help.salesforce.com/s/articleView?id=sf.bi_help_setup_admin_wave_permissions.htm&type=5)
- [CRM Analytics の制限](https://help.salesforce.com/s/articleView?id=sf.bi_limits.htm&type=5)
- [セキュリティアドオン – Salesforce Shield | セールスフォース・ジャパン](https://www.salesforce.com/jp/products/platform/products/shield/)
- [Event Monitoring Analytics アプリケーション](https://help.salesforce.com/s/articleView?id=sf.bi_app_admin_wave.htm&type=5)
- [Event Monitoring Analytics アプリケーション | Salesforce Trailhead](https://trailhead.salesforce.com/ja/content/learn/modules/event_monitoring_analytics)
- [イベントモニタリングのログデータを出力する - Qiita](https://qiita.com/TaaaZyyy/items/e0270ca2976a7110b0a1)
- イベントログファイルを出力するプラグイン作成→[Salesforce CLIのsfプラグインを作成する - Qiita](https://qiita.com/TaaaZyyy/items/43b878bbcd050c2538d5)
LocationService API


このAPIを使うにはライセンスが必要かもしれない

+ [{"status":500,"body": {"error":"Disconnected or Canceled"},"headers": {},"ok":false,"StatusText": "Server Error","errorType":"fetchResponse"}](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PleUS)

Where: This feature is available in Lightning web components when they’re running in Mobile Publisher. 

[Use Location in a Lightning Web Component](https://help.salesforce.com/s/articleView?id=release-notes.rn_lwc_locationservice.htm&release=236&type=5)

Your organization must license Salesforce Mobile Publisher to use the feature. Contact your Salesforce sales rep for more information.

[Mobile Publisher for Salesforce App](https://help.salesforce.com/s/articleView?id=sf.s1_branded_apps.htm&type=5)
Firebase Cloud FunctionsのonCallでCORS(Access-Control-Allow-Origin)エラーになったので手動で対応した話

## 解決方法

[アプリから関数を呼び出す](https://firebase.google.com/docs/functions/callable?hl=ja)の`functions.https.onCall`でCloud Functionsを呼び出した際に、以下のようにCORSエラーに遭遇した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/caf4377f-601f-2e6e-71b4-f82ad52b3c75.png)

色々調べてた結果、[onCall function returning cors on web and "UNAUTHENTICATED" on mobile](https://github.com/firebase/firebase-functions/issues/645#issuecomment-605835353)に書かれている通り、Google CloudのCloud Functionsの権限設定で以下のような権限を追加したら問題は解決された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/6b06c593-c5bb-0c33-87b1-a7102aebf6d5.png)

上記は[公式](https://cloud.google.com/functions/docs/securing/managing-access-iam?hl=ja#after_deployment)でも触れられているので解決策としてアリだとは思われる。が、その場合、クライアント（ブラウザ）からの全てのクロスドメインアクセスが許可されてしまうので、[App Check](https://firebase.google.com/docs/app-check?hl=ja)での保護が必須になるだろう（もしApp Checkがない場合、全てのPOSTリクエストが到達してしまいNG）。

※CORSはブラウザからのリクエストでしか発生しないので、バックエンドからのAPI呼び出しはCORSエラーにならず普通に通ってしまう。その意味でもApp Checkによる保護は必須だろう。

- 参考：[FirebaseのCloud FunctionsでCORSが~とかAccess-Control-Allow-Originが~と言われたらこれ](https://qiita.com/qrusadorz/items/40234ac0b5c5c2315cad)
- 参考：[Firebase Callable Function + CORS](https://stackoverflow.com/questions/50278537/firebase-callable-function-cors)
- 参考：[プリンシパル　すべてのユーザー](https://cloud.google.com/iam/docs/overview?hl=ja#all-users)

## うまくいかなかった方法

### RuntimeOptions.invokerの`allUsers`を設定する（`public`も同じった）

[RuntimeOptions.invoker](https://firebase.google.com/docs/reference/functions/firebase-functions.runtimeoptions.md#runtimeoptionsinvoker)を`allUsers`に設定する、という方法。実装としては以下のようになる。

```js
export const hogeHoge = functions
	.region('asia-northeast1')
	.runWith({ enforceAppCheck: true, invoker: 'allUsers' })
	.https.onCall(async (data, context) => {
       ...
	});
```
【MicroStrategy】ドシエ上での項目の書式設定

## はじめに

本記事ではMicroStrategyのドシエ上で項目の表示形式を変更する方法を紹介します。
取り込んだデータを元の形式とは異なる形式で表示したい場合に参考になるかと思います。
（データはダミーデータを使用）

## 日付の書式設定

以下のような日付データを取り込みドシエ上に配置すると、
2023/3/1
2023/3/2
2023/3/3

そのままだと読み込んだ形式のまま表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/026955d2-d426-48a3-a65e-04d965cd9a41.png)

例えばこれを以下のように「2023年3月1日」の表示形式に変えたい場合は
次の手順で簡単に形式を変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/fd0a207b-94b0-8150-70a7-36e5c7f691ca.png)

#### 日付書式変更手順

①日付のアトリビュート上で右クリック
②「数値の書式」を選択
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/fc958d82-5b23-315d-6069-ef5ff553fae2.png)
③「日付」を「カスタム」に変更し、任意の表示形式を入力
　「2023年3月1日」のような形式にする場合は「yyyy年mm月dd日」と入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/5988e68f-1f63-7be3-3cfa-b45ba09acab1.png)
④OKを選択

以上です。
③での形式を任意のものに変更することで、「yyyy年mm月dd日」以外の形式も表示させることが可能ですので、試してみてください。

日付の書式変更をする際の注意点ですが、
日付データを日付型ではなく文字列（テキスト型）として取り込んでしまうと上記の変更ができないのでご注意ください。

## 数値の書式設定

この書式変更は日付データだけでなく数値データでも可能です。
例えば数値（桁数）が大きくてそのままでは一目でわかりにくい場合に、
下図例のように1000=Kとして短縮して表示させることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/31b7ea15-7f53-b1b8-7e86-360a74852416.png)

手順は日付データを変更した際と同様で、③の手順で形式を任意のものに指定可能です。


## おわりに
今回はドシエ上での項目の表示形式を変更する方法を紹介しました。
記事内ではシンプルな例を紹介しましたが、他にも様々な形式に変更させることができます。
形式を変更することで表やグラフをより分かりやすく、見やすくすることもできるかと思いますので、ぜひ試してみてください。
最後までご覧いただきありがとうございました。
拡張ドメイン有効後の結果


+ [Basic Question for Enhanced Domain Effect on Experience Cloud and Salesforce Sites](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Otj1j)


+ **Production Org**: Since our My Domain name didn't change, the login process for users was unaffected.
+ **Digital Experience Sites**: The URL domain for our Digital Experience sites changed as expected ("my.site.com" in place of "force.com"). Going to the old URL automatically redirects to the new URL, so users aren't negatively impacted and there is plenty of time to inform users of the change.
+ **Salesforce Site**: This was my biggest concern. The URL changed for our Salesforce Site, as expected ("my.salesforce-sites.com" in place of "secure.force.com"). Our My Domain name replaced the different name we had used as the beginning of the URL, but this makes sense. We really only use this site as part of the Volunteers for Salesforce package, and even then only for the Volunteer Personal Site that volunteers use to log their hours. As with the other Enhanced Domain changes, going to an old link for this Salesforce Site automatically redirects to the new URL. This is true also for the Volunteer Personal Site URL, which is important because we didn't need to immediately give the new URL to all the volunteers. In addition to the changes made by Enhanced Domains, I also updated the custom field formula that creates the URL for the Volunteer Personal Site that we give to volunteers, so that it results in a URL with the updated domain. I then did a mass email with this updated field to let all active volunteers know about the new URL. Obviously, new volunteers will be given the new URL from the start.

+ **本番組織**: 私のドメイン名は変更されていないため、ユーザーのログインプロセスは影響を受けませんでした。
+ **デジタル エクスペリエンス サイト**: デジタル エクスペリエンス サイトの URL ドメインが予想どおり変更されました (「force.com」の代わりに「my.site.com」)。古い URL にアクセスすると、自動的に新しい URL にリダイレクトされるため、ユーザーが悪影響を受けることはなく、ユーザーに変更を通知する時間が十分にあります。
+ **Salesforce サイト**: これが私の最大の懸念でした。予想どおり、Salesforce サイトの URL が変更されました (「secure.force.com」の代わりに「my.salesforce-sites.com」)。私のドメイン名は、URL の先頭として使用していた別の名前を置き換えましたが、これには意味があります。実際、私たちはこのサイトを Volunteers for Salesforce パッケージの一部としてのみ使用し、さらにボランティアが勤務時間を記録するために使用する Volunteer 個人サイトとしてのみ使用します。他の拡張ドメインの変更と同様、この Salesforce サイトの古いリンクに移動すると、新しい URL に自動的にリダイレクトされます。これはボランティア個人サイトの URL にも当てはまります。新しい URL をすべてのボランティアにすぐに教える必要がないため、これは重要です。拡張ドメインによる変更に加えて、ボランティアに提供するボランティア個人サイトの URL を作成するカスタム フィールドの式も更新して、更新されたドメインの URL になるようにしました。次に、この更新されたフィールドを含む一斉メールを送信して、活動中のボランティア全員に新しい URL について知らせました。当然のことですが、新しいボランティアには最初から新しい URL が与えられます。
Cognos Analyticsのサンプル・カスタム・ビジュアルを追加する

# はじめに
Cognos Analyticsではカスタム・ビジュアルのサンプルが提供されています。
サンプルのコードをGitHubからダウンロードしてCognosに追加することでサンプルが利用可能になります。

※Visualization samples
https://www.ibm.com/docs/en/cognos-analytics/11.2.0?topic=samples-visualization

# カスタム・ビジュアルの追加手順
今回は、Sankey グラフを追加しながら手順を紹介します。

## サンプルの入手
まず最初にGitHubにアクセスしサンプルのコードをダウンロードします。

GitHub
https://github.com/IBM/ca_customvis

※2023年4月26日現在、11.2のガイドからもリンク先は上記11.1のものになります。
　最新のリンク先についはオンラインドキュメントを常に確認してください

GitHubにアクセスしたら、「Code」を展開して、「Download ZIP」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/e2a5af7f-788f-9af2-d8cd-d9ad014494d0.png)


ダウンロードしたzipファイルを展開する
※展開先のフォルダは任意の場所で問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/d6dbf1f9-98a1-4f9b-dd64-70716c36f190.png)

## Cognosへの追加
ブラウザからCognosにアクセスします。
ダッシュボードまたはレポートを新規作成します。
視覚化を追加し、「カスタム・ビジュアルの追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/6b13a575-d3e2-d3d0-fa54-cf47eb4d7511.png)

先ほど展開したzipファイルに含まれているカスタム・ビジュアルのコードを選択して追加します。
<zip展開先>\ca_customvis-master\ca_customvis-master\visualization-samples\11.1.x\sankey
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/a8830a37-52c4-93f1-b983-7096e243c40b.png)

以上で、カスタム・ビジュアルの追加が完了です。

視覚化ギャラリーの「カスタム」タブにSankeyグラフが追加されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/63c1b57c-384f-94dc-9c72-4590a86735d6.png)


Cognos全体に追加されているので、レポートでもダッシュボードで利用可能になります。
また、追加したユーザー以外の全ユーザでカスタム・ビジュアルを利用することができます。

## カスタム・ビジュアルの権限設定
全てのユーザーに開放したくない場合は、権限設定を変更する必要があります。
管理 > カスタマイズ > カスタム・ビジュアル を開き、Sankeyのプロパティから権限を変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/319ce439-2c0d-ab6b-2c09-4cfdc5524119.png)


## 追加したカスタム・ビジュアルの削除

追加したカスタム・ビジュアルは、下記の2か所から削除することが可能です。
* 視覚化ギャラリー
* 管理 > カスタマイズ

視覚化ギャラリーでSankeyグラフを選択し、ごみ箱アイコンをクリックすることで削除することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/39c16bb2-c8fb-0ffd-af92-290c5b844004.png)




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/62efe1c9-7019-e61b-bfb1-a040d7e4e251.png)


管理 > カスタマイズ > カスタム・ビジュアル を開き、メニューから削除することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/dfde7172-5eab-f955-57f3-b6dabb1aa354.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/ac68ae82-f682-e8f6-b9c6-76839361dabc.png)


## カスタム・ビジュアル削除時の注意点

削除したカスタム・ビジュアルを使用してたレポートを実行すると下図のようなメッセージが表示されるようになります。

使用してるレポートやダッシュボードが無いことを確認して削除してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/a0f0881c-0171-38cb-6107-017daeea9d37.png)


## 運用上の注意点

開発環境などで追加したカスタム・ビジュアルは本番環境への移行対象となります。
移行資源の管理からもれないように注意してください。

# さいごに

Cognos Anakyticsでは、バリエーション豊富なサンプル・カスタム・ビジュアルが用意されています。
環境への追加は見ていただいたように簡単に行うことができるので、ぜひ試してみてください。
また、サンプルコードが入っていたフォルダにはサンプルデータも用意されているので、簡単に使い始めることができるのも特徴です。

サンプルで用意されたものでは要件に合致しない、もう少し細かな仕様が必要となると、カスタム・ビジュアルの開発が必要になります。サンプルのコードをベースに開発に取り組んでみるのも良いですね。
プルダウン

<template>
  <div>
    <select v-model="selected1" @change="onChange1">
      <option value="">選択してください</option>
      <option v-for="item in item1" :value="item.value">{{ item.label }}</option>
    </select>
    <select v-model="selected2" @change="onChange2">
      <option value="">選択してください</option>
      <option v-for="item in item2" :value="item.value">{{ item.label }}</option>
    </select>
    <select v-model="selected3" @change="onChange3">
      <option value="">選択してください</option>
      <option v-for="item in item3" :value="item.value">{{ item.label }}</option>
    </select>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selected1: "",
      selected2: "",
      selected3: "",
      item1: [
        { value: "1", label: "ラベル1" },
        { value: "2", label: "ラベル2" },
        { value: "3", label: "ラベル3" }
      ],
      item2: [],
      item3: []
    };
  },
  methods: {
    onChange1() {
      if (this.selected1 === "1") {
        this.item2 = [
          { value: "a", label: "ラベルa" },
          { value: "b", label: "ラベルb" },
          { value: "c", label: "ラベルc" }
        ];
      } else if (this.selected1 === "2") {
        this.item2 = [
          { value: "d", label: "ラベルd" },
          { value: "e", label: "ラベルe" },
          { value: "f", label: "ラベルf" }
        ];
      } else {
        this.item2 = [
          { value: "g", label: "ラベルg" },
          { value: "h", label: "ラベルh" },
          { value: "i", label: "ラベルi" }
        ];
      }
      this.selected2 = "";
      this.selected3 = "";
      this.item3 = [];
    },
    onChange2() {
      if (this.selected2 === "a") {
        this.item3 = [
          { value: "1", label: "ラベル1" },
          { value: "2", label: "ラベル2" },
          { value: "3", label: "ラベル3" }
        ];
      } else if (this.selected2 === "b") {
        this.item3 = [
          { value: "4", label: "ラベル4" },
          { value: "5", label: "ラベル5" },
          { value: "6", label: "ラベル6" }
        ];
      } else {
        this.item3 = [
          { value: "7", label: "ラベル7" },
          { value: "8", label: "ラベル8" },
          { value: "9", label: "ラベル9" }
        ];
      }
      this.selected3 = "";
    },
    onChange3() {}
  }
};
</script>
Unity Asset Storeでアセット購入時にエラーになった時


Unity Asset Storeで久しぶりにアセット購入しようと思ったら、以下のエラーが発生。

![20230510085257.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74237/8e7ea1fd-156a-5650-b03e-ce7e1e465e89.png)

あれ。。前は普通に購入できたな。。と思っていたがひとまず
```
You will be contacted by a Unity representative in approximately one business day.
```
ってあるので、1日待ってみた。が何も音沙汰なし。。
色々ググってみて、どうやら `Company Name` を空にしたらよいとあったので、購入情報再度確認して修正してみると成功！

![20230510085605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74237/ec6bd250-dd7e-0182-789d-262be837da11.png)

んー入力フォームにバリデーションつけてほしいと思った次第でした。



https://www.yhikishima.com/entry/2023/05/10/085810
Gitはメンヘラかまってちゃん

+ 多くの人間と関係（ブランチ）を結びたがる
+ 自分の過去のいいところだけをコミュニティ（レポジトリ）に伝えている
+ 新しい人には今までの自分を読んでとお願いする（クローン）
+ 相手に対して関係（ブランチ）を変える（チェックアウト）
+ 手順を踏まないと(アッド)受け入れもしない
+ 何時何分何秒に何をしたかを理由付きで聞いてくる（コミット）
+ その記録（コミットログ）を自分のコミュニティ（レポジトリ）に公表している
+ 都合の悪いことは記憶の改ざん（アメンド、リベース）をする
+ わけがわからなくなったらリセット
+ 切れた関係（ブランチ）を消すことに躊躇はない
+ 今つないでいる関係（ブランチ）を消すことは許さない
+ 関係（ブランチ）を進めてしまったら戻すのはとても難しい
+ 矛盾による喧嘩（コンフリクト）が日常茶飯事
+ 全員との関係をまとめる（マージ）のに多くの手間が必要
+ まとめる（マージ）だけで優秀な人が１日潰されるのもザラ
+ もしも関係を切りたければ全てを捨てて逃げるしか無い（管理されたフォルダごと削除）
+ たとえ逃げられてもそいつとの思い出（コミットログ）は永遠に残っている
N2DインスタンスからT2Dインスタンスに切り替えてみた話

# はじめに
以前の記事「[Intel系インスタンスからAMD系インスタンスに切り替えてみた話](https://qiita.com/HiroyasuKuraya/items/dd2ed68c4302a880d9db)」のその後の話です。
Intel系からAMD系のインスタンスに変更したことでコストは安くなったのですが、更に安くできないかと思い調べていたところT2Dインスタンスの存在に気づきました。

# T2Dインスタンスとは
N2Dインスタンスはバランス型で幅広く利用できるのに対し、T2Dインスタンスはスケール特化型になっています。
頻繁にスケールが行われるWEBサービスには、とても相性が良いです。

コストに関しては、継続利用割引が適用されないためT2Dインスタンスが高くなります。
ただ、CPU性能はT2Dインスタンスが圧倒しているので、全体で見ると安くなるはずです。
・N2D
![スクリーンショット 2023-05-10 8.55.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133366/add9724c-005c-0423-263f-b71c8738b8e2.png)
・T2D
![スクリーンショット 2023-05-10 8.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133366/96bf6d0e-1e97-d304-d94a-9250e3e97fef.png)

# 実際適用してみた
前回と同じくピーク時にどれだけCPUが使用されているかで比較していきます。
まず、N2Dですが **242CPU** 使用しました。
![スクリーンショット 2023-03-08 10.21.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133366/83493ab8-ecaf-87c1-3159-002f6baa69a4.png)
続いて、T2Dですが **166CPU** 使用しました。
![スクリーンショット 2023-05-10 8.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133366/3f86a832-b6d2-e0b4-60c2-4dee9a68b1ee.png)
ソースを全く変えずに、インスタンスタイプを変えただけ76CPU(32%DOWN)削減されました。
これは凄い。。。

# まとめ
スケールが頻繁に行われるサービスの場合、T2Dインスタンスに切り替えることでコストがかなり抑えられる。
StripeのアカウントID(acct_xxx)を、ダッシュボードで確認する方法

Stripeでは、アカウントごとに`acct_`から始まるIDが発行されています。

このIDは、顧客データのコピーやサポートへの問い合わせ時などに利用することがあります。

## アカウントIDは、ダッシュボードの設定ページから

アカウントIDを確認する簡単な方法は、Stripeのダッシュボードにログインすることです。

ダッシュボードにログイン後、右上の歯車アイコンをクリックして設定ページに移動しましょう。

![スクリーンショット 2023-05-09 10.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/96bf1e76-af0a-eb0f-67d5-70340ddc42e2.png)
直接リンク: https://dashboard.stripe.com/settings

[ビジネス設定 > お客様のビジネスについて]から、[アカウントの詳細]を選びましょう。

![スクリーンショット 2023-05-09 10.06.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d0b94290-2ca7-cac1-657c-d09095f23097.png)

[アカウントの設定]に、[acct_]から始まるアカウントIDが表示されています。

![スクリーンショット 2023-05-09 10.07.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/1e0fe95a-262f-abd7-788b-256bf83849a7.png)

## アカウントIDが必要になったら、テキストをクリックしてコピー

アカウントIDは、テキストをクリックするだけでコピーできます。

![スクリーンショット 2023-05-09 10.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/39b4d8e7-97cd-c73e-2331-d439bb74d73a.png)

頻繁に必要となることはありませんが、その分「あれ、どこで見れたっけ・・・」となりやすい情報でもあります。

「アカウントIDを利用することが多いな」と思われる方は、この記事をブックマークするとよいかもしれません。
Github Actionsでjsonファイルをsecretsに設定する

## はじめに
　credential情報を持つjsonファイルを用いたプログラムを、Github Actionsで自動化させたかったのですが、どうしたら良いか迷子になりました。初心者の備忘録なので、ご指摘あればぜひお願いします。


## 改行文字のせいでsecretsに登録できない
　趣味でスプレッドシートをいじるプログラムを作っていたのですが、googleへの認証のため次のようなcredential.jsonが必要でした。

```json
{
  "type": "xxxx",
  "project_id": "xxxx",
  "private_key_id": "xxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\nxxxx\n-----END PRIVATE KEY-----\n",
  "client_email": "xxxx",
  "client_id": "xxxx",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxxx"
}
```

　この情報をGitHub Actionsのsecretsに登録するのに、引っかかったところが`"private_key"`でした。ここの改行文字の処理が上手くいかず、secretsに登録しても`"private_key"`を呼び出せませんでした。


## create-jsonを使う
　GitHub Actionsのマーケットに公開されている[create-json](https://github.com/marketplace/actions/create-json)というツールを使って解決できました。探せば大体悩みは解決しますね。
　基本的な使い方は、まず登録したいjsonファイルの内容をsecretsに登録します。
![スクリーンショット 2023-05-08 10.15.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1426862/392eb4e9-be47-4ec2-72fb-9f103c8eb5ab.png)

　その後、以下のようにActionsのワークフローに追加することで、secretsに登録したjsonファイルを作成することができます。

```yaml
- name: create-json
  id: create-json
  uses: jsdaniell/create-json@v1.2.2
  with:
    name: "credentials.json"
    json: ${{ secrets.CREDENTIALS_JSON }}
    dir: "src/"
```

`dir`を設定することで必要に応じて、作成するディレクトリを変更することも出来ます。


## おわりに
　大分このsecrets問題と戦っていて諦めかけていたんですが、stackoverflowに辿り着きActionsのマーケットというのを知りました。このマーケットを眺めて便利ツールを発見するのも面白そうです。


## 参考記事
- [javascript - How to pass Github secrets as value in json file? - Stack Overflow](https://stackoverflow.com/questions/72177570/how-to-pass-github-secrets-as-value-in-json-file)
- [create-json · Actions · GitHub Marketplace](https://github.com/marketplace/actions/create-json)