日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

Rustのgoogle/arghライブラリで引数をstructにbindする

GWにRustを触り始めたら楽しくなってきました。
新しい言語を触るのはやはり楽しいです。
今回はなんやかんやするコマンドを作ろうと思って、
引数をいい感じにしてくれるライブラリないかなと思って調べてたら、
googleのarghというライブラリがあったのでそれを触った備忘録です。

google/arghはこちら

github.com

基本的に使用するCargo.tomlはinitして、dependenciesにarghを追加した下記のようなのものでした。

Cargo.toml

[package]
name = "argh_opt"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
argh = "0.1.7"

目次

1.1 --hoge fugaのようなオプションを設定する

よくある ./bin/foo --hoge fuga みたいなやつですね。
これを実装してみましょう。

src/main.rs

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    /// hoge
    #[argh(option)]
    hoge: String,
}

fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
    println!("{:?}", a.hoge);
}

/// があるのは、descriptionを書くのが必須のようで、エラーになってしまうからこうしました。
argh(description= "...")とも書けるようですが、ドキュメンテーションコメントで書いても拾ってくれるみたいでした。
これを実行してみるとこんな感じになります。

$cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
     Running `target/debug/argh_opt`
Required options not provided:
    --hoge

$cargo run -- --hoge fuga
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/argh_opt --hoge fuga`
FooArg { hoge: "fuga" }
"fuga"

これで--hogeが必須のオプションになりました。
--hogeを必須ではなく任意にしたい場合は下記のように型を Option[String] にするといいようです。

struct FooArg {
    /// hoge
    #[argh(option)]
    hoge: Option[String],
}

1.2 数字やbool値を引数に渡す

次は ./bin/foo --hoge bar -- fuga --piyo 100 みたいなものを目指します。
数字は型に数字系のデータ型を指定し、
boolはoptionではなくswitchを指定することで使えるようでした。

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    /// hoge
    #[argh(option)]
    hoge: String,

    /// fuga
    #[argh(switch)]
    fuga: bool,

    /// piyo
    #[argh(option)]
    piyo: i32,
}

fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
    println!("{:?} {:?} {:?}", a.hoge, a.fuga, a.piyo);
}
$cargo run -- --hoge foo --fuga --piyo 10
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/argh_opt --hoge foo --fuga --piyo 10`
FooArg { hoge: "foo", fuga: true, piyo: 10 }
"foo" true 10

# 数字の部分に文字列を渡したらエラーにしてくれました
$cargo run -- --hoge foo --fuga --piyo bar
    Finished dev [unoptimized + debuginfo] target(s) in 0.35s
     Running `target/debug/argh_opt --hoge foo --fuga --piyo bar`
Error parsing option '--piyo' with value 'bar': invalid digit found in string

zsh: exit 1     cargo run -- --hoge foo --fuga --piyo bar

1.3 デフォルト値を設定する

default = "関数名"で指定してあげると良さそうでした。
ダブルクオートの中に文字列で関数を指定するのどことなく不思議な感じがしますね。

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    /// a
    #[argh(option, default = "String::from(\"hoge1\")")]
    hoge1: String,
    /// a
    #[argh(option, default = "default_hoge()")]
    hoge2: String,
    /// a
    #[argh(option, default = "\"hoge\".to_string()")]
    hoge3: String,
}

fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
    println!("{:?} {:?} {:}", a.hoge1, a.hoge2, a.hoge3);
}

fn default_hoge() -> String {
    return "hoge2".to_string();
}

なお、関数の型があっていないときはコンパイルエラーになりました。
例えば上記のdefault_hogeをi32が返るように変更し、
コンパイルするとエラーになった様子です。

fn default_hoge() -> i32 {
    return 100;
}
error[E0308]: mismatched types
  --> src/main.rs:10:30
   |
10 |     #[argh(option, default = "default_hoge()")]
   |                              ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
   |                              |
   |                              expected struct `String`, found `i32`

便利ですね〜

1.4 from_str_fnを使って文字列をstructに変換する

なんらかのフォーマットのデータを入力時に変換してもらおうと思います。
例えば 14:15 のような時間のフォーマットを変換します。
./bin/foo --time 14:15 みたいなコマンドのイメージです。
from_str_fnに、 &strを受け取りResult<T, String>を返す関数を渡すといい感じに変換してくれるみたいでした。

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    /// a
    #[argh(option, from_str_fn(str_to_time))]
    time: Time,
}

#[derive(Debug)]
struct Time {
    _h: u32,
    _m: u32,
}

fn str_to_time(v: &str) -> Result<Time, String> {
    let x: Vec<&str> = v.split(":").collect();
    let h = match x[0].parse::<u32>() {
        Ok(x) => x,
        Err(e) => return Err(e.to_string())
    };
    let m = match x[1].parse::<u32>() {
        Ok(x) => x,
        Err(e) => return Err(e.to_string())
    };

    if h >= 24 {
        Err(format!("{} is too large", h))
    } else if  m >= 60 {
        Err(format!("{} is too large", m))
    } else {
        Ok(Time { _h: h, _m: m })
    }
}

fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
    println!("{:?}", a.time);
}

実行してみると

$cargo run -- --time 14:15
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/argh_opt --time '14:15'`
FooArg { time: Time { _h: 14, _m: 15 } }
Time { _h: 14, _m: 15 }

# ResultのErr側に渡したStringをメッセージとして出してくれるようですね
$cargo run -- --time hoge
   Compiling argh_opt v0.1.0 (/Users/arata/Documents/Workspace/rust/argh_opt)
    Finished dev [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/argh_opt --time hoge`
Error parsing option '--time' with value 'hoge': invalid digit found in string

みたいな感じでした。

2.1 sub commandを使う

次はサブコマンドを実装してみます。
./bin/foo hoge./bin/foo fuga みたいなやつです。
これを実装してみます。
enumでコマンドを作成し、
それぞれarghのマクロにsubcommandと渡してあげれば良さそうでした。  

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    #[argh(subcommand)]
    _command: SubCommand,
}

#[derive(FromArgs, Debug)]
#[argh(subcommand)]
enum SubCommand {
    Hoge(HogeCommand),
    Fuga(FugaCommand),
}

#[derive(FromArgs, Debug)]
/// h
#[argh(subcommand, name = "hoge")]
struct HogeCommand {}

#[derive(FromArgs, Debug)]
/// h
#[argh(subcommand, name = "fuga")]
struct FugaCommand {}


fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
}

実行してみるとこんな感じ

$cargo run -- hoge
    Finished dev [unoptimized + debuginfo] target(s) in 0.06s
     Running `target/debug/argh_subcommand hoge`
FooArg { _command: Hoge(HogeCommand) }

$cargo run -- fuga
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/argh_subcommand fuga`
FooArg { _command: Fuga(FugaCommand) }

$cargo run -- piyo
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/argh_subcommand piyo`
Unrecognized argument: piyo

2.2 sub command内でオプションを使う

サブコマンドにオプションをつけるのは、
サブコマンドのstructに、1.xでやったようにオプションを追加するだけでよかったです。
試しにhogeコマンドにpiyoというオプションを追加してみます。

use argh::FromArgs;

#[derive(FromArgs, Debug)]
/// 
struct FooArg {
    #[argh(subcommand)]
    command: SubCommand,
}

#[derive(FromArgs, Debug)]
#[argh(subcommand)]
enum SubCommand {
    Hoge(HogeCommand),
    Fuga(FugaCommand),
}

#[derive(FromArgs, Debug)]
/// h
#[argh(subcommand, name = "hoge")]
struct HogeCommand {
    /// piyo
    #[argh(option)]
    piyo: String,
}

#[derive(FromArgs, Debug)]
/// h
#[argh(subcommand, name = "fuga")]
struct FugaCommand {}

fn main() {
    let a: FooArg = argh::from_env();
    println!("{:?}", a);
    match a.command  {
        SubCommand::Hoge(x) => println!("{}", x.piyo),
        SubCommand::Fuga(_) => (),
    }
}

実行してみるとこんな感じ

cargo run -- hoge --piyo fooooo
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/argh_subcommand hoge --piyo fooooo`
FooArg { command: Hoge(HogeCommand { piyo: "fooooo" }) }
fooooo

感想

  • とりあえずこれ使っておけばやりたいことはできそうだなーと思った
  • google製だから安心かなと思ったけどREADMEの最後に↓って書いてあって少し不安になったw
    • NOTE: This is not an officially supported Google product.

  • Rust楽しい

モデルナ製ワクチンの3回目を受けたときの副反応体験の備忘録

職域摂取でワクチンの3回目を受けられたので、その時の体験をメモっておこうと思います。
色々な反応があるようですが、自分は今回かなり軽めでした。
1、2回目モデルナで、今回3回目もモデルナ製にしました。
理由はタイミングがよかったから以外特にありません。

2回目のときの備忘録はこちら arata.hatenadiary.com

ワクチン3回目摂取からの流れ

1日目(摂取日)

  • 15:15
    • ワクチン3回目摂取
  • 17:00
    • 36.5度
  • 19:00
    • 37.1度
  • 22:30
    • 36.6度
    • 注射した左腕を押すと痛くなった
  • 0:00
    • 36.5度

という感じで、左腕を押すと痛いくらいの症状で他はほとんどなにもありませんでした。

2日目

3日目

  • 8:00
    • 36.4度

その後体温が37度に上がることもなく熱などの副反応は落ち着いた。
ただ、注射した左腕が腫れ上がっていて痒かった。
痒みについては、下記を参考に冷やすと落ち着いたので、痒みがあるときは冷やすを繰り返した。
具体的には保冷剤?があったのでそれをタオルで包んで腕に当てて様子見るなどしました。

www.cov19-vaccine.mhlw.go.jp

左腕の腫れはだいぶ赤みを帯びていて、心配になるレベルだったが、
4日目には薄いピンク色くらいになり、5日目にはほとんど見えないくらいになり、6日目以降消えていき、
これを以て3回目の副反応は終わった。

振り返り

  • K
    • 保冷剤があってよかった
      • モデルナアームっぽくなって痒くなったときに使える
      • 熱冷まシート貼ると痒かった
    • ゼリーとは別にパンを買ったのはよかった
      • 前回死にそうになったときに食べるものがあった方がいいなとPに書いていたのでミニクロワッサンを買っていた
      • 腹が膨れるのでとても便利だった
      • 用意してくれた奥さんに感謝 :pray:
    • 2回目同様
      • ゼリー系の食べ物を用意しておいてよかった
      • バファリンプレミアムが効いてよかった
  • P
    • 症状が軽かったこともあり、特段困りごとはなかった

Tobii EyeTracker5を使ってゲームを見てる視線をOBS上に表示する

誕生日にTobii EyeTracker5をプレゼントしてもらえたので、それの設定方法のメモです。
Windowsでしか動きませんが、Mac mini(2018)のBootcamp上のWindows 10 Pro上でも動きました。
公式のヘルプ上では、Boot CampParallels上のWindowsでの動作について、ユーザからは動くという報告はあるらしいですが、
サポートはしていないみたいなので自己責任の範囲での使い方になるみたいですね。

実際にSplatoon2をやってみたらこんな感じで見てるところにうにょんうにょんって動く感じになりました。 www.youtube.com

Tobii Eye Tracker5はこちら。複数の画面で使いたい場合、Mounting Kitもあると便利です。

やること

1. 設定用アプリケーションのダウンロード

画面用にEye Trackingの調整を行うtobii experienceというアプリケーションと、
OBSやTwitch上にBubbleを出す設定を行うtobii ghostをダウンロードします。
いずれも公式のページからダウンロードします。

gaming.tobii.com

2. Eye Tracking設定を行う

ディスプレイの下にTobii Eye Tracker 5をつけなければならないのですが、
Windowsで行うゲームにEye Trackingを行いたい場合は、ゲームに使うディスプレイにつけてください。
もし、Switch等のPC以外で行う場合は、そのゲームのために使うディスプレイの下につける必要があるため、
そこにつけつつ、後述する「PC以外のゲーム用の設定を行う」の欄を参考に設定してください。

tobii experienceを起動して設定を行います。
下記の様な画面が出てくると思うので、ディスプレイに映っているEye Trackerの位置と
ディスプレイの下にくっつけたEye Trackerの位置を合わせます。

f:id:arata3da4:20210921134612p:plain
tobii experienceキャリブレーション1

その後、ドットが爆発するまで見続けてくださいという調整っぽいのが始まるのでその通りに行います。

f:id:arata3da4:20210921135613p:plain
tobii experienceキャリブレーション2

3. OBSに設定を追加する

次にtobii ghostの設定を行います。
このアプリケーションによってOBSやTwitchの配信にBubbleを載せられるようになります。
起動して設定からTobii Ghostを有効にします。
またこのPreviewをオンにすることで、現在のディスプレイにBubbleを表示させることができるので、それでうまく行っているか確認するのも良さそうです。

f:id:arata3da4:20210921135832p:plain
tobii ghost

有効にしたらOBS上でソースの設定を行います。
ソースに「ゲームキャプチャ」を追加し、モードを「特定のウィンドウをキャプチャ」にします。
そしてウィンドウを「SSOverlay」に設定すればOBS上にBubbleが表示されるようになります。 これでWindows上でゲームを行い、OBSで記録する場合はこれで終了です。
私はやっていないのですが、Twitch上に載せることもできるみたいなので気になる方はやってみてください。

f:id:arata3da4:20210921140340p:plain
ゲームキャプチャ-特定のウィンドウをキャプチャ-SSOverlay

EX. PC以外のゲーム用の設定を行う

Windowsで使っているディスプレイごとに設定を行うため、
Nintendo Switchなどの別で使っているディスプレイに設定するには少し工夫が必要です。
私は画面を複製して設定を行いました。

Switchで使用するディスプレイAとWindowsで使用するディスプレイBがあったとして、
Aのディスプレイの下部にEye Trackerを設置します。 そして設定のためAをWindowsに一旦つなげ、Windowsのディスプレイ設定からAとBを複製させ、
その状態でtobii experienceからディスプレイBの画面設定を行いました。

f:id:arata3da4:20210921130839p:plain
Windowsのディスプレイ設定

この状態で3.に書いたOBSの設定を行えば、ゲームのキャプチャの上にEye TrackingのBubbleを載せられるようになります。

使ってみた感想

  • なんか視線がうにょうにょ動いてて楽しい
  • 振り返る気持ちが微増する
    • あーあそこ見てなかったのかとか気付けるような気がしてる(ちゃんと振り返れていない
  • 何よりガジェットで遊ぶと楽しいのですべてヨシッ