OmniAICreator/Qiita-1.07M huggingface dataset:
自転車通販サイトcyma-サイマ-のフロントエンドリプレイス戦略

[Ateam Commerce Tech Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ateam-commerce-tech) の17日目は、@nagimaruxxxが担当します。

# はじめに
[cyma](https://cyclemarket.jp/)ではレガシーなフロントエンドから脱却するため、2021年の初め頃からフロントエンドリプレイスに向けて動き出しています。
本格的なリプレイスはこれからなのですが、テスト的にリプレイスされたページをリリースしてみての反省や良かったことをお話ししたいと思います。

# リプレイスに至った経緯
cymaのフロントエンドの技術スタックはこのような感じになっています。

- Rails
- jQuery
- SCSS

よくある感じの組み合わせですが、それに加えて

- 少しSCSSを触っただけて全く関連のないページのスタイルが破壊される
- フロントエンド担当者以外が書いている部分があり、それが積もってソースコードの解読が困難な部分が多々見受けられる

などの問題があり1つの施策を出すのにも余計な工数がかかってしまい、スケジュール通りに開発が進まないのが常でした。
そのため解読困難なソースコードをこれ以上増やさないように、且つ現状ある解読困難なソースコードも撲滅するため、フロントエンドのリプレイスを行うことにしました。

# クリアしなければいけない課題
cymaは通販サイトのためサイトの変更がCVに直結します。そのため、本格的にリプレイスする前にテスト的にプロトタイプを作成し以下の指標がリプレイスによって下がらないか検証する必要がありました。

- CVR
- SEO順位
- ページスピード
- 技術的実現可能性
    - jQueryだとできることがフレームワークに置き換えることによって出来なくなることはないか

上記を1ヶ月検証し、数字が悪くならないことを証明できた後に本格的に動いていくことにしました。
どのページを試しにリプレイスするかはマーケチームと相談し、ある程度CVがついていてかつそんなに影響が大きくないページを選んでもらいました。

# 技術選定
リプレイスに使用する主な技術は以下のようになっています。

- TypeScript
- Next.js
- Vercel
- SCSS
- REST(Rails)

![Group 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246277/19b00790-5e7f-3cd6-bd15-e8e575617a97.png)

初めはVue.jsかReactで議論していたのですが、ライブラリの豊富さ、Vue.jsのTypeScriptの相性の悪さから(現在は解消されています)Reactに決定、その後ローンチ作業が進行されていた新規プロジェクトとなるべく合わせた方が良いのではという結論に至りNext.jsに決定しました。

# リプレイス後の数字の変化

### リプレイス前
![スクリーンショット 2021-12-14 18.36.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246277/1a96e065-082c-963e-7196-c2ea20f3d62b.png)

### リプレイス後
![スクリーンショット 2021-12-14 18.37.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246277/368f70fe-99e8-fe31-b568-4c9d7d85ac56.png)

プロトタイプを実装した当時はNext.jsの経験が浅く、なぜかSSRでページを実装してしまったためもう少しパフォーマンスの数字は上げられそうです。

CVRやSEOの順位もリプレイスによって悪影響が出ていることは確認できませんでした。

# 振り返り
### 良かったこと
- プロトタイプを作成したこと
    - 実際に手を動かしてみないとわからないことが出てくる
    - ぶっ壊す前提で実装したので、本実装時はこの技術使うのやめようという選択ができる

- 他のチームとの連携
    - マーケチームにどのページをリプレイスしてもいいか選んでもらったり
    - SEOチームにリプレイス後のページのレビューをしてもらったり
    - そもそもリプレイスを試して良いか経営陣に許可をもらったり
    - 本当に色んな人のご協力があって踏み出せたと思います。

### 悪かったこと
- RESTで実装したこと
    - リプレイス時はRESTでも良いと考えていましたが、今後施策等でデータ構造が変わるといったときにバックエンドとフロントエンドが同時にリリース出来ないので面倒
    - 新規プロジェクトがNext.js + Hasuraで構成されておりその開発体験の快適さにRESTで書くのがしんどくなってしまった

# 検証完了後に変更した技術

- SCSS　→ `emotion/styled`に
    - SCSSはtsファイルと別にできるのでスッキリしますが、CSS propsを扱いにくいのと施策を重ねていくうちに不要なスタイルが増えそうなので変更しました(cymaが現状そうなってしまっているので余計に避けたかった)
    - その点`emotion`は使用していないスタイルにすぐ気づくことができます
    - emotion/reactはコンパイル時間が遅いのでemotion/styledを選択しました
- REST　→ GraphQL
  - `Rails on GraphQL Resolver` か `MySQL8 + Aurora + Hasura`にする予定
  - Railsに書かれたロジックを利用しつつGraphQLを使う戦略
  - 新規プロジェクトがNext.js + Hasuraで構成されておりその開発体験の快適さにRESTで書くのがしんどくなってしまいました
  - ただcymaはHasuraの運用を考慮したデータ構造になっていないのでそこをどうクリアするかが課題です
- monorepo環境へ
    - 現状はSPとPCのViewが別々になっており、サーバーサイドで見た目の振り分けをしています
    - 今後もレスポンシブデザインになる予定はありませんが、ロジックは共通化したいのでmonorepo環境に変更しました

# 最後に
完了したのはリプレイスの最初の一歩だけですが、なかなか踏み切れなかったフロントエンドのリプレイスに取り組み始めて検証まで終えられて良かったと思います。
リプレイス完了まではまだまだ道のりは長いですが見つけた課題を一つ一つ確実に潰していってより良い環境をお客様と開発していくメンバーに提供していきたいと思っています。
最後まで読んでいただきありがとうございました！
[SwiftUI] 意図せず外部ブラウザを開いてしまう問題。

TextやButtonなど、URLを文字列で格納しているViewを押下した際に、外部ブラウザを開いてしまう問題。

以下の場合、Text("遷移した")に遷移せずに、外部ブラウザ（safari）でhttps://qiita.com/trend を開いてしまう

![NG1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1322570/eed19200-2631-eabc-e9d8-a7b13f90f1d0.gif)


```swift
VStack(spacing: 30) {
    NavigationLink(destination: Text("遷移した")) {
        Text("https://qiita.com/trend")
    }
}
.foregroundColor(Color.materialColor(colorCode: .amber))
.background(Color.materialColor(colorCode: .teal))
```

## 解決

遷移させたいURLを変数に格納して使うことで、外部ブラウザを開くのを回避することができる。

```swift
VStack(spacing: 30) {
    let URL = "https://qiita.com/trend"
    NavigationLink(destination: Text("遷移した")) {
        Text(URL)
    }   
}
.foregroundColor(Color.materialColor(colorCode: .amber))
.background(Color.materialColor(colorCode: .teal))
```

![OK1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1322570/a8943dda-03c7-5d6b-cef3-2423061524de.gif)
ノーコードツール「Bubble」に触れて思うこと

こんにちは。
はじめてQiitaのアドベントカレンダーに投稿します。
内容は、今年に入って初めて取り組んだノーコードツール「Bubble」についての体験をお話ししたいと思います。

この手の話（情報）はネット上を探せば山ほどあると思いますが、誰かの参考になれば幸いです。
#ノーコードとの出会い
IT業界で仕事をしているので、OSに関係する機能を開発したり、ユーティリティソフトウェアなどを開発した経験もあるのですが、Webアプリケーションといわれるソフトウェアの開発経験はありませんでした。
ですが昨今、身の回りにはスマートフォンやPCのウェブブラウザを使ったオンラインショッピングなど、Webアプリケーションは身近なソフトウェアになっています。

仕事でソフトウェアのコードを書く現場から離れて久しいですが、Webアプリケーションの開発を体験してみたいと思っていた矢先、"ノーコード"というキーワードが目の前に現れました。言葉だけを見れば”コードを書かなくてアプリケーションが作れる”ということなので、「まゆつばな話」と思いながらも、ちょっとチャレンジしてみたいと思ったのがノーコードに触れるきっかけでした。それからどんなツールや環境があるのか探してみたところBubbleというツールに出会いました。これがノーコードとの出会いでした。

#Bubbleって簡単!
Bubbleはオンラインのサービスで、Webサイトからログインすると初回はチュートリアルが始まる仕組みになっていました。（2021.12.14現在も同じなのかどうか確認してません）
早速、このチュートリアルにチャレンジしました。チュートリアルは、Bubble側から操作の指示が矢印アイコンと文字情報で行われ、そのとおりに進める形式でした。

とりあえず一通りこなしました。ですが、初回のチュートリアルをこなしただけでは消化不良で分かったような、分からないような状態でした。
操作の指示に従っているときに「これは何をしているのか？」という意識が不足していて、使っているツールの意味や特徴を把握できなかったのが原因だと思います。そのため、チュートリアルをさらに数度こなしました。

チュートリアルの範囲が理解できると、Bubbleという世界観が以前に見たことのある世界に見えてきました。
それは、昔々に趣味で夢中になったApple社のOSにバンドルされていたHyperCardという道具（ソフトウェア開発・実行環境？）の世界です。

HyperCardが登場した頃、オブジェクト指向プログラミングが脚光を浴びていた時期だったと思うのですが（ずれてたらゴメンナサイ）、HyperCardはそのオブジェクト指向プログラミングを実践できるような道具だったと思います。
HyperCardがどんな感じの物かというと（表現できるか心配）、カード（四角い領域）上に、ボタンやテキスト領域やリスト領域などのオブジェクトをマウスを使って配置して、そのオブジェクトに対するイベント（マウスでクリックしたとか、マウスカーソルが上にあるなど）に応じた処理を対象のオブジェクトに作りこんでソフトウェアを開発するものです。
Bubbleのグラフィカルなエディタを使って、ボタンやテキスト領域などのオブジェクトをマウスで配置する、配置したオブジェクトの色や形や条件設定を加える属性を持っている点などが、まさに当時のHyperCardと重なって見えました（片方はオブジェクト指向なので違う点も多々あります）。

このチュートリアルをマスターした時点では「Bubbleって簡単！」と思っていました。
ただそれは、敷かれたレールの上の進んでいる状態なので、なにも分かっていない状態だったのでした。

#Bubbleって難しい!
チュートリアルをマスターした後、いざ、自分でアプリケーションを作り始めると直ぐに壁にぶち当たります。その壁は、Bubbleのデータタイプという物でした。

BubbleにはBubbleが用意したビルトインのデータタイプがあり、テキストや数値やリストなど基本的なものがあります。Bubbleを始めた頃、データタイプはこれらの基本要素だけのように思い込んだ事が壁を作り出していました。
実際には、開発者がアプリケーション作成環境上で新たに定義するデータ構造も、データタイプとして新たに追加されます。

このデータタイプの意識が低い（無い）状態で、Bubbleでアプリケーションを作ると、データのやり取りでデータタイプが違うと言われてエラーを頻発します。扱うデータが文字だとか、数値だとかでは無く、扱うデータのデータタイプが何なのかを意識する必要があります。

この壁も、振り返って見ればとても当り前の事なのですが、不慣れな環境／不慣れな道具の中で手探りで進んでいる最中には気付かなかったポイントでした。

このように、新しい物にチャレンジすると、簡単だ→難しい→簡単だ...を繰り返しながらスキルアップして行くと思います。今後も「難しい！」と思う事が現れると思います。でも、Bubbleに関する日本語での情報も増え続けているので、いろいろな壁を乗り越えて行けると思います（英語での情報は日本語以上にあるのでそちらも参考になります）。

#Bubbleっていろいろできそう!
いろいろと試行錯誤しながら、アプリケーションを作っているとAPIが提供されているサービスと連携したくなります。そんなとき、BubbleではBubble社が無償で提供しているAPI Connectorが利用でき、とても便利です。

Bubbleでは他にもプラグインが用意されていて、アプリケーションの機能を拡張できます。

そして、Bubbleのプラグインは自作することも可能です。自作のプラグインによって、新しいオブジェクト（Bubbleの用語ではエレメント）やワークフロー用にあらたな機能などを追加して利用することもできそうです（ここまでくるとノーコードの域を出てしまっていると思いますが、そこまで広がっているということです）。

#Bubbleを拡張したい！
作っているアプリケーションの都合でAWSのS3にデータを格納したり取り出したりする処理が必要となり、プラグインの自作を試みました。

BubbleのプラグインはJavaScriptで記述するようで、jQueryに対応しているとどこかに書かれていました。しかしながら、私自身はJavaScriptを使ったことが無く、全く知らないのでJavaScriptとjQueryの勉強が必要で一旦プラグイン作りをあきらめました（一人で作っているので他者に頼めません）。

アプリケーションのAWSのS3へのアクセスは、幸いな事に、プラグインのマーケットプレイスに幾つか希望する機能があったのでその中から選んで実装しました。

#Bubbleを極めたい！
これまでの経験から、プラグインなどを利用することで幅広く処理を実装できそうな気がしているので、まずは自作プラグインが作れるスキルを身に着け、さらにBubbleを極めて行きたいと考えています。
[py2rb] __getstate__

# はじめに
移植やってます
# `__getstate__` (Python)
```python
    def __getstate__(self):
```
`シリアライズ`って何？

```python
try:
    import dill
except ImportError:
    dill = None
    try:
        import cPickle as pickle
    except ImportError:
        import pickle
    serializer = pickle
else:
    serializer = dill
```
`pickle`って美味しいの？
# どうする？ (Ruby)
```ruby
```
もちろん`Ruby`にもシリアライズの機能はある。
同実装するかは、要検討。
# メモ
+ Python の `__getstate__` を学習した
+ 道のりは遠そう
エンジニアの成長をRPGとして考えてみた

#人が成長するって何だろう？

エンジニアを長くやってきました。
株式会社やどかりをやっている松澤です。

最近、年をとってくるとコードを書く時間よりも、設計をする時間。
設計をする時間よりもマネジメントをする時間と変わってきています。
少し年をとった分、エンジニア、人としての成長って何かを考えてみたことがあるので
今回は書いてみたいと思います。

##ドラクエみたいに成長って右肩上がりと思っていたころ
まだ何も考えられずに社会人になってエンジニアになりはじめたころは
勉強や仕事をすればするほどレベルがあがるドラクエみたいに
やった分だけ自分のレベルが上がると思って全力で走っていました。
先輩を見ても、みんな雲の上くらいに上だと感じるし、
自分がわからないことも調べなくても
いろんなことがスラスラ出てくるし、
**「すげー、かっこいいー」**と思うことが多かったですね。

そして実際にもわからないことだらけだった20歳代のころは
勉強したことが着実に力がついてレベルがあがっていたのも
毎日では気づきにくかったですが、あとで考えると力になっていた気がします。

##後輩や部下がついたら「おやって」感じ始めたころ
30歳くらいになるとやれることも多くなってきて
サブリーダーやリーダーになられる方も多いと思います。
自分よりも若い人が社内に入ってきたりして、
自分が教わることもいっぱいあるんですけど
初めての後輩がついていっぱい教えてあげたくなったり
思ったようにチームや後輩が育たなかったり
結構壁と呼ばれるものにぶつかることも多いし
また今までよりも多くの責任や期待を会社から受けたりして
一人の力でやれることを考えるよりも
チームでやれることを考える必要もでるし
外部の方々との接点も増えてくる頃です。

その結果、今までの会社で頑張り続ける人もいれば
転職されたり、フリーランスになったり、会社起こしたり
プライベートでは、はたまた結婚なんてこともあったり
人生でいろいろ考えさせられる時期です。

ここでは何が正解かということは、
自分の人生として判断して決断したことを
後々に後悔しないことだけが大事な時期です。

##でもさ、人生ってゴールは１つじゃないんだよ
ここで冒頭のドラクエを思い出してもらうとよいのですが、
実はエンジニアという一次職からスタートをすることは
多いと思うのですが、実は二次職へ転職する時期だったり
するんですよね。

ドラクエでいえば魔法使いでスタートしたけど
賢者になったり
はたまた魔法剣士になったり
場合によっては召喚士になるのかもしれません。

私達のITの仕事をしていると、ずーっとエンジニアという職で
頑張らなければいけないという錯覚に陥るのですが、
実は結構な人が二次職に転職されている事が多いです。

具体的には
- システムエンジニア
- セールスエンジニア
  - クリエイター
  - プロデューサー
  - プロジェクトマネージャ
  - テクニカルディレクター
  - フルスタックエンジニア
  - etc

ざーっと考えてみても、＋αで何を身につけるかで
ほんとに多くの二次職があると思います。

このあたりがあまりわからないままに一次職のエンジニアを
経験されていることがたまにもったいないなと思います。

私はたまたま勉強していたことなどから
結果として**「テクニカルディレクター」**になったな
とは実感していて私としても満足はしているのですが
他の道も面白そうだったなと思い返すことも多いです。

**人生の道はわかりやすい一本道ではありません。
いろいろと考えて悩んで自分が進むべき道を見つけて
切り開いていってもらいたいなと思います。**

ありがとうございましたm(__)m
画像をマスク合成するときに、短いコードで縦横比率を計算してはみ出さないようにする

合成画像がはみ出さないようにする簡単な方法を書きます。
<img width="300" alt="スクリーンショット 2021-12-15 10 07 46" src="https://user-images.githubusercontent.com/23278992/146104454-af8c7e8c-4eb9-4b9a-9ea4-31492cbf9f3a.png">
【縦横に思い切りはみ出すfrontImage】

縦横比のちがう2枚の画像をマスク合成するときに、
**場合によっては画像がはみ出してしまう。**

###はみ出してしまう原因

はみ出さないように画像をスケール変更しないといけないのだが、
合成するFrontImageとBackgroundImageがあるとき、

FrontImageの横と縦どちらが長いか。
BackgroundImageの横と縦どちらが長いか。
FrontImageの縦とBackgroundImageの縦どちらが長いか。
FrontImageの横とBackgroundImageの横どちらが長いか。

の組み合わせがあり、はみ出しがないように全てのパターンを記述するのは面倒くさい。
**僕は最初「短い方の辺で合わせればいいんだな」と思ってスケールを設定すると、横だけはみ出したりした。**

単純に2枚の画像を合成する場合は、
[CIMinimumCompositing](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIMinimumCompositing)
を使えばはみ出さないように計算してくれるが、
マスク画像の場合は計算してくれるフィルターはなく、単純に画像の座標とサイズで合成される。

###解決法

そこで、**全てのパターンをカバーし、FrontImageがBackgroundImageからはみ出さない、
かつ、なるべく大きく表示されるように合成するには以下のスケール計算をすれば良い。**

```swift
var scale:CGFloat = 1

// あらかじめ画像同士の縦横それぞれの比を計算し、スケールが小さい方に合わせる
let widthScale = backgroundCIImage.extent.width / frontCIImage.extent.width
let heightScale = backgroundCIImage.extent.height / frontCIImage.extent.height
        
if widthScale < heightScale {
    scale = backgroundCIImage.extent.width / frontCIImage.extent.extent.width
} else {
    scale = backgroundCIImage.extent.height / frontCIImage.extent.extent.height
}

let transform = CGAffineTransform(scaleX: scale, y: scale)

let scaledFrontCIImage = frontCIImage.transformed(by: transform)
// マスク画像をfrontImageに合わせる場合、同様にスケールする。
```

<img width="300" alt="スクリーンショット 2021-12-15 10 07 30" src="https://user-images.githubusercontent.com/23278992/146104449-53632f80-2cfb-4797-a10c-023e3a045c6f.png">
【ちゃんと収まったFrontImage】
🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
簡単な開発内容をお書き添えの上、お気軽にご連絡ください。
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
ジョークで学ぶ通信プロトコル

若手のエンジニアによってはいきなりクラウドから入ったために、実はどういう仕組みで通信できているのかよく分かっていなかったりすることがあるようです。クラウドやら SDK がよしなにやってくれるので意識しなくてもなんとかなっちゃう部分について、頭の中でイメージを形づくりながら楽しく学ぶ方法はないかなぁ、と思いを巡らしたところ、ジョークから学べないかと狂気じみた発想に至りまして、その可能性についてテストがてらメモっときます。

ジョークはググるとあちこちで見つかるので、気になる方は検索してみてください。

# ハンドシェイク

> In high society, TCP is more welcome than UDP. At least it knows a proper handshake.

コネクション型の TCP はデータの送受信を始める前にコネクションを確立するために 3-way ハンドシェイクをします。一方、コネクションレス型の UDP はハンドシェイクなしでデータの送信を始めます。上記のジョークはこの違いをネタにしたものです。

ではここで質問です。TCP はなぜ初めにハンドシェイクをするのでしょうか？それはコネクションの両端でシーケンス番号を同期させるためです。送信ポートと受信ポートの仲がいいからノリでやっている訳ではありません。無駄なことはしないところが通信プロトコルの洗練さであり "proper" の所以です。

# バー

> A TCP packet walks in to a bar and says “I want a beer”, barman says “you want a beer?” and TCP packet says “yes, a beer”.

TCP が ACK でパケットの到着を確認する様を皮肉ったジョークです。なかなかビールが飲めません。

これを踏まえて、バーには色々な通信プロトコルのパケットがやってきます。

> A UDP packet walks into a bar without a checksum. Nobody cares.

気にしない、気にしない。

> A DHCP packet walks into a bar and asks for a beer. Bartender says: “here, but I’ll need that back in an hour!"

これまた飲めません。まぁ、リースですからね。それにしても 1 時間とはなかなか厳しい運用です。

> A LSA Type 6 packet walks into a bar and asks the bartender for a drink. The bartender ignores him.

Standards Track の RFC であるにも関わらず、Cisco が OSPF の LSA Type 6 をサポートしていないので、世間から無視される悲しい運命にあるようです。

> A LSA Type 2 packet walks into a bar and asks for a beer. Bartender say’s “here, but don’t leave the area with it.”

OSPF の LSA Type 2 はエリア内でのみフラッディングされるので、持ち出しできません。

> IP packet with TTL=1 arrives at bar. Bartender: “Sorry, can’t let you leave…and you don’t get any beer either…”

ああ、やっぱり飲めないのね。。TTL (Time To Live) はルーター・スイッチをホップする度に 1 減ります。0 になるとパケットが消滅します。TTL の初期値を見ればどういう OS のホストか分かったり、減り具合を見て中継路がどうなっているか推測できたりと、トラブルシューティングでも使えるフィールドです。

とまあこんな具合で、各プロトコルで同型のジョークが量産できそう・されてそうです。

# 混雑

> A bunch of TCP packets go into a bar, until it’s overcrowded. The next day, half as many go in.
> A bunch of TCP packets walk into a bar. The bartender says, “Hang on just a second, I need to close the window.”

これらは TCP のウィンドウ制御に関するものです。TCP は輻輳ウィンドウとフロー制御ウィンドウのいずれか小さい方を一度に送信できるパケットの数 (送信ウィンドウ) として用います。

一文目は輻輳ウィンドウの制御をネタにしたものです。タイムアウトにより輻輳を検知すると輻輳ウィンドウをその時の輻輳ウィンドウの半分のサイズに設定します (という記述から TCP Reno のことだと分かります。TCP Tahoe だと、次の日のお客さんパケットは 1 人になっちゃいます)。なお、より厳密には半分のサイズ + 3 パケット分になるのですが、お酒の場でそういう細かいことをチクチク言うのは野暮ってもんです。

二文目はフロー制御ウィンドウをネタにしたものです。フロー制御ウィンドウは受信側のバッファの空き容量を表します。受信側のバッファの空きがなくなると、ACK で通知されるフロー制御ウィンドウのサイズが 0 になります。それを "close the window" と言ってる訳ですね。このお客さん達はドアからではなく窓から入ってくるのです。実際のバーで想像してみるとなかなかシュール。

それにしても、店の要請はもちろんのこと、自分で判断してお店通いを控えるあたりがお行儀がよくさすがハイソサイエティ。

# さいごに

通信プロトコルに関するジョークをいくつか見てきましたが、バーに客が訪れる感じとか、親近感の沸きやすい日常的な物事になぞらえて表現できることがお分かりかと思います。もちろん実際にはもの凄い速さでお店を出入りしている訳ですが。。。

ここまで読んでいただいた皆さん、RFC やテキストで仕様をもうちょっとちゃんと調べたいな〜、パケットをダンプして実際の挙動を観察してみたいな〜、という気持ちが少しでも湧いてきたでしょうか？もしそうであればこのアイデアは芽があるな、ということで。

なお、この投稿は UDP でお届けしております。
給与に悩みがある人こそ、評価制度の理解を深めよう

当社の評価制度が「どんな評価をしているのか」「評価から期待する効果」「何をすればいいのか」等を抜粋しながら、評価の想い等をお伝えして行きたいと思います。

当社以外にお勤めの方々にはこの記事を切っ掛けにご自身の会社の評価制度を理解・興味を深めて頂きたい。
当社従業員各位には、評価制度の理解を深め日々の取り組みに活かして欲しい。

そんな想いで執筆したいと思います。
#目次
[1.評価の影響/効果](#1-評価の影響/効果)
[2.会社が期待する効果](#2-会社が期待する効果)
[3.社員が期待する効果](#3-社員が期待する効果)
[4.本日の纏め](#4-本日の纏め)

#1. 評価の影響/効果
評価制度を理解して行く上で切っても切り離せないモノが「経営理念」。
皆さん、自社の経営理念はご存知ですか？

経営理念とは、創業者や経営者の信念や目標を具体化した言葉です。
この理念を実現する為に、人を集め、サービスを提供し、時には会社の環境も整備しながら経営しているのです。
評価制度というのもまさに会社が作った”環境”の１つであり、採用基準やサービス等、様々な事柄に経営理念は紐づいています。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294329/cfedcd29-b10b-fcc3-17c4-50357cc48f2d.png)

その制度を活用して行くと、どのような効果が期待できるのでしょうか。
当社の経営理念と評価制度を参考にしながら会社側/社員側双方の目線で見てみましょう。
※2021年11月時点の評価制度を参照しています。

#2. 会社が期待する効果
当社オブジェクティブグループの経営理念
**～快適かつ最適な環境の提供～**
社会や時代の変化にも対応しながら、顧客にとって快適であり最適な環境を提供出来る組織を目指しています。

この理念を実現する為に「能力」と「情意」という2つの目標を設け、それに付随した合計8つの項目で評価出来るようにしました。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294329/ba5ff86d-c92f-ed89-7f4a-0ebe6aacf9fd.png)
評価項目の意図
**仮説/改善/自動化**・・・クライアントのニーズに仮設を立て、その考えを元に改善をして行きます。さらにIT技術を用いて自動化する事で、快適さと最適さを兼ねたサービスを提供出来る人材を目指して行けます。

**キャッチアップ/ボトムアップ**・・・常に新しい情報を取り入れる事で、その時代に合った価値を見出せるようになります。また、組織や個人の能力を底上げする事により、品質を向上させる事も出来ます。

**OKR/インプット/報告**・・・目標設定やその達成、学びや報告等、当社の社員として持ち合わせて欲しい考え方や姿勢を取り入れています。

各項目を理解し成果/評価を上げてくれる社員が増える程、会社としての能力も上がり、当社の理念である快適さや最適さを提供出来る組織に近づく事が出来ると考えています。
これが会社から見た時の評価制度の効果・期待値でもあります。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294329/610810ce-62c3-f2b3-2ba2-4424bd09c047.png)

#3. 社員が期待する効果
社員にとって、評価の結果として得たいものの１つは給与では無いでしょうか。
経営理念をもとに作られた当社の評価制度。
これがどのように給与に影響して行くのか見てみましょう。

当社では、能力・情意目標の点数により、グレード(ランクのようなもの)を4段階(S1/S2/L1/L2)設けています。
S・・・スタッフクラス
L・・・リーダークラス
入社当初はS1からスタートし、グレードが上がる毎に手当が付与されたり、グレードによって基本給や手当の付与割合が上がったりします。

また、評価点だけでなく組織や個々が配属されているチームの業績目標に対する達成度次第で変動する手当もあります。

評価点数や業績の達成度を参照し給与を算出しているので、**個人の評価を上げていく事**と**組織やチームの業績に貢献する事**が当社で給与を上げるにはポイントになって来ます。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2294329/d53f5ee7-d556-d33e-62aa-852d1fd12e77.png)
評価内容や業績への貢献等、給与を上げる為の要素を理解する事で、何をどうすれば給与がどれくらい付与されるのか”見える化”出来るようにしています。

#4. 本日の纏め
本日は評価制度目的や会社や従業員に与える影響の一部をお伝えしました。
それぞれの会社に評価制度の目的や想い等があり、それに沿った取り組みをしてくれた社員を評価したいという考えで制度が作られていると思います。

評価制度の意図や効果などにも理解を深めて頂く事で、自分は何から取り組めば**求める効果を得られる**のか”考える”切っ掛けになれば幸いです。

今後も当社の評価制度についてお伝えしながら、「評価とは」「オブジェクティブという組織とは」どういったものなのか知って頂きたいと思います。
[py2rb] setattr

# はじめに
移植やってます
# setattr (Python)
```python
for attr in ['delimiter', 'label', 'block_size', 'label_group']:
    if attr in kwargs:
        setattr(self, attr, kwargs.pop(attr))
```
```python
        self.attr = kwargs.pop(attr)
```
`self`の属性を設定。
# eval (Ruby)
```ruby
['delimiter', 'label', 'block_size', 'label_group'].each do |attr|
  if kwargs.include?(attr)
    eval("@#{attr} = #{kwargs.delete(attr)}")
  end
end
```
無理矢理感が凄いんですけど。
# メモ
+ Python の setattr を学習した
+ 道のりは遠そう
1年間、1on1のメンターをやってみて学んだこと


こんにちは、GxPの雨宮です。
この記事は [グロースエクスパートナーズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/gxp) の15日目です。

本日は自分自身が昨年から行っている1on1と1on1勉強会について書きます。

# はじめに
1on1とは上司(メンター）と部下（メンティー）で行う定期的な1対1のミーティングです。評価や管理のための人事面談とは異なり、部下の成長のサポートするための時間が1on1です。1on1を通じて上司は部下がどういうキャリアを考えているのか、どういう悩みを持っているかということを把握し、部下のサポートを行います。時間は15~30分の短時間で繰り返し行い、頻度は毎日、毎週、毎月といった短い期間が一般的です。
3年目となり、今まではメンティー側だった自分が先輩となり、後輩の悩み事を少しでも解決できるように1on1を始めました。
また、コロナという状況下で行ったため、リモートでやることが多かったです。

# 1on1をやってみて
1on1を1年間やってみて、感じたことは
#### やるといいこと

* 事前準備をしてから臨むこと
* 話している内容をまとめている議事録を共有すること
* アイスブレイクを入れること

#### 上手くできなかったこと

* メンティーが話してくれたことから、深堀して話を進めること
* 話しやすい雰囲気を作ること
* 相手から話してもらうこと

1on1を行う前に事前準備として前回話したことや日報、月報を確認することで、話す内容が明確となり、スムーズに進められたからです。また、議事録を共有することで、相手が今どんな状況かをお互いに把握でき、私自身も焦る気持ちがなくなり、落ち着いて会話を進められたからです。アイスブレイクで休日の過ごし方や、趣味の話をしたことで、和やかな雰囲気のまま会話を進めることができたからです。

反対に1on1を日々行ったとしても、話してくれたことから深堀して話を進めることは難しかったです。話がないために、沈黙が続いてしまうことも多々ありました。また、相手から話してもらうような雰囲気づくりもなかなか上手くできませんでした。

1on1をやっただけで終わらずに良かったこと、悪かったことをKPTでまとめ、視覚化することでどう改善していけばよいかをわかりやすくし、次につなげられるようにしました。そうすることで、以前できなかったことができていることが分かりやすくなりました。

1on1を行ったときのKPTの内容
![KPT2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334239/d8750d12-37cb-e9fb-185a-9ce8baf8b823.png)




# 1on1勉強会
1on1勉強会とはメンターであるメンバーで集まって、1on1での悩み事、困っていることの相談を行う勉強会になります。
勉強会では主に、

* 1on1での悩み事、困っていることの相談
* 1on1の書籍の読み合わせ
* 1on1ラジオの聴取

を行いました。

相談事では話が尽きたときにはどうしたらいいかや、どのように話を進めたら話しやすいかなどの話し合いをしました。

書籍の読み合わせでは1on1とはどういうものなのかという基本的なところから学んでいきました。
1on1というものはメンティーに話してもらう場であり、メンターは聞き手に回る必要があると学び、アドバイスや沈黙になった場合はどこから話をすればよいか悩んだことがあったことを思い出します。

1on1ラジオの聴取では下記のラジオを使って、1on1について学びました。
　[1on1ラジオページ](https://anchor.fm/1on1radio)
テーマには「話ネタに困ったときにどうする」や「考えるって難しいよね~考えられない4つのパターン~」といったものがありました。
その中でも1番印象に残っているものは「自分の「普通」は相手は違うかも」というテーマのものです。「普通、あるべきというのはその人の価値観なのかもしれない、普通じゃないと輪にうまく入れなくなると思ってしまう」といった言葉がでてきました。
普段「普通」という言葉は「普通にできるよね」という風に日常会話で自然と出てしまっているもので、特に気にせず使っていた自分がいました。でも、このラジオを聞いて、「普通」とは人それぞれ違うものだと改めに知り、使わないように気を付けるようになりました。

#おわりに
今までの1on1ではメンティー側だった自分がメンター側となり行ったことで、相手から話をしてもらうことの難しさを知りました。
どういう質問をすることで話を続けられるか、また、相手の悩みをどれだけ解決できているのかなど、すごく悩むことはありました。ですが、1on1勉強会でできないところの悩みを相談したことで、1年間やりきることができました。現在はメンティーだった方がメンターとなり、その相談や引き続き悩みをサポートするという以前との1on1での内容とは少し変わったため、行う回数も減りましたが、1on1勉強会で得たことを参考にして、これからも続けていきたいです。
RailsアプリのサーバOS変更時、Bcryptが古いとBCrypt::Errors::InvalidHash: invalid hashがでることがある

# まとめ
Railsアプリで認証などに bcrypt （https://rubygems.org/gems/bcrypt ）を使っている場合、バージョンが3.1.10以下だとUbuntu20.04では動作しないのでアップデートが必要。

こんなエラーが出る。

```
BCrypt::Errors::InvalidHash (invalid hash):
```

現時点では下記で対応すると解消する。

```
gem 'bcrypt', '3.1.16'
```

## 経緯
Herokuにて、StackをHeroku-18（Ubuntu 18.04ベース）からHeroku-20（Ubuntu 20.04ベース）にアップデートする際に発生しましたが、エラーメッセージでググっても（自分のググり方が悪く）直接の原因をすぐ探せなかったので記事にしてみました。

開発時のOSを本番と合わせておくことで早期発見対応できるはず。

参考）
https://github.com/bcrypt-ruby/bcrypt-ruby/issues/225 
https://github.com/bcrypt-ruby/bcrypt-ruby/issues/226
AWS上のシステムを維持管理して得たハマりポイントその2

#はじめに

前回の記事の続きでAWSでハマったポイントについて書きます。

https://qiita.com/daitak/items/3feab6e063969bd855d7


#ELBのCookieはリクエスト毎に変わる！

* ELB(ALB)のセッションパーシステンス用のCookie(AWSALB, AWSALBCORS)はリクエスト毎に新しいものが払出される。

* 完全に直近のCookieを送信しなくてもパーシステンスされるが、設定された有効期限が切れたCookieを送信するとパーシステンスが解除されてしまう(他のサーバ号機に振り分けられてしまう)。

* Cookieの有効期限はStickiness durationの値を変更することで1 秒から 7 日の間で指定可能。 

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/sticky-sessions.html

* 通常のブラウザであれば自動で新しいものに上書かれるが、スマホアプリ等でCookieを作り込みで管理している場合は注意が必要。


#サービス稼働直後からメールが送れない！

* サービス稼働直後から、特定ドメインに対してメールが送信できない事象が発生。

* EC2で構築したメール送信サーバ用のNAT GatewayのEIP(グローバルIP)がメール受信ブラックリストに登録されていたのが原因。

* このIPは以前AWS上の別システムに付与されていた際にブラックリスト登録された模様。

* 急ぎブラックリストの解除をブラックリスト管理に依頼しほどなく解決。

* メールサーバをAWSで構築する場合には、以下を実施した方が良いと実感。
  1. 主要ドメイン宛てに一通りメール送信テストを実施。
  1. サービスイン前にEIPがブラックリストに登録されていないか主要ブラックリスト管理サイト(Smaphaus 等)で確認。

https://check.spamhaus.org/

![eip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1905292/21e5a33c-7335-8cd5-fe0a-8c369af5d707.png)
[py2rb] 可変長引数

# はじめに
移植やってます。
# * ** (Python)
```python
class A:
    def init(*args, **kwargs):
        print(args)
        print(kwargs)

a = A
a.init('dog', 'pet', name='poti', age=10, sex='male')

# ('dog', 'pet')
# {'name': 'poti', 'age': 10, 'sex': 'male'}
```
argsはタプル、* -> ** の順にする。
# * ** (Ruby)
```ruby
class A
  def init(*args, **kwargs)
    p [args, kwargs]
  end
end

a = A.new
a.init('dog', 'pet', name: 'poti', age: 10, sex: 'male')

# [["dog", "pet"], {:name=>"poti", :age=>10, :sex=>"male"}]
```
Rubyでは、argsはタプルではなく配列になります。
# メモ
+ Python の * ** を学習した
+ 道のりは遠そう
Bitriseのslack通知をyamlで設定する


## WebHookの設定
Bitriseからslackに投稿できるようにWebHookを設定します。

まずは、slackを開いて、incoming WebHookを設定し、WebHook URLを取得します。
こちらのURLからできます。[https://slack.com/services/new/incoming-webhook](https://slack.com/services/new/incoming-webhook)

次に、WebHook URLを環境変数に設定します。
BitriseのWorkflowEditorを開き、`secrets` タブを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6149/4496a0e9-6219-56f1-8179-7320c1d71669.png)

`Add new` ボタンを押して先程取得したWebHook URLを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6149/7ba5c389-1637-a6b1-c899-4e3633238310.png)

## bitrise.yamlの設定

テスト実行のあとに以下を追加するだけです。

これにより、テストが成功しても失敗してもslackに通知が飛びます。

```yaml
    - slack@3:
        title: Slack Notification
        is_always_run: true
        inputs:
        - webhook_url: $SLACK_WEBHOOK_URL
```

通知が多すぎてうっとおしい場合は、`run_if: .IsBuildFailed` をつけると失敗した場合にだけ通知が飛ぶようにすることができます。(Documents: [IsBuildFailed](https://devcenter.bitrise.io/en/steps-and-workflows/enabling-or-disabling-a-step-conditionally.html#running-a-step-only-if-the-build-failed), [is_always_run](https://devcenter.bitrise.io/en/steps-and-workflows/developing-your-own-bitrise-step/developing-a-new-step.html#setting-conditions-for-running-the-step))

```yaml
    - slack@3:
        title: Slack Notification
        is_always_run: true
        run_if: .IsBuildFailed
        inputs:
        - webhook_url: $SLACK_WEBHOOK_URL
```
MyBatis利用時に発生した例外から抜け出した話

<h1>はじめに</h1>
O/Rマッパーの一つであるMyBatisを使いQiitaのような質問投稿アプリを作成しています。
そこで悩んだ例外処理の発生原因について、忘備録兼同じことで悩んでいる方の手助けができればと思い投稿しました。
認識が異なる点があればご指摘いただけると嬉しいです。。。

<h1>org.apache.ibatis.binding.BindingException</h1>
<h4>①リポジトリクラスにアノテーションが抜けていた</h4>
```
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.example.demo.repository.UserMapper.insert
    at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.7.jar:3.5.7]
```

こちらの例外は、ユーザー情報を入力し、登録ボタンを押して次の画面に遷移する際に発生しました。
発生原因としては、Javaで作成しているRepositoryクラスに@Insertのアノテーションが抜けていたことでした。
ちなみに全件検索やID検索をする際は@Select、更新では@Updateなどやりたい処理ごとにアノテーションをつける必要があります。


```java
/** ユーザー情報を登録する */
@Insert("insert into users(name, email, password, zipcode, address, telephone) \n"
			+ "        values(#{name},#{email},#{password},#{zipcode},#{address},#{telephone});")
public void insert(User user);

   
```

<h4>②パラメータの指定ができていなかった</h4>

```
org.apache.ibatis.binding.BindingException: Parameter 'email' not found. Available parameters are [arg1, arg0, param1, param2]
	at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212) ~[mybatis-3.5.7.jar:3.5.7]
```
「メールアドレス」と「パスワード」が一致している場合のみログインする処理を実装したとき、上記例外が発生しました。
こちらの例外発生は、@Param指定ができていないことが原因でした。
そのため、下記のようにパラメータを指定することで解決しました。

```java
/** メールアドレスとパスワードが一致したレコードを取得する */
@Select("select * from users where email = #{email} and password = #{password};")
	public User findByEmailAndPassword(@Param("email") String email, @Param("password") String password);
```

<h1></h1>
以上が今回発生した例外処理と解決方法でした。
ご参考になれば幸いです。

<h1>参考資料</h1>
<h4>①リポジトリクラスにアノテーションが抜けていた</h4>
https://teratail.com/questions/169846

https://qiita.com/d-yosh/items/a2bec9718bccfe15a6ae

<h4>②パラメータの指定ができていなかった</h4>
https://www.codetd.com/ja/article/10796444

https://mybatis.org/mybatis-3/ja/java-api.html
実用的なストアIDの取得方法

#前提
アップデート等をさせるため、アプリのストアに遷移させる時は多々あると思います。
ただ、アプリのパッケージ名でGoogle Playのリンクを作ってしまうと、flavorによってGoogle Playに飛なくてQAで困ります。
だからと言って本番のパッケージ名を`strings.xml`に記述するのもおかしな話ですよね？
そこで利用するのがストアIDです


#どこに置くのが最適か
######ではどこに保管しておき、どのように取得するのが最適かです
早速ですが答えは下記の通りになります

```kotlin:build.gradle
defaultConfig {applicationId = "jp.co.sample.app"}
buildTypes {
        getByName("debug") {
            buildConfigField("String", "STORE_ID", "\"${defaultConfig.applicationId}\"")
        }
        getByName("release") {
            buildConfigField("String", "STORE_ID", "\"${defaultConfig.applicationId}\"")
        }
    }
```
このように`dafultConfig`に`applicationId`が置かれていると思うのでそちらを`buildConfigField`で参照することによりコード内で必要な時に

```kotlin
BuildConfig.STORE_ID
```

上記の通り取得することができます
こうすることにより`strings.xml`にわざわざ本番のパッケージ名をおく必要も無く、flavorによるパッケージ名の変化も気にする必要がありません。

#最後に
ついでではありますがストアIDに関して調べている方がこの記事にたどり着きやすいとは思いますので
ストアIDを使用したGooglePlayへの遷移用Uriを置いておきます

```kotlin
https://play.google.com/store/apps/details?id=${BuildConfig.STORE_ID}
```
ラズパイでチャイム検知してみた Part2

# はじめに

https://qiita.com/seaka829/items/703ab918be2813f9ea06

上記記事の続きになります。
前回はPyAudioを使ってチャイム音を取得し、取得した音声データをFFTして特徴を出しました。
今回はFFT後の値が閾値を超えたときに、LINEに通知を送る実装を行ったので記事を書きます。


# LINEへの通知方法

[LINE Notify](https://notify-bot.line.me/ja/)を使用します。
使い方は簡単で、まず通知先を設定して、アクセストークンを発行します。
アクセストークンとメッセージ内容を付与して、[URL](https://notify-api.line.me/api/notify)にリクエストすると設定した通知先にメッセージが送信されます。


# 実装

前回のプログラムを元に処理を追加しました。

``` .py
import numpy as np
import requests
import pyaudio
import matplotlib.pyplot as plt
from scipy.fftpack import fft

# 設定値
FORMAT      = pyaudio.paInt16
CHANNELS    = 1                 # マイクのチャンネル数
RATE        = 48000             # マイクのサンプリングレート
CHUNK       = 1024
IDINDEX     = 23                # マイクのindex
DATA_LENGTH = 1000              # 格納するデータ数


# メイン処理
def main():
    # 変数
    y = []

    # マイクの設定
    audio = pyaudio.PyAudio()
    stream = audio.open(
         format = FORMAT
        ,channels = CHANNELS
        ,rate = RATE
        ,frames_per_buffer=CHUNK
        ,input=True
        ,output=False
    )

    while stream.is_active():
        try:
            # 音声データの取得
            input = stream.read(CHUNK, exception_on_overflow=False)
            ndarray = np.frombuffer(input, dtype='int16')
            for i in ndarray:
                data = i.item()                     # 音声データの取得
                append_arr(y, data, DATA_LENGTH)    # 音声データを配列に格納

            # FFT
            freq = np.linspace(0, RATE, DATA_LENGTH)
            yf = np.abs(fft(y))
            yf = yf * yf
            
            # 判定（1000Hzの値が閾値を超えた場合通知する）
            if len(yf) == DATA_LENGTH:
                if yf[22] > 100000000000:
                    send_line_notify('チャイムがなったぞ！')

        except KeyboardInterrupt:
            break

    # plt.plot(freq[0:int(DATA_LENGTH/2)], yf[0:int(DATA_LENGTH/2)])
    # plt.show()

    stream.stop_stream()
    stream.close()
    stream.terminate()


# 配列へのデータ追加（配列数がlengthを超えた場合古いデータを削除）
def append_arr(arr, data, length):
    arr.append(data)
    while len(arr)>length:
        arr.pop(0)


# ラインに通知
def send_line_notify(notification_message):
    line_notify_token = '{LINE Notifyのアクセストークン}'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f'message: {notification_message}'}
    requests.post(line_notify_api, headers = headers, data = data)


if __name__ == "__main__":
    main()
```

上記プログラムは、1000Hz音声を取得したときLINEに通知を送る仕組みになっています。
閾値を修正することで他の特徴を持つ音声も検知することができます。
※連続でLINE通知されるなど修正すべきところがいくつかありますので、ご注意ください

↓音声検知後のライン通知
![B8580B06-E333-48D5-B0AA-256A19BE973D.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108396/7ad7b955-3c7d-e75f-33c4-873cc6aae8ff.png)


# さいごに
[LINE Notify](https://notify-bot.line.me/ja/)が予想以上に使いやすかったです。
通知部分のみであれば10分くらいで実装できます。
システム監視等の通知にも使えるかもですね！
FlutterでprimarySwatchをcustomする方法

この記事は、【 [可茂IT塾 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kamo-it) 】の15日目の記事です。

Flutterでアプリを作り始めるタイミングで、アプリのテーマカラーの設定がありますよね。
カラー設定の中でも、最も重要な`primarySwatch`にcustomしたcolorを設定する方法をご紹介します。

## カラー設定なんて簡単でしょ？
色のカスタマイズくらい余裕でできるよ。。って思っている方も多いかもしれません。
しかし、`primarySwatch`の型は`MaterialColor`なんです。

デフォルトで設定されている`Colors.blue`の中身は以下のような感じです。

```dart:colors.dart
  static const MaterialColor blue = MaterialColor(
    _bluePrimaryValue,
    <int, Color>{
       50: Color(0xFFE3F2FD),
      100: Color(0xFFBBDEFB),
      200: Color(0xFF90CAF9),
      300: Color(0xFF64B5F6),
      400: Color(0xFF42A5F5),
      500: Color(_bluePrimaryValue),
      600: Color(0xFF1E88E5),
      700: Color(0xFF1976D2),
      800: Color(0xFF1565C0),
      900: Color(0xFF0D47A1),
    },
  );
```
このように50~900のカラーバリエーションがありますね。
`MaterialColor`に数値を設定することで`Color`になるのです。
別物なんです..
`Colors.blue`や`Colors.green`あたりしか見当たらず。
=> 自分でカスタマイズしたカラーを設定したい！となったわけです。

## ColorをMaterialColorに変換するコード

```dart:material_color.dart
import 'package:flutter/material.dart';

MaterialColor createMaterialColor(Color color) {
  //渡されたカラーを分解
  final r = color.red;
  final g = color.green;
  final b = color.blue;
  
  //カラーの濃さのベースをなるリストを作成
  final strengths = <double>[.05];
  final swatch = <int, Color>{};
  for (var i = 1; i < 10; i++) {
    strengths.add(0.1 * i);
  }
  //50~900のカラーパレット(Map)を作成
  for (final strength in strengths) {
    final ds = 0.5 - strength;
    swatch[(strength * 1000).round()] = Color.fromRGBO(
      r + ((ds < 0 ? r : (255 - r)) * ds).round(),
      g + ((ds < 0 ? g : (255 - g)) * ds).round(),
      b + ((ds < 0 ? b : (255 - b)) * ds).round(),
      1,
    );
  }
  return MaterialColor(color.value, swatch);
}
```

この関数を使えば、MaterialColorも自分の思い通りになります。

## 最後に
いかがでしたか。
Flutterのカラーテーマの中でも、最も重要と言ってもよい`primarySwatch`をcustomする方法をご紹介しました。
参考になれば幸いです。

また、primarySwatchとはなんぞや？というところから学びたいかたは、
以下の記事が大変勉強になります。

https://zenn.dev/sugitlab/articles/bef3a05963680a


参考

https://medium.com/@filipvk/creating-a-custom-color-swatch-in-flutter-554bcdcb27f3
エンジニアの調査力は大事ってことよ

自分用の備忘録。

コーディングしているときや他人のソースコードを解析しているときに、知らない構文を調査しようとするとき、各自の調査スキルによって調査時間に雲泥の差がでるので、参考情報を転載します。自分もよく調べるけど解決できないときがあるから戒めよう。

https://qiita.com/dodonki1223/items/955819806297ee554b31?utm_source=Qiita%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9&utm_campaign=9e72988ca7-Qiita_newsletter_492_12_15_2021&utm_medium=email&utm_term=0_e44feaa081-9e72988ca7-43447346

英語は翻訳ツールがあるから覚えなくていいとか思ってるときがあるけど、さっと英語を読めたほうが効率はいいね。単語覚えなきゃ・・・
AWS SDK for Javaのバージョンごとのクライアントの設定

[ZOZO Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) の16日目の記事です。

# AWS SDK for Java
AWS SDK for JavaにはAWSのサービスを利用するためのJava APIが用意されています。

その中で接続タイムアウトやリクエスト再試行などのクライアントの設定を変更することができます。
AWS SDK for Javaには、バージョン1(v1)とバージョン2(v2)があり、アップデートする際に使用するそれぞれのバージョンの主なクラスとメソッドの対応をまとめました。


# v1、v2オプション対応表
以下のようにメソッドチェーンを使用して設定することを想定しています。

```
new ClientConfiguration()
    .withConnectionTimeout(connectionTimeout)
    .withClientExecutionTimeout(clientExecutionTimeout)
    .withRequestTimeout(requestTimeout)
    .withSocketTimeout(socketTimeout)
    .withMaxConnections(maxConnections)
    .withMaxErrorRetry(maxErrorRetries);
```


| 設定内容| v1 クラス | v1 メソッド | - |v2 クラス | v2 メソッド|
|:---|:---:|:---:|:---:|:---:|:---:
|接続タイムアウトまでの時間| ClientConfiguration | withConnectionTimeout | → | ApacheHttpClient | connectionTimeout |
|クライアントがAPI呼び出しの実行を完了するのにかかる時間| ClientConfiguration | withClientExecutionTimeout | → | ClientOverrideConfiguration | apiCallTimeout |
|リクエストをタイムアウトするまでの時間| ClientConfiguration | withRequestTimeout | → | ClientOverrideConfiguration | apiCallAttemptTimeout |
|ソケット通信をタイムアウトするまでの時間| ClientConfiguration | withSocketTimeout | → | ApacheHttpClient | socketTimeout |
|HTTP接続の最大数| ClientConfiguration | withMaxConnections | → | ApacheHttpClient | maxConnections |
|最大リトライ数| ClientConfiguration | withMaxErrorRetry | → | ClientOverrideConfiguration | retryPolicy |

## 注意点
v1からv2にアップデートするにあたり、以下の注意点があります。
- v1の引数は、プリミティブ型であるのに対し、v2の引数は参照型に変更されています。
- v1ではClientConfigurationクラスにほとんどの設定できましたが、v2ではサービスクライアントの中で以下のように設定する必要があります。

以下はDynamoDBClientを使用した場合の例です。

```
 DynamoDbClient.builder()
  .overrideConfiguration(ClientOverrideConfiguration.builder()
    .apiCallTimeout(Duration.ofMillis(clientExecutionTimeout))
    .apiCallAttemptTimeout(Duration.ofMillis(requestTimeout))
    .retryPolicy(
          RetryPolicy.builder().numRetries(maxErrorRetries).build())
    .build())
  .httpClient(ApacheHttpClient.builder()
    .connectionTimeout(Duration.ofMillis(connectionTimeout))
    .socketTimeout(Duration.ofMillis(socketTimeout))
    .maxConnections(maxConnections)
    .build())
  .build();
```

# まとめ
AWS SDKのv1とv2のそれぞれでクライアントの設定は公式ドキュメントでもまとめられていますが、バージョンアップ時のそれぞれの対応表がなく困ったので、まとめました。AWS SDK v2へのバージョンアップへのきっかけになれば幸いです。
[Rails]日本の時刻に合わせる タイムゾーン

#設定する場所

config/application.rb

```
config.active_record.default_timezone = :local
config.i18n.default_locale = :ja
```
この2行を付け足すだけです。

今作っているアプリで最後の投稿からの日付を出したくて導入しました。
カラムの型はdatetimeです。
AtCoder002をやった(Java)

AtCoder002をやった。
初めてC問題解けた。

##[A](https://atcoder.jp/contests/abc002/tasks/abc002_1)
大小の比較です。正直者を出力してあげてください()

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();    
        
        list.add(scan.nextLine());
        if(Integer.parseInt(list.get(0).split(" ")[0]) < Integer.parseInt(list.get(0).split(" ")[1])){
            System.out.println(Integer.parseInt(list.get(0).split(" ")[1]));    
        } else {
            System.out.println(Integer.parseInt(list.get(0).split(" ")[0]));    
        }
    }
}
```

##[B](https://atcoder.jp/contests/abc002/tasks/abc002_2)
文字列の長さは30文字程度と書いてあるので、ループさせてあげれば問題なく通ります。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);    
        String str = scan.nextLine();
        
        int i = 0;
        while(i < 30){
            if(str.contains("a")){
                str = str.replace("a", "");
            } else if(str.contains("i")){
                str = str.replace("i", "");
            } else if(str.contains("u")){
                str = str.replace("u", "");
            } else if(str.contains("e")){
                str = str.replace("e", "");
            } else if(str.contains("o")){
                str = str.replace("o", "");
            }
            i++;
        }

        System.out.println(str);
    }
}
```

##[C](https://atcoder.jp/contests/abc002/tasks/abc002_3)
たしか高校数学で公式習った気がします。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);    
        String str = scan.nextLine();
        
        int[] triangle = new int[6];
        for(int i = 0; i < triangle.length; i++){
            triangle[i] = Integer.parseInt(str.split(" ")[i]);
        }
        System.out.println(Math.abs((double) (((triangle[0] - triangle[4]) * (triangle[3] - triangle[5])) - ((triangle[2] - triangle[4]) * (triangle[1] - triangle[5]))) / 2));
    }
}
```

D問題解けそう。。。
enebular Node-REDのbert-tokenizerノードを使ってみた

# まずBERTとは？

- Googleが発表した自然言語処理モデルで、2019年からは検索エンジンにも使用されています。
- 文脈理解の精度が評価されています。
- 様々な自然言語処理タスクにファインチューニングする前の、ベースモデルとしても使用できます。

# Tokenizerとは？

- 日本語の解析をする場合には単語、文字など何らかの部分に分ける必要があって、分割された文字列のことをトークンといいます。
- Tokenizerは文書を単語分割をして、それにIDという数値に変換するモジュールです。
- 分割方法はN-gramやMeCabなど様々

例えば、「今日の予定は池袋にご飯を食べに行きます」という文章をTokenizerしてみるとこちらのようになるイメージです。

![スクリーンショット 2021-12-15 7.41.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/6910edf7-3b83-efd8-4b56-36dbdc1ed6cb.png)

分かち書きされた文章の単語それぞれが数値に変換されていますね。これをトークンというそうです。

# bert-tokenizerノードを使ってみる

Node-REDで使用できる[node-red-contrib-bert-tokenizer](https://flows.nodered.org/node/node-red-contrib-bert-tokenizer)というノードを使用して、さまざまな文章からどのようなトークンが得られるのか見てみます。
こちらのようにノードを組んでみます。(enebularを使用してます。)

![スクリーンショット 2021-11-25 8.31.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/28146878-308e-0628-2c82-adb96a76dfd9.png)

injectノードで何か文章を入力して、debugノードで中身を見てみるとこんな感じになります。

![スクリーンショット 2021-11-25 8.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/588401df-0251-fc06-561d-768bcebeff49.png)

128個の配列の中にトークンとなる数字が格納される、という仕様のようです。

tokenizerされた結果を見てみます。

```
吾輩は猫である。名前はまだない。どこで生れたか頓（とん）と見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。
[101,100,1636,100,1636,100,1006,1666,30217,1007,100,1636,100,1636,100,1636,102,0,0,...]
```

トークンを見てみると、100や1636という数字がたくさん出てきているので違和感を覚えます。トークンの元は単語なので、同じ単語じゃないと同じトークンにならないはず。

bert-tokenizerが使っているデフォルトの辞書があるかどうか調べてみました。

https://github.com/tedhtchang/bert-tokenizer/blob/master/assets/vocab.json

こちらのようです。見た感じほぼ英単語ですね。
日本語の文章だと辞書が不十分のため同じようなトークンに収束してしまうようです。

英語の文章をtokenizerしてみました。

```
I am a cat. I don't have a name yet. I have no idea where I was born. All I remember is that I was crying in a dark and dank place. This was the first time I saw a human being.
[101,1045,2572,1037,4937,1012,1045,2123,1005,1056,2031,1037,2171,2664,1012,1045,2031,2053,2801,2073,1045,2001,2141,1012,2035,1045,3342,2003,...]
```

トークン値バラけましたね。
ちなみにbert-tokenizerノードにて辞書のURLを設定できるみたいでして、自分で作成した辞書を使ってbert-tokenizerノードを試すことができそうです。

![スクリーンショット 2021-11-25 8.48.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329420/55c5e4a1-ad0e-115b-7c17-71fae52290f3.png)

# 使ってみた感想
取得できたトークン値を使って類似度計算など行ってみましたがうまくいきませんでした。(辞書データが同類の単語でマッピングされている訳ではないので当然ですね。)
分かち書きの値なのでBERT関係ないじゃん！と最初は直感的に感じたものの、挙動を見てみると辞書にない単語も何かしらのトークンになっているようなので、その辺りの類似単語判定的なところにBERTが使われているのだろうか？などと考察しました。

Tokenizerはそれ自体を自然言語処理に使うものというより、処理のベースやつなぎになるものかなというイメージです。どのように自然言語処理につなげられるのかもう少し調べてみたいなと思いました。
【FileMaker】Rakuten Rapid API経由でCOVID-19情報を取得する

今回は、いつもの商業ベースの情報ではなく、[Rakuten Rapid API](https://api.rakuten.co.jp/)から利用できるCOVID-19情報の取得についてのサンプルです。
世界中でまだまだ勢いの衰えないCOVID-19、世界中の「今」の状況を得るのにも、APIがたくさん紹介されています。

:::note warn
これらの情報は有料無料のものとたくさん公開されています。
これらの情報だけでなく、他のメディア等でも情報を取得し、多方向から正しい情報を得るようにしてください。
:::

https://api.rakuten.net/collection/coronavirus-covid-19

上記リンク先は直接のCOVID-19情報を得るAPIのページですが、この時点で24のAPIが公開されています。

では、早速実装してみましょう。

# 実装環境
## FileMaker
curlとJSONを扱いますので、FileMaker ver.16以上で実装可能です。
それ以前のバージョンの場合は、何かしらのプラグインを活用して実装してみてください。
プラグインを利用した場合は、必ずしも今回の記事通りの実装では稼働しないかもしれない、ということをあらかじめご了承ください。

## Rakuten Rapid API
アカウントを取得し、今回テストするAPIの利用を有効にしてください。
今回は、こちらのAPIです。
その名もズバリ、「COVID-19 data」APIです。
料金プランでBasicを選択すると、無料でテスト可能です。

https://api.rakuten.net/Gramzivi/api/covid-19-data


# テーブル設計
JSONでデータを得るだけであれば、特にフィールドを追加することはありませんが、情報の確認ということで表示するフィールドを追加します。
人の目で確認するときにわかりやすいように、計算フィールドで[JSONFormatElements](https://help.claris.com/ja/pro-help/content/jsonformatelements.html)を使った計算をしておきます。
![スクリーンショット 2021-12-15 7.17.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/40fe2eee-b8f5-ba7c-d003-976979dac53a.png)

# レイアウト設計
こちらも、今回は表示するだけなので、JSONFormatElements計算をした結果を表示するフィールドをペッと置いておきます。
![スクリーンショット 2021-12-15 7.18.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/423719fc-5eea-8a48-7600-9d62352a9b79.png)

# スクリプト実装

## curl構文
curlの構文を見ていきましょう。
Rakuten Rapid APIのエンドポイントページのサンプルからcurl構文を確認します。
コードスニペットでShell > cURLの順に見ていくと、サンプルを表示できます。

```
curl --request GET \
	--url 'https://covid-19-data.p.rapidapi.com/country/code?code=jp' \
	--header 'x-rapidapi-host: covid-19-data.p.rapidapi.com' \
	--header 'x-rapidapi-key: <Rakuten Rapid API>'
```

COVID-19の状況を知りたい国のコードをURLのパラメータに指定するだけ、というシンプルな構文です。
国コードは、以下のページで確認できます。

https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes

## スクリプト実装
[URL から挿入](https://help.claris.com/ja/pro-help/content/insert-from-url.html)を使い、curl構文を実装していきます。
![スクリーンショット 2021-12-15 7.29.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/37ac27c8-1f3f-61f4-94d9-669ed0acd808.png)

このスクリプトステップに、curl構文を分解して入れていきます。
シングルクォーテーションは、バックスラッシュ付きのダブルクォーテーションにして書き換えることを忘れずに。
![スクリーンショット 2021-12-15 8.02.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/87a7d7fd-9b5c-3f9d-6e09-ce48e1964bf9.png)

2行目は、APIを実行した結果をフィールドに保存しています。
適宜、エラーコードを取得するなどもいいと思います。

# 実行してみる
では、実行してみましょう。
サクッときましたね！
![スクリーンショット 2021-12-15 8.05.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/7b0fe961-c3c6-30d9-baa4-5dbd058c551e.png)
JSONで返ってくるので、そのままFileMakerで処理できますね。
位置情報も取得できるので、地図にマッピングしたり、国別の感染者数等のグラフを作ったりということができますね。

まずは、COVID-19の情報を取得する、というAPIを紹介しました。
GitHubでpushできない原因

最近、久しぶりにGitHubで開発を始めたんだけど、何故かpushできない・・。
認証情報も合ってるはず！
結論から言うと、今回の原因は以下の2点でした。
・GitHubのデフォルトブランチがmaster → mainに変わった
・パスワード認証が廃止された

割と時間を取られたので、メモることにしました。

## よくある原因
ネット上で検索するとよく出てくるのが、以下の原因。
・コミット忘れ
・競合
・ブランチ名間違い

今回は上記の原因では無かったが、エラーメッセージが被っていたので解決するのに時間がかかった。

## GitHubのデフォルトブランチがmaster → mainに変わった
こちらは以下のエラーが出ます。(他の原因と被る)
タイトルの通り、master → mainに変えれば、プッシュできます！

~~~bash
% git push origin master
error: src refspec master does not match any
error: failed to push some refs to 'https://github.com/リポジトリ名/プロジェクト名.git'
~~~

# パスワード認証が廃止された
こちらは見慣れないエラーが出たので、ググって直ぐに解決できました。
2021年8月13日からアクセストークンで認証するように変わったみたいです。
アクセストークンの作り方は、[GitHub公式](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)を参考に作成しました。

~~~bash
% git push origin main 
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for 'https://github.com/リポジトリ名/プロジェクト名.git/'
~~~

# 終わりに
今回はGitHubでpushできない原因をまとめました。
長い間プライベートで開発していなかったので、そのツケですかね・・。
まだ長く続くてあろうIT人生を油断せず、日々、切磋琢磨していきます！

# 参考
https://qiita.com/shunsa10/items/e43564cf48f84b95455b
https://www.publickey1.jp/blog/20/githubmainmastermain.html
https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
プログラミングのおすすめ勉強法

#はじめに
この記事は[SLP KBIT Advent Calender2021](https://adventar.org/calendars/6706)の15日目の記事です。
みなさんどのようにプログラミングの勉強をしているでしょうか？参考書を読んで勉強をする、ネットの学習教材を使ってなど様々な学び方があると思います。その中でも自分が約2年間プログラミングをやってきた中でおすすめの勉強法を紹介しようと思います。

#手順
手順はこんな感じです
１：作りたいものを決める
２：プログラミング言語を決める
３：使う言語の基本的な構文の確認
４：他人のコードを動かしてみる
５：動かしたコードの構造分析
６：自分なりにアレンジ

では一つずつ説明していこうと思います。

#１：作りたいものを決める
これに関しては本当に何でもいいと思います。
例えばwebアプリやゲームなど色々あると思います。
自分が欲しい理想的なものほどモチベ―ションが上がります！

#2：プログラミング言語を決める
プログラミング言語にはそれぞれ得意なこと苦手なことがあります。
自分が作るものに適したプログラミング言語がおすすめです。
しかし、もうすでに使いたいプログラミング言語が決まっていたらその言語でやってもいいと思います。おそらくそちらの方がモチベ―ションが上がると思います。
どんなプログラミング言語があるかよくわからないという方はこちらを参考してください。
[【難易度順】プログラミング言語を一覧で一挙紹介！](https://www.pasonatech.co.jp/workstyle/column/detail.html?p=2505)

#3：使う言語の基本的な構文の確認
このステップは基本的には初めてそのプログラミング言語を使う人向けです。
ではどこまで勉強すればいいのかと言われると正直難しいです。
個人的にはここに時間をかけすぎるのはおすすめしません。たしかに構文を学ぶことは大事なのですが、あまり長くやりすぎると「作りたいものを作る」という本来の目的を忘れがちになってしまいますからね。
自分はifやfor、配列、関数などのどの言語でもよく使うものを目安にして他は作りながら必要に応じて勉強するようにしています。

#４：他人のコードを動かしてみる
作りたいものも決まりプログラミング言語が決まって作ろうとしても１から自力で作ろうとするのはなかなか難しいです。（自分もまだできない）
なのでネットから自分が作りたいものに近い他人のコードを探して動かしてみましょう。
「作りたもの　プログラミング言語」で検索すると大抵のものであれば出てくると思います。

#５：動かしたコードの構造解析
４で動かしたコードがどのような構造をしているかを見ていきましょう。
このステップがおそらく全ステップの中で一番大変だと思います。
分からないところはネットで調べるか[terateil](https://teratail.com/)などで質問しながら解決していきましょう。

#６：自分なりにアレンジ
構造が分かればどこをどう変更したら自分が作りたい理想に近づくかわかってくると思います。
どんどん改造していきましょう！
おそらくここまでできるようになると初めと比べて相当の力がついていると思います。

#最後に
いかがだったでしょうか。自分も最初はプログラミングをどう学べばいいかわからなかった時期があったので、プログラミングを始めたけどどのように学べばいいかわからないという人に参考となればと思います。
では皆さん良い年末を～
データ＿サイエンティストへの道（ロードマップ）

以下、備忘録。
目次
1.プログラミング
2.機械学習
3.統計学
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
1.プログラミング
大学入学時あたりの、あの暇な春休み中、、、
この本（誤字脱字のオンパレードかつ、後半、自然言語処理あたりから、入門者向けではなくなるし、そもそも、入門者がやるもんじゃない。しかも、前半のpythonの基礎とか、オブジェクト指向についての説明は、哲学書並みに入門者に不親切。頭が痛くなりました）で頑張って勉強。ただ、マルコフ連鎖？あたりで挫折。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375151/6e5bdbc0-533a-2fd6-98dd-7e25c8c0c940.png)

大学２年の夏休み、、、
コロナで死ぬほど暇になる。何かしたいなあと思って、pyqにはまる。このサービス、結構よくて、力がついた気にさせてくれる。ただ、まあ、意味も分からず、ひたすら写経していた。
https://pyq.jp/quests/

大学２年のときに、、
バイオインフォマティクス。matplotlabの無料版、freematとCを触る。

大学３年の年末年始、、、
なんか、プログラミングの基礎的なところを教科書的にやってきたけど、正直、何の役にも立ってないなあ、と思っていた今日この頃。ふと、吉祥寺の本屋で、botterというものについて書かれている本を発見。
ななめ読みしてみると、プログラミングして作ったBTC自動売買bot??みたいなことが書かれていた。家に帰って、調べてみる。すると、文系でもわかるbot自動売買というブログを発見。
https://ryota-trade.com/
このサイト、とてもいい。目から鱗です。プログラミングの実践として、bot制作いいんじゃないかと思い、ここでひたすら勉強。勝手に稼いでくれるbotができたらなあ。。はやく、不労所得ほしい。。。（bot界隈、、気になる。。）

最近思うのは、プログラミングって、結局、コピペなんじゃないか？。。。天才プログラマーがお慈悲で公開してくれてるコードを読んで理解して（理解できないけど）、それをただ自分のコードにつぎはぎする今日この頃。。。





2.機械学習
大学3年：kaggle を知る。kaggleのcourseで機械学習などを触る。kaggle のcourse良い。英語だけど、無料で機械学習のプログラムを学べる

また、この本を勉強。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375151/7a90990b-57d7-0307-7a6c-7ac59d3408cf.png)

↑は、ちとむずかった。データサイエンスの一般的な流れは理解できて

問題設定→データ取得→データ探索→前処理→モデル構築→モデル評価

の、モデル構築あたりから理解できなくなったので、これは機械学習を根本から理解せなあかんなと思い、筑波大学オープンコースウェアにあった機械学習の授業を受ける。


筑波大の機械学習の授業、とてもいい。こんなにわかりやすい授業はまれ
https://ocw.tsukuba.ac.jp/course/systeminformation/machine_learning/p-1/


3.統計学
大学一年のとき、統計学を取る。正直、意味不明。ただ、今振り返ると、統計学的分析、Rを組み合わせて授業をするという、まあ、統計入門のくせして、いろいろ積み込みすぎた授業をぼうッと聞く。当然、評価はC。
さすがにもうちょい理解したいなあと思って、夏休み、北海道に行くために羽田空港で便を待っている時間にこの本を読む。わかりやすくていい。（数学の基礎がないとむずいけど）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375151/707c57f9-42a1-5297-f01f-158058d1c586.png)







大学２年のとき、バイオ統計をとる。そこでは、記述統計→推測統計→多変量解析の主成分分析まで、触る。

















、


今後は、、、
機械学習関連として、
Kaggleで勝つデータ分析の技術：https://amzn.to/3re0LpJ
はじめてのパターン認識：https://amzn.to/3jYd31O
仕事ではじめる機械学習：https://amzn.to/2PkERno

bot関連

あたりを勉強しようかなと。
あと、バイオインフォマティクス入門は積読になっています。、
botと機械学習って関係あるのかな。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375151/e9bc49f2-7033-f40c-1a26-fb26d04b8617.png)


これからも、統計学、プログラミング、機械学習、バイオインフォマティクスの勉強を続けます。あと、linuxの勉強もしたみ
コピーレフト・準コピーレフト・非コピーレフト とは

## 勉強前イメージ

なんかで聞いたけど忘れた・・・・

## 調査

### そもそも コピーレフト・準コピーレフト・非コピーレフト とは？

OSSのライセンス形態になります。
そもそもOSSは利用者の目的を問わずソースを使用・調査・再利用・修正・拡張・配布が可能なソフトウェアの総称になります。
オープンソースの定義はOSI(Open Source Initiative)というオープンソースを促進する組織によってOSD(Open Source Defition)としてまとめられています。
OSSは自由ならなんでライセンスがあるの？って感じですが、
ライセンスは使用承諾条件のことであり、ライセンスを守ることでOSSを使用することが許されています。
コピーレフト・準コピーレフト・非コピーレフト はライセンスの分類になります。

### コピーレフト

Linux等で採用されているライセンスで、3つの中で制限が一番厳しいものになります。

- 著作権の表示を保持
- 保障がない
- 自由に複製・改変・配布が可能
- [GPLライセンス](https://qiita.com/miyuki_samitani/items/3478df16ae66da84c3ee) を使用すると成果物もGPLライセンスで配布

代表的なライセンスはGPLになります。

### 準コピーレフト

Firefoxなどで採用されているコピーレフトから少し制限をゆるくしたライセンスです。

- 再配布の際は著作権の表示を記載
- 派生したソフトウェアまでは同じライセンスを適応
- 他のソフトウェアとOSSを組み合わせた場合、組み合わせ先のソフトウェアまではライセンスの適応をしない

代表的なライセンスはMPL(Mozilla Public License)になります。

### 非コピーレフト

バークレイ大学によって作成されたBSDライセンスになります。

- 派生したソフトウェアまで同じライセンスを適応しなくて良い
- 他のソフトウェアとOSSを組み合わせた場合、組み合わせ先のソフトウェアまではライセンスの適応をしない

この特徴から派生物のソースコードを配布する場合非公開にすることができます。
大乗的なライセンスはApache Licenseになります。

### まとめ

| -              | 複製・再配布 | 改変 | 派生したソフトウェアまでは同じライセンスを適応 | 他のソフトウェアと組み合わせた場合、他のソフトウェアのライセンス適応 | 
| -------------- | ------------ | ---- | ---------------------------------------------- | -------------------------------------------------------------------- | 
| コピーレフト   | 可能         | 可能 | 必要                                           | 必要                                                                 | 
| 準コピーレフト | 可能         | 可能 | 必要                                           | 不要                                                                 | 
| 非コピーレフト | 可能         | 可能 | 不要                                           | 不要                                                                 | 

## 勉強後イメージ

OSSって自由だと思ってたけど、ここではライセンス=使用承諾条件のことなのかー

## 参考

- [コピーレフト型と非コピーレフト型OSSライセンスの違いとは？](https://thinkit.co.jp/story/2014/02/03/4804?nopaging=1)
- [オープンソースライセンスとは？定義や注意点を解説](https://www.pasonatech.co.jp/workstyle/column/detail.html?p=2423)
[Drupal]特定のバンドルの全ての必須フィールドを取得する

## バックエンドで取得する場合

```php
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions(ENITTY_TYPE, BUNDLE);

$required_fields = [];
foreach ($field_definitions as $field_definition) {
  if (isset($field_definition->getConstraints()['NotNull'])) {
  $required_fields[] = $field_definition->getName();
  }
} 
```

## 管理画面で確認する場合
※ hook_form_alterなどでフォーム上の必須を修正している場合は以下の方法ではチェックできないので注意

- フォームの設定で全てのフィールドを表示させる
- 赤い米印が付いてるフィールドが必須フィールド
![スクリーンショット 2021-12-14 15.23.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/8cf415c6-bc83-4c9f-a428-b6d8653ce261.png)