OmniAICreator/Qiita-1.07M huggingface dataset:
架空のサービス(devops)を要件定義してみた

# 前置き
前回の記事からの続きになります。

https://qiita.com/miyabi-san/items/4db5700a7febe20847db

本システムの機能要件と非機能要件を定義しました。
非機能要件に関しては、ipaの非機能要件グレードを参考に大項目を立てましたが、
非機能要件グレードはあまりにも広範過ぎ、網羅性が高すぎるのと
その一方でクラウドを主体に置いたものではそもそもないので、結局中身は自分で考えるしかないのかなと思いました。

クラウドインフラ等の非機能要件設計に役立つデファクトのツールとかプラクティスとかって、何かあるのでしょうか・・・？

(ちなみに自分は実務で要件定義を担当した事はありません。予めご了承ください)

# 機能要件

## Infrastructure as Code
開発の際、処理を担うソースコードだけでなく、それが動く実行環境を含めて開発・管理できること。

## ビルドの自動化
アプリケーションのコンパイルとリンク作業などのビルドプロセスを自動化できること

## テストの自動化
単体テストの自動化ができること(単体テスト以外も自動化できれば望ましいがマストではない)

## ワークフローの自動化
スクリプトレビューや、テストの各工程において、起案・承認などのプロセスが自動化されること

## リリースの自動化
アプリケーションのリポジトリへのソース配置作業が自動化できること

## デプロイの自動化
本番環境へのホスティング作業が自動化できること

# 非機能要件

## 可用性
クラウドのIaaS・PaaS・FaaS利用を想定しており、アプリケーションごとの要件に応じて都度変更可能であるため、規定しない

## 性能・拡張性
クラウドのIaaS・PaaS・FaaS利用を想定しており、アプリケーションごとの要件に応じて都度変更可能であるため、規定しない

## 移行性
#### 実現性要件
既存アプリケーションをコンテナ化して当基盤上に移行できる実現性があること
#### 移行運用
既存アプリケーションの移行に関して、ガイドラインがあること。

## セキュリティ
#### 権限管理
組織単位の設定の実施に関して、設定担当者のみに制限することができること
#### 認証
設定担当者の認証プロセスにおいて、多要素認証または生体認証を強制できること
#### アクセス制限
外部公開しないクラウド上の社内リソースに対して、外部の人間からのアクセス拒否を実現できること
#### シークレット管理
インフラのコード化に際して、ID・パスワード・アクセスキー・キーペア等のシークレットの漏洩防止対策が徹底されていること（社内リポジトリにおいても平文でのアップロードは禁止する）
#### エンドポイント対策
クラウド上のソースコード保管領域（パイプライン含む）のセキュリティが多要素認証等で担保されていること

## 運用・保守性
#### 管理方針の明確化
当基盤の運用管理方針が明確化されており、管理上の判断の指針になること
#### 環境の統制
運用環境の統制が取れており、当基盤の方針から外れる独自の環境を勝手に増やすことを制限できること。（申請ベースで実現できれば良い）
#### 運用ドキュメント整備
DevOps関連、コンテナ関連の技術的ドキュメントが整備されており、運用上の判断の指針になること

## リソース監視
コンテナに対する監視を行うことができること

## 環境・エコロジー
物理的な設備導入を伴わない為、定義しない

# あとがき
要件の取りまとめにかかった期間は2週間程度だった。
あくまでも自分一人で勝手に要件定義出来るので非常にイージーモードであることは間違いない。
これがお客さんを交えて諸々のちゃんとした資料等も準備して実施すると何ヶ月かは掛かるのだと思う。
SEって大変な仕事だなあと思う。
flutter android バージョン コード 1 の apk が既に存在するため、別のバージョン コードを使用する必要があります

## 再申請の際にaabファイルをアップロードするとエラー

`バージョン コード 1 の apk が既に存在するため、別のバージョン コードを使用する必要があります。`

以下の記事でandroid/app/build.gradleのversioncodeとversionnameを変更したらいけると思ってました。

https://smot93516.hatenablog.jp/entry/2018/05/21/140558


それではflutterでは、うまくいきませんでした。なので、以下の記事を参考に
pubspec.ymlの+1を+2に変えて、`flutter clean`のあとに`flutter build appbundle --flavor prod -t lib/main-prod.dart` を実行しました。

以下にファイルが出力される
`build/app/outputs/bundle/prodRelease/app-prod-release.aab`


```:pubspec.yml
# version: 1.0.0+1
version: 1.0.0+2
```

https://qiita.com/zb185423/items/2a7b49c32b817049cf2d
[Kotlin]ずっと分からなかったsealedクラスを掘り下げる

#誤り
`sealed`クラスのメリットである、When式の網羅に関して、具体例のコードがwhen文になっていました。
つまり、戻り値がないので網羅されてない時にコンパイルエラーは起きないという事でした。

また、when文であってもKotlin1.7以降はコンパイルエラーになるようです。

[sdkeiさん](https://qiita.com/sdkei)ありがとうございました。

##はじめに
Kotlinに`sealed`クラスという機能があります、度々見たり、周りのAndroiderが公用語のごとく使っていて、自分は分かったふりをしていました・・・

ここで掘り下げておきます。

##`sealed`クラスを端的に
一言で表すと、「制限」。
何を制限するかと言いますと、下記の様にマークされたクラスは継承を制限することを明示します。

制限されていても、継承できる場合は下記です。

コンパイル時に、同ファイル以外にサブクラスがないことが共有されます。

- `sealed`クラスのネスト内
- 同じファイル内

```kotlin:Sonic.kt
sealed class Sonic {
     class Shadow: Sonic()
     class Tails: Sonic()
     class Knuckles: Sonic()
}

class EggMan: Sonic()
```

```kotlin:Other.kt
class Other : Sonic() // error
```

##メリット
`enum`とかなり似てるなと思いました。
違いに関しては、 `enum`は、コンパイル後にインスタンス生成ができないが、`sealed`はコンパイル後にサブクラスを作成できない。

### `when`文の時に分岐の漏れがなくなる

例えば、`sealed`クラス内に新しくクラスを追加した後、when文の方にも変更を加える必要がある場合。
仮に忘れてしまっても、コンパイルで弾いてくれます。

```kotlin
// Sonic.EggManが欠けているのでコンパイルエラー
val result = when(sonicCharacter) {
    is Sonic.Shadow -> { print("It's Shadow.") }
    is Sonic.Tails -> { print("It's Tails.") }
    is Sonic.Knuckles -> { print("It's Knuckles.") }
}
```

3.サブクラスを簡単に把握することが出来る（エラー確認の時間も短縮）

##おわりに
意外と単純なことだなと思いました。

しかし、こちらの方がかなり深く考察をされていたので、氷山の一角しか見れてないのだなと思いました・・

https://qiita.com/kikuchy/items/ad89a12029082be8d218

##参考
https://kotlinlang.org/docs/sealed-classes.html

https://blog.kotlin-academy.com/enum-vs-sealed-class-which-one-to-choose-dc92ce7a4df5
駿台予備校広告のあの答え合わせをRで一行でやってみた

https://qiita.com/sano192/items/a27a481395ce8827bbf6
https://qiita.com/TSeri/items/6958d0ad98d4beb7571d

要するに，6文字の順列を作り，重複を省いて，ソートして，100 番目の要素を出力する。
まあ，どんなパッケージを使っても良さそうなので，順列を生成する e1071::permuttions を使う。

```R 
library(e1071)
sort(unique(apply(permutations(6), 1, function(i) paste(unlist(strsplit("GAKKOU", ""))[i], collapse=""))))[100]

```

ところで，dplyr とかの %>% 演算子を使って，パイプで書いてみます。

```R
permutations(6) %>% t %>% applyx %>% unique %>% sort %>% ans
```
applyx とか ans なんて見たことないですよね。dplyr とか tidyverse のマニュアル見てもないですよ。

```R
applyx = function(a) apply(a, 2, function(i) paste(unlist(strsplit("GAKKOU", ""))[i], collapse=""))
ans = function(a) a[100]
```

と定義しているだけです。なあんだ!と思いますよね。
パイプで書けるように，関数を定義しているだけです。
これはユーザレベルだからバカバカしいと吐き捨てればよいのですが，tidyverse の開発側がやれば，素晴らしい！となるんですかね。
PHP コードの変更が反映されない


- Docker コンテナで立てた PHP 環境のコードを編集した後に、 API を叩いても変更が反映されない
- コンテナ内部のコードはローカルで変更した通りに反映されていた



Dockerfile で読み込んでる、 php.ini で [opcache](https://www.php.net/manual/ja/opcache.configuration.php#ini.opcache.enable) が有効になってた。

```:php.ini
opcache.enable = 1
```

無効にしてコンテナビルドしなおしたら治った


https://www.php.net/manual/ja/intro.opcache.php

- 本番環境では有効にすることでキャッシュが聞いてパフォーマンスが上がる
- コードに変更を加えたらサーバーを再起動する必要がある
- 開発環境では無効にしてないとめんどくさい
【swift Combine】WWDC2019 から Combine についてまとめてみた

# 目的
・Combine を理解すること
・他の人の解説ではなく、実際のWWDC2019の動画をみて Combine についてまとめること
・英語の動画から技術を学ぶこと

# なぜCombineなのか？
・Appleが提供する標準ライブラリであり、今後使用率が上がると考えているから
・WWDC2019で発表された比較的新しいライブラリだから
・発表時期から、SwiftUI との相性が良いと考えたから

※今後、Combineを学んだ後、RxSwiftについても学びたいと思う。 


# 参考文献

【Combine の概要】

https://developer.apple.com/videos/play/wwdc2019/722/

【Combine のコード】

https://developer.apple.com/videos/play/wwdc2019/721


# 【Combine の概要】 

WWDC2019で初めて登場した「Combine」というフレームワークについての話。
話をしているのは Foundationチームのマネージャーである Tony Parker。
※Foundation というのは　Swift の標準ライブラリ

私たちは「ログイン機能」に非同期処理を使用しています。
例えばログイン時に氏名やメールアドレスを入力しているときです。ログイン時は氏名を打ち、メールアドレスを打つ。メールアドレスを打っているとき、氏名が「既に登録済みの氏名か？」ということを並列で処理して、処理結果に応じて指名横の画面を変更します(△→○ のように)。
ここでは、HTTP通信を使用した氏名の確認や処理結果に応じた変数の状態管理,KVC 等を行っている。
処理の流れは、『HTTP通信→処理結果がわかる→画面を再描画する』というもの。

`Combineの目的は"組み合わせること"`
Combineはリクエスト駆動式である → 意味はわかっていない
重要なものが3つある
`Publishers`
Combineの宣言的なもの
値やエラーがどう出たかを表示するたえめのもの
Swiftでは構造体で示す。値を受け取り続けられる

`Subscribers`
Publisher とは逆の考え
値を受け取って、完了の報告を受ける
値によって状態が変化するため、クラスを持つSwiftの参照型になる

Publisher から受け取ったデータの処理履歴を示す。
Publisher と通信を行い、「非同期処理の進捗を確認する？イメージ」

`Operators`
値の追加や削除等様々な値が動作する動作を決めるもの

つまり下のような流れになるのかなと筆者は考えます。
① Publisher で値を発行
② Subscriber で値を受け取る
③ Operator で値を加工したり制御したりする
【tempus dominus】bootstrap 4 datetimepicker　カレンダーを月曜日スタートにする

datetimepicker初期化前にこう書く

```js:
moment.lang('ja', {
    week : {
        dow : 1
    }
});
```

デフォだと日曜スタート

```js:moment.min.js
week: {dow: 0, doy: 6},
```

他のdatepicker系だとweekStart:1みたいに書けば出来る場合が多いけど何故かそういうオプションが無い。
kotlinでオブジェクトを画面遷移で渡す【@Parcelize】

メインからサブ画面にオブジェクトを渡すときの方法

画面遷移の際に値を渡すのは書籍やネットにもよくあります。しかしオブジェクトになると、
あるにはあるがjavaであったり古かったので今回備忘録として残します。


まずオブジェクトはそのまま渡すことはできないので、シリアライズという方法を使う必要がある。
このシリアライズはオブジェクトを一旦バイト列にし、遷移先で再度オブジェクトにするという手段。

シリアライズを実装するにあたり以下のどれかを使う。
1,Serializable
2,Parcelable
3,@Parcelize

私が選択したのは@Parcelize
今回はメイン画面で値を入力したものを処理するクラスに渡しデータクラスの型にして
戻り値でメイン画面に戻し、サブ画面に遷移する流れでやります。


まずはbuild.gradle(:app)にプラグインを追加

```build.gradle
    //parcelize
    id 'kotlin-parcelize'
```

データクラスを作成し@Parcelizeの追加と継承でParcelableを入れる

```Info.kt
@Parcelize
data class Info(
    val info: Double
    ) : Parcelable
```

次にメイン画面の値を処理するクラスを作成する。

```Calculation.kt
class Calculation {
    private var num1: Double = 0.0
    private var num2: Double = 0.0
    private var result: Double = 0.0

    //掛け算をする
    fun result(num1: String, num2: String ): Info{
            this.num1 = num1.toDouble()
            this.num2 = num2.toDouble()
            result = this.num1 * this.num2
            return Info(result）
        }
    }
}
```

メイン画面では値を入力したものをCalculationクラスに渡し結果をInfoクラスの型で受けとりオブジェクトとして
画面遷移する

```MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        binding = ActivityMainBinding.inflate(layoutInflater)
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        //計算をするクラスをインスタンス化
        val calculation = Calculation()

        //クリックするとサブアクティビティに移動
        binding.measurementButton.setOnClickListener {
                    val result = calculation.result(
                    num1 = binding.num1InputForm.text.toString(),
                    num2 = binding.num2InputForm.text.toString()
                )

                //Infoクラスをインスタンス化
                val info = Info(result)
                intent = Intent(this, SubActivity::class.java)
                intent.putExtra("RESULT", info)

                startActivity(intent)
            }
        }
    }
}
```

受け取り側のサブクラスでは

```SubActivity.kt
class SubActivity : AppCompatActivity() {
    private lateinit var binding: ActivitySubBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySubBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //前画面からBMI数値をもらい、詳細画面に入力
        val result = intent.getParcelableExtra<Info>("RESULT")

        binding.resultOutput.text = result.Info.toString()
    }
}
```

以上でオブジェクトの画面遷移になります。
@Parcelizeは簡単に実装できるが、実力を上げるためにはSerializable、Parcelableを
使って見たいと思います。
駿台予備校広告のあの答え合わせをRでやってみた

Qiitaの駿台予備校の広告の「あれ」の記事がありましたので、Rでも台無しにしてみました。

https://qiita.com/sano192/items/a27a481395ce8827bbf6


# 動作環境
- R 4.1.2
- RStudio 2021.09.1 Build 372

# 使用パッケージ
今回使用するパッケージはRcppAlgosパッケージです。
以下のサイトのやり取りを参考にさせていただきました。
パッケージ作成者の方の書き込みがドンピシャの回答でした。

https://stackoverflow.com/questions/69910536/why-does-gtoolscombinations-and-permutations-not-work-with-a-vector-containing


#RcppAlgosパッケージによるスクリプト

```GAKKOU.R
install.packages("RcppAlgos")
library(RcppAlgos)

vec <- c("G","A","K","K","O","U")
tbl_v <- table(vec)

GK <- permuteGeneral(names(tbl_v), 6, freqs = tbl_v)
GK[100,1:6]
```

3行目：文字列のベクトルvecを作成
4行目：テーブルで文字列の頻度を作成
5行目：permuteGeneral関数で組み合わせを格納するマトリクスGKを作成
6行目：GKの100番目の1番目から6番目の文字列を表示


# gtoolsパッケージでは動かず
ちなみに、以下のサイトで紹介されているgtoolsでもやってみたのですが、残念ながら今日現在（2022年1月20日）私の環境では6文字のベクトルで6文字の組み合わせではエラーが出て使えませんでした。残念。

https://toukei.link/programmingandsoftware/r/combinationpermutation/


# なぜこの記事を作ったのか
先日、電車に乗っていたらこの駿台予備校の広告を目にして、何となくモヤモヤして過ごしていました。

https://www.sundai.ac.jp/news/2021/jeki-award.html

仕事がすこし落ち着いたので、モヤモヤを解決すべくQiitaで調べてみたところ冒頭の記事を見かけました。
これはRでも作れるのではないかということで、調べて記事にしました。
組み合わせの関数やfor文などの基本的な関数を組み合わせたもので作りたかったのですが、仕事で時間が取れないためRの世界中の豊富なパッケージの力を活用させていただきました。
先人の努力に感謝します。
(Thank you Joseph-san for your package to solve this problem)

私自身のモヤモヤがスッキリして、今夜はゆっくり眠れそうです♪

# 受験生の皆さんへ
色々と不安なこともあるかと思いますが、最後は自分を信じて本番で力を出し切ってください。
皆さんのご健闘を祈っています。
FreeDOSのctty

FreeDOSにはMS-DOS同様にcttyがあり、コンソールをシリアルなどに変更できます。

スクリーンキャプチャだと画像になってしまうので、qiitaの記事にするときなどコンソールをシリアルにしてコピペできると便利です。

ボーレートなどを設定しておきます。

```
C:\>mode com1:9600,n,8,1,b
```

Windows7のRLoginでMCP2221を使ったUSBモジュールにMAX3232レベル変換モジュールを接続してみました。

実行してみます。

```
C:\>ctty com1
Error reading from device COM1: write fault
(A)bort, (I)gnore, (R)etry, (F)ail? 
Invalid or no read-write device 'com1'.
```

どうも制御線を見ているようで、DTR(4)-DSR(6)とRTS(7)-CTS(8)を接続してループさせたら、ちゃんと使えるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/7e472acc-3294-5574-f6a4-50a79a803150.png)

HW-044というモジュールを使っているがRXDがOUTでTXDがINになっていて、混乱する。MAX3232は4系統つなげるのだが、2系統しかつかっていなくてちょっともったいない。

FreeDOS 1.3 RC4で試しました。

RLoginでSJISを選ぶと日本語の表示も確認できます。

```
C:\RATOC\R231DOS>csc
CardService Check Program Version 1.00
Copyright (c) RATOC System Inc. 1994-1997. All rights rserved

 === CardService Information ===        Not Installed

 === SocketService Information ===      Not Installed

 === PCMCIA Controler ===               Port = 03E0 Controler ID : 84

 === Socket Information ===             Number of Sockets : 1

Slot 0 Memory Segment  : DF00
        Maker    : RATOC Systems,Inc.
        Product  : UltraSCSI CARD R231
        AddInfo1 : 
        AddInfo2 : 

C:\RATOC\R231DOS>devload asp3350d.sys
DEVLOAD v3.25 - load DOS device drivers - license GNU General Public License 2
(c) 1992-2011 David Woodhouse, Eric Auer (FreeDOS.org)

Loading: C:\RATOC\R231DOS\ASP3350D.SYS

REX ASPI Manager <NotUseIRQ> for Eagle (REX-R231)  2.8S-R17.1(H120224) (06 Oct. 1998)
for i82365 direct control & dual Socket
Copyright (C) 1994-1997 Advanced System Products, Inc. / RATOC Systems,Inc. slr



1 char device installed.
Driver loaded.

C:\RATOC\R231DOS>ssc
 SSC.EXE (SHOW SCSI)  ＳＣＳＩ接続機器チェックプログラム  Ver1.04 (980302)
                 (c) RATOC system.inc,1995. SLR. all right reserved. 

ＳＣＳＩ ＩＤ : #0  .....Not Connect

ＳＣＳＩ ＩＤ : #1  .....Not Connect

ＳＣＳＩ ＩＤ : #2  .....Not Connect

ＳＣＳＩ ＩＤ : #3  .....Not Connect

ＳＣＳＩ ＩＤ : #4  .....Not Connect

ＳＣＳＩ ＩＤ : #5  .....Not Connect

ＳＣＳＩ ＩＤ : #6  .....Not Connect

ＳＣＳＩ ＩＤ : #7  .....Connect!
ホストアダプタ
   ホストアダプタ名：REX-R231 ADAPTER


処理を終了します。
```

画面キャプチャはこちらが使えました。

http://pixelmetrics.com/Snarf/index.htm

![SNARF000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/0ee6ca1c-ba3d-7769-7fd7-dacd4ca0fa82.png)

キャプチャされるファイルはBMPなのでペイントでPNGにしました。
TypeScriptでTwitter APIのtextを生データにデコード(アンエスケープ)する

## はじめに

Twitter APIでツイートを取得すると、text(ツイート本文)に中途半端なエスケープが入ります。

2022年現在、エスケープされる文字は以下の3つが確認されています。

- `<` → `&lt;`
- `>` → `&gt;`
- `&` → `&amp;`

'(シングルクオート)や`(バッククオート)などは対象ではないようです。

正直、フロントエンドで見せるときにこっちでうまいことエスケープするので、いらんことするなって感じです。

したがって、Twitter APIから取得したtextを生データに戻す関数を作りました。
TypeScriptです。

## コード

引数(text)にTwitter APIから受け取ったtextを渡すと、生データにデコードして返してくれます。

```ts
const decode = (text: string) => {
  return text
    .replace(/&lt;/g, "<")
    .replace(/&gt;/g, ">")
    .replace(/&amp;/g, "&");
};
```

## コードの解説

現状、TypeScriptだと`replaceAll`関数が使えないので、`replace`関数に正規表現を渡してます。
受け取ったtextからエスケープされた文字列を探索して全て元の文字に変換して返却しています。

## まとめ

2022年現在のTwitter APIのエスケープに対応する方法でした。
ただ、今後Twitter APIの仕様変更がないとは限らないので、定期的にチェックする必要があるのかな…と思っています。
(素直に生データ返してくれ…)
もっと良さそうな方法とかあれば、コメントで教えてください〜

## 参考記事

- [Twitter API で取得できるツイートはエスケープされている。](https://qiita.com/Takayuki_Nakano/items/8399f829fc3e1d7c476e)
- [[TypeScript] 文字列置き換え～replaceAllの代わり](http://propg.ee-mall.info/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0/typescript-%E6%96%87%E5%AD%97%E5%88%97%E7%BD%AE%E3%81%8D%E6%8F%9B%E3%81%88%EF%BD%9Ereplaceall%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A/)
NextJS > Yarn Workspacesを使う




Next公式Exampleの以下を参考にします。

https://github.com/vercel/next.js/tree/canary/examples/with-yarn-workspaces



How to useに記載がある以下のコマンドでプロジェクトを作成します。

```
yarn create next-app --example with-yarn-workspaces with-yarn-workspaces-app
```



yarnを実行

```
yarn
```


初期状態ではpackage.jsonの設定がnpm用になっているので、warningが出ます。

```
warning Missing name in workspace at "/with-yarn-workspaces-app-yarn/packages/bar", ignoring.
warning Missing name in workspace at "/with-yarn-workspaces-app-yarn/packages/foo", ignoring.
warning Missing name in workspace at "/with-yarn-workspaces-app-yarn/packages/web-app", ignoring.
```

## package.jsonに設定追加

yarn用に設定を追加していきます。


- packages/web-app/package.json

`name`と`version`を追加します。

```:packages/web-app/package.json
{
  "name": "@project/web-app",
  "version": "1.0.0",
  "private": true,
  "scripts": {
割愛
```


- packages/bar/package.json
- packages/foo/package.json
同様に、`name`と`version`を追加します。

```:packages/bar/package.json
{
  "name": "@project/bar",
  "version": "1.0.0",
  "private": true,
割愛
```



yarnを実行

```
% yarn
yarn install v1.22.17
[1/4] 🔍  Resolving packages...
中略
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 0.56s.
```

yarnが問題なく完了しました。



## next

#### next.config.js


['bar'] -> ['@project/bar'] に変更します。


```:packages/web-app/next.config.js
const withTM = require('next-transpile-modules')(['@project/bar'])

module.exports = withTM()
```

#### pages

packages/web-app/pages/index.js

```
import foo from '@project/foo'
import Bar from '@project/bar'

export default function Home() {
```




## package.json scriptsの変更

yarnのworkspaceを使うように変更します。
（yarn --cwdのままでも動作はするようです）

```:package.json
"scripts": {
  "dev": "yarn workspace @project/web-app dev",
  "build": "yarn --cwd packages/web-app build",
  "start": "yarn --cwd packages/web-app start"
}
```






# 補足

next-transpile-modulesはNextのバージョンと対になるバージョンを選択する必要があります。

https://github.com/martpie/next-transpile-modules#compatibility-table
matplotlibで散布図（plt.scatter）をアニメーションにする

plt.plot()をアニメーションにする知識はぐぐるとたくさん見つかるけど、それをscatterで行っても失敗する。成功させるには、

```
img = plt.plot(...)
ims.append(img)
```
これの

```
ims.append(img)
```

ここを

```
ims.append([img])
```

リストにしてあげて

```
img = plt.scatter(...)
ims.append([img])
```

こうすると成功する。
Azure Data Factory - Data Flow の In関数の使い方

#はじめに

Azure Data Factory や Azure Synapse Pipeline の Data Flow (GUIとノーコードでデータ加工できるツール）を使ってデータ加工するときのIn関数の使い方がちょっとクセありなので、使い方例を紹介します。

#やりたいこと

列内の複数データを抽出するとか除外するとかSQL文でもよくIn関数使いますよね？
Data Flowの式ビルダーで、SQL同様に
test_data in ('test1', 'test2', 'test3')
と指定したらエラーになりました
あれ？In関数使えないの？って思って別の方法で実装しようとした方もいるのではないでしょうか
筆者もその経験者の1人です

#方法

結論から言いますと、Data Flow の式ビルダーでIn関数は使えます　ちょっとクセがあるだけです
test_data in ('test1', 'test2', 'test3')
ではなく、
in (['test1', 'test2', 'test3'], test_data)
と書けばいいみたいです SQLの書き方に慣れていると違和感ありますよね
わかりにくいですが、リファレンスに記載もあります
https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-expression-functions#in

こちらは実際に使用した例ですが、フィルター(Filter)モジュール等で特定のデータを除外したい場合なんかに使用することもありますね
inの前に!(ビックリマーク)を付けることで、not in (次の値を含まない）の意味になります
![Dataflow02_02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/0ae2d277-be94-80b0-ce94-0b1ee03509f9.png)

#さいごに

プログラミングやSQLの経験がある方は、どのツールやプログラムでもやりたいことをどう実装すればよいか勘所があると思います
ただしツールやプログラムによって関数式の記述方法は若干クセがあります
そんなときは、各ツールで必ずリファレンスページが用意されていますので、リファレンスページで[Ctrl +F]でページ内検索して探してみて下さい
![Dataflow02_03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/e7d47879-4014-849e-a5f6-61233f051b73.png)

#参考

https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-expression-functions
Azure Data Factory - Data Flow で中央値、第1四分位数、第3四分位数を算出する方法

#はじめに
Azure Data Factory や Azure Synapse Pipeline の Data Flow (GUIとノーコードでデータ加工できるツール）を使ってデータ集計や予測モデル用のデータ加工をするときのテクニックを整理しています

#やりたいこと
各データの期間別の要約統計量（平均、標準偏差、分散、中央値、第1四分位数、第3四分位数、等）を算出したい要件があると思います
Data Flow の式関数で算出できるのですが、平均、標準偏差、分散については1ステップで算出できるのですが、中央値、第1四分位数、第3四分位数については、median的な関数は残念ながらData Flowにはなく、ちょっとテクニック（2ステップで算出）が必要なのでその方法をこれから記載します

#方法
#####平均、標準偏差、分散の算出方法
①集計(Aggregate)モジュールを使用して統計量を算出したい単位に（下記例ではセンサーIDと年月）グループ化して
![Dataflow04_01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/81e04dcf-803d-52aa-7f3b-3281fffb8798.png)
②平均(avg)、標準偏差(stddev)、分散(variance)の集計関数で集約する
![Dataflow04_02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/690a1f38-09bc-68e9-cff6-cab0003e6842.png)
※標準偏差と分散に関してはグループ化した集計対象データ件数が1件しかないとエラーになるので注意 対応策としては1件しかないデータを削除してから集計する（そもそも統計量を取得する上で極少件数しかないデータは1件でなくとも除外すべき）
![Dataflow04_03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/1f137b71-5caf-c66d-577a-7d1e226f019c.png)

#####中央値、第1四分位数、第3四分位数の算出方法
######Step1. nTile関数を使ってデータを昇順に4等分する
①ウィンドウ(Window)モジュールを使用して、[1.Over]タブで統計量を算出したい単位に（下記例ではセンサーIDと年月）グループ化して
![Dataflow04_05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/ef89e935-ab55-85b9-9fc6-a01b1c3fbd3c.png)
②[2.並べ替え]タブで対象項目を昇順に並べ替え
![Dataflow04_06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/cf408910-1400-1a2e-7afd-e1e18f5b1e6d.png)
③[3.範囲]タブはデフォルト設定のまま変更なし
![Dataflow04_07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/1aa054e0-3a1e-6fca-7ddf-4c9715bfa16b.png)
④[4.ウィンドウの列]タブでnTile関数を使って4等分する
![Dataflow04_08.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/96a2638a-2899-c9d0-a456-24d02eeca915.png)
下記はイメージ
![Dataflow04_04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/8bea49f5-7b18-003c-7edb-753cd2376dea.png)
######Step2. 4等分されたデータから中央値、第1四分位数、第3四分位数を算出
⑤集計(Aggregate)モジュールを使用して統計量を算出したい単位に（下記例ではセンサーIDと年月）グループ化して
![Dataflow04_09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/e3576395-0bae-cf03-774c-05ff85de73d0.png)
⑥max関数とmin関数を使用して下記の計算式で集約する
![Dataflow04_11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/48962568-fd20-8403-62d3-0d7f91e430d4.png)
・中央値の場合、第2四分位のmax値と第3四分位のmin値を足して2で割ると中央値が算出できる
`(max(iif(test3_tile==2, test3, toFloat(null()))) + min(iif(test3_tile==3, test3, toFloat(null())))) / 2`
![Dataflow04_10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/e69dda31-22dc-6018-77a8-d508a76ad2fa.png)
・第1四分位数
`(max(iif(test3_tile==1, test3, toFloat(null()))) + min(iif(test3_tile==2, test3, toFloat(null())))) / 2`
・第3四分位数
`(max(iif(test3_tile==3, test3, toFloat(null()))) + min(iif(test3_tile==4, test3, toFloat(null())))) / 2`


#参照
https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-expression-functions#ntile
Azure Data Factory - Data Flow で月初を取得する方法

#はじめに

Azure Data Factory や Azure Synapse Pipeline の Data Flow (GUIとノーコードでデータ加工できるツール）を使ってデータ集計や予測モデル用のデータ加工をするときのテクニックを整理しています

#やりたいこと
日次データを月別に集計したいケースがあると思いますが、そのとき日付データから月単位の値を作成すると思います
'YYYYMM' とか 'YYYY-MM-01' とか
このときに日付値で保持していた方が日付計算の関数が利用できたり、BIで可視化する際に日付軸として扱いやすいので、筆者は日付値の'YYYY-MM-01'で作成するようにしてます

#方法
日付項目から月初('YYYY-MM-01')を作成する方法はいくつかありますが、筆者は下記のやり方で算出してます
派生列(Derived column)モジュールで列の追加をして式ビルダーにて下記の関数で算出
`addMonths(lastDayOfMonth({日付項目}),-1)+1`
やっていることを解説しますと
①lastDayOfMonth関数を使って対象日付の月末を算出し
　日付項目='2022/01/20'の場合は'2022/01/31'
②①の日付をaddMonths関数を使って1ヶ月前にして　'2022/01/31'⇒'2021/12/31'
③②の日付に1日足す　'2021/12/31'⇒'2021/01/01'
![Dataflow03_01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/265a022e-af15-89ab-b7c7-f0be05f67d4f.png)

#参照
https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-expression-functions
Azure Data Factory - Data Flow で null値をセットする方法


#はじめに

Azure Data Factory や Azure Synapse Pipeline のData Flow を使ってデータ加工するときに
ある列の値をゼロでもなくブランクでもなく明示的に null 値にする方法です。
普通に null() と設定してエラーなって困った人は意外と多いと思います。筆者もその経験者の1人です。

#方法

Data Flow の派生列、集約、ウィンドウ等のモジュール内で使える式ビルダーで、
null 変換したい列のデータ型に合わて toXXXXX() の中に null() をセットします
例1）toString(null())
例2）toInteger(null())
　　 iif(length({年}) == 0, toString(null()), {年})
![Dataflow01_02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/e3e91a78-df7c-9500-1816-983bd5c13013.png)

#補足：どんなときに null() 変換をつかうのか？

例えばこんなとき null() 変換が必要でした
例1）
やりたいこと：
 後続処理でFill(値埋め)したいが、値にブランク('')が入っており、Fillのためのcoalesce関数が効かない
方法：
 ①前段でブランク値をnull値に変換してから
![Dataflow01_02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/e3e91a78-df7c-9500-1816-983bd5c13013.png)
 ②ウィンドウ(window)モジュールでcoalesce関数を使ってFillする
![Dataflow01_03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/ec9b4a8e-bd84-5829-805d-9d2b0a794ff8.png)
Fill実装の参考：https://techcommunity.microsoft.com/t5/azure-data-factory-blog/implement-fill-down-in-adf-and-synapse-data-flows/ba-p/2013406

例2）
やりたいこと：
　ある項目の平均値を算出したいが、値が999のデータは無視して平均値を出したい
　※ゼロ(0)に変換すると平均値として計算されてしまうので、無視する場合はnull値に設定するのがポイント
方法：
　集約(aggregate)モジュールの式ビルダーにて以下のように式を設定する　
![Dataflow01_01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482258/4d390cec-ecfd-51d8-4d35-9e804ca9f10a.png)

#参考
https://docs.microsoft.com/ja-jp/azure/data-factory/concepts-data-flow-expression-builder

https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-expression-functions

https://docs.microsoft.com/ja-jp/azure/data-factory/data-flow-transformation-overview
【nodejs】NodeJS v17.4.0 ソースインストール【RockyLinux】

# NodeJS の最新版 インストール

2022/01/20

- NodeJS : v17.4.0
- OS : Rocky Linux release 8.4 (Green Obsidian)

## 手順

### C, C++コンパイラが必要なのでinstall

```
# dnf install -y gcc gcc-c++ make
```

### Source Install

```
# cd /usr/local/src
# wget https://nodejs.org/dist/v17.4.0/node-v17.4.0.tar.gz
# tar xzvf node-v17.4.0.tar.gz 
# cd node-v17.4.0
# ./configure

# ↓ GCE2コア8GBのインスタンスだと1時間くらいかかるので注意 -j<cpuコア数>で分散処理可能？
# make
# make install
```

### 確認

```
$ node -v
v17.4.0

$ npm -v
8.3.1

$ npx -v
8.3.1
```
Looking For the Best Private Detective Agency in Gurgaon?

HR Investigation is the best Private Detective Agency in Gurgaon to provide various services such as loyalty test investigation,  Pre Matrimonial Investigation, post marital investigation services to you. They provide the best supervision ability without harming your privacy. Pre Matrimonal Investigation has become the most crucial way nowadays to investigate their potential partner and your in-laws. HR Investigation is having a team of Private Investigator Gurgaon that provide 24/7 surveillance on the subject and provide you with appropriate results. 
https://hrinvestigation.com/private-detective-agency-in-gurgaon/
【Swift】PDFViewの拡大率・縮小率を設定する方法

## 課題

SwiftでPDFViewを実装すると、デフォルトだと無限に拡大＆縮小ができてしまう。

最初から拡大率と縮小率を設定しておかないとユーザービリティが悪化してしまう。

## 実装方法

```swift
let pdfView = PDFView()

//拡大率の上限
pdfView.maxScaleFactor = 2
//縮小率の下限
pdfView.minScaleFactor = 0.5

//以下のPDFViewの設定は適当です
pdfView.autoScales = true
pdfView.displayMode = .singlePage
pdfView.displayDirection = .horizontal
pdfView.displaysPageBreaks = false
```

## 参考

https://developer.apple.com/documentation/pdfkit/pdfview/2869775-maxscalefactor

https://developer.apple.com/documentation/pdfkit/pdfview/2869783-minscalefactor

## おすすめ情報

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

https://wagtechblog.com/programing/swift-textbook.html
renovateのconfigのvalidateをCI(CircleCI)で行う

# Renovateとは

DependaBotのようなライブラリのバージョンのアップデートをしてくれるサービス・ツールです。
https://www.whitesourcesoftware.com/free-developer-tools/renovate/
https://github.com/renovatebot/renovate

# configのvalidateとは(やりたいこと)

Renovateの設定は、yamlファイルに書くのですが、実際動かしてみるまでその記述があっているのかなどの確認ができないと設定ファイル書くのが大変なので、CIでチェックできるようにしたいところです。
※ configファイルがvalidかどうかなので、設定が意図通り動くかのチェックはできないです。

この記事では、それをcircleCIで動かす方法についてです。ですが、他のCIツールやローカルで動かすときにも参考になると思います。

# 要約

- 公式Documentでは、CircleCIのOrbを使う方法が書かれている。
- しかし、3rdPartyのOrbなので、利用しづらい
- npmなどでvalidatorが公開されているので、それをCIで動かせば良い

# 公式で書かれてる Orb を使う

<https://docs.renovatebot.com/examples/self-hosting/#renovate-config-file-validation-when-using-circleci>

```yml
version: '2.1'
orbs:
  renovate: daniel-shuy/renovate@2.1
workflows:
  lint:
    jobs:
      - renovate/validate-config
```

CircleCIのorb(共通で利用できる設定みたいなもの)があって、Renovateのdocumentでもそれを利用するように書かれてるので、基本的にはそれを参考にすれば動かすことができます。
しかし、3rd-party(非公式)なOrbのため、3rd-patyのorbを許可していないとと以下のようにエラーになってしまいます。

```
#!/bin/sh -eo pipefail
# Orb daniel-shuy/renovate@2.1 not loaded. To use this orb, an organization admin must opt-in to using third party orbs in Organization Security settings.
# 
# -------
# Warning: This configuration was auto-generated to show you the message above.
# Don't rerun this job. Rerunning will have no effect.
false

Exited with code exit status 1
CircleCI received exit code 1
```

## 3rd-party orbを許可するには

CircleCIの設定で、3rd-partyのorbを許可する設定があるので、そこで許可することができます。
:warning: 注意 :warning: 3rd-partyのorbを許可していいかは、各自責任を持って判断をしてください！(デフォルトは許可しない設定になっています)
3rd-partyのorbを許可するのはRepository個別の設定ではなく、Organizationの設定です。
しかも、特定のorbを許可するような設定ではなく、3rd-partyのorbすべてを利用可能になってしまいます。
個人開発ならあまり問題ないと思いますが、チーム・会社でのorganizationの場合、これを有効化するというのはあまり好ましい状態ではないと思います。

https://circleci.com/docs/2.0/orb-intro/#the-orb-registry

> Note: In order to use uncertified orbs, your organization’s administrator must opt-in to allow 3rd-party uncertified orb usage on the Organization Settings > Security page for your org.

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26310/efb25192-c68a-8957-a4e6-ec5b8889aee1.png)


# Orbを使わずに動かす

Orbを使わず validator を自前で動かすことができます。
ありがたいことに、npm package, docker image, GitHub actionsなどでvalidatorが公開されています。
https://docs.renovatebot.com/#renovate-development-and-use

たとえば、
npm packageを利用してvalidateを動かそうとすると

```sh
$ npm i -g renovate # yarn global add renovate
$ renovate-config-validator
```

という感じです。

ので、これらを CircleCI で動くように書いてしまえばOKとなります。

# CircleCI で Renovate の config の validator を動かす

```yml
version: 2.1

executors:
  default:
    working_directory: ~/repo
    docker:
      - image: cimg/node:lts

jobs:
  lint:
    executor: default
    steps:
      - checkout
      # renovate-config-validator を install したりなどはよしなに書く必要があります。
      - run: yarn renovate-config-validator

workflows:
  build:
    jobs:
      - lint
```

最終的にはこのような感じです。
(renovate-config-validatorのinstallやnodeのversionとかは調整してください)
ニアショアソフトウェア開発が完璧なソリューションである理由

![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512901/a5f87f4f-3cfa-467a-c085-a88fe79e81b2.png)
ニアショア開発は、ソフトウェアアウトソーシング開発として新に注目されていますが、すでに多数の事業で行われ、多くの効果とメリットを期待できるソリューションです。では、 ニアショア開発とはどんなことでしょうか？ニアショアリングのメリットは？ LTSの本記事でこれらの質問に答え、この有利な開発アプローチ方法を適用する理由を理解しましょう。

#1.  ニアショア開発とは 何？
ニアショア開発は、ITアウトソーシングの一種です。 ITアウトソーシングを活用することで、一般的にITセンターの置かれる所を構わないと考えられていますが、ニアショア開発では、顧客とベンダーは地理的に近くにあることが多いです。時差は2、３時間が理想的です。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512901/07f1c1aa-2b57-406c-44d0-c01e3ac1884c.png)
                *ニアショアソフトウェアのアウトソーシング・簡単な事例*
たとえば、日本の企業は、ベトナムやその周辺国のオフショア開発センターを探すことがよくあります。

ITアウトソーシングは、多くの場合、企業がビジネスの運用またはIT運用全体に負担を減らすようにするためのソリューションです。よく知られているITアウトソーシングのメリットは、コスト削減、技術の専門知識、または移転時間の短縮などです。ただし、ITアウトソーシングプロセスに関しては、まだいくつかの欠点があります。次の潜在リスクが挙げられます。

1) コミュニケーションの問題
2) 慣例の違い
3) 時差の違い

これらのリスクを回避するために、多くの企業はニアショアアウトソーシングに移しています。ニアショアアウトソーシングでは、顧客はITのいくつかの業務、つまりソフトウェア開発またはソフトウェアテストを近隣の企業に委任します。これを行うことにより、顧客は業務委託の作業を良く監督、管理することができます。ニアショア開発では、顧客とベンダーは、同様の言語、同じ文化、および便利なタイムゾーンを共有することが多いです。

 **[続きを読む](https://lotus-ts.com/jp/blogs/nearshore-software-outsourcing-perfect-solution/?utm_source=Qiita&utm_medium=Share+Blog&utm_campaign=LTS)**

----------------------------------------------------

__LTSによるニアショアソフトウェアのアウトソーシング__
LTSは、アジアの多くの国々のニアショア開発パートナーであり、優秀なIT人材を国際市場に送り込んでいます。 顧客にサービスを提供する際にLTSでは常に次のことを確保します。

・確定のスケジュールにより製品を常にQAプロセスの複数のレイヤーを通じてレビューし、顧客に最高の成果を渡します。
・顧客の質問に答えるための継続的なコミュニケーションを確保します。
・プロジェクトにITコンターまたはブリッジSEスタッフも参加させます。これらの従業員は、技術的な知識を持っているだけでなく、顧客と流暢にコミュニケーションが取れる言語能力も持っています。

ニアショアソフトウェア開発に興味がございましたら、お気軽にご連絡ください。

Website: https://lotus-ts.com/jp
Tel: (+84) 24-6660-7474
Linkedin: https://www.linkedin.com/company/lotus-ts/
ngrok使ってローカル環境をサクッと外部公開する

## ngrok
https://ngrok.com/

[Wordpressローカル環境をLocal By Flywheelで構築した](https://qiita.com/lvn-takeuchi/items/85c7dad8b7653e5de2ab)でLive Linksが便利だったのでngrok使ってみた

Live Links同様、ローカル環境を外部からアクセスできるようになります!!

## 手順

1. [公式](https://dashboard.ngrok.com/)でFreeプランでアカウントを登録する
    * Basic認証を使用しない場合はアカウント登録しなくてもOK)
    * サブドメイン指定は有料プランにする必要あり
2. [DLぺージ](https://ngrok.com/download)からDL方法を選択する.  
    macの場合

    ```shell
    $ brew install ngrok/ngrok/ngrok
    $ ngrok -v
    ngrok version 2.3.40
    ```

3. [Your Authtoken](https://dashboard.ngrok.com/get-started/your-authtoken)ページで確認できるトークンを登録する

    ```shell
    $ ./ngrok authtoken <トークン>
    ```
    ※トークンは~/.ngrok2/ngrok.ymlに記録されます

4. webサーバーを起動する
    * authオプションでBasic認証のID/PWを設定する
    * regionオプションで日本リージョンを指定

```shell
$ ngrok http -region jp -auth="user-name:user-pass" 8080
```

```shell
ngrok by @inconshreveable                                                                                                 (Ctrl+C to quit)
                                                                                                                                          
Session Status                online                                                                                                      
Account                       dtakeuchi (Plan: Free)                                                                                      
Version                       2.3.40                                                                                                      
Region                        Japan (jp)                                                                                                  
Web Interface                 http://127.0.0.1:4040                                                                                       
Forwarding                    http://ffbe-118-238-205-180.jp.ngrok.io -> http://localhost:8080                                            
Forwarding                    https://ffbe-118-238-205-180.jp.ngrok.io -> http://localhost:8080                                           
                                                                                                                                          
Connections                   ttl     opn     rt1     rt5     p50     p90                                                                 
                              0       0       0.00    0.00    0.00    0.00  
```

## Web Interface  
コンソールでもリクエストは確認できますが、Web Interface( http://localhost:4040 )も用意されています

![スクリーンショット 2022-01-20 14.48.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348159/34a965a4-bcbc-9299-f986-99f05d804684.png)
Workato：Rubyコネクターを使用して、multipart/form-data でファイルをPOST(アップロード)する

## はじめに
Workatoは、REST APIによるファイルのアップロードおよびダウンロードに対応しています。

コネクターが用意されているアプリケーション（サービス）の場合は、そのアプリケーションがファイルのアップロードやダウンロードに対応していれば、コネクターを利用してファイルのアップロードやダウンロードを行うことができます。

コネクターが用意されていないアプリケーションの場合、ファイルのダウンロードはHTTPコネクターを利用することで対応が可能です。

ファイルのアップロードは、Bodyへファイルをセットする方法の場合はHTTPコネクターを使用してアップロードすることが出来ます。 `Content-Type: multipart/form-data` でファイルをアップロードする場合は、HTTPコネクターではなく、Rubyコネクターを利用するか、Connector SDKでカスタムコネクターを作成して対応する必要があります。

ここでは、Rubyコネクターを利用して `Content-Type: multipart/form-data` によるファイルアップロードを実現する方法について説明します。

## 手順
Rubyコネクターをレシピに追加し、次の通り定義します。

### Input および Output schema
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/112d6a17-c43b-3d73-7134-f9a40838072a.png)

なお、UI上から編集できないプロパティ（optional）は、Edit schemaをクリックし、手動でJSONテキストを編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d27d12b6-ec87-5f42-3c34-b8489e821250.png)


### コード

```ruby
# アップロード先URL
url = input['url']

authorization = ''

# 認証情報としてBasic認証情報をセット（Basic認証情報がセットされている場合）
if ! input['basic_auth_username'].blank? && ! input['basic_auth_password'].blank?
  	authorization = 'Basic ' + "#{input['basic_auth_username']}:#{input['basic_auth_password']}".encode_base64
end

# 認証情報としてBearer Tokenをセット（Bearerトークンがセットされている場合）
if ! input['bearer_token'].blank?
  	authorization = "Bearer #{input['bearer_token']}"
end

# Payloadセットする値を定義
values = {}
values[input['file_key']] = [
  	input['file_body'],
  	'application/octet-stream',
  	input['file_name']
  ]

# HTTPリクエストと結果を取得
if authorization.blank?
  res = post(input['url'])
      .payload(values)
      .request_format_multipart_form
      .response_format_raw
else
  res = post(input['url'])
      .payload(values)
      .headers('Authorization': authorization)
      .request_format_multipart_form
      .response_format_raw
end

# 結果を返す（JSONテキストとしてセット）
# 各種フォーマット（JSON等）からのパースは、後続での対応（例えば JSON parser by Workatoで行うこと）を想定
{
  res: res
}
```

## 参考

https://docs.workato.com/developing-connectors/sdk/guides/data-formats/request_format_multipart_form.html#how-to-guides-multipart-form

https://docs.workato.com/developing-connectors/http-vs-sdk.html#http-vs-sdk
SPSS Modeler ノードリファレンス 1-2 Excel入力

# 1-2 Excel入力ノード[入力タブ]
<img width="200" alt="107_89エクセル.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8cda3ebe-0f20-41d6-20ff-529feee7a183.png">
##1.ノードの目的
Excelファイル形式のデータを読み込みます。


## 2.解説動画（60秒）

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

## 3.クイックスタート

ファイルタブの[ファイル：]の[...]ボタンから読み込むファイルパスを指定します。
（またはエクスプローラからXlsxファイルをストリーム領域にドロップ）
![スクリーンショット 2022-01-20 17.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a934f8f2-801d-01d8-1ed2-821e1647db57.png)

画面上のプレビューでデータが表示されます。

![スクリーンショット 2022-01-20 17.47.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cc793d0c-5947-7ba1-0286-175a82696836.png)

### うまく読めない場合のヒント
Excelはデータが複数のシートに分かれている場合があります。
![スクリーンショット 2022-01-20 17.49.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a4985f62-334d-138e-d292-d59fb74190e7.png)
入力時にワークシートを指定します。
![スクリーンショット 2022-01-20 17.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/36027d23-fb5d-c6c8-8ac8-eeec5a9c81a6.png)

またヘッダーを無視して特定範囲だけ読み込むことができます。以下の例はA3セルからC８セルを範囲指定しています。
![スクリーンショット 2022-01-20 17.55.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/5dbb1863-8d55-6d00-c6c4-c15d9bd93527.png)


## 4.Tips

####名寄せ
以下の取引データにはさまざまな会社が登場しますが、表記揺れを補正すると2社に名寄せすることができます。
![スクリーンショット 2022-01-20 18.17.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/88fb347c-a917-5a98-97ed-77cecda964a7.png)

その場合にはあらかじめ以下のような（会社名マスタ）をExcelで作ります。Excelは更新がしやすいので小規模な取り組みではマスタ管理に適しています。

![スクリーンショット 2022-01-20 18.15.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f37dbc16-9f1f-7a7d-c2f6-0eb5267b8999.png)

[レコード結合]ノードで社名1をキーに取引データと社名マスタを結合すると名寄せは完了です。[会社名1]は[会社名2]に翻訳されました。
![スクリーンショット 2022-01-20 18.25.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/96470afb-7539-ab47-9916-136f29765529.png)



## 5.参考情報

#### 利用データ

リンク先を選択し保存してください。

https://github.com/yoichiro0903n/blue/blob/main/product.xlsx?raw=true

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee
CSS：マスキングテープ風

##はじめに
完全なるメモ。HTMLとCSS(SCSS)だけでやります。
ネットの記事を参考にしているので被っているものがあったらすみません。
参考程度に。

種類は、ストライプ柄とドット柄。

##完成イメージ

ストライプ柄 マスキングテープ
<img width="300" alt="masking-tape-stripe.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365722/b079e924-94fc-e6e0-80b5-12821dc795d7.png">

ドット柄　マスキングテープ
<img width="300" alt="masking-tape-dot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365722/16025c23-fee6-df16-23ea-fba8fa6268e1.png">

##HTML


```html:HTML
<div class="card">
  <span class="masking-tape"></span>
</div>
```

##CSS ストライプ柄

```scss:scss
.card {
 position: relative;
  width: 20rem;
  padding: 5rem 0;
  border: 2px solid black;
  background-color: whitesmoke;

  //マスキングテープ風　ストライプ
  .masking-tape {
    position: absolute;
    top: -1em;
    left: 30%;
    width: 100px;
    height: 30px;
    background-image: linear-gradient(
      -45deg,       
      rgba(203, 64, 66, 0.5) 25%,
      transparent 25%,
      transparent 50%,
      rgba(203, 64, 66, 0.5) 50%,
      rgba(203, 64, 66, 0.5) 75%,
      transparent 75%,
      transparent 100%
    );
    background-repeat: repeat;
    background-size: 20px 20px;
    background-position: 0 0, 20px 20px;
    border-left: 2px dotted rgba(0, 0, 0, 0.1);
    border-right: 2px dotted rgba(0, 0, 0, 0.1);
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
    padding: 0.25em 2em;
    background-color: white;
    transform: rotate(-4deg);
  }
}
```

`background-image: linear-gradient(  -45deg, `
を `45deg`に変えると左上から右下へのストライプに変わる。

##CSS ドット柄

```scss:scss
//変数　色
$yellow-clear: rgba(245, 216, 0, 0.8);

.card {
 position: relative;
  width: 20rem;
  padding: 5rem 0;
  border: 2px solid black;
  background-color: whitesmoke;

  //マスキングテープ風　ドット
  .masking-tape {
    position: absolute;
    top: -1em;
    left: 30%;
    width: 100px;
    height: 30px;
    background-image: radial-gradient($yellow-clear 30%, transparent 30%),
      radial-gradient($yellow-clear 30%, transparent 30%);
    background-size: 16px 16px;
    background-position: 0 0, 8px 8px;
    background-repeat: repeat;
    border-left: 2px dotted rgba(0, 0, 0, 0.1);
    border-right: 2px dotted rgba(0, 0, 0, 0.1);
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
    padding: 0.25em 2em;
    background-color: white;
    transform: rotate(-4deg);
  }
}
```

`background-size: 16px 16px;`
`background-position: 0 0, 8px 8px;`

`background-size` は　`background-position`の倍である必要がある！


##最後に
構造はデベロッパーツールでいじりながら理解しました。
もっとスマートな方法があるかもしれませんが
メモとして残しておきまーす。
NVIDIA GPU の NVIDIA architectures のまとめ

# 概要
NVIDIA の GPU には NVIDIA architectures という コードが割り当てられているが、よく忘れるのでまとめたもの。

出典： https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ 


|世代 | NVIDIA architecture name | ボード名 | 対応CUDA バージョン|
|---|---|---|---|
|Fermi| sm_20| GeForce 400, 500, 600, GT630| CUDA3.2 ~ CUDA 8 |
|Kepler| sm_30| GeForce 700, GT-730| CUDA 5 ~ CUDA 10 |
|| sm_35| GeForce K40|  |
|| sm_37| GeForce K80|  |
|Maxwell| sm_50| Quadro RTX 4000 | CUDA 6 ~ CUDA 11 |
|| sm_52| Quadro M6000, GeForce 900, GTX-970, 980, Titan X |  |
|| sm_53| Tegra TX1, Tegra X1, Drive CX, Drive PX, Jetson Nano |  |
|Pascal| sm_60| Quadro GP 100, Tesla P100, DGX-I | CUDA 8 -  |
|| sm_61| GTX 1080, GTX 1070, GTX 1060, GTX 1050, GTX 1030 (GP108), GT 1010 (GP108) Titan Xp, Tesla P40, Tesla P4, Discrete GPU on the NVIDIA Drive PX2 |  |
|| sm_62| Integrated GPU on the NVIDIA Drive PX2, Tegra (Jetson) TX2 | CUDA 8 -  |
|Volta | sm_70| DGX-1 with Volta, Tesla V100, GTX 1180 (GV104), Titan V, Quadro GV100 | CUDA 9 -  |
| | sm_72| Jetson AGX Xavier, Drive AGX Pegasus, Xavier NX | CUDA 9 -  |
| Turing | sm_75| GTX/RTX Turing – GTX 1660 Ti, RTX 2060, RTX 2070, RTX 2080, Titan RTX, Quadro RTX 4000, Quadro RTX 5000, Quadro RTX 6000, Quadro RTX 8000, Quadro T1000/T2000, Tesla T4 | CUDA 10 -  |
| Ampere | sm_80| NVIDIA A100 (the name “Tesla” has been dropped – GA100), NVIDIA DGX-A100 | CUDA 11.1 -  |
| | sm_86| Tesla GA10x cards, RTX Ampere – RTX 3080, GA102 – RTX 3090, RTX A2000, A3000, A4000, A5000, A6000, NVIDIA A40, GA106 – RTX 3060, GA104 – RTX 3070, GA107 – RTX 3050, Quadro A10, Quadro A16, Quadro A40, A2 Tensor Core GPU | CUDA 11.1 -  |
| Hopper | sm_90| NVIDIA H100　（GH100） | CUDA 12 [計画] -  |
DatabricksのUIが日本語対応しました！

> [Databricksクイックスタートガイド](https://qiita.com/taka_yayoi/items/125231c126a602693610)のコンテンツです。

お待たせしました。ようやくDatabricksのユーザーインタフェースが日本語に対応しました。

以下の手順でGUIを日本語に変更できます。

1. **Settings > User Settings**を開きます。
1. **Language Settings**タブをクリックします。
![Screen Shot 2022-01-20 at 17.58.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/13aaa56f-81fd-eed3-06ce-e9389873dd94.png)

1. Change Your Languageから言語を選択します。
![Screen Shot 2022-01-20 at 17.58.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5c334039-8455-98fd-99c8-348b399bea7b.png)

    以下の言語がサポートされています。
    - 英語
    - ドイツ語
    - フランス語
    - イタリア語
    - 日本語
    - 韓国語
    - ポルトガル語

1. 言語を選択すると画面がリフレッシュされ、GUIが選択した言語で表示されます。
![Screen Shot 2022-01-20 at 17.58.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/577fc520-ee2d-f063-b334-00e0f84cc70c.png)

![Screen Shot 2022-01-20 at 17.59.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4dcfd245-feff-306d-b9ec-8c18bbbef7aa.png)
![Screen Shot 2022-01-20 at 17.59.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8d12fde0-dea5-ee4d-ca8e-a7d200c0025b.png)
![Screen Shot 2022-01-20 at 17.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/48fdf5e3-d2d7-a80e-8cea-6156e23ca3e8.png)

なお、プレビュー機能ですので、翻訳結果に関しては生暖かい目で見守っていただけると幸いです。継続的に改善してまいります。私も一部翻訳しました。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
【Node.js、Javascript】SeleniumでOffice365にログインする

# はじまり

はじめてSeleniumを使って悪戦苦闘した熱が冷めない内に、成果を上げておきます。
Seleniumで、Office365から立ち上げるアプリの直リンクへアクセスした際に、Office365へのログインが求められた際に切り抜けたソースを貼っておきます。
ブラウザはChromeで行いました。

# ソース

コメントアウトしているところはなくても動きますが、Seleniumのコードの動作確認ではあったほうがより役立ったという感覚がありました。
画面遷移の度に10秒くらいは余裕を持っていたほうが良いと思います。driver.waitは試していませんが、他のソースにも転用するために`driver`に依存しないものにしました。
`waitTimeToDisplay`は、各々のアプリによって時間を設定していただければと思います。

```javascript
const { Builder, By } = require('selenium-webdriver');
const { it } = require('mocha');

const sleep = waitTime => new Promise( resolve => setTimeout(resolve, waitTime) );

const openAppViaO365 = async(driver, url, username, password, waitTimeToDisplay=40000) => {
    // const funcName = 'openAppViaO365';
        
    await driver.get(url);
    await driver.manage().window().maximize();
    // await console.log(funcName, "aaaaaaaaaaaaaaaaaa");
    await sleep(10000); 
    
    await driver.findElement(By.id("i0116")).sendKeys(username);
    await driver.findElement(By.id("idSIButton9")).click();
    // await console.log(funcName, "bbbbbbbbbbbbbbbbbb");
    await sleep(10000);
    
    await driver.findElement(By.id("i0118")).sendKeys(password);
    await driver.findElement(By.id("idSIButton9")).click();
    // await console.log(funcName, "cccccccccccccccccc");
    await sleep(10000);
    
    await driver.findElement(By.id("idBtn_Back")).click();
    // await console.log(funcName, "dddddddddddddddddd");
    await sleep(waitTimeToDisplay);
};

let driver;
describe("テスト", () => {
    before(() => {
        driver = new Builder().forBrowser("chrome").build();
    });

    after(() => {
        return driver.quit();
    });

    it(`Office365ログイン`, async () => {
        await openAppViaO365(driver, "https://~", "<username>", "<password>")
    });

});
```

# おしまい
同じテスト自動化ツールのCypressだとこのログインになかなか苦戦しましたが、Seleniumだと案外あっさりできました。
Cypressだと`it`ブロックが切り替わると表示されていた画面が閉じてしまったりもしますしね・・・
【Node.js、Javascript】Seleniumで疑似要素の属性値を取得する

# はじまり

今回、Seleniumで疑似要素の`content`属性の値を取得するコードを作成しましたので掲載します。

本ソースは、OutSystemsで作られたシステムにおいて、チェックボックスのチェックの有無を判断するために使用したので、同様にOutSystemsを使っている方も利用できるのではないでしょうか。

動かしたブラウザは、Chromeです。

# ソース

```javascript
const { Builder } = require('selenium-webdriver');

const getPseudoElementsContentsByClassName = async(driver, className, isAfter=true) => {
    const funcName = 'getPseudoElementsContentsByClassName';
    let afterOrBefore;
    if(isAfter === true){
        afterOrBefore = ':after';
    }else{
        afterOrBefore = ':before';
    }
    let contents = await driver.executeScript(`const elements = document.querySelectorAll(\"${className}\"); let contents = []; for(let i = 0; i < elements.length; i++){contents.push(window.getComputedStyle(elements[i], \"${afterOrBefore}\").content);}; return contents;`);
    return new Promise( resolve => resolve(contents) );
}

let driver;
describe("テスト", () => {
    before(() => {
        driver = new Builder().forBrowser("chrome").build();
    });

    after(() => {
        return driver.quit();
    });

    it(`疑似要素after取得`, async () => {
        let contentsCheckboxAfter = await getPseudoElementsContentsByClassName(driver, '.checkbox', true);
        console.log(contentsCheckboxAfter);
    });
});
```

僕がこのソースを実行した結果が、`" "`と出力されているチェックボックスはチェックが入っていて、`null`はチェックが入っていないチェックボックスという並びでした。

```bash:出力例
[
  '" "',  '" "',  'none', 'none', 'none', 'none', 'none',
  'none', 'none', '" "',  'none', 'none', 'none', 'none',
  '" "',  'none', '" "',  'none', 'none', 'none', 'none',
  'none', 'none', 'none', 'none', 'none', 'none', 'none',
  'none', 'none', 'none', 'none', 'none', '" "',  '" "',
  'none', 'none', '" "',  'none', '" "',  'none', 'none',
  'none', 'none', 'none', 'none', 'none', 'none', 'none',
  'none', 'none', 'none', 'none', 'none', 'none', '" "',
  '" "',  'none', 'none', 'none', 'none', 'none', 'none',
  '" "',  '" "',  'none', 'none', 'none', 'none', 'none',
  'none', 'none', 'none', 'none', 'none', 'none', 'none',
  'none', 'none', 'none', '" "',  '" "',  '" "',  'none',
  '" "',  'none', 'none', '" "',  'none', 'none', 'none',
  'none', 'none', 'none', 'none', 'none', 'none', 'none',
  'none', 'none',
  ... 218 more items
]
```

# おしまい

`checked`属性ではなく、`::before`と`::after`の判定になることで、`executeScript`を使う羽目になりだいぶ面倒になりました・・・。
デザインを凝ると、その分テストが大変になるんですなあ。と思いました。