OmniAICreator/Qiita-1.07M huggingface dataset:
ServiceNowデルタ試験 Tokyo版 を受験するときに参考にしたドキュメントまとめ


![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323138373931302f62336438323036642d316230332d316339312d356135362d3330396636316562373239322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2187910/d7782062-79fc-d757-c917-a9d34b1024e5.png)


ServiceNowデルタ試験 Tokyo版を受験してきました。

私はServiceNowを業務で使った経験はなく、試験対策のトレーニングで少し触ってみた程度の知識でした。そんなServiceNowほぼ初心者が、合格までに準備したことをご紹介しようと思います。
試験の期限が迫っていますので、まだの方はこの記事を参考にして、ぜひ一発合格目指してみてください！

## デルタ試験とは

ServiceNowは半年に1度バージョンアップが行われます。それに伴い認定資格の更新が必要になり、その時に行われるのがデルタ試験となります。
最新リリースで提供された新機能や、関連する既存機能について問われる試験です。

試験の概要は次のようになっています。
* 受験形式
    * Now Learningにログインして受講する
    * 監視なし
    * 自宅で受験可能
* 言語
    * 選択可能（日本語あり）
* 試験時間
    * 60分
* 問題数
    * 10問
* 出題形式
    * 選択問題 (解答は 1 つ)
    * 複数選択問題 (該当するものをすべて選択)
* 試験範囲の主要分野
    * 新機能
    • 更新または変更された機能
    • 廃止された機能
* 再試験は3回まで受験可能
    * 不合格になると、24時間経過するまで再受験できない
    * 4回目以降は、トレーニングコンテンツを再受講する必要がある


Tokyo版の場合、試験期間は2022年11月13日〜2023年2月17日まで受験となります。

詳しくは、こちらのデルタ試験仕様書をご確認ください。

https://www.servicenow.com/content/dam/servicenow-assets/public/ja-jp/doc-type/other-document/delta-exam-blueprint.pdf


## 試験対策、準備したこと

デルタ試験は、ドキュメントを参照しながら受験することができます。試験というより、**新機能を理解するトレーニング**という位置付けなのだと思います。

今回参考にしたドキュメントは、2つあります。これらをうまく活用して試験に臨みましょう。

### Tokyoリリースノート
新機能は、リリースノートを確認することが一番早いと思います。実際に試験をするときに、このドキュメントを参照しながら問題を解きました。
注意点は日本語版が少なく、英語を読み解きながら理解していく必要があります。

https://docs.servicenow.com/ja-JP/bundle/tokyo-release-notes/page/release-notes/family-release-notes.html

### ファクトシート
日本語で製品や機能を確認できる数少ないドキュメントです。
全体をざっくり理解することができます。詳細は製品ドキュメントを参照する流れになります。

https://www.servicenow.com/content/dam/servicenow-assets/public/ja-jp/doc-type/release-docs/release-fact-sheet.pdf


## さいごに

受験前は億劫に感じていましたが、試験内容はリリースノートを読んでいれば解ける問題がほとんどでした。「今回はこんな機能が追加されたんだな〜」といった感じで読み進めると、楽しみながら試験に臨めると思います。
本記事が、読んでくださった方の試験準備に役立てれば幸いです。
Stream#distinct

distinct method 重複削除される
hashcode, equalsで判断されるためcustom classの場合は
overrideする
下記のサンプルはValue#equals()が常にtrueのために
同一値と判断され、すべて重複みなされる
```java
class Value {

    String str;
    public Value(String str) {
        this.str = str;
    }

    @Override
    public int hashCode() {
        return 1;
    }

    @Override
    public boolean equals(Object obj) {
        return true;
    }

}
public class Outer {
    public static void main(String[] args) {
        List<Value> l = Arrays.asList(
                new Value("A"),
                new Value("B"),
                new Value("C"),
                new Value("A")
            );
        Stream<Value> s = l.stream();
        System.out.println(s.distinct().count());
    }
}
```
```
1
```
SNSロゴパック　ダウンロードページまとめ

## Instagram

https://about.meta.com/ja/brand/resources/instagram/instagram-brand/

## Facebook

https://about.meta.com/ja/brand/resources/facebookapp/logo

## Twitter

https://about.twitter.com/ja/who-we-are/brand-toolkit

## LINE

https://line.me/ja/logo

## YouTube

https://www.youtube.com/intl/ja/howyoutubeworks/resources/brand-resources/#logos-icons-and-colors

## TikTok

公式ページ無
python manage.py runserverを行なった際に起きたMySQLに関するエラー

<h1>はじめに</h1>
<p>数日ぶりに、Djangoを利用し作成していたWebアプリを起動しようとすると以下のエラーが起きた。</p>

``System check identified no issues (0 silenced).
Exception in thread django-main-thread:
Traceback (most recent call last): …``
※実際はもっと長いのですが省略しています。

コードを変更した覚えもない、プラス、System check identified no issues (0 silenced)と書かれているので、コードに関わるエラーではないと感じた。

エラーログを読んでみると、どうやらMySQLが起動していないような雰囲気だったので、ターミナルにて
``mysql.server status``
を行ったが、状態を確認すると起動中であった。

結論からすると、MySQLの状態が起動中にも関わらず、うまく動いていないことが原因で、再起動をする必要があった。
自分自身も何故エラーが起きたのかはっきりしていないが、MySQLの再起動に関する手順の勉強にもなったので、メモとしてその手順を書いておく。

<h1>MySQL再起動の手順</h1>

はじめに、MySQLが起動中であることを前提として停止を行いたい。
``mysql.server stop``
をターミナルで入力し、停止しようとするが、状態を確認しても起動中のままだった。

どうやら、この原因はhomebrewにインストールしたMySQLが起動していることが原因らしく
``brew services stop mysql@5.7``
とコマンドを打つ必要があった。
※バージョンは自分の使用しているもの

上記のコマンドを打った後に、状態を確認すると停止になっており
``brew services start mysql``
を行うことで再起動が出来た。

MySQL再起動後に、python manage.py runserverを行うとエラーは発生せず、起動をすることが出来た。

<h1>おわりに</h1>
コードに問題がなさそうにも関わらずエラーが起き、MySQLが怪しい時には、ひとまず再起動をしてみるとも一つの手だと感じた。
neosでlogix その94

# 概要
neosでlogixやってみる。
logixを、俺コードで表現してみる。

# 参考にしたページ

https://qiita.com/ohisama@github/items/48e1e3d773ce702c3070


# 俺コード

```
String = Pulse
	|> While i < 4 do
		if start do
			write ""
			write Int 0
		end
		RandomBool
		|> if true do
			String
			|> + "zun "
			|> write
			write Int 0
		else
			String
			|> + "doko "
			|> write
			n = Int
    			|> + 1
			write Int n
		end
		if end do
			write "doko kiyosi!!"
		end
	end
```

以上。
hashCode, equals method

equals methodは same valueを判定
multi field classは、自分でequals methodをoverrideする。
また、hashcodeは、
equals method is trueの場合、same hashcodeというルールがあるため
equals method override のタイミングで hashcode() method overrideする

下記はnetbeansでgenerateしたequals, hashcode。

```java
class Value {

    String str;
    int i;

    public Value(String str, int i) {
        this.str = str;
        this.i = i;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + Objects.hashCode(this.str);
        hash = 83 * hash + this.i;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Value other = (Value) obj;
        if (this.i != other.i) {
            return false;
        }
        return Objects.equals(this.str, other.str);
    }


    public Value(String str) {
        this.str = str;
    }

}
public class Outer {
    public static void main(String[] args) {
        Value v1 = new Value("A",1);
        Value v2 = new Value("B",1);
        Value v3 = new Value("A",2);
        Value v4 = new Value("A",1);
        System.out.println(v1.hashCode());
        System.out.println(v2.hashCode());
        System.out.println(v3.hashCode());
        System.out.println(v4.hashCode());
        System.out.println(v1.equals(v2));
        System.out.println(v1.equals(v3));
        System.out.println(v1.equals(v4));
    }
}
```
```
53619
53702
53620
53619
false
false
true
```
mocopiをMotionBilderで使う手順

# はじめに
　現時点のmocopiの開発環境としてはUnityとMotionBuilderが用意されている。ここでは、Sonyのサイトに丁寧に書いてある情報以外のMotionBuilderについてメモする。

# 環境
Windows 10
MotionBuilder 2020 (2019-2023が対応)
mixamo

# Sonyのマニュアル
　まず目を通す。ライブラリファイルの置き場所、DeviceからD&Dして繋げるなど、その他のキャプチャデバイスと使い方は変わらない。

　勘違いしやすいのは、ファイル保存モードから、UDP転送モードにした後に、緑のボタンで３，２，１開始しないといけない。勝手に送信始めるわけではない点に注意。

マニュアル
https://www.sony.net/Products/mocopi-dev/jp/documents/ReceiverPlugin/MotionBuilder/MoveAvatar.html

トラブルシューティング
https://www.sony.net/Products/mocopi-dev/jp/documents/ReceiverPlugin/MotionBuilder/TroubleShoot.html



# 通信問題を解決する
Windows標準のままでは、UDP通信を遮られてしまうので、解除する。
コントロールパネルの「ファイアウォールによるアプリケーションの許可」から、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/48320ebb-a559-d575-e9b2-7e79df3cc1d3.png)

「設定の変更」ボタンを押してから、Autodesk MotionBuilderのチェックをし、OKして、閉じる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/99d4739a-25d5-3932-25c5-bcb2fe1c8b4a.png)

# キャラクタの読み込み
モーションデータは適当なモデルに適用して、曲がり具合などチェックする。キャラクタデータは何でもいいが、骨の命名規則が確実なmixamoを使う。適当なキャラクタを選択し、Downloadする。download設定は、FBX binaryのT-pose。
FBXファイルをMotionBuilderにD&Dし、No Animationで読み込む。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/e8ce91cf-46da-b7c2-ac34-d2cb56ecc575.png)

右上のDefine>Skeletonを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/4aa6d58f-beb3-3801-787b-323149b805e1.png)

左下のScene>mixamorig:Hipsを選択した状態で、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/63855cc7-8cc6-5804-71f8-10b4a4bf8e7e.png)
右上の「フォルダを開く」みたいなアイコンLoad Skeleton Definitionを押し、HIKが選択された状態で、OKする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/dd4c14b1-070e-b9ef-53fc-6d87649f6b13.png)
すると、緑の骨になり、骨のマッピングが完了する。mixamoの保存形式が違っていると、名前解決が一発でできない。
南京錠のボタンを押して、ロックして、Bipedを選択し、完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/0bac917e-a331-b0e2-a482-191ffcc053ac.png)
右上のSourceのところをmocopi characterに変更して、完了。
mocopiのキャラクタ定義は、キャプチャが始まると自動で完了すると記載がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/3878e1c5-3798-d746-a1b6-7110c78a9e04.png)


録画などの方法はSonyのマニュアルに記載してある。
レコーディングするには、Device>mocopiのrecordingにチェックすること。
また、レコーディングの赤丸ボタンを押した後に、再生ボタンを押すことで、レコーディングが始まる点に注意。

レコーディング後は、Bake(Plot)作業がある。mocopiを参照しているだけの状態から、骨にkeyを焼き付ける作業がある。なお、mocopiのスペックは50fps。
Swift 複数の条件ソート方法

複数条件でソートする方法を書きます。

# 対象読者
Swift初学者

# 辞書の複数条件ソート
```swift
let dictionary = ["b": 2, "c": 3, "a": 1, "d": 1, "z": 1]
// 1.value昇順ソート
// 2.同じvalue値の時ZtoA降順ソート
let sortedDictionary = dictionary.sorted { (first, second) -> Bool in
    if first.value != second.value {
        return first.value < second.value
    } else {
        return first.key > second.key
    }
}
for (key,value) in sortedDictionary{
    print("\(key) \(value)")
}
// 出力
z 1
d 1
a 1
b 2
c 3
```

条件部分を三項演算子で書くと行数を減らせる。
```swift
let sortedDictionary = dictionary.sorted { (first, second) -> Bool in
    return first.value != second.value ? first.value < second.value : first.key > second.key
}
```

# 構造体のソート
```swift
struct Person {
    let name: String
    let age: Int
    let height: Double
}

let people = [
    Person(name: "Alice", age: 25, height: 162.5),
    Person(name: "Bob", age: 30, height: 180.0),
    Person(name: "Charlie", age: 20, height: 170.0),
    Person(name: "David", age: 35, height: 165.0)
]

// 名前でソートし、名前が同じ場合は年齢でソートし、年齢が同じ場合は身長でソート
let sortedPeople = people.sorted(by: { (p1, p2) -> Bool in
    if p1.name != p2.name {
        return p1.name < p2.name
    } else if p1.age != p2.age {
        return p1.age < p2.age
    } else {
        return p1.height < p2.height
    }
})

print(sortedPeople)
// [Main.Person(name: "Alice", age: 25, height: 162.5), Main.Person(name: "Bob", age: 30, height: 180.0), Main.Person(name: "Charlie", age: 20, height: 170.0), Main.Person(name: "David", age: 35, height: 165.0)]
```

条件部分を比較したいプロパティをタプルにまとめて書くことで、
複数のプロパティでソートすることができます。
```swift
let sortedPeople = people.sorted {
    ($0.name, $0.age, $0.height) < ($1.name, $1.age, $1.height)
}
```
AccessにPostgreSQLのリンクテーブルを張る

# 概要

この記事では

1. PostgreSQLのODBCインストール。
2. DSN登録。

についても書いてます。

AccessにPostgreSQLのリンクテーブルを張るには、まず上記の2つを先にやっておく必要があります。

# ODBCインストール

インストーラー取得の為に、下記へ行く。

https://www.postgresql.org/ftp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/bd73eb76-02aa-f9d5-c620-4622a311db5b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/675b88ab-8505-5081-1303-9b8b2f969e44.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/62026a02-bb74-3291-8e89-1016cc42c637.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a9109f64-7c87-2dcb-9498-7f16f74ea544.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a31f957f-7e16-55ba-2fb1-6103dc34ed64.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/e12b4c7b-36ef-87d5-7fc5-c5b58b59abeb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c2bf386e-d374-a4fa-3120-10f8b0535c36.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f1c7d84d-3e1e-71da-0942-18549d7cedf7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3915dc22-92c6-8068-1c8f-66ab1745a369.png)

# DSN登録

Access（Microsoft365）は32bitを使う場合の設定です。
（DSNもAccessに合わせて32bitを登録します）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/985c56f1-b932-303c-eb04-9ca8077c4d9a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/878fd460-c015-8591-4d0c-5208c5abf69d.png)

ざっくり言うと、ANSIは古いOSでも動くが動作がUNICODEに比べて遅い。
特別な理由が無ければUnicode。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5c17226a-7fa1-aca6-0914-21d925b53181.png)

データソース名はAccessでリンクテーブル貼る時に使う。
『テスト』ボタンで接続OKなら下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a49f3ae1-3100-94f2-6d5a-5b553f3c1111.png)
設定終了したら『保存』ボタン。

# Access側の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4d6e68d0-dbd8-5571-9973-5ebf81cb94f4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2b0930e6-3787-b483-de20-c21964a059a9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/5ac0167e-faeb-23f8-645c-33e0499ae6c7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b64da4f4-7fb3-e857-63fa-2e95112050c5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/222a1e62-dc45-c76b-5b80-b4851047a7fd.png)

リンクテーブル貼れました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/82a1867f-9f14-45f0-4b79-218609630d8e.png)

# 蛇足

個人的にはレコード数が5,000を超えたらリンクテーブルではなく、パススルークエリを使った方がいいかと思います。
（リンクテーブルだと処理重くなる）

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2546
PostgreSQL 15.1, compiled by Visual C++ build 1914, 64-bit
 Microsoft Access for Microsoft 365 MSO (バージョン 2212 ビルド 16.0.15928.20196) 32 ビット
DATASaber:Performance Best Practice　ポイント解説

※解説では解答を明記することがないように気をつけたいと思います、なので全問は載せません、ご了承ください、、
#### パフォーマンがなぜ悪いといけないのか？
フローが途切れて本当のタスクを忘れてしまうリスクがあります。
答えを得るのに遅延が発生したり、もやもやしてしまうかもしれません
#### Tableau内でパフォーマンス向上のために件数を減らせます！
・データ ソースにフィルターを作成し、データソース内のデータ量を削減が可能
・データを読み込む前に抽出フィルタかけておくことでパフォーマンスを向上させる
#### 結合種類
結合
クロスデータベース結合
ブレンド
ブレンディング
リレーションシップ
プライマリグループ
左結合、右結合、内部結合、外部結合
ユニオン　などなど！

#### ライブ接続は早い？抽出接続が早い？
ケースバイケースである！あくまでも

#### 「関連知のみ」オプションを使用すると？
クエリが多くなりますよね！？
block-autosquash-commits-actionとBranch protection ruleでfixupコミットをマージしてしまうのを防ぐ

GitHubでレビューで指摘をもらったり、自分で間違いを見つけたとき、修正のためにgitのfixupコミットを使う人は多いと思います。
多くの開発チームではレビューが通ればfixupコミットをrebaseコマンドなどで、修正先のコミットにfixupコミットを取り込んでからマージする場合が多いでしょう。
ただ、何も対策を講じていないと **あっ！fixupコミットをrebaseしないままmaster(main)にマージしちゃった・・・・** となることが多いです（自分もやらかしたことがあります）。


GitHubを使っている人の場合　https://github.com/mozamimy/autosquash-please のような拡張を入れることで防ぐことができますが、発火しない場合があったりGitHubが変更を加えるとアップデートまで動かなくなる問題があります。

そこで今回紹介する [block-autosquash-commits-action](https://github.com/xt0rted/block-autosquash-commits-action) を導入することでfixupコミットの混入を防ぐ策を紹介します。

## 導入方法
シンプルで、`.github/workflows/(適当な名前).yml`に下記の記述を行うだけです。

```yml:.github/workflows/check_fixup_commit.yml
on: pull_request

name: Check include fixup/squash commit

permissions:
  pull-requests: read

jobs:
  message-check:
    name: Block Autosquash Commits

    runs-on: ubuntu-latest

    steps:
      - name: Block Autosquash Commits
        uses: xt0rted/block-autosquash-commits-action@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}
```

また、各リポジトリのBranch protection ruleに対してこのような設定をします。


![スクリーンショット 2023-03-24 16.22.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359721/e230dee6-1aee-be84-b20e-d50a52fcebf4.png)


ブランチは今回mainを守りたいので `main`、そしてBlock Autosquash Commits(yml参照)を合格しないと、マージできないという設定を加えています。

ここまで設定した上で、fixupコミットを含めたPRを作ってみます。
すると、普段はあるマージボタンが消えており、しっかりマージができないようになっています。


![スクリーンショット 2023-01-26 15.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359721/0d7640bf-bf55-f5c0-766c-ee1b8b1e6898.png)

逆にfixupを解消するとマージができるようになっています。

![スクリーンショット 2023-01-26 15.31.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359721/f7c2f91a-f144-8e86-ae18-8cb98dde0acb.png)

## まとめ
今回はblock-autosquash-commits-actionとGitHubのBranch protection ruleと掛け合わせることでfixupコミットのままマージを阻止する仕組みを作成してみました。
各リポジトリに設定を入れないといけないのがネックですが、拡張機能をチームメンバーに入れてもらうなどの手間はなくなるので是非導入を検討をしてみてください。
【Vue3】Viteで起動したローカル開発サーバーにIPアドレスで外部からアクセスする方法

# はじめに

Vue.js開発において、Viteは非常に便利な開発サーバーとなります。

Vue.jsのコードを書いてViteを使用することで、簡単にローカル開発サーバーを立ち上げることができ、即座にブラウザで確認することができます。

しかし、Viteを使用したローカル開発サーバーはデフォルトではlocalhost(127.0.0.1)にしかアクセスできないため、他のPCからアクセスすることができません。

この記事では、Viteを使用したローカル開発サーバーに対してIPアドレスでアクセスする方法について説明します。

# Network部分にIPアドレスが表示されない

以前は「npm run dev」あるいは「yarn dev」を実施した際に、以下のように結果が表示され、IPアドレスを使ってNetwork経由でアクセスすることが出来ていました。

```shell
VITE v2.1.0  ready in 1426 ms

➜  Local:   http://localhost:8080/
➜  Network: http://192.168.0.100:8080/
```

新しいバージョン(Version2.2より最新)のViteで「npm run dev」あるいは「yarn dev」を実施した場合は、以下のように表示され、Network経由のアクセスは出来ないようになっています。

```shell
  VITE v3.2.5  ready in 1525 ms

  ➜  Local:   http://127.0.0.1:8080/
  ➜  Network: use --host to expose
```

ViteのGithubのディスカッションを確認すると以下のように記載されています。

> The default host now listens to 127.0.0.1 so you only get localhost exposure. It was changed because it is a security concern to expose your file system to external addresses by default.

> [翻訳]localhostでしか公開されないように、ホストのデフォルトでは127.0.0.1のみをリッスンするようになりました。
デフォルトでファイルシステムを外部のアドレスに公開することは、セキュリティ上の問題があるため変更されました。

*セキュリティ上に問題があるとのことで、デフォルトでは外部アドレスでの公開はされなくなったとのことです。*

# Vite開発サーバーをIPアドレスで公開する方法

以前のバージョンと同様にNetwork経由で開発サーバーにアクセス出来るようにする方法は以下の２つあります。

- package.jsonの変更
- vite.config.tsの変更

上記いずれの方法でもIPアドレスでアクセスすることが可能となります。
具体的に２つの方法を説明します。

### package.jsonの変更

プロジェクト内に配置しているpackage.jsonの「scripts - dev」の「vite」に「--host」を追加し、「vite --host」に変更してください。

```json:変更前
{
	"name": "test",
	"private": true,
	"version": "0.0.0",
	"scripts": {
		"dev": "vite",
		"build": "vite build",
		"preview": "vite preview"
	},
	・・・
}
```

```json:変更後
{
	"name": "test",
	"private": true,
	"version": "0.0.0",
	"scripts": {
		"dev": "vite --host",
		"build": "vite build",
		"preview": "vite preview"
	},
	・・・
}
```

ファイルを変更し保存後に「npm run dev」あるいは「yarn dev」を実行することで、Network部分にIPアドレスが表示され、アクセスすることが可能となります。

もし、別のポート番号を使用したい場合は、--port オプションを使用することでポート番号を指定することも可能です。

```json
"dev": "vite --host --port 8080",
```

### vite.config.tsの変更

プロジェクト内に配置しているvite.config.tsの「defineConfig」内に「server - host: true」を追加してください。

```typescript:変更前
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ]
})
```

```typescript:変更後
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    host: true,
  },
  plugins: [
    vue(),
  ]
})
```

ファイルを変更し保存後に「npm run dev」あるいは「yarn dev」を実行することで、Network部分にIPアドレスが表示され、アクセスすることが可能となります。

# 注意点

- Viteを使用してIPアドレスでアクセス出来るようにしたが、他人からのアクセスを許可したくない場合は、制限をかけるなどの対策を取ってください。
- 「--host xxx.xxx.xxx.xxx」でIPアドレスを指定する場合は、自分が属しているネットワークで到達可能なIPアドレスである必要があります。
- Viteを使用する場合は開発サーバーとしてのみ利用することが推奨されています。

# まとめ

Viteを使用する際に「--host」オプションを使用することで、ローカルサーバーにアクセスするためにIPアドレスを利用することができます。

本記事では、Viteの設定方法や注意点について説明しました。
Viteを使用する際の参考にしてください。
VBAでJScriptを利用し、JSONデータをパースする

# この記事について

VBAそのものにはJSON文字をパースするための関数は含まれていないそうです。
なので、JScriptを利用しJSONを読み込み、パースする方法をご紹介します。

### 開発環境
~~~
PC: Windows10 64ビット
Excel：2022 32ビット
~~~
Macだと下記の方法で試しても動かなかったので注意してください。


# 準備

読み込むJSONデータはこんな感じ
~~~json
    {"date":"20221201 17:31:35","measurer":{"id":"0000001""contents":"テスト"},"name": "HogeHoge",}
    {"date":"20221202 11:28:10","measurer":{"id":"0000002""contents":"テスト2"},"name": "HogeHoge2",}
~~~
例なので2行しかありませんが、実際使用したデータは100行以上あります。
このデータの名前を`test.json`とし、Cドライブのhogehogeフォルダの中に格納しました。


# 実装内容
###  コード
~~~VisualBasic
Sub test()
Dim num As Integer
Dim str As String

'ファイル番号を取得
 num = FreeFile
'JSONファイルを開く
 Open "C:\hogehoge\test.json" For Input As #num
 
 'EOF関数でファイルの末尾まで処理を繰り返す
  Do Until EOF(num)
   '1行ずつデータを読み込む
    Line Input #num, str
   'JSON文字列をデシリアライズ（JScriptを利用）
    Dim json: Set json = ParseJson(str)

   'JSONのmeasurer.idを取得
    Dim id As String
    id = CallByName(CallByName(json, "measure", VbGet), "id", VbGet)

    '処理を繰り返す
    Loop
 'ファイルを閉じる
 Close #num
End Sub

Function ParseJson(str)
  Dim scriptControl: Set scriptControl = CreateObject("ScriptControl")
  scriptControl.Language = "JScript"
  scriptControl.AddCode "function Parse(str) { return eval('(' + str + ')'); };"
  Dim json: Set json = scriptControl.CodeObject.Parse(str)
  Set ParseJson = json
End Function
~~~
### 解説
~~~VisualBasic
   'JSONのmeasurer.idを取得
    Dim id As String
    id = CallByName(CallByName(json, "measure", VbGet), "id", VbGet)
~~~
例として、ここでidを取得していますが、同じような書き方でdateやnameも取得可能です。
~~~VisualBasic
   'JSONのdateを取得
    Dim date As String
    date = CallByName(json, "date", VbGet)
   'JSONのnameを取得
    Dim name As String
    name = CallByName(json, "name", VbGet)
~~~


また、メッセージボックスでIDを表示させるなら以下のような書き方になります。
~~~VisualBasic
    MsgBox CallByName(CallByName(json, "measure", VbGet), "id", VbGet)
~~~


# 参考記事
https://andnote.co/notes/717
Linuxについての雑なメモ（たまに更新）

## 概要
* パスを通す
* manコマンド
* 外部コマンドと組み込みコマンド
* よく使うLinuxコマンド
* 各ディレクトリの役割

## パスを通す
### パスを通すとは
* 環境変数`PATH`にコマンド検索パスを追加すること

### パスの通し方
* 環境変数を`export`で設定
* ↓だと最後尾に`/opt/test/bin`を追加する
```
$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
$ export PATH="$PATH:/opt/test/bin"
$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/test/bin
```

### パスが通っているとどうなる？
* 外部コマンドが実行できる
* パスが通っている場合
```
$ print_test
test
```
* パスが通っていない場合
```
$ print_test
-bash: print_test: コマンドが見つかりません
```

## `man`コマンド
### `man`コマンドとは
* `man <コマンド名>`でコマンドのマニュアルを表示するコマンド
* マニュアルからコマンドの説明やオプションなどを知ることができる
* manにはセクション番号がある
```
1: コマンド
2: システムコール
3: ライブラリ関数
4: デバイスファイル
5: ファイルの書式
6: ゲーム
7: その他のいろいろなもの
8: システム管理コマンド
9: カーネルルーチン
```

### `man`コマンドの使い方
* 同一名称が存在するコマンドはセクション番号で検索する
    * 例えば、writeは1.コマンド、2.システムコールの２種類ある
    * システムコールのwriteを調べたい時は``man 2 write``のように検索する
```
$ man -wa write
/usr/share/man/man1/write.1
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man/man1/write.1
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man/man2/write.2
$ man 2 write
```

## 外部コマンドと組み込みコマンド
シェルのコマンドには、外部コマンドと組み込みコマンドがある。

### 外部コマンド
* 実行ファイルとしてファイルシステム上に存在するコマンド

### 組み込みコマンド
* シェル自体に内蔵しているコマンド
* `type <コマンド名>`で外部コマンドか組み込みコマンドか判別できる
```
$ type ls
ls is /bin/ls
$ type cd
cd is a shell builtin
```

### 組み込みコマンドとsudo
* sudoは外部コマンドを実行ためのもの
* 組み込みコマンドをsudoで実行するとエラー
```
$ sudo cd /
sudo: cd: コマンドが見つかりません
```
* サブシェルを使えばsudoでcdを実行可能
```
$ sudo sh -c "cd /tmp/forbidden;ls"
test
```

* `printf`のような組み込みコマンドと外部コマンドの両方が存在する場合は実行可能
```
$ type -a printf
printf is a shell builtin
printf is /usr/bin/printf
$ sudo printf "test\n"
test
```

### `sudo echo "test" > file`のパーミッションエラー
* `>`でファイルに書き込むのはシェルなのでシェルアクセス権限でパーミッションエラーが出る
```
$ sudo echo "test" > file
bash: permission denied: file
```
* 外部コマンド`tee`に`sudo`を付けて解決
```
$ echo "test" | sudo tee file
test
```

## よく使うLinuxコマンド
* ``mkdir -p``
    * 存在しない親ディレクトリも含めてディレクトリを作成する

* ``rmdir``
    * 空のディレクトリを削除
    * 誤って必要なディレクトリを削除するのを防止

* `cat -n <file>`
    * 行番号つきでファイルの内容を表示する

* `less <file>`
    * ファイルの内容をスクロール表示する
```
/<検索したい文字列>:下方向に向かって検索する
?<検索したい文字列>:上方向に向かって検索する
n:次の検索結果に移動する
N:前の検索結果に移動する
```

* `tail -f <file>`
    * アクセスログのような更新されていくファイルを監視しやすい

* `grep -v '文字列'`
    * cat等で除外したい文字列を含む行を指定できる
```
cat access.log | grep -v 'healthcheck'
```

* `find . -name <filename>`
    * ファイルを探す

* ``<cmd> --help``
    * コマンドのヘルプメッセージ表示

* `which <コマンド名>`
    * はコマンドのフルパスを表示するコマンド
    * catを検索する例
```
$ which cat
/bin/cat
```

* `grep -ril "文字列" .`
    * 文字列を含むファイルを検索する
```
$ grep -ril "Hello World" .
./test/test.txt
```

## 各ディレクトリの役割

* `/bin`
    * Linuxシステムの動作に最低限必要な重要度の高いコマンドを格納

* `/dev`
    * デバイスファイルを格納

* `/etc`
    * 設定ファイルを格納

* `/home`
    * ユーザごとに割り当てられるホームディレクトリが配置されるディレクトリ

* `/sbin`
    * 管理者ユーザ向けのコマンドを格納

* `/tmp`
    * 一時的なファイルの置き場

* `/usr`
    * 各種アプリケーションとそれに付随するファイルを置くためのディレクトリ
    * 内部にルートディレクトリ配下と似た構造を持つ

* `/var`
    * 変化するデータを置くためのディレクトリ
    * ログファイルなどが格納される。
stream forEach sorted method

ListやArrayの各要素を委譲処理する仕組み
Stream interfaceに用意されたmethodを使用して処理する
Collection#stream()でfactoryする。
sorted, filter is  intermidiate operation
forEach  is  terminal operation
primitive type は、IntStream, LongStream etc を使用

```java
public class Outer {
    public static void main(String[] args) {
        List<Integer> l = List.of(4,2,3);
        Stream<Integer> s = l.stream();
        s.sorted().forEach(x -> System.out.println(x));
        s = l.stream();
        s.filter(x -> x % 2 == 0).forEach(x -> System.out.println(x));
        int[] ia= {1,2,3};
        IntStream is = Arrays.stream(ia);
        is.forEach(System.out::println);
        Set<String> st = new HashSet<>();
        st.add("c");
        st.add("x");
        st.add("b");
        Stream<String> ss = st.stream();
        ss.forEach(System.out::println);
    }
}
```
```
2
3
4
4
2
1
2
3
b
c
x
```
paralellStream sample
multi thread process
forEachOrderedは順番通り、forEachは順不同
```java
public class Outer {
    public static void main(String[] args) {
        List<Integer> l = List.of(1,2,3);
        l.<String>parallelStream().forEach(System.out::println);
        l.<String>parallelStream().forEachOrdered(System.out::println);
    }
}
```
```
2
3
1
1
2
3
```
Xcodeビルドエラーの備忘録


**M1,M2のiOS Simulatorでビルドする際に発生するバグが対象。**
## **could not find module for target 'x86_64-apple-ios-simulator'...**
対処法
1. Finderを開きXcodeのアプリがある場所に移動する。
2. Xcodeを右クリックして、「情報を見る」を選択する。
3. Rossetaを使用して開くにチェックを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128814/63c68162-e9ef-805c-69b5-23b220922f92.png)

## **building for iOS Simulator, but linking in object file ... for architecture arm64**

対処法
1. Xcodeでプロジェクトを開き、TARGETSからアプリを選択してBuild Settingのタブを選択する。
2. Excluded ArchitectureのDebugに「Any iOS Simulator SDK」を選択して「arm64」を追加する。

エラー文では「arm64」と出ているが「x86_64」などの場合のエラーも存在するためエラーに合わせて変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128814/9b7a5799-a895-4af1-60e1-1534aa6570c4.png)
Testlink：プロジェクト表示順を変えたい

メイン画面のプロジェクト選択の表示

1.9.9 では最新のプロジェクトが上になるよう表示されていた
1.9.15 あたりから、プロジェクトの Prefix 順に表示されるようになった

**最新プロジェクトが上位に来る表示に戻したい**

# 1.9.9 と同じ表示にするには

config.inc.php を修正

コンフィグファイル中の tprojects_combo_order_by を検索
* 543行目付近の prefix を空欄に、
* 552行目付近の ORDER BY を 'ORDER BY nodes_hierarchy.id DESC ' にする

---

    /**
     * ''       => test project name
     * 'prefix' => prefix : test project name
     *
     * ATTENTION : * is used to indicate test project is INACTIVE
     *             see also $tlCfg->gui->tprojects_combo_order_by
     */
    $tlCfg->gui->tprojects_combo_format = '';
    //$tlCfg->gui->tprojects_combo_format = 'prefix';

    /**
     * Order to use when building a testproject combobox (value must be SQL compliant)
     * For example:
     *    'ORDER BY name'
     *    'ORDER_BY nodes_hierarchy.id DESC' -> similar effect to order last created firts
     **/
    $tlCfg->gui->tprojects_combo_order_by = 'ORDER BY nodes_hierarchy.id DESC';
    //$tlCfg->gui->tprojects_combo_order_by = 'ORDER BY TPROJ.prefix ASC';

---

## テストプロジェクト名順で表示したい場合

    $tlCfg->gui->tprojects_combo_order_by = 'ORDER BY name' ;

にする。
chatGPTというかGPT-3をスプレッドシートから使うテスト

Twitterでも話題になっていたので試してみた。

結論としては、何かを調べる代わりに使うのはGPT-3だとまだ無理。
（GPTが駄目なのではなく、現時点では向いてない）

# やりかた

事前にOpenAIでAPIのキーを作成しておく必要あり。
１８ドルの無料利用権がとりあえず貰えるので、試すだけならそれで出来る。

適当にスプレッドシートを作成して、拡張機能からAppScriptを選択して、次のコード（コメント適当）を保存する。

```
/**
* GPT-3 Google Sheets
*/

const SECRET_KEY = "OpenAIのシークレットキー";

// 0が一番賢いが一番料金がかかるdavinci（デフォルトにする）
const MODEL_NAME_LIST = ["text-davinci-003","text-curie-001","text-babbage-001","text-ada-001"];

// 0-5, for random param.
const MODEL_TEMP = 0.3;

// 質問分、MAX利用トークン、利用モデル番号の順に指定
function GPT(prompt,max_tokens=25,use_model=0) {
  const url = "https://api.openai.com/v1/completions";
  const MODEL_NAME = MODEL_NAME_LIST[use_model];

  const payload = {
    model: MODEL_NAME,
    prompt: prompt,
    temperature: MODEL_TEMP,
    //max_tokens: MAX_TOKENS,
    max_tokens: max_tokens
  };

  const options = {
    contentType: "application/json",
    headers: { Authorization: "Bearer " + SECRET_KEY },
    payload: JSON.stringify(payload),
  };

  const res = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
  return res.choices[0].text.trim();

}

```

これで、適当にスプレッドシートから質問文をテキスト結合とかでこのGPT関数を実行してやる。

```
=IF(ISBLANK($A4),,GPT($A4&"の"&B$3&"は？",50,2))
```
例えばこんな感じ。

# 結果
そもそもGPT-3は2020年くらいまでのデータセットしか持っていないので、最新の情報は答えられないというのは理解しておく必要がある。
chatGPTで使われている3.5はもうすぐAPI公開で、こっちは2021年くらいまでのが入っている、とかいうのは詳しい解説ページにおまかせ。

とりあえず国の人口を答えて貰う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081290/1115aef3-8ee1-ec4e-5f62-3f2ec5f15073.png)

質問形はダ・ヴィンチ以外はとりあえずマトモな回答が返ってこなさそう。
ということは分かった。

次に企業について答えてもらう
語尾とかを指定できるようにシートは少し改良。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081290/53c77e5c-da01-f51e-bac4-4dc67a7cdc74.png)


ちなみにchatGPTのサイトで試すと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2081290/1ebb874a-44e6-85e5-737a-c6afa1e169cd.png)

ニンテンは京都にあるの知ってれば騙されないが、色々間違っている部分がある。
凄いAIだけど、何かの正確な情報をピンポイントで出すという点ではまだいまいち。
ファインチューニングとかすれば問い合わせ対応にはある程度は答えられるのかも。

多分MSが進めようとしている、検索エンジンとのあわせ技とかで威力は発揮されるけど、
現時点ではこれで人を置き換えるというレベルではない。
あと２，３年したらかなり強化されるとは思う。
neosでlogix その93

# 概要
neosでlogixやってみる。
logixを、俺コードで表現してみる。

# 参考にしたページ

https://qiita.com/t-yamanashi/items/01136d54d89fe42679ab


# 俺コード

```
Int = Pulse
	|> For 4 do
		if start do
			write 0
		end
		Int
		|> + i
		|> write
	end

String = Pulse
	|> For 4 do
		if start do
			write "start"
		end
		s = i
			|> Format "{0}"
		String
		|> + s
		|> write
		if end do
			write "end"
		end
	end

```

以上。
Windowsでコマンドプロンプトのレスポンスを直接クリップボードに入れる

# 概要

下記のようなコマンドのレスポンス（表示された値）を文字列として取得したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4aeb38cd-831d-81af-84ec-51c25250a57d.png)

```>``` を使ってtxtに出力する方法もあるが、それだとゴミファイルができてしまう。

もう少しサクッとできる方法がいい。

# やり方

コマンドの後に ``` | clip``` 付ける。

例えば下記のようにやると、 ```ipconfig /?``` の結果がクリップボードに入る。
（コマンドプロンプトにはレスポンスが表示されない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a3964689-ab3e-6c4f-9e4e-208436e69a3b.png)

テキストエディタに Ctrl + V すると、下記のようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a80cdca6-a4b7-eb62-d0e5-c54048c6a337.png)

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2546
Windowsでigraphを入れてpythonから使うまで

主にこちらの記事を参考にさせていただきました。

 - https://qiita.com/link_to_someone/items/4a8de1824287d3976031

# ポイント

 - pythonからpipだけでは完結しない
 - まずwindowsでターミナル操作するためMsys2が必要
 - Msys2のバージョン管理ソフトPACMANを使ってcairoをインストール
 - pycairo-pythonバインディングをDLして手動でpip
 - igraphモジュールをDLして手動でpip

# Msys2のインストール

 - https://www.msys2.org/
 - インストーラーをダウンロードしてインストールするのみ

参考
 - https://hytmachineworks.hatenablog.com/entry/2017/03/19/184108

# Msys2でPACMANを使ってcairoをインストール

Msys2はインストールすると、似たようなアイコンが複数できてどれを起動すればいいのか迷った・・・。
![スクリーンショット 2023-01-26 133813.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371786/161a12ce-8f41-c800-a67a-52aa86fcd4dd.png)
**MSYS2 MSYS**というので良いのだと思う。（誰かそれぞれのアイコンの意味を教えてください）
Msys2を起動して、次のようなコマンドを打つのみ。

    pacman -Syu  #pacmanの更新 
    pacman -Sy mingw64/mingw-w64-x86_64-cairo

参考
 - https://hytmachineworks.hatenablog.com/entry/2017/04/22/155842

# pycairo-pythonバインディングをDLして手動でpip

Msys2を使った操作は前節で終わりで、ここからはPowerShellを使った操作になる。

cairoとpythonのバインディングのために、Python拡張のWindowsバイナリをインストールせねばならない。コンパイルが自力でできる人ならば、ソースコードからコンパイルして自力でバイナリを作ればよいが、それができない人のために非公式でバイナリを配布している方がいらっしゃるのでそちらの力をお借りする。Christoph Gohlke ありがとうございます。

 - https://www.lfd.uci.edu/~gohlke/pythonlibs/

私がアクセスしたときはhttpsの証明書が切れていて、Chromeの「安全ではないサイトにアクセスしようとしています」という警告にビクイクしながらダウンロードしました。

上記のサイトでpycairo含む様々なバイナリが配布されている。ページ内検索で「pycairo」を検索して目的のバイナリを探す。

 - pythonのバージョンが3.11なら cp311 という文字列が入っているもの
 - windows 64bitならamd64という文字列が入っているもの
 - 上の両方の条件を満たすものがダウンロードすべきもの
 - 自分の場合は pycairo‑1.21.0‑cp311‑cp311‑win_amd64.whl でした

バイナリをダウンロードしたら、ダウンロードした場所に移動して、pipでインストールを行う。

    PS>pip install .\pycairo-1.21.0-cp311-cp311-win_amd64.whl
    #もしかしたら --user を最後につけたほうがよいかも？

# igraphモジュールをDLして手動でpip

続いて、igraphをpipでインストールします。同じく https://www.lfd.uci.edu/~gohlke/pythonlibs/ からダウンロードします。

自分の場合は 「 igraph-0.9.11-cp311-cp311-win_amd64.whl 」をダウンロード。

    PS>pip install .\igraph-0.9.11-cp311-cp311-win_amd64.whl --user
    Processing c:\users\llshi\downloads\igraph-0.9.11-cp311-cp311-win_amd64.whl
    Requirement already satisfied: texttable>=1.6.2 in c:\python311\lib\site-packages (from igraph==0.9.11) (1.6.7)
    Installing collected packages: igraph
    ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
    python-igraph 0.10.3 requires igraph==0.10.3, but you have igraph 0.9.11 which is incompatible.
    Successfully installed igraph-0.9.11

ここで、python-igraphはigraph 0.10.3を要求するけれども、あなたは 0.9.11 ですというエラーが出てヒヤッとします。

しかし、なぜかわからないけれども大丈夫でした。

そのあとで、

    pip install igraph

というコマンドも実行しましたが、必要だったかどうかは不明です。

# pythonでigraphが使えるかどうか動作確認
    
pythonを対話型で起動します。

     from igraph import *

まずはインポートします。面倒なのでigraphから全部です。
そして、有名なグラフを指定してplotします。

    g = Graph.Famous('Levi')
    plot(g)

Famous関数の中にほかにも　Bull, Diamond, Petersen, Zachary など入れることができます。

 - https://igraph.org/c/doc/igraph-Generators.html#igraph_famous

![スクリーンショット 2023-01-26 142830.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371786/af3a7354-fc52-1360-43ab-b9ff3a7c2d09.png)
Steam Deckは開発環境になるのか

Steam Deckを買いました。ゲームもやってますが、それと同じくらいWebアプリの開発機としても使いたいなと思っています。

一度VSCodeやDockerのインストールに挑戦はしたんですが、Arch Linuxに慣れていない点や、
https://help.steampowered.com/ja/faqs/view/671a-4453-e8d2-323c
こちらの記事にある
> Flatpak以外（例：Pacmanなどを使用）でインストールしたものはすべて、次のSteamOSアップデートで消去される可能性があります。

という点が引っかかってしまい、一旦諦めてしまいました（その後のOSアップデートで無事作りかけの開発環境は消えてしまいました）。

今回は

https://qiita.com/KEROLL5/items/fdcc64d9d395e4ad1e86

こちらの記事を参考にDistroBoxを使ってWebアプリ（React）の開発環境構築をしてみたいと思います。確かに、コンテナ内に作るのが一番クリーンそうです。

# 0. DistroBoxのインストール

上記の記事を参考にインストールします。

## 0.1 DistroBxとは

https://ja.linux-console.net/?p=2546#gsc.tab=0

Linux内に別のディストリビューションのLinuxを、WinsowsのWSLのように立ち上げることが出来るもののようです。Qiitaで`distrobox`というタグのついた記事が全くないのが少し驚きでした（`Docker`のタグのついた記事はめっちゃある）。

> 起動されたコンテナはホストシステムと高度に統合され、これにより、外部ストレージ、USBデバイス、およびグラフィカルアプリケーションとともにユーザーのHOMEディレクトリを共有できます。

というのがちょっと面白そうなところですね。

# 1. Ubuntuコンテナを追加

Ubuntu:22.04を追加します。
```shell
$ distrobox create -i ubuntu:22.04
```
こちらの環境ではエラーが出てしまいました。
どうも`/etc/subuid`と`/etc/subgid`に`deck`ユーザーを追記する必要がありそうです。
どちらのファイルも
```
root:100000:65536
```
という内容になっていたので、そこに
```
deck:200000:65536
```
を追記しました。
続いて
```shell
$ podman system migrate
$ podman unshare cat /proc/self/uid_map 
```
を叩くと
```shell
$ distrobox create -i ubuntu:22.04
```
が正常終了しました。

# 2. UbuntuコンテナにVSCodeをインストール

Windows＋Dockerの場合だとDevContainerを使うところですが、今回はUbuntuコンテナにVSCodeをインストールし、コンテナ内から
```shell
$ code .
```
を叩くようにしてみます。

```
distrobox enter ubuntu-22-04
```

でUbuntuコンテナ内に入ります。ちなみにコンテナ作成時に`--name`オプションでコンテナに名前を付けることが出来ます（デフォルトでは`ubuntu-22-04`という名前のコンテナが作成されます）。


https://code.visualstudio.com/download

こちらから`.deb`をコンテナ内にダウンロードし、コンテナ内で
```
$ sudo dpkg -i code_xxx_amd64.deb
```
を叩きます。

しかしこちらの環境では、色々とパッケージが足りないと言われてしまいました。

とりあえず、パッケージマネージャーをアップデートします。
```shell
$ sudo apt-get update
```
インストールされているパッケージも最新化しておきます。
```shell
$ sudo apt-get upgrade -y
```

すると再びエラーメッセージが表示され、`apt --fix-broken install`を叩くよう表示されたので、

```
$ apt --fix-broken install
```

を叩きます。これで再実行すると、無事UbuntuにVSCodeがインストールされました。

# 3. VSCodeの開発環境構築

Ubuntu内の任意のディレクトリで以下を叩きます。

```shell
$ code .
```

するとVSCodeのウィンドウが開きます。コンテナ内にリモート接続しているわけではなさそうですが、Ubuntu内が参照できています。

後は通常の環境構築を進めることになります。

## 3.1 Node.jsをインストール

以下のコマンドでNode.js18が入ります。

```shell
$ curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
$ sudo apt-get install -y nodejs
```

## 3.2 Reactの開発環境構築

```shell
$ npm create vite <プロジェクトディレクトリ>
```

を叩くとまず`vite`のインストールが始まり、Viteを使った環境構築が始まります。

環境構築後、

```shell
$ cd <プロジェクトディレクトリ>
$ npm run dev
```

でブラウザでアプリケーション画面が確認できるようになり、ついでにファイル編集でHMRが動いていることが確認できると思います。

## 3.3 コンテナとのファイル共有に関して

```shell
$ distrobox rm Ubuntu-22-04
```
でコンテナを削除してしまえば、コンテナ内にインストールしたVSCodeは消えてしまいます。ただhomeディレクトリは（Dockerと違い）特に設定しなくてもコンテナ内外で共有されているので、開発したソースファイル等は残りそうです。

# まとめ

今回の構築方法でも、SteamOSのアップデートで消去されないかは残念ながらまだ未検証です（そのうちわかると思います　→　消去されないようでした）。

そんな場合でもVSCodeのインストールだけ済ませたUbuntuをイメージ化しておくと、少しは再構築が楽そうですね。

SteamDeckが気軽なゲーム機だけでなく、気軽な開発環境機になると良いなと思います。
youtube動画を検索して複数いっきにみる JavaScript

JavaScript で youtube 動画を複数おってきていっきにみる
大雑把な流れと使ったAPI

- youtube実行するAPIキーを取得（手順は適当なページを参考）

- youtube 表示する枠を作る（youtube player api の読込）
https://developers.google.com/youtube/iframe_api_reference?hl=ja

- youtube の api で動画をとってくる（youtube data api 実行） 
https://developers.google.com/youtube/v3/docs/search/list

```HTML:index.html
<!doctype html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
</head>

<body>
<input type="text" id="word"></text>
<button id="find">検索</button>
<div id="youtubeplayer"></div>
</body>

<script src="script.js"></script>

</html>
```

```JavaScript:script.js
/** youtube data api key */
const youtubeDataApiKey = 'ここに取得したkeyを設定';

/** youtube player api の読込 */
const youtubePlayerApiScript = document.createElement('script');
youtubePlayerApiScript.src = "https://www.youtube.com/iframe_api";
const firstScript = document.querySelector('script');
firstScript.parentNode.insertBefore(youtubePlayerApiScript, firstScript);

/**
 * youtube player の表示用 dom 追加、設定
 */
const players = new Array(20); // 表示したい数
function onYouTubePlayerAPIReady() {
    for (let index = 0; index < players.length; index++) {
        let pl = document.createElement('div');
        pl.id = 'player' + index;
        document.querySelector('#youtubeplayer').appendChild(pl);
        players[index] = new YT.Player(pl.id, { width: 'auto', height: 'auto' });
    }
}

/**
 * 検索 ボタン押下で youtube api 実行して動画取得して設定
 */
document.querySelector('#find').addEventListener('click', async (e) => {
    console.log(players);
    const params = {
        key: youtubeDataApiKey,
        type: 'video',
        part: 'id',
        maxResults: players.length,
        q: document.querySelector('#word'),
        order: 'date',
    };
    const url = new URL('https://www.googleapis.com/youtube/v3/search');
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
    const response = await fetch(url);
    const json = await response.json();
    console.log(json);
    for (let index = 0; index < players.length && index < json.items.length; index++) {
        players[index].loadVideoById({ videoId: json.items[index].id.videoId });
    }
});
```
JSのように簡潔にレコードをつくる方法

追記 2023.07.25

RIOのREADMEに、詳細は追ってませんが、次のような注記あり。

> RecordWildCards is really up for debate. It's widely used, but rightfully considered by many to be dangerous. Open question about what we do with it. 

----

(以下原文)

RecordWildCards 拡張を導入すると次のような簡潔な方法でデータを生成できる。

```haskell
#!/usr/bin/env stack
-- stack --resolver lts-20.7 script

{-# LANGUAGE RecordWildCards #-}

data MyData = MyData
  { foo :: !String
  , bar :: !String
  } deriving (Show)

main :: IO ()
main = do
  let foo = "Foo"
  let bar = "Bar"
  let myData = MyData {..}
  print myData -- Output: MyData {foo = "Foo", bar = "Bar"}
```

# 参考文献

- https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/record_wildcards.html
LINEの公式アカウントをAIに任せてみる


突然ですが、LINEの公式アカウントってどうしていますか。キャンペーンなどで友達追加してみたけれど通知が煩わしかったりして何となくブロックしてしまった経験は誰にでもあるかと思います。

これは見る側としては自然な行動ですが広報として使うには避けたい事例です。定期的に新しい情報が送れるのが強みなのに、次の更新までに見放されてしまっては意味がありません。またせっかくLINEを利用しているのですから、もう少し双方向でのやり取りも行いたいものです。

今回は自分の開発したアプリの公式アカウントに会話AIを組み込むことでこの問題に対応してみました。細かい部分の差はあれど、同じような試みをする際の参考になればと思います。

# 会話AIを使おう！

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713689/87398ce7-96cc-a80f-1cb6-e6223eee067c.png)



ここでの会話AIとは質問に答える事務的なチャットボットではなく、Chat GPTのような自然な会話ができる人工知能のことを指します。彼らを公式アカウントに組み込むことで、これに話し相手としての役割を加えることができます。

これによってただ情報発信を行うだけのものよりは注目してもらえると考えました。少し話は違いますが、高級ブランドや車販売の現場では売り込みだけでなく普段のコミュニケーションも大事にしていると聞きます。私たちエンジニアはそこまで手を回すことはできなくとも、代行してくれるシステムは組み上げることが可能です。

# 実際にやってみる

## 会話AI『Eveki』

肝心なのはどんなAIを選ぶかということです。GPT-3など多くの選択肢が考えられますが、今回は自作の会話AI『Eveki』を採用しました。そもそも宣伝するのがこれのアプリ版である、というのも選定の理由のひとつでもありますが、キャラクター性に特化しているので広告塔にはもってこいなのです。こちらについての詳しい記事は以下を見てもらうとわかりやすいと思います。

https://qiita.com/KokumaruGarasu/items/bfb7f28286f7b48e2c99

どんなAIを使うかは広めたい内容によって変更すべきだと考えます。ただし漠然とサービスの代表として設定するよりも、マスコットのような何らかのキャラクターを決めてそれに話してもらう方が会話AIとしての特性を活かしやすくなるはずです。

## LINE Developerの準備

![スクリーンショット 2023-01-26 13.51.42.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713689/5da67b27-3512-6aa2-3179-6cff5bab8208.jpeg)


必要なアカウント作成の手順については既に詳しい記事が多く存在するためここでは詳しく触れません。ただ公式の登録ページおよびドキュメントが充実していること、また後から修正できる部分も多いため作業自体はかなり簡単に行うことができると思います。無料枠も良心的です。

ちなみに今回は使用していませんが公式が提供しているAIメッセージサービスも存在するようです。回数制限や細かい点が気にならないならこちらをまず試してみるのもよいかもしれません。

## Google App Scriptとの連携

応答を手軽に試すにはGoogle App Scriptが便利です。こちらの実装には以下の記事を参考にさせていただきました。関連記事も含め非常に丁寧な説明がある素晴らしい記事です。

https://qiita.com/WdknWdkn/items/ceb933c5499d15f985cd



Google App Scriptなら他の用途でも広く使われており、情報を得るのが比較的簡単なのもメリットの一つです。スプレッドシートなどを活用すれば運用状況の分析も可能です。

# LINE独自の面白さ

## グループLINEに参加できる

実は設定を変更することによって公式アカウントでもグループに招待してもらうことができます。会話AIを友達との会話に参加させることができるというわけです。これはSlackではよく見られる遊び方ですが、よりカジュアルな使い方が中心のLINEでも同じことができるのは魅力的です。


## 会話をスクリーンショットできる

AIとの会話で面白い場面が現れたとき、LINEなら本体の機能を使って特定の部分だけをスクリーンショットすることができます。さらにこれを同じLINE上で他の人に送ることもできるので拡散してもらえる確率も高くなります。ちなみに記事冒頭の画像もこの機能を使って製作したものです。


# まとめ

その手軽さゆえに離脱も簡単にできてしまうLINEの公式アカウントですが、会話AIを組み込むことで人を惹きつける機能を追加することができます。また会話するという性質自体が相性の良いものだとも言えます。

企業のサービスから個人開発の宣伝、仲間内の遊びまで色々な用途に活用できると思うのでぜひ一度試してみてください。
【DVA勉強】Step Functionsについて

## 概要
AWS認定DVA資格勉強時にまとめたものです。Step Functionsの概要について説明します。

## Step Functionsのタイプ

| key | value  | 
| ---------------- | ------ |
| Pass | Resultに指定した値をそのまま次のステートの入力に渡す |
| Task | アクティビティやLambda関数、その他AWSサービスとの統合を指定 |
| Wait | 指定した時間や日時まで処理を待つ |
| Choice | 分岐 |
| Fail | エラー名・理由を指定できる |
| Parallel |並列処理  |
| Map | 動的配列の並列処理 |



## Pass
Lambda関数などを実行せずに、ステートマシン内で次のステートに渡す入力を指定する場合などに使用する。

## Task
Taskタイプには、アクティビティ、他のAWSサービスが指定できる。

### 指定できるAWSサービス
* Lambda
* AWS Batch
* DynamoDB
* Amazon ECS/Fargate
* Amazon SNS
* Amazon SQS
* AWS Glue
* SageMaker
* Amazon EMR
* CodeBuild
* Athena
* Amazon EKS
* API Gateway
* AWS Glue DataBrew
* Amazon EventBridge
* AWS Step Functions

### Lambda関数を指定する例
- TaskでLambda関数を指定する
![](https://storage.googleapis.com/zenn-user-upload/abdaca393e2b-20230119.png)

## Choice, Fail
- Choice：変数fooの値が1の場合はFirstMatchState、2の場合はSecondMatchState、それ以外はDefaultStateへ分岐
- Fail：Errorでエラー名、Causeでエラー理由を指定
![](https://storage.googleapis.com/zenn-user-upload/8c5675069836-20230119.png)

## Parallel
- Branchesに複数のStatesを指定して並列化
- FinalStateは並列処理の全てが正常終了後に実行
![](https://storage.googleapis.com/zenn-user-upload/46681b62bc56-20230119.png)

## Map
- 動的配列の並列処理
- Iteratorの処理を配列の数だけ実行
![](https://storage.googleapis.com/zenn-user-upload/fa63a44ea4f9-20230119.png)

## InputとOutput
| フィールド | 内容  | 
| ---------------- | ------ |
| InputPath | ステートに渡す値 |
| ResultPath | ステートの実行結果を受け取るフィールド名 |
| OutputPath | 次のステートに渡す値 |

## 実行方法

### StartExecution APIを実行
- Lambda関数等から実行

### CloudWatch Eventsルールで実行
- 周期的に実行
- cron式で実行
- 特定のAPIイベントのタイミングで実行

### API Gatewayによる統合実行
- API GatewayからAWSサービス統合を使用しワークフローをAPI化

## 参考
* [ポケットスタディ AWS認定デベロッパーアソシエイト](https://www.amazon.co.jp/dp/4798063401/ref=cm_sw_em_r_mt_dp_BR0QGC4KJMKYFZ5YTYYC)
* [その他の AWS のサービスを呼び出す - AWS Step Functions](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-to-services.html)
PowerAutomateで組織のメンバーを一覧する

PowerAutomateでワークフローを構築・運用していると、時折、自組織のメンバーを一覧したいことがあります。
今回はそのようなシーンでのソリューションのご紹介です。

# Problem

ワークフローを構築・運用しているうち何かしらの目的で自組織のメンバーの一覧が必要になった。
あるメンバー（マネージャー等）を頂点に、その配下のメンバーを再帰的に探索して一覧したい。
「Office 365 Users」コネクターの「直属の部下の取得」アクションでは、文字通りあるメンバー（マネージャー等）の直属メンバーの一覧しかえられない：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/497f45bc-cd58-ef56-5d54-399f74e9506e.png)

# Solution

「直属の部下の取得」アクションと「Do Until」アクションを組合せて、再帰的なメンバー探索を行います。

## 成果物の容れ物を準備

まずは、下準備。
「直属の部下の取得」アクションの対象となるユーザーたちを一時的に格納するキュー（配列）を作成します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/65db594b-bd8d-0c17-800f-19e457a2d002.png)

再帰的探索の結果を格納するリスト（配列）も作成します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/a6c537ea-4b39-0b81-6078-ada5b5e702ef.png)

## 探索の起点を決める

「ユーザープロフィールの取得」アクションで、再帰的探索の起点となるユーザーのプロフィール情報を取得し、キューにプッシュ（配列に追加）します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/304f9ebb-c919-0074-29b2-7cdeeb1f4791.png)

## 再帰的な探索を開始する

いよいよ「Do Until」の登場です。終了条件は `length(variables('memberQueue'))` == `0` とします：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/6e7e202e-cd31-7dbd-d9de-a6fd6f0d499b.png)

必須の操作ではありませんが、このあとの作業（式の記述）を少しでも簡単にするため、「作成」アクションを使い、あらかじめキューの先頭の要素を取り出します。入力は `variables('memberQueue')[0]` です：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/1f09f914-65b7-71c7-bcbe-a8d9125c2d26.png)

今しがた取り出したユーザーのプロフィールを取得します。また今回は当該ユーザーの上司の情報もセットで管理したい（非正規化したい）ので、「上司の取得」アクションも実行します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/f7325a21-a4e6-5aa4-7b0f-f3e3b518c12d.png)

成果をリストに格納しましょう：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/deabc79b-8657-0f1f-f53e-4d0991bcffc9.png)

そして当該ユーザーの「直属の部下」を取得します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/c605670c-3d48-a49d-d75e-6164e1080a34.png)

取得したユーザー（0～N件）を次回以降の探索対象としてキュー（配列）に追加しましょう。
キューの先頭要素（先ほど処理済み）を除く要素からなる配列を作成し、それと「直属の部下の取得」で取得した配列とまとめます。「作成」アクションの入力はこんなかんじ：
`union(skip(variables('memberQueue'), 1), outputs('直属の部下の取得_(V2)')?['body/value'])`：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/17a62d6e-fc30-da68-5d8b-4dad253af8d7.png)

:::note info
ここでは「直属の部下の取得」で取得したユーザーをすべてキューに追加しています。
しかし、ユーザーの属性（例えば `jobTitle`）などで「当該ユーザーに部下はいない」あるいは「当該ユーザーの部下の探索は不要」と判断できる場合もあるでしょう。その場合は「直属の部下の取得」の出力に対して「アレイのフィルター処理」による選別を行なうことで、不要な探索処理をスキップできます。
実際、私が職場で運用しているワークフローでは `jobTitle` によりマネージャー（部下がいる）とそれ以外（部下がいない）を分け、マネージャーは先程示した通りキュー（`variables('memberQueue')`）に追加する一方、メンバーは即座に探索結果を保管するリスト（`variables('memberResult')`）に追加しています：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/09eafa56-fc7d-16f1-ae0d-6733ce02825d.png)
:::

## ワークフローを実行する

あとはフローを実行するだけです。
少々時間がかかってしまいますが、起点となるユーザーから順次組織構造の下方に向かって再帰的な探索が行われていき、結果が配列に格納されていきます。

もちろん、成果物をどうやって保管するのかは目的次第です。私の場合はSharePointサイト上のExcelファイルのテーブルと、同じくサイト上のJSONファイルとしてデータを書き出しておき、別のワークフローから利用しています。
neosでlogix その92

# 概要
neosでlogixやってみる。
logixを、俺コードで表現してみる。

# 参考にしたページ

https://qiita.com/FRICK/items/123e91f4078de3a9d2d2]

# 俺コード

```
String = Pulse
	|> BooleanLatch
	|> if ture do
		|> write "契約書だよそこに名前を書きな"
	else
		name = 荻野千尋
		|> StringLength
		|> RandomInt
		|> SubStrings 1
		"フン。{0}というのかい。贅沢な名だねぇ。今からお前の名前は{1}だ。いいかい、{1}だよ。分かったら返事をするんだ、{1}!!"
		|> Format name
		|> Write
	end


```


以上。
Swift key valueで配列要素の追加、変更をしたい

Swiftで辞書型で[String: [String,Int]]のようなとき後から要素追加、変更方法を書きました。
他言語の連想配列的な処理をしたい。
例文はChatGPTで生成しました。

# 対象読者
swift初学者

# Dictionaryで特定のキーに対応する値を追加したい場合
```swift:keyとvalueの新規追加
var dict: [String: [(String,Int)]] = [:]
// var dict = [String: [(String,Int)]]() これも同じ
dict["key"] = [("value1",1)]
```
この例では、新しい要素として、キー "key"、値 [("value1", 1)] が追加されています。

# すでに存在するキーに値を追加したい場合
```swift:value配列に値を追加
dict["key"]?.append(("value2",2))
// dict["key"]? += [("value2",2)] これでも同じ
```
値 ("value2",2)が追加される。

# 特定のインデックスの値を変更したい場合
```swift:value配列のindex値を変更
dict["key"]?[0] = ("newValue1",1)
// [0]でindexを指定
```
このように書けば、値 ("newValue1",1)が変更される。

上記の例では、dict["key"]がnilの場合にクラッシュしないように、Optional chainingを使用しています。

# 上記を出力すると
```swift
var dict: [String: [(String,Int)]] = [:]
dict["key"] = [("value1",1)]
dict["key"]?.append(("value2",2))
dict["key"]?[0] = ("newValue1",1)

print(dict) // ["key": [("newValue1", 1), ("value2", 2)]]
print(dict["key"]?[0]) // Optional(("newValue1", 1))
print(dict["key"]![0]) // ("newValue1", 1)

for value in dict["key"]!{
    print("\(value.0) \(value.1)") // newValue1 1
}                                  // value2 2

```

# おわりに
今回詰まったのはdict["key"]?の"?"をつける部分
> dict["key"]がnilの場合にクラッシュしないように、Optional chainingを使用しています

書き方がわからず苦戦しました。
今読み返すと公式ソースにも?付いてる部分ありました。


# 参考
公式[Apple/swift/dictionary](https://developer.apple.com/documentation/swift/dictionary)
[コード検証:paiza.io](https://paiza.io/ja/projects/new)