OmniAICreator/Qiita-1.07M huggingface dataset:
CodePen で Intersection Observer の rootMargin が効かない

#はじめに
CodePenでIntersection Observerを利用したら、なんだかうまく機能していなかった。具体的には、rootMarginが効いていない。

#具体例
下記のコードはカードが中央線に重なった場合に背景をカードと同じ色にするように書かれていますが、下からカードが頭を出した瞬間に背景がその色に変更されています。つまり、交差判定がviewport(screen)全体になっています。
<p class="codepen" data-height="600" data-default-tab="result" data-slug-hash="QWqGRaB" data-user="zakime" style="height: 600px; 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/zakime/pen/QWqGRaB">
  Untitled</a> by Zakime (<a href="https://codepen.io/zakime">@zakime</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#解決方法
埋め込みの問題でその辺がアレってると思うので、~~いつ使うのかよく分からなかった~~ rootオプションで解決しました。
CodePenのプレビュー画面と同じ大きさの要素を作って固定し、その中で表示します。
具体的には、コード全体をwrapで囲ってfixedで固定。
<p class="codepen" data-height="600" data-default-tab="result" data-slug-hash="NWabVXM" data-user="zakime" style="height: 600; 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/zakime/pen/NWabVXM">
  How to get IntersectionObserver's rootMargin to work correctly in CodePen</a> by Zakime (<a href="https://codepen.io/zakime">@zakime</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

とりあえず問題解決！
※windowのscrollイベントを使ったコードを書いている場合は、コード全体を囲ったwrapのscrollイベントに変更しないと動かないので注意
競技プログラミングって？有名問題「Ants(蟻)」を解説

#はじめに
 先日、株式会社ゲームフリークさんの「ピカチュウきのみを探索中」という企画で、初めて競技プログラミングをする機会があったので、これを機に競技プログラミング(略して**競プロ**)について調べてみました。

#そもそも競技プログラミングって何？
競技プログラミングとは、いかに課題を解決するプログラムをスピーディーに正確に記述するかを競う、プログラミングコンテストの総称です。
<br>
競技プログラミングにはいくつかジャンルがありますが、ここでは最も代表的なジャンルである**アルゴリズム**について説明します。

#有名問題「Ants(蟻)」
競技プログラミングが実際にどんな問題を説いているのか、競プロ界の**超有名問題**を紹介したいと思います。その問題は「Ants(蟻)」と呼ばれ、内容は以下のようになります。

![Group3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1144456/234e8e45-f431-e315-22a6-7afb59fd2dee.png)
1.　棒の上に100匹の蟻がいます。
2.　棒は99cmで、蟻は棒の端から端に1cm間隔で並んでいます。
3.　左端の蟻は右を向いており、次の蟻は左を向いています。
4.　その後の蟻も右・左・右…左と交互を向いています。(右端の蟻は左を向いています。)
5.　上記の状態から、全ての蟻が秒速1cmで歩き出します。
6.　蟻は他の蟻に出会うと即座に反対を向いて歩き出します。
7.　蟻は棒の端にたどり着くと棒から落ちます。

この条件で、全ての蟻が棒から落ちるまでにかかる時間を求めよ。

#普通に解こうとしてみる
まず、一番左の蟻に注目してみましょう。
<br>
1.　蟻は開始と同時に右に歩き出します。
2.　右隣の蟻も左に歩き出すので、この2匹は0.5秒で出会います。
3.　蟻は左に向かって歩き出し、0.5秒後に棒から落ちます。

このように、一番端の蟻が落ちるまでにかかる時間を求めるのは簡単で、1秒かかると分かります。
<br>
しかし、内側の蟻になればなるほど、何度も他の蟻と出会うので計算量は増えていきます。
条件を全て設定してコンピュータに計算してもらうこともできますが、かなりの時間がかかってしまいます。
<br>
競技プログラミングでは、このように単純にコンピュータに計算させようとすると、**計算時間がかかりすぎて答えが求められない**ような問題が出題されます。

#「Ants」の解法

この問題は、**蟻を区別しない**ことで一瞬で答えを求めることができるようになります。
<br>
どういうことかというと、この問題では最後の蟻が落ちた時間を求めればいいので、蟻は区別しなくてもいい、蟻は「**出会って反対を向いた**」のではなく「**すれ違った**」としても全体の位置関係に支障がないということです。
<br>
蟻が方向を変えずに他の蟻とすれ違っていくと考えると、落ちるまでに一番時間がかかる蟻は**一番端の2匹**だといえます。
<br>
蟻は秒速1cmで99cmの棒を歩くので、この2匹が落ちるのにかかる時間は99秒です。
<br>
つまり、元の問題で最後の蟻が落ちるまでにかかる時間も99秒であると言えます。

#まとめ
問題「Ants」は、工夫によって圧倒的に少ない計算量で答えが求められる非常に良い例でした。
<br>
競技プログラミングでは、与えられた問題を**いかに少ない計算量で解くか**が重要だということがわかっていただけたでしょうか。こういったアルゴリズムを考える能力は、新たなシステムを必要とするモノづくりには欠かせないので、多くの企業も注目しています。

<br>
また、逆にいうと、プログラミングに必要な知識はほとんどないため、計算式を書き、答えを出力さえできれば誰でもコンテストに参加することができます。使用する言語も好きなものを選べるので、プログラミングをはじめたての方もぜひ挑戦してみてください。

#補足
問題「Ants」は「プログラミングコンテストチャレンジブック」という本で紹介されており、そのことから競プロ界では"**蟻本**"と呼ばれています。プログラミングコンテストの問題を通してアルゴリズムのしくみや考え方を楽しく習得できる本なので、興味を持った方はぜひ読んでみてください。
初心者がAndroidアプリを作ってみる　～入力したデータを扱う(前半:準備)～

#**初めに**

Androidアプリの自己学習として、シリーズ化を目指しています。
過去の記事を記載しておきますので、
Androidアプリは作ったことがないよ！
という方がいれば、以前の記事から見ていただければ幸いです。

リンク
・[初心者がAndroidアプリを作ってみる　～開発に必要なツールの設定～](https://qiita.com/t-namba/items/e9272635e9e85f25438d)
・[初心者がAndroidアプリを作ってみる　～プロジェクトの作成～](https://qiita.com/t-namba/items/69161387bee61c0187aa)
・[初心者がAndroidアプリを作ってみる　～アプリを起動する～](https://qiita.com/t-namba/items/ff24bca81be9459bd302)
・[初心者がAndroidアプリを作ってみる　～レイアウトエディタの画面構成について～]
(https://qiita.com/t-namba/items/7534f8e5b7039dbea130)
・[初心者がAndroidアプリを作ってみる　～Viewを配置する～]
(https://qiita.com/t-namba/items/006fa221f3404ee90af4)


本記事では簡単なインプットを行っていきます。
尚、記事は前後半で分割とし、今回はデータを扱うための準備までになります。


#**アプリのイメージ**
**入力欄とボタンを配置する**
まずどんなアプリを作成するかですが、今回はシンプルに
「入力欄に文字を入力して更新ボタンを押すことで、入力した文字でラベルを上書きする」
というアプリを作成することにします。

■アプリのイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/371826b2-26dc-4263-e87c-e0d19d56f03d.png)

想定している画面部品
・入力欄(EditText)
・ボタン(Button)
・ラベル(TextView)

※プロジェクトは新しく作成とする


**入力欄(EditText)の配置**
まずパレットから＜Plain Text＞をデザインエディタにドラッグ＆ドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/dd198f6c-5f4d-f22c-f0ee-ce5dbfa1742d.png)

配置後、属性から以下の通り設定します。
・id：「editText」
・hint：「テキストを入力してください」
・text：デフォルトの「Name」を削除して空にする




**ボタン(Button)の配置**
次に、パレットから＜Button＞をドラッグ＆ドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/1140997d-2755-c7a6-2372-1bb4fea34d49.png)

配置後、属性から以下の通り設定します。
・text：「更新」




**ラベル(TextView)の配置**

次に、パレットから＜TextView＞をドラッグ＆ドロップします。
特に設定の必要はありませんが、
TextSizeは上げておいた方が見やすいかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/582927d2-8f3a-530a-20db-74095ba99b99.png)


最後に、適当に制約を付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/b9f25eba-4917-2d6b-5ee1-d30e8a93ac73.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/a39bd74d-5fc7-ad58-c150-1dad41075dfd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/99ed3c99-a073-98ed-749d-e47aed0efa10.png)

これですべてのビューを配置できました。
一度アプリを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530030/0a957817-9f87-5b3c-5a83-c7030dfaf991.png)

画面配置まで完了したので前半はここで終わります。
次回は入力したデータを使ってラベルの上書きを行う予定です。


#**最後に**
本当は分割する予定ではなかったのですが、
上手くいかなかったので一旦分けます。
(ほぼほぼ動くんですが、更新ボタンが聞かない。。。)
目標は今年中の更新です。。。

今回もありがとうございました。
ArduinoUNOとI2Cスレーブを使ってACM1602Kに出力する


x 原因は、わからないが液晶がちらつく場合は、ウェートを調整してね!!


x まだ試していない　テスト済みで確認済2021/12/14
x 74hc164を使用

目的
I2Cスレーブのテスト


いろいろ
3分クッキング「レベル」に雑になってきた。
ハードの配線やI2Cマスタープログラムの作成が追い付いていない。
3分以下で作った(だからどうだ?)　2021/12/14一発大成功


```c++


#include <Arduino.h>
#include <Wire.h> //I2Cのヘッダー


#define DW digitalWrite

#define swdclk 4 // 4pin
#define swdio  3 // 3pin
#define en     2 // 2pin

//液晶に一文字送信する
void seg1(int v,int rs)
{
  for(int jj=0;jj<8;jj++){
    if( (v<<jj) & 0x80 ){      
      DW(swdio,1); //ビットが1
    } else {
      DW(swdio,0); //ビットが0
    }//endif
    DW(swdclk,1);
    DW(swdclk,0);
  }//for
  DW(swdio,rs);   
  DW(en,1); delay(1);
  DW(en,0);  
}//seg1

//文字列の表示
int ns_printf(char *str1) {
  //文字の中身がゼロか
  while(*str1){
    //一文字出力
    seg1( *str1 ++ , 1  );
  } //while
  //戻り値
  return(0);
}//ns_printf

//液晶の初期化コード
int lcd_int[]={
  0x30,0x30,0x30,0x38,0x08,0x01,0x06,0x08+0x04
};//lcd_init

//初期化
void setup() {
  //GPIO初期化
  pinMode(swdclk,OUTPUT);
  pinMode(swdio,OUTPUT);
  pinMode(en,OUTPUT);
  DW(en,0);

  //液晶の初期化
  for(int ii=0;ii<8;ii++){ 
    seg1( lcd_int[ii] , 0);delay(2);
  }//for

  //seg1(   0x01  , 0  ); delay(1000); //画面クリア

  seg1( 0x80+0x00 , 0  ); //1ライン目にカーソルを移動

  ns_printf("Hello World !"); //表示

  Serial.begin(9600);  //シリアルの通信速度を9600bpsにする。
  Serial.println("START"); //開始メッセージを表示
  Serial.println(' '); //改行
  delay(3000); //3秒待つ


  seg1(   0x01  , 0  ); delay(5); //画面クリア


  Wire.begin(0x40);  //I2Cスレーブアドレスの設定
  Wire.onReceive(receiveEvent); //データが来ると呼ばれる関数


}//setup

//無限ループ
void loop() {}

//レシーブイベント
void receiveEvent(int howMany) {

  int x = Wire.read(); //I2C受信データの読み込み
  Serial.println(x); //受信した数値の表示

  //一文字出力
  seg1( x, 1  );

}//receiveEvent




```


テスト用　I2Cマスター nucleo-f303k8  適当にリセット



```c++


//I2C_OUT_HEL_303_1

#include "mbed.h"

//GPIOの初期化
DigitalOut myled(PB_3);//LED1

//シリアルの初期化
//Serial pc(SERIAL_TX, SERIAL_RX); //nucleo 303

//I2Cの初期化
I2C i2c(I2C_SDA, I2C_SCL); //nucleo 303

//文字列の表示 nana_seg
int ns_printf(char *str1) {

    //文字の中身がゼロか
    while(*str1){

        //一文字出力
        i2c.write(0x80,   &(*str1 ++) , 1);
        wait_ms(1);

    } //while

    //戻り値
    return(0);

}//ns_printf



//メイン関数
int main()
{

    ns_printf("Hello World !");

    //無限ループ
    while(1) {

        //LEDの点滅
        myled = 1;
        wait_ms(100);
        myled = 0;
        wait_ms(100);

    }//while

}//main





```
社内勉強会で心がけていること

この記事は、[KLab Engineer Advent Calendar 2021](https://qiita.com/advent-calendar/2021/klab) の14日目です

初めまして、初投稿のtekun0701です。初めましてすぎてQiitaの勝手がよくわかっていないですがよろしくお願いします。（投稿するまでメールアドレス認証していないことに気づかなかったぐらいです）

## 自己紹介
サーバーエンジニア出身で、今はマネジメントが中心のエンジニアです。が、コードを見るのは好きなのでプロジェクト内のコードにPull Requestはよく投げる、そんな感じのエンジニアです。

## 社内勉強会をしていました

私といえば、KLab社内で今年1月から2週間に1回のペースで自身の持っている知識を話す社内勉強会を開催していました。今回はその話をします。

## 内容について

KLabといえば、スマートフォン中心にゲーム開発、運営をしている会社ですね。私の扱った内容としては、以下となります。(全14回です)
<dl>
  <dt>前半6回(運営編)</dt>
  <dd>アップデートをどのように行なっているのか、を中心としては運営作業をする上で必要な知識の講座</dd>
  <dt>後半8回(実装編)</dt>
  <dd>ゲームのクライアントコード、サーバーコードの構成はどのようになっているのかという実装する上で必要な知識の講座(ただ、私はサーバーエンジニア出身なのでサーバーコード中心とした講座)</dd>
</dl>
多忙な時期も多かったため都度リスケしつつ勉強会した結果今年1月から10月までの開催で全14回になりました。
最初から全14回だったわけではなく、話したい内容を毎回講座を終えるごとに考えながら準備していたら全14回になりました。


## なぜ勉強会をしたのか
- 自身や他人がしている作業内容を理解してもらうため
  - この作業はこれを目的として行われている　といったこと
  - 自分が全体のシステムのうちこの部分を担当している というところを理解させることでやる気の向上になる
- ゲームを運営する上でのシステムの理解
  - そもそもどのようにしてゲームの運営を行なっているのか　という疑問の解消
  - このような疑問は先輩に聞いてもなかなか説明するのが面倒、というのもあるので動画で残して見返せるようにしておきたかった
- 今後のプロジェクトへの参考として
  - 今回の勉強会では私がいるプロジェクト(とあるスマートフォンゲーム)のシステムを例に解説したが、別のプロジェクトでは違うシステムになっていることもあるため、その比較や、今後のプロジェクトに参考とするために勉強会を開きました

## 発表資料を作る上で心がけていること
- 説明する内容について、自分がどのように理解したのか、という理解していった時の思考プロセスを思い出して、難しくなりすぎないような導入を作る
- 説明が多くなりすぎないようになぜそうなったのか(なぜそのようなシステムになったのか)の背景を入れる
- 資料を作る上で自分がなんとなくしか理解できていない点は、事前に調べたり、社内で聞いたりして補完していく
- 説明するのが難しい箇所は、発表資料の中には入れずに、別のドキュメントに書いてリンクだけ貼る　ということも行なっている(そのため、頑張って調べたけど説明するには難しいから補足資料だけ追加、ということもします)

## 発表当日
- 開催前に社内のプログラマの多くが参加しているslackの部屋で宣伝し、資料とオンライン会議のURLを貼っておく
- (弊社は直近リモートで作業することが多いがゆえ)オンライン開催のため、ラジオ感覚で聞く人も大歓迎
- 開始時間に遅刻する人もいるので開始時間5分後から話し始める
- 話終わったものは録画しているため、後から会社に入ってきた人でも見返せるようにしている
- あと私の中で重要なこととしては・・・、**発表練習は一切しないこと**
  - 外部で発表するわけではなく社内勉強会のためリソースを割きすぎないように準備しています
  - ただ、動画も撮っているので、完全に話す発言が飛んでしまうとまずいのである程度イメージつけてから勉強会開くようにしています。

## 勉強会してみて
- 発表者である私からすると、なんとなくになっている知識を整理し、どのように説明すればいいのか、を考えながら勉強会したので、発表した内容についてより理解が深まったと感じています
- 録画した動画を見せることも最近だと多いのですが、動画あると理解が深まりやすいという評判をいただくことが多く、勉強会してみて良かったと感じています

私は教えるのが好きな面もあるので、今後とも持っている知識を社内で浸透させる動きをしていきたいと思っています。
資料内容は非公開です、一部を切り出して外部発表に使い回すことは有り得ますが、、
モールス信号でツイートしたかった

この記事は[クソアプリ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kuso-app)の15日目の記事です。

モールス信号ってかっこいいですよね？
**「あーモールス信号でツイートしたいなー」**
と思ったときに便利なアプリを作りました！

## 作ったもの

![スクリーンショット 2021-12-14 1.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/0bec71e1-c922-bc09-29a1-255b5889bc72.png)

■[morse-tweet](https://morse-tweet.web.app/)

今回作ったのは
・ひらがななどをモールス信号に変換して
・モールス信号をツイートできる
アプリです！シンプル！

ちょっとはずかしいこともモールス信号なら
すぐわからないのがいいですね(\*´ω｀\*)

![スクリーンショット 2021-12-14 1.14.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/8cd31796-b5bd-b7c9-8191-059807b1e089.png)

![スクリーンショット 2021-12-14 1.30.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/048a6ed9-d898-003d-9341-50870a26d01e.png)

モールス信号をつぶやきたくなったときに
ぜひ使ってみてください(\*´ω｀\*)!!


## 使った技術

今回はこんな感じの構成で作ってます！

- フロントエンド ... [Nuxt.js](https://nuxtjs.org/)/TypeScript/[Tailwind CSS](https://tailwindcss.com/)
- デプロイ ... [Firebase Hosting](https://firebase.google.com/docs/hosting?hl=ja)
- データ変換 ... [SSSAPI](https://sssapi.app)

基本はよく使ってるNuxt＋Firebaseの構成。

中身は単に文字を変換してるだけですが、
JSONの手書きはめんどくさいので、SSSAPIで変換。

![スクリーンショット 2021-12-14 1.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/1b60024d-39a8-0ec7-9138-f9f78ea56220.png)

```json
{
  "0": {
    "code": "－－－－－"
  },
  "1": {
    "code": "・－－－－"
  },
  "2": {
    "code": "・・－－－"
  },
  "3": {
// ...
```

全体をマップに変換するオプションもあるので、そのまま使える形に。

[Tailwind](https://tailwindcss.com/)は、はじめて使ってみたけど、
CSSを書かずにサクサクとデザインできてよい感じ(\*´ω｀\*)

ただ普段[Buefy](https://buefy.org/)を使っているので、UIコンポーネントがないはつらい。。
なので、[daisyUI](https://daisyui.com/)もあわせて使ってます。

## おわりに

クソアプリの初参加作品がこれでいいのか。。？
と思いながら作りました(\*´ω｀\*)

**「モールス信号でツイートしたいなー」**
と思ったときにぜひどうぞ！

■[morse-tweet](https://morse-tweet.web.app/)
Next2D Framework入門

MVVM（Model-View-ViewModel）パターンを利用し、規模を問わず効率的な開発が行える事を目的としたNext2D専用のフレームワークです。

# プロジェクトを開始する

プロジェクトを開始するのはとても簡単です。
下記のコマンドで自動的に必要な環境を構築します。

```linux
npx create-next2d-app app-name
```
※1 `app-name`は任意部分なので、プロジェクト名などを入れてください。
※2 Node >= 14.0.0 及び npm >= 5.6 の環境が必要です。

# ディレクトリ構造
コマンドが終了すると、下記のディレクトリ構造が出来上がっています。

```linux
app-name
├── src
│   ├── index.js
│   ├── App.js
│   ├── Packages.js // このファイルは自動的に生成されます。
│   │
│   ├── component
│   │   └── default empty
│   │
│   ├── config
│   │   ├── config.json  // 環境変数などを管理するJSON
│   │   ├── routing.json // ページのルーティングを管理するJSON
│   │   ├── stage.json   // 表示エリア(Stage)の設定を管理する JSON
│   │   └── Config.js    // このファイルは上記のJSONを読み込んで、自動的に生成されます。
│   │
│   ├── content // NoCode Toolと連携したコンテンツディレクトリ
│   │   ├── TopContent.js
│   │   └── HomeContent.js
│   │
│   ├── image
│   │   └── default empty
│   │
│   ├── model // ロジックはこのディレクトリにまとめます。
│   │   ├── callbask
│   │   │   └── Background.js
│   │   ├── api
│   │   │   └── HomeText.js
│   │   └── default empty
│   │
│   └── view // シーン(ページ)毎にViewとViewModelを準備します。
│       ├── top
│       │   ├── TopView.js
│       │   └── TopViewModel.js
│       └── home
│           ├── HomeView.js
│           └── HomeViewModel.js
│
└── __tests__ // ロジックテストは大切ですw
    └── model
        └── default empty
```

# Hello, World.

プロジェクトのディレクトリに移動して、サンプルを起動します。

```linux
cd app-name
npm start
```

## TOPページ

`Click Me.`をクリックもしくはタップすると、次のシーン(ページ)に移動します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80502/9d2617d6-4861-571b-f828-f3b924d07df5.png" width="600">

## HOMEページ

`Click Me.`をクリックもしくはタップすると、このHomeシーン(ページ)が描画されます。
`Next2D Framework`はSPA(Single Page Application)に対応しており、意外とゲームでは実現されなかったURLでの直接的なアクセスを可能にしてます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80502/92a03756-dd53-4810-c401-683d8a4450e5.png" width="600">
URLでの直接アクセス、ブラウザの戻る機能でのシーン遷移にも対応してます。
ゲームをしていて、戻る機能を誤って押してしまいオープニングページから始まる。。。なんて事を体験された方は多いのではないでしょうか？もしくは、行きたい画面に早く遷移したいけどオープニングページからマイページに移動して友達を検索して移動。。。など手順が多く億劫な経験をされた方もいると思います。
`Next2D Framework`は上記のようなストレスを減らし、快適にゲームが行えるよう工夫してます。また、ローディング画面もデフォルトで実装しているなど、開発する方の手間も削減する工夫もしてます。

# フローチャート
`Next2D Framework`は下記の図の順で画面の準備を行います。
<img src="https://raw.githubusercontent.com/Next2D/Framework/main/Framework_Flowchart.svg">

今日は是非、「Hello, World.」を表示する体験をしてみてください。
明日からはNext2D Frameworkの機能を紹介できればと思います。
TypeScriptの「こういう時ってどう書くの？」〜React Component編〜

## 関数コンポーネントに型を付けたい！

### `React.VFC`
`React.VFC`は引数に**Propsのオブジェクト**を受け取り、関数コンポーネントの型を作ります。

```jsx
import React, { VFC } from 'react';

type Props = {
  propsA: string;
  propsB: number
};

export const Component: VFC<Props> = (props) => {
  return (
    // ...
  );
};
```


似たような型に、`React.FC`がありますが、暗黙的にchildrenが含まれてしまいます。
今後、`React.FC`からchildrenが抹消されると言われているため、なるべく`React.VFC`を使って書き、
childrenが削除されて`React.VFC`が非推奨になった時に`React.FC`に置き換えましょう。



### `() => JSX.Element`
`React.VFC`を使わずとも、愚直に1つずつ型を書く方法もあります。
関数コンポーネントは`JSX.Element`を返すため、あとはPropsに型をつけてあげるだけです。

```jsx
import React, { VFC } from 'react';

type Props = {
  propsA: string;
  propsB: number
};

export const Component = ({propsA, propsB}: Props): JSX.Element => {
  return (
    // ...
  );
};
```

ちなみに私は上のように書いたことはないですが、
`React.VFC`非推奨問題の対策として使っている人もいるみたいです。

## コンポーネントのPropsの型を使いたい！
### `React.ComponentProps`
`React.ComponentProps`を使うことで、定義したComponentのProps部分のみの型を抽出することができます。

```jsx
type CardProps = ComponentProps<typeof Card>;
```

refが含まれるかを明示的にしたい場合は、ComponentPropsではなく
`ComponentPropsWithoutRef`/`ComponentPropsWithRef`を使うと良さそうです。


## 〇〇要素の属性を全部Propsで渡せるように型定義したい！
### `JSX.IntrinsicElements['html要素名']`

リンクのComponentで「aタグの全ての属性をPropsで渡せるようにしたい」というケースがあるかもしれません。
そのような時は、`JSX.IntrinsicElements['html要素名']`を使うと良いです。

```jsx
import React, { VFC } from 'react';

type Props = JSX.IntrinsicElements['a'];

export Link: VFC<Props> = ({...attrs}) => {
  return (
    <a {...attrs}>リンク</a>
  );
};
```

## `children` や `JSX` を Propsで渡したい！
### `React.ReactNode` / `React.ReactChild` / `React.ReactElement`

```jsx
import React, { VFC, ReactNode } from 'react';

type Props = {
  children: ReactNode;
};
```

### 使い分け
基本 `React.ReactNode`を使えば良いです。
より厳格に「string型は許容したくない！」「React.fragmentもだめ！」というケースのみ、
`React.ReactChild `や `React.ReactElement`を使いましょう。





▼ 参考

https://dackdive.hateblo.jp/entry/2019/08/07/090000
「リモートブランチをローカルへ」 「一旦退避&カムバック」

以前部下の方々が困っていたため、打ち込んでたのをそのまま共有したGitのコマンドです。

## リモートブランチをローカルへ

```
git fetch
//リモートブランチの確認
git branch -r
//リモートをローカルに持ってくる
git checkout -b 新規ローカルブランチ リモートブランチ
git checkout -b branch origin/feature/branch
```

## 一旦退避 & カムバック
```
git stash
git stash apply stash@{0}
```
【IoT】冬でも水分を摂ろう！

こんにちは！
こちらの記事はWorks Human Intelligence Advent Calendar 2021 14日目の記事です。

普段は大学生をしながら、個人開発をしたりイベントに参加したりしています。
今回はobnizを使って、自分の困っていることをHackしてみました！

## わたしの困りごと
水分を摂るのがめちゃくちゃヘタクソで、1回あたりペットボトルキャップ1杯分で満足してしまいます。
最近、気づいたのが普通の人は"ごく"で終わるのではなく、"ごくごく"することに気づき練習中です。今まで、他の人は一回あたり飲み込める量が多いのかと思っていました。。。
なので、ペットボトルを買っても全然消費できない日もあります。
ダイエットのサイトには1日1リットルから2リットル水分を摂ろう！とよくあるので、せめて１リットル飲むようにしたいです。
参考: https://www.suntory.co.jp/eco/teigen/jiten/life/01/

特に冬場になるとみなさんもあまり水分を摂らないのではないでしょうか。

## つくるもの
水分を一定の時間まで量が減っていなかったら、光ってお知らせしてくれるデバイスを作ります。
LINE BotなどのBotも検討しましたが、LEDが光ってくれるのが1番気がつきそうだと思いました！

## 用意するもの

今回はお家であるもので作りたかったので、以下を用意しました！

|  部品  |  補足  |
| ---- | ---- |
|  obniz本体  | obniz Board 1Y |
|  ロードセル  |    |
|  赤色LED  |  抵抗機能非搭載  |
|  使いたいタンブラーやマグカップ |  ロードセルの上に載せれるもの |

## デモ動画
使い方は、2時間でコップに入っている一定の量を飲むのを目標にして、飲めていなかったらLEDで光ってお知らせしてくれます。
コップが空になったら自分で飲み物を足しに行きます。ずっと座っているのはあまり健康的によくないのでそのような仕様にしました！！

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520177/53da1bc7-c987-fc04-6d89-c5088e507b49.gif)

## 配線
ロードセルは、gnd:8, dout:9, sck:10, vcc:11に接続し、
LEDは、anode: 0, cathode: 1  に接続しました。

## ソースコード

```html
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@3.x/obniz.js" crossorigin="anonymous" ></script>
  </head>
  <body>
    <div id="obniz-debug"></div>
    <div class="container">
      <div class="text-center">
        <h3>冬でも水分摂ろうよ！！</h3>
      </div>
    </div>

    <script>
      //type in your obniz ID
      var obniz = new Obniz("OBNIZ_ID_HERE");
      var sensor;

      //during obniz connectionv
      obniz.onconnect = async function() {
        //wire LED to obniz
        //io0: anode
        //io1: cathode
        var led = obniz.wired("LED", { anode: 0, cathode: 1 });

        // Initialize Temp Sensor
        sensor = obniz.wired("hx711" , {gnd:8, dout:9, sck:10, vcc:11});

        // 重量測定
        sensor.setScale(441.9);
        var value = await sensor.getValueWait(5); //5 times average
        console.log('grams:' + value);

        while (value > 400 ) {
          led.on();
          sensor.setScale(441.9);
          var value = await sensor.getValueWait(40); //40 times average
          console.log('grams:' + value);
        }
        obniz.display.print("😁👍");

        // sleep next 120 minutes. 120分間スリープをデバイスに指示
        obniz.sleepMinute(120);
      };
    </script>
  </body>
</html>
```
https://github.com/mikik0/water-reminder

setScaleやsleepMinuteの値をいじって、自分好みにカスタマイズしてみてください！！


## おわりに
スリープモード機能付きobnizを購入していたのに使いこなせていなかったので、今回試せてよかったです！！
とても優秀🎉
これからも水分をきちんと摂れるようにどんどん改良していこうと思います！！
今回使用した[obniz](https://obniz.com/ja/products/obnizboard)は、おもしろいことたくさんできるので皆さんもぜひ一緒に遊びましょう！！


最後まで読んでいただき、ありがとうございました！
継承　〜魔法戦士への道〜

## 経緯
1年ほど前に上司にペアプロをしてもらった際に継承について知識があやふやだったため、有名なRPGの例えで説明してくれました。
この例え自体知ってはいたけど、上司の説明が一番個人的にわかりやすかったです。自分も部下に全く同じことを喋りたかったのでメモ帳に封印していたのですが、使う機会がないので投稿。

## 継承
1.一つのクラスは一つの親クラスを持っていて2つは持てない
ex.魔法使いクラスがあって、戦士クラスがあるとする

2.勇者タロウ(以降太郎)は魔法使いクラスを継承して太郎クラスになっているとする
= だから太郎は魔法が使える

けど、太郎は剣で戦うこともできるから剣の継承もしたい...
でも太郎は魔法使いを継承してるからできない...

**「だから、魔法使いと戦士をtraitにすればどちらも継承して魔法戦士太郎」**

つまり、多重継承がPHPだとできないからそれを実現しようとしている

共通の親がいないとした時にそれぞれの親を一箇所に書きたいときにはtrait使ってuseしちゃえば良い
FCP Scroll - スクロール中にセクションが中央に固定されて中のコンテンツが進むアレ

#はじめに
**"スクロール中にセクションが中央に固定されて中のコンテンツが進むアレ"**を実装しようとしたところ、相応の記事が見当たらなかった（見つけられなかった）ので備忘録として載せておきます。

#アレってどれ？
アレってどれだよって感じなので簡単なDEMO貼っておきます。
<p class="codepen" data-height="700" data-default-tab="result" data-slug-hash="VwMmyaR" data-user="zakime" style="height: 700px; 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/zakime/pen/VwMmyaR">
  FCP-Scroll (fixed center position scroll)</a> by Zakime (<a href="https://codepen.io/zakime">@zakime</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#FCP Scroll
名前が分からないので**勝手に**"FCP Scroll(fixed center position scroll)"と名付けました。
正式な名前があれば教えてください。
また、すでに王道な手法やりライブラリがあればぜひ教えてください。


#作り方

1. 表示したいコンテンツ(群)をdivで囲んでposition:fixedで画面中央に固定する。この時、囲むfivの高さを100vh未満にしたい場合は上下のdivも一緒に囲んでおく必要がある。
2. 切り替えたいコンテンツの数だけそれに対応する判定用のdivを作る。
3. screenの中央を監視（[IntersectionObserver](https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API)）して、判定用のdivが中央線に重なっているときに、そのdivに対応したコンテンツを表示する。

お前の語彙力雑魚過ぎて意味不明なんだけどって感じだと思うので下記参照。
~~図を描いたり文字を書くのが面倒なわけではありません。~~
<p class="codepen" data-height="700" data-default-tab="result" data-slug-hash="dyVOaqN" data-user="zakime" style="height: 700px; 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/zakime/pen/dyVOaqN">
  Base of  FCP-Scroll</a> by Zakime (<a href="https://codepen.io/zakime">@zakime</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


中のコンテンツ次第で書き方が変わるので汎用的なコードにはなりませんが、骨組みのところは変わらないのでに自分で書くのダルいって方は参考にしてください。
Remixの特徴と思想について

# はじめに
こんにちは。 KDDIアジャイル開発センターの小板橋です。 この記事は、[KDDI Engineer&Designer Advent Calendar 2021](https://qiita.com/advent-calendar/2021/engineer-designer)の14日目の記事です。

* 2021/11/23にReact Routerの制作者(Michael JacksonとRyan Florence)が新たに作成した[Remix](https://remix.run/)のV1.0が正式リリースされました。
* 今回は、このRemixの特徴と思想についてまとめていきます。

# Remixとは
* Remixとは、React製のフルスタックフレームワークでファイルベースのルーティングができます。(Next.jsと同様)
* remixでは、SSGなどであらかじめレンダリングしておく(事前にビルドをして静的サイトを作成しておく)のではなく、サーバサイドレンダリングやfetch APIを利用して画面表示のデータをやり取りするようです。
* Fetch APIを最大限使うことで**Cache control**でSSGと同じようなことしています。

## 特徴1: なので、SSGの機能を含んでいないということになります。

なぜなのか、それは秒ごとに変わるコンテンツに対応させるにはSSGでは無理だったからです。
なので、最近ではSSGでも動的なデータを含むサイト作成する手段として生まれたのが、ISRです。

あとは、SSGの欠点として例えば、ビルド時間がかかるや、サイトの変更をするまでに一度ビルドしないといけないことや、認証が必要なサービスには利用できないといったことです。

* RimixではSSRとFetch APIを利用すると冒頭で説明しましたが、そうすると画面表示までのパフォーマンスに影響を与えるのではないかという問題が現れます。

**それを解決する方法が2つある。**

* **１つ目の解決策 : CDN環境での実行です。**ただ、ここで扱うCDN環境はCloudflareのようなものを指しています。(**分散サーバー/分散データベースをエッジで実行できる環境**)
* なので、**現在は、Cloudflareのみに対応している**状況です。


* **2つ目の解決策 : ファイルベースのルーティングです。**

* React Router v6の機能でもあるNestedRouteingをサポートしています。
* これを使うと、**コンポーネント間の関連する部分のみを更新することができます。**

例えば、同じようなファイルベースのルーティングをするNext.jsの挙動だと、pageを移動するとそれまでのコンポーネントが全てマウントされ直される(内部の状態は失われる)ので、関連するものを再度マウントする必要がありました。
NestedRouteingでは、全体に関連するレイアウトコンポーネントを作ることなく、共通化することが簡単に出来ます。
また、Remixがファイル構造を知っていることで不必要にFetchされることがなくなるのも特徴の一つです。


## 特徴その2: cache-headerの設定

* Remixでは、ページコンポーネントごとにheadersをexportするだけで、HTTP headerをコントロールできます。
* それを利用することで、Cache-Control HTTPヘッダーを調整することができます。


## 特徴その3: 環境依存がない

* Next.jsでは、VercelにデプロイすることでISRの恩恵やパフォーマンスの最適化ができます。(もちろん他の環境へのデプロイはできるが)
* Remixの場合、Vercel/AWS Lambda/Cloudflareなどのアダプターが用意されている



# 参考資料

https://remix.run/docs/en/v1/pages/philosophy

https://dev.classmethod.jp/articles/qucikstart-remix-framework/

https://zenn.dev/steelydylan/articles/remix-nextjs-comparison

https://zenn.dev/kaa_a_zu/articles/fbd06ca2cc3b86
hashmapの使い方

# タイトルの通り
https://atcoder.jp/contests/abc231/tasks/abc231_b
に相当躓いた。
解いた人のソースを見てみるとどうやらhashmapを使えば簡単に書けるらしい。
しかしながらhashmapってなんぞや状態なので調べてみた
https://moshg.github.io/rust-std-ja/std/collections/struct.HashMap.html#method.entry
公式の解説だけどよくわからん
https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB
を見てみるとどうやら配列の添え字に文字列を使えるようにした構造らしい。
今回のやつを使うのには確かに便利。
というわけで頭を動かしがてら自分で書いてみた
サンプルみているとentryとor_insertでいけそう.
あとはイテレータになるみたいなのでmaxとって終わりか。
hashmapの要素はタプルと同じ感じで取り出せそうなのでそれをうまいこと使う。

```rust:test.rs
let mut map: HashMap<&str, u32> = HashMap::new();
map.entry("poneyland").or_insert(12);
map.entry("poneyla").or_insert(2);

println!("{:?}",map.iter());
```

を実行したときが
[("poneyland", 12), ("poneyla", 2)]
になる。

というわけで解答。

```rust:test.rs
use proconio::input;
use std::collections::{HashMap, HashSet};

fn main() {
  input! {
    n: usize,
    mut S: [String; n]
}

let mut map = HashMap::new();
for i in S{
*map.entry(i).or_insert(0) +=1;
}

let ans = map.iter().max_by_key(|x| x.1).unwrap();

  println!("{}",ans.0);
}

```

参考にした人の解答とほぼ同じ。
精進したいねえ
array_flip

#なんか何度もググっちゃうarray_flip
よく「あれ、これなんだっけ」ってなるので、投稿。

## array_flip

array array_flip ( array $array )
array_flip() は、配列を反転して返す。 すなわち、array のキーが値となり、 array の値がキーとなる。

array の値は有効なキーを必要とすることに注意。 すなわち、キーは、integer または string である必要がある。
ある値が間違った型である場合、 警告が出力され、問題のこのキー/値の組は結果には含まれない。

ある値が複数回出現した場合、最後のキーがその値として使用され、 その他の値は失われる。

パラメータ
array
反転を行うキー/値の組。

返り値
成功した場合に反転した配列、失敗した場合に NULL を返す。

ちなみに、以前拝見したQiitaの記事でarray_keysとarray_flipだと、array_keysの方が処理速度が早いみたいです。
array_flipで同様の実装をしたことがあったので、次に似たようなケースがあればarray_keysを使いたいなぁと思います。
以下参考文献
https://qiita.com/watamana/items/2557da3536d9b4b4c344
ラズベリーパイの日記

去年の1月ごろにラジコン作成の勉強のつもりで購入したのだが、
Webアプリ作成の勉強のため、久々に使うことにした。

入門に関しては以下サイトを参照ください。

https://deviceplus.jp/hobby/raspberrypi4_01/

ちなみにラズベリーパイのOSはLinux（Debian）である。
オープンソースのため無料で利用できる。（有償のものもある。）

状況は、デスクトップ画面は開けたが、日本語入力とアップデートをしていない。
この状態から再開することにした。

アップデートは以下コマンドを使用した

```
subo apd update
```
しかし、1発ではうまく行かず、何回かやってようやく成功した。

続いて、日本語入力ができなかったため、以下サイトを参照した。

https://www.yutry.net/pc/debian/debian-nihongo

日本語入力に必要な　uim　anthy　を導入した。
前者はフレームワーク（土台となるプログラム）、後者は日本語入力のシステムだそうだ。

日本語入力まで完了した。

続いて、LAMPと呼ばれる。Webサイト作成の準備を始めたいと思う。
Remarkでmarkdownのformatを設定する

VSCode使い始めてからずっとpretter使っていたけど、他の人とmd編集するようになってからpretterの「全角と半角の間に謎スペース入る問題」に対処するのがめんどくさくなったので[Remark (remarkjs/vscode-remark)](https://github.com/remarkjs/vscode-remark)を試し中。

マーケットプレイスのURLはこれかな？(mrmlncさんからremarkjsに管理が移ったのか？)

- <https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-remark>

`settings.json`でいろいろ設定できるんだけど、いまんとこ入れてる設定はこれくらい。

```json
{
    // 前略
    "remark.format": {
        "rules": {
            "bullet": "-",
            "listItemIndent": "1",
            "fences": true
        }
    }
}
```

アップデートがあれば追記する。
Reactの基本について解説してみた(学習まとめ)

#初めに(前書き)

今回は、Reactの基本について解説していきたいと思います。
Reactは、Facebookが開発したWebアプリケーションのフレームワークです。
巷では、「フレームワーク３強」の一つに数えられるものになります。
※「フレームワーク３強」とは、「Vue」「React」「Angular」のことです。
※日本では、「Vue」が一番人気のようですが・・・。



#本題(本文)
Reactは、従来のネイティヴ―アプリ(＝デスクトップ―アプリ)のような画面のチラツキや動作の硬直の少ないストレスレスなWebアプリケーション(＝SPA)を開発するためのフレームワークです。
ここで、ReactではWebアプリの画面(＝ヴュー)を「コンポーネント」(＝UI部品)と呼ばれる単位で構成します。また、ReactではWebアプリの画面をクライアント＆サーバー間で非同期にやりとりします。
※「非同期」とは、クライアントがページ単位ではなく、コンポーネント単位でサーバーからJSON形式のデータを取得・読込みすること。さらには、クライアントがサーバーからのレスポンスを待たずに処理できる範囲で処理を進めるということです。


さらに、Reactでは各コンポーネントに「ステート」と呼ばれるものを持たせています。
※ステートとは、コンポーネント上に表示されるテキストや、コンポーネントの画面上での振舞いを決めるためのフラッグ等の値のことです。
各コンポーネントの間では親子関係を形成することができます。たとえば、親コンポーネントの更新(＝状態の変化)が子コンポーネントに伝達されることで、親コンポ－ネントが再描画される際に、これに伴って子コンポーネントも再描画されます。
この際、「プロップス」と呼ばれるものを利用します。各コンポーネントは、このプロップスを介することでステートの更新を行います。プロップス自体は、「ステートにセットする更新後の値(＝変数)」と「フレームワークがステートを更新する動作(＝関数)」により構成されます。
※親コンポーネントから子コンポーネントへと、「バケツリレー式」にプロップスが渡されることで、この仕組みを実現しています。
※プロップスは、各コンポーネントの画面上での動作・振舞いを動的に変更する際にも用いられます。具体的には、コンポーネントがプロップスを外部から取り込んで、そのプロップスに持たされている情報(＝変数と関数)に応じて処理を変えることで動作・振舞いを決定します。



#終わりに(後書き)

今回は、Reactの基本について解説してみました。
今後、機会があれば、具体的なコードを交えての解説もしてみたいと思います。
それではまた～。
defaultString

# defaultString
 **変換対象の文字列がNULLの場合、空文字に変換する。** 

nullがわたる可能性がある箇所で、空文字を渡したかったので以下のように実装していたのですが、こういったメソッドがあるということを知ったので投稿します。
以下自分が書いた感じのコード

```java
             while (rs.next()) {
            	 String number = "";
            	 String cumulative = "";
            	 String sNumber = "";
            	 String sCumulative = "";
            	 String nNumber = "";
            	 String nCumulative = "";

            	 cumulative = rs.getString("TOTALCUMULATIVE");
            	 sNumber = rs.getString("S_NUMBER");
                 sCumulative = rs.getString("S_CUMULATIVE");
            	 nNumber = rs.getString("N_NUMBER");
             	 nCumulative = rs.getString("N_CUMULATIVE");

                 printData = new PrintData4(
                 		 number,
                 		 cumulative,
                 		 sNumber,
                 		 sCumulative,
                 		 nNumber,
                 		 nCumulative
                 );
                 printDataList.add(printData);
             }
```

defaultStringを使うとしたら

```java
             while (rs.next()) {
            	 String number = StringUtils.defaultString(rs.getString("DEVIATION"));
            	 String cumulative = StringUtils.defaultString(rs.getString("TOTALCUMULATIVE"));
            	 String sNumber = StringUtils.defaultString(rs.getString("S_NUMBER"));
            	 String sCumulative = StringUtils.defaultString(rs.getString("S_CUMULATIVE"));
            	 String nNumber = StringUtils.defaultString(rs.getString("N_NUMBER"));
            	 String nCumulative = StringUtils.defaultString(rs.getString("N_CUMULATIVE"));

                 printData = new PrintData(
                 		 number,
                 		 cumulative,
                 		 sNumber,
                 		 sCumulative,
                 		 nNumber,
                 		 nCumulative
                 );
                 printDataList.add(printData);
             }
```

こんなかんじかな？コンパクトになる。
StringUtilsクラスとは文字列を扱う時に便利なメソッドやメンバ変数が集まっているクラスです。
アトミックデザインメモ

## アトミックデザインの単位

Atoms（原子）
UI構成の最小単位。ボタン・ラベルなど。

Molecules（分子）
Atomsを組み合わせて作る構成物。
ラベル(Atom)+ボタン(Atom)+インプット(Atom)=入力フォーム(Molecules)

Organisms（有機体）
原子や分子を組み合わせて作る構成物。
ラベル複数(Atom)+入力フォーム(Molecules)=サイドバー(Organisms)

Templates（テンプレート）
原子や分子、有機体を組み合わせて作るサイト全体の構成。
ヘッダー(Organisms)+サイドバー(Organisms)+フッター(Organisms)=サイト構成（template）

Pages（ページ）
テンプレートに独自のコンテンツを入力したアトミックデザインの最終形。
サイト構成(template)+文章・画像などの情報=サイトの完成品(Pages)


## 自分のディレクトリ構成
|- screens：各画面単位で利用するComponentを格納する
　|- component：複数の画面で利用する部品をまとめるフォルダ
　|　|- organisms：AtomicDesignでいうOrganismsでAtomsやMoleculesを組み合わせた小さめの部品。
　|　　|- molecules：AtomicDesignでいうMoleculesでAtomsを組み合わせた小さめの部品。
　|　　　|- atoms：AtomicDesignでいうAtomsで最小の部品。
　|
　|- container：AtomicDesignでいうPagesで一番の親
　　|- template：AtomicDesignでいうTemplatesでcontainerの子
　　　|- organisms：このページでしか使わない少し大きめの部品。AtomicDesignでいうOrganismsでcontainerの子
リリースに最低限必要なテストをどう見極めるか

# はじめに
先日「[ソフトウェアテスト自動化カンファレンス](https://testautomationresearch.connpass.com/event/228204/)」に登壇させていただいたのですが、懇親会にて「リリースに最低限必要なテストをどう見極めるか？」という議論が起こりました。面白かったので私なりの考えを書いてみようと思います。

# リリースの頻度とテスト
かつてのソフトウェア開発では、リリース後の変更・修正コストが高いなどの要因から「完璧な製品をリリースし、その後は基本的に変更しない」考え方が主流であり、リリース前に様々な可能性を考慮する必要がありました。必然的に、ソフトウェアはいちどに多くの複雑さを扱うことになり、その複雑さを検証するためのテストもまた複雑なものになりました。複雑なドメインを分析し、膨大な組み合わせのテストを考え、重箱の隅をつつくようなテストを考えることが求められました。
しかし、リリース後の変更・修正コストが徐々に下がってきたなどの要因から「必要最低限の製品をリリースし、その後は継続・反復的に開発し続ける」考え方に時代が変わってきました。例えば、リリースサイクルを1週間と決めて、サイクルごとにリリースを繰り返すイメージです。リリースごとに求められるものは、リリースに最低限必要な設計と実装であり、テストも必要最低限に絞って設計する必要が出てきました。

では、必要最低限のテストをどう設計すれば良いのでしょうか。私なりに4Stepで考えてみました。

# 必要最低限のテスト
## Step1.明確な変更点
例えば、「日本円で合計金額を表示する」機能があるとして、「USドルでも合計金額を表示できる」変更をするとします。この場合、「USドルで合計金額を表示できる」ことは最初に思いつくテストでしょう。明確な変更点についてのテストは、要件に書かれていることを右から左に書き写すだけで組み立てられるので、実務でも特に見落とすことはなく、この記事の冒頭にある議論の範疇には含まれないように思います。

ところで、「日本円でもUSドルでも合計金額を表示できる」機能が完成するとすれば、「日本円とUSドルの表示を相互に切り替えることができる」機能が必要になるかもしれません。必要ならば実装もテストもするし、「いや、まずはUSドルで表示できさえすればいいから、切り替えられなくても今回はOKだと」ということなら実装もテストも不要です。どちらが正解ということはないのですが、どちらに意思決定したかは関係者間で共通認識を作っておく必要があるでしょう。

## Step2.暗黙の前提
仮に、このサービスが複数のブラウザをサポートしているとします。このとき、各ブラウザで「USドルでも合計金額を表示できる」テストをする必要はあるでしょうか。
「USドルで合計金額を表示できる」を実現するためには、暗黙の前提として様々な要素が関係します。例として、ユーザーの種別や、ソフトウェアが動作する環境の種別、表示に用いるデータの種別、ソフトウェアを取り巻く法律などが挙げられます。これらは、(Step1で挙げた)明確な変更点だけに目が行っていると抜けがちなポイントですが、かといってこれらの要素を全て網羅してテストする必要があるかは別の話です。

テストの考え方として、このような状況で個人的によく見聞きするのが「リスク分析」の考え方です。もし不具合が発生したときの影響の大きさと、発生頻度の2軸で考えることが一般的なようです。これについても正解はないのですが、リスクを関係者間で話し合ったうえで、どこまで細かくテストをするか意思決定することが良いと思います。


## Step3.過去の経験
Step2後段のリスク分析の話にも関係してきますが、過去の経験、特に、過去に発生した障害の情報を思い出してみることには価値があると思います。私の経験の範囲では、Step2で挙げたような何らかの暗黙の前提に対する考慮が欠けていた場合が多いです。大事なものは、きっと関係者みんなが覚えていると思いますが、障害の記録を取っておくのもひとつの手段だと思います。

## Step4.いま現在できていることの維持
ここは補足的な話ですが、「USドルで合計金額を表示できる」変更を行なった結果、「日本円で合計金額を表示できなくなってしまった」のであれば問題です。いま現在できていることが維持されていることは、テストとして考えておく必要があると思います。


# ほどほどに議論する
ここまで、私なりに「必要最低限のテスト」の軸となりそうな要素を4つのStepとして書いてみました。これらを、あまり時間をかけずに議論することも重要だと思います。重箱の隅をつつきに行ってしまうと、結局リリースは遅れてしまいます。この「ほどほど」のバランス感覚は関係者のスキルなのではないかと思います。スキルであるならば、最初はみんな下手ですが、思考と経験によって鍛えることができるでしょう。

なにが「ほどほど」かという点については、これも正解はないと思いますが、個人的には「次回のリリースを待つことができるか」あたりがラインだと思っています。

# 補足：万が一間違っても大丈夫な仕組み
最後に補足として、間違ってしまっても大丈夫な仕組みの必要性に触れます。見極めが常にうまくいくとは限らない以上、本番環境に致命的な不具合をリリースしてしまうこともゼロにはならないでしょう。ですから、何か問題が起きた場合に迅速に対応できる仕組みが併せて必要になります(Blue/Greenスイッチやフィーチャートグルなど)。この仕組みが無かったり、弱かったりするうちは、やはりリリース前のテストを厚くするしかないでしょう。


# おわりに
私なりに、普段からモヤモヤと考えていたことを文字にしてみました。勢いで書いてみたのでいろいろと突っ込みどころがありそうな気がしますが、今後の議論のたたき台になればとても嬉しいです。今回記事として書いてみて、個人的にもとても楽しかったので、このテーマには引き続き取り組んでいきたいと思います。
AWS SDK Ruby で credentials の読み込みに失敗する場合

この記事は [🌊 UMITRON 🐟 Advent Calendar 2021](https://adventar.org/calendars/6652) **13日目** の記事です。
Advent Calendar も折り返し地点です 🏃

---

お魚食べてますか? 🐟

現在は UMITRON 株式会社で、水産養殖 🐟🐟🐟 の持つ潜在的可能性を IT を使って引き出すことに取り組んでいます。

当初予定していた内容がちょっと間に合わなかったので、以前遭遇したエラーについての小ネタを書きたいと思います。

---

AWS SDK for Ruby を環境変数 `AWS_CONFIG_FILE`, `AWS_SHARED_CREDENTIALS_FILE` を指定しつつ、使おうとしたときに `Aws::Errors::MissingCredentialsError` のようなエラーが起きました。これらの環境変数で指定している設定ファイルは確実に存在している状態で、 AWS CLI などは正常に使えている状態だったので、原因を突き止めるのに難儀しました。

結論から言えば、これらの設定ファイルの内容にインデントが含まれていたのが原因でした。

設定ファイル中では、名前付きプロファイルを用いており、[名前付きプロファイル - AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html) に書かれている例を使わせてもらうと、もともと私は以下のように記載していました。

```ini
[default]
    region=us-west-2
    output=json

[profile user1]
    region=us-east-1
    output=text
```

AWS の config, credentials 設定ファイルでは、 INI ファイル形式が使われていますが、名前付きプロファイルの数が多い場合には、上のようにインデントを付けることで、視認性はよくなるため、そのようにしていました。 INI ファイルの公式仕様のような存在を私は知らないのですが、なんとなく慣習的にインデントを付けるのは OK なのかなという理解でいました。実際、 AWS CLI や Boto3 (AWS SDK for Python) では、インデントが含まれた状態でも読み込んでくれていました。

しかし、下のファイルが AWS SDK for Ruby で INI ファイルを読み込む実装になっているのですが、正規表現の部分がインデントに対応していないことがわかります。

https://github.com/aws/aws-sdk-ruby/blob/a8332558e8c8a4889dfce17dd54742172500dffb/gems/aws-sdk-core/lib/aws-sdk-core/ini_parser.rb

改めて INI ファイルについて説明しているネット上の情報を見てみると、確かに、敢えてインデントに言及しているものはあまりなさそうです。
(Wikipedia は `Leading and trailing whitespaces around the outside of the property name are ignored.` と書いてあるので、それだとインデントも許容されそうではあるんですが)

- [INI file - Wikipedia](https://en.wikipedia.org/wiki/INI_file)
- [Format of the .ini File | Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms717987(v=vs.85))
- [INI - Initiation File Format](https://docs.fileformat.com/system/ini/)

ともかくも AWS SDK for Ruby は対応していないので、それに従う他ありません。以下のように修正することでエラーは解消しました。

```ini
[default]
region=us-west-2
output=json

[profile user1]
region=us-east-1
output=text
```

INI の仕様が決まっていて、インデントを許容すると明示してあるなら、修正の Pull Request を送るのですが、これはむしろこちらの指定ミスの可能性があるので、微妙なところですね。。
とはいえ、踏んでしまうと原因がわかりにくいので、嫌なエラーでした。
InfluxDBからKotlinで公式SDKを使わず値を読み取る


この記事は、[ゆめみ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yumemi) の14日目の記事です。

## 概要

個人プロジェクトでInfluxDBを読み取るAndroidアプリをKMMで作ろうとした。
しかし、InfluxDBの公式SDKを追加すると、エラーでビルドができなくなってしまった。

色々調べた結果、KMMでは公式SDKが使えない事が分かった。

## なぜ公式SDKを使わないのか？

GitHubで公式SDKである [influxdb-client-kotlin](https://github.com/influxdata/influxdb-client-java/tree/master/client-kotlin) を見ると、Java版をKotlinでwrapしているだけだった。

その何が問題かというと、**KMMでKotlin SDKが使えない** のである。
（KMMではJavaライブラリは使えず、全てKotlinで書かれたライブラリしか使えない）

## InfluxDB APIを使えばいけそう

公式SDKを使わずAPIで値を取れないかと調べたところ、
「InfluxDB APIでFluxクエリーを使えば取得できる」という情報を見つけた。

[Query with the InfluxDB API](https://docs.influxdata.com/influxdb/cloud/query-data/execute-queries/influx-api/)

このページを見て驚いたのは以下の２つ
* レスポンスが`CSV形式`である
* Fluxクエリを送信する必要がある

「え？CSVなの・・・？」
「Fluxクエリってなに・・・」

という驚きを今でも覚えている。
（Jsonが良かったな...）

## InfluxDBから値を取得できたコード

以下が公式SDKを使わず、Kotlin値を取得できたコードである。

Ktor Clinetを使ってAPI通信している。

```kotlin
    // APIクライアント
    private val client: HttpClient by lazy {
        HttpClient(CIO) {
            defaultRequest {
                headers {
                    append(HttpHeaders.ContentType, "application/json")
                    append(HttpHeaders.Authorization, "Token ${InfluxCloudApiConfig.TOKEN}")
                    append(HttpHeaders.Accept, "application/csv")
                }
                url(InfluxCloudApiConfig.URL) // API URLは固定
            }
        }
    }

    // API通信処理
    suspend fun fetchInfluxDB(): String {
        // kotlinx.serializationでFluxクエリをJsonにする
        val json = Json.encodeToString(Query(query = firstRowQuery, org = InfluxCloudApiConfig.ORG))
        // InfluxDBにAPI通信スタート
        val response: HttpResponse = client.post {
            body = json
        }
        // レスポンス文字列を取得
        val stringBody: String = response.receive()
        println(stringBody) // CSVが表示される

        // あとはCSVをModelクラスに変換したりする
        return  stringBody
    }

```




```kotlin
/**
 * Queryクラス
 * FluxクエリをJsonに変換するクラス
 */
@Serializable
internal class Query(
    // 登録メールアドレス
    val org: String,
    // Fluxクエリ
    val query: String,
)
```

```kotlin
// Flux Query
private val firstRowQuery = """
from(bucket: "dev")
  |> range(start: -12h)
  |> filter(fn: (r) => r.location == "BedRoom" )
  |> filter(fn: (r) => r["_field"] == "pressure" or r["_field"] == "temperature" or r["_field"] == "humidity")
  |> sort(columns: ["_time"], desc: true)
  |> first()
""".trimIndent()
```

Flux Queryを軽く説明しておくと

- GraphQLのようにクライアント側で取得する値を指定できる
- `|>`のパイプ演算子？で取得した値を任意の条件で絞り込める
- 上記のクエリだと「12時間前のデータを、指定した値に絞り込み、途中で並び替えて、最後に1件に絞る」

## 感想

- とりあえず目的は達成できたので良かった。
- InfluxDBの公式SDKのKotlin版がとても微妙なので、これを機にKotlinライブラリを作ってもいいかもしれない。
- Fluxクエリは初めて使ったが、なかなか慣れない
- ここまで書いておいてアレだが、クライアント側でInfluxDBを直接参照せず、Lambda等でCSV→Jsonに変換する処理を挟んだほうがい絶対にいい。
CSVの変換が超絶めんどくさすぎる...
  - その時にこそ、この記事のコードが役立つと思う。
AWSを使い始めてよかったこと、初めて触ったときのこと

Ambassadorアドベントカレンダー１3日目の記事です！
いつもは普通に技術の記事を書いているのですが、今回は「いち個人」としてAWSを使い始めてよかったことを書きます。誰かのモチベーションや、その再確認になれば幸いです。

結論ですが自分にとって「何がよかったか」。それは **「気軽に自分で作れる/運用できるものが、めちゃくちゃ増えた」** ということです。他にも色々ありますが「いち個人」として考えるとこれが一番大きいです。私にも「何か物を作って動かすのが好き」という部分が多少はあり、そこに深く刺さっています。

もともと組み込みエンジニアとして主にC++を使ってプログラミングをしていました。仕事以外では趣味でHTML+JSやTypescriptでゲームを作ったり、レンタルサーバーを借りて簡単なAPIを実装していました。ただどうも自分が気軽に作れるものの範囲がなかなか広げられていない感覚がありました。

AWSを本格的に触るようになったのは、AWSを得意とする現在の会社に転職してから。入社前の予習として触ったのが、ほぼ初めてだったと思います。

# 最初につくったもの

面接の場で「何か準備しておくといいことありますか？」と聞いたら「適当なサンプルを触ったり改造して、コード(SDK)を通してクラウドリソースを操る感覚を体験しておくといいよ。Lambda,SQS,S3,DynamoDBはよく使うのでBalckBeltで概要は掴んでおくといいかも」とアドバイスをもらいました。

ということで当時の公式サンプルにあった「S3に画像を保存したらLambdaを発火して画像を縮小し、サムネイルとしてS3に保存する」をドキュメントに沿って作ってみました。

![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/6694b6dd-41e2-6456-4643-a1a0f7563a13.png)


画像を縮小するためのライブラリをインストールしてパッケージ化する部分で苦労しましたが、とりあえず動かすことに成功。言語はPythonでSDKはboto3だったと思います。


# その次に作ったもの

前述のサンプルを改造して「S3に画像を保存したらLambdaを発火して、その画像をTwitterにそのままツイートする」というものを作ることにしました。


![tweet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/b6c1b61c-483c-e119-ebdb-9b4b3df03d16.png)


TwitterのAPIを叩くSDKがあったので、それを前述のサンプルでの「画像を縮小するためのライブラリをインストールしてパッケージ化」と同じ方法で取り込んで実装しました。たいしたものではないですが、これが動いた時は嬉しかったです。普段自分が使っているサービスに繋がった！外に出れた！という感動がありました。

このあとも「リプライでじゃけんして戦歴を記録できるbot」や「映画館の上映スケジュールをスクレイピングして梅田のレイトショー一覧を昼頃に送りつけるbot」を作ったりしました。

# そのあと
仕事でAWSをいろいろと触り、できることを増やし、足りない知識を資格勉強・取得で体系的に補完し、たまにブログや勉強会でアウトプット&整理、そうこうしている間に作れるものが徐々に増えてきました。(その間にいろんな人に迷惑をかけ助けてもらいましたw)

マネージドなサービスやSaaSを組み合わせることで、手軽に作れる/運用できるものはかなり増えたと思います。ノーコードやローコードでいけちゃう部分も増えました。
もちろん、ただ動くだけでなく考慮すべきことは沢山ありますが、マネージドなものをつかうことでこちらで担保すべき範囲は減らせますし、チューニングもしやすいです。

今回Ambassadorブログということで、いつもと違う記事を書いてみました。「気軽に自分で作れるものが、めちゃくちゃ増えた/増えている」ということ、それがモチベーションになっていることを再確認できたのでよかったです。

ではまた！
【AWS】Aurora MySQLのレコードが操作されたら、SNSにTopicを発行したかった

# やりたかったこと

Aurora MySQLの特定のテーブルのInsert/Update/Deleteに反応して、
該当レコードのPKをSNSのTopicにpublishしたい。

# さいしょにやったこと

AuroraにはLambdaを呼び出すネイティブ関数「lambda_(a)sync」が存在します。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.Lambda.html#AuroraMySQL.Integrating.NativeLambda

なんで、これで「SNSにTopic発行するLambda」を、PKをパラメータにして呼び出せばいけるじゃんヤッター！

![AuroraToSNS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386021/e613b71c-3b69-eeee-ac77-2ff6c2166388.png)


```sql:create_trigger.sql
-- TESTというテーブルにIDというPKがあると仮定
DELIMITER ;;
CREATE TRIGGER TEST_TRIGGER_1 AFTER CREATE ON TEST FOR EACH ROW
BEGIN
  SELECT
    lambda_async(
      '<LambdaのARN>',
      CONCAT(
        '{
          "subject": "TEST TABLE MODIFIED",
          "message": "{ \\"ID\\": ', NEW.ID, ' }"
        }'
      )
    )
 INTO @result; -- 単純なSELECTのみだと「トリガーは値を返せない」エラーが出るので、てきとうなローカル変数に格納します
END;;

-- UPDATEとDELETEも同様に記載します

DELIMITER ;
```

```python:lambda.py
import json

import boto3

sns = boto3.client("sns")


def handler(event, context):
    return sns.publish(
        TopicArn="<SNS TopicのARN>",
        Subject=event["subject"],
        Message=event["message"],
        MessageStructure="string",
    )
```

## だめでした

SNSTopicのサブスクライバーがいざ該当レコードを確認しに行くと、レコードがないことがある。

調べたところ、トランザクションでレコードをいれてCOMMITしたタイミングで発生していました。
どうも、 **lambda_(a)syncは、トランザクションとは無関係に動く** らしいです。

https://stackoverflow.com/questions/51371678/only-call-lambda-function-when-aurora-transaction-commits-but-guarantee-call-a

要するに、トリガー内のlambda_(a)syncは、トリガーが作動した瞬間に起動するので

1. トランザクション内でlambda_asyncを呼んでレコードの内容をlambdaに渡した場合、その瞬間は**まだ該当レコードはコミットされていない**
2. **トランザクションがロールバックされても呼ばれている**

ということのようですね。参った。
1は実際起こった症状であるからまだいいとして、2は深刻です。
なんせ**lambda経由でロールバックされて存在しないPKをTopicに発行**してしまいますから、
サブスクライバーからしたらたまったものではありません。

## こまったなあ

* できたレコードをクロールするのが確実だけど、そんなことはやりたくない
* レコードの存在確認をしようにも、ロールバックされたレコードだと永遠に存在しない
* レコードを操作したアプリケーションがpublishするのが正攻法だろうが、複数のアプリケーションがレコードを操作するので、そんな工数はかけられない

# 最終的にどうしたのか

DMSを使いました。

https://aws.amazon.com/jp/dms/

なんでこんなところでDMSが出てくるねん、と識者はお思いでしょうが、まずは下の構成図をごらんください。

![withDMS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386021/62351975-3676-70f8-3329-345d28cd74d0.png)

```sql:create_audit_log.sql
-- TESTというテーブルにIDというPKがあると仮定

CREATE TABLE TEST_AUDIT_LOG(
  ID INT PRIMARY KEY
) ENGINE = InnoDB;

DELIMITER ;;
CREATE TRIGGER TEST_AUDIT_LOG_TRIGGER_1 AFTER CREATE ON TEST_AUDIT_LOG FOR EACH ROW
BEGIN
  SELECT
    lambda_async(
      '<LambdaのARN>',
      CONCAT(
        '{
          "subject": "TEST TABLE MODIFIED",
          "message": "{ \\"ID\\": ', NEW.ID, ' }"
        }'
      )
    )
 INTO @result; -- 単純なSELECTのみだと「トリガーは値を返せない」エラーが出るので、てきとうなローカル変数に格納します
END;;

-- UPDATEとDELETEも同様に記載します

DELIMITER ;
```

(lambda.pyはそのまま)

こうすることにより、 `TEST` テーブルから `TEST_AUDIT_LOG` にレコードがマイグレーションされ、
マイグレーション時のINSERT/UPDATE/DELETEに反応してLambdaがコールされるようになります。

確かに、lambdaがコールされた段階では、`TEST_AUDIT_LOG`にはレコードはないかもしれません。
でもマイグレーションが作動するということは、**`TEST`のレコード自身は確実に最新の状態です**。
なので、Topicのサブスクライバーはオリジナルの`TEST`を見に行くことで、確実に最新の状況を得られる状態になります。

# さいごに

以上、DMSの悪用例をご紹介しました。
こんな使い方、AWSの中の人も想定しているまい。

正しい攻略法があったらぜひともご教授いただきたいです。
よろしくおねがいします。
Litecoinの鍵をbitcoinjs-libで生成する

# はじめに

https://qiita.com/shu-kob/items/380e26eaee025edd6fcb

以前、bitcoinjs-libを用いてBitcoin Testnet/Signetの鍵、アドレスを生成してそこに送金し、TX作るというハンズオンをやったのですが、
Litecoin Mainnetの鍵を作ってみましょう。

# ニーモニックを生成

使うコードはこちら

https://github.com/shu-kob/walllet-dev-study

```
node getMnemonic
```

```
mnemonic:
bomb strategy round brown bomb solve biology soft second artefact once delay coach slight arch vintage always life toss artwork peasant finish device bamboo
```

ここに載っているニーモニックは使わないでくださいね。

# Litecoinの鍵を生成

https://github.com/shu-kob/walllet-dev-study/blob/50e691e8c5e66a1304c068bbbd06c06a56c5b94f/getKeys.js#L32

```getKeys.js
let bitcoinNetwork = TESTNET; // MAINNET, TESTNET, LITECOIN or DOGECOIN
```

↑この行を以下のように書き換えます。

```getKeys.js
let bitcoinNetwork = LITECOIN; 
```

以下のLITECOINのprefix情報が使われるようになるわけですね。

```getKeys.js
const LITECOIN = {
    messagePrefix: '\x19Litecoin Signed Message:\n',
    bech32: 'ltc',
    bip32: {
      public: 0x019da462,
      private: 0x019d9cfe,
    },
    pubKeyHash: 0x30,
    scriptHash: 0x32,
    wif: 0xb0,
};
```

実行して拡張秘密鍵と拡張公開鍵を生成してみましょう。

```
node getKeys.js
```

```
path:
m/44'/2'/0'
xpub:
Ltub2Yp2889mKTKeuzHyJqgDszUfp8GWyRcYACGp5JhSwhJ92tLpuKuimd44JZ5Brfq4HzeLzdHFHLZJMQTgGxpvzEmBcyCoKuxzkRnfneDrdK6
xpriv:
Ltpv77dgXLjE5JnhJ7b94EBqoQeTNZaKuB3t5gAnQKwA1WWYSX9kaQsHm1wo4CNLNPHyv9vyaAR4CRrWuqUqx3fV9xbuDo9HmLXMLzAF8mGM2eG
```

Litecoinの拡張公開鍵、拡張秘密鍵の接頭辞は"L"になります。

次回はアドレス生成してみましょう！
Galaxy Z Fold3が気になったので調べてみた

# はじめに
こんにちは、運動通信社でiOSアプリを担当している松川です。
今回は気になっていたガジェットの `Galaxy Z Fold3` について調べてみました！

# 調べてみた
まず、皆さんGalazy Z Foldって端末についてご存知でしょうか！

https://www.galaxymobile.jp/galaxy-z-fold3-5g/?cid=jp_pd_ppc_google_galaxy-z-fold3_text---1000530-210901_hot-galaxy-z-fold&gclid=CjwKCAiA-9uNBhBTEiwAN3IlNC3E1AoSyQO-X8C-Ba7_mPQ3WjuTW-zWsVzD0KcgXJiIAN7rpI7A2hoCxFgQAvD_BwE

Galaxyから出ているAndroid端末なんですが、なんと折りたたみスマホなんです！
2019年にGalaxy Foldが発売して、現在の最新機種はGalaxy Z Fold3みたいです。
Galaxyのホームページを見るのはいつぶりか分からないくらい久しぶりですが、さっそく閲覧。

ふむふむ...おぉ、かっこいい...！！！！
端末もそうですが、サイトの作りがすごいA○pleっぽくてそれもまた良い！

スペック的にはこんな感じです。

![スクリーンショット 2021-12-13 21.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116708/aeceea39-ca1c-5f6e-e23c-60acdf3fc4aa.png)
![スクリーンショット 2021-12-13 21.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116708/4cf2f5cc-f8b4-3ae9-c422-a63842253ecb.png)

ディスプレイは開いてる時も閉じている時もどちらも120Hz！
しかも防水に対応しているみたい。良いね！

私は店舗にも実際に触りに行ったんですが、閉じている時は6cm弱と若干厚く感じたものの、折りたたみを開いた時の画面の広さは圧巻！
真ん中の折れ目も個人的にあまり気になりませんでした。
画面サイズが大きいのでアプリを左右に表示しても、YouTube見ながらブラウジングなども快適。
良いぞぉー...！

ただ値段がなんと...237,565円！！
た、高いー！！

![](https://3.bp.blogspot.com/-tR8LfjrHvos/Wn1VhqmLQQI/AAAAAAABKDA/jFDBClOQnf4_vPpNPXNdCPYdVDL9ZUH0QCLcBGAs/s400/bikkuri_me_tobideru_man.png)

ということで中々手をつけられていません！

# 開発視点
開発面も少し見てみると、色々考えることがあるみたい。

- アプリの続行可能性
    - 折りたたみ式端末は内側や外側のディスプレイの考慮や、閉じた後にもシームレスに状態を続行できること
- 新しい画面比率
    - 21:9 〜 1:1に至るまで変化する可能性を考慮
- マルチウィンドウ
    - 画面上で3つ以上のアプリを同時実行可能
    - 上記に伴い以下を考慮
        - マルチ再開
            - Android9.0以前と、10以降でマルチウィンドウにしていた時のアプリのライフサイクルの状態が変わる
            - 9.0以前はフォーカスしているアプリのみライフサイクルがResumeだったが、10以降は表示している全てのアプリがResumeになるみたい
        - 排他的リソースアクセス
            - 新しいライフサイクルcallback [onTopResumedActivityChanged](https://developer.android.com/reference/android/app/Activity?hl=ja#onTopResumedActivityChanged(boolean))
                - 共有のリソース（端末のマイク、カメラ）が利用されていることを検知するために必要なメソッド
            - マルチで実行中に急にリソースが無くなる場合があるため
                - シングルアプリでも考慮は必要だけど、マルチだとさらに状態の考慮は必要だ

![スクリーンショット 2021-12-13 23.06.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116708/7523013a-3ba0-b98b-de2d-c6cbfbc85dec.png)

- マルチディスプレイ
    - Android10以上で、アクティビティが複数ディスプレイの端末で実行されている場合、ユーザーはアクティビティを別のディスプレイに移動することができる
    - 起動時、または別のアクティビティ作成時に、どのディスプレイで実行するか指定できる
    - 折りたたみ移行時、コンテキスト更新、ウィンドウのサイズ変更、構成変更とリソース変更が実行される
- テスト
    - 折りたたみ式対応にするには以下にどう対応するかテストする必要がある
        - 構成の変更
        - マルチウィンドウおよびマルチ再開
        - サイズ変更と新しい画面縦横比


...めちゃくちゃ大変そう！！
でも楽しそうだなー型落ちで安くなったら買おうかな...。
皆さんもぜひ触ってみてください！
以上、折りたたみデバイスにさらに興味を持った話でした。

# 参照

https://developer.android.com/guide/topics/ui/foldables?hl=ja
【UiPath】次の営業日を計算する

# はじめに

この投稿は、RPAツール「UiPath」の 実装例 の記事です。良くある実装ですので、参考程度に。

UiPath Adventカレンダーの 12日目 の記事でもあります。

https://qiita.com/advent-calendar/2021/uipath


# 営業日とは

営業日とは、土日祝日を除いた平日の稼働日のことを指します。
今日が「12/13（月）」だとすると、2営業日先は「12/15（水）」になります。

企業・団体によっては「年末年始の営業日」が違うなど、祝日ルールが違ったり「平日でも営業してない日」や「土日でも営業してる日」などもあるので、単純には計算できません。

祝日・営業日ルールをエクセルなどで管理しながら、営業日かどうかを判定していくロジックになります。


# ワークフロー

以前に、個人的に作成したものがあるので、紹介します。

https://marketplace.uipath.com/listings/qmxbyjw75bkqbegekabe8n

＜設定エクセル＞
エクセルに 「曜日ルール」シートと「特別日リスト」シ－トがあります。
「曜日ルール」シートには「曜日別の営業する／しない」設定を入力します。
「特別日リスト」シートには曜日ルールに関係なく、営業する（しない）日を入力します。

初期データとして、下記3つを設定してあります。

- 2030年までの祝日を「営業しない」日で設定
- 2030年までの12月30日、12月31日を「営業しない」日で設定
- 2030年までの1月1日、1月2日、1月3日を「営業しない」日で設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b734488c-90d0-c58c-5486-e8720dcfeeea.png)

＜ロジック＞
以下のようにループしながら、営業する曜日か？営業する日か？を判定していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b891ea69-cf50-fd18-b14e-2cedc981f2b9.png)

# 終わりに

以上、実装例の紹介でした。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。