OmniAICreator/Qiita-1.07M huggingface dataset:
[WordPress] wp-config.php で error_reporting() を設定しても反映されない

WordPress が出力するエラーを制御しようとして wp-config.php に [error_reporting()](https://www.php.net/manual/ja/function.error-reporting.php) を追加しても、全然反映されないって事象に遭遇したことありませんか？
WordPress でのエラー制御は `WP_DEBUG` という定数で制御されるのですが、この値によって `error_reporting()` が実行されるので、wp-config.php に error_reporting() を設定しても無視されるんです。

https://github.com/WordPress/WordPress/blob/master/wp-includes/load.php#L424-L490

* WP_DEBUG == true の場合: `error_reporting( E_ALL );`
* WP_DEBUG == false の場合: `error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );`

これは [wp_debug_mode()](https://developer.wordpress.org/reference/functions/wp_debug_mode/) という関数の中で実装されています。
無視して、任意の設定にしたい場合は以下のようにしなさいとコメントがありますので、そのようにしましょう。

```PHP
	/**
	 * Filters whether to allow the debug mode check to occur.
	 *
	 * This filter runs before it can be used by plugins. It is designed for
	 * non-web runtimes. Returning false causes the `WP_DEBUG` and related
	 * constants to not be checked and the default PHP values for errors
	 * will be used unless you take care to update them yourself.
	 *
	 * To use this filter you must define a `$wp_filter` global before
	 * WordPress loads, usually in `wp-config.php`.
	 *
	 * Example:
	 *
	 *     $GLOBALS['wp_filter'] = array(
	 *         'enable_wp_debug_mode_checks' => array(
	 *             10 => array(
	 *                 array(
	 *                     'accepted_args' => 0,
	 *                     'function'      => function() {
	 *                         return false;
	 *                     },
	 *                 ),
	 *             ),
	 *         ),
	 *     );
```

wp-config.php に追加するコードはこんな感じになります。

```PHP
// 本番用: Warning は出力しない
@ini_set( 'log_errors', 'On' );
@ini_set( 'display_errors', 'Off' );
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
define( 'WP_DEBUG_DISPLAY', false );
error_reporting( E_CORE_ERROR | E_COMPILE_ERROR | E_ERROR | E_PARSE | E_USER_ERROR );
// enable_wp_debug_mode_checks フィルターフックには false を返す
$GLOBALS['wp_filter'] = [
    'enable_wp_debug_mode_checks' => [
        10 => [
            [
                'accepted_args' => 0,
                'function'      => function() { return false; },
            ],
        ],
    ],
];
```
SQL Server から取り込んだデータはPower BIで編集できるか

概要
-
SQL Server のテーブルをインポートしたあと、データを追加する方法。

行の追加方法
-
1. Power BI Desktopにて対象のレポートを開き、[ホーム]タブ>[データの変換]を選択して、PowerQueryを開く。
2. [ホーム]タブ>[データの入力]を選択し、[テーブルの作成]にて列名、および追加したい行データを入力して[OK]を選択する。
※テーブル名は任意でOK。
※列名、および列数は、追加したいテーブルと同じ構成に設定する必要がある。
3. 元のテーブルを選択した状態で、[ホーム]タブ>[クエリの追加]を選択する。
4. [追加するテーブル]にて、手順2で作成したテーブルを指定し、[OK]を選択する。
 

補足
-
* Power BIは既存データを編集することはできない。
* 列を変更したい場合は[条件列]を追加するなどして、新しい列を作ること。
* DirectQueryで接続している場合、データソースから取得した特定列の値そのものを置換することはできず、DirectQueryにて接続しているテーブルにおいても、PowerQueryで[対象列]>[値の置換]を選択すれば、値置換自体は可能。
* 複数の同一値（例えばnullとか）に対して、行ごとに別の値に置換する機能はない。
文字列をspanタグで囲む


    <div class="items">
        <h1 class="item">titletitle</h1>
        <p class="item">texttexttexttexttexttexttexttexttext</p>
    </div>

(function(){
        const items = document.querySelectorAll('.item');
        items.forEach(target => {
            let newText =  '';
            const text = target.textContent;
            const result = text.split('');
            for(let i = 0; i < result.length; i++){
                newText += '<span>' + result[i] + '</span>';
            }
            target.innerHTML = newText
        });
    }());

変数の用途
・jstext→要素の取得
・target[引数]→取り出した要素の格納
・newText要素を入れる空の変数
・text取り出したtarget要素を取得
・result取得した文字を格納

for文内の記述
・resultで取り出した文字列を繰り返しspanタグで囲っていく。
囲った文字列をnewTextに格納する。
ARC154回答メモ

0.はじめに
　2週連続のARC。1問解けないとレート駄々下がりという緊張感の中
　1問も解けずにレート急落・・・。

1.A - Swap Digit
　正直問題文を読んだだけでは、解法が皆目見当もつかなかった。
　ただ、直感的に同じ桁の数字のうち、小さい方を一方に集めれば
　なんとなく行けるのではないかと思い実装

　9問ACで9問TLEに。
　その後試行錯誤するもあえなく時間切れ。
　解説読んでも、直感があっていることが裏付けられただけでした。

　翌日ふと、pypy3ではなく、python3で提出したらTLEにならずにAC・・・・
　桁の大きい計算があるときはpypyを使うなという昔刻んだ鉄則を
　忘れてました・・・。無念。。

　https://atcoder.jp/contests/arc154/submissions/38273958

2.B - New Place
　2023/1/23 修正
　解説を読んでも今一でしたが、解説動画を見て解法が分かりました。
　
　本番時は、使用されている文字が一致すれば回数はともかく
　一致する文字列が作れることはわかりつつ放置してましたが
　やはり最初にそのチェックをした方が良いことが分かり
　SとTをソートして比較。
　一致しなかったら-1を出力して終了。
　を、してからの以下の考え方。

　【考え方】
　　操作は先頭から行う形式のため、途中のある文字だけ動かす等はできない
　　→Sの最後の文字から動かさなくてもいい順序になっている文字をカウントし
　　 それ以外の文字は動かすと考える
　　　例題１）で考えると
　　　　S:abab 
　　　　T:abba
　　　　→1)S4：b以外を動かす場合・・・abbaにできる
　　　　→2)S3：a、S4：b以外を動かす場合・・・abbaにできる
　　　　→3)S2：b、S3：a、S4：b以外を動かす場合・・・babに対して、aをどうやっても、abbaにできない
　　　　　→2個残しの状態までがTに一致させられる＝N-2が答え
　　【実装】
　　　Tの後ろから一文字ずつ、Sの後ろから比較していく＝順序を保てる位置にあるかをチェック

　　解説にある通り、2分探索を使わずに、愚直な比較でAC頂けました。

　　https://atcoder.jp/contests/arc154/submissions/38280421

以上
Windows subsystem for Androidの導入

## はじめに
windows11ではwindows subsystem for Androidが利用可能です。
subsystemではapkファイルをインストールし、直接アプリを起動できます。

必要スペック:Windows 11のバージョン22H2以降のスペックにしか対応していません。(8世代以降のcore i7など)

## 手順
今回はAmazon アプリ storeをインストールし、kindleやその他のapkを導入します。

1. Micrrosoft Storeより、「Amazonアプリストア」をインストールします。
※再起動を促されて、再起動をしてもこちらで素直にインストールできない場合があります。
(何の設定弄ったか忘れたので、また追記します。)

2.次に、**Amazon アプリストア**より、kindleをインストールします。(Microsoft storeのはインストールできません。)

## apkの直接インストール
※WSA_Pacmanなるソフトウェアを使うと、D&Dで簡単にインストールできるそうな。

まずは、adbコマンドを必要としますので、[SDK](https://developer.android.com/studio/releases/platform-tools)よりSDKをインストールして、パスを通してください。

**Android用サブシステム設定**をいうアプリを検索し、開発者のタブから開発者オプションをオンにしてください。
オンにすると、同設定部分に「ADBは xxx.x.x.x:xxxxx」との表示があるので、このIPをコピーしてください。

コマンドプロンプトを開き、
「adb connect {IP}」と入力して、adb接続をします。

「adb install {apkファイルの完全パス or ファイルをD&D}」をしてインストールします。

適当なアプリストアなどをインストールすれば、そちらからインストールができます。

以上となります。
safari で RangeError: Invalid time value が出る

Chrome
> new Date('2000-1-1')
> Sat Jan 01 2000 00:00:00 GMT+0900 (日本標準時)

Safari
> new Date('2000-1-1')
> Invalid Date

Chrome
> new Date('2000/1/1')
> Sat Jan 01 2000 00:00:00 GMT+0900 (日本標準時)

Safari
> new Date('2000/1/1')
> Sat Jan 01 2000 00:00:00 GMT+0900 (JST)

* 結論：new Date するとき、ハイフンは使っちゃダメ
便利なJenkinsプラグイン

# 概要
Jenkinsを使用する際に便利なJenkinsプラグインまとめ
※随時追加予定

## 1. Workspace Cleanup Plugin
workspaceを一掃したい場合に使用
[ドキュメント](https://www.jenkins.io/doc/pipeline/steps/ws-cleanup/)
[pluginソースコード](https://github.com/jenkinsci/ws-cleanup-plugin)
- ビルド前にワークスペースをクリーンアップしたい場合：
    1. SCM からソースがチェックアウトされる前にクリーンアップできるように、skipDefaultCheckout(true)オプションを記載
        ```
            options {
                skipDefaultCheckout(true)
            }
        ```
    1.  クリーンアップ後にSCM からソースがチェックアウトする
        ```
        cleanWs()
        checkout scm
        ```
- ビルド後にワークスペースをクリーンアップしたい場合
    - PipelineジョブのpostセクションにcleanWs()を追加
        ```
        post {
            always {
                cleanWs()
            }
        }
        ```
下記、Plugin GitHubのREADMEよりサンプル抜粋
```
pipeline {
    agent any
    options {
        // This is required if you want to clean before build
        skipDefaultCheckout(true)
    }
    stages {
        stage('Build') {
            steps {
                // Clean before build
                cleanWs()
                // We need to explicitly checkout from SCM here
                checkout scm
                echo "Building ${env.JOB_NAME}..."
            }
        }
    }
    post {
        // Clean after build
        always {
            cleanWs()
        }
    }
}
```

## 2. Slack Notification
Slackに処理結果などを通知したい場合に使用
[ドキュメント](https://plugins.jenkins.io/slack/)
[pluginソースコード](https://github.com/jenkinsci/slack-plugin)


例：ビルド成功時、失敗時でslackへ通知出しわけ
[通知先slackの設定方法](https://baba-s.hatenablog.com/entry/2020/09/25/090000)
```
pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo "Building ${env.JOB_NAME}..."
            }
        }
    }
    post {
        success {
            slackSend  color: 'good',
                               message: "build success."
            }
        }
        failure {
            slackSend  color: 'danger',
                               message: "build failure."
            }
        }
    }
}

```
Gitリポジトリのコピー時、git lfs migrateでGIT-LSF移行

# はじめに
Gitって難しいですね。どうやってよいかいつも悩んでいるように思えます。
お仕事で別リポジトリへのコピー作業を行ったのですがすんなりいかなかったので調べた結果をまとめて記述しておきます。

# コピー元リポジトリからGitHubのリポジトリへ丸ごとコピー（Commit情報やtagも反映）したいのだが

- コピー元リポジトリにバイナリファイルが入っているがLSFを使用していな状態でCommitされている。
- コピー先リポジトリはLFSが使える。
- 「git clone --mirror」しただけではリポジトリのコピーが出来ない。（100MB以上のファイルはCommitできない旨のエラーが発生してCommitできない。）

「git lfs migrate」で必要なバイナリファイルをLFSに登録しなおすことによりリポジトリのコピーが可能になりました。

# 前提
- コピー元リポジトリからコピー先のGitHubリポジトリへ丸ごとコピーされます。
- Commit情報やtagも反映されます。
- この操作をするとコピー元の情報で上書きされます。（注意！！）

# 例
- コピー元：　https://XXXXXXXX/git/XXXXXXXXXXX/hehehe.git
- コピー先：　https://github.com/XXXXXXXXXXXXXXXXXX/new-hehehe.git

# 参考資料

https://nanmo.hateblo.jp/entry/2019/08/31/120008


https://github.com/git-lfs/git-lfs/wiki/Tutorial#migrating-existing-repository-data-to-lfs


# 操作
### 適当な場所にworkディレクトリを作成します。
### コピー元から「--mirror」オプションでgit cloneします。

```bash
$ git clone --mirror https://XXXXXXXX/git/XXXXXXXXXXX/hehehe.git
Cloning into bare repository 'hehehe.git'...
remote: Enumerating objects: 32, done.
remote: Counting objects: 100% (32/32), done.
remote: Compressing objects: 100% (30/30), done.
remote: Total 32 (delta 10), reused 0 (delta 0)19.00 KiB/s
Unpacking objects: 100% (32/32), 140.21 MiB | 415.00 KiB/s, done.
```
### git cloneしたディレクトリに移動します。

```bash
$ cd hehehe.git/
```

### git lfs migrate info による事前調査
クローンした[リポジトリ名].gitフォルダに移動したのち、現在の状態を調査
LFSに登録したいファイル拡張子を確認。

```bash
$ git lfs migrate info --everything
migrate: Sorting commits: ..., done.
migrate: Examining commits: 100% (5/5), done.
*.weights 157 MB  1/1 files(s)    100% <<===これをLFSに移行
*.py    23 KB   6/7 files(s)     86%
*.png   15 KB   1/1 files(s)    100% <<===これをLFSに移行
*.pyc   11 KB   3/3 files(s)    100%
*.md    2.9 KB  3/3 files(s)    100%
```

### git lfs migrate import 実行
「--include」にGit LFSに移行するファイルタイプを指定してgit lfs migrate importコマンドを実行する。

```bash
$ git lfs migrate import --include="*.weights,*.png,*.jpg" --everything
migrate: Sorting commits: ..., done.
migrate: Rewriting commits: 100% (5/5), done.
  master        XXXXXXXXXXXXXXXXXXXX -> XXXXXXXXXXXXXXXXXXXXXXXXXXX
migrate: Updating refs: ..., done.
```

### 整合性を保つためローカルのファイル・キャッシュを整理する。

```bash
$ git reflog expire --expire-unreachable=now --all && git gc --prune=now
Enumerating objects: 33, done.
Counting objects: 100% (33/33), done.
Delta compression using up to 8 threads
Compressing objects: 100% (25/25), done.
Writing objects: 100% (33/33), done.
Building bitmaps: 100% (5/5), done.
Total 33 (delta 10), reused 20 (delta 6), pack-reused 0
```

### GitHub.com へ --mirror でプッシュ
```bash
$ git push --mirror https://github.com/XXXXXXXXXXXXXXXXXX/new-hehehe.git
Uploading LFS objects: 100% (2/2), 157 MB | 0 B/s, done.
Enumerating objects: 33, done.
Writing objects: 100% (33/33), 13.64 KiB | 13.64 MiB/s, done.
Total 33 (delta 0), reused 0 (delta 0), pack-reused 33
remote: Resolving deltas: 100% (10/10), done.
To https://github.com/XXXXXXXXXXXXXXXXXX/new-hehehe.git
 + XXXXXXX...XXXXXXXX master -> master (forced update)
```


### GitHubのリポジトリを確認し、全ての変更が反映されている事を確認します。

リポジトリのルートディレクトリに .gitattributes が追加されているので、--include で指定したファイル名、パターンが問題なく記述されていることを確認する。
履歴も改変されて.gitattributesが最初期にコミットされたことになっているはず。
CyclicBarrier class

指定した数のスレッドが終了したら、終了後メソッドを実行させるコントローラ
await methodが終了通知

疑問点
newFixedThreadPool(2),CyclicBarrier(3,...)にすると、
2個目の処理までは行われ、3個目の処理が動き出さない事象が
確認している。
CyclicBarrierに使用しているthread poolは占有されていて使いまわしが
できない？

また、CyclicBarrier(3,...)、実行するスレッドが7の場合、
shutdownしても実行終了しない。
CyclicBarrierが残りのスレッド要求を待ち続けているようだ。
強制的に終了させる方法が不明


```java
class RunnableWithCyclicBarrier implements Runnable {
    private CyclicBarrier c;
    RunnableWithCyclicBarrier(CyclicBarrier c) {
        super();
        this.c = c;
    }
    @Override
    public void run() {
        long id = Thread.currentThread().getId();
        int i = new Random().nextInt(10) * 100;
        System.out.println("START" + id);
        try {
            Thread.sleep(i); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("END" + id);
        try {
            this.c.await();
        } catch (InterruptedException ex) {
            Logger.getLogger(RunnableWithCyclicBarrier.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BrokenBarrierException ex) {
            Logger.getLogger(RunnableWithCyclicBarrier.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
public class Outer {
    public static void main(String[] args) {
        CyclicBarrier c = new CyclicBarrier(3, () -> {System.out.println("after method");});
        ExecutorService e = Executors.newFixedThreadPool(4);
        for(int i=0; i<3; i++) {
            RunnableWithCyclicBarrier r = new RunnableWithCyclicBarrier(c);
            e.submit(r);
            //e.shutdown();
        }
        e.shutdown();
    }
}
```
```
START15
START14
START13
END15
END14
END13
after method
```
Next.jsを使ったプロジェクトをスタートダッシュできるGithub Templateを公開しました

## これはなに？

Next.js x TypeScriptを業務でも副業でもよく使用していて、最初のlint, prettierやらの環境構築が面倒なのでテンプレートを作成したという話です。

同じように最初の設定が面倒だという方の助けになれば嬉しいです。

## 作ったもの

Githubのテンプレート機能として公開しました。

https://github.com/mu-suke/nextjs_template

## どんなものか？

このテンプレートの中には保守性を高めるというテーマで自分がよく設定するものを入れています。

- Renovate
- Husky
- Eslint, Prettier

それぞれの利用目的や設定についてを下に書いていきます。

## Renovate

package.jsonを読み取ってインストールしているパッケージに更新がないかを確認し、更新があれば自動でPull Requestを作ってくれるツールです。

パッケージのアップデートはいちいち追えないうえ、自動でPull Requestまで作ってくれるので迷わず導入しています。

テンプレートを使用する際は自分でアクセストークンやアプリの登録をする必要があるので注意してください。

↓公式ドキュメント

[Running Renovate - Renovate Docs](https://docs.renovatebot.com/getting-started/running/)

renovateに関する設定は/renovate.jsonに記載していて、具体的には以下を設定しています

| 名称 | 機能 | テンプレートの設定 |
| --- | --- | --- |
| baseBranchs | マージ先になるブランチ | main |
| schedule | アップデート確認&PR作成を行うタイミング | every weekend |
| rangeStrategy | 既存の範囲を更新する際のルール | pin |
| prConcurrentLimit | 一度のアップデート確認で作成するPRの数 | 5 |
| packageRules | 1PRに含めるパッケージのグルーピング | Next.js, Linter, React, TypeScript |

## Husky

Huskyはコミットやプッシュの際にテストやlintを実行してくれるツールです。

[https://typicode.github.io/husky/#/](https://typicode.github.io/husky/#/)

個人開発の際は使わないのですが、複数人での開発やプロジェクトの場合はコードの品質が人に依存してしまうのでそれを防ぐために利用しています。

このテンプレートでは**コミット時にlintとprettierが走るようになっていて、lintでエラーや警告が1つでもある場合はコミットできないようになっています。**

セットアップに関してはこちらの記事を参考にしてみてください。

[https://qiita.com/mu-suke08/items/43a492fda5cd71a31506](https://qiita.com/mu-suke08/items/43a492fda5cd71a31506)

## Eslint, Prettier

### Eslint

説明不要の静的解析ツールです。

構文エラーやコーディング規約を設定できるので利用しています。

このテンプレートでは以下の設定をしています。

#### ■eslint-plugin-import

importおよびexportステートメントの構文をチェックしています。

このテンプレートではimportの順番を細かく設定しています。

順番はざっくりと以下のように設定しています。

ルール1

1. オブジェクト（object）
1. 型（type）
1. インデックス（index）
1. ビルドインモジュール（builtin）
1. 外部モジュール（external）
1. 内部モジュール（internal）

#### ■eslint-config-prettier

ESLintの設定をPrettierのフォーマット設定に合わせるために使用しています。

#### ■eslint-config-next

Next.jsに特化したに特化したESLintの設定を提供するパッケージです。

### Prettier

これもまた説明不要のコードフォーマッターです。

複数人での開発の際に、チームの中でのコードのスタイルの統一性を高め、コードをより一貫性のある読みやすいものにするために利用しています。

## 最後に

「こんなものもデフォルトで入れてあると便利かも！」とかあると自分も学びになるのでコメント等していただけると嬉しいです！

ではまた！
Rubyにおいて正規表現 \Aと^の違い

# 正規表現
```Rubyの正規表現でよくある落とし穴は、より安全な\Aや\zがあることを知らずに危険な^や$を使ってしまうことです。```

Rubyの正規表現では、```文字列の冒頭や末尾にマッチさせる方法が他の言語と若干異なります```。このため、多くのRuby本やRails本でもこの点について間違った記載があります。どのようなセキュリティ問題が生じるのでしょうか。たとえば、URLフィールドの入力が有効かどうかを検証するのに、以下のような単純な正規表現を使ったとします。
```
  /^https?:\/\/[^\n]+$/i
```
これは一部の言語では正常に動作しますが、Rubyの^や$は、```入力全体の冒頭と末尾ではなく「行の」冒頭と末尾にマッチしてしまいます```。従って、以下のように改行を含む毒入りURLはフィルタを通過してしまいます。
```
javascript:exploit_code();/*
http://hi.com
*/
```
上のURLをフィルタで検出できない理由は、入力の2行目にマッチしてしまうからです。つまり、1行目と3行目にどんな文字列があってもフィルタを通過してしまいます。フィルタをすり抜けてしまったURLが、ビューの以下の箇所で表示されたとします。
```rb
  link_to "Homepage", @user.homepage
```
表示されるリンクは一見無害に見えますが、クリックすると、攻撃者が送り込んだ悪質なexploit_code()関数を初めとする任意のJavaScriptコードが実行されてしまいます。

```これらの正規表現に含まれる危険な^や$は、以下のように安全な\Aや\zに置き換える必要があります。```
```
  /\Ahttps?:\/\/[^\n]+\z/i
```
```^```や```$```をうっかり使ってしまうミスが頻発したため、Railsのフォーマットバリデータ（validates_format_of）では、正規表現の冒頭の^や末尾の$に対して例外を発生するようになりました。めったにないと思われますが、どうしても```\Aや\zではなく^や$を使いたい場合は、以下のように:multilineオプションをtrueに設定することも可能```です。

この文字列のどの行にも"Meanwhile"という文字が含まれている必要がある
```rb
  validates :content, format: { with: /^Meanwhile$/, multiline: true }
```
この機能は、フォーマットバリデータ利用時に起きがちなミスから保護するだけのものであり、それ以上のものではない点にご注意ください。```^や$はRubyでは 1つの行 に対してマッチし、文字列全体にはマッチしないということを開発者が十分理解しておくことが重要```です。

### 出典
https://railsguides.jp/security.html#%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE:~:text=6.5%20%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE,%E3%81%8C%E9%87%8D%E8%A6%81%E3%81%A7%E3%81%99%E3%80%82

### 気づかせてもらった記事
https://blog.tokumaru.org/2014/03/z.html#:~:text=%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%AB%E3%82%88%E3%82%8B,%E3%81%AE%E3%81%A4%E3%82%82%E3%82%8A%E3%81%A7%E3%81%99%E3%80%82


https://qiita.com/itsumoonazicode/items/e3c7886909ce68986c9a#:~:text=%E3%81%93%E3%81%A1%E3%82%89%E3%81%AE%E3%83%96%E3%83%AD%E3%82%B0%E8%A8%98%E4%BA%8B%E3%82%92%E8%A6%8B%E3%81%A6%E3%81%BF%E3%82%8B%E3%81%A8%E3%80%81%E3%80%8E%E3%80%8C%5CA%E3%80%8D%E3%81%A8%E3%80%8C%5Cz%E3%80%8D%E3%82%92%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%97%E3%82%87%E3%81%86%E3%80%8F%E3%81%A8%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%0A%E2%96%BC%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%AB%E3%82%88%E3%82%8B%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E3%81%AF%20%5E%20%E3%81%A8%20%24%20%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%20%5CA%20%E3%81%A8%20%5Cz%20%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86%20%7C%20%E5%BE%B3%E4%B8%B8%E6%B5%A9%E3%81%AE%E6%97%A5%E8%A8%98

# 感想
まさか正規表現の勉強をしていてRubyの仕様を学ぶことができるとは思わなかった。。
これからも頑張っていきたい。
LAMP、MAMP、XAMPPを基本からまとめてみた【PHP環境構築】

## なんとかAMPとは
① webサービスを構築するための１つのパッケージのこと
② ローカル環境で使う事が多い
③ 簡単に作業を始められる手軽さがある

## LAMPとは
L = Linux
A = Apache = webサーバー = WEBサイトを公開する為に必要なシステム 
M = Mysql = データベース
P = PHP

## MAMPとは
M = Mac 
※MAMPは、MAC環境の人しか使わない

## MAMPを使ってMySQL/phpMyAdminをセットアップ

公式サイト:[MAMP&MAMP PRO](https://www.mamp.info/en/windows/)

①MAMPを立ち上げ、『start』と『WebStart』を押す
②『Tools』の『Myadmin』を選択する


## XAMPPとは
X = どのOSでも対応できる
A = Apache
M = MarinaDB
P = PHP
P = Pearl 

## 参考サイト
[【初心者向け】LAMP,MAMP,XAMPPって何？【ヒント：OS】](https://www.youtube.com/watch?v=8PoyIsvEo9E)
[挫折しないPHPの環境構築(MAMP・MAC)](https://www.youtube.com/watch?v=NC3IQPUCOkw)
[MAMPを使ってMySQL/phpMyAdminをセットアップしよう - SQL講座](https://www.youtube.com/watch?v=Fw_Dpo5pyow)
ChatGPTをQiita記事投稿に活用したい 

## はじめに
2022年後半の熱いトピックの一つにChatGPTがあります。
ChatGPTを使って記事を書けるのか、、ということを試してみます。
さっそく、ChatGPTに聞いてみました。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727269/45c6e5da-8d0f-c675-b998-29ea25f94633.png)
ほほう、そうなんですね。いきなり企画倒れにならずに済みそうな気がしてきました。
私の文章とChatGPTの出力情報を交互に使っていきます。
内容は「ChatGPTについて」です。
とても優秀な回答ですね。

## ChatGPTについて
文を用いた問いかけに対して、文で回答をくれるチャットツールですね。
始まったばかりのサービスで機能としてまだ粗いところがあるものの、AIの機械学習によって日々機能が強化されていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727269/df30cf5e-be6e-08f2-256c-ee9cf7d500c5.png)

## OpenAI社について
ChatGPTを作っているOpenAI社ってどんな会社か知りたいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727269/43bff4a4-15b2-9278-c3d2-076378ae64ab.png)

## Googleとの関係性について
ネットを見ているとGoogle検索に対して脅威になりうるという記事をいくつか見かけた気がします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727269/dc13f643-b41b-c965-c223-cac9961064e7.png)
なるほど、、既存のテクノロジーとのシナジーが期待できますね。

## 最後に
ChatGPTの出力内容をかき集める形でqiitaの記事を書くことはできそうです。
いままでは、ネット検索を使って情報収集しそれをわかりやすく編集するなどして記事を書いていたと思います。
ChatGPTを使用することで、コピー＆ペーストで記事を作れるような場面も増えてきそうですね。
今後ChatGPTが発達することにより、明確な解があるような内容については人間よりも早くわかりやすい文章を生成できることは間違いないのではないでしょうか。
解を出すことが容易になるということは、私たちはいかに有効な問いを立てられるかが重要になってくると考えています。
DataGridViewのデータをDataTableにコピーする処理

~~~ CopyDGVtoDT.cs

private DataTable CopyDGVtoDT(DataTable pdt, DataGridView dgv)
{
    DataTable dt = new DataTable();

    //列名コピー
    for (int i = 0; i < dgv.ColumnCount; i++)
    {
        pdt.Columns.Add(dgv.Columns[i].HeaderText);
    }

    //データコピー
    for (int dgvrow = 0; dgvrow < dgv.RowCount; dgvrow++)
    {
        //Datatableの行追加宣言
        DataRow dr = pdt.NewRow();

        for (int col = 0; col < dgv.ColumnCount; col++)
        {
            dr[col] = dgv.Rows[dgvrow].Cells[col].Value;
        }
        
        pdt.Rows.Add(dr);        //DataRowCollectionに登録
    }
}
~~~ 
DataRow dr = pdt.NewRow(); について、詳細説明ページ：
[Link]: https://resanaplaza.com/datatable%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9/
【Linux】削除チートシート

#  【Linux】削除コマンド
## ディレクトリごと削除
```
rm -rf ディレクトリ名
```
* rは再帰的に処理（ディレクトリの中にディレクトリがあった場合に同じ処理（この場合削除）をする）
* fは強制的に削除

## ディレクトリの中身だけ削除
```
rm -rf ディレクトリ名/
```
* rは再帰的に処理（ディレクトリの中にディレクトリがあった場合に同じ処理（この場合削除）をする）
* fは強制的に削除
文字列を配列と乱数を使って天気を表示するプログラム

文字列を配列と乱数を使って天気を表示するプログラムを実装しました。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文字列の置換テスト</title>
  <style>
    .test1 {
      color:#0000c1;
      font-size:20px;
    }
  </style>
</head>
<body>
  <script>
    // 天気配列
    const array1 = ["snow","cloudy","rain","fine"];
    // 乱数表示0から2
    const num = Math.floor(Math.random()*4);
    const str = "It is fine!";
    let ans = "";
    ans = str.replace('fine',array1[num]);
    
    
    document.write(`<p class="test1"> ${ans} </p>`);

  </script>
</body>
</html>
```
javaScriptのソースコードです

```JavaScript
 // 天気配列
    const array1 = ["snow","cloudy","rain","fine"];
    // 乱数表示0から2
    const num = Math.floor(Math.random()*4);
    const str = "It is fine!";
    let ans = "";
    // 文字の置換
    ans = str.replace('fine',array1[num]);
    //ブラウザに表示
    document.write(`<p class="test1"> ${ans} </p>`);
```
CSS, HTMLのみのカラーパレット

<h1>CSS, HTMLのみのカラーパレット</h1>

<h2>概要</h2>
カラーパレットの作り方が色々ありますが、<br/>
Javascriptを一切使わずにカラーパレットを作りたかったので、<br/>
トライしてみた。<br/>

<h2>利点・こだわり</h2>
<ul>
    <li/>Javascriptを使わないのでシンプル。
    <li/>選択した後のFormの生成も要らないのでそのまま送信できる。
    <li/>カラーパレット自体に選択機能を持たせるのでradio自体は要らない。
    <li/>すべてのidを持たせるのが嫌なので、labelのforは使わない。
    <li/>HTMLはなるべくシンプルに。
</ul>

<h3>仕組み</h3>
<ol>
    <li/>radioを作って、ボタン自体は非表示にする。
    <li/>選択のUIはCSSを付与する。
    <li/>選択したらカラーパレットのbgをグレーにする。
    <li/>カラーパレットのカラーはCSSで指定してHTMLでは指定しない。
</ol>

<h3>HTML</h3>
基本的な構造はそのようになる。

```HTML:html
<div class="colors">
  <label>
    <input type="radio" name="color"/>
  </label>
</div>
```

カラーパレットを増やすとこはコピペするだけで良い
(実際に送信するにはvalueがいるけど)


<ol>
<li/>radioを作って、ボタン自体は非表示にする。

```CSS:css
.colors > label > input {
  display:none;
}
```

<li/>UIはCSSを付与する。<br/>
(パレットの表示に●を使っている)

```CSS:css
.colors > label::after {
  content: '●';
}
```

<li/>選択したらカラーパレットのbgをグレーにする。
inputのbgを変えても、inputは非表示にしているので変化しない。<br/>
なので、checkされているinputの子供を持つlabelのbgを変えている。

```CSS:css
.colors > label:has(> input:checked) {
  background-color: gray;
}
```

<li/>カラーパレットのカラーはCSSで指定してHTMLでは指定しない。

```CSS:css
.colors > label:nth-child(1) {
	color: #E2EFDA;
}
```

child(1)をコピーして、2,3,と書き換えればHTMLは書き換える必要がない。

<h2>最終形態</h2>
こんな感じになる<br/>
例では三つ。

```HTML:html
<div class="colors">
  <label>
    <input type="radio" name="color"/>
  </label>
  <label class="color">
    <input type="radio" name="color"/>
  </label>
  <label class="color">
    <input type="radio" name="color"/>
  </label>
</div>
```

```CSS:css
.colors > label > input {
    display:none;
}

.colors > label::after {
    content: '●';
}

.colors > label:has(> input:checked) {
    background-color: gray;
}

.colors > label:nth-child(1) {
    color: #E2EFDA;
}

.colors > label:nth-child(2) {
    color: #ddEBF7;
}

.colors > label:nth-child(3) {
    color: #FFF2CC;
}
```

<h2>最終</h2>
シンプルだー。<br/>
実際にはinputにnameを付けなきゃいけないので、<br/>
nth-childは作らないでも良いのかもしれない。<br/>
<p/>
ただ、htmlにカラー情報を書きたくない気はする。<br/>

動作コードはこちら
<a href="https://codepen.io/sforest1975/pen/dyjJmdN">
    https://codepen.io/sforest1975/pen/dyjJmdN
</a>
Microsoft の OpenHack (AI Knowledge Mining) に参加してきた

Microsoft が主催するハッカソンのイベントである OpenHack に参加してきた (通算3回目) ので、その内容を今回もまとめます。
前回の記事はこちら↓↓↓

https://qiita.com/coitate/items/1ff6bdc81698f0b66682

https://qiita.com/coitate/items/0ddf75e73c13574ef45f

# OpenHack とは？
以前の記事をお読みくださいませ :bow:

# 何するの？
今回は、Azure の AI 関係のリソースを使ってドキュメントの内容を分析し、クエリによって抽出できるようにするもの。
具体的な内容はネタバレになるのでここには書けないが、キーワードとしては以下など。
* Azure Cognitive Service
* Azure Cognitive Search

上記のリソースを使って検索サービスを構築する。構築はいくつかの Challenge で段階的に行っていき、各 Challenge に設定されている達成基準をクリアすると次の Challenge に進めるという流れ。
他の OpenHack と同様に Challenge 5 までクリアすればバッジをもらえる！ (このバッジのために参加している部分もあったり。。)


# 感想
AI 系については、AI-900 の資格を持っている程度でそれほど詳しくないので、なかなかに難しかった。特に触ったことのないリソースを作成・操作することが多く、OpenHack 自体も9:00～17:00までと長時間なので、だいぶ疲れた。。 :innocent:
でも普段触ることのないリソースを使うのは非常に勉強になったし、事前知識ゼロから試行錯誤しながら目的のサービスを作り上げていくのは大変ながらも非常に楽しかった！

良かったところや微妙なところは以前の記事に書いているので、そちらもお読みください。ご参考まで！

以上です。
もう悩まない！style.displayが効かないなんて言わない！JS

なんで要素取得できてるのに、style.display効かないんや・・・
思考の迷路に迷い込み、classじゃなくてidだと何故かstyle.displayが効いた。
**なんでやねん・・・**

と思っていたら、ちゃんとした理由が書いてある記事を発見しました。
https://teratail.com/questions/275052
>getElementsByClassNameは配列のようなHTMLCollection を返すので、1つしか要素が無くてもそれに適したアクセスをする必要があります。
>
独学でやってると基本がすっぽり抜けちゃうよねぇ。。
```javascript
const hoge = document.getElementsByClassName('class_name');
hoge[0].style.display = 'none'; // hogeが一つだけだろうが[0]が必要
```
とのこと！
もうstyle.displayが効かないなんて言わないよ〜♪絶対〜♪
仮想環境内でのpythonのバージョン変更

<h1>仮想環境でのバージョン変更</h1>
<p>pythonのバージョン変更を行なった際に、仮想環境内でのみ、バージョン変更が反映されていないことに気が付いた。</p>

調べてみると、やはり仮想環境でのバージョンは、仮想環境作成時のバージョンに固定されるらしく、**仮想環境のクリア**を行う必要があると判明した。

<h1>バージョン変更の手順</h1>

初めに、**クリアを行うとpip installしていたものが全て削除されしまう**ので、それへの対応を行うため、以下のコマンドをターミナルで実行する。

ルートディレクトリにrequirements.txtを作成し,
`$ touch requirements.txt`

現在の環境でインストールしているパッケージとバージョンを書き込む。
`$ pip freeze > requirements.txt`

この作業を行うことで、バージョン変更後に、
`pip install -r requirements.txt`
を行うことで、インストールしていたパッケージとバージョンを一括でインストールできる。

以上の作業を行なった後に、
`python -m venv [venvディレクトリ] --clear`
を実行し、仮想環境のクリアを行う。

仮想環境に入り直し、バージョンを確認すると、変更されていると思う。

<h1>最後に</h1>

自分が仮想環境でのバージョン変更が反映されないことに悩んだので、誰かの助けになれば嬉しいです。
数値型で表せないn桁整数の剰余

# **はじめに**
AtCoderで，long long int型（64bit整数）でも表せない整数の剰余を求めるのに苦労した。そのメモ。

# **考え方**
・long long int型（64bit整数）でも表せない整数は文字列型で表す
・剰余計算を桁ごとに分割する

# **関数（c++)**
```diff_cpp
// str...割られる数，mod...割る数，rem...剰余，digits...桁数
using namespace std;
typedef long long ll;
const ll mod = 998244353; 

void str_rem(const string str, const ll digits, ll &rem) {
    rem = 0;
    for (ll i = 0; i < digits; i++) {
        ll p = rem * 10 + (str[i] - '0');
        rem = p % mod;
    }
}
```

# **例**
```diff_cpp
#include <iostream>
using namespace std;
typedef long long ll;

const ll mod = 3;

void integer_rem(const ll num, ll &rem) { rem = num % mod; }

void str_rem(const string str, const ll digits, ll &rem) {
    rem = 0;
    for (ll i = 0; i < digits; i++) {
        ll p = rem * 10 + (str[i] - '0');
        rem = p % mod;
    }
}

int main(void) {
    ll num = 254;
    string str = "254";
    ll digits = str.size();
    ll rem1 = 0, rem2 = 0;
    integer_rem(num, rem1), str_rem(str, digit, rem2);
    cout << "rem1 = " << rem1 << ", rem2 = " << rem2 << '\n';
    return 0;
}

```

# **トレース**
整数254をmod = 3で割ったときの剰余計算

**// 整数254を数値型で表す場合（integer_rem）**

num = 254
*num* % mod = *rem1*
254 % 3 = 2
***rem1 =* 2**

**// 整数254を文字列型で表す場合（str_rem）**
| *i* | *str[i]*|*str[i] - '0'* | *p* | *rem2* |
|:---: |:---:|:---:|:---:|:---:|
|0|'2'|2|2|2|
|1|'5'|5|25|1|
|2|'4'|4|14|**2**|

※ *str[i] - '0'* ...char型（str[i]）をint型にキャスト
***rem* = 2**

# **実行結果**
```
rem1 = 2, rem2 = 2
```

# **関連問題**
[・AtCoder Beginner Contest 135 E - Digits Parade](https://atcoder.jp/contests/abc135/tasks/abc135_d)
[・AtCoder Regular Contest 154 A - Swap Digit](https://atcoder.jp/contests/arc154/tasks/arc154_a)
組込ソフトウエア開発概説：ミドルウエアの入手

<h3>■ミドルウエアの入手</h3>
TCP/IPなどネットワークプロトコルやファイルシステムなど、中間に存在するライブラリ群のことを「ミドルウエア」と呼びます。パソコン向けソフトウエア開発では意識しない、用意されていて当たり前のライブラリも、ファームウエアの世界では何らかの方法で入手する必要があります。<br>
<br>
<b>（ミドルウエア例）</b><br>
・TCP/IPプロトコルスタック<br>
・FileSystem<br>
・暗号/認証アルゴリズム<br>
・GUI<br>
・画像処理、音声処理<br>
・メモリ操作、文字列操作<br>
<br>

ミドルウエアの入手先は、デバイスドライバ同様外部から購入または無償のものを入手するか、自力で実装します。
デバイスドライバで必要だった「デバイス固有の制御方法に関する知識」は不要ですが、やはりミドルウエアはミドルウエアなりに実装難易度が高かったり規模が大きかったりします。自力で実装して実運用に耐えられるくらい動作確認（品質担保）するコスト及び開発に必要な期間を考えると、外部から入手した方が現実的です。

ただ、個人的には「何でもかんでも外部から入手」とは考えていません。例えばイベントログをサーバに送信するSyslogクライアント（オリジネータ）ならRFC読んで書いた方が早いように思いますし、HTTPのリクエストのバリエーションがないなら決め打ちのデータをやりとりするだけの「なんちゃってHTTPc」を実装しただけで用が足りるかもしれません。「外部から入手する！」と決める前にちょっと立ち止まって考えてみるのがエンジニアかなと。

さて、外部から入手する、となるとデバイスドライバ同様必要なカスタマイズの度合いや、ライセンス、サポートについてよく確認しましょう。

<b>・カスタマイズの度合い</b>
普通ミドルウエアは幅広い用途向けに汎用的に設計されているため、設定の変更だけでなく、そのままでは御社の組込機器に対する要求仕様に一部機能が不足していたり性能が満たない可能性もあります。ミドルウエアの仕様についてよく確認しましょう。

<b>・ライセンス</b>
無償ミドルウエアの場合でも完全に好きに使って良いわけではありません。Linuxに多いGPLライセンスのミドルウエアであれば、外部からの求めに応じてファームウエアのソースコードを開示する義務を負いますし、BSDライセンスであれば製品に添付したドキュメントにBSDライセンス条項自体を記載する必要があります。
有償ミドルウエアの場合はそういったことは発生しませんが、どこまでそのソースコードを流用して良いかが条件として決められています。同一会社の製品なら何に使っても良い、CPUが同じなら流用して良い、製品で限定など、ライセンスが御社用途に合致しているかご確認ください。

<b>・サポート</b>
前述のことをWebサイトなどで確認したとしても不明な点も出てくるでしょう。また、組込作業を始めてみると上手く動かずに誰かに相談したくなるはずです。サポートは、誰がどの程度相談相手になってくれるか、という話題です。無償ミドルウエアの場合、その相談相手はユーザフォーラムや運営グループが普通でしょう。某知恵袋やここ（Qiita）も有効かもしれませんが、いずれにせよ回答が来るとは保証されないので、最終的には自分でなんとかする覚悟が必要になります。
一方有償ミドルウエアの場合、そのミドルウエアについての相談はしっかり受けてくれるはずです。購入先候補の会社としっかりコミュニケーションをとり、ミドルウエアが自分の組込機器で目的の動作をさせられることを確認すべきです。
また、どんなに事前に確認・準備しても、実際に組み込んでみると意図した挙動をしなかったり、組込機器が完成して市場に出た後でトラブルが発生、というケースはゼロにはなりません。どの程度サポートしてくれるのかもミドルウエア選択のポイントとなるかと思います。

<b>★Centeでは...</b>
CenteではiTRONOS用のミドルウエアをCソースコード形態で販売（使用許諾）しており、ターゲット基板への移植、独自仕様へのカスタマイズ作業も承っております。案件がやわらかい段階でもお気軽にお問合せください。この道のベテラン営業担当はもちろん、打ち合わせ内容によってはミドルウエアを開発したエンジニアも参加するなど、お客様が不安に思うことがなくなるまでしっかり説明いたします。サポートに関しても購入時には半年のサポートがついており、その後は年単位でサポート契約が可能です。専用メールアドレスにお問合せをいただくと、ミドルウエア開発エンジニアが原則その日のうちに一次回答する体制としており、直ちにソースコードレベルの詳細な問い合わせから始めることができます。また、ミドルウエアに原因があるか切り分けができていない段階でもお問い合わせいただければ切り分けの方法などアドバイスを差し上げます。

Centeミドルウエアパッケージシリーズ
https://www.cente.jp/product/list/


なお、ネットワークミドルウエアだけでも相当種類があり、自分の組込機器にどれが必要なのか不明という方もいらっしゃると思います。ネットワークやセキュリティについては別シーズンで解説したいと思います。


<h3>■今日の閑話</h3>
PCで動作するソースコードを組込環境に移植したことがある方ならわかると思うのですが、PC環境で動作することが前提のソースコードは同じCでもそのままでは組込環境で動かないことがあります。たとえばこんなことで苦労します。<br>
・リトルエンディアン前提で変数と配列を変換している（組込機器ではビッグエンディアンのマイコンがある）<br>
・オート変数で大きな（1Kbyteを超える、など）配列を使っている（組込機器ではリソースが厳しいことが多い）<br>
・intやlongなど表現できる最大値の前提が組込環境と異なる（組込機器のCPUは8bit、16bitのものがあった）<br>
・外部関数を大量に呼んでいて、includeするヘッダファイルも大量（そもそもそれらを全部新たに用意する？）<br>
<br>
もちろん元コードを書いたエンジニアに罪はありません。様々なスペックのマイコン上で、最小限のカスタマイズで動く汎用的なミドルウエアを書く立場になって、改めて組込ソフトウエアの難しさを感じた、というお話です。<br>
<br>

Cente：
https://www.cente.jp/
SPIKEプライムを3系から2系にダウングレードする方法

# SPIKE app 3系について
昨年末、SPIKEのアプリケーションが3系にアップグレードされました。

https://spike.legoeducation.com/

web版で遂にBluetooth接続でプログラムが書き込めるようになった一方で、
各種使用変更やPython使用不可など現状は使い辛いです。
すでに、3系のOSにアップグレードされてしまい、2系を使いたくても使えない方も多いのでは。
ここでは2系にダウンロードする方法を説明します。

# SPIKE プライムのOSダウングレード
下記のサイトよりダウンロードすることができます。

https://spikelegacy.legoeducation.com/hubdowngrade/#step-1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/d8a76e20-aab3-681e-f5a7-ee431f808d57.png)
ボタンを押すと、ページが変わり、PCとSPIKEの接続方法の説明があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/3177ada8-1cbb-71a1-8522-308c8008b780.png)

:::note warn
通常の接続の方法とは異なります。
手順通り、SPIKEとPCを接続しましょう。
ここではこの接続の方法を「DFUモード接続」と呼びます。
:::

:::note alert
WindowsPCをお使いの方は下記のドライバーをインストール必要があります。


https://zadig.akeo.ie/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/73e7dd30-ad5b-1ca6-f6d2-e92fd7d309da.png)
Zadig2.7をクリックしてダウンロードします。

SPIKEとPCをDFUモードで接続後、Zadig-2.7.exeを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/b7588a8a-cd1b-7618-0722-0795debd1543.png)
Install Driverをクリックし、ドライバーをインストールします。
:::

DFUモードで接続出来たら、Open Connection Windowボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/0daba4a0-3b24-7635-e9e5-5e4d5f4c5305.png)

すると、次のポップアップが表示されるので、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/f164d445-912d-cee4-4ff5-43f3b0e657b9.png)

LEGO Technic Large Hub in DFU Mode をクリックし、接続します。

その後、START FIRMWARE DOWNGRADEを押すと、ダウングレードが始まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513482/d1eb6e70-203e-2e97-b0fb-4cb0461eb8ce.png)
Qiita投稿テスト

## 投稿テスト

VSCodeでMarkdownを書く時と同じ操作感！
不便は無さそう。

|11|22|
|--|--|
|aa|bb|

テーブルも大丈夫

2. aa
2. bb
2. cc

リストも大丈夫

```cmd
pip install
```

コードブロックも大丈夫

aaa`aaaa`aaa
↑これも大丈夫

![testimage.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118227/09033b64-5162-a60a-e8ee-5505e6c21638.jpeg)
ドラッグ・アンド・ドロップで画像貼り付け出来る！
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Microsoft Cost Management」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Microsoft Cost Management」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[Microsoft Cost Management を実装する](https://learn.microsoft.com/ja-jp/training/modules/configure-subscriptions/6-implement-cost-management)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azureサブスクリプションの選択」](https://qiita.com/fsd-jume/items/d393f76e0da4f5bea00b)

## Microsoft Cost Management
### Microsoft Cost Management
・コストの分析/管理/最適化を可能にする財務運用(FinOps)ツール
・コストの予測分析や推奨事項によるコストの削減も可能
・コストデータの自動エクスポートも可能
⇒外部システムや外部プロセスと統合可能
・下記の単位(スコープ)で利用可能
　-課金アカウント
　-管理グループ
　-サブスクリプション
　-リソースグループ

※AZ-900の学習まとめでも扱っておりますので、復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azureの管理とガバナンスについて説明する「Azure Cost Managementツール」](https://qiita.com/fsd-jume/items/19b3d30cee710541d25c)

**◆Cost Managementに含まれるコスト**
・Azureサービス使用状況(予約/交渉済みの価格に基づく)
・Marketplace(使用状況/購入)
・予約購入(EA契約/Microsoft顧客契約の各アカウントのみ)
・Azureハイブリッド特典割引など

**◆Cost Managementに含まれないコスト**
・クレジット
・税金
・サポート料金

**◆Cost Managementのレポート**
・Azureサービス/Marketplaceオファリングによって消費された使用量ベースのコストを表示
・支出やリソースの使用量を把握し、異常な支出を検出可能
・レポートをスケジュール化することも可能

### Microsoft Cost Management使用時の考慮事項
**◆コスト分析を検討**
・コスト分析機能で組織のコストを調査/分析可能
・集計コストを組織別に表示することで、コスト発生元の把握と支出傾向の特定が可能
・一定期間の累積コストを監視することで、月/四半期/年単位のコスト傾向を推定可能

**◆予算オプションを検討**
・コストがしきい値や上限を超えないように予算を設定可能
・支出が予算に達するか超えた場合にユーザに通知可能

**◆推奨事項を検討**
・推奨事項でアイドル状態や使用率が低いリソースを確認可能
⇒効率を最適化/向上させることでコスト削減が可能

**◆コスト管理データのエクスポートを検討**
・コスト管理データをAzureから簡単にエクスポート可能
⇒外部システムでコスト管理データにアクセスや確認する場合など

## 次の学習内容
**◆リソースタグ**

https://qiita.com/fsd-jume/items/d1c2799c00afa30ea1b1

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
ServiceNow - g_scratchpad使用方法

### 1.ビジネスルールを作成する
今回は、Incidentにて「Category」が"Hardware"に変更されたときに、「Assignment group」に"Hardware"を設定するという動作を実装します。
表示時ビジネスルールを作成し、"Hardware"グループのSysIDをg_scratchpadに保持します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/669a52a4-3cdc-d301-a39a-df3ccb94e866.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/8a3b6071-1807-6eda-eb7d-a282b5aa2571.png)

### 2.Client Scriptを作成する
「Category」が変更されたときのScriptを実装します。
g_scratchpadは設定時と同様の方法で呼び出すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/b5e3153c-4439-f6dd-5ac9-e1cf1982334b.png)

### 3.確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/eec9d4fa-18c7-d822-fece-2f315cfac6c6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2843998/75b6493f-e291-55a6-bbbc-64ba14cdf5a0.png)
PL-900：ボタン フローを作成する

この投稿はMicrosoft PL-900の受験に向けた勉強資料をMS Learnページを参考にして作っています。
一発合格に向けて頑張りましょう！

[ボタン フローを作成する][MS-Learn]

[MS-Learn]: https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/2b-build-button-flow

## ボタン フローを作成する
* Power Automateモバイル アプリからアクセスできる機能はこちら
    * アクティビティ フィード
    * 参照
    * ボタン
    * フローの管理

* Power Automateモバイル　アプリを使うのに
    * アプリ ストアからPower Automateモバイル アプリをダウンロードしてインストール
    * その後、起動してサインイン
    * アプリを初めて起動すると、アクティビティ フィードが表示される
アクティビティ フィードでは、フローで何が起こっているかを表示する機能
PC側の動作とまったく同じものではないが、役に立つ詳細情報が確認できる
例）フローの最後のアクティビティの表示　→　フローが正常に実行されたかどうかを確認できる
　　失敗した場合は、フローが失敗したステップが表示される

## ボタン フローを作成する
* ボタンフロー
手動アクションによって開始されるフロー
例）上司に「本日は自宅で作業」というメールを送信するためのボタンを作成

    * ボタンを選択すると、フローのいくつかを使用可能
    * 参照を選択すると、コレクションに追加できるその他のボタン フロー用のテンプレートが確認できる

* ボタンの使い方を説明するために、10分後に通知を送信するボタン テンプレートを使用してみる
    * (1) 参照を選択
    * (2) 10分後にアラームを送信するボタン フローを選択

    <img src="https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/media/browse-templates.png" />

    * (3) 「このテンプレートを使用」を選択

    <img src="https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/media/use-template.png" />

    * (4) 「作成」を選択し、完了の順に選択すると、フローが保存される

    <img src="https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/media/create-flow-from-template.png" />
    <img src="https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/media/saved-flow.png" />

    * (5) ボタンを選択し、新しいフローを確認

    <img src="https://learn.microsoft.com/ja-jp/training/modules/build-automated-solution/media/button-flow.png" />

    * (6) フローを選択すると、10 分後、アラームが届く
AWSにアクセス制限をかける

# 課題
AWSにアクセス制限(IP)をかけたい

# AWS公式情報
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html

# 実装の流れ
1. IAMポリシーの作成
2. IAMユーザーもしくはIAMユーザーグループにIAMポリシーをアタッチする
 (IAMユーザーグループにアタッチするのが一般的)

# 手順1. IAMポリシーの作成
IAMポリシーを作成し、以下のjsonで記述する。
xxx, yyyy としているところを許可したいIP郡に書き換える。
<font color="green">**[IAMコンソール] > [IAM] > [ポリシー] > [ポリシーを作成]**</font>
```
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*",
        "Condition": {
            "NotIpAddress": {
                "aws:SourceIp": [
                    "xxx.xxx.xxx.xxx/24",
                    "yyy.yyy.yyy.yyy"
                ]
            },
            "Bool": {"aws:ViaAWSService": "false"}
        }
    }
}
```
■ポリシー作成のイメージ図
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/d44761ec-4ec1-a478-62e6-140be685f235.jpeg)


# 手順2. IAMユーザーもしくはIAMユーザーグループにIAMポリシーをアタッチする
ポリシーをアタッチする (割り当てる)
以下の手順はグループにアタッチする場合
<font color="green">***[IAMコンソール] > [IAM] > [ユーザーグループ] > [対象のグループを選択] > [許可]のタブ > [許可を追加]***</font>

# 実装後
■xxx.xxx.xxx.xxx/24, yyy.yyy.yyy.yyy からアクセスした場合
ログイン可能、割り当てられたIAM権限で操作可能。

■xxx.xxx.xxx.xxx/24, yyy.yyy.yyy.yyy<font color="">***以外から***</font>アクセスした場合
<font color="red">※AWSコンソールのログインは可能。</font>
ただ、全てのAWSサービスへのアクセスが Deny された状態で表示される。
Testlink：添付ファイルがダウンロード出来ない

Testlink 1.9.9

* 添付ファイルをクリックするとブラウザタブが開きそこに内容が表示されてしまう。
* EXCELファイル等は文字化してしまい使えない。

TestLinK イベントログを確認すると、headers already sent by　のエラーが記録されている。
これは　Header関数を呼ぶ前になにかのHTML出力があったことを示している。

C:\xampp\htdocs\testlink\lib\attachments\attachmentdownload.php
を修正することでダウンロードできるようになった。

---

13行目、をコメントアウト

    //@ob_end_clean();

この関数は28行目でも呼ばれているので2回実行されることになる。

---

最初の方をコメントアウトすることでファイルとして出力可能になった。
ターミナルを起動したら直接入力、終了したらローマ字入力に戻す方法

こんにちは、Ctrl([@hiyoctrl](https://twitter.com/hiyoctrl))です。

ターミナルを起動して設定ファイルを変更する時、 ローマ字入力のままだと編集しにくいため、半角英数の直接入力に切り替えなくてはなりません。

設定ファイルの変更を行った後も、半角英数の直接入力のままだとやりにくいため、ローマ字入力に切り替える必要があります。

https://qiita.com/hiyoctrl/items/70885ee39938b72dd657

CTRL配列の最適化のために各種ファイルを修正変更していく中、IMEをその都度、変更するのが億劫（IMEの切り替えを忘れる→間違って入力してしまう→入力した文字を消す→IMEを切り替える）になったため、ターミナルを起動したら半角英数、終了したらローマ字入力に戻す方法を考えてみました。

```
alias nmm='nano .Xmodmap && xmodmap .Xmodmap && xdotool key F13 && exit'
```

上記のような形で適当にエイリアスを設定します。.Xmodmapの編集が終わったら、.Xmodmapを再読み込みして、ローマ字入力に戻して、ターミナルを閉じるという流れです。

```
!/bin/bash

xdotool key F14
sleep 0.1
xfce4-terminal --geometry 95x55+0+0
sleep 0.1
xdotool mousemove 100 100
xdotool click 1
xdotool type "nmm"
sleep 0.1
xdotool key Return
```

ターミナルをウィンドウ左側半分のサイズで開き、ターミナルをフォーカスするため左上をクリック、先ほどのエイリアスを入力、少し待ってから確定という流れです。

（F14は直接入力、F13はローマ字入力）

時々、切り替わらないことがあるため、何かもっとスマートに解決できる方法があるようでしたら、教えて下さると幸いです。
顧客分析の手順 - 単一の表の作り方

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


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


# 顧客分析の手順

## 第4回： 単一の表の作り方
顧客に関するデータを分析していく上で、データ間の関係が有している複雑さは、データ全体の見晴らしを悪くしてしまいます。前回記述した通り、データ管理上、そしてさまざまな目的に利用するために、汎用性の高い形式でデータが保持されていることについて触れました。これによってさまざまな形式に変換することが可能となり、本来はすごく便利なのですが、特定の目的に沿って分析する場合には一見複雑にも見えます。

### 分析データセット
このため、顧客分析を実施するという目的において、以下のような前提でデータを準備してみませんか？というのが今回の提案です。それは「各顧客を行に、それぞれの顧客に関する事実を列に配置した、単一の表を前提として顧客分析を実施する」ということです。これをデータマイニングの世界では、「分析データセット：Analytical Data Set」と呼んでいます。

図6 を参照ください。各行には顧客（番号）が配置され、そして各列にはそれぞれの顧客に関する、性別や年齢、売上金額が並んでいます。実施したい分析の対象は顧客なのですから、最初にこのような行、そして列を考え、これを前提に分析を実施したら、分かりやすくなるのではないでしょうか。列に配置しているのは顧客に関するさまざまな事実です。それは属性であったり、指標値であったりします。データマイニングの世界ではこの行を「サンプル」、そして列を各サンプルに関する「変数」と呼びますが、これと同じ方法で、分析対象となるデータを考えることとします。

<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2768546/e6db3aec-c80c-1c9e-da59-282c1dbe1ae0.png">


そしてこの表の列には、幾つも必要な属性や指標値を追加できると考えます。物理的にこのような表を用意して、列を追加しても構いませんし、仮想的にこのような列を考えても構いません。このような形式で常にデータを想定することにより、データそのものをイメージし易くします。余談ですが Teradata のテーブルでこのような表を作成する場合、列数の制限が 2,048 のため、約2,000列毎に表を用意します。つまり、行数 = 自社の顧客数、列数 = 2,000 のテーブルが N個作成され、分析対象として用意されることを意味します。いずれにしても、このようなデータを前提に分析を実施することによって、それぞれの顧客を横並びで比較できるようになります。


### 変数の作り方
続いて、この列に変数（顧客属性や指標）を流し込むかを考えます。例えば性別であれば、そのままで良いかもしれません。次に年齢。単純化した方が良い場合には年齢層に集約し、より詳細な年齢で理解したい場合には、そのまま利用します。

定量的な指標値の場合、集計の仕方がデータの意味付けを変えていきます。例えば「ある商品A の買上金額」を考えた場合、以下のような変換例が考えられます。

１．商品A 買上金額（500円お買上、変換無し）
２．商品A 買上金額構成比（全商品の買上金額のうち、商品A の買上金額の割合）
３．商品A 買上有無（買上が有ったか、無かったか）
４．買上成長率（任意の連続する 2期間における買上増減率）
５．商品A 買上リフト（全顧客における買上金額平均を分母として、当該顧客の買上金額を把握）
６．2月度買上金額（特定期間に区切った場合の買上金額）
７．セール期間中における買上金額（同上）
８．オンライン買上金額（特定チャネルに区切った場合の買上金額）
９．…

このような例は、理解したい特徴の数だけ存在します。従って、必要な列数は膨大になり得ますし、分析を実施していく中で、さまざまな変数が新たに必要になり、新規に変数を作成しなければならなくなってきます。たとえば、前述した性別と商品A の買上金額を考えた場合、性別と商品A の関連性が気になるかもしれません。その場合、以下の変数を作り変えた方が良いかも…と思われるかもしれません。

##### 商品A 買上リフト（全顧客における買上金額平均を分母として、当該顧客の買上金額を把握）
「例えば男性にしては商品A をよく買う、女性にしては商品A を買わない」という顧客毎の特徴を理解したいのであれば、上記変数を以下のように作り変えます。

##### 商品A 買上リフト（性別毎の買上金額平均を分母として、当該顧客の買上金額を把握）
こういった試行錯誤を分析しながらも実施する場合、最初からこのような形式でデータウェアハウスに保持することが難しいことも、正規形で保持しなければならない理由も分かってきます。それは発生した素のデータをそのまま、重複なく、関連性を維持した形式で管理することにより、このような要求にも柔軟に対処するためです。



このような単一の表をベースにした考え方を実現していくにあたって、元のデータ、そして作られた変数の性質について把握しておく必要があります。このため、次回の連載では、変数の性質について整理することにします。


#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)
DataStage:Windowsにログイン後「Starting DataStage Flow Designer Server..」と出続けるコマンドプロンプトを出ないようにする方法

## はじめに

DataStageをインストールした後にWindowsログインをすると、
コマンドプロンプトが表示され、「Starting DataStage Flow Designer Server..」
というメッセージが連続して表示され、数分後にコマンドプロンプトが
閉じられるという現象があります。

こちら、必須のサービスでは無いので手動でコマンドプロンプトを
閉じても良いですが、自動起動になっている設定を無効化で対応も可能なので、
今回は、そちらの方法を備忘録として残しておきます。

## 実施環境
OS:Windows Server 2019
InfoSphere Information Server:11.7

## 実施方法
1.レジストリエディターを開き、下記のパスまで移動する。
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run

2.IBM_DataStage_Flow_Designerを右クリック＞修正をクリック＞値のデータを削除し
OKをクリックしてOSを再起動する。

## おわりに
今回はwindowsレジストリの自動起動設定を無効にしました。
レジストリを変更しないで対応する手順が、IBMのリファレンスにありますので、
リンク貼っておきます。
<a href="https://www.ibm.com/support/pages/node/6614159">レジストリを変更しないで対応する手順</a>
Container RegistryからArtifact Registryへ移行する際に陥る罠

# はじめに
Google Cloud Platformにおけるコンテナイメージの保存と管理は今までContainer Registryが提供されていましたが、今後提供される新しい機能などはArtifact Registryの方に盛り込まれるそうです。
それゆえ、新規プロジェクトで用いるならばArtifact Registryを採用した方が何かと良さそうです。
今回初めてこのArtifact Registryを利用したのですが、幾つか罠があったので書き留めておきます。

# 注意点その1 Docker認証が違う
Dockerコマンドでpullやpushを行う際、Dockerの認証が必要ですが、それぞれコマンドが異なります。
* Container Registryの場合
```
gcloud auth configure-docker
```
* Artifact Registryの場合
```
gcloud auth configure-docker [選択したリージョン]-docker.pkg.dev
```
まぁ、これはリポジトリのドメインがContainer Registryの場合、`gcr.io`で固定だったから指定しなくてもよかった、っていうので普通にわかるんですよ。
問題は次、、、
# 注意点その2 リポジトリの階層が違う
これが分かっていなくて、認証通ってるのにpushできず半日無駄な時間を使ってしまいました、、、
* Container Registryの場合
```
gcr.io/[作成プロジェクトID(固定)]/[イメージ名+タグ(任意)]
```
* Artifact Registryの場合
```
[選択したリージョン]-docker.pkg.dev/[作成プロジェクトID(固定)]/[リポジトリ名(任意)]/[イメージ名+タグ(任意)]
```
そうです。Artifact Registryになって`[リポジトリ名(任意)]`というのが増えているんです。
TerraformでContainer Registryと同じ感覚でArtifact Registryを作成したら実はそれはイメージ名でなくリポジトリ名だったので、Container Registryと同じ階層の名前でpushしても全然できないという、、、
権限も確実にあるし、認証も通ってるし、、、何なんだ！と思いながら[公式](https://cloud.google.com/artifact-registry/docs/docker/names?hl=ja#containers)を隅から隅まで読んでたらそれに気づいたという、、、
HTMLでPython（PyScript）を使って見た【まだまだ使いにくい】

2022年の5月くらいにリリースされた `PyScript` を今更ながら使ってみました。

## 使ってみた感想・難点

- 動作が遅い（最初にpython実行関連をダウンロードしてコンパイルするため）
- ライブラリを使うとさらに遅くなる
- HTML上でpythonを記述するので補完がない
- 情報が少ない
- 外部ライブラリで使えるものは少ない

## 使い方

`head` 内に以下を追加。

```html
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
```

あとは `body` の　`py-script` 内にpythonのコードを書くだけ。

```html
<py-script>print("Hello, world!");</py-script>
```

![e6b1bd2fb12081fd3ec8b6755e884bf0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949803/bdcbf06c-d0d6-f85c-20bb-1528a442ee51.gif)


## 外部のライブラリを使用する場合

`head` に `<py-env></py-env>` で使用するライブラリ名を記載する。

ライブラリ名の前に `- ` は必要。

標準ライブラリは書かなくてOK。

```html
<py-env>
  - BeautifulSoup
</py-env>
```

あとはimportして使うだけです。

## 外部ライブラリでも使えるものは限られている

使えるライブラリの一覧は以下の通りです。

https://pyodide.org/en/stable/usage/packages-in-pyodide.html

`urllib` や `requests` は使えないので、Webページやデータを取得（特定のキーワードで上位サイト抽出など）はかなり難しそうです。

## まとめ

htmlにpythonをかけるのは革新的ですが、まだまだ改善の余地ありです。

特に、スクレイピングなどもライブラリの少なさから難しいようです。

これからに期待ですね。
GitHub ActionsでChromaticをデプロイした際に発生したエラーの対処法

# やりたいこと
[Automate Chromatic with GitHub Actions • Chromatic docs](https://www.chromatic.com/docs/github-actions)
こちらの公式ドキュメントを参考にして、プルリクエスト作成時にChromaticをデプロイを行うワークフローを作成します。

```:ディレクトリ構成
.
├── .github
│   └── workflows
├── app
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   └── src
├── compose.yml
└── docker
    └── next
```

```yml:.github/workflows/chromatic.yml
name: Deploy Chromatic

on:
  pull_request:
    branches:
      - develop
    types:
      - opened
      - synchronize

jobs:
  chromatic-deployment:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: app
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Install dependencies
        run: npm ci

      - name: Publish to Chromatic
        uses: chromaui/action@v1
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

```


# エラー内容
```
Error: The "path" argument must be of type string or an instance of Buffer or URL. Received null
```

# 解決策

公式ドキュメントのモノレポ構成でのサンプルのように、workingDirを指定することで動作しました。
[Automate Chromatic with GitHub Actions • Chromatic docs](https://www.chromatic.com/docs/github-actions#run-chromatic-on-monorepos)
```diff_yaml:.github/workflows/chromatic.yml
      - name: Publish to Chromatic
        uses: chromaui/action@v1
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
+         workingDir: app

```
cscの作法 その291

# 概要
cscの作法、調べてみた。
HidApiAdapter.dll使ってみた。

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>csc /r:HidApiAdapter.dll usb0.cs

```

# サンプルコード

```
using System;
using System.Linq;
using HidApiAdapter;

namespace DevicesViewer
{
	class Program {
		private static void ShowDevices() {
			var deviceManager = HidDeviceManager.GetManager();
			var devices = deviceManager.SearchDevices(0, 0);
			if (devices.Any())
			{
				foreach(var device in devices)
				{
					device.Connect();
					ShowDeviceInfo(device);
					device.Disconnect();
				}
			}
			else
			{
				Console.WriteLine("no devices found");
			}
		}
		private static void ShowDeviceInfo(HidDevice device) {
			Console.WriteLine(String.Format("device: {0}", device.Path()));
			Console.WriteLine(String.Format("manufacturer: {0}", device.Manufacturer()));
			Console.WriteLine(String.Format("product: {0}", device.Product()));
			Console.WriteLine(String.Format("serial number: {0}", device.SerialNumber()));
			Console.WriteLine("");
		}
		static void Main(string[] args) {
			ShowDevices();
		}
	}
}
```

# 実行結果

```
>usb0
device: \\?\hid#atk4002#3&2f32b022&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
manufacturer:
product:
serial number:

device: \\?\hid#elan1200&col03#5&150f7c31&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
manufacturer: Microsoft
product: HIDI2C Device
serial number: 9999


```


以上。