OmniAICreator/Qiita-1.07M huggingface dataset:
aitendoの不良パーツに引っかかった

# 出会い

aitendoで以下の製品を買いました。
ファームウェアが書き込まれていないので、
もとから入っているファームウェアを消さずにプログラムを書き換える実験ができるという利点があります。

* [IC実装済みIchigoJam-T互換基板 - aitendo](https://www.aitendo.com/product/13949)
* [ベーシック部品ボックス - aitendo](https://www.aitendo.com/product/14015)

![IchigoJam互換機 (未組立)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/79afd80c-1d25-2aa0-0bcf-5b44612034e9.jpeg)

何も考えずに組み立てました。

![IchigoJam互換機 (組立完了)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/a664d5e1-e8dc-e53e-b789-ea53705c0d34.jpeg)

早速拡張基板を挿してシリアル通信を試し…

＿人人人人人＿
＞挿さらない＜
&nbsp;￣Y^Y^Y^Y￣

詳しく見たところ、左側の14ピンのピンソケットと、5ピンのピンソケットは正常ですが、
右側の14ピンのピンソケットにピンが挿さりません。
拡張基板ではなく、1ピンのケーブルを挿そうとしても挿さりません。
よく見ると、微妙に口が小さいような気がします。

そういえば、組み立てる時になんかハンダ付けする端子が短い気がしたんだよね…

![IchigoJam互換機 (裏面)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/16ad9cc3-70e3-002b-7213-d4ecab11593b.jpeg)

左側の14ピンのピンソケットの端子は突き出ているのに対し、
右側の14ピンのピンソケットの端子は突き出ず、短かったことがうかがえます。

他のパーツも含めすでに組み立ててしまっているので、返品・交換というのも難しそうに思えます。
うーん…まあ泣き寝入りですかね。
(こうしてアドベントカレンダーを埋めるためのネタとして役立ったじゃないか。よかったよかった。)

# 対処

シリアル通信の端子がある側に接続できないピンソケットを取り付けてしまったため、シリアル通信ができない…！？

いえいえ、この基板をよく見ると、ピンソケットの脇に部品がついていない穴があります。
そして、以前買ったこんな時に便利なケーブルがあります。

それは…[秋月電子通商](https://akizukidenshi.com/catalog/)の「スルホール用テストワイヤ TP-200」(C-09830)！

|全体図|端子の拡大|
|:-:|:-:|
|![TP-200 全体図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3c4255ac-5533-206a-cd9e-29e6398fc572.jpeg)|![TP-200 端子の拡大](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/a9a9e0a5-ede7-1fb6-1caa-30e2f3b086f6.jpeg)|

このケーブルは、一方の端が通常のピン、もう一方の端が基板のスルーホールに接続するためのバネになっています。
これを使うことで、USB-シリアル変換器とこの基板を接続し、シリアル通信をすることができそうです！

実際に接続します。

![USB-シリアル変換器との接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/ce031186-1c04-eedb-00ec-660dedcdc375.jpeg)

スイッチを入れ、[Tera Term](https://ttssh2.osdn.jp/)を操作します。

![シリアル通信の様子](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/b9704bc4-56b7-4f7c-8c1e-9fab09930e9e.png)

無事シリアル通信ができました！

# おわりに

今回はたまたま不良を踏んでしまったようですが、不良が出る確率はわかりません。
aitendoで売られている製品の品質を信じるか信じないかはあなた次第です。

IchigoJamはjig.jpの登録商標です。
今更だけど、エンジニア35歳定年説について考えてみた

# はじめに

[UdonTech Advent Calendar 2021](https://qiita.com/advent-calendar/2021/udontech) の8日目です。

先日36歳になりました。エンジニアの世界には「35歳定年説」という言葉がありますので、もはや老後なのかもしれません。せっかくなのでこの言葉について少し考えを巡らせてみます。

# エンジニア35歳定年説とは

定年ということですから、その後はもう働かなくても生活に困らないということなのでしょうか。

一部の外資系金融マンの間では、若いときからとんでもない年俸を稼ぎ、40歳前後で莫大な資産を蓄えて早期リタイアする人達がいるという話を聞いたことがあります。また最近は、1億円前後を貯めて慎ましく余生を過ごすFIREなる草食系の早期リタイア思想が流行っているとかいないとか。

エンジニアが35歳でこのような早期リタイアをするのは少し難しそうですね。
ならば、スタートアップに参画し、一発エグジットの恩恵を夢見る・・・

いやいや、まてまて。

エンジニア35歳定年説には、「35歳限界説」という別名もありますので、きっとこんな夢のある話ではないのでしょう。

# エンジニア35歳定年説とは その2

気を取り直して。
本来のエンジニア35歳定年説とは「そろそろ現場で活躍するのが難しくなるよ」という意味だそうです。

それには
・学習能力や意欲が低下し、新しい技術を学びにくくなる
・体力が低下し、長時間労働がしにくくなる
・年功序列的な賃金相場では、単価と能力が見合わなくなる
・扱いづらくなる
などの理由が挙げられます。

確かに長く同じ業界にいると好奇心も枯れてきますし、締め切り前のひと踏ん張りする気力や体力も衰えてきますし、20代のマネージャーとかだと4,50代のエンジニアに指示しにくいかもしれませんね。

# 一般的な対抗策

この定年説に対する一般的な対抗策には次のようなものがあります。
(1) 技術職を離れ、マネジメント職に移る
(2) 受託開発会社を作って独立する
(3) 現場に残ってできる範囲の仕事を続ける

(1) に関しては、好奇心が枯れてしまった人と相性が良さそうですね。
(2) に関しては、マネジメントもできますし、自分でコードを書くこともできますし、モダンな技術を使おうと思えばそれもお客様への提案次第ですし、自由にポジションが取れますね。
(3) は対抗策ではなく成り行きなのですが、それはそれで悪くない選択肢ですね。業務系だとこのタイプの方もかなりたくさんいらっしゃいますね。Web系だとまだ業界の歴史そのものが20年くらいしかないので、まだ少ないですが、今後業界の歴史が長くなるとともに、このタイプの方も増えていくことでしょう。

# 35歳定年説のその先へ

以上のようにいろいろとネガティブなことが囁かれるようですが、実際に自分の周りを見渡してみると、40代以上でご活躍されているエンジニアの方がたくさんいらっしゃいます。きっと35歳定年説という言葉ができた頃とは随分時代も変わってきたことでしょう。

昔はエンジニアやプログラマというと「IT土方」「3K」などの言葉が連想されましたが、今は労働環境も良くなり、そんな言葉はあまり聞かなくなりました。

技術の進歩は加速し、次から次へと新しい技術が生まれ、好奇心を刺激し続けてくれます。

逆に考えてみると若い頃は、技術職以外の選択肢は取りにくいですし、大きな意思決定もしにくいですし、むしろ自由がないように感じてしまいますね。

選択肢が増えて、やりたいことがやりやすい。
エンジニア35歳っていうのは、定年じゃなくてむしろ旬なんじゃないかと感じる2021年の師走でした。
明治のCMを再現する

テレビに「 Meltykiss（メルティーキッス）」という商品を宣伝するCMがあるのですが、  
その中に「降る雪が~全部~メルティーキッスなら~いいのにね」という台詞があります。  
それを再現しよう！！って感じのやつです。

# 環境
PocketMine-MP 4.0.0

# 再現する

いい感じに再現していきます。

## どうやって再現するか

ItemEntityを使用してメルティーキッスっぽいアイテムを降らすのが一番良い感じじゃねってことでItemEntityを使って再現しようと思います。

## 実装する

ItemEntityを使うのでまあ重いです。

```php
class MeltyKiss extends PluginBase{

    public function onEnable() : void{
    	$this->getScheduler()->scheduleRepeatingTask(new MeltyTask(), 10);
    }
}
```

```php
class MeltyTask extends Task{

    public function onRun() : void{
    	foreach(Server::getInstance()->getOnlinePlayers() as $player){
    	    $pos = $player->getPosition();
    	    $pos->y = (int) $pos->y + 10;
    	    $bb = new AxisAlignedBB((int)$pos->x - 3, (int)$pos->y + 10, (int)$pos->z - 3, (int)$pos->x + 3, (int)$pos->y + 10, (int)$pos->z + 3);
    	    for($x = $bb->minX; $x <= $bb->maxX; $x++){
    	    	for($z = $bb->minZ; $z <= $bb->maxZ; $z++){
                    $pos->x = $x;
                    $pos->z = $z;
                    $location = new Location($pos->x, $pos->y, $pos->z, $player->getWorld(), 0,0);
                    $entity = new ItemEntity($location, new Item(new ItemIdentifier(ItemIds::NETHER_BRICK_BLOCK, 0)));
                    $entity->getItem()->setCustomName("Melty Kiss");
                    $entity->spawnToAll();
                    $entity->setDespawnDelay(20 * 1.5);
                }
            }
        }
    }
}

```
AxisAlignedBBを利用してプレイヤーの周りにネザーレンガブロック(メルティーキッス)を落としてます。 
Playerが多いとその分ItemEntityを落とす数が多くなるので鯖に20人とかいると終わります。
所詮ネタなので仕方なし。

一応これで動くには動くのですが、降ってきたメルティーキッスがインベントリを圧迫します。邪魔。
なので、MeltyKiss.phpの

```php
public function onEnable(){
    $this->getScheduler()->scheduleRepeatingTask(new MeltyTask(), 10);
}
```

に

```php
$this->getServer()->getPluginManager()->registerEvents($this, $this);
```

を追加し、新たなメソッドとして

```php
public function e(EntityItemPickupEvent $event){
    $entity = $event->getOrigin();
    $player = $event->getEntity();
    if($entity instanceof ItemEntity and $player instanceof Player){
    	if($entity->getItem()->getCustomName() === "Melty Kiss"){
    		$item = $event->getItem();
    		$player->getInventory()->remove($item);
    	}
    }
}
```

を追加します。これでインベントリ内にたまってくことはなくなるはずです。

## メルティーキッスに当たったときのダメージ

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

誰得だよって感じの動画ですね。（笑）
まあそれほど痛くなさそうなので、ダメージは少なくします。
それでも大量に降ってきたら余裕に死にますが。
とりあえず、

```php
if($entity->getItem()->getCustomName() === "Melty Kiss")
```

の中に

```php
$player->heal(new EntityRegainHealthEvent($player, -1, EntityRegainHealthEvent::CAUSE_CUSTOM));
```

を追加して1ダメージ食らうようにしてみました。


# 最後に

冬ということでメルティーキッスを再現しました。それ以上でもそれ以下でもありません。
せっかくなら参加してみようということでAdvent Calendarに参加してみました
ほんとにしょうもない記事で申し訳ないです。ちなみに私はメルティーキッスを食べたことがありません。
ていうかチョコ嫌いです。
もっと軽くする方法はあります、たぶん。ただネタなのであまり深くまではいきません。
Codeanywhereのタイムゾーンを日本標準時に変更する

#はじめに

CodeanywhereのタイムゾーンはデフォルトではEST（米国東部標準時）になっている。

```sh:
cabox@container:~/workspace$ date
Wed Dec  8 10:30:58 EST 2021
```

通常Ubuntuではtimedatectlコマンドでタイムゾーンを変更するが、Codeanywhereではtimedatectlが使えない。

```sh:
cabox@container:~/workspace$ timedatectl
Failed to create bus connection: No such file or directory
```

#解決策

```sh:TimeZoneをEST->JSTに変更する
sudo apt-get install -y tzdata &&
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```
Jupyter Notebook上で画像分類用のアノテーションをする

## はじめに

画像のアノテーション作業、面倒くさいですよね。
特に、簡単なn値分類(n<=3)程度のアノテーションの場合、面倒なのがアノテーション自体の準備だったりすると思います。
そこで、簡単な分類タスクのアノテーション作業をJupyter Notebook上で実現することにしました。

NOTE: 本記事のコード部分は、参考記事[Python: ipywidgets で Jupyter に簡単な UI を作る](https://blog.amedama.jp/entry/ipywidgets-jupyter-ui)のコードおよびコメントを拝借し、それに修正を加えたものになります。
参考記事では、別のユースケースに適用するための説明とコードが非常に沢山かつ丁寧に含まれておりますので、興味があれば一読することをお勧めします。

## コード

```python
import random
from PIL import Image
import ipywidgets as widgets
from matplotlib import pyplot as plt

from glob import glob
from IPython.display import display


class AnnotationOnJupyter:
    def __init__(self, img_fps, labels=["犬", "猫", "鯨"]) -> None:
        """
        Args:
        - img_fps (List[str]): アノテーション対象の画像パスのリスト
        - labels (List[str]): アノテーションラベルのリスト
        """
        self.img_fps = img_fps
        self.prev_img_path = ""

        self.output = widgets.Output()
        self.ax = plt.gca()

        # コールバックを登録したボタンを用意
        btns = []
        for label in labels:
            btn = widgets.Button(description=label)
            btn.on_click(self.on_click)
            btns.append(btn)
        self.btns = btns

    def start(self):
        # boxを使うと横並びにできる。縦並びが良ければboxの行を削除して display(*btns, output) にする
        box = widgets.Box(self.btns)
        display(box, self.output)

        # セルの出力に描画されるのを抑制するために一旦アクティブな Figure を破棄する
        plt.close()

        # 最初の1回目の描画を手動でトリガーする
        blank_btn = widgets.Button(description="blank")
        blank_btn.on_click(lambda x: self.on_click(x))
        blank_btn.click()

    def on_click(self, b: widgets.Button) -> None:
        if self.prev_img_path != "":
            with open("results.txt", "a") as f:
                f.write(f"{self.prev_img_path},{b.description}\n")

        self.ax.clear()

        # NOTE: 画像パスのリストを順番にたどっていく場合はindexなどを受け取るようにすれば大丈夫
        img_path = random.choice(self.img_fps)
        self.prev_img_path = img_path
        img = Image.open(img_path)
        self.ax.imshow(img)

        #  Output に書き出す
        with self.output:
            self.output.clear_output(wait=True)
            display(self.ax.figure)


if __name__ == "__main__":
    # 画像パスのリストを適当に取得
    img_fps = glob("imgs/*.png")
    annotator = AnnotationOnJupyter(img_fps)
    annotator.start()

```

## 注意点

on_click内の処理ですが、

1. 画像Aを表示する
2. ラベルaが選択されるまで待つ
3. Aに対するラベルaを保存する

のループが1から回っているというのがわかりやすい挙動なのですが、
今回の場合は処理の最初にダミーのラベルを選択することで最初の画像を表示するところからスタートするため、選択したラベルと対応するのはひとつ前の画像パスであることに注意してください(on_clickの最初の方)。

## 動作確認

VSCodeのJupyter Notebookにて動作を確認しています。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190157/961bce9a-53b3-abcb-a01f-41b416603e70.gif)

## さいごに

IPythonの標準ライブラリ、いつもは`clear_output`くらいしか使ってなかったんですが、結構色んな事が出来そうですね。
もっといい書き方などがあればコメント等で教えていただけると嬉しいです。
読んでいただきありがとうございました。
【AWS】VPCのまとめ

# はじめに

こんにちは。
この記事は[GFAMアドベントカレンダー2021](https://qiita.com/advent-calendar/2021/gfam)の初日の記事です。
Amazon VPCについてまとめてみました。

# VPCの概要

VPCとは、クラウド上に自分専用のネットワーク環境を構築できるサービスです。AWSアカウントを作成した大抵の方が、最初に使うことになるサービスです。要件に合わせたネットワーク環境を簡単に作成可能です。

従来のネットワーク構築は、様々なネットワーク機器やサーバ、セキュリティ機器などを準備し、それぞれ構築してから利用できる状況でした。時間的に数か月からと時間のかかるのが普通でした。

AWSではあらかじめネットワークや機器が構築されているため、利用者は必要な機能をWebの管理画面から選択、設定するだけで自由に、そして素早くネットワーク環境を構成できるようになっています。

VPCをまとめる上で必要となるリージョンとアベイラビリティゾーンについてまとめます。

## リージョンとアベイラビリティゾーン

* リージョン：データセンターが集まった（概ね国単位の）物理的ロケーションのことです。各リージョンで複数のアベイラビリティゾーンが存在します。AWSでは、北米、南米、欧州／中東／アフリカ、アジアパシフィックなどの地域に25のリージョン（2021年12月調べ）があります。VPCはリージョン単位で作成することになります。

* アベイラビリティゾーン：略してAZと呼ばれています。AZは1つ以上のデータセンターのことです。リージョンには複数のデータセンターが存在しますが、低レイテンシーで接続された専用ネットワークを持っています。サブネットはリージョン内のAZ単位で作成することになります。

以下に、VPCに関係する機能部品についてまとめます。

# サブネット

サブネットはVPC内に構成するネットワークセグメント（分割したネットワーク）のことです。
1つのVPCに対して1つ以上のサブネットで構成されます。

# インターネットゲートウェイ

インターネットゲートウェイは、インターネットへアクセスするための出入口のことです。
例えばEC2からインターネットへアクセスしたいときに必要です。

# ルートテーブル

ルートテーブルは、サブネットに設定する通信の経路表のことです。
例えば、サブネット内のEC2から発信した通信（宛先IPアドレス）がどのターゲットに向けて送られるかを決定します。なお、ルートテーブルのlocalはVPC内の内部リソースを表した表記です。

(例)ルートテーブルの例

| 送信先       | ターゲット            |
|:-----------:|:------------------:|
| 10.0.0.0/24 | local              |

# パブリックサブネットとプライベートサブネット

サブネットにはパブリックサブネットとプライベートサブネットという呼び方があります。

* パブリックサブネット：ルートテーブルにインターネットゲートウェイへのルーティングが設定されているサブネットのことです。つまり、インターネットと直接通信ができるネットワークのことです。なお、ルートテーブルの0.0.0.0/0はすべてのIPアドレスを表した表記です。

(例)パブリックサブネット用のルートテーブルの例

| 送信先       | ターゲット            |
|:-----------:|:------------------:|
| 10.0.0.0/24 | local              |
| 0.0.0.0/0   | インターネットゲートウェイ |

* プライベートサブネット：ルートテーブルにインターネットゲートウェイへのルーティングが設定されていないサブネットのことです。つまり、インターネットと直接通信ができないネットワークのことです。

(例)プライベートサブネット用のルートテーブルの例

| 送信先       | ターゲット      |
|:-----------:|:------------:|
| 10.0.0.0/24 | local        |

# NATゲートウェイ

プライベートサブネットに配置したインスタンスがインターネットへ接続する場合に使うサービスです。
例えば、プライベートサブネットに配置されたEC2がOSアップデートを実施したいときなどに使います。ルートテーブルは下記のとおり設定します。

(例)NATゲートウェイを利用する場合のルートテーブルの例

| 送信先       | ターゲット      |
|:-----------:|:------------:|
| 10.0.0.0/24 | local        |
| 0.0.0.0/0   | NATゲートウェイ  |

# おわりに

今回はVPCの一部（基本の中の基本）をまとめました。
次回はセキュリティグループとネットワークACLについて学習します。

ありがとうございました。

# 参考

* [BlackBelt](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/)
p5.jsの関数まとめ part.8 line()

この記事は Qiita p5js アドベントカレンダー9日目の記事です。

## これはなに
p5.jsが用意している関数について理解を深める記事です。
今回はShapeのline()について。

## line()
文字通り、canvasに線を描画するための関数です。

### リファレンスより
> スクリーンに線（2点間の直接の経路）を描画します。パラメータを4つだけ指定して呼び出すと、デフォルトで1ピクセルの幅で2Dの線を描画します。この幅は、strokeWeight()関数を使って変更することができます。線は塗りつぶすことができないので、fill()関数は線の色に影響を与えません。したがって、線に色をつけるには、stroke()関数を使います。（DeepL翻訳）

stroke()なんかも話題に出そうとしていたのですが、リファレンスがご丁寧でした。

ちなみにfill()とは矩形（rect()）の中の色を指定するときに使ったりします。
line()はそもそも線なので、fill()は使えないよということが書かれています。
（rect() の枠線の色を変えたいときにはstroke()を利用する）


### Type
```typescript
line(x1: number, y1: number, x2: number, y2: number): p5;
```
引数
- x1 最初の点のx座標
- y1 最初の点のy座標
- x2 終わりの地点のx座標
- y2 終わりの地点のx座標
２種類の(x, y)をつないで線を作ります。

また引数を６つ渡すと、3番目と6番目がz座標になるようです。

```typescript
 line(x1: number, y1: number, z1: number, x2: number, y2: number, z2: number): p5;
```


### どんな時に使えそうか
[前日に投稿した記事](https://qiita.com/shibuya01055/items/b913105e1e8ba79de9b6)でもline()を使用しています。
自分はそのうちp5で描画したものに音をのせたいと思っているのですが、
line()を使用していろんなパターンのボリュームメーターや波形が作れそうですね。

### 気になった挙動
ここでp5の挙動について注意点を発見しました。

```javascript
function draw() {
  line(0, 0, 100, 100)
  
  stroke('red')
  line(100, 0, 0, 100 )
}
```
上記のように書くことで、１本はデフォルトの黒。２本目は直前にstroke('red')を差し込んでいるため赤になる予定でした。
で、実行してみると。。
![スクリーンショット 2021-12-09 1.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/99c17a50-891d-b3d7-239d-af07b41ed00f.png)

あれ、両方赤だ！

何が起こっているかというと、
1. 色がデフォルト値の黒で１本線が描画される
2. stroke('red')で「線を赤にする！」という命令が下される
3. ２本目の線は赤で描画される

ここまでが1フレームの挙動です。
そして2フレーム目に入ったときに**stroke()の命令が保存されているため、最初の線も赤で描画される**というものでした。
試しにsetup内で`frameRate(1)`を指定したところ最初の線が黒から赤に変わる瞬間がはっきりとわかりました。

```javascript
function setup() {
  createCanvas(600, 600);	
  frameRate(1)
}
```

片方黒にしたい（それぞれに色をつけたい）場合は、各lineの直前にstroke()を実行することで動作します。
これはstrokeWeight()（線の太さ）でも同じことです。

```javascript
function setup() {
  createCanvas(600, 600);	
}

function draw() {
  stroke('black')
  strokeWeight(10)
  line(0, 0, 100, 100)
  
  stroke('red')
  strokeWeight(5)
  line(100, 0, 0, 100 )
}
```

![スクリーンショット 2021-12-09 2.03.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358229/cd944ead-4bf5-f13e-8f9f-2df8bd0bb3f7.png)


## 参考
[p5.js reference | line()](https://p5js.org/reference/#/p5/line)
Ruby サーバーレスフレームワーク "SOULs"

こんにちは！[Volare Advent Calendar 2021](https://qiita.com/advent-calendar/2021/volare)の9日目の記事です。

ちょうど少し前に話題になっていたRubyのサーバーレスフレームワークであるSOULsを触ってみて素晴らしかったので紹介します、、！

今後も少しづつ触っていくので補足していきます。

## SOULsとは
Active RecordとScaffoldやCI/CDが標準装備された、Rubyのサーバーレスフレームワークです。
GCP (Google Cloud Platform) 上で動作します。
オランダ政府より先端研究開発として認定されており、日本人の方が開発されているため[ドキュメント](https://souls.elsoul.nl/ja/)も丁寧です。

## 全体アーキテクチャ
公式ドキュメントに載っているアーキテクチャはこちらになります。

![SOULs 全体アーキテクチャ](https://souls.elsoul.nl/imgs/docs/SOULs-architecture.jpg)


## SOULsを使うことのうまみ
Railsを使わないで、SOULsを使うことで何が得られるねんってことですが並べていきます。

### サーバー管理が不要
SOULsはサーバーレスフレームワークであるため面倒なサーバー管理が不要です。
> SOULs プロジェクトはソフトウェアの開発・運用・保守に関するコストを下げることを目的に立ち上げられました。

公式ドキュメントにこの記載があることから特に重視してることがわかります。

### 高速な開発体験
Railsのメリットとして開発速度が早いというものがあります。
SOULsはこれをActive RecordとScaffoldの採用とファイル生成の自動化によって引き継いでいます。
型定義ファイルからテストファイルまで必要なファイルはすべてModelを元に生成され、ルーティングも自動で行われちゃいます。
![自動生成されるファイル](https://souls.elsoul.nl/imgs/gifs/scaffold-video.gif)

### Rubyの型チェック
SOULs フレームワークでは Ruby 3.0 から登場した RBSとSteep を採用しているため型安全な開発ができます。
タイプミスやカラムの型違いなどのあるあるなミスが防げます。
![型安全なSOULs](https://souls.elsoul.nl/imgs/gifs/rbs-video.gif)

### 自動テスト＆自動デプロイ
デフォルトでGitHub Actionsが使用されるため、悩むことなくテストからデプロイを自動化できます。
また、コマンドでGitHub Actionsの実行状況を見ることができるため、わざわざGitHubに見にいく必要がありません。
![GitHubActions](https://souls.elsoul.nl/imgs/gifs/souls-gh-watch.gif)

## 最後に

また、本記事ではGCPにはデプロイしていませんがこれもGitHubActionsが用意されているので簡単にできます。
RubyにはRuby on JetsというAWSで動作するRubyのサーバーレスフレームワークがあるのですがGCPで運用するのであれば全然SOULsでよさそうな気がします。

コマンドの充実やファイル生成などの自動による高速な開発体験でかつ、Rubocop, RSpec, RBSによって生み出される安全性を兼ね備えたSOULsはサーバーのことを気にせず、ビジネスロジックに集中できます。

また、SOULsは特に本番で運用されることを想定して作られているので業務の際には選択肢の1つに入れるといいかもしれません。

[別の記事](https://qiita.com/sohey/items/85b39da8f6f87296f020)でAPIを立ててみた時の手順をまとめたので気になる方は是非。
AWS CLIで Web サイトを構築、管理、運用する(9日目)

9日目です！

8日目の最後で「セキュリティ設定」の見直しをするとお伝えしましたが、1点、気がついたことがあります！

なんと、アクセスログが取れていません(涙)

たしかに2日目でアクセスログの設定を入れましたが、これは、あくまでも S3 バケットに対するアクセスを記録するログの設定でした。

現在の構成はどうなっていたでしょうか。

そうですね、 CloudFront が前面に出ています。

つまり、現在、 S3 のログにでてくるのは、 CloudFront からのオブジェクト取得アクセス(とその他、AWSからのポーリングだったり、自分でオブジェクトを操作した際など)のみなんですね。

ということで、 CloudFront 側にもアクセスログの設定を入れます。

今回も、 get-distribution-config コマンドと update-distribution コマンドでの操作になります。

# 9日目の要約
CloudFront に対するアクセスログをとるようにするよ！

# AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。

バージョン１
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html

バージョン２
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

# 概要
CloudFront の設定を変更して、アクセスログを S3 バケットに格納するよ

# さあ、やってみよう！
## CloudFront の設定変更を準備する
やはり、基本的には、[6日目](https://qiita.com/hirosys/private/c339bf0d85d4a8ac74e5#cloudfront-%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B%E6%BA%96%E5%82%99)で実施したものと似た内容です。

1. cloudfront get-distribution-config コマンドで現状の設定を取得する
2. ETag の値を確認する
3. 取得した json ファイルに対して、設定変更を加える
4. cloudfront update-distribution コマンドを実行して更新する

この記事では、3と4についてのみ記載します。１と２の実施内容については、6日目の記事をご確認ください。

## 取得した json ファイルに対して設定変更を加える
以下の Logging があることを確認します。

```json
  "Logging": {
    "Enabled": false,
    "IncludeCookies": false,
    "Bucket": "",
    "Prefix": ""
  },
```

以下を参考に書き換えます。

```json
"Logging": {
    "Enabled": true,
    "IncludeCookies": false,
    "Bucket": "<ログ格納用バケット>.s3.amazonaws.com",
    "Prefix": "cloudfront"
  },
```

## cloudfront update-distribution コマンドを実行して更新する
準備ができたら、6日目と同様に cloudfront update-distribution コマンドを実行して、設定変更を行います。

```sh
aws cloudfront update-distribution --id <CloudFront Distribution ID> ¥
--cli-input-json file://distribution_error.json ¥
--if-match 確認したETag の値
```

コマンド実行に成功すると、Distribution の内容が記された json が返されます。
やはり長いので割愛します。

# 動作確認
curl コマンドを実行して独自ドメインのアドレス(CloudFront)に対してアクセスします。

```sh
curl https://<ドメイン名>/
```

その後、ログ用の S３ バケットにログが配信されるまでしばし待ちます。

概ねアクセスから30〜40分程度経過するとログファイルが配信されます。
実際には１時間〜４時間程度かかることも[ある](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#access-logs-timing)ようです。

s3 ls コマンドを実行してログファイルの有無を確認します。

```sh
aws s3 ls s3://<バケットファイル名>
```

以下のように表示されます。

```sh
                   PRE /
                   PRE cloudfront/
```

さらに確認します。

```sh
aws s3 ls s3://<バケットファイル名>/cloudfront/
```

以下のように　gz 形式で圧縮されたログファイルが格納されるようになりました。

```sh
2021-12-08 16:46:00        901 *********.2021-12-08-16.********.gz
```

ファイルを解凍するとテキストファイルが出てきます。ログの形式は、こちらの[開発者ガイド](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#LogFileFormat)の通りです。

# まとめ
これで CloudFront にアクセスがあった際のログが保存されるようになりました。
ログ形式にあるとおり、クライアントのIPアドレスが記録されているので、もしものときの調査に使ったり、アクセス解析などにつかったりができるようになります。

* 今回使ったコマンド
 * (cloudfront get-distribution-config)
 * cloudfront update-distribution
Notionのデータベースをシンプルテーブルに変換する

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2021](https://qiita.com/advent-calendar/2021/notion) 9日目のエントリです。
8日目は[Notionのシンプルテーブルをデータベースに変換する](https://qiita.com/pictiny/items/66fb63bfeca219fcbb2c)でした。

# シンプルテーブルへの変換
[シンプルテーブルからデータベースに変換できることを紹介しました](https://qiita.com/pictiny/items/66fb63bfeca219fcbb2c)が、データベースからシンプルテーブルに変換することもできます。

データベースのメニューから `Turn into simple table` を選択すると、シンプルテーブルに変換できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/24cf9e73-eb9c-8104-82ac-35a13d3160b6.png)
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/a5707cbb-7cea-c38e-9081-c1ddd89ce0d4.png)

# 変換の注意点
データベースからシンプルテーブルへの変換は、データベースの情報が一部失われるため注意が必要です。

![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/de3b0d63-805a-e834-3c3f-f218c81fb1a9.png)

このようなご飯リストのデータベースをシンプルテーブルに変換すると、見た目は変わらずに変換できています。

![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/41c4d198-b54e-a4cc-439a-4bbd11ceccdb.png)

一度変換したシンプルテーブルをもう一度データベースに変換してみます。

![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/7643b47b-431f-1281-34e3-f7ff8cf44829.png)

シンプルテーブルから変換したデータベースのタイトルが全て `Untitled` になります。
また、シンプルテーブルから変換したデータベースはタイトル以外のプロパティタイプが全てTextになるので、プロパティの設定が失われることがあります。

# まとめ
データベースとシンプルテーブルは相互に変換できるので、データベースで情報を整理したあとにシンプルテーブルで表示を整えるような使い方もできます。便利ですね！
Explore - "Easy Procedural Sci-Fi City Tutorial - Blender 2.9 EEVEE Geometry Nodes"

https://www.youtube.com/watch?v=SPHPAgXUnL8

#作業

1. デフォルトのキューブの削除
1. Lightの種類をSunに設定
1. Contact Shadowsをオンにする
1. ライトのStrengthを5に設定
1. Planeを作成
1. ５倍に拡大
1. キューブの作成(これが作られるビル群のテンプレートになる)
1. キューブの底面がPlaneと同じ高さになるように移動
1. キューブをPlaneの範囲外になるように移動
1. Cavityをオンにする
1. 7で作成したキューブの隣にそのコピーを作成
1. 新しい geometry modefierの作成
1. Attribute Randomizeの作成
1. Point Distributeの作成
1. Point Instanceの作成
1. Input -> Point Distribute -> Attribute Randomize -> Point Instanceの順にそれぞれのGeometryを接続していく。
1. Point Instanceの参照オブジェクトを先ほど作成したキューブにする。
1. Join Geometryの作成
1. Input -> Join -> Outputの順に接続
1. 16で作ったのをJoinに接続
1. Point DistributeのDensityを0に設定
1. Randomize Attributeの種類をVectorに変更Attributeを"scale"に設定
1. Randomize Attributeのminを0.05、maxを0.2に設定
1. scaleを適用(ctrl+aを押しscaleを選択)
1. 先ほど作ったキューブの１つをTallBulidingという名前にし、もう片方をSmallBuildingにする。
1. Ambient Occlusoin, Bloom, Screen space reflectionをオンにする。
1. Ambient OcculusionのDistanceを2.5ぐらいに変更

#詰まった場所
1. Cavityの変更の仕方。結果としてはshadingがsolidでないと変更できない。

#知らなかったこと
1. Cavity

#感想
上記のところから先はよくわからなかった。
とりあえず新しくしれたのはPoint Distribute, Randomize Attribute, Point Instance, Join Geometryの４つがどんな作用があるものなのかしれたのでよかった。
LTEモバイルルータGL-XE300(Puli)をRTK基地局にする

###GL-XE300(Puli)
https://www.gl-inet.com/products/gl-xe300/

###概要
USB接続があるLTEモバイルルータを見つけたのでRTK基地局にしてみました。

###他に必要な材料
・u-blox F9Pなど。RTCM3が出せる&UBX-CFG-TMODE3でMODE 1-Survery-inで適度な設定（300s,3m程度？）を入れてセットアップ済み。/dev/ttyACM0でマウントするものとします。
・固定IPのSIM契約（あったほうが楽）

###初期設定
何はともあれネット繋げてsshでログインしないと作業出来ないので、GUIでインターネットに繋ぐ設定やSIMカード周りの設定をして、その他設定→高級機能→Luciをインストールする。

####OSXからssh接続する際
<div>
<details><summary>設定</summary><div>

なんかエラー出て繋げないので、ググったらこの設定で繋がった。

```~/.ssh/config
host 192.168.8.1
    #HostName gl-xe300.local
    HostName 192.168.8.1
    User root
    HostKeyAlgorithms +ssh-rsa
```


</div></details>

###opkg
必要なパッケージを入れる。

```
opkg update
opkg install str2str screen
```

####mDNS教徒の場合
<div>
<details><summary>mDNS教徒の場合</summary><div>

```
$ opkg find avahi-utils
avahi-utils - 0.8-1 - Avahi is an mDNS/DNS-SD (aka RendezVous/Bonjour/ZeroConf)
 implementation (library). It facilitates
 service discovery on a local network -- this means that
 you can plug your laptop or computer into a network and
 instantly be able to view other people who you can chat with,
 find printers to print to or find files being shared.
 This kind of technology is already found in MacOS X
 (branded 'Rendezvous', 'Bonjour' and sometimes 'ZeroConf')
 and is very convenient.
 .
 This packages installs the following avahi utility programs:
 avahi-browse, avahi-publish, avahi-resolve, avahi-set-host-name.
 It also automatically adds the required libavahi-client package.
 For more information please see the avahi documentation.```
$ opkg install libavahi-client
```

</div></details>

###ntrip caster

ntripcasterパッケージはあるけれども、他のマシンの設定をコピペで持ってきてもなぜかkickしちゃうため、str2strで代用。スクリプトをよしなに作る。
ログ取りをしたいとかいう人は-hで詳細ヘルプ確認推奨。

```/root/ntripcaster.sh
screen  -AmdS ntrip str2str -in ntripc_s://:pass@:2100 -
out ntripc_c://user@pass@:2101/base
```

server側はこんな感じ

```/root/ntripserver.sh
str2str -in serial://ttyACM0:115200 -out ntrips://user:p
ass@localhost:2101/base
```

実行権限付与

```sh
chmod +x /root/ntripcaster.sh
chmod +x /root/ntripserver.sh
```

毎回sshで接続するのは大変なので、自動起動するようにする。

```/etc/rc.localの末尾

screen -AmdS caster /root/ntripcaster.sh &
screen -AmdS server /root/ntripserver.sh &
sleep 10
```

ROVERとして運用したい場合

```
str2str \
-in ntrip://[user[:passwd]@]addr[:port][/mntpnt] \
-out serial://ttyACM0:115200
```

###Port開放
今回の場合だとルータの設定画面から、2101をルータに開放するのを忘れずに。

###Inject RTCM 1008
そのうち書く

###ログ取りしたい場合
作ってないけどOpen Loggerどうでしょうか
https://www.switch-science.com/catalog/2716/

#気づいたこと
・バッテリー残量０だとUSB認識しない。
・FTDI等のUSBシリアルに送信するとバグる？
・面倒くさがらずに公式の電源アダプター使おう。
Notionのシンプルテーブルをデータベースに変換する

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2021](https://qiita.com/advent-calendar/2021/notion) 8日目のエントリです。
7日目は[Notionのシンプルテーブルで列の幅を揃える](https://qiita.com/pictiny/items/393756e5235f40fc55df)でした。

# データベースへの変換
シンプルテーブルで表を作っていると、データベースの機能が使いたくなることがあります。
新しくデータベースを作ってシンプルテーブルのコンテンツをコピペしなくても、シンプルテーブルをそのままデータベースに変換することができます。

シンプルテーブル上部のメニューの `…` から `Turn into database` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/77e0f188-017e-2530-841f-64517f8da09a.png)

シンプルテーブルがデータベースに変換されます。

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/1adabc96-b354-0bfb-05dc-b96d4272dc70.png)

行をヘッダーにしているとヘッダーのコンテンツがデータベースのプロパティ名になりますが、ヘッダーがない場合には自動で命名されます。

![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/405e91c6-202b-dcaf-2ebe-8a39b6715f33.png)

また、プロパティタイプは一番左の列がTitleプロパティ、それ以外は全てTextプロパティになります。

# まとめ
シンプルテーブルはあとからデータベースに変換できるので、迷ったときはシンプルテーブルで作っておくとよさそうですね！
SageMaker Studio Lab から Snowflake にシュッとつないで作業開始する

# SageMaker Studio Lab 出ましたね！

SageMaker Studio Lab ついに出ましたね！
Google の Clabo っぽいと話題になりましたが、イマイチGoogleが信用できない皆様には待望の無料Labなんじゃないでしょうか？

まだプライベートプレビュー的な扱いで、利用するにはリクエストが必要ですが、私の場合は比較的早く利用案内のメールが届きましたので、興味のある方はリクエストを投げてみてください。

SageMaker Studio Lab：https://studiolab.sagemaker.aws/

# ログインするとこんな画面です

![SageMaker_Studio_Lab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75613/0d5f9d76-6f65-766c-72d4-fd8784c8ffad.png)

では Start runtime を押して始めていきましょう！
※押すと1分くらいで起動されるようです。Studioより少し早いかな？

# では行ってみましょう

だいたいデータはDWHに入ってることが増えてきてるのかなと思います。
なので、今日は Snowflake にシュッとつないでみましょう。

```
!pip install --upgrade snowflake-connector-python
```

![Untitled_ipynb_-_JupyterLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75613/3055b7f3-b6e8-5550-5618-a65da8b404ce.png)

# シュシュッ

```
import snowflake.connector

user='HOGE_USER'
password='HOGE_PASSWD'
account='hogehoge.ap-northeast-1.aws'

ctx = snowflake.connector.connect(
    user=user,
    password=password,
    account=account
    )
cs = ctx.cursor()
try:
    cs.execute("SELECT current_version()")
    one_row = cs.fetchone()
    print(one_row[0])
finally:
    cs.close()
ctx.close()
```

![Untitled_ipynb__2__-_JupyterLab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75613/837921ba-45e4-e998-c91d-c6c1daba7a68.png)


完璧だ！できてしまった！
メチャクチャ簡単ですね。

# まとめ

SageMaker Studio Lab は無料なので、色々使ってみて、可能性を探してみましょう。
Google Colab と違ってTPUは使えないですし、まだ Colab のほうがハードルが低いかなと思いますが、 選択肢の一つとして持っておいてもいいのかもしれません。

もちろん Snowflake にも繋がります。
cloud9でReactの環境構築

※こちらは既にAWSに登録、またCloud9の環境作成完了していることを前提に
　手順を掲載しております。

#1.Node.js、npm(Node Package Manager)のバージョン確認
cloud9の「Open IDE」をクリックし、開発環境を表示

ターミナルで以下コマンドを入力
それぞれバージョンが表示されればOK

```
node -v
ec2-user:~/environment/react $ node -v
v10.24.1
```

```
ec2-user:~/environment/react $ npm -v
6.14.12
```

#2.yarnのインストール

yarnとは...node.jsのパッケージマネージャ
既にnpmがデフォルトで入っていますが、こちらではnpmより高速で信頼性も高いyarnを利用します。
※より詳しくyarnの利用するメリットについて知りたい方は以下の記事をご参考にして下さい。

https://qiita.com/akitxxx/items/c97ff951ca31298f3f24

```
ec2-user:~/environment/react $ npm i -g yarn

> yarn@1.22.17 preinstall /home/ec2-user/.nvm/versions/node/v10.24.1/lib/node_modules/yarn
> :; (node ./preinstall.js > /dev/null 2>&1 || true)

/home/ec2-user/.nvm/versions/node/v10.24.1/bin/yarn -> /home/ec2-user/.nvm/versions/node/v10.24.1/lib/node_modules/yarn/bin/yarn.js
/home/ec2-user/.nvm/versions/node/v10.24.1/bin/yarnpkg -> /home/ec2-user/.nvm/versions/node/v10.24.1/lib/node_modules/yarn/bin/yarn.js
+ yarn@1.22.17
added 1 package in 0.86s
```

バージョン確認

```
ec2-user:~/environment/react $ yarn -v
1.22.17
ec2-user:~/environment/react $ 
```


#3.create-react-app(コマンドラインツール)のインストール

yarnを使用しグローバルにcreate-react-appのインストールを行う。

```
ec2-user:~/environment/react $ yarn global add create-react-app                                                                           
yarn global v1.22.17
[1/4] Resolving packages...
warning create-react-app > tar-pack > tar@2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Installed "create-react-app@4.0.3" with binaries:
      - create-react-app
Done in 3.49s.
```

4.アプリの作成

「アプリ名」の部分に任意のアプリ名を入力し、以下コマンドでアプリを作成

```
yarn create-react-app アプリ名
```

以上
クリスマスにちなんだブラウザゲームを作ってみた



#はじめに
クリスマスということで、クリスマスにちなんだゲームを作ってみました。
PCとスマートフォンで遊べます。
<font color="Red">※音が出るので注意</font>

#ゲーム説明
タイトル画面でクリックするとツリーがたくさん並んだ画面が表示されるので、その中から<b>飾りのついたツリー</b>だけをクリックして下さい。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="zYdQJvX" data-user="noji505" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/noji505/pen/zYdQJvX">
  Qiita14_game</a> by nojima (<a href="https://codepen.io/noji505">@noji505</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

それでは是非遊んでみてください♪
current で mixer ライブラリが追加された

## 14-current では mixer が新しくなってます

　14-current では mixer コマンドが新しいバージョンに変わっています。
　mixer コマンドが新しくなった、というのは実際には表面的な話で、mixer のユーザーランドライブラリ(/usr/lib/libmixer.so)が新たに作られたのが主要な出来事です。新たなライブラリが出来たため、mixer(8) コマンド(/usr/bin/mixer)はそれを呼び出す形で完全に書き直されました。今まではmixer操作用のユーザーランドライブラリはなかったんですね。

## 新たな mixer ライブラリ/コマンド は FreeBSD Summer of Code 2021 の成果物

　mixer の新たなライブラリ/コマンドの開発は、Google Summer of Codeの FreeBSD 部門の 5つのプロジェクトのうちの一つだったようです。 Google Summer of Code は　Googleが指定した課題をクリアした学生さんに賞金を支払うというイベントですね。

　FreeBSD Summer of Code の mixer プロジェクトのページは以下です。


https://wiki.freebsd.org/SummerOfCode2021Projects/SoundMixerImprovements

## mixerコマンドはこんな感じ

　mixerコマンドを実際に実行してみるとこんな感じです。ボリューム値が0.00〜1.00になってます。

![newmixer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/c0aa0fb5-67e2-d5bd-e844-c6698c7e24f6.png)

　今までの mixer コマンドはこんな感じで各ボリューム値は整数ですね。
　ボリュームの変更も従来と違い、例えば vol 要素のボリュームを変更する場合は

<pre>
左右同じ値(50%)
mixer vol.volume=0.5
左右別指定(40%:60%)
mixer vol.volume=0.4:0.6
</pre>

となります。mute指定する場合は
<pre>
mixr vol.mute=1
</pre>

で、1をセットするとmuteになります。

また -o オプションで、
<pre>
mixer -o > mixersetting
</pre>

で mixer 設定をmixersetting ファイルに保存できます（従来の -s オプションに相当）。
設定を再度 restore するには

<pre>
mixer `cat mixersetting`
</pre>

とします。

細かな使い方は man (man 8 mixer)を参照してください。

https://www.freebsd.org/cgi/man.cgi?query=mixer&apropos=0&sektion=8&manpath=FreeBSD+14.0-current&arch=default&format=html

## ユーザーランドライブラリでプログラミングで扱いやすく

　新たに追加された mixer のユーザーランドライブラリのC言語での使い方は man に書かれています。

![スクリーンショット_2021-12-08_23-11-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/8c1a87cb-145b-addb-f726-b61f111a2ee9.png)

　mixer.hを include して、mixer_open で得られるmixer 構造体に対して操作を行い mixer_close するという感じで操作できるようです。

　実際の書き方は ExAMPLES の項目のコードが参考になります。実際のコードがなによりわかりやすいですね。

![スクリーンショット_2021-12-08_23-12-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/9cc11561-c992-3216-0793-6b216527dbd4.png)

　この man の全体はこちら (man 3 mixer)

https://www.freebsd.org/cgi/man.cgi?query=mixer&apropos=0&sektion=3&manpath=FreeBSD+14.0-current&arch=default&format=html

# FreeBSD Summer of Code 他のプロジェクト

mixer 以外の FreeBSD Summer of Code 2021 のプロジェクトの一覧はこちらです。

https://wiki.freebsd.org/SummerOfCode2021Projects

コンソールで CJK を入力できるようにする Input Method(開発者は中国語圏の人なので日本語は試してなさそうですが）

https://wiki.freebsd.org/SummerOfCode2021Projects/InputMethodInFreeBSDVirtualTerminal

や、XFS を fuse でmountして読めるようにするプロジェクト

https://wiki.freebsd.org/SummerOfCode2021Projects/XFSFUSEImplementation

とか色々おもしろそうです。mixer と違って current にマージされてないので簡単には試せなさそうですが。
[k8s] secretでstringDataを使う時の注意

# 前置き

kubernetesのsecretで、`data`の代わりに`stringData`を使うことで、base64エンコード前の文字列を直接manifestに定義することができます

例えば

```yaml:encode.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  foo: Zm9vZm9vZm9v
  bar: YmFyYmFyYmFy
```

と

```yaml:string.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
stringData:
  foo: foofoofoo
  bar: barbarbar
```

は同じsecretとして扱うことができます

# 注意

base64エンコードする手間が省けるという点では便利な`stringData`ですが、ちょっとおかしな挙動があります

上の`string.yaml`をapplyしてgetすると

```yaml:my-secret
apiVersion: v1
data:
  bar: YmFyYmFyYmFy
  foo: Zm9vZm9vZm9v
--以下省略--
```

このようなdataのsecretが作られます
stringDataがdataに変換されてます

で、`string.yaml`のbarを削除してkubectl applyします

```string.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
stringData:
  foo: foofoofoo
```

apply後にgetすると

```yaml:my-secret
apiVersion: v1
data:
  bar: ""
  foo: Zm9vZm9vZm9v
--以下省略--
```

barに空文字が残ってしまいます
ちなみに`encode.yaml`のほうで同じ操作をすると、ちゃんと`bar`は消えます

更に`stringData`を全部消してkubectl applyしてみます（実際にこういう操作をすることがあるかはさておき）

```yaml:string.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
```

apply後にgetすると

```yaml:my-secret
apiVersion: v1
data:
  bar: ""
  foo: Zm9vZm9vZm9v
--以下省略--
```

もはや空文字にもならない、何も変わらないという
もちろん`encode.yaml`で同じ操作をするとちゃんと全部消えます

# なにこれ
https://github.com/kubernetes/kubernetes/issues/89938
stringDataを受け取ってdataにする処理とkubectl applyの差分処理の間で不整合が起きるみたいですね
バグと言っていいと思いますが、見た感じ今の時点で修正する予定はなさそうです
vimのIdris2プラグインのインストールメモ

本記事はidris2-vimのGitHubリポジトリの[Issue(https://github.com/edwinb/idris2-vim/issues/19)](https://github.com/edwinb/idris2-vim/issues/19)を参考にした.

# 環境
OS: Nix OS 20.09
Editor: vim
Idris2処理系: nixでインストール済み

# インストール

**Idris2処理系がインストールされていることが必要.**

[idris2-vim](https://github.com/edwinb/idris2-vim)を使う.
ただし記事執筆時点での[最新バージョン](https://github.com/edwinb/idris2-vim/tree/964cebee493c85f75796e4f4e6bbb4ac54e2da9e)では動作しなかったため,[古いバージョン](https://github.com/edwinb/idris2-vim/tree/099129e08c89d9526ad092b7980afa355ddaa24c)をインストールした.

※インストール手順を示すが冗長な可能性あり.

筆者の環境ではvimのプラグインマネージャとして[vim-plug](https://github.com/junegunn/vim-plug)を使っている.
通常通り~/.vimrcに下記のコードを追記,vim再起動,:PlugInstall実行,の手順でインストールする.

```vimscript
call plug#begin('~/.vim/plugged')
" other plugins ...
Plug 'edwinb/idris2-vim'
" other plugins ...
call plug#end()
```

最新版がインストールされているため,ダウングレードする.

```shell-session
cd ~/.vim/plugged/
rm -rf idris2-vim
git clone https://github.com/edwinb/idris2-vim
cd idris2-vim
git reset --hard 099129e08c89d9526ad092b7980afa355ddaa24c
```

# インストール確認
~/.vimrc に追記.

```vimscript
let maplocalleader="."
```

vimでhello.idrを開いて次のコードを打ち込む.

```haskell
module Main

main : IO ()
main = putStrLn "Hello World"
```

ノーマルモードでputStrLnにカーソルを移動して .t とキーをタイプする.
putStrLnの型が次のように表示されれば成功のはず.

```
Prelude.putStrLn : HasIO io => String -> io ()
```
Laravel8.x テンプレートのcomposerライブラリについて調べてみた

[株式会社やどかり](http://www.yadokari.tv/)のニシカワです
よくお世話になっているQiitaですが、記事の投稿は初です

[やどかり&ネッコス Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yadokari_qiita)の9日目を担当します

#自己紹介
やどかりに入社していつの間にか半年経っていました
業務では主にPHP,Laravelを使ってWebアプリやLINEのミニアプリなどの開発を行なっています
最近はコーディングだけではなく設計から関わることも増えてきており、楽しいですが四苦八苦してます

#記事の内容
Laravel8.xにデフォルトでどんなライブラリが入っているのか？
メモ書き程度ですが紹介します。


#今回使用する言語
php 7.4
Laravel 8.73.2

#そもそもcomposerとは何か？

ライブラリやパッケージなどを管理するツール
パッケージの依存関係も考慮してくれるので超便利！


#デフォルトで記述されているもの
早速ですが、laravel8.73.2をインストールした際にcomposer.jsonにデフォルトで記述されているパッケージやライブラリがこちら

````json:composer.json
    "require": {
        "fruitcake/laravel-cors": "^2.0",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/sanctum": "^2.11",
        "laravel/tinker": "^2.5",
    },
    "require-dev": {
        "facade/ignition": "^2.5",
        "fakerphp/faker": "^1.9.1",
        "laravel/sail": "^1.0.1",
        "mockery/mockery": "^1.4.4",
        "nunomaduro/collision": "^5.10",
        "phpunit/phpunit": "^9.5.10"
    },
````
※require-devには本番環境で必要のない開発環境用のパッケージを記述します。

#本番環境で使うやつ
````
fruitcake/laravel-cors
````
クロスヘッダーオリジンなどの設定で使用
APIなどのアプリケーションリソースに外部からのアクセスを受け入れるためのCORSヘッダーを設定できる

````
guzzlehttp/guzzle
````
HTTPクライアント
HTTPリクエストを投げられる
GETやPOSTなどのHTTPリクエストを様々なオプションとともに生成し、レスポンスも取得できる

````
laravel/sanctum
````
SPA(シングルページアプリケーション)
モバイルアプリケーション
などシンプルなトークンベースのAPIに軽い認証システムを提供する

````
laravel/tinker
````
対話型コンソール(コマンドプロンプトやターミナルのようなもの)
キーボードから打ち込まれた命令を
読み込み(Read)
評価・実行し(Eval)
結果を画面に表示し(Print)
また命令待ちの状態に戻る(Loop)処理

#開発環境で使うやつ
````
facade/ignition
````
エラー表示ツール
OSコマンドの実行ができる
※2.5.1以下は脆弱性あり
↓このエラー画面を表示をしていたのはこのパッケージだったのか。。
![スクリーンショット 2021-12-08 23.33.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2319173/4fed930b-abb0-e80c-a03f-bdf78b63c73f.png)

````
fakerphp/faker
````
fzaninotto/Faker の後継らしい
ダミーデータを生成するPHPライブラリ
ランダムデータ生成は単体テストに使えそう

````
laravel/sail
````
laravelをdocker開発環境で動作させるためのツール
laravelを動作させるための一通りの仕組みが構築され、簡単にdockerで開発環境を構築する事ができる

````
mockery/mockery
````
PHPUnit(後述)やPHPSpecなどのテストフレームワークと一緒にユニットテストで使用できる
存在しないClassを代替してテストを進めるためのツール

````
nunomaduro/collision
````
エラーレポートを見やすくできる
Laravel ArtisanとPHPUnitをサポートしている
↓こんな感じで表示される
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2319173/c179085d-a254-2634-8c93-86fd29211ee6.png)


````
phpunit/phpunit
````
単体テストを行うためのフレームワーク

#おまけ
せっかくなので実際に業務で使ったライブラリも１つ紹介します

````
linecorp/line-bot-sdk
````
LINEbotのSDK
ライブラリ、ツール、およびサンプルが含まれている
SDKを使えば、Messaging APIを組み込んだボットアプリの開発を簡単に始めることができる
MySQLのAurora化でMyISAMがなくなって苦戦した話

あるシステムで、MySQLをオンプレからAuroraに移行してテストしたところ、異常発生した際に操作ログ保存用のテーブルにレコードが保存されなくなったことが判明。

原因を調べたところ、MyISAMテーブルがInnoDBテーブルに変わっていたことが判明。
AuroraはMyISAMテーブルをサポートしていないので、移行時にInnoDBに変わってしまっていた模様。

これによって、トランザクション制御が効いてロールバックされるようになっていた。
（MyISAMテーブルはトランザクションの概念がないため、常に自動コミット同様となる）

つまり、ログ保存用のテーブルに書き込んだあとに異常発生時はロールバックしていたため、ログもロールバックされていた・・・（ログの意味無し！）。

が、単純にトランザクションのタイミングをずらそうとすると、ログテーブルへの書き込み前後両方でトランザクションテーブル（これは逆にまとめてロールバック必要）に書き込みしている箇所も多々あり、ずらすこともできない。

1.トランザクション開始
2.テーブルA更新
3.操作ログテーブル登録（もとはMyISAMテーブルなので、異常でもロールバックされなかった）
4.テーブルB更新
5.正常ならコミット、 異常ならロールバック（3も含めてロールバック、、、）

２～４の処理順変えるのも困難なコードだったので、これは詰み？

かと思ったが、よくよく考えれば、ログテーブル登録だけコネクションを別にすれば解決だった。

1.トランザクション開始
2.テーブルA更新
3.別コネクションで操作ログテーブル登録（この時点でコミットされるので、5でロールバックされても無関係）
4.テーブルB更新
5.正常ならコミット、 異常ならロールバック（2と4だけがちゃんとロールバックされる）


ただ、もうちょっとマシな方法ないのか、これ。。
PowerAppsPortalシリーズ_①_ポータルの概要

#ポータルとは
モデル駆動型アプリおよびキャンバスアプリは、ビジネス機能をユーザーに提供します。 Power Apps ポータルは、コミュニティ、顧客、パートナー、従業員など、Microsoft Dataverse の対象者を社内および社外へと拡張します。ローコードで、レスポンシブなサイトを外部ユーザー向けに公開できるウェブサイトを管理・構築できるサービスとなっています。
##モダンなビジネス
業務では既に Power Apps アプリが使用されています。 Power Apps ポータルを利用すれば、以下の機能を追加できます。

* セルフサービス サポートの提供 
 * ビジネスが成長しているとき、コール センターのスタッフを増員する代わりに、Power Apps ポータルを使用して、セルフサービス機能を Web サイトに追加できます。これにより、顧客はスタッフと対話を一切行わずに、ナレッジ記事の検索、他の顧客との対話、回答の取得、必要に応じたサポート案件の作成 (Dynamics 365 Customer Service に直接送信される) ができるようになります。
* 営業パイプラインの構築 
 * リードが企業の Web サイトの お問い合わせ フォームに入力すると、この情報が Dynamics 365 Sales に記録され、自動的に営業パイプラインの一部になります。
* 従業員の強化
 * 従業員に新しいコンピューターが必要になったときは、オンライン フォームに入力を行うことができます。この情報は Dataverse に記録されるため、ヘルプデスクのスタッフはその情報に直ちにアクセスし、対応できるようになります。
* モバイル従業員の強化
 * エージェントがどこでも、どのデバイスからでも作業できるようにします。 現場の技術者は、列内の作業指示書を処理し、完了して、即座に Dynamics 365 Field Service を更新できます。

##Power Apps ポータルテンプレート
* コミュニティ ポータル
 * 内部または外部の利害関係者とコミュニティを作成したい場合、ブログ、フォーラム、および投票を共有するための優れた方法です。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/0267f84c-b585-7bff-38ef-fae4cf119f5f.png)
* 顧客セルフサービス ポータル
 * サポート案件管理を可能にすることを目的としています。
この機能の目的は、顧客が電話をかける代わりにポータルを使用して独自のサポート案件を作成できるようにすることです。これらのサポート案件はDynamics 365カスタマーサービスに直接結び付けられ、エージェントと利害関係者の間のシームレスなコミュニケーションを可能にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/9344e5d6-47f4-f3ce-1d8b-754d7b60d195.png)

* パートナー ポータル
 * 連携するベンダーと顧客のパイプラインを管理する場合に、リードと機会を管理します。 Dynamics365フィールドサービスまたはプロジェクト操作を利用してポータルでプロジェクトと作業指示を公開する場合に有効にできる追加のコンポーネントもあります。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/43cdf438-e17b-64c2-59ff-1e6d80b531ed.png)

* 従業員セルフサービス ポータル
 * 社内スタッフは知識記事を活用して特定の質問や問題の解決策を見つけることができます。同様に、このテンプレートをカスタマイズして、経費報告書を提出して時間を短縮し、情報を適切に提出するなど、特定のビジネスプロセスを合理化することができます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/6c4d603c-ff3b-95ef-bb7a-926c19d0ed25.png)

* カスタマー ポータル
 * B2B販売注文処理および関連シナリオのためにD365サプライチェーン管理環境に接続された外部向けのWebサイトを作成できます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/faa15712-44ed-e0b7-5a87-ab38fc6276ce.png)

* Field Service ポータル
 * 顧客にメールと SMS による最新情報、ETA、次のサービス訪問に関する技術者の場所をリアルタイムで提供します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2307534/99f24557-1c2c-b7e7-6d50-b1927b5d3aeb.png)

* Communityポータル
 つい最近Previewで公開された新機能、アイデアやフォーラムの機能が提供されます。詳細は以下になります。
 https://docs.microsoft.com/ja-jp/dynamics365/customer-service/community-overview 

Power Apps ポータルの概要を簡単に説明しましたが、次回からPower Apps ポータルに対して、開発方法、運用方法、最新の技術点などを紹介していきます。
[SwiftUI] iOS13では、SwiftUIは使わないべきだと思った理由７選

# iOS13の場合、ピュアSwiftUIだとなかなか厄介なことが多い
iOS13の場合、ピュアSwiftUIでアプリを作成しようと思うと、厄介なことが多い。
絶対に使うであろうコンポーネントがない...
Property Wrappersが少ない...


## ・@StateObjectがない。
これが1番のデメリット。
複数のViewで変数を共有したり、変数が更新されるとViewを再描画できるProperty WrappersでiOS13では、@StateObjectがないので、@ObservedObjectを使う。
@ObservedObjectは、Viewが再描画されると、インスタンスは破棄され、再生成される。
@StateObjectは、Viewが再描画されると、インスタンスは破棄されても、再描画された後も維持され、再利用される。


[What’s the difference between @StateObject and @ObservedObject?](https://www.donnywals.com/whats-the-difference-between-stateobject-and-observedobject/)

@ObservedObjectだと、viewが再描画された時に、クラスが再作成され続け、すごく厄介。


## ・toolbarが使えない。
navigationBarTitleには画像を選択できないので、navigation barに画像を載せるのに一苦労する。
SwiftUIXや自作navigation barを使って対策は練るなどで一応対応はできる。

## ・フルスクリーンモーダルがない
iOS14からフルスクリーンモーダル（fullScreenCover）が用意されている。
https://developer.apple.com/documentation/swiftui/view/fullscreencover(ispresented:ondismiss:content:)

## ・LazyVStack系がない
LazyVStack系だと、大量のデータを表示する際に、遅延読み込みして、表示させることでパフォーマンスが向上する。
しかし、iOS13にはない。

## ・グリッドが作れない
iOS14からのLazyVGridでグリッドを実現できる。
iOS13では、collection viewのようなグリッドが実現できない。自作viewかライブラリでグリッドを実現するしか選択肢がない。

有名どころにQGridがある
https://github.com/Q-Mobile/QGrid

しかし、 ScrollViewの中にグリッドを置きたい時にグリッドの高さを指定しなければいけなかったりなど、厄介なところがある。

縦スクロールする画面（scrollview）の中に、LazyVStack と QGridがある場合、
LazyVGridは、Grid全体かcellの高さを決めなくても、高さは自動的に決めてくれるので便利。それは、子要素（cell）が表示されたときにのみシステムがジオメトリを計算するから自動的にやってくれる。

しかしながら、QGridでは、Grid全体の高さを決めないと、表示されない。
cellの高さと数を下に、Gridの高さを計算して、gridの高さを決めないといけないから大変。


```swift
ex) このような場合

// QGrid

// QGridの高さを計算
init() {
    let rowCount = ceil(Double(stubDatas.count) / 2) // 列の数
    gridHeight = CGFloat(rowCount * 170) // 列の数 × cellの高さ でgrid全体の高さを求める。
}

ScrollView(showsIndicators: false) {
    VStack{
        VStack{
            QGrid(self.datas,
                columns: 2,
                isScrollable: false
            ) { homeInfomation in
                HomeInfomationCell(homeInfomation: homeInfomation)
            }
        }
    }
    .frame(height: 200)  // ---- 固定version ここで高さを決めないといけない。 -------------
//    .frame(height:　gridHeight)　// --- 可変version gridの高さをcellの数で固定にする場合 ------
    .padding(.horizontal, 16)
}


// LazyVGrid
ScrollView(showsIndicators: false) {
    LazyVGrid(columns: columns, spacing: 20) {
        ForEach(datas) { homeInfomation in
            HomeInfomationCell(homeInfomation: homeInfomation)
        }
    }
}
```

## ・ProgressViewがない
iOS13でも自作で作っている記事などネット上に存在するが、他のバージョンだとレイアウト崩れが起きるなどの問題が発生し、厄介。


## ・ヒーローアニメーションがやりにくい
このようなアニメーション
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1322570/5cb1010c-ab32-c30f-0b56-093b54a0bf57.gif)


iOS14からだと、matchedGeometryEffectを使うことで、ビュー階層の2つの異なる部分に同じビューが表示されていて、それらの間でアニメーション化することができる。
https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)


https://www.hackingwithswift.com/quick-start/swiftui/how-to-synchronize-animations-from-one-view-to-another-with-matchedgeometryeffect
SNSに共有するURLを作成仕方

# はじめに
初めまして、ダットです！４ヶ月前にSNS関連な新機能を実装しました。具体的には、ユーザーはアンケートを答えてからその結果をソーシャル・ネットワーキング・サービス（SNS）に投稿できる機能です。全部のSNSに対象ではなくLINEやTwitterやFacebookなどの現在流行っているSNSだけで十分です。目的は認知度を上げることでした。<br>
では、SNSに共有したい場合どうすればいいのかちょっと調べました。結局、共有するURLを作成する方法にしました。理由としては実装も軽くてユーザーは一回押すとURLとコンテンツとも一緒に投稿できるのでユーザーにとっては便利だと判断しました。
# 概要
簡単にいえば、コピぺしなくても共有したいURLを即時に共有できるものです。SNSによって共有できるものも変わりますが、せめて導入したいURLを共有できるはずです。
その共有URLをボタンにしてページに置くと済みます。ユーザーはそういうボタンを押すだけで即時に自分のSNSに投稿できるようになります。
具体的にはこういう感じですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539197/1dcf2337-6823-d5c3-4d6e-ec2ea3f1d6d7.png)
# 実装
全部のSNSの共有するURLを紹介しなくて人気があるものだけ紹介させていただきます。:clap:
### Facebook（フェイスブック）
Facebookの共有できるものはURLだけです。ユーザは押すとシェアする画面に入って自分好きなコンテンツを適当に入力できる仕様です。

`https://www.facebook.com/sharer.php?u=[url]`

**注意：**`[url]`は共有したいURLです。
例をすると[これ](https://www.facebook.com/sharer.php?u=https://couplink.jp)を押すと私のウェッブURLをFacebookに投稿できるはずですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539197/0de24c8f-8315-81f9-3de5-fc48b6b689c3.png)

### Twitter（ツイッター）
Twitterの方がFacebookよりたくさんの情報をURLと一緒に共有できます。記事の内容も投稿できるしハッシュタグも含められます。具体的にはこの形式です。

`https://twitter.com/intent/tweet?url=[url]&text=[text]&hashtags=[hashtags]`

**注意：**`[url]`は共有したいURLで`[text]`は共有したいコンテンツで`[hashtags]`はハッシュタグです。なお、コンテンツの長さは制限があります。最大限は280文字ですが、日本語文字は二倍になるため140になってしまうのでご注意ください。

例を出すと[これ](https://twitter.com/share?url=https://couplink.jp&text=初めまして！&hashtags=CoupLink)を押すと全部の情報をすぐに投稿できます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539197/000b1624-160e-91ea-384a-fced9df97392.png)

### LINE（ライン）
LINEは以上の二つと違うことがあります。パソコンとモバイルで共有するときURLは異なってますので分岐する必要があるのです。そうしないと不具合が発生するはずです。

#### モバイル

`https://line.me/R/share?text=[text-url]`

**注意：**`text-url`はテキストとURLを混じってる共有する内容です。パラメータは`text`しかないですが、その中にURLを含めてもいいので大丈夫です。

#### パソコン

`https://social-plugins.line.me/lineit/share?url=[url]&text=[text]`

**注意：**`[url]`は共有したいURLで`[text]`は共有したいコンテンツです。

例を出すと[これ](https://social-plugins.line.me/lineit/share?url=https://couplink.jp&text=はじめまして)を押すとLINEに投稿できるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539197/4bdbf53b-9cb6-6b3f-4393-f79c6968f592.png)

# 終わりに
以上は私が体験した内容なので間違ったところがあればお気軽に教えてくださいませ。この記事はあなたに何か役立つなら幸いです。興味があったら私たちの機能を試してもらえればと思います。`マッチング戦闘力診断`です！

登録しなくても体験できますのでぜひ診断を受けてみてください。よかったら[これ](https://couplink.jp/matching_power_diagnosis)を:point_left: