OmniAICreator/Qiita-1.07M huggingface dataset:
httpでpostしたデータをmqttでpublishする

# はじめに

zabbixのwebhookから通知されたアラートをmqttでばらまきたくて、httpでpostされたjsonデータをmqttでpublishする簡単なプログラムを書いてみました。

# websocketではなくmqttにした理由

mqttをつかったことがなく、使ってみたかったから

# 実装

pythonで実装します。flaskとpaho-mqttが必要なのでインストールします。

```bash
$ pip install flask paho-mqtt
```

topic, payload, client_idがjsonでPOSTされてきたときmqttでpublishするようコーディングします。

```python:http_publisher.py
from flask import Flask, request
import paho.mqtt.publish as publish

app = Flask(__name__)

BROKER = 'localhost'
PORT = 1883


@app.route('/', methods=["POST"])
def send():
    data = request.json
    if data and 'topic' in data and 'payload' in data and 'client_id' in data:
        try:
            publish.single(
                data["topic"],
                data["payload"],
                hostname=BROKER,
                port=PORT,
                client_id=data['client_id'],
            )
        except Exception as e:
            print(e)
            raise e
        return data
    else:
        return "Bad Request", 400


if __name__ == '__main__':
    app.run()
```

# 動作確認

[ここ](https://qiita.com/pyjackal/items/3631e540ade75b20469c)で作ったコンテナとsubscriber.pyを使って動作確認してみます。

### コンテナ起動

```bash
$ docker run -it -d -p 1883:1883 -p 9001:9001 -v $PWD/mosquitto.conf:/mosquitto/config/mosquitto.conf eclipse-mosquitto
```

### subscriber起動

```bash
$ python subscriber.py
Connected to MQTT Broker!
```

### http_publisher起動

```bash
$ python http_publisher.py
 * Serving Flask app 'http_publisher' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployme                                                                                                                                   nt.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

### データをPOST

```bash
$ curl -X POST -H 'Content-Type:application/json' -d '{"topic":"pyjackal/mqtt", "payload":"hello world!!", "client_id": "publisher1"}' http://127.0.0.1:5000/
{"client_id":"publisher1","payload":"hello world!!","topic":"pyjackal/mqtt"}
$
```

無事受け取れました

```bash
$ python subscriber.py
Connected to MQTT Broker!
Received `hello world!!` from `pyjackal/mqtt` topic
```

実運用するには認証とかリクエストが集中した時の挙動とか考慮しなければならないことがいろいろありますが、やりたいことはできそうです。
JavaScriptとjQueryの相互変換早見表

# JavaScript ⇔ jQuery 早見表

忘れがちなやつをメモ。正確にはイコールではないが。少しずつ書き足していこう。

|変換内容|JavaScript|jQuery|
|:------|:------|:------|
|ID指定|[document.getElementById('foo')](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)<br>[document.querySelector('#foo')](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector)|$('#foo')|
|Class指定|[document.getElementsByClassName('foo')](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName)<br>[document.querySelector('.foo')](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector)|$('.foo')|
|タグ指定|[document.getElementsByTagName('tag')](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByTagName)|$('tag')|
|イベント設定|[target.addEventListener('event', callback)](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener)|$(target).on('event', callback)|
|属性設定|[target.setAttribute(name, value)](https://developer.mozilla.org/ja/docs/Web/API/Element/setAttribute)|$(target).attr(name, value)|
|テキスト取得|[target.textContent](https://developer.mozilla.org/ja/docs/Web/API/Node/textContent)|$(target).text()|
|テキスト設定|[target.textContent = string;](https://developer.mozilla.org/ja/docs/Web/API/Node/textContent)|$(target).text(string)|
Javaを用いて1人麻雀ゲームもどきを作ってみた。

# はじめに
この記事は、Java（8以上）を学習するにあたって試しに作成した麻雀ゲーム（未完成）の内容に関する説明となっています。コードの方はgithub（[https://github.com/watcher041/the_java_work/tree/main/mahjong)）に配置しておりますので、ご参考にどうぞ…。

# ゲームの動作

以降では、コードをご覧いただいている前提で話をしております。

ゲームは「javac Main.java」とコンパイルしていただいて「java Main」とすると遊べます。役が揃うまで牌を捨てるだけのものとなっています。（七対子だとあがれない、点数計算もないです）おおまかな流れといたしましては、

- 卓（卓の画像、壁牌）を作成する
- プレイヤー（手牌、手配の画像）を作成する。このとき、牌をクリックすると手牌が捨てられて壁牌から一枚引いて理牌されるように手牌一つ一つにMouseClickCheckクラスを仕込む。

- 作成したものをもとに画像を表示する

- 手牌をクリックすると、その手牌のMouseClickCheckクラスが動作し、牌を引いた後の手牌を再描写する。これを役が揃うまで繰り返す（できなければ流局）

# 使用しているクラス

- Main：ゲームの全体像を表記しているクラス
- Table：卓上の情報（壁牌の数）を持っているクラス
- Player：プレイヤーに関する情報（手牌）を持っているクラス
- Tile：牌の情報を持っているクラス（列挙型）
- MouseClickCheck：どの牌を捨てたか識別するためのクラス
Ruby で解く AtCoder ABC 227 D

# はじめに
*[AtCoder Problems](https://kenkoooo.com/atcoder/#/)* の Recommendation を利用して、過去の問題を解いています。
AtCoder さん、AtCoder Problems さん、ありがとうございます。

# 今回のお題
*[AtCoder Beginner Contest D - Project Planning](https://atcoder.jp/contests/abc227/tasks/abc227_d)*
<font color="blue">Difficulty: 1643</font>

今回のテーマ、二分探索　＋　鳩ノ巣原理

青レートは難しいですが、解いてみました。
# Ruby
```ruby
n, k = gets.split.map(&:to_i)
a = gets.split.map(&:to_i).sort
b =[0]
n.times do |i|
  b[i + 1] = b[i] + a[i]
end
ans = (0..).bsearch do |x|
  c = a.bsearch_index{ _1 >= x } || n
  b[c] + x * (n - c) < k * x
end
puts ans - 1
```
まず、`1 つのプロジェクトは K 個の相異なる部署から 1 人ずつ選出`となっていますので、`鳩ノ巣原理`より、各部署より選出できる人数は、作成するプロジェクト数が上限となります。
![20211119a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/c4429a09-2a3a-10e3-48fd-70ae9cb84196.png)

```ruby
# あらかじめ累積和を作成
b =[0]
n.times do |i|
  b[i + 1] = b[i] + a[i]
end

# プロジェクトに選出できる人数を計算
  c = a.bsearch_index{ _1 >= x } || n
  b[c] + x * (n - c)
```
次に、プロジェクト数の最大を求めますが、各部署の社員が最大`10の12乗`人所属していますので、先頭から順番に探索しては`TLE`になってしまいます。
そこで、`二分探索`の登場となります。

```ruby
ans = (0..).bsearch do |x|
```
ここで、上限をうまく設定しないと`WA`に~~なった~~なりますのが、`Ruby`ではハッピーな書き方があり、二分探索の威力もあって気楽にコーディングできます。

||Ruby|
|:--:|:--:|
|コード長 (Byte)|233|
|実行時間 (ms)|146|
|メモリ (KB)|33588|
# まとめ
+ ABC 227 D を解いた
Vue.jsのエラー「Elements in iteration expect to have 'v-bind:key' directives  vue/require-v-for-key」の解決方法

#エラー内容
`v-for`タグを使ったら、
`Elements in iteration expect to have 'v-bind:key' directives  vue/require-v-for-key`
が発生

#エラー原因
`v-bind:`を使って、キー属性を指定してください とのこと

#解決方法
    # 元コード
        <tr v-for="(item,key) in data.fire_data">
    
    # 解決コード
        <tr v-for="(item,key) in data.fire_data" v-bind:key='key'>
SwiftUIの@EnvironmentObjectを使ってみる

## 概要
`@EnvironemtObject`についてまとめます。

## 環境
`macOS Big Sur 11.6`
`Xcode 13.1`

## 公式より
公式より和訳した文章を添付します。

:::note info
親ビューまたは祖先ビューによって提供される監視可能なオブジェクトのプロパティラッパータイプ。
:::

:::note info
環境オブジェクトは、監視可能なオブジェクトが変更されるたびに現在のビューを無効にします。
:::

:::note info
プロパティを環境オブジェクトとして宣言する場合は、environmentObject（_ :)修飾子を呼び出して、対応するモデルオブジェクトを祖先ビューに設定してください。

:::

https://developer.apple.com/documentation/swiftui/environmentobject

## `@EnvironmentObject`を使ってみる
以下の手順で実際に使ってみます。
1. モデルを定義する
1. 全てのViewからモデルにアクセスできるようにする
2. モデルの変更でViewが自動で更新されるようにする

### 1. モデルを定義する
プロパティの変更を監視できるように`ObsavableObjec`プロトコルに準拠させます。
`Counter`クラスの`number`プロパティの値を監視できるように`@Published`を宣言します。

```swift:Models/Counter.swift
class Counter: ObservableObject {
    @Published var number: Int = 0
}
```

### 2. 全てのViewからアクセスできるように設定する
今回はルートViewにあたる`プロジェクト名App.swift`に設定を行います。
`environmentObject(_:)`モディファーを使います。

```swift:プロジェクト名App.swift
@main
struct XXXApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(Counter())
        }
    }
}
```

### 3. モデルの変更を検知してViewを自動で更新させる
`@EnvironmentObject`で監視可能なクラスを宣言します。

```swift:ContentView.swift
struct ContentView: View {
    @EnvironmentObject var counter: Counter
    
    var body: some View {
        VStack {
            Text(String(counter.number))
            
            Button("Count Up") {
                counter.number += 1
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(Counter())
    }
}
```

## 動作確認
完成すると以下のような動作になると思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/a629f4f0-6a04-db22-0c0d-4cf77590bc3c.gif" width="400" />

## 参考リンク

https://capibara1969.com/3119/

https://developer.apple.com/documentation/swiftui/environmentobject
grid_mapを使ってみる(1)

grid mapの使い方を調べました。
ここでは,インストールとサンプルを1つ動作させます。

https://github.com/ANYbotics/grid_map

## ROS

- noetic

## Install

```
sudo apt install ros-noetic-grid-map*
```

## サンプル

READMEに乗っていた最初のサンプルを実行して見ます.

```
roslaunch grid_map_demos simple_demo.launch
```

実行すると以下のように波打ったgrid mapが表示されました.

![Screenshot from 2021-11-19 06-35-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/cf8fc389-70e0-33e5-7bd0-a6c44db7df71.png)


launchファイルの中身は以下のようになっていました.

```xml:simple_demo.launch
<launch>
  <!-- Launch the grid map simple demo node -->
  <node pkg="grid_map_demos" type="simple_demo" name="grid_map_simple_demo" output="screen" />
  <!-- Launch the grid map visualizer -->
  <node pkg="grid_map_visualization" type="grid_map_visualization" name="grid_map_visualization" output="screen">
    <rosparam command="load" file="$(find grid_map_demos)/config/simple_demo.yaml" />
  </node>
  <!-- Launch RViz with the demo configuration -->
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(find grid_map_demos)/rviz/grid_map_demo.rviz" />
</launch>
```

launchファイルのコードから`simple_demo`と`grid_map_visualization`が実行されていることが分かります。

それぞれのノードの役割とトピックについてまとめると以下のようになります。

- `simple_demo` : `grid mapを作成し配信するノード`

 - Pub:`grid_map[grid_map_msgs/GridMap]`

- `grid_map_visualizatoin` : `grid mapトピックを受け,ROSのPointCloud2などに変換`

 - Sub:`grid_map[nav_msgs/OccupancyGrid]` 
 - Pub:`grid_map_pointcloud[sensor_msgs/PointCloud2]`

# エラー対策

上記launch起動時`image_publisher.py`でエラーが発生.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/422cd0ef-d97b-7dc9-b347-f4d214a0a41b.png)

```
diff --git a/grid_map_demos/scripts/image_publisher.py b/grid_map_demos/scripts/image_publisher.py
index 9c1745d..7b35337 100755
--- a/grid_map_demos/scripts/image_publisher.py
+++ b/grid_map_demos/scripts/image_publisher.py
@@ -40,7 +40,7 @@ def callback(self):
     rosimage.width = img.shape[1]
     rosimage.height = img.shape[0]
     rosimage.step = img.strides[0]
-    rosimage.data = img.tostring()
+    rosimage.data = img.tobytes()
     rosimage.header.stamp = rospy.Time.now()
     rosimage.header.frame_id = 'map'
```

# まとめ

- grid_mapを操作するためのツールが色々用意されている.
- それをPointCloud2などに変換することもできROSとの連携が可能.

# 次回

次回は,画像をgrid mapに変換するデモを動作させた後,
オリジナルの画像をgrid mapとしてrvizに表示します。

https://qiita.com/hoshianaaa/items/a5eb931354a8652f37d4
プリザンターのテーブルで「アプリケーションで問題が発生しました。」と表示され開けなくなった場合の対処方法

## 概要
プリザンターでサーバスクリプトなどを設定した際に、「アプリケーションで問題が発生しました。」と表示されテーブルが開けなくなる事があります。このような状態から回復する方法について記載します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/8d7eeffc-29a5-ee8a-1ac2-31fdc8c39b39.png)

## 手順
1. 対象のテーブルのURLを調べます。テーブルを開かずにマウスオーバーすることでブラウザの左下などでURLを確認することができます。
1. 前の手順で確認したURLの末尾の/indexを除いたURLをブラウザのアドレスバーに直接入力します。URLが「 https://servername/pleasanter/items/2/index 」の場合「 https://servername/pleasanter/items/2 」を入力します。これによりテーブルの管理画面を開くことができます。
1. エラーの問題個所がわかっている場合（サーバスクリプトに構文エラーがあるなど）には、それを取り除き画面下部の更新ボタンをクリックします。
1. 問題個所がわからない場合には、変更履歴から元に戻すことができます。その場合は変更履歴タブを開きます。
1. 元に戻す履歴にチェックを入れ復元ボタンをクリックします。テーブルの設定がエラー発生前の内容に戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/dd627ebd-3916-a484-e7af-fcb0747eb565.png)

## 新バージョンでの回復方法
バージョン 1.2.16.0 以降では、アプリケーションエラーが発生した際に「テーブルの管理」ボタンが表示され、URLを控えることなくテーブルの管理画面に移動できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78230/7747fdb9-c1b7-7b0f-93b9-4eb97a8ea9d6.png)
windowsでiverilog その123

#概要　

windowsでiverilogやってみた。
open-avr試してみた。

#参考にしたページ。

https://github.com/descampsa/open-avr

#サンプルコード


```
module avr_cpu_progmem #(parameter ADDR_WIDTH = 9, parameter DATA_WIDTH = 16, parameter MEM_SIZE = 512) (input clk, input [ADDR_WIDTH - 1:0] addr, output reg [DATA_WIDTH - 1:0] data);
	reg [DATA_WIDTH - 1:0] mem[0:MEM_SIZE - 1];
	always @ (posedge clk)
	begin
		data <= mem[addr];
	end
	initial
	begin
		mem[0] = 16'hEF0F;
		mem[1] = 16'hB904;
		mem[2] = 16'hEF0F;
		mem[3] = 16'hB906;
		mem[4] = 16'hE000;
		mem[5] = 16'hB906;
		mem[6] = 16'hCFFB;
		mem[7] = 16'h0000;
		mem[8] = 16'h0000;
		mem[9] = 16'h0000;
		mem[10] = 16'h0000;
		mem[11] = 16'h0000;
		mem[12] = 16'h0000;
		mem[13] = 16'h0000;
		mem[14] = 16'h0000;
		mem[15] = 16'h0000;
	end
endmodule




module test;
	reg clk;
	reg rst;
	reg [5:0] b;
	reg T0;
	wire [5:0] portb;
	attiny11 u(.clk(clk), .rst(rst), .portb(portb), .T0(T0));
	initial
	begin
		clk = 1;
		rst = 0;
		#2
			rst = 1;
		#2
			rst = 0;
		#80
			$finish;
	end
	always
		#1
			clk = ~clk;
endmodule

```

#実行結果

```
    x 
    0 
    1 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 
    5 
    6 
    7 
    2 
    3 
    4 

```

以上。
外部PCからVirtualBoxのゲストOSにRDP接続したい



:::note warn
2023/2/10 追記：これ構築して1か月後、VirtualBoxが起動できなくなりました。。
ログ見たらskyseaがうんたら。。新しいIPは割り振ってないですが監視されてて怪しいと判断されアプリケーションの利用をブロックされたのかも？
社内で検証環境建てる場合は、ルール決めてる部門に聞かないとですね。。
:::

# やりたいこと
社内で検証用PC上にVirtualBoxでWindowsSever仮想マシン建てて、社内の別PCから自由にリモート接続したい！

# 環境と設定イメージ
見にくくてごめんなさい…
![1637480294659220449689014539867.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1429640/93be70d2-cf22-0da8-18bb-4f33a1b65b95.jpeg)

# 実現方法
ブリッジ設定で仮想マシン建てると社内ネットワークにポっと怪しいPCが出現したみたいに見えるらしい
勝手にやったらネットワーク管理者見つかって怒られそう

じゃあ、NAT+ホストオンリーのポートフォワーディング設定が良さそうかな！

# 設定の構想
外部PCからRDP接続(宛先/ホストIP:3389)
▶▷▶︎▷ホストOSがゲストOSのIPにフォワーディング▷▶︎▷▶︎
ゲストOS接続

としたい

ただ、この方法だとホストOSがスルーされるので外部からホストOSにRDPしたくても、できない気がする

なので

ポートを変えて、下記3つのケース毎に設定を分けてみた。

## 接続ケース
宛先のIPは、ホストOSのWiFiアダプタのIPです。ipv6を無効にしたらホスト名(ホストOSのPC名)でも名前解決できました。

###### ①外部PCからRDP(宛先/ホストIP:3389)▶ホストOS
###### ②外部PCからRDP(宛先/ホストIP:重複しなさそうなポート)▶ホストOS経由▶ゲストOS
###### ③ホストOSからRDP(宛先/ホストIP:3389)▶︎ゲストOS
※②のポートは以降53389で設定する。
※③はホストオンリーアダプタで通信できるので、NATの設定不要だが、今後のためにゲストOS側で既存のRDPポート3389で受診出来る設定は残しておく。

# 手順

#### 1. VirtualBox＞NAT設定＞ポートフォワーディング設定

先程の接続ケース②用のルール追加

##### ②外部▶ゲストOS用RDP接続
名前:Gaibu-guest_RDP_53389
TCP
ホストポート:53389
ゲストポート:53389

> VirtualBox　ゲストOSのWebサーバに外部から接続する
> https://undersourcecode.hatenablog.com/entry/2013/08/11/212246

#### 2. ゲストOSでRDPのレジストリコピー＆ポートを3389以外のポートに変更

1つ目参考ではスクリプトを利用してますが、私は2つ目参考のレジストリエディタから手動で設定しました。

1.regedit起動

2.HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcpのキーを右クリックエクスポート

3.エクスポートしたファイルをテキストエディタで名前とポート番号を編集、保存

 + 編集は、下記ワードを置換する
  - RDP-Tcp→RDP-Tcp-53389
  - 3389→53389
 + 保存時は拡張子が.regになっていることを確認。
 
4.regeditでファイル＞インポートで編集したファイルを指定

5.新しいレジストリが追加されていることを確認

> WindowsサーバでRDPを複数ポートで受け付ける
> https://qiita.com/malbare932/items/dd8c743306d8747384b0
> 【Windows 10】レジストリをバックアップ・復元する
> https://soma-engineering.com/desktop/windows10/backup-restore-registry/2018/10/28/#st-toc-h-2


#### 3. ゲストOSのファイアウォールで受信ルール作成

接続ケース②③用のルール追加

##### ②外部▶ゲストOS用RDP
ポート53389許可
ネットワーク:ドメインのみ
※今回社内NW内のみのため

##### ③ホストOS▶ゲストOS用RDP
ポート3389許可
ネットワーク:ドメインのみ
※既定で存在する設定なのでネットワーク設定をドメインのみに変えておく

> 【リモートワーク自由自在】Windowsリモートデスクトップ接続のポート番号を変更してよりセキュアにする
> https://atmarkit.itmedia.co.jp/ait/articles/0309/27/news003.html

#### 4.最後にゲストOS再起動

# 動作確認

接続ケースの①②が実装されているか動作確認
※③はホストオンリーアダプターにより既に接続出来ているので今回は確認無し。

##### ①別PCからゲストOSにRDP接続

 1.RDP起動

 2.宛先:「ホストOSのIP:53389」or「ホストOSのPC名:53389」
ユーザー情報:ゲストOSのユーザー
 3.入った先がゲストOSか確認

##### ②別PCからホストOSにRDP接続
 1. RDP起動
 2. 宛先「ホストOSのIP」or「ホストOSのPC名」
ユーザー情報:ホストOSのユーザー
 3. 入った先がホストOSか確認

今度はサービスのポートもフォワーディングさせて、ゲストOS上のサーバーと社内の他のサーバーを連携出来る用にしてみたい。

ここまで見てくれてありがとうございました！
UbuntuにプリンタMG4100のドライバをインストール

# はじめに

UbuntuにプリンタMG4100のドライバをインストールする方法をメモしておきます。

# 手順

[Canon公式](https://cweb.canon.jp/drv-upd/ij-mfp/linux-pd-mg4130-360.html)からドライバをダウンロードします。

インストールしようとすると`libpng12-0`と`libtiff4`をインストールしなさいと怒られます。

まずは`libpng12-0`をインストールします。

```shell
sudo apt install libpng12-0
```

次に`libtiff4`をインストールしますが、その前に`multiarch-support`を入れなければいけません。

[ここから`multiarch-support`をダウンロード](http://security.ubuntu.com/ubuntu/pool/main/g/glibc/)して、以下のようにインストールします。

```shell
sudo dpkg -i multiarch-support_2.27-3ubuntu1.4_amd64.deb
```

[ここから`libtiff4`をダウンロード](http://ftp.ksu.edu.tw/FTP/Linux/ubuntu/pool/universe/t/tiff3/)して、以下のようにインストールします。

```shell
sudo dpkg -i libtiff4_3.9.7-2ubuntu1_amd64.deb
```

# 環境
Ubuntu 20.04

# 参考文献
https://cweb.canon.jp/drv-upd/ij-mfp/linux-pd-mg4130-360.html

https://cweb.canon.jp/drv-upd/ij-mfp/linux-sd-mg4130-180.html

http://zorinos.seesaa.net/article/439194037.html
TypescriptのinterfaceでTypeSafeなコードにリファクタしてみた

TypeScriptのInterfaceを定義することで定義したオブジェクトにinterfaceで型を定義してみました


## インターフェースとは

オブジェクトの型に名前をつけて型を定義できるもの

> TypeScriptの核となる基本原則のひとつに、値の型チェックが値が持つ形状に焦点を当てていることがあげられます。 これは、時には"ダックタイピング"または"構造的部分型"と呼ばれます。 TypeScriptでは、インターフェースはこれらの型の名付けの規則を満たし、 また、プロジェクトの外観を構成するだけでなく、コードの構造を定義する強力な方法になります。


## interfaceの定義


:::note info
オブジェクトのプロパティ名にデータ型を定義します
extendsでinterfaceを継承することで継承元のinterfaceを継承先のinterfaceに付与できます
:::
```
export interface AgencyInterface {
  agency_id: number
  name: string
  branch_name: string
  staff_name: string
  ins_ts?: string
}

export interface MathInterface {
  one: number,
  two: number,
  three: number,
} 

export interface AgencyDetailInterface extends AgencyInterface {
  parent_agency_id: number
  prefecture_id: number
  post_code: string
  city: string
  town_address: string
  building: string
  president: string
  staff_email: string
}
```

## クラスにインターフェースを実装する

:::note info
implementsを使用してクラスをinterfaceで実装する
AgencyInterfaceのプロパティをクラスに定義していない場合はコンパイルエラーとなります
:::
> 誰かがあなたのためにinterfaceで宣言したオブジェクト構造に従わなければならないクラスを使いたい場合、互換性を保証するためにimplementsキーワードを使うことができます：

```
class SampleClass implements AgencyInterface {
  name: string
  agency_id: number
  branch_name: string
  staff_name: string
  ins_ts?: string
}
```

## 引数にインターフェースを定義する

:::note info
implementsを使用してクラスをinterfaceで実装する
AgencyInterfaceのプロパティをクラスに定義していない場合はコンパイルエラーとなります
:::
> 誰かがあなたのためにinterfaceで宣言したオブジェクト構造に従わなければならないクラスを使いたい場合、互換性を保証するためにimplementsキーワードを使うことができます：

```
export interface MathInterface {
  sum: number,
} 

function hoge(params:MathInterface){
 return sum
}

// OK
hoge(sum:1);

// BAD コンパイルエラー
hoge(sum:"1");
```

## 最後に

読んでいただきありがとうございます。
今回の記事はいかがでしたか？
・こういう記事が読みたい
・こういうところが良かった
・こうした方が良いのではないか
などなど、率直なご意見を募集しております。
Pryのlsを使うと謎の^A^B^A^Bとかが表示されて格闘した話


## pryを0.14.1に更新したらなんかls機能が正しく動いてない

shellのlsではなく、pryのlsの話です

最後に付け加えていますが、0.14.1だからバグるという話ではないみたいです

## 2023/01/30 追記 0.14.2で修正されました
https://github.com/pry/pry/pull/2235

元はANSIエスケープシーケンス文字を見た目上でちゃんと非表示にするための変更だったようです。
readlineにあるオプションに従って `\001` と `\002` を差し込んだところ、実際には多くの環境で仕様が言っているように消えるどころか、それそのものが文字化け、あるいは正しくない状態で表示されていました。

※ちなみに私の別の環境では `^A^B` ではなくいわゆる豆腐が表示されていました

導入された当時のPRがこちらで、今回 0.14.2 に含まれる形でこのPRをrevertする運びとなったようです。

https://github.com/pry/pry/pull/2154

## 問題の現象

```ruby
pry> ls ActiveRecord::Base
```

pryでページングが必要になるような長いリストを出力されるようなものをlsすると下の画像のような文字化けを起こす

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39804/b6606a0f-dee3-5394-e416-9f62566855f7.png)


## 解決方法

```bash
export PAGER=" less --raw-control-chars -F -X"
```

- 環境変数PAGERにlessをオプション付きで設定する
- lessの直前にある**スペースが とても とても 重要**

[pry/pry Non-Visible Characters Printed with Pager #2185](https://github.com/pry/pry/issues/2185) の [このコメント](https://github.com/pry/pry/issues/2185#issuecomment-945082143) に解決方法を記載してくれている人がいました

### そもそもページング機能いらないよっていう場合


```ruby
# .pryrc

Pry.config.pager = false
```

これで解決できます

lessが必要になりそうな長いリストでも全て表示するため、lessの機能を使わない、かつスクロールが自由にできる端末環境であればぶっちゃけこれでいいと思います

ちなみにless以外のものを使うという選択肢もありますが、色々試してみてそちらでも解決しなかったので今回は記載していません

## 再現手順

```bash
ruby -e 'puts "\u0001\u0002hoge"' | less
```

`^A^Bhoge`

```bash
ruby -e 'puts "\u0001\u0002hoge"' | less --raw-control-chars
```

`hoge`

## 原因

https://github.com/pry/pry/blob/master/lib/pry/pager.rb#L135
抜粋

```ruby
class Pry
  # 略
  class Pager
    # 略
    class SystemPager < NullPager
      def self.default_pager
        pager = Pry::Env['PAGER'] || ''

        # Default to less, and make sure less is being passed the correct
        # options
        pager = "less -R -F -X" if pager.strip.empty? || pager =~ /^less\b/

        pager
      end
    end
  end
end
```

ここでlessにオプションを設定しようとしてPAGERを頑張って書いても、スペースを入れるトリックをやらない限り、
`pager =~ /^less\b/` という無慈悲な正規表現があるためデフォルトに上書きされてしまいます

またlessにおいて `-r` および `-R` と、 `--raw-control-chars` は意味が違うらしく、Pryではデフォルトとして `-R` を採用しているために問題が発生しました
これを環境変数PAGERを工夫して設定することで回避しようというお話でした

PRの方でもっと詳しく解説されているので知りたい方はこちらを参照してください
https://github.com/pry/pry/pull/2207#issue-936203009

## 動作が確認できたlessのバージョンなど

※多分そこまで関係ないけど記録のために残しておきます

MacOSに標準で入っていたless

```
$ less -V
less 487 (POSIX regular expressions)
Copyright (C) 1984-2016  Mark Nudelman
```

Homebrew経由で入れたgnu由来のless

```
$ /usr/local/Cellar/less/590/bin/less -V
less 590 (PCRE2 regular expressions)
Copyright (C) 1984-2021  Mark Nudelman
```

この2つにおいてはとりあえずサポートされていました


## ちなみに問題はpryじゃないかもというお話

`^A` や `^B` といった文字の正体はunicodeにおけるSOHとSTXという制御用文字らしいです
それぞれ `\u0001` と `\u0002` でこの文字を扱うことができます
これがreadlineのバージョンによってサポートされていたりされなかったり、そもそも実行環境に含まれていなかったり、という違いで現象が発生するようです

pry 0.14.1 を名指ししてはいますが、実は問題のPAGERを扱う部分のコードは少なくとも[0.12.2の段階でも存在している](https://github.com/pry/pry/blob/v0.12.2/lib/pry/pager.rb#L129-L139)ため直接的な原因ではないと考えられます
同時期に発売されたMacbook AirとMac Miniで試して、Airの方の環境では再現できなかったためreadlineまわりの環境による影響が大きいと思います

詳しい仕様や理屈については今回深くまで追いませんが、何かこれ関係で問題を発見した人の検索キーワードの助けになれば幸いです
Reactで外部リソースをキャッシュする方法


# React で 外部リソースをキャッシュする方法

## 概要

Http等で外部に問い合わせて取得した値を、View側でキャッシュする方法の解説です。

今回のユースケースは 一文字入力する毎にメンバー検索を行い、サジェッションを表示する場合を考えます。

新しい文字入力はサーバーサイドから取得する必要がありますが、文字を削除した場合は過去に問い合わせた内容を再度リクエストすることになります。

また、検索のView自体は常に表示されている訳ではなく、特定のView内に存在していると過程します。

つまり、新しい検索のキーワードならリクエストする。既知のキーワードなら過去の結果を利用する。

これが出来れば、リクエスト頻度を押さえつつ、ユーザー体験的にも貢献できると言えるでしょう。（リクエストにはどうしても待機時間が発生してしまうため）

## 実装

### キャッシュ機構

内部にマップオブジェクトを作成し、View側にリクエストしたい関数を渡せるようにします。

コメントにもありますが、どこでも利用できてしまうと思わぬ事故が発生しかねない（メモリ圧迫や不整合）ので、
useCallbackを経由させることで、関数コンポーネントからしか呼べないようにしておきます。

```typescript

// マップのデータ構造を使ってキャッシュを行う。
const cacheByMap = <K extends unknown, V extends unknown>(map: Map<K, V>) => async (
  value: K,
  requestFunc: (value: K) => Promise<V>
) => {
  const cache = map;

  const cacheValue = cache.get(value);
  if (!cacheValue) {
    const result = await requestFunc(value);
    cache.set(value, result);
    return result;
  } else {
    return cacheValue;
  }
};

/**
 * 外部へ通信を行う関数の入力値と、出力値をマップでキャッシュすることで、不要なI/Oを削減する関数。
 * 一時的な用途を強制するため, あえてuseCallbackでView専用にし、アンマウントされれば開放されるようにしている。
 * @param initValue
 */
export const useRequestWithCache = <K extends unknown, V extends unknown>(initValue?: Map<K, V>) => {
  return useCallback(cacheByMap<K, V>(initValue ?? new Map<K, V>()), []);
};

```

### 利用する側 (関数コンポーネント)

初めの方で宣言しておき、あとはuseEffect内部などでリクエストする関数(例だと`findMembersByName`)を渡して利用するだけです。

外から利用する側は、キャッシュから取れたか、実際にリクエストしているかは分かりませんが、戻ってきた値を利用すれば良いだけなので、特に考えなくても良いでしょう。

```react

const UserList = ({ userName }: { userName: string }) => {
  const [users, setUsers] = useState<User[]>([]);
  const requestWithCache = useRequestWithCache<string, User[]>();

  useEffect(() => {
    requestWithCache(userName, findMembersByName).then(setUsers);
  }, [userName]);


  return (
    <View>
      <Something />
    </View>
  )
}
```

上記の例ですと、userName に '太' (1文字目)　が渡された場合キャッシュにヒットしませんからサーバーサイドに問い合わせし、ユーザー情報一覧を取得します。 
2文字目 として '太郎' ときた場合も同様にサーバーサイドに問い合わせします。
そこでユーザーが1文字削除し、userName が '太' になった場合、前回の結果を利用した値を返し、サーバーサイドへは問い合わせしません。

そういった形で、地味にリクエスト数を削減 ＆ レスポンスタイムを早く見せかけられるわけです。

その後ユーザーがこのViewを閉じるなどして、アンマウントされた場合は、もちろんキャッシュも破棄されますので、次回以降はリフレッシュされた値が取得できることになります。
AtCoder ABC218 E - Destruction クラスカル法

##問題概要
連結な重み付き無向グラフを考える。
このグラフから辺を取り去る際の報酬をその辺の重みと定義するとき、得られる報酬の最大値を求めよ。ただし、グラフの連結性を崩してはならない。

* 主な制約
 * $2 \le $ 頂点数 $N $ $\le 2 \times 10^5$
 * $N-1 \le $ 辺数 $\le 2 \times 10^5$
 * $-10^9 \le $ 重み $ \le 10^9$ 

https://atcoder.jp/contests/abc218/tasks/abc218_e

##考察
辺を取り去る操作を実装することは難しいので、辺が全くない状態から辺を繋いで連結なグラフを構築する作業を考えて、その過程で採用されなかった辺を「取り去った辺」と見なすことにする。

$$報酬額  =  (重みの総和) - (使った辺の重みの総和)$$

だから、結局は右辺第二項の最小化問題に帰着し、Kruscal 法の範疇と分かる。負辺を取り除くメリットはないので負辺は必ず使う、という微修正を典型的な Kruscal 法の実装にかけて素直に実装する。

##実装
ほぼ典型的なKruscal 法の実装のまま。ループ内の if 文に追加で `w > 0` を課しただけ。

```cpp
typedef long long ll;
struct edge_k {
    ll u;
    ll v;
    ll weight;
    // ordering by weight 
    bool operator<(const edge_k &rhs) const {
        if (weight == rhs.weight) {
            if (u == rhs.u) {
                return v < rhs.v;
            } else {
                return u < rhs.u;
            }
        } else {
            return weight < rhs.weight;
        }
    }
    edge_k(const ll &u, const ll &v, const ll &w) : u(u), v(v), weight(w) {}
    edge_k() {}
};

int main() {
    using kruskal_graph = vector<edge_k>;
    ll total_w = 0;
    // read input
    auto n = in<ll>();
    auto m = in<ll>();
    kruskal_graph g;
    rp(i, m) {
        ll a, b, c;
        cin >> a >> b >> c;
        --a;
        --b;
        total_w += c;
        g.emplace_back(a, b, c);
    }

    auto kruskal = [&](kruskal_graph &g) -> ll {
        // sort by weight
        sort(g.begin(), g.end());
        ll res = 0;

        // use your union_find
        union_find uf(n);
        for (auto e : g) {
            ll w  = e.weight;
            ll u = e.u;
            ll v = e.v;

            // ignore negative edges
            if (uf.same(u, v) && w > 0) continue;

            // add edges
            res += w;
            uf.merge(u, v);
        }
        return res;
    };

    ll ans = total_w - kruskal(g);
    print(ans);
}
```
２点のCGPointからCGRectを作る

任意の２点で構成される四角形を作る場合、よく`(p1.x - p0.x, p1.y - p0.y)`をsizeとしてCGRectを生成することがあるが、CGRectのunionを利用することで計算を手書きせずに簡単に作ることができる。


```swift
let r0 = CGRect(origin: p0, size: .zero)
let r1 = CGRect(origin: p1, size: .zero)
let rect = r0.union(r1).standardized
```

unionは２つのCGRectを構成する最小のCGRectを生成する関数で、これを利用して座標だけを持つCGRect２つをunionさせて四角形を計算させる。
ツェナーダイオードに光を当てると電圧が発生する

#経緯
2015年くらいにRaspberry Piに強い光を当てるとクラッシュするという話があった。

[カメラのフラッシュを当てると動作停止するデスフラッシュ現象が「Raspberry Pi 2」で発生](https://gigazine.net/news/20150209-raspberry-pi-2-crash/)
[フラッシュでの撮影時に生じるデスフラッシュ現象についてRaspberry Piの公式が詳細を公開](https://gigazine.net/news/20150210-raspberry-pi-2-death-flash/)

Raspberry Piの件はその後解決したらしいが、
最近「ソーラーパネルに電圧を加えると光る」という内容の動画を見た。

[Why all solar panels are secretly LEDs (and all LEDs are secretly solar panels)](https://youtu.be/6WGKz2sUa0w?t=45)
<iframe width="925" height="520" src="https://www.youtube.com/embed/6WGKz2sUa0w?start=45" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

逆にガラス封止されたダイオードに光を当てると電圧が発生するが、ADコンバーターの前段に入れるツェナーダイオードでも光に反応するかな？と思って実験した。

#実験方法
手元にあったツェナーダイオードは3種(他にもあったが電圧が違った)
・05Z5.1
・RD5.1J
・5.1EB
これに懐中電灯の光を当ててテスタで電圧を測定する。

#結果
###05Z5.1
点灯前 0.3mV
![a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/e1c5175d-6c47-0ef0-9dcb-443ad2a4ae00.jpeg)

点灯時 185mV
![b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/891aa779-815d-c5c6-e404-67478e215566.jpeg)

懐中電灯の他デスクライトでも影響があった。

###RD5.1J
点灯前 ほぼ0mV
点灯時 0.1mV以下

###5.1EB
点灯前 ほぼ0mV
点灯時 0.4mV前後

#結論
・ツェナーダイオードは光の影響がある(可能性が高い)。
・ツェナーダイオードの種類によって発生する電圧は異なる

#余談
ツェナーダイオードを熱収縮チューブで覆うと光の影響は回避できたが、極性が分からなくなるのが難点。
ADコンバーター周辺を遮光するか、マイコンボックスを開く時は注意する必要があるかも。
透明ケースや屋外運用は対策が必要だろう。

ADコンバーターの前段にツェナーダイオードを入れる状況の回路図(下図)
![sch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563735/0d38d35c-03c6-7e9c-995f-c2d27753aec2.jpeg)
仕様は外部のセンサー等から4-20mAの信号を受け、シャント抵抗で0-4Vに変換してADコンバーターに入力する。
ADコンバーターのアナログ入力の絶対定格がVDD+0.3なので5.3V以下にする必要がある。
JuliaでIterator

## Iterator
Iterator とはデータ列を生成する際に、一括で生成せず、必要に応じてLazyに生成する手法。近代的な言語にはすべてサポートが入っていて、例えループなどで使用できる。Iteratorの定義方法は、まあ、どの言語でも大体同じで、初期化メソッドと、次のアイテムを要求するためのメソッドを定義する。

## Pythonのイテレータ
0から9までを生成するイテレータは次のように書ける。`__iter__`がイテレータとしての初期化メソッド、`__next__`が次の値を取得するメソッドである。`current`というインスタンス変数で次に生成すべき値を覚えている。

```python
class Iterable:
  def __init__(self, n):
    self.n = n
  def __iter__(self):
    self.current = 0
    return self
  def __next__(self):
    if self.current >= self.n:
        raise StopIteration
    x = self.current
    self.current += 1
    return x
```

## Juliaのイテレータ
Juliaのイテレータもだいたい同じだが、状態をイテレータ側に持つ必要がない。

```julia
mutable struct Iterable
    n::Int64
end

function Base.iterate(self::Iterable, state::Int64 = 1)
    state > self.n ? nothing : (state, state + 1)
end
```

`iterate`は`__next__`に相当する関数だが、この関数は生成する値だけでなく、イテレータの内部状態にあたる情報も返す。次に`__next__`が呼ばれる際にはこの内部状態が引数として渡される。このため、内部状態を構造体に維持しておく必要がない。

これだけでも、`for`文などでは使えるのだが、`collect`関数では使えない。使えるようにするには、長さもしくは形状を返す関数を何らかの形で定義してやる必要がある。長さが定まるなら`length`を定義する。

```julia
Base.length(self::Iterable) = self.n
```
定まらない場合には、次のように`IteratorSize`メソッドを定義すればいい。

```julia
Base.IteratorSize(self::Iterable) = Base.SizeUnknown()
```

## PythonのGenerator

PythonにはGeneratorという機能があり、Iteratorのようなものが簡単にかけるようになっている。

```Python
def gen(n):
    for i in range(n):
        yield i
```

すばらしい。`return`の代わりに`yield`を用いているが、これはジェネレータとなる関数のトップレベルでしか使えない。これを使うと何をしているのかが明快になる。

## Julia のChannel
Juliaでもかなり近いことができる。チャネルがイテレータとして機能するので、長さゼロのチャネルを作って、コルーチンでそこに値を生成してやるようにすればいい。長さゼロのチャンネルは全くバッファリングを行わないので、オンデマンドで値を生成するのとかなり近い動作になる。余分なメモリを消費することはない、はず。

```Julia
function generator(n)
    ch = Channel()
    @async begin 
        for i in 1:n
            put!(ch, i)
        end
        close(ch)
    end
    ch
end
```

これで次のように使うことができる。

```julia
for i in generator(10)
    ....
end
```

この簡単な例だと`__iter__`を定義したほうが簡単なくらいだが、状態を明示的に取り扱うのに比べると、この書き方のほうが何をしているのか理解しやすいので書きやすいかもしれない。

マクロを使ってちょっとお化粧してやれば、もうすこし見栄えがするようにできるかも。

## Generatorの内包表記
ご指摘いただいたので追記。

Juliaにはリストの内包表記に似たジェネレータの記法がある。基本的に`[]`を`()`に置き換えるだけ。

``` Julia
julia> (i for i in 1:10)
Base.Generator{UnitRange{Int64}, typeof(identity)}(identity, 1:10)
```

Pythonにも全く同じ記法がある。

``` Python
>>> (i for i in range(10))
<generator object <genexpr> at 0x101132ff0>
```

`if`文も使えるので、ある程度複雑なこともできるはず。でも２分木をたどるようなことはこの方法では書けなさそう。

``` julia
julia> collect(2^i for i in 1:10 if i % 2 == 0)
5-element Vector{Int64}:
    4
   16
   64
  256
 1024
```
find と xargs でファイル名を一括置換して、またもとに戻す。


## １． 一括置換

```sh
find . -maxdepth 1 -name "*.md" -type f | xargs -I% mv % %.org
```

- `find` で、
    - カレントディレクトリ直下の (`. -maxdepth 1`)
    - マークダウンの (`-name "*.md"`)
    - ファイルすべてに対して (`-type f`)
- `xargs` で、
    - ファイル名 (`-I%`) の
    - 末尾に .org を付与する (`mv % %.org `)

補足： `-I%` で % という変数でファイル名を受け取るという指定になる。


## ２． もとに戻す


```sh
find . -maxdepth 1 -name "*.md.ignore" -type f | sed 's/\.ignore$//' | xargs -I% mv %.org %
```

ファイル一時的に退避しといて作業が終わったらもとに戻す、とかのときに使える。
Wordpressプラグイン「PublishPress Revisions」で既存の記事をタイマー更新する

Wordpressに既存記事のタイマー更新が無いので「PublishPress Revisions」で対応しました。

[「PublishPress Revisions」](https://ja.wordpress.org/plugins/revisionary/)

しかしこのプラグイン、**ぶっちゃけ使い方がわかりにくい**のと、検索して出てくる紹介記事はバージョンが古いようであんまり参考になりませんでした。

# タイマー更新の使い方

記事一覧からタイマー更新したい記事をクリック。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/89798840-6968-09e4-abb4-d4aa544be408.png)
「New Revision」というボタンが追加されているのでクリック。
更新用に記事が複製される。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/d0b7ed2f-dbad-890b-a1b4-15f860ce2e09.png)
サイドメニューの「リビジョン」をクリックすると更新用に複製された記事の一覧が表示される。
記事をクリックして編集。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/e1e55783-563a-df28-d73a-b01594db1257.png)
記事を編集し、公開時刻を指定する。
**公開希望時刻の1分前くらいに設定することをおすすめします。**
この記事ではタイトルのみ変更してみた。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/cd9f022c-8932-d98f-1781-c79a11592d0f.png)
公開時刻を指定したら「OK」をクリック。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/eae0f351-1b22-07d6-b03e-1283831a6fb2.png)
「下書き保存」をクリック。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/3a890377-5a2f-8c04-d849-f791787a49b0.png)
現状はまだ変更結果が確定していないので「Submit Revisions」で確定する。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/d24b587e-1cc6-6677-beca-3737db46c225.png)
そのまま `[control / command] + [R]` で再読み込みすると「Approve Revision」ボタンが表示されるのでクリック。
この操作によって記事がタイマー設定が承認される。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/c427f68d-bbb0-53c9-2d02-d17b53493922.png)
サイドメニューの「リビジョン」で編集した記事を確認。
Statusが「Scheduled」になっていればタイマー設定が完了。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/074c2892-2eaa-f460-9b4b-73a5b466bd07.png)
なぜか設定時刻通りではなく、プラス1分くらいで記事が公開される。
公開されるとリビジョンの一覧からは消える。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513/bdcab587-b9b5-1872-ba58-299cdfa74b68.png)

以上です。
Wordpressに既存記事のタイマー更新機能があるのがベストなんですけどね。
Unexpected side effect in ~ computed property の対処法

## はじめに
「 Unexpected side effect in ~ computed property」というエラーが出た時の対処法の1つを紹介します．

## 動作環境
vue-cli : 4.5.12
vue : 2.6.12

## 現象
算出プロパティ warningMessages を作成しました．

```vuejs:snackBar.vue
<script>
export default {
  name: "SnackBar",
  data() {
    return {
      snac: false,
    };
  },
  computed: {
    warningMessages() {
      if (this.$store.state.message.warnings.length > 0) {
        this.snac = true;
      }
      return this.$store.state.message.warnings;
    },
  },
};
</script>
```

すると，このようなエラーが発生しました．

```vuejs
 error  Unexpected side effect in "warningMessages" computed property  
```


## 原因

```vuejs
this.snac = true;
```
の部分がエラーの原因でした．算出プロパティ （warningMessages）は，データ（snac）を直接変更することができないようです．

## 解決策
snac を直接変更する openSnackBar メソッド を用意して，warningMessages から openSnackBar を呼び出すことにより解決しました．

```vuejs:snackBar.vue
<script>
export default {
  name: "SnackBar",
  data() {
    return {
      snac: false,
    };
  },
  // snac を変更するmethod を追加
  methods: {
    openSnackBar() {
      this.snac = true;
    },
  },
  computed: {
    warningMessages() {
      if (this.$store.state.message.warnings.length > 0) {
        this.openSnackBar(); // snac を直接変更するのではなく，method を呼び出して変更するようにした
      }
      return this.$store.state.message.warnings;
    },
  },
};
</script>
```
## まとめ
算出プロパティは，データを直接変更することができないということが分かりました！これに対処する方法の一つとして，データを変更するメソッドを用意して，算出プロパティからそのメソッドを呼び出すということがあります．

## 参考リンク
こちらの記事でも，同じ「Unexpected side effect ~ 」というエラーについて取り扱われています．算出プロパティ内でdata の配列をソートしようとしたらエラーが出たため，「.slice()」を使って配列をコピーしたものをソートすることで解決しています．

https://qiita.com/gungungggun/items/9464ecdf8275f4e53b8f
Unity初心者 変数定義の豆知識

## 3つのfloatをメンバで自動的にVector3にする方法
<スクリプト側>

```
    public float x, y, z;
    Vector3 moveXYZ {
        get => new Vector3(x, y, z);
        set => new Vector3(x, y, z);
        }
```
<Inspector view側>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1548088/83d41462-85b5-d2c0-a5e3-8b5d77aaad88.png)

これで、Editor側で数字を入れるとVector3を作成してくれました！

## アクセス修飾子 (よく出てくるものだけ)
| static系 | private  |  [SerializeField] private | public  |
|:-:|:-:|:-:|:-:|
| inspectorには表示できない | 同一スクリプト内でしか参照できない| 外部から参照できないがinspectorで入力できる|外部からの参照もできるしinspectorでも入力できる |
会社で月間Best Qiita賞を受賞したので自慢します

テックブログに書く内容ではないかもですが、先日、弊社で実施されてるBest Qiita賞を受賞したので、自慢がてらうちの会社のメンバーの記事も含め、宣伝しようと思います。

テックブログというより、読み物っぽい感じになるかもですが、ちゃんとテックブログへのリンクもあるので、ゆっくりしていってください。

# Best Qiita賞

弊社WHIでは、毎月Oraganization(WHI)にjoinしてるアカウントで書かれた記事に対して数件をノミネート。
その中から最もLGTMな記事を投票形式で選び、最も票数を獲得したものを月間Best Qiita賞として選びます。

Best Qiita賞に選ばれるとプライズがもらえます。
※今は「Amazonギフト券」または「オライリー電子書籍購入費」で、5000円分です。
(ちなみに課税対象←給与計算やってる会社っぽくあえてか書いてみた)

毎月だいたい30件前後の記事が更新されていて、いずれも素晴らしい記事ばかりです。

# 受賞した記事の紹介

私が今回Best Qiita賞を受賞した記事はこちらです。

https://qiita.com/soepy/items/6b33859501fc5811c04b

私は現在パッケージ開発に携わるエンジニアで、主にバックエンド、フロントエンドを担当しています。
(弊社ではアプリエンジニアとインフラエンジニアで大きく2分されてる感じです)

フロントエンドに関しては大した事ないのですが、そんな私が、Amazonの定期配送を受け取った時「これぞUXだ！」とひらめいて、ばぁーーっと書いた記事です。

一般にUXというとフロントエンドの範疇ですが、いいUXとは何なのか？そのためにはどういう思考でモノを考えたらいいか？くらいは大した知識がなくても考察できるので、そんな気持ちで書いた記事です。

長くないので読んでみてください。
ライティングスキルはまだまだですが、我ながらいい出来ですww

# ノミネート作品の紹介

今回私がプライズをゲットしたわけですが、今回ノミネートされていた7記事を紹介していきます。
弊社のエンジニアが何に興味があって、どういうことを考えてるか垣間見えると思うので、こちらもぜひ目を通していただきたいです。私の個人的な感想付きで行きます！

https://qiita.com/takeC74/items/d26f192cf554047b06b1

45歳定年とかありえない。50代半ばで設定可視化ツールの主担当として大活躍している大先輩もいる。
圧倒的な経験値と知識で、正直替えが効かないと思っている。
年齢で区別すべきではない。その通り！

https://qiita.com/sasaki_hir/items/13382804ea3a892d1d12

私こういうの苦手なのですが、Gitを使ったブランチ操作は日常茶飯事なので面白そうだなーと思って読んでました。
ただ私メインはGit-Bashなんだよな。。。


https://qiita.com/kabik/items/16834397f9c482e9af21

Python最近書いてないな〜。うちの製品はJavaが最もよく使われてるんですが、なにかとPythonが便利で、CI/CD周りでよく使われてるんですよね。そしてPython好きが結構多い気もする。
PPAP久しぶりに見た(笑)


https://qiita.com/zhang_yid/items/0f065098fe4a0e0066d0

実は私、大学時代、電気電子回路の授業てこんな図見てます。理解はあまりしてませんw
ただこのbit計算(2進数)の考え方は、ITエンジニアとしては必修科目だと思うので、理解しておく必要ありますね。

https://qiita.com/e99h2121/items/97168cad64ff40afb77d

有名人ですね〜。
言わずもがな、markdownは便利かつ手軽な記法なので一刻も早く使いこなせるようになるべきです。


https://qiita.com/hitsumabushi845/items/1af69cc5db65a1607d70

、、、正直Kubernetes分からんのですよね。でも読んだら理解できるのかな？バックエンドで食おうとしたら知ってるべきだよな〜と思いつつ勉強できてない。。

https://qiita.com/flyaway/items/7c47edc9b04f8b87e13a

同じプロダクト開発してる大先輩の記事。
最近はもっぱらこういうことやってますよ、私も。
技術的負債との戦い、レガシーコードとの戦い、その過程で必ず単体テストが必要になるし、モックが必要な局面があります。
結構まとまってて、わかりやすいので、逆引きじゃないけど、よくこの先輩の記事閲覧してます。


以上7記事でした。


# 最後に

自慢 & 弊社エンジニアの記事紹介となりましたが、B2Bの堅苦しい会社ではなく、さまざまなことを外部発信する風土が広がってきていて、特定の技術や話題にも偏らない、まさにダイバーシティな会社であり、開発部門だと勝手に思っています。

超モダンなわけではないですが、日々楽しく仕事できてるのも、こういう会社だからだし、いろんな人がいろんなことを発言して、毎日刺激を受けられるからです。

興味ある求職者、転職考えている人、就活生はぜひカジュアル面談(そのうちエンジニアもやるようになるかな？今はやってないと思う)、選考などでお会いできるといいな〜と思っています。

# 最後の最後に
Best Qiita賞のプライズなどのために稟議を通してくれたプロジェクト運営の皆様、この場を借りて御礼申し上げます。プライズはきっと書籍代として消えます。きっと。。
【Swift】Xcodeでカスタムフォントをコードで実装する方法

Xcodeでカスタムフォントを使用する方法。

## フォントファイルの用意

まずはフォントファイルを手元に用意します。

拡張子は`otf` `ttf` `ttc`のいずれかにしておきましょう。

## フォントファイルをアップロード

次に用意したフォントファイルをXcodeにドラッグアンドドロップでアップロードします。

![スクリーンショット 2021-11-18 23.17.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522445/83d5f7a5-56ea-6319-58e8-1ed6e37246ee.png)

上の画像のようにウィンドウが表示されるので、画像のようにチェックを入れてFinishをクリックしましょう。

## Swiftコードで実装

アップロードが完了したらSwiftのコードで実装していきます。

```swift
private let sampleLabel: UILabel = {
    let label = UILabel()
    label.font = UIFont(name: "フォント名", size: 15)
    label.frame = CGRect(x: 0, y: 0, width: 300, height: 100)
    label.textColor = UIColor.black
    label.textAlignment = .center
    return label
}()
```
装飾やサイズは適当にしてあります。

## 参考

https://developer.apple.com/documentation/uikit/uifont

## おすすめ情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
sysimage_creator の紹介

# 本日は

Julia アドベントカレンダーネタとして自作ツール [sysimage_creator](https://github.com/terasakisatoshi/sysimage_creator) の紹介をします.

`using Plots.jl` など初回ロードが遅いパッケージは PackageCompiler.jl を使うことで Julia の sysimage にコンパイル情報を追加することで解決することができます. Jupyter の Julia カーネルも初回のロードやカーネルの再起動は Python のそれに比べると遅いので少しイライラする方もいると思います. sysimage_creator はそれらの問題に対処するツールです.

# 導入

この記事を読むにあたっては Julia/Python/Jupyter の環境はあらかじめ整っていると仮定します. 他にも `pip install ...` とか jupytext とか PacakgeCompiler.jl の使い方を他の記事で読んだ経験があれば理解しやすいと思います.

ひとまず下記の手順を踏むと道具が揃います.

```console
$ git clone https://github.com/terasakisatoshi/sysimage_creator.git
$ pip install jupyter jupytext nbconvert ipykernel
$ cd sysimage_creator && make && jupyter notebook
```

ノートブックを起動する際に `julia-1.6.3-sys` という名前のカーネルを指定すると
初回のノートブックの起動時のもっさり感や using Plots のロードの遅さが改善されていると思います.

`make` コマンドの中では 

- IJulia によって jupyter カーネルが起動する際に行われるJITコンパイル情報を取得
- StatsPlots.jl を jupyter 上で実行する際に行われるJITコンパイル情報
- 得られたコンパイル情報をもとにPackageCompilerによって sysimage を作ってもらう
- その sysimage を呼び出すためにカーネルを作成する (これが julia-1.6.3-sys です)

```console
$ make test
```

とすると簡単なノートブックの起動・実行に対して素の sysimage と sysimage_creator で作った sysimage で試した場合でおおよそ３倍改善される様子を見ることができます．

```
julia --project=@. benchmark.jl
[jupytext] Reading testout_naive.jl in format jl
[jupytext] Executing notebook with kernel julia-1.6
Starting kernel event loops.
[jupytext] Writing testout_naive.ipynb (destination file replaced [use --update to preserve cell outputs and ids])
[jupytext] Updating the timestamp of testout_naive.jl
[jupytext] Reading testout_sys.jl in format jl
[jupytext] Executing notebook with kernel julia-sys-1.6
Starting kernel event loops.
[jupytext] Writing testout_sys.ipynb (destination file replaced [use --update to preserve cell outputs and ids])
[jupytext] Updating the timestamp of testout_sys.jl
t_naive = 26.774783521 # こっちがデフォルトの状態
t_sys = 7.839323549.   # 我々のツールを使った場合
Test Summary: | Pass  Total
benchmark     |    1      1
```

お試しあれ
【iOS】FastlaneでUnitTest/UITestをいい感じに自動化してみた

## はじめに
Fastlaneをプロジェクトに導入をする機会があって、いろいろ調べたので記事にしてみました。
Fastlaneをこれから使ってみたい、XCTestを自動化したいという方の参考になれば幸いです。

## この記事で学べること
- Fastalenの導入の方法
- XCTest(UnitTest/UITest)を自動化する方法（前提としてプロジェクトにXCTestが導入されている必要がある）
- Test自動化のための細かいオプション

## Fastalen導入
Test自動化の前にFastlaneをプロジェクトに導入する必要があります。
プロジェクトのディレクトリに移動して、

```
bundle init
```

を実行すると、同ディレクトリに`Gemfile`が生成されます。

`Gemfile`をテキストエディタなどで開いて、コメントアウトされている`# gem "rails"`の下に、

```
gem 'fastlane'
```

を書き足します。
ここまでは、エラーが起きて失敗したりすることはあまり無いと思います(自分は大丈夫でした)

次はインストールです。

```
bundle install --path vendor/bundle
```

このコマンドが結構厄介で、環境によっては権限周りのエラーを吐きます。
PCによって大丈夫だったり、ダメだったり色々です。とりあえず、エラーで検索すれば、解決できました。

ここまできたら次は、Fastalen導入です。

```
bundle exec fastlane init
```

1 - 4 の選択肢を提示されて、選ばされますが、どちらにせよ後で編集できるので、4番を選択します。
なんか色々聞かれますが、Enterですべてすっ飛ばします。


このコマンドが成功するとディレクトリに`fastlane`というファイルが作られます。
その中に、`Fastfile`、`Appfile`があるはずです。← 今回はこれ使いません。

## XCTestの自動化
とりあえず、Fastlaneの導入が終わりましたので、こっから自動化する作業に入ります。
### Scanfileを生成する
```
bundle exec fastlane scan init
```

### とりあえずTest実行してみる
`Scanfile`が作られたら、とりあえず中身を何も変更しないデフォルトでも自動テストが動きます。

```
bundle exec fastlane scan  
```

これだけです。
UnitTestとUITestがプロジェクトに両方ある場合は、両方とも自動で実行されます。

ターミナルでテストが完了したことを確認し、
`/fastlane/test_output`のディレクトリに`report.html`が出力されていればテスト完了です。
テストの結果はこのHTMLファイルから確認できます。

こんな感じです。
![test_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580445/384d15ba-818e-4b74-207d-726b1f410f7c.png)

プロジェクトにある全てのTestをとりあえず回したいという場合はここまででOKです。

## Scanfileを使ってもっと便利にしてみる
デフォルトでもXCTest自動化という目的は達成ですが、せっかくScanfileを生成したので、もう少しカスタムしていきたいと思います。
自分が使ってみて便利だったカスタムは以下に記載しました。

```
devices(["iPhone 8"])

open_report(true)

clean(true)

only_testing(["Switf5UITestTrainUITests/Switf5UITestTrainUITests/testLogin"])

# skip_testing(["Switf5UITestTrainUITests/Switf5UITestTrainUITests/testLogin"])
```

| key | value | type |
|:---|:---|:---|
| devices | テストを実行する端末を配列で指定可能 | [String] |
| open_report | テスト完了後にhtmlを開くかどうか<br>終わったタイミングが分かるので良い | Bool / default = false |
| clean | clean build するかどうか | Bool / default = false |
| only_testing | 実行したいテストを1メソッド〜指定可能<br> フォルダ名/ファイル名/メソッド名 を配列で指定可能<br>めちゃ使える | [String] |
| skip_testing | スキップしたいテストを1メソッド〜指定可能<br> フォルダ名/ファイル名/メソッド名 を配列で指定可能 | [String] 

パラメーターの仕様をもっと知りたい方はこちらのドキュメントに記載されているので読んでみてください。

https://docs.fastlane.tools/actions/scan/

## 参考にさせていただいた記事
https://qiita.com/touyu/items/7ea0d2d666716ffb5e96
Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs.

# ファイルを base64 でエンコードしようとした

最初に正解を書きます。

``` tsx
const Hoge = () => {
  const [file, setFile] = useState<File | null>(null);
  
  return (
    <>
      <p>ファイルを選択してボタンを押してね</p>
      <input type="file" onChange={e => setFile(e.target.files?.item(0) ?? null)} />
      <button onClick={() => if (file) encode(file)} />
    </>
  )
}

const encode (file: File) => {
  const reader = new FileReader();
  reader.readAsDataURL(file); 

  reader.onload = () => console.log(reader.result); // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA..."
}
```

コンソールに出力されます。

参考: https://developer.mozilla.org/ja/docs/Web/API/FileReader/readAsDataURL

## 間違った例

### reader.result が null

``` ts
const encode (file: File) => {
  const reader = new FileReader();
  reader.readAsDataURL(file); 
  console.log(reader.result); // エンコードした文字列が出て欲しいが null
}
```

encode() の reader.onload を省いてしまっています。
読み込み操作の終了をちゃんと待ちましょう。

### already busy reading Blobs

タイトルです。
エンコードの処理の間違えた部分をループさせたり、**debugger** を使用すると起こります。

``` ts
const encode (file: File) => {
  const reader = new FileReader();
  reader.readAsDataURL(file); 
  console.log(reader.result); // エンコードした文字列が出て欲しいが null
  
  debugger; // 確認しようとして debugger を入れる
  // 停止中に reader.readAsDataURL(file); をすると以下のエラーが出ます。
  // Uncaught InvalidStateError: Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs.
}
```

ループの場合はこんな記事ありました
https://stackoverflow.com/questions/24843508/filereader-error-the-object-is-already-busy-reading-blobs
全シートのフッターを一括編集する

Excelで文書なんか作らすなよ...

それも数十ページすべてのフッターに社名だのページ番号入れろと...

さらにページ番号は単純連番ではなく1, 2, 3-1, 3-2, ...と微妙に枝番があると来た...

そんな面倒はマクロでやっつけてしまえ

## 準備
### テーブルを用意
`整理表`という名前のテーブルを用意する

|マクロ実行|シート名|フッター左|フッター中|フッター右|
|---|---|---|---|---|
||||||

### 表示シートのリストを取得する
`Getシート名リスト`を実行するとテーブルにシート名が列挙されます。

この時、非常時になっているシートは無視するようにしてますが、
非常時シートもリストアップしたい方は`If wb.Sheets(i).Visible = True Then`をコメントアウトして下さい。

### `マクロ実行`列に何か入れる

1でも〇でもなんでもいいので入れるとそのシートがフッター編集対象になります。

### フッターに入れたい文字列をテーブルに入れる
賢いお馬鹿機能が発動して1-1とかそのまま入れると1月1日とか余計なお世話を焼いて下さるので書式を文字列にして黙らせておいた方がいいです。

### `フッター一括編集`を実行
以上です。

## コード
``` vb
Option Explicit
Const myテーブル名 = "整理表"
Enum c
  マクロ実行 = 1
  取得したシート名
  フッター左
  フッター中
  フッター右
End Enum
Type 対象
  取得したシート As Worksheet
  フッター左 As String
  フッター中 As String
  フッター右 As String
End Type
Dim Target As 対象

Sub Getシート名リスト()
  Dim wb As Workbook
  Set wb = ActiveWorkbook
  Dim ws As Worksheet
  Set ws = ActiveSheet
  Dim i, Row最終
  
  Application.ScreenUpdating = False
  With ws.ListObjects(myテーブル名)
    '初期化
    .DataBodyRange.Delete
    
    'シート名をテーブルにリストアップ
    For i = 1 To wb.Sheets.Count
      If wb.Sheets(i).Visible = True Then
        .ListRows.Add
        Row最終 = .ListRows.Count
        .Range(Row最終, c.取得したシート名).Value = wb.Sheets(i).Name
      End If
    Next
  End With
  Application.ScreenUpdating = True

End Sub

Sub フッター一括編集()
  Dim wb As Workbook
  Set wb = ActiveWorkbook
  Dim ws As Worksheet
  Set ws = ActiveSheet
  Dim i, Row最終
  
  Application.ScreenUpdating = False
  With ws.ListObjects(myテーブル名)
    For i = 1 To .ListRows.Count
      If .DataBodyRange(i, c.マクロ実行) <> "" Then
        Set Target.取得したシート = wb.Sheets("" & .DataBodyRange(i, c.取得したシート名) & "")
        Target.フッター左 = .DataBodyRange(i, c.フッター左)
        Target.フッター中 = .DataBodyRange(i, c.フッター中)
        Target.フッター右 = .DataBodyRange(i, c.フッター右)
        
        With Target
          If フッター編集(.取得したシート, .フッター左, .フッター中, .フッター右) = False Then
            MsgBox .取得したシート.Name & "の途中で失敗しました。"
            End
          End If
        End With
        
      End If
    Next
  End With
    
  Application.ScreenUpdating = True
  MsgBox "フッターを設定しました。"
    
End Sub

Private Function フッター編集(ws As Worksheet, フッタ左, フッタ中, フッタ右) As Boolean
  On Error GoTo Err
  With ws.PageSetup
    .LeftFooter = フッタ左
    .CenterFooter = フッタ中
    .RightFooter = フッタ右
  End With
  フッター編集 = True
  Exit Function
Err:
  フッター編集 = False
End Function
```

## 小言

`フッター一括編集`内のここ

``` vb
Set Target.取得したシート = wb.Sheets("" & .DataBodyRange(i, c.取得したシート名) & "")
```

`Sheets(シート名)`のところ、`""`で挟まないとエラーになる