OmniAICreator/Qiita-1.07M huggingface dataset:
[Django REST framework] 複合ユニーク制約の実装

1. モデルにconstraintsを付与
   


    ```python:models.py
    from django.db import models
    
    class Book(models.Model):
    
        book_name = models.CharField()
        book_author = models.CharField()
    
        class Meta:
            constraints = [
                models.UniqueConstraint(
                    name='book_unique',
                    fields=[
                        'book_name',
                        'book_author',
                    ]
                )
            ]
    ```

    これで重複したデータをPOSTすると500エラーが帰ってくる。

    ```
    curl -w'%{http_code}\n' -so /dev/null -X 'POST' \
      'http://127.0.0.1:8001/book/' \
      -H 'Content-Type: application/json' \
      -d '{
      "book_name": "TEST",
      "book_author": "TEST",
    }'
   
    # ステータスコードが500で帰ってくる
    500
    ```

    単一フィールドがユニーク制約の場合だと400が帰ってくるので統一したい場合は下記設定をさらに投入する

2. シリアライザにUniqueTogetherValidatorを付与


    ```python:serializers.py
    from rest_framework import serializers
    from rest_framework.validators import UniqueTogetherValidator
    
    class BookSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = Book
            fields = '__all__'
            validators = [
                UniqueTogetherValidator(
                    queryset=Book.objects.all(),
                    fields=[
                        'book_name',
                        'book_author',
                    ]
                )
            ]
    ```
    
    ```python:views.py
    from rest_framework import viewsets
    
    class BookViewSet(viewsets.ModelViewSet):
    
        queryset = Book.objects.all()
        serializer_class = serializers.BookSerializer
        filterset_fields = '__all__'
    ```

    この状態でPOSTするとバリテーションエラー扱いで400を返してくれる。

    ```
    curl -w'%{http_code}\n' -so /dev/null -X 'POST' \
      'http://127.0.0.1:8001/book/' \
      -H 'Content-Type: application/json' \
      -d '{
      "book_name": "TEST",
      "book_author": "TEST",
    }'

    # ステータスコードが400で帰ってくる
    400
    ```
mask

「instantNeRFで遊ぶ Advent Calendar 2022」の21日目です。

今日は背景の影響を減らすmaskについて調べてテストデータを作り試しました。

:::note
業務外の個人的な検討活動です。
:::

#### mask
instantNeRFには背景マスク処理する仕組みが準備されています。

https://github.com/NVlabs/instant-ngp#frequently-asked-questions-faq

![8-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/b7aaa100-bd65-c69f-207b-9cde58ae8f31.png)
> 学習データにおける透明は、学習済みモデルにおける透明への欲求を示す。無地の背景色を用いると、モデルは透明度（ゼロ濃度）ではなく、単純にその背景色を予測することで損失を最小にすることができます。背景色をランダムにすることで、モデルはランダムな色を「透かす」ためにゼロ密度を学習することを余儀なくされます。 
https://www.deepl.com/translator

つまり計算機にズルさせないということかもしれないです。

#### テストデータ
sketchfabのNefertiti statueを使用させていただきました。ありがとうございます。

https://sketchfab.com/3d-models/nefertiti-statue-d148f771c3f44225b56cb7ce8d3c5ce6

#### nerf_loader.cu
見つけられた範囲で5種類の仕組みがありました。
- alpha
- dynamic mask
- depth
![8-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/cbc69098-7a13-43df-710e-68def0bfd5d6.png)

- white transpararent
- black transparent
![8-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/e2bde9c6-95e9-70fe-2e20-890d68a7f218.png)

#### white transparent
試しに背景を白にしてBlenderで作成した画像を入力しました。
white transparentをfalseにすると背景の白色がそのまま残っていますが、trueにすると背景の白は除去されました。

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


:::note
プログラムを修正しなければ背景の白は255になっている必要があります。
:::

プログラムを改造したらクロマキー合成の撮影技術を応用できそうです。
Lambda Node.js 18 でaws-sdkを使おうとして詰まった

:::note info
この記事は[miriwoお一人様 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/miriwo)の17日目の記事です
:::

## 〜宣伝〜

:::note info
下記、個人開発でエンジニア専門マッチングサービスを開発しましたので、是非未経験からエンジニア目指している人！現役エンジニアで教えたい人！使ってみてください！
:::
https://dokupro.dev/

## 概要

- LambdaのNode.js18にてaws-sdkを使おうとしてかなり詰まったのでまとめておく。

## 謝辞

- 本問題の解決は同プロジェクトの先輩エンジニアさんにご協力いただきました。改めてお礼申し上げます。

## 情報

| 内容 | 情報 |
| --- | --- |
| ランタイム | Node.js 18.x |
| ハンドラ | index.handler |
| アーキテクチャ | x86_64 |
| 関数の作成 | 一から作成 |

## 問題発生までの経緯

- Lambda関数にブラウザから下記の様にindex.mjsに記載をした。

    ```index.mjs
    import { AWS }  from 'aws-sdk';
    
    exports.handler = async (event) => {
        return AWS.VERSION;
    };
    ```

- コードを保存してデプロイしてhello-worldテストを実行した。

## 問題

- 下記のエラーが出る。

    ```
    "errorType": "Error",
    "errorMessage": "Cannot find package 'aws-sdk' imported from /var/task/index.mjs",
    ```

## 問題解決までの経緯

- ランタイムをNode.js 12.x、 Node.js 14.x、 Node.js 16.xに変更しながら実行したところ、エラーが出ず実行する事ができた。でも自分はNode.js 18.xで実行したい。
- どうやら16まではAWS SDK for JavaScript v2だったが18からはAWS SDK for JavaScript v3になる模様
- v3の場合はサービスのクライアントを指定してsdkをインポートするようだ。

    ```js
    import {S3Client, コマンドを実行する場合はコマンドを指定} from "@aws-sdk/client-s3";
    ```

- 下記の様に記載し、テストを実行したところエラーが出なかったため問題は解決した模様

    ```index.mjs
    import { S3Client } from "@aws-sdk/client-s3";
    
    console.log(S3Client);
    
    export const handler = async(event) => {
        
        const response = {
            statusCode: 200,
            body: JSON.stringify(S3Client),
        };
        return response;
    };
    ```


## 参考文献

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/index.html

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/classes/listbucketscommand.html

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/index.html

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/index.html#import
grub2-mkconfigの使い方

## 1. 概要

CentOS7で`/etc/default/grub`を変更したときの、カーネルへの反映方法を解説します。

## 2. 解決したい課題

`/etc/default/grub`を変更したとき、BIOSブートとUEFIブートで、カーネルへの反映方法が異なります。


## 3. 解決方法

まず、BIOS、UEFIどちらでブートしたのかを確認し、対応する反映方法を実施します。

### 3.1 BIOS、UEFIどちらでブートしたのかを確認

BIOSブートしたマシンでの実行結果

```
# [ -d /sys/firmware/efi ] && echo UEFI Booted || echo BIOS Booted
BIOS Booted
#
```

UEFIブートしたマシンでの実行結果

```
# [ -d /sys/firmware/efi ] && echo UEFI Booted || echo BIOS Booted
UEFI Booted
#
```

### 3.2 BIOSブートされたマシンへのカーネルへの反映方法

```
# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.71.1.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-1160.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-74d201337f7d4c1884bd9f5a09840ab9
Found initrd image: /boot/initramfs-0-rescue-74d201337f7d4c1884bd9f5a09840ab9.img
done
#
```


### 3.3 UEFIブートされたマシンへのカーネルへの反映方法

```
# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.71.1.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-1160.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-74d201337f7d4c1884bd9f5a09840ab9
Found initrd image: /boot/initramfs-0-rescue-74d201337f7d4c1884bd9f5a09840ab9.img
done
#
```

## 4. 類似の解決方法

## 5. 現在と今後

## 6. 関連記事

## 7.リファレンス

## 8. 付録

`/etc/default/grub`の記述例です。そのまま使用しないでください。マシンが起動しなくなる可能性があります。

### I350のSRIOVの有効化例

```
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet hugepagesz=2M hugepages=8192 iommu=pt intel_iommu=on pci=assign-busses pci=realloc=on"
GRUB_DISABLE_RECOVERY="true"
```

### X550のSRIOVの有効化例

```
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet hugepagesz=2M hugepages=8192 intel_iommu=on intel_iommu=on pci=assign-busses pci=realloc=on"
GRUB_DISABLE_RECOVERY="true"
```

### 1G HugePageを作る

```
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto spectre_v2=retpoline rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet default_hugepagesz=1G hugepagesz=1G hugepages=4 hugepagesz=2M hugepages=1024"
GRUB_DISABLE_RECOVERY="true"
```
基本情報の擬似言語とクイックソートでk番目に小さい値を探してみた！

基本情報技術者の擬似言語の学習のため実際にプログラム化してみました。
仕様はそのままに一部アルゴリズム強化のため自分で自分で条件式等を考えているため実際の擬似言語プログラムとは差異があります。

```java:qiita.java
import java.util.*;

public class SelectArrayElement {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    System.out.println("配列の要素数を入力してください");
    int elements = Integer.parseInt(sc.next());
    int[] data_array = new int[elements];

    /*
     * テストデータ
     * 入力値 = 3 2回目 7
     * [3,5,6,4,7,2,1] 1回目 => 3 ok 2回目: => 7 ok
     * [1,3,2,4,2,2,2] 1回目 => 2 ok 2回目: => 4 ok
     * [7,6,5,4,3,2,1] 1回目 => 3 ok 2回目: => 7 ok
     * [1,2,3,4,5,6,7] 1回目 => 3 ok 2回目: => 7 ok
     * [7,7,7,7,7,7,7] 1回目 => 7 ok 2回目: => 7 ok
     * [1,2,5,10,5,6,7] 1回目 => 5 ok 2回目: => 10 ok
     * [8,2,5,10,11,6,7] 1回目 => 6 ok 2回目: => 11 ok
     * [1,2,5,10,11,6,7] 1回目 => 5 ok 2回目: => 11 ok
     * [12,13,15,5,1,9,20] 1回目 => 9 ok 2回目: => 20 ok
     * [9,9,9,9,1,6,8] 1回目 => 8 ok 2回目: => 9 ok
     */

    System.out.println("配列の各要素を" + elements + "回入力してください");
    for (int i = 0; i < elements; i++) {
      data_array[i] = Integer.parseInt(sc.next());
    }

    System.out.println("何番目に小さい要素を取得しますか？(1~" + elements + "までの範囲)");
    int k = Integer.parseInt(sc.next()) - 1; // 何番目の要素を取得するか

    int return_value = selectElement(k, data_array);

    // 出力
    System.out.println("結果表示");
    System.out.println((k + 1) + "番目に小さい要素は" + return_value + "です。");
    System.out.println(Arrays.toString(data_array));

  }

  // クイックソートを応用し配列の要素を昇順に並べる。
  public static int selectElement(int k, int[] data_array) {
    int top = 0;
    int last = data_array.length - 1;

    /*
     * k番目に小さい要素を取得する。
     */
    while (top < last) {
      // 変数
      int i = top;
      int j = last;
      int pivot = data_array[k];

      while (true) {

        // 基準値よりも大きい値を左側へ振り分ける
        while (data_array[i] < pivot) {
          i++;
        }
        // 基準値よりも大きい値を左側へ振り分ける
        while (data_array[j] > pivot) {
          j--;
        }

        // ループ条件trueのループを抜ける
        if (i >= j) {
          break;
        }

        // 並び替え
        swap(i, j, data_array);
        i++;
        j--;
      }

      /*
       * topとlastを書き換えて再探索
       * k = i, k = j になったら探索終了
       */

      // kが基準以上以下より小さい場合 last更新
      if (i > k) {
        last = i - 1;
      }

      // kが基準以上以下より大きい場合 top更新
      if (j < k) {
        top = j + 1;
      }

      // 終了
      if (i == k && j == k) {

        top = k;
        last = k;

      }

    }

    return data_array[k];

  }

  public static void swap(int i, int j, int[] data_array) {
    int tmp = 0;

    tmp = data_array[i];
    data_array[i] = data_array[j];
    data_array[j] = tmp;
  }

}
【Laravel】ヒアドキュメントを使ったSQLの実行

Laravelで複雑なSQLを実行する際は、ヒアドキュメントを使用した方がわかりやすい場合があります。
以下は全く複雑なSQLではありませんが、基本となる記述方法になります。

```php
use DB;

public function findUser($userId)
{
    $key = config('app.key');

    $sql = <<<SQL
SELECT
  user_id,
  CONVERT(AES_DECRYPT(UNHEX(first_name), ?)USING utf8) first_name,
  CONVERT(AES_DECRYPT(UNHEX(last_name), ?)USING utf8) last_name,
FROM
  users
WHERE
  user_id = ?
SQL;

    $userModel = DB::select($sql, [$key, $key, $userId]);
}
```

第二引数に配列で値を渡すことで、バインドパラメータを使用できる。
SQLの疑問符プレースホルダー(?)の数だけ用意してあげます。
```php
DB::select($sql, [$key, $key, $userId])
```
[NewRelic] カスタム属性の値でダッシボュボードを絞り込む

この記事は [New Relic Advent Calendar 2022](https://qiita.com/advent-calendar/2022/newrelic) 17日目のエントリーです。

## 概要
NewRelicのTransactionでアプリケーションのパフォーマンスを確認したい時に、
全体でなくある属性ごと（例えばテナント）ごとに確認したいという状況がありました。
そのために「カスタム属性」とダッシュボードの「Facet Linking」を使ってみたので紹介させていただきます。

## 手順
### 1. 任意のグループを指定するためのパラメータをアプリケーション側から送信

https://docs.newrelic.com/jp/docs/data-apis/custom-data/custom-events/collect-custom-attributes/

例) アプリケーション側（Ruby）で`subdomain`というカスタム属性をから送信する
```ruby
 ::NewRelic::Agent.add_custom_attributes(subdomain: subdomain)
```

### 2. カスタム属性で「絞り込む」ためのダッシュボードの作成
「Dashboards」 からwidgetを作成し、Save時に「Facet Linking」を有効にします。
「current dashboard」もしくは「related dashboard」は絞り込みたいダッシュボードの範囲に合わせ設定します。

https://docs.newrelic.com/jp/docs/query-your-data/explore-query-data/dashboards/filter-new-relic-one-dashboards-facets/

例). 以下はNRQLで`SELECT sum(databaseDuration) from Transaction  FACET subbomain`と、データベース処理の合計時間が長い`subdomain`を降順(デフォルト）に表示するWidgetです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19638/834589aa-aed1-5d4a-7f7f-b485db7bf064.png)

### 3. カスタム属性で「絞り込まれる」ダッシュボードを作成
「Dashboards」 から任意のwidgetを作成します。このWidgetは「Facet Linking」の設定は不要です。

例). 以下はNRQLで`SELECT max(duration) from Transaction  FACET name`と、最大実行時間が長い処理を降順(デフォルト）に表示するWidgetです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19638/5f161511-3c0a-e957-a2d2-436c02ce3df4.png)

これでカスタム属性で「絞り込む」ためのダッシュボードと、「絞り込まれる」ダッシュボードが作成されました。

### ダッシュボードから絞り込みを行う
「Facet Linking」を有効にしたWidgetで`subdomain`の値にフォーカスすると「Filter this dashboard」が表示されるのでクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19638/72fae142-dab8-d451-c8eb-1cc07d7140bd.png)

すると、3で作成したカスタム属性で「絞り込まれる」ダッシュボードが`subdomain`で絞り込みをされた結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19638/da61ad77-8a18-8b0a-fc1d-50787fe3f612.png)

### 纏め
任意のカスタム属性の値でダッシボュボードを絞り込む方法を紹介しました。
他にも、カスタム属性に「アカウント」を指定したり用途は色々とありそうで便利ですね。

また、最近リリースされたこの方法の他にも「テンプレート変数」を使って「ダッシュボードを動的にフィルタリングする」という方法も絞り込みが便利になりそうですね。
https://newrelic.com/jp/blog/nerdlog/new-relic-update-202211
https://docs.newrelic.com/jp/docs/query-your-data/explore-query-data/dashboards/dashboard-template-variables/
【Laravel】Model内で変数をグローバル宣言したい

Model内にクエリビルダを使ってSQLを記述しています。
クロージャ（functionの中のfunction）でグローバル変数を使用したいのですが、`null` が返ってきてしまい、数時間ハマったため備忘録として残します。
## 目次
- 結論
- useとは
## 結論
下記の通り実装することで動作確認できました。
```php
public function check_notify_user($auth_user_id) {
  $query = DB::table('notifications as n')
      ->leftJoin('notification_user as nu', function ($join) use($auth_user_id){
          $join->on('n.id', "=", 'nu.notification_id')
          ->where('nu.user_id', "=", $auth_user_id);
      })
      ->where('nu.user_id', null)
      ->get();

  return $query;
}
```
重要箇所は`leftJoin`の中にある`use($auth_user_id)` です。
`check_notify_user`の引数に`Controller`で定義した`$auth_user_id`を使っています。`use($auth_user_id)` を使用することで、クロージャの外で定義した変数を使用できるようにしています。
## useとは
今回のエラーは全てドキュメントに答えが書いてありました。
`function() use(変数名)`は、PHPで定められた記法。
> クロージャは、変数を親のスコープから引き継ぐことができます。 引き継ぐ変数は、`use` で渡さなければなりません。 PHP 7.1 以降は、引き継ぐ値に [スーパーグローバル](https://www.php.net/manual/ja/language.variables.predefined.php)や $this、およびパラメータと同じ名前の変数を含めてはいけません。 戻り値の型は、`use`の*後*に置かなければいけません。
> 
参考：[無名関数](https://www.php.net/manual/ja/functions.anonymous.php)
クロージャーは親のスコープを引き継ぐことが可能ですが、親スコープの関数を使用する際には必ず`use` で変数を継承しなければなりません。
PHPの知識が不足していると、LaravelとPHPのどちらが原因なのか判断できないので基礎固めは重要、ということを改めて実感した今日この頃です。

参考：[【Laravel】function () use ($変数名)とは何か？意味や使い方を実例で解説｜無名関数の外の変数を使う方法とエラーの対処法：ErrorException (E_NOTICE) Undefined variable](https://prograshi.com/framework/laravel/what-is-use-in-function/)
参考：[変数のスコープ](https://www.php.net/manual/ja/language.variables.scope.php)
emacs で spellcheck (hunspell)

emacs で spellcheck といえば ispell ですが、今は hunspell というのがいいらしい。

```sh
$brew install hunspell
```

```elisp
(use-package ispell
  :custom
  (ispell-program-name "hunspell")
  (ispell-really-hunspell t)
```

ispell, flyspell で error になる。

```elisp
Error enabling Flyspell mode:
(Can't find Hunspell dictionary with a .aff affix file)
```

commandline でも error になる。
```sh
$hunspell -d en_US hoge.txt
Can't open affix or dictionary files for dictionary named "en_US".
```

辞書を　dl して mv する
```sh
$wget -O en_US.aff https://cgit.freedesktop.org/libreoffice/dictionaries/plain/en/en_US.aff?id=a4473e06b56bfe35187e302754f6baaa8d75e54f
$wget -O en_US.dic https://cgit.freedesktop.org/libreoffice/dictionaries/plain/en/en_US.dic?id=a4473e06b56bfe35187e302754f6baaa8d75e54f
$mv en_US.* Library/Spelling/
```

環境変数 DICTIONARY に en_US
```elisp
(use-package ispell
  :custom
  (ispell-program-name "hunspell")
  (ispell-really-hunspell t)
  :config
  (setenv "DICTIONARY" "en_US")
```

ok.
Laravelの外部キー制約についてまとめた

「外部キー制約したい」と思った時に、毎度ネットサーフィンするのが面倒なので、参照用として記録しておきます。

Version → `8.83.26`
PHP → `8.1.12`
## 外部キー制約の追加
### 手順

①親テーブル(`parents`)のマイグレーションファイル作成→`migrate`実行（特別な作業がないので省略）
②子テーブル(`childs`)のマイグレーションファイル作成

```bash
$ php artisan make:migration create_childs_table
```

③外部キー制約の追加（ここが肝）

```php
Schema::create('childs', function (Blueprint $table) {
    $table->id();
// ↓ ここに追記
    $table->foreignId('parent_id')->constrained('parents')->cascadeOnUpdate()->cascadeOnDelete();
});
```
### ポイント

`foreignId()→constrained()`で外部キー制約に関する記述をしています。
なおかつ`cascadeOnUpdate()…`で親テーブルが削除されると子テーブルも同時に削除されるように設定しています。

> CASCADE: 親テーブルの行を削除または更新し、子テーブル内の一致する行を自動的に削除または更新します。ON DELETE CASCADE と ON UPDATE CASCADE の両方がサポートされています。2 つのテーブル間で、親テーブルまたは子テーブル内の同じカラムに対して機能する複数の ON UPDATE CASCADE 句を定義しないでください。
> 

参考：[MySQL公式](https://dev.mysql.com/doc/refman/5.6/ja/create-table-foreign-keys.html)

※別の記述方法

書き方としてはもう一つあって、外部キー制約の部分を以下にしても成功します。

```php
$table->unsignedBigInteger('parent_id');
$table->foreign('parent_id')->references('id')->on('parents');
```

この方法でも制約を追加できますが、二行になるので最初の記述がおすすめです。

### 補足（中間テーブルの場合）

これも難しくなくて、親テーブルが複数なので、もう一行追加すればOK。

```php
Schema::create('childs', function (Blueprint $table) {
    $table->id();
// ↓ ここに追記
    $table->foreignId('parent1_id')->constrained('parents1')->cascadeOnUpdate()->cascadeOnDelete();
		$table->foreignId('parent2_id')->constrained('parents2')->cascadeOnUpdate()->cascadeOnDelete();
});
```
④`migrate`実行

```bash
$ php artisan migrate;
```

これで完了です。

今後はこの流れでリレーションについてもまとめていきたいと思います。
暗記しちゃって、バチバチ開発スピードを上げていきたいです😌
Rustでgraphqlサーバーを作る！

# はじめに
この記事は[C3 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/c3) 17日目の記事です

今回の記事では，RustでBearer認証が行える程度の簡単なGraphQLサーバーを作成していきたいと思います。

# 使用技術

使用した主要な技術は以下の通りになっています。
- [actix-web](https://actix.rs/) (rustのwebフレームワーク)
- [juniper](https://docs.rs/juniper/latest/juniper/) (rustのgraphqlライブラリ)
- [diesel](https://diesel.rs/) (rustのorm)
- postgresql
- docker

# 動かしてみる
ソースコードは以下のリポジトリにあります。
[https://github.com/yamato0211/rust-graphql-tutorial](https://github.com/yamato0211/rust-graphql-tutorial)

参考にさせていただいた記事です。
[【Rust】GraphQL API Serverを作ってみる話。(1/?) ～導入編～](https://qiita.com/dino3616/items/a99f33488ac6a306cdb4)

※README.mdに環境構築の設定などがまだ記述できていません。申し訳ない。なるはやで書きます。

APIサーバーやDBサーバーを起動して、[http://localhost:8000/playground](http://localhost:8000/playground)にアクセスすると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/1870f775-1071-fa08-85c0-1d859cf2eda0.png)
こんな感じの画面が表示されます。ここでクエリを実行できます。

新規登録とログインの機能を実装しているので実際に行ってみます。

まずは新規登録から以下のようなMutationを投げてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/29190866-8d6f-4954-1f3d-71c9637f9663.png)
真ん中の三角ボタンを押すと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/e3902dad-4f43-94e6-ad96-380bc7fd3b02.png)
登録が完了します。次にログインを行ってみます。

以下のqueryを実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/c9b71e21-8cc7-b5ad-8513-e9e5fb9c9522.png)

実行すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/27be1b44-25f6-9e00-cd10-a66545ad19ed.png)
うまくログインが行われてjwtトークンが返ってきます。

他のqueryやmutationを実行するときにはAuthorizationヘッダーにこのトークン情報を入れて実行します。
試しに、すべてのユーザー情報を取得するqueryを投げてみたいと思ます。


以下のようにヘッダーも記述して以下のようなqueryを実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/0d901a85-46f4-510e-d499-777438c46432.png)

登録されたユーザーがすべてかえってきています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086809/81bdca92-b6b1-3317-cccc-955f683a8c0c.png)
idを指定してユーザー情報をとってくることもできます。

# 最後に
今回はrustのactix-webとjuniperを使用して認証サーバーを作成してみました。
実行結果のみでコードについて詳しく説明ができなかったので、その他もろもろの説明も近日中に書き上げます。

明日の[C3 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/c3)はシモ先輩の「SPA・SSGにおける動的OGP生成」です．お楽しみに！
Google UXデザイン：モックアップ（階層）

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<details><summary>これまでの振り返り</summary>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/27bbe002-b03c-b9ae-4ec1-77472a96a14f.jpeg" width="700">

</details>

# 階層の定義

階層とは、ページ上の要素に順番をつけ、その重要度によって強調するビジュアルデザインの原則のことです。階層化の目的は、ユーザーを誘導することです。

UXデザインにおける階層は、異なる要素間の相対的な重要性をユーザーに理解させることができます。

[前回紹介した強調][emp]と階層がどう違うのか不思議に思うかもしれません。

[emp]: https://qiita.com/mapami/items/2f7e850a13bc604143fe

- ***階層*** ：重要性の順に整理された要素群を参照する
- ***強調***：ある要素をそれを取り囲む他の要素から際立たせる

例えば、あるメディアのニュースを見るときを考えてみてください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/3984ee19-acfc-5aa4-f86b-b4d02d130731.png" width="300">

- 通常、まず見出しをチェックしますよね。多くの人は、それぞれの記事の内容をざっと把握するためにそうします。見出しは、最も重要であるため、ページ上で目立つ要素です。
- 見出しの下にはストーリーの要約があり、通常、フォントは小さく、太さも抑えてあります。この場合、タイポグラフィによってトップページに階層が生まれました。

# 階層の重要性

UXデザインでは、ユーザーが最初にどこに注目し、どのような行動をとればよいかを常に明確にしたいと考えます。***<font color="MediumVioletRed">階層は、ユーザーがユーザー・ジャーニーで取るべき最初のステップを指し示す</font>*** のに役立ちます。

私たちは、モックアップを作成する際に、ユーザーがアプリを簡単にナビゲートできるように階層構造を適用しています。階層化することで、ユーザーは最も関連性の高い情報やメインアクションボタンを最初に見つけることができます。また、階層は、ユーザーをページ上の最も重要な場所に導きます。

# 階層化を実装してみる

デザインは、ユーザーにとって　***<font color="MediumVioletRed">最も重要な情報を優先的に表示する</font>***　ことが大切です。重要度の高い順に並べることで、ユーザーが必要な情報を的確に得ることができ、製品に不満を抱くこともなくなります。

階層構造をデザインに取り入れるには、***<font color="MediumVioletRed">ユーザーが製品に触れたときに達成したい主な目標に焦点を当てます</font>***。たとえば、ユーザーがサイトにログインして操作することが第一の目標であれば、ログインページやサインアップページへの明確なリンクから階層を始める必要があります。

メインゴールとサブゴールが分かれば、デザインの階層を整理することができます。次のGoogleリワードのアプリのデザインをご覧ください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/5138eda7-ed2d-708a-eb9d-da617d23a435.png" width="４00">

- ***左:***　階層を追加することで、アプリのデザインに強調性を持たせています。大きく太い文字と色を使うことで、ユーザーが獲得した報酬に注目させ、ユーザーがこのアプリを終了する際に知っておくべき情報を明確にしているのです。
- ***右:***　ユーザーにとって重要な情報領域が強調されていないものです。ユーザーはこの画面のどこに最初に焦点を合わせればいいのか、どんな行動をとればいいのかがわからず、ユーザーエクスペリエンスに欠けるものになっています。

# サンプル：犬の散歩のアプリ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/9a14b350-b79e-7866-db2d-758e4013065d.png" width="300">

- ***"Select the dog walker"*** テキストをページの一番上に配置することで、その下にあるコンテンツのほとんどがこのプロセスに関する情報を含んでいることを示します。テキストを大きくすることで、そのことがより明確になります。
- ***"Availability based on your date and time***"テキストは、"Select the dog walker"よりも小さく、各ドッグウォーカーの詳細よりも大きくなっています。リストアップされたドッグウォーカーのすべてが、選択した日時に利用可能であることをユーザーが認識することが重要なのです。
- ***"各ドッグウォーカーの名前***"テキストは、そのドッグウォーカーに関連する他のテキストよりも濃いグレーで表示されていることに注目してください。

# 参考

- [Golden Tips and Examples to Create Visual Hierarchy in Website Design](https://www.mockplus.com/blog/post/ui-visual-hierarchy) で、効果的な視覚的階層を作るための旅を始めてください。
- インクルーシブなデザインについてもっと知りたい方は、UX Collectiveの記事をご覧ください：[A is for Accessibility - 12 top tips for designing an inclusive user experience](https://uxdesign.cc/the-a-to-z-of-ux-a-is-for-accessibility-12-top-tips-for-designing-an-inclusive-user-experience-667eedaf5bca)。
Javaのアノテーション

## アノテーションとは
プログラムの構成要素に付与するメタ情報。
アノテーションとは日本語で「注釈」という意味です。Javaではコンピューターに対してソースコードだけでは命令しきれない情報を伝えるために使用します。

標準ライブラリに含まれる主なアノテーション
|アノテーション名|意味|
|:--|:--:|
|Override|オーバーライドしたメソッド|
|Deprecated|非推奨であることを明示|
|SuppressWarnings|コンパイルの警告メッセージを抑制|
|SafeVarags|ジェネリック型の可変長引数の警告メッセージの抑制|
|FunctionalInterface|関数型インターフェイスを表示|
|Native|フィールドがネイティブコード由来であることを明示|

## 使い方

### @Override
overrideをつけると、「このメソッドはオーバーライドしているメソッドです」という注釈になります。
基となるメソッドが無く、オーバーライドしていると言えない場合はエラーが発生するようになります。

```java

class AnimalOverride {
    public void eat() {
        System.out.println("むしゃむしゃ");
    }
}

class Animal extends AnimalOverride {
    @Override //アノテーション
    public void eat() { //メソッド名がeat以外だとオーバーライドしたことにならないのでエラー
        System.out.println("ぱくぱく");
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Animal animal = new Animal();
        animal.eat(); //ぱくぱくと出力される
    }
}
```
Animalクラスのメソッドがeat以外だと、オーバーライドしたことにならないので「オーバーライドしていませんよ」とエラーで教えてくれる。

### @Deprecated 
Deprecatedは推奨しない対象要素を明示します。「このメソッドやクラスは非推奨です」というエラーを出すために使います。開発者に新しい機能への移行をうながします。

```java

class Animal {
    @Deprecated //アノテーション
    public void eat() {
        System.out.println("むしゃむしゃ");
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Animal animal = new Animal();
        animal.eat();
    }
}

//実行結果
Documents $ 1java animal.java
注意 :animal.javaは推奨されないAPIを使用またはオーバーライドしています。
注意 :詳細は、-Xlint:deprecationオプションを指定して再コンパイルしてください。
```

### @SuppressWarnings
SuppressWarningsは警告を抑制する指示です。何か間違ったコードを書くとコンパイルエラーが発生しますが、このアノテーションを使うと警告を抑制して強制的に実行することができます。
()の中でどの警告を抑制するか指定します。
```java
@SuppressWarnings("divzero") //ゼロに対して除算している
@SuppressWarnings(“unused”) //使っていない変数がある
```
@SuppressWarningsに指定できる文字列はjavaコンパイラに依存します。下のコマンドで指定可能な文字列を調べることができます。
```java
//JDK8の場合
$ javac -X
```
サーバーのホスト名を変更する方法

# サーバーのホスト名変更
set-hostnameで変更ができる。
```console
# hostnamectl set-hostname {ホスト名}
```
コマンド打っただけだと、ターミナルの表示は変わらず。
変更した状態で再ログインすると、ターミナルの表示が変わる。

# ホスト名確認
unameコマンドやhostnameコマンドで変わっていることを確認できる。
現場では、ログインしてる装置があっているかどうか確認のために使う場合もある。
```console
# uname -n
{ホスト名}

# hostname
{ホスト名}
```

ちなみに、ホスト名は`/etc/hostname`に格納されている。
```console
# cat /etc/hostname 
{ホスト名}
```

# 一時的に変更する
hostnameコマンドで一時的な変更は可能。恒久的な変更はhostnamectlで変更する。
```console
# hostname {ホスト名}
```
zabbixでrubyのsnapshot tarballの更新監視

2022年現在、[Rubyのsnapshot tarball](https://cache.ruby-lang.org/pub/ruby/snapshot/)は[GitHub Actions](https://github.com/ruby/actions)で更新しています。
これは何らかの原因で更新が失敗して止まってしまうことがあるので、少しでも気がつきやすくするために、Zabbixで更新状況を監視しています。

## 動作確認バージョン

- Zabbix 5.0 と 6.0 (5.0 から 6.0 への移行中のため)

## アイテム設定

アイテムはHTTPエージェントでJSONを取得して、依存アイテムで個別の情報を取り出して、そこにトリガーを設定するようにしています。

### HTTPエージェント

名前やキーは適当にわかりやすいものにしています。
汎用的なものではないですが、とりあえずテンプレートとして作成して `cache.ruby-lang.org` というホストに設定しているので、URLの一部は `{HOST.DNS}` を使っています。

- 名前: `snapshot-master.json`
- タイプ: HTTPエージェント
- キー: `pub.ruby.snapshot.master.json`
- データ型: テキスト
- URL: `https://{HOST.DNS}/pub/ruby/snapshot/snapshot-master.json`
- 取得モード: ボディとヘッダー
- JSONへの変換: チェック
- 監視間隔: 1h

他はほぼデフォルトです。

### 更新日時

依存アイテムで HTTP応答ヘッダーの `last-modified` を取り出しています。サーバーによって `Last-Modified` だったり、いつの間にか全部小文字に変わったりすることがあるようです。
ZabbixのJavaScriptエンジンはDuktapeというものを使っているらしく、HTTPの日付のパースは用意されていなかったので、`Date.parse`でうまくいかなかったときは自前でパースしています。

- 名前: `snapshot-master last-modified`
- タイプ: 依存アイテム
- キー: `pub.ruby.snapshot.master.last-modified`
- データ型: 数値(整数)
- マスターアイテム: HTTPエージェントで作成したアイテム
- 単位: `unixtime`

保存前処理:

```javascript
var lastmod = JSON.parse(value).header['last-modified'];
var date = Date.parse(lastmod);
if (date) return date/1000;
// Sat, 03 Aug 2019 12:35:34 GMT
var a = /^\w+, (\d\d) (\w+) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$/.exec(lastmod);
var months = {"Jan":0, "Feb":1, "Mar":2, "Apr":3, "May":4, "Jun":5, "Jul":6, "Aug":7, "Sep":8, "Oct":9, "Nov":10, "Dec":11};
date = Date.UTC(a[3], months[a[2]], a[1], a[4], a[5], a[6]);
return date/1000;
```

### ファイルサイズ

ファイルサイズが急に変わると何か問題が起きている可能性があるので、それも監視するようにしています。
閾値の設定が難しいのと、意図的な変化の場合もあるので、今のところトリガーは設定していません。

ファイルサイズは `gz`, `xz`, `zip` をそれぞれ作成しています。
保存前処理はボディで返ってくるJSONから取り出すだけで、中身の形式は自分たちで決めた独自のものなので、良い感じにキーなどを指定するだけです。

- 名前: `snapshot-master size gz`
- タイプ: 依存アイテム
- キー: `pub.ruby.snapshot.master.size.gz`
- データ型: 数値(整数)
- マスターアイテム: HTTPエージェントで作成したアイテム
- 単位: `B`

保存前処理:

```javascript
return JSON.parse(value).body[0]['size']['gz'];
```

## トリガー設定

条件式では条件式ビルダーの説明で以下のような説明の関数を使いました。
1日だけなら生成や取得タイミングの誤差の可能性もあるので2日間更新がなさそう、というのをトリガーにしています。

- 名前： `snapshot-master stopped`
- 深刻度: 軽度の障害
- 条件式: `or`
    - `max(last-modified,2d)-min(last-modified,2d)=0`
        - アイテム: last-modified
        - 関数: max() - 期間Tでの最大値
        - 関数: min() - 期間Tでの最小値
        - 最新の (T): 2d 時間
    - nodata(last-modified,2d)=1
        - アイテム: last-modified
        - 関数: nodata() - 期間Tの間取得データなし (1 - 取得データなし、 0 - それ以外)
        - 最新の (T): 2d 時間

## 他のsnapshot

master と同様に現在メンテナンス中の ruby_2_7, ruby_3_0, ruby_3_1 の snapshot も監視しています。
ruby_2_7 までは bz2 もあるので、それも監視しています。

## まとめ

今までは個人的なサーバーの中でこのような監視をしていて、たまに役に立つということがわかっています。

今は他の個人的な監視も混ざっていて自分しか見えない場所にあるのですが、Zabbix 6.0 への移行をきっかけに外部から見えるような場所に移動して、Rubyコミッターの他の関係者にも見えるようにしたいと思っています。
NLP-APIの設計

昨年から計画していた下記の検討をさらに進めている。

https://qiita.com/EasyCording/items/f74437800508d76adb8b

# モデル設計
設計のポイントを明確化する。
* ユーザーは認証できるようにする
* ＭＬサーバーには語句ベクトル（TFIDF）を与える。主キーはHASH化　→　ここが最大の悩みどころだった
* 学習セットは語句ベクトル（外部キー）とラベルで構成する
* 文書ファイルはテキストファイル単位で管理し、パス情報のみをデータベースに格納する　→　ここも悩みどころだった

結局のところモデル図は下記のようになった。

```mermaid
 classDiagram
      TFIDFS <|-- LABELS
      LABELS <|-- MODELS
      USERS --|> MODELS
      MODELS <|-- SOURCES
      class TFIDFS{
          id: hash(PK)
          tfidf: hstore
      }
      class LABELS{
          id(PK)
          tfidf_id(FK)
          label:text
      }
      class MODELS{
          name
          ai_parameter
          crossvalid_result
          model_id(PK)
          labelset_id(FK)
          source_id(FK)

user_id(PK)
      }
class SOURCES{
source_id(PK)
user_id(FK)
document_path:csv
}

class USERS{
          user_id(PK)
          name:TEXT
          pass:TEXT
      }
```

# フロー

以下は具体的処理の流れを示す

### 前処理
* ユーザーはTEXTデータをuploadする。
* TEXTデータはPATHのみをソースデータ(SOURCE)に格納する。
* SOURCEデータを文章単位に処理する。
* 文章とラベルの組み合わせをラベルデータ(LABELS)に格納する。
* ラベルデータ毎に、自然言語処理によりTFIDFデータに変換する。
* ラベルデータ→HASHキーで対応付けを行う
* 単語ベクトルデータ(TFIDF)はPOSTGRESのHSTORE形式として、HASHとペアで格納する。　→　最大のポイント

### 学習プロセス
* 教師データとなるラベルデータをモデルデータ(MODELS)に指定する。
* 学習モデルを生成。
* 交差検証結果を戻す。
* 生成モデル、機械学習パラメータを保存する。

### 予測プロセス
* TOKENによりユーザー認証を行う。
* 予測したいテキストをTFIDF処理して、ML-APIに渡す。
* RESPONSEでラベルとスコアを返す。
PrologでもGPIO制御

# PrologだってLチカしたいよ
Prologというと論理型の言語であり、どちらかというとアカデミック用途が多いです。PrologでラズパイのGPIO制御については応用例が少ないようなのですが、PrologでだってLチカしたいですよね。その方法についてご紹介します。

# SWI-Prologの場合
Prolog処理系といいますとJanさんのSWI-Prologが有名です。事実上の世界標準だと思われます。とても高性能です。ところでSWI-PrologでGPIOを扱いにはどうしたらいいのでしょうか？ググってみるとJanさんが説明しているのが見つかりました。
https://discourse.swi-prolog.org/t/access-to-gpio-on-raspberry-pi/4438
CのライブラリをSWI-Prologから呼び出すようです。

# N-Prologの場合
拙作のN-Prologはできるだけお手軽にGPIOを制御できるようにしてあります。ラズパイで処理系をコンパイルしますとハードがラズパイの場合には自動的にGPIO制御の述語を組込み述語として組み入れるようになっています。
拡張された述語は下記のとおりです。

```
N-Prolog <==================================> C
wiringpi_spi_setup(ch speed) <===> wiringPiSPISetup (SPI_CH, SPI_SPEED)
wiringpi_setup_gpio  <===> wiringPiSetupGpio()
pin_mode(n, 'output) <====> pinMode(n, OUTPUT) or 'input -> INPUT 'pwm-output -> PWM_OUTPUT
digital_write(n, v) <===> digitalWrite(n, v)
digital_write_byte(v) <===> digitalWriteByte(value)
digital_read(pin) <===> digitalRead(pin)
delay(howlong) <===> void delay(unsigned int howLong)
delay_microseconds(howlong) <===> void delay_microseconds(unsigned int howLong)
pull_up_dn_control(pin, pud) <===> pullUpDnControl(pin,pud)
pwm_set_mode('pwm_mode_ms) <===> pwmSetMode(PWM_MODE_MS); or 'pwm_mode_bal -> PWM_MODE_BAL
pwm_set_clock(n) <===> pwmSetClock(n)
pwm_set_range(n) <===> pwmSetRange(n)
pwm_write(pin, value) <===> pwmWrite(pin , value)


```

# 自律型ロボット
写真はPrologで制御のおもちゃロボットを作ろうとして途中になったままのものです。超音波センサーとLチカを仕込んであります。バッテリーは携帯電話用のバッテリー。欲がでて画像認識もとDeepLearning（以下「DL]）にはまってしまいました。この後Elixir用のDLライブラリ[DeepPipe2](https://github.com/sasagawa888/deeppipe2)の開発に没頭してしまい、ロボットは中途半端なままです。（苦笑）

![IMG_1126.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/1b7063bd-faa1-fa0b-c26f-84fc5f5e7692.jpeg)
![IMG_1127.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/6ea0addc-d1a2-812f-7036-5130a8c0a6bb.jpeg)



# 夢は膨らむ
Prologは論理的推論ができます。これとDLを組み合わせると面白いことができそうです。そしてGPIOでセンサーやサーボモーターを制御したら面白そうです。といいつつ、Lisp処理系開発、Prolog処理系開発に没頭していたのでさっぱり進展していないのですが。


N-PrologはRUN/PROLOG互換のインタプリタ・コンパイラです。OSSとして無償提供しております。
https://github.com/sasagawa888/nprolog
Kageki (TD4互換機) でサーボ SG90 を操作してみる

[TD4の命令を実行できる自作CPU「Kageki」](https://elchika.com/article/9ac9fd67-86c5-4b1b-a355-4f662e8af794/) でサーボ SG90 を操作してみた。

# サーボ SG90

SG90 は、小型サーボであり、電気信号によって回転角度を制御することができる。
例えば[秋月電子通商](https://akizukidenshi.com/catalog/default.aspx)で売られている。(M-08761)

以下のように、20ms間隔で0.5～2.4msのパルスを与えることで制御を行う仕様である。
回転角度はパルスの幅で表現する。
![SG90の制御信号](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/5264769b-eb2f-9cce-7c89-0680a930d411.png)

# 今回の仕様

サーボを制御する用の信号を、出力ポートのビット0から出力する。
入力ポートの値により、パルスの幅を変える。値が大きいほどパルスを長くする。

# プログラム

```
位置 機械語   アセンブリ言語
--------------------------------
0    00100000 FIRST: IN  A
1    10110001        OUT 0001
2    01010001 WAIT1: ADD B, 0001
3    11100010        JNC WAIT1
4    00001111 SIG:   ADD A, 1111
5    11100111        JNC OFF
6    11111000        JMP NOOFF
7    10110000 OFF:   OUT 0000
8    01010001 NOOFF: ADD B, 0001
9    11100100        JNC SIG
A    00110000        MOV A, 0000
B    01010001 WAIT2: ADD B, 0001
C    11101011        JNC WAIT2
D    00000001        ADD A, 0001
E    11101011        JNC WAIT2
F    11110000        JMP FIRST
```

0番地：入力ポートの値を読む。
1番地：信号をHIGHにする。
2～3番地：固定の時間待つ。
4～9番地：入力ポートの値によって変わるタイミングで信号をLOWにする。
A～E番地：二重ループにより、長めの時間待つ。
F番地：最初に戻る。

# 実行結果

50kHzのクロックで実行した。

## 動作の様子

軸の回転により0～Fを切り替え、2進数で出力するスイッチを用いた回路を入力ポートに接続した。
これにより、入力ポートに `0000` ～ `1111` を入力し、それに応じてサーボが回転している。

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

## 信号の確認

オシロスコープ FNIRSI-1013D を用い、出力信号を観察した。

### パルスの間隔の確認

`0000` を入力したとき、パルスの間隔は 13.1ms であった。
仕様の 20ms よりかなり短いが、動いたのでヨシ…？

![入力が 0000 のときのパルスの間隔](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/5ca0000f-76e2-bcf2-8376-c1f35e7b75b6.png)

`1111` を入力したときも、パルスの間隔は 13.1ms であった。
パルスの間隔は入力によらないようである。

![入力が 1111 のときのパルスの間隔](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/d8b2fbad-a562-455f-f3d3-17849fc867f5.png)

### パルスの幅の確認

`0000` を入力したとき、パルスの幅は約 0.7ms であった。

![入力が 0000 のときのパルスの幅](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/ca52e1d1-cbf4-74c8-e01a-cfdb3953cb3b.png)

`1111` を入力したとき、パルスの幅は約 2.2ms であった。

![入力が 1111 のときのパルスの幅](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/d7a24936-1271-6f6e-ff7a-4e5286265b52.png)

いずれも、仕様 (0.5～2.4ms) 内に収まっている。
【エラー・Exception】検査例外・非検査例外~Java~

## 検査例外・非検査例外とは
#### 検査例外
検査をしなくてはいけないもの
#### 非検査例外
検査をしなくても良いもの
　　
一括りにするとざっくり「異常や例外」です。
下記のように継承関係があります。
```java
Object
//↑
Throwable
//↑        ↑
Error   Exception
//         ↑
        RuntimeException

```
まず、大きく分けて「**Error**」か**そうではない**かに分けられます。

**Error**はプログラムから回復不可能なエラーのことを言います。「プログラムで対処する」ことを求められていません。

逆に言えば**Error以外は**プログラムの中で対処することが求められているエラーです。

以上を踏まえた上で以下のように分けられます。
「**Error**」「**Exception**」「**RuntimeException**」に分けられます。
それぞれ**エラー**、**検査例外**、**非検査例外**を表します。



#### Exceptionの一部（RuntimeException以外）は"検査例外"
☆「Exception」はtry~catchなどで囲む。throws句で宣言をする。
**【Exception　例】**
・IOException
・SQLException
・ClassNotFoundException
#### RuntimeException"非検査例外"
☆「RuntimeException」とそのサブクラスは非検査例外でありtry~catchを強要されることはない。
**【RuntimeException　例】**
・ClassCastException
・NullPointerException
・ArrayIndexOutOfBoundsException



#### Errorとは
☆「Error」はプログラムではどうしようもなく回復不可能なエラーが出てしまった時。「実行マシンのメモリが不足」「ディスクに対する読み込み、書き込みの権限が不足」「ネットワークの接続ができない」
**【Error　例】**
・StackOverflowError
・OutOfMemoryError
・UnknownError

ただプログラムでの対処が求められていないだけで任意で例外処理を行なっても良いのです。

### まとめ
エラーをまず「プログラムでの対処」が求められているか、求められていないかで分ける。その中で「**プログラムでの対処が求められている**」ものを更に検査例外(try~catchが必要)か非検査例外(必要ではない)かに分ける。その分け方ができるようになれば知識として定着するはずです。

プログラムでの対処を '求める' か '求めない' か
↓
【Error】【Error以外】
↓
try~catchが '必要' か '必要でない' か
↓
【Exception】【RuntimeException】
必要↑ 　　　　不必要↑

最初はこういう風に段階に分けてエラーを分けていくのが良いと思いました！
私も最近ようやく理解しましたが、、、笑
他部署向けにざっくりコードレビューについて解説！

会社で共有したコードレビューの記事を汎用化したらいいのでは・・・？と思って書きました。
社内MTG等で活用してください！

## **コードレビューとは？**

エンジニアには他人が書いたコードをチェックするという業務があります。
[コードレビューとは - IT用語辞典](https://e-words.jp/w/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC.html)

## **コードレビューの方法？**
[GitHub](https://github.co.jp/)にアクセスして実装したコードを目視で確認するのが基本になります。
([octocatから引用](https://github.com/octocat/linguist/compare/octocat:96d29b7%5E%5E%5E%5E%5E...octocat:96d29b7)。赤が削除分、緑が追加分)
![スクリーンショット 2022-12-17 8.33.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/9f4edd6d-7ebf-00f7-7647-591ba6f56330.png)


## **目視で確認するの面倒じゃない？**
自分のPCにレビューするコードを取り込むこともできます。メリットはコード編集ソフト(エディタ)でコードを検索したり、(必要に応じて)書き方を統一してくれるといった点があります。

## **そのコード本当に動くの？**
レビューをお願いした段階でコードが正しく動作することが前提としている開発組織が多いです。
コードレビューで行うのは基本的にコードのレビューだけになり、それ以外のこと(設計や仕様など)のレビューは別機会で行うことが多いです。
>通常、CL がコードレビューに至るまでには、コードが正しく動作することを開発者が十分にテストしていると期待できます。 それでもレビュアーはエッジケースを想定する、並行処理の問題を探す、ユーザーになりきって考えるなど、コードを読むだけではわからない不具合がないかを確認してください。

※CL(Critical Limit)は管理基準のこと
[Google's Engineering Practices documentation 日本語訳から引用](https://fujiharuka.github.io/google-eng-practices-ja/ja/review/reviewer/looking-for.html)

## **コードレビューよりバンバンコード書いた方がいいのでは？**
以下のようなことを考えるとメリットがあります

### うっかりミスをなくせる
スペルミス(apple→appel)等をなくせる

### コードのレベルが上がる
極端な例ですが、無駄な記述しか知らない人にとっていい気づきになるかもしれません

1 + 1 - 1 + 1 = 2
↓
1 + 1 = 2

### クセや属人性を極力なくせる
例えば丸いボタンをクリックした時のプログラム名をcircleJostleにしたとしましょう。
circleJostleという単語を見た時にボタンをクリックというイメージがわきますでしょうか？
と考えた時に関数名をclickButtonなどに訂正することをレビューしてあげる必要があります。

※jostle:押し返す
ノーコードテスト自動化ツールにおける自動テストシナリオの分割単位について考える

## はじめに
新たにUIテストの自動化に取り組むとき、既存の手動テストスクリプトを参考に自動テストスクリプトを実装したり、新たに自動テストスクリプトを実装することになります。
その際、一つのテストシナリオをどのくらいの長さにすればよいのか悩むことがあります。
当然、何をテストするのか、どれくらいテストをするのかという視点も重要ですが、ここでは何をどれくらいテストするのかが決まった上で、自動テストスクリプトをまとめたり、分割したりするときに考慮すべき点について考えてみます。
使用するテスト自動化ツールによっても考慮すべき点が変わってくるため、これまで私が業務の中で携わったノーコード/ローコードテスト自動化ツールであるAutify、MagicPodを使う場合を考えます。

## SaaSサービスならではの悩み
OSSのテスト自動化ツールと異なり、契約プランによって作成できるテストケース数や、テストの実行回数の上限が定められている場合があるため、
自動テストシナリオの数をできる限り少なくしたい、という要望があるかもしれません。
ただ、一つの自動テストシナリオの中で様々なことを確認しようとすると、問題が起きることがあります。

## ステップ数を考慮する
2022年12月現在、AutifyとMagicPodでは機能的にステップ数の上限は定められていませんが、ステップ数が増加すると、実装環境のハードウェアスペックによっては動作が重くなったり、テスト結果の参照に時間がかかるため、ステップ数の増やしすぎには注意が必要です。

:::note info
Autifyでは、サポート対象のステップ数は200ステップまでと定められています
https://help.autify.com/docs/ja/what-is-the-maximum-number-of
::: 

:::note info
MagicPodでは、プランにより画像差分チェックステップ数の上限が定められている場合があります。(通常のステップにおける上限はなし)
https://magicpod.com/pricing/
::: 

## 実行時間を考慮する
[ISTQB Advanced Level シラバス テスト自動化エンジニア](https://jstqb.jp/syllabus.html#syllabus_advanced_specialist)では、テスト自動化の目的として「テスト実行期間の短縮」や「テスト実行頻度の向上およびテストサイクルに要する時間の短縮」などが挙げられています。
テスト自動化の利点である迅速なフィードバックを享受したい場合は、実行に時間のかかる自動テストを見直す必要があります。

また、自動テストの実行時間が長いと、失敗したテストを調査するための時間や、自動テストスクリプトの保守の際、修正対象のステップに行き着くまでの時間が長くなるといった欠点もあります。
そのため、実行時間が長い自動テストシナリオは分割することができないかを検討してみましょう。

## 依存関係を考慮する
テストシナリオの中でデータを作成後、作成したデータを使って別のテスト観点を確認するような場合、分割を検討したほうがよいケースがあります。
例えば、ECサイト等でユーザアカウントのサインアップを行ったのち、登録したユーザアカウントでサインインし、注文フローを確認するようなシナリオがあったとき、サインアップとサインインを一連の流れとして行うべきなのかを検討してみましょう。

ただし、テストシナリオAで作成したデータを、テストシナリオBで参照するような場合、ふたつのテストシナリオに依存関係が生まれてしまい、テストシナリオAでテストが失敗したとき、テストシナリオBでもテストが失敗することになるため、テスト失敗時の再実行が容易に行えなくなる可能性があります。
そのため、分割をしすぎてテストシナリオ間での依存関係が生まれないように留意することも重要です。

なお、テストの前提条件を満たすためのデータの初期化などはWebAPIを提供してもらい、UI操作を行わずとも前提条件を整えられるようにすると良いでしょう。

## テスト対象やテストのコンテキストを考慮する
テスト自動化の目的によっても変化する部分ですが、迅速なフィードバックを得ることを目的とするのであれば、テスト対象の機能や、テストのコンテキストで分割することを検討します。

例えば、DBのマイグレーションが行われたときにはデータのCRUDを意識したテストを実施したいですし、フロントエンドフレームワークのバージョンアップが行われたときはUI表示を確認するテストを実施したいです。
自動テストの規模が大きくなるほど実行時間も長くなり、フィードバックも遅くなってしまうため、必要なときに必要なテストが必要な分だけ実行できる単位での分割を検討するとよいでしょう。

## おわりに
ノーコードテスト自動化ツールにおける自動テストシナリオの分割単位について考えてみました。
実装の際に少しでもご参考になれば幸いです。
また、「こんな視点でも考えたほうが良い」という点があれば、コメント欄にてお知らせいただけると嬉しいです。
【JavaScript】find,findIndex,filterによる配列オブジェクト加工例

## やりたかったこと

指定したプロパティのvalueを持つ要素にだけ、追加でpushなどをしたかった時の実装方法について少し時間がかかってしまったのでその備忘録です。
例えば、下記のようなデータがAPIから返ってくるとます。
```js
 const data = [
        {
          date: "2022-12-11",
          messages: [
            {
              text: "メッセージデータ1-1",
              creatTime: "10:00",
            },
          ],
        },
        {
          date: "2022-12-12",
          messages: [
            {
              text: "メッセージデータ2-1",
              creatTime: "11:00",
            },
            {
              text: "メッセージデータ2-2",
              creatTime: "12:00",
            },
          ],
        },
        {
          date: "2022-12-13",
          messages: [
            {
              text: "メッセージデータ3-1",
              creatTime: "10:00",
            },
          ],
        },
      ];
```

日付が一致したオブジェクトの`messages`プロパティにのみ、新しいメッセージとしてオブジェクトを追加します。
そのような時に`find`,`findIndex`を用いることで実装が可能です。

## `find()`,`findIndex()`

`find()`はコールバック関数を引数に持ちます。
booleanとなる条件を設定し、それを満たす配列内の**一番最初の要素**のみ返します。
`findIndex()`は、そのindex番号を返すという違いです。

**`find()`の場合**
```js
const find = data.find((item) => item.date === "2022-12-12");
console.log(find); // → {date: '2022-12-12', messages: Array(2)}
find.messages.push({
        text: "メッセージデータ2-3",
        creatTime: "13:00",
    });
});
```

**`findIndex()`の場合**
```js
const findIndex = data.findIndex((item) => item.date === "2022-12-12");
      console.log(findIndex); // → 1
      data[findIndex].messages.push({
        text: "メッセージデータ2-4",
        creatTime: "14:00",
      });
```
`data`を`console`すると指定した2022-12-12の日付をもつ要素にだけ新しいデータをpushすることができました。
![スクリーンショット 2022-12-17 8.08.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/a997a30c-3062-e19c-7c70-b29a3a16c8f8.png)

## `filter()`

`filter()`も同様にコールバック関数を引数に持ち、booleanとなる条件を設定します。
それを満たす配列内の**全ての要素**を抽出した新しい配列を生成します。
今回やりたかったこととは少し違いますね。

```js
 const filter = data.filter((item) => {
    return item.date === "2022-12-13";
});
```
![スクリーンショット 2022-12-17 8.23.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2609332/7c99a530-41ee-daed-34f6-d1f22c5b1f76.png)

## まとめ

複雑?なデータの加工や抽出はまだ時間がかかってしまいますが、いろんなメソッドを知っておくと素早くやりたいことがコードに落とし込めそうですね。
配列内に値が存在するかどうかを調べる必要がある場合は、[includes()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)、指定したテスト関数を満たす要素があるかどうかを調べる必要がある場合は、[some()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)を使用できるとのことです✍🏻
他部署向けにざっくり開発関連の用語一覧

## 目的
開発陣が当たり前に使っている開発ワードを開発以外のメンバーにも理解してもらうため。
会社で共有した記事を一部汎用化したものになります。
全社MTGなどで活用してください！

## 用語一覧
### フロントエンド(エンジニア)
ブラウザに表示される部分をプログラムすること。UI部分

### バックエンド(エンジニア)
データの管理に関するプログラムすること。ユーザーの情報管理・更新など

### キャッシュ
Webページなどを閲覧した際にデータをパソコン内に一時的に保存して、再度閲覧する際に素早く表示するための機能

### デバッグ
プログラムのバグを見つけて修正すること

### リファクタ
コードをより良いものにする行為

### stg(ステージング)
本番リリースの最終確認をするサイト環境のこと

### prod(本番)
基本的にお客様が使っているサイト環境のこと

### GitHub
書いたプログラムコードを保存・共有できるサイト
https://github.co.jp/

### issue
書いたコードの課題、不具合の要約をGitHub上に残すこと

### リポジトリ
ファイルとか変更履歴とかをGitHubなどに保管しておくこと

### (コード)レビュー
GitHubなどで公開したコードを他の開発者がチェックすること。
結婚式でスピーチを依頼された方のためにNGワードのチェックサイトを作成しました。

# 2024/6/2 追記
この記事でご紹介したサイトは現在停止しています。

# 今回ご紹介したいサイト
https://wedding-speech-check.net/

# サイトを作成する至った背景
昨年(2021年)、友人の結婚式があり、祝辞を頼まれました。
祝辞のスピーチ原稿をメモでまとめていたときにNGワードがないかをチェックしていましたが、自動でチェックするツールがあれば便利だと思い作成しました。祝辞や友人スピーチを行う時は結構緊張すると思いますので、そういった方々を少しでも手助け出来れば嬉しいなと感じています。

# このサイトで出来ること
- 結婚式スピーチ(祝辞や友人スピーチ等)でNGワードと呼ばれる単語をチェックすることが出来ます。チェックできる単語については、サイトにも記載しております。
- おおよそのスピーチ時間の計測が出来ます。
- おおよそのスピーチ時間が5分を超えると警告メッセージを表示してくれます。

# 利用技術
サイトのシステム構成図は以下のようになります。
直線で通信の流れを示し、点線で資材の流れを示しています。
![wedding-sppech-check.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429119/f480a00a-5194-4412-6ad2-d7fdc89450a7.png)

## フロントエンド
- HTML5
- JavaScript
- Bootstrap
## インフラ
- Amazon S3
- Amazon CloudFront
- Amazon Route 53
- AWS Certificate Manager
- AWS WAF

## CICD
- GitHub Actions

# 所感
初めて個人開発で作成したサイトをリリースすることが出来ました。
今までの個人開発では、実際にリリースするまでに至ったことがありませんでした。
そのため、まずはリリース出来た自分を素直に褒めてあげたいと思っています。
今後の取り組みとしては、せっかくサイトを公開したので少しでも利用者を増やしていきたいと考えています。現在は、Google Analyticsを利用してサイトの利用者をチェックしていますが、2022年12月17日時点では、私のみが利用者となっておりますので、どれくらい出来るか分かりませんが、SEO対策も行っていきたいと考えております。また、運用を行う中でソースコードの改修やインフラ構成の見直しも行っていきたいと考えています。少しでも長く運用することが出来るように頑張ります。
GUI改造6 固定位置カメラ

「instantNeRFで遊ぶ Advent Calendar 2022」の20日目です。

今日はinstantNeRFのtestbedに視点変更機能を追加しました。
BlenderやRealityCaptureのようにTop ViewやRight Viewなどのショートカットが欲しかったです。

:::note
業務外の個人的な検討活動です。
:::

:::note alert
警告
環境や入力内容によっては現在使用できている状況が壊れることがあります。
あなたの責任と判断で試してください。私は責任を取りません。
:::

#### テストデータ
sketchfabのNefertiti statueを使用させていただきました。ありがとうございます。

https://sketchfab.com/3d-models/nefertiti-statue-d148f771c3f44225b56cb7ce8d3c5ce6

#### testbed.cu
Testbed::keyboard_event() に下記を追加しました。
HをFront、JをRight、KをBack、LをLeft、YをTop、BをBottomに割り当てました。

```
	// ZXY			
//from front [ x: 0, y: -180, z: -180 ]			
	if (ImGui::IsKeyDown('H')) {
		m_camera <<
			1.0f, 0.0f, 0.0f, 0.5f,
			0.0f, -1.0f, 0.0f, 0.5f,
			0.0f, 0.0f, -1.0f, m_aabb.max[2];
	}
	//from right [ x: 0, y: 90, z: 180 ]			
	if (ImGui::IsKeyDown('J')) {
		m_camera <<
			0.0f, 0.0f, -1.0f, m_aabb.max[0],
			0.0f, -1.0f, 0.0f, 0.5f,
			-1.0f, 0.0f, 0.0f, 0.5f;
	}
	//from back [ x: 0, y: 0, z: -180 ]			
	if (ImGui::IsKeyDown('K')) {
		m_camera <<
			-1.0f, 0.0f, 0.0f, 0.5f,
			0.0f, -1.0f, 0.0f, 0.5f,
			0.0f, 0.0f, 1.0f, m_aabb.min[0];
	}
	//from left [ x: 0, y: -90, z: -180 ]			
	if (ImGui::IsKeyDown('L')) {
		m_camera <<
			0.0f, 0.0f, 1.0f, m_aabb.min[0],
			0.0f, -1.0f, 0.0f, 0.5f,
			1.0f, 0.0f, 0.0f, 0.5f;
	}
	//from top [ x: 90, y: 0, z: 0 ]			
	if (ImGui::IsKeyDown('Y')) {
		m_camera <<
			1.0f, 0.0f, 0.0f, 0.5f,
			0.0f, 0.0f, -1.0f, m_aabb.max[1],
			0.0f, 1.0f, 0.0f, 0.5f;
	}
	//from bottom [ x: -90, y: 0, z: 0 ]			
	if (ImGui::IsKeyDown('B')) {
		m_camera <<
			1.0f, 0.0f, 0.0f, 0.5f,
			0.0f, 0.0f, 1.0f, m_aabb.min[1],
			0.0f, -1.0f, 0.0f, 0.5f;
	}
```

実行した様子です。
19日目のcamera pathの改造GUIと合わせて使用しています。
キーボードのH、J、K、Lキーを順番に押しキーフレームの視点を入力しました。

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

https://qiita.com/nakmura/private/6ed68cb45e404037970f
GMC-4でフィボナッチ数列を計算してみた

学研の4ビットマイコン GMC-4 でフィボナッチ数列を計算してみた。

# フィボナッチ数列

最初の2項は `0, 1` であり、3項目からは前の2項の和である数列。

0, 1, 1, 2, 3, 5, 8, 13, 21, …

[A000045 - OEIS](http://oeis.org/A000045)

# 今回の仕様

フィボナッチ数列の各項を16進数で表現し、下位4ビットを7セグメントLEDに、上位7ビットを2進LEDに表示する。

以下のC言語のプログラムにより、表示されるはずの値を求めることができる。

```c
#include <stdio.h>

int main(void) {
	int cur = 0, prev = 1, pprev;
	int i, j;
	for (i = 0; i < 100; i++) {
		/* 値をコピーする */
		pprev = prev;
		prev = cur;

		/* 現在の値を表示する */
		for (j = 7; j >= 0; j--) {
			putchar("o*"[(cur >> (j + 4)) & 1]);
		}
		printf(" %X\n", cur & 0xf);

		/* 現在の値に前の値を足す */
		cur = (prev + pprev) & 0xfff;
	}
	return 0;
}
```

実行結果のうちオーバーフローしない範囲は、以下のようになった。
(GMC-4 の2進LEDは7桁であるが、ORANGE-4 にも対応できるように8桁で出力している)

```
oooooooo 0
oooooooo 1
oooooooo 1
oooooooo 2
oooooooo 3
oooooooo 5
oooooooo 8
oooooooo D
ooooooo* 5
oooooo*o 2
oooooo** 7
ooooo*o* 9
oooo*oo* 0
oooo***o 9
ooo*o*** 9
oo*oo**o 2
oo****o* B
o**ooo** D
*o*oooo* 8
```

# プログラム

以下のプログラムは、[MikeAssembler](https://mikecat.github.io/mike_assembler/) でアセンブルできる。

```
target gmc4

	; [0xF]:[0xE]:[0xD] : 現在の値
	; [0xC]:[0xB]:[0xA] : 前の値
	; [0x9]:[0x8]:[0x7] : 前の前の値

main_loop:
	; 値をコピーする (前の前の値←前の値、前の値←現在の値)
	TIY 0xC
copy_loop:
	MA
	AIY -3
	AM
	AIY 6
	MA
	AIY -3
	AM
	AIY -1
	CIY 0x9
	JUMP copy_loop

	; 現在の値を表示する (最後にコピーするのが現在の値の1の位であることを利用する)
	AO
	CAL DSPR
	TIA 9
	CAL TIMR

	; 現在の値に前の値を足す
	; 1の位を足す
	TIY 0x7
	MA
	TIY 0xD
	M+
	JUMP carry0
	AM
carry0_end:
	; 0x10の位を足す
	TIY 0x8
	MA
	TIY 0xE
	M+
	JUMP carry1
	AM
carry1_end:
	; 0x100の位を足す
	TIY 0x9
	MA
	TIY 0xF
	M+
	AM
	JUMP main_loop

	; 足し算の処理の一部 (1の位→0x10の位への繰り上がり)
carry0:
	AM
	TIY 0xE
	MA
	; 足される数に1を足す
	AIA 1
	AM
	; 足した結果が0なら、0x100の位へ繰り上がる (0x100の位からの繰り上がりは捨てる)
	CIA 0
	JUMP carry0_end
	TIY 0xF
	MA
	AIA 1
	AM
	JUMP carry0_end

	; 足し算の処理の一部 (0x10の位→0x100の位への繰り上がり)
carry1:
	AM
	TIY 0xF
	MA
	AIA 1
	AM
	JUMP carry1_end

	org 0x5A
	datan 1, 0, 0, 0, 0, 0
```

以下は、このプログラムの機械語表現である。

```
  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
0 | A C 5 B  D 4 B 6  5 B D 4  B F D 9
1 | F 0 2 1  E D 8 9  E C A 7  5 A D 6
2 | F 3 8 4  A 8 5 A  E 6 F 4  D 4 A 9
3 | 5 A F 6  4 F 0 0  4 A E 5  9 1 4 C
4 | 0 F 2 4  A F 5 9  1 4 F 2  4 4 A F
5 | 5 9 1 4  F 2 E
```

さらに、以下のように手動でデータメモリを初期化してから実行する。
(数列の初期値を設定する)

```
  | 0 1 2 3  4 5 6 7  8 9 A B  C D E F
--+-----------------------------------
5 |                       1 0  0 0 0 0
```

# 実行結果

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

フィボナッチ数列の各項が求まっている。