OmniAICreator/Qiita-1.07M huggingface dataset:
43歳のノースキルMOSエキスパートがGASでサンタさんのアリバイを証明する。

こんにちは！
毎日さむいですね、ツヨツヨエンジニアの皆さんは気象庁かNOAAからデータ取ってきて
プロフィットで気温予測してるでしょうから、防寒対策もバッチシですよね！
※やりたいけどできてないスキル。

さて、アドベントカレンダーのネタとして[身の回りの身の回りの困りごとを楽しく解決！]した小話を開陳しようと思います。

# 身の回りの困りごとを楽しく解決！ by Works Human Intelligence Advent Calendar 2022
https://qiita.com/advent-calendar/2022/works-hi-1

## 毎年師走は師匠じゃなくて緊張が走るのをどうにかしたい。。
12月になると、低年齢育児世代には緊張が走ります。
+ 「今年はプレゼント何を贈ろうか」
+ 「まだ、サンタさんが直接来ると信じているのかしら？（いないとは言わない、親は代行業者だから）」
+ ブラックフライデー早すぎんよ、まだこどもが欲しいもの決まってないし、買っても隠し切れない・・・。

そんな親の気苦労を知ってか知らずかうちの三姉妹、呑気にアレクサにひたすらサンタの位置を聞いたりサンタと電話してます。

## そうだ、テクノロジーでアリバイを作ろう。
ちょうど学校のＩＣＴ授業でGoogleの使い方を習い始めてるから勉強も兼ねて日本語以外のそれっぽい言語で手紙作って送ろう。
仕事で作った「GASで一発翻訳スライド君」のスクリプトとicoonmonoさんの素材でサクっと仕上げます。

[icooon mono](https://icooon-mono.com/)
[GoogleAppsScript googleslide](https://developers.google.com/apps-script/reference/slides)


```JavaScript
//メニューをつけるやつ
function onOpen() {
const ui = SlidesApp.getUi();
ui.createMenu('マルチ翻訳')
.addItem('日本語→英語', 'jaToEn')
.addItem('英語→日本語', 'enToJa')
.addItem('日本語→ドイツ語', 'jaToDe')
.addItem('ドイツ語→日本語', 'deToJa')
.addItem('日本語→スペイン語', 'jaToEs')
.addItem('スペイン語→日本語', 'esToJa')
.addToUi();
}

function jaToEn(){
  multitranslate("ja","en")
}

function enToJa(){
  multitranslate("en","ja")
}

function jaToDe(){
  multitranslate("ja","de")
}

function deToJa(){
  multitranslate("de","ja")
}

function jaToEs(){
  multitranslate("ja","es")
}

function esToJa(){
  multitranslate("es","ja")
}



function multitranslate(ori,tar){
   //このファイルを取得。
  const slide = SlidesApp.getActivePresentation();
  //スライド→シェイプをそれぞれ.mapでまとめて取得処理。
  //後半、取得した文字列を自作のtranslate関数で翻訳   
  const kekka = slide.getSlides().map(x => x.getShapes().map(y => translate(y.getText().asString(),ori,tar)))
  
  //ここから下をもっと上手に書きたい！誰か教えて！！！
  for(let i=0;i<kekka.length;i++){
    for(let j=0;j<kekka[i].length;j++){
      slide.getSlides()[i].getShapes()[j].getText().setText(kekka[i][j])
    }}}
  
 function translate(txt,source,target){
    return LanguageApp.translate(txt,source,target)}

```

## onOpen関数を実行する。
onOpen関数をじっくするとメニューが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/3f5a5c18-58eb-863f-8a5b-3485b0198341.png)

## サクサクっと翻訳！
スライドにテキストボックスを入れて、テキストを追加しましょう。
何語でもいいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/e9accf49-db8a-dd36-a3ee-4baa7203828e.png)

これが・・・・。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/4fa0fd66-a867-698f-967a-2e315f6dfe3c.png)

こうなる！

![xmas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/f26a799b-8d1e-d8cc-68b7-3b5769f55b66.png)
PDF化して、セブンのネットプリント使ってサックリお手紙作成完了。
あとは「それっぽく」おうちのどっかに忍ばせて自然に見つけさせましょう。


## 有識者の皆様へのお願い
いわずもがな、独学へっぽこ非エンジニアなのでいわゆるクソコードと思います。
+ [ココはこうやって書くんやで]
をやさしく教えてくれると生きていけます！

[#俺が見たクソコード選手権](https://togetter.com/li/544905)


このころは何言ってんのかさっぱりわからんかったけど今ならチョットワカル。
redis-pyでRedis Clusterから全件取得する

タイトルの通り、redis-pyというPythonライブラリを使ってRedis Clusterから全件取得する記事です。

# 方針

- 全マスターノードで`SCAN`
- 全スロットで`CLUSTER COUNTKEYSINSLOT`でKEY数を取得し`CLUSTER GETKEYSINSLOT`でKEYを取得

の2種類の方針があると思っています。
今回は後者のやり方になります。

# 環境

- Python 3.7.10
- redis-py 4.3.4
- hiredis 2.0.0

```shell
$ python --version
Python 3.7.10

$ pip list | grep redis
hiredis             2.0.0
redis               4.3.4
```

# 全件取得してみる

## Redis Clusterに接続

```python
from redis.cluster import RedisCluster, ClusterNode

nodes = [
    {"host": "host_name_1", "port": 6379},
    {"host": "host_name_2", "port": 6379},
    {"host": "host_name_3", "port": 6379}
]

cluster_nodes = [ClusterNode(**node) for node in nodes]
redis_cluster = RedisCluster(startup_nodes=cluster_nodes, readonly_mode=True)
```

## スロットの全キーを取得
```python
slot_id = 0
num_keys = redis_cluster.cluster_countkeysinslot(slot_id)
keys = redis_cluster.cluster_get_keys_in_slot(slot_id, num_keys)
```
これで特定のスロット`slot_id`のKEY数を取得できます。
スロットはデフォルト設定であれば0〜16383まであるのでforとかでやれば全件取得できます。

対話モードでやってみた結果が下です。
```
>>> slot_id = 1392
>>> num_keys = redis_cluster.cluster_countkeysinslot(slot_id)
>>> num_keys
1
>>> keys = redis_cluster.cluster_get_keys_in_slot(slot_id, num_keys)
>>> keys
['key_name']
>>>
```

## 注意点

`SCAN`系で取得したときと`CLUSTER GETKEYSINSLOT`では型が違います。(1敗)
`SCAN`だと`bytes`、`CLUSTER GETKEYSINSLOT`だと`str`でKEYが返ってきます。

```
>>> type(redis_cluster.cluster_get_keys_in_slot(slot_id, num_keys)[0])
<class 'str'>
>>> 
>>> type(next(redis_cluster.scan_iter(match='*')))
<class 'bytes'>
>>>
```


## コード全文

やってきたことをまとめるとこんな感じです。

```python
from redis.cluster import RedisCluster, ClusterNode

nodes = [
    {"host": "host_name_1", "port": 6379},
    {"host": "host_name_2", "port": 6379},
    {"host": "host_name_3", "port": 6379}
]

cluster_nodes = [ClusterNode(**node) for node in nodes]
redis_cluster = RedisCluster(startup_nodes=cluster_nodes, readonly_mode=True)

for slot_id in range(16384):
    num_keys = redis_cluster.cluster_countkeysinslot(slot_id)
    keys = redis_cluster.cluster_get_keys_in_slot(slot_id, num_keys)

    # keysを使った何かの処理
```
歴史あるプロダクトとの付き合い方 〜デザイン負債解消の手引き〜


[Ateam LifeDesign Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ateam-life-design)、本日はWebデザイナー4年目の@snd-07 が投稿します！

## 2022年を振り返って

今年は、8年以上運用されているプロダクトをメインに携わった1年でした。

今までは運用歴1〜2年ほどの、比較的モダンなリポジトリを触っていましたが
それに比べると、長く運用されていることによるプロダクト特有のクセが多く、
なかなかうまくいかないことも多かったように思います。

この記事では、事業を成長させるため過去の方々が積み上げてくださった
プロダクトの歴史と向き合いながら、少しずつ進化させていった取り組みについて紹介します。

## 届けたい人

- 長く運用しているサービスに携わるクリエイター
- プロダクト負債との付き合い方に悩んでいる人

## 当時の課題

### サイト全体で統一感がない

ページによって、少しずつ違う見出しやパーツ、レイアウトが存在していました。

* デザインするのに、正しいものがわからない
* 要素を足したい時に、整合性がとれない

結果、調査や確認の時間が発生。
かけなくてもいい無駄な工数がかかっていました。


### ユーザビリティ・アクセシビリティが良くない

世の中にないUIや、コントラスト比の低い配色などが存在していました。
利用するユーザーが若い人だけではないこと、人によって色の見え方が違うことをふまえると
決して良いUIとは言い難かったです。

### ガイドラインのないコード

リポジトリは、ガイドライン・ナレッジがないに等しい状態でした。
どのファイルに書けばいいか？どういうコードを書けばいいのか？がわからない。

作業したメンバーの時期によって書き方の差分がありましたし
デザインが揃っていないことで、似たようなコードが量産されていました。


## 現在

施策実施時に、デザイン・コード改修も組み込むことで
少しずつ整頓させていくことができました。

* コード
    * 新規参入者でもすぐにコードが書ける状態に
    * ガイドラインに則りながらリファクタリングできる状態に
* デザイン
    * 色、余白などの定義がある状態に
    * 使いまわせるコンポーネントを使って制作ができている状態に

## やったこと

### 現状の把握

まず、どれだけの色・パーツがあるのかの把握から始めました。
パーツをスクショして集めたり、[CSS overview](https://developer.chrome.com/ja/blog/new-in-devtools-96/#css-overview)で配色の全体を見通し。

![A4 - 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250206/a55211fa-82ae-31d3-20d5-167f62a67620.png)


その中で、「なんとなく決まっているもの」と「全くバラバラなもの」などをぼんやり理解し、
一新していくのか？今あるものを踏襲して整理するのか？の判断をつけていきました。


### ページの改修時、デザイナーを必ずアサインした

デザイナーがいるかいらないか、の判断を任せず
実施したい改修内容を共有してもらうことにしました。

結果、一定品質を保ったものを世に出せるように。
「知らないうちにリリースされている！」といった状況を防ぐことができました。

![A4 - 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250206/55316b29-a443-5d1d-4e7b-992a826ea662.png)




### ガイドラインの策定

デザインの整備をしながら、コードのルールも決めていきました。
結果、誰もが一定の設計に則ってコードが書けるように。
UIも、他で使いまわせるパーツが少しずつ増えていきました。

![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250206/8287e18f-d309-4256-c561-8893e9f356e0.png)


* プロダクト独自ルールではなく、できるだけ世の中に倣う
* 小さいところから徐々に決めていく
* 完璧に決め切るのではなく、うまくいかないところがあればその都度メンバーで議論する

といったスタンスを意識して取り組んでいます。

## なぜ頑張れたのか

### 自分の性に合っていた

「メンバーが、もっと楽に作業できるようになってほしい」という気持ちは、
自分のモチベーションになっています。

また、デザインやコードがリファクタされると、スッキリして気持ちが良いです。
物を捨てることが好きな私にとって、今行っている取り組みは同じような体験が得られました。

* 他人のために頑張れる、貢献欲を持っている
* 整理整頓が好き

そんな人は、比較的前向きに取り組めるのではないでしょうか。


### 気持ちを共有できる人がいた

いざ着手してみて、なんだこれ！！とビックリすることもあり
しんどい気持ちになることもありました。

しかし、同じチームのデザイナーと気持ちを共有し
励まし合えたことで諦めずに継続できています。

今、一人でプロダクトに立ち向かっている方は
ぜひ気持ちを共有できる人・発散できる人を探してみてはいかがでしょうか。

## 最後に

ここまで読んでくださりありがとうございました。
気になる点あれば、お気軽にコメント・お問合せください。
まだまだ取り組みは道中ですので、引き続きチャレンジをしていきます。

明日のアドベントカレンダーは @l_dOwOd_l  さんです！お楽しみに:relaxed:
研究の再現性担保 - Artifact Review対応の事例紹介

# TL;DR
研究の再現性向上のために、レビュアーから指摘されたポイントと、アクセプトされた事例を紹介します

# 背景：研究の再現性
最近、こんな記事を目にしました。
> 2008年に発表された100本の論文を対象とした大規模な追試プロジェクトの結果によると、心理学のトップジャーナルの論文を対象とした研究において、再現性が認められたのは4割程度だったと言われます（5％有意水準）。心理学とはいえ分野によって再現率は異なり、社会心理学系では25％、認知心理学系では50％程度は再現できたようです
https://note.com/s1000s/n/na0dbd2e8632d

こういった研究の再現性に関する課題は、分野を問わず存在します。結果が再現できないのはもってのほかですが、実行環境の構築や提案手法の実装が大変だと、その後の研究活動が遅延してしまいます。私も学生時代は情報系の学科に所属していたのですが、論文作成のための既存研究サーベイ/再現の際に、本質的でないところ(環境構築/書かれていないパラメータ設定/etc...)で大変な苦労をした思い出があります。再現はできました。

ただ、データの利用許諾範囲やコードの知的財産権など、公開・共有できない事情もあると思います。そういった事情を加味しつつ、可能な限り情報を公開して、他の人が簡単に研究内容を再現できる環境を確保していきたいです。

# この記事の内容：Artifact Reviewの事例紹介
...とはいえ、再現性確保ために何をしたらいいか、よくわかりません。適当に対応して再現不可能だと困りますが、要求されるレベルが高くて対応が超絶大変だったら、やる気が出ません。

そこで今回は、国際会議に論文投稿した際のArtifact Reviewに対応した結果を紹介することで、研究者界隈で求められる品質レベルを共有します。

具体的には、プライバシー保護技術の主要国際学会「[Privacy Enhancing Technologies Symposium](https://petsymposium.org/)」で、[産総研村上さん](https://staff.aist.go.jp/takao-murakami/)主著(私も共著で参画)の[論文](https://arxiv.org/abs/2107.10407)を投稿した際のレビュー結果を紹介します。提案手法を公開した[レポジトリ](https://github.com/PPMTFPlus/PPMTFPlus)の内容について、Artifact Reviewで頂いたコメントの内容と対応方針を紹介します。

そこまで大変じゃない(と思う)ので、みなさん頑張りましょう。

# Artifact Review：レビューポイント (本記事の主題)
まず自分たちでREADMEをいい感じに書いて、ソースコードを配置したGithubレポジトリを作成し、レビュアーにURLを共有したところ、以下の内容でチェック・レビューされました。

>- [ ] 手順書が分かりやすいか
>- [ ] ライセンスが明記されているか
>- [ ] 環境構築やソースコードのビルドが成功するか
>- [ ] 数値実験が正しく走るか
>- [ ] 必要なファイルが配置されているか
>- [ ] ソースコードが論文中の図を出力するか
>- [ ] 論文中の図が全て再現されるか
>- [ ] ソースコードが出力する実験結果が、論文の内容と同じか

以下で、対応方針を個別に紹介します。

# Artifact Review：個別対応
>- [ ] 手順書が分かりやすいか
>- [ ] 環境構築やソースコードのビルドが成功するか

こちらは、[Readme](https://github.com/PPMTF/PPMTF/blob/master/README.md)を頑張って作成しました。計算環境の差異や、細かい手順の詳細を書くのが大変です。想定している実行環境は明記しつつ、構築手順の詳細はDockerfileにまとめて、「docker compose up -d --buildしてね！」という手順にしました。これなら、手元の環境で成功すれば、レビュアーの環境でも成功するでしょう。

ビルドに時間がかかると不安になるので、「このくらいのスペックの環境だと、15分くらいかかるよ」みたいに相場観を書いておくと、再現する人に安心して貰えると思います。終わらないと怖いので。

>- [ ] 必要なファイルが配置されているか

ファイルの配置については、フォルダ構成を明示しつつ、依存している主要な外部ライブラリを明記しました。

>- [ ] ライセンスが明記されているか

MITライセンスであることを示す[Licence.txt](https://github.com/PPMTF/PPMTF/blob/master/LICENSE.txt)を配置しました。コピペするだけです。[参考](https://qiita.com/shinya_sun_sun/items/bdafe803a7643e6dd15b#mit%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9)

>- [ ] 数値実験が正しく走るか
>- [ ] ソースコードが論文中の図を出力するか

こちらは、実行手順の詳細を書くのも大変なので、Dockerfileにて数値計算の実行・図の出力まで行うようにしました。

>- [ ] 論文中の図が全て再現されるか
>- [ ] ソースコードが出力する実験結果が、論文の内容と同じか

論文中の図には、分かり良さ向上目的でPowerPoint等で作った概念図も含まれます。全ての図の再現、は大変です。
レビュアーに「この辺の再現は本質的ではないので、メインの図であるこれとこれで良い？」などと相談したところ、レビュアーの方も納得してくれました。指定した図を再現できていることが確認でき、アクセプトされました。

# Artifact Review：提出後のレビューコメントのメモ
レビュアからは、データソースのWebサイトが日本語でわからん！など、いくつかコメントを頂きました。粛々と対応すればよいです。こういうのはなかなか気づきませんね...。

本質的ではないところの再現、については、都度説明すれば省略可能でした。相談することが大事ですね。

他、何か思い出したら追記していきます。

# まとめ/おわりに
[こんな感じでレポジトリを公開する](https://github.com/PPMTFPlus/PPMTFPlus)と、レビュー通過しました。
他の技術領域だと、求められる内容・品質が異なると思います。あくまでも参考情報として活用いただければと思います。

同時複数人での研究や、既存研究の引き継ぎなどを考慮すると、環境や実験結果の再現性確保は普段から準備しておいて損は無いですね。
ベストプラクティスが定まったら、研究のお作法として、大学の授業とかで学べたらいいな、と思いました。

以上です。

NSSOLアドベントカレンダー、次の記事はこちらです!
https://qiita.com/kmnky/items/c86749911c71801c6b46

# 参考資料
- [Popets Artifact Review](https://petsymposium.org/artifacts.php)
ブックマークサイドバーめちゃくちゃ捗る [Chrome拡張]

# ブックマークサイドバーについて

「ブックマークサイドバー」は、ブックマークをサイドバー内に表示できる拡張機能です。

Chrome に、Firefox のようなブックマークサイドバーを設置可能にする拡張機能で、ブックマークしたウェブサイトをサイドバー上から手軽に開ける＆管理できます。

サイドバーは、見た目（配色、フォントなど）を細かくカスタマイズできるようになっていて、表示方法も

ホットキー
- マウスカーソルを、画面左端、または右端へ移動
- マウスカーソルを画面左端、または右端へ移動させ、左（あるいは右）クリック
- ツールバーボタンをクリック
の中から選べたりします。

さらに、サイドバーはマウスカーソルが外れると自動で隠れるようになっているため、スムーズかつ邪魔になることなく扱えるようになっています。
（自動で隠れないようにすることも可能）

普段、`Chrome のブックマークツールバーは、どうにも使いづらい` と感じていたりする人におすすめです。

![unnamed.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/b78fd78e-15fc-936c-77bd-c6e7271fd798.jpeg)


## インストール先    

https://chrome.google.com/webstore/detail/bookmark-sidebar/jdbnofccmhefkmjbkkdkfiicjkgofkdh?hl=ja



## install後の設定

![Monosnap セットアップ - ブックマークサイドバー 2022-12-08 10-56-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/4182e1a2-2f11-d6c1-ebff-36e74eab00a2.png)

![Monosnap セットアップ - ブックマークサイドバー 2022-12-08 10-56-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/f5f67c90-2f3d-4ef6-fe46-9cde11a05f69.png)

![Monosnap セットアップ - ブックマークサイドバー 2022-12-08 10-57-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/72c83814-0592-43fa-5a39-d456b2b62aee.png)

![Monosnap Qiita 2022-12-08 10-58-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/e2b8f28c-03fe-8aa4-07d9-ec04d14ef182.png)
Elmでマウスの右クリックを検知する

Elmでマウスの右クリックを検知するにはどうすれば？と思って調べた際のメモ。

[mpizenberg/elm-pointer-events](https://package.elm-lang.org/packages/mpizenberg/elm-pointer-events/latest/) を使うのが楽そう。

```elm:左クリックor右クリックをボタンのテキストに表示するサンプルコード
module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events.Extra.Mouse as Mouse

type alias Model = { buttonText : String }

type Msg = LeftClick | RightClick

initialModel : Model
initialModel =
    { buttonText = "Clicked: -" }

update : Msg -> Model -> Model
update msg model =
    case msg of
        LeftClick ->
            { model | buttonText = "Clicked: Left" }

        RightClick ->
            { model | buttonText = "Clicked: Right" }

view : Model -> Html Msg
view model =
    div []
        [ button
            [ Mouse.onClick (\_ -> LeftClick)
            , Mouse.onContextMenu (\_ -> RightClick)
            ]
            [ text model.buttonText ]
        ]

main : Program () Model Msg
main =
    Browser.sandbox
        { init = initialModel
        , view = view
        , update = update
        }
```

[実際のアプリ(Ellie)](https://ellie-app.com/knJywMHFQQsa1)

**2022.12.10 追記**

@ababup1192 さんから `Html.Events.custom` でいけますよとのこと。

https://twitter.com/ababupdownba/status/1601169161467854848

折角なので実装してみましょう。

```elm:Html.Events.custom版
module Main exposing (main)

import Browser
import Html exposing (Attribute, Html, button, div, text)
import Html.Events as Events
import Json.Decode as JD

-- (略)

view : Model -> Html Msg
view model =
    div []
        [ button
            [ Events.onClick LeftClick
            , Events.custom "contextmenu" <|
                JD.succeed
                    { message = RightClick
                    , stopPropagation = True
                    , preventDefault = True
                    }
            ]
            [ text model.buttonText ]
        ]

-- (略)
```

[実際のアプリ(Ellie)](https://ellie-app.com/kpJSnCYvJrWa1)

OK👍
擬似要素 :placeholder-shownについての忘備録。


## 経緯と説明
フローティングラベルがcssだけで実装できる擬似要素、
**:placeholder-shown**。

なになに！ そんなんあるん？ と思って色々サーフィンし始めた、お仕事中の午後！

手始めに調べてみると、MDNさんの解説ではこう。
> :placeholder-shown は CSS の擬似クラスで、プレイスホルダー文字列が表示されている <input> または <textarea> 要素を表します。

https://developer.mozilla.org/ja/docs/Web/CSS/:placeholder-shown


アホなワイには、この簡潔で素晴らしいテキストでは完全に理解し難い。笑
体で覚える派なので、とりあえず試しに実装してみた。


## 結論

input（type=text）とかtextareaに、
「値が入力されているか、されていないか」の判定を行ってるだけでした。

（placeholderあんま関係ないんかい笑）
※inputにplaceholderのattrは必要。




#### 【補足として】
これの何がフローティングラベルに活かされるかというと、
値が入力されている限りcssが効くので、forcusが外れてもラベル位置は維持できる。

フローティングラベルの動きはcssで擬似的に作る、
んでfocusが外れることによって擬似的に作ったラベルが元の位置に戻ってしまうのを防ぐために

:not(:placeholder-shown) ※inputに値が入ってまっせ状態にして
ラベルにしている兄弟要素のspanを指定して記述ができるわけ。

なるほどやん。
またなんか機会があったら使ってみようの忘備録でした。
Azure Administrator(AZ-104)：Azure管理者向けの前提条件「PowerShellのコマンドレットとモジュール」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「PowerShellのコマンドレットとモジュール」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure 管理者向けの前提条件](https://learn.microsoft.com/ja-jp/training/paths/az-104-administrator-prerequisites/)
◇対応するモジュール
[Azure PowerShell でスクリプトを使用して Azure リソースを作成する](https://learn.microsoft.com/ja-jp/training/modules/automate-azure-tasks-with-powershell/5-create-resource-interactively?pivots=windows)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure管理者向けの前提条件「モジュールと出力(Bicep)」](https://qiita.com/fsd-jume/items/49dc332f2d697e8259e3)

## PowerShellのコマンドレットとモジュール
### PowerShell
**コマンドを記述してすぐに実行できる対話モードでAzureを操作可能**

**◆コマンドレット**
・1つの機能を実行するPowerShellのコマンド
・モジュールを追加することにより基本以外のコマンドレットの追加が可能
・`動詞(Verb)`-`名詞(Noun)`の名前が付けられている
(例：Get-Process、 Format-Table、 Start-Service)
・動詞の規則例
　-Get：データの取得
　-Set：データの挿入/更新
　-Format：データの書式設定
　-Out：宛先への直接出力
・説明を表示させる場合は「Get-Help」を実行する
例)「New-AzResourceGroupDeployment」コマンドレットの説明を表示させたい場合
```powershell:PowerShell
Get-Help -Name New-AzResourceGroupDeployment -Detailed
```
**※コマンドの意味**
**・Get-Help -Name `コマンドレット` (-Detailed)**
コマンドレットの説明を表示
　-Detailed：つけた場合はより詳しい説明を出力
**・New-AzResourceGroupDeployment**
リソースグループにリソースを作成

### モジュール
・利用可能な各コマンドレットを処理するコードが含まれるDLL(Dynamic Link Library)
※DLL：多くのプログラムに共通して必要な機能などが一つにまとまったプログラムファイル
・使用したいコマンドレットが含まれるモジュールを読み込むことで、PowerShellでそのコマンドレットが使用可能
※PowerShell3.0以降ではモジュール内のコマンドレットを使用した際にモジュールが自動で読み込まれるため、手動読み込みは不要
・「Get-Module」コマンドで読み込まれたモジュールのリストを確認可能

**◆Az PowerShellモジュール**
・Azure PowerShellモジュールの正式名称
・Azure機能で使用できる数百単位のコマンドレットを含む
・あらゆるAzureリソースのほぼすべてを制御可能
・更新する場合は「Update-Module」コマンドを使用する
```powershell:PowerShell
Update-Module -Name Az
```
**※コマンドの意味**
**・Az**
Az PowerShellモジュールを表す

## 次の学習内容
**◆PowerShellによるAzureリソースの作成**

https://qiita.com/fsd-jume/items/3d5953d8bef8e1007bf6

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
【MySQL】一時テーブル作成から更新までの流れ

MySQLでツラツラ学んだことを書いていきます(^-^)

# MySQLで一時テーブルを作成
一時テーブルを```CREATE TEMPORARY TABLE```で作成します。
 TEMPORARY テーブルは現在のセッション内でのみ表示され、セッションがクローズされると自動的に削除されます。2 つの異なるセッションが同じ一時テーブル名を使用することができ、互いに同じ名前の既存の TEMPORARY 以外のテーブルと競合することはありません。 
ストレージエンジンは``` InnoDB ```が選択されます。

```
CREATE TEMPORARY TABLE contract_temp (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
contract_at TIMESTAMP,
PRIMARY KEY (id)
)ENGINE=InnoDB
;
```

```show create table contract_temp;```で作成した一時テーブルの中身を確認できます。

# 一時テーブルに作成したCSV or TSVファイルを投入する
```FIELDS TERMINATED BY```の``` '\t'```は区切り文字を設定するので、今回はタブ区切りのTSVファイルを読み込みます。
```例
LOAD DATA LOCAL INFILE '/Users/○○○○/○○○○/contract_test.tsv'
INTO TABLE `contract_temp`
FIELDS TERMINATED BY '\t' OPTIONALLY ENCLOSED BY '"'
IGNORE 1 LINES
(`id`, `contract_at`, `digital_log`);

```
# １つのテーブルを別のテーブルの値でUPDATEするやり方
先程の一時テーブルで作成した値（今回は前もって準備していたTSVファイルを投入しておきます）を既存のテーブルに更新します。今回は```user_profile```テーブルの3つのカラムを```contract_temp```一時テーブルのカラムで更新します。
```例
UPDATE user_profile,contract_temp
SET user_profile.contract_at = contract_temp.contract_at,
user_profile.digital_log = contract_temp.digital_log
WHERE user_profile.id = contract_temp.id;
```
Herokuでデプロイできずやらかしかけた話

検証環境なのですが、Herokuでデプロイができずやらかしかけた話です。
DBの更新も含んでいたため、デプロイ完了時にサービスが止まることが想定でき、お客様に止まる事と終了したら確認して欲しいとお伝えしていたため長時間お待たせすることができず焦った体験談になります。
誰かしらが同じような問題に直面した時の一助になればと思いさらします。

ざっくりとした環境
```
Ruby 2.7系
Rail 6.1系
Node 14系
```

## 経緯
### 問題発生まで
その日はお客様から修正依頼が来ており、社内レビューが終了したため検証環境にデプロイしようとしていました。
今回の修正ではDBのテーブルにカラムの追加があり、主要機能でその追加したカラムを参照することから、デプロイ終了後にmigrateを実行しないと主要機能が使えなくなる内容でした。

そのため、お客様に検証環境が一時期使えなくなることと終了したら確認して欲しいと連絡を入れてデプロイを開始。
デプロイはPCからのコマンドで何度も行っている作業なのでデプロイ先が検証環境なことと修正したブランチをデプロイしようとしていることを確認して実行しました。
普段からデプロイに30分弱かかるのでデプロイが終わったらmigrateを実行しないとなと考えながら他の作業をしていました。
そろそろ終わったかとコンソールを確認するとデプロイが失敗している！！
つい先週もデプロイしているので何でだと思いながらも上司に報告し、調査を開始しました。

### 最初の対応
Herokuのデプロイ失敗は初めてのことだったため焦りながらも、HerokuにDashboardにデプロイ時のログが残ることを確認して自分でログを残す必要がないことを確認しました。
その後、デプロイの失敗が一時的なものかと安易に思いもう一度デプロイを実行しました。
この時は今回の修正ではテーブルにカラムの追加と画面の修正だけで特にデプロイに失敗するような変更はしていないのにと思いながら、再度実行したら大丈夫だろうと思いログもあまり確認しておりませんでした。

ただ、残念ながら今回のデプロイも失敗。
一時的なものでないと判断しデプロイ時のログを最初から確認していきました。

ログの全文は割愛しますがログを初めから見ていたら`failed`の文字が。
```
[4/4] Building fresh packages...
Done in 36.83s.
Compiling...
Compilation failed:
Browserslist: caniuse-lite is outdated. Please run:
  npx browserslist@latest --update-db
  Why you should do it regularly: https://github.com/browserslist/browserslist#browsers-data-updating
Error: error:0308010C:digital envelope routines::unsupported
```

`npx browserslist@latest --update-db`と書かれていますしこのコマンドを実行すればエラーも無くなるだろうと考え上司に報告しました。

上司からも初めて見る内容だが、ログにも出ているし一度その対応をしてみてくれと言われました。
ローカルでの開発環境はdocker及びdocker-composeを使用しているので、コンテナに入って`npx browserslist@latest --update-db`を実行することに。
実行した結果`yarn.lock`ファイル内でバージョン指定が変更になっていること、ローカルのコンテナを再起動して問題なく動くことを確認してから3回目のデプロイを実行しました。

ですが3回もデプロイ失敗。
3回目のデプロイ時のログを確認したところ、先ほどのコマンドを実行するように書かれていたエラーは解消されたものの後続でエラーが続けて出ていることがわかりました。
このエラーは２回目の際にも出ていたのですが、その前のエラーを解消すれば治るだろうと思い確認していませんでした。

### ２回目の対応
そろそろ、最初のデプロイ開始から1時間。
お客様に後ほど確認いただくと連絡していたので焦りながらも継続して出ているエラーの調査に入りました。

エラー内容は下の通りでここからは何もわからないのでgoogle先生に質問しました。
```
Error: error:0308010C:digital envelope routines::unsupported
```
そうするとNodeのバージョンについて言及しているページが。
- [「 Error: error:0308010C:digital envelope routines::unsupported 」 の対処法](https://zenn.dev/pontagon333/articles/26c89cbc14e81f)
- [【Next.js】Error: error:0308010C:digital envelope routines::unsupportedなエラー](https://penpen-dev.com/blog/error-error0308010cdigital-envelope-routinesunsupported%E3%81%AA%E3%82%A8%E3%83%A9%E3%83%BC/)

Nodeのバージョンなんて今回の修正では変更していないよなと思いながらも、思い当たる節がありました。
それは、別の仕事においてCIの参照しているイメージが更新されており、Nodeのバージョンが変更になったことでCIが落ちるようになったという出来事でした。

もしかしてHerokuで使用されるデフォルトのNodeのバージョンが変わったのかも...と思いながら、落ちているデプロイのログと先週の成功しているデプロイのログを見比べたところ案の定、Nodeのバージョンが成功した以前のは`Resolving node version 16.x...`だったのが`Resolving node version 18.x...`になっており想像通りの理由だというのがわかりました。
ローカルのdocker環境では14系を指定しており、前から違うじゃないかと思いながらも一旦16系か14系を使用するよう固定してしまえば良さそうだと一安心。

上司に連絡し、一旦14系で固定するように変更したことで無事４回目でデプロイが成功しました。
その後、デプロイ後の作業を行なって、お客様へ確認いただくように無事連絡できました。

## 最後に
最初のデプロイ開始してから1時間30分。
検証環境だという事もあって問題なかったのですがこれがサービスを止めてでの本番作業だったらとゾッとしました。

また、以前同じような場面に遭遇していたのですぐに当たりをつけられましたが知らなければ今回はNodeのバージョンなんて変えていないはずと的外れな検証をしていたはずです。
なのでこの文章を読んだ誰かしらが、同じような問題に直面した時の一助になればと思います。

長文＆駄文を失礼いたしました。
FileMaker 親切なレイアウト切り替え

動作検証:FileMaker Pro 19.6

## 残念なレイアウト切り替え

People のリストを表示
- レイアウト:lst_People

![Image_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/4134a10a-11be-356c-b984-4c5cf24f26a3.png)

People の詳細に切り替え
- レイアウト:dtl_People

![Image_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/10f44561-f47e-b9f8-eff7-65e22db4d13e.png)

Classroom のリストを表示
- レイアウト:lst_Classroom

![Image_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/e9ea83fd-1a17-054e-0d8c-97e0e33a8e33.png)

**残念なポイント!**
ボタン[People]でレイアウトを切り替える際、

![Image_003-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/45982ccc-c58a-f4ff-f14c-ee774e053ff4.png)

「レイアウト切り替え」で lst_People を指定だと...

![Image_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/db3c4f13-06f4-4562-4172-51a70c066ef8.png)

People の最後の表示は、レイアウト:dtl_People だったのに lst_People に切り替わってしまいます。
People に戻ったとき、最後に表示していたレイアウトになるようにした方が親切です。

## 親切なレイアウト切り替え
### レイアウト上の設定

現在のレイアウトを記憶しておく必要があります。
レイアウト上に`LayoutName:<<$$LayoutNamePeople>>`設置
「次の場合にオブジェクトを隠す」に以下の式を設定
```
Let(
$$LayoutNamePeople = Get ( レイアウト名 )
;
0)
```
レイアウトが表示されるたびにグローバル変数`$$LayoutNamePeople`に、レイアウト名が保存されます。
> $$LayoutNameテーブル名 としています。

![Image_006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/ed51e4ec-f66c-f64e-1085-a2e3c9e3a5b8.png)


レイアウト:lst_People, dtl_People に同じモノを設定。

![Image_008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/f44e6fcc-6bc5-b693-8fe3-20a150be3b4a.png)

Classroom の方も同様に設定します。
グローバル変数は、`$$LayoutNameClassroom`

![Image_009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/a7b851eb-6f65-fcf8-f216-42559776e6ae.png)

### スクリプト

スクリプト:GoToLayout[People]
![Image_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/28cc1cdb-ee05-c7bc-06d2-9fafd554d247.png)

スクリプト:GoToLayout[Classroom]
![Image_011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/e9b81b8a-1a80-c76f-f528-f66a368cbf0b.png)

それぞれのスクリプトをボタンに設定
![Image_012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703491/6218c375-ce1b-2984-84ef-5dcc48546ba6.png)

# 完
:::note info
良いシステムって、親切心の塊...だと思う。
:::
本番環境へのデプロイ


+ [本番環境リリース後のロールバックの方法について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JfNfOSAV)

標準では用意されていないので、別のツールを活用するとのことです。


https://salesforce.stackexchange.com/questions/123758/how-to-roll-back-a-code-deployment-from-sandbox-to-production


https://gearset.com/blog/rolling-back-unwanted-changes-in-a-salesforce-deployment/
macOS Venturaで時計の秒針を表示させる方法

普段から、PCの時計を表示する時、秒針があったほうが色々と都合が良いので、先日macOSを12から13（Ventura）にアップデートしたのですが、UIが結構変わってしまい、「Dockとメニューバー」から秒針を表示させることができなくなってしまいました。
自分用の備忘録として、Venturaでの秒針の設定方法をメモしておきます。

# 設定方法

1\. 左上のアップルアイコンを選択し、メニューの中から「システム設定(System Setting)」を選択します。
2\. 「コントロールセンター(Control Center)」を選択し、下の方へスクロールして、「メニューバーのみ（Menu Bar Only）」にある「時計のオプション（Clock Options）」ボタンを押します。
![画像1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596044/3f6a085d-0163-6e1b-60e8-b5ba24dbe6dc.png)
3\. 時刻のオプションの中にある「秒を表示(Display the time with seconds)」のスイッチをオンにします。
※お好みで、「時刻内の":"を点滅させる（Flash the time separators）」にチェックを入れると、時刻の区切りの"："を点滅させる事ができます。
![画像2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596044/4efc1dcf-3b1f-c8f6-dedd-1259a5282291.png)
4\. 「完了（Done）」ボタンを押して設定完了

以上です。
イテレータとイテラブルについて（備忘録）

## イテレータとは？
>イテレータとは、イテラブル（繰り返し可能）なオブジェクトから要素を取り出すオブジェクトのことです。
※イテラブル…for文を用いて、繰り返し処理ができるオブジェクトのこと。リストやタプルなどがあげられます。

## next関数とiter関数について
next関数は、next(イテレーター)　のようにイテレータから要素を一つ取り出して消去することができる関数のこと。最後の要素を取り出し終わり、再度、関数を実行しようとするとstopIterationという例外が発生する。（繰り返し停止の意味）

iter関数とは、指定されたイテラブルに対するイテレーター（iterator）を返す関数のこと。
~~~python
>>> iterater = iter([3, 10, 7])
# インデックス０から順番に取り出していく
>>> next(iterater)
3
>>> next(iterater) 
10
>>> next(iterater)
7
# エラーが発生する
>>> next(iterater)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
~~~

## イテラブルとイテレータの違い
>仮に、for i in some_list　と書いたときfor文は、some_listに実装されているiter()を呼び出して、その戻り値を使います。この戻り値をイテレータと呼びます。for文では、inの後にしてされたオブジェクトには、必ずiter()を適応する。

>イテレータオブジェクトは、特殊メッソドの「__iter__()」と「__next__()」が実装されています。
~~~python
some_list = iter([0, 1, 2, 3, 4, 5])
print(dir(some_list))

>>>[---省略---'__iter__', ---省略---, '__next__', ---省略---]
~~~
対して、listの特殊、メッソドを表示してみます。
~~~python
some_list = [0, 1, 2, 3, 4, 5]
print(dir(some_list))
    # イテレーターを生成できるが、次の要素にアクセスする機能を持ちえない
>>>[---省略--- '__iter__', ---省略---]
~~~
つまり、イテレータは、next()を使うことができるので、次の要素にアクセスできるが、イテラブル（list）は、next()を使うことができないので、次の要素にアクセスする機能を持ちえません。
研究用のAWSインスタンス

- CPUのコア数は欲しい
- 安いのが良い
- GPUはいらない

という条件で探してみた。

## インスタンスタイプに関して

そもそもインスタンスのインスタンスタイプの意味が良く分からなかったので命名規則を調べてみた。

- a
    - CPUがArmのAWS Gravitonプロセッサを使ったやつ
    - AWSのaと覚えよう
- c
    - CPU処理に特化している
    - CPUのcと覚えよう
- d
    - Dense-storage搭載
    - Dataのdと覚えよう
- f
    - FPGA (Xilinx UltraScale+ VU9P FPGA)搭載
- g
    - NVIDIAのGPUを搭載
    - GPUのgと覚えよう
- h
    - dと同様のストレージ系
    - 最大ローカルストレージはdの方が多いらしい
- i
    - NVMe SSDローカルストレージが提供されるファミリー
- inf
    - AWS Inferentia搭載
    - 機械学習の推論用途
- m
    - 汎用インスタンス
    - midrangeのm？
- t
    - 汎用インスタンス
    - mファミリーより低コスト
- p
    - 汎用 GPU インスタンス
    - gより高い
- r
    - 積載されるメモリの割り当て量が多い
- x
    - 巨大なメモリとCPUを備えるモデル。HPCなどの用途に向く
- z
    - 全コアのクロックを最大 4.0 GHz に維持できるファミリー

どうやらmかcが良さげな気がする。
Sudachi辞書の紹介 Part 4　-分割情報（体言）-

[第1回の記事](https://qiita.com/sakamoto_mi/items/4b55898aa221c290f411)
[第2回の記事](https://qiita.com/sakamoto_mi/items/c1787973dd1a591c9957)
[第3回の記事](https://qiita.com/sakamoto_mi/items/9b5105cb7881442a716c)


『Sudachi辞書の紹介』の続きです。
第3回の記事で、Sudachiの分割モードおよび分割情報の概要について紹介しました。
今回は、分割情報の続きとして、体言系の分割情報について、もう少し詳細に見ていきます。


## 前回のおさらい

Sudachiには、[A, B, C, 3つの分割モード](https://github.com/WorksApplications/Sudachi)があり、辞書登録されている複合語を、短い単位に分割することができます。そのための辞書情報が分割情報です。
分割情報には、"A単位分割情報" と "B単位分割情報" があります。"A単位分割情報"は、Sudachiにおける最も短い単位に分割する情報、"B単位分割情報"は、接辞付き相当の長さに分割する情報です。


## 分割情報の付与対象

複合語に分割情報を付与します。
ここでいう複合語とは、

* 漢語については、3字以上の語を複合語とします。2字熟語は単独の語として扱います。
* 外来語については、原語表記が2語以上のもの（スペースを挟んで記述される）を複合語とします。和製英語についても同様です。
* 和語については、結合している語数にかかわらず基本的に単独の語として扱いますが、語ごとに判断し複合語とする場合があります。※補足後述
* 混種語については、基本的に複合語とします。ただし「 1漢字（漢語）+ 和語1語 」から成るものは単独の語として扱います。
* 慣用句については、複合語とします。
* 複合語の略語は、単独の語として扱います。


例）
|　|複合語|単独の語|
|:---|:---|:---|
|漢語|乗馬服、駐車違反、切磋琢磨|乗馬、駐車、違反、切磋、琢磨|
|外来語|テニスコート、サマータイム|トムキャット、ライフライン|
|和語|菜種油、吊るし柿、うがい薬、錆止め|親知らず、割り引き、雨宿り、しとしと|
|混種語|生ビール、蚊取り線香、自己PR|手製、重箱、荷物、気持ち、支払い|
|慣用句|痩せの大食い、火に油を注ぐ、転ばぬ先の杖||
|正式名称と略語|安全保障理事会、パーソナルコンピューター|安保、パソコン、PC|


## 分割情報の基本方針

* A単位またはB単位の構成語に分割します。

|見出し|A単位分割情報|B単位分割情報|
|:-----|:---|:---|
|自動運転モード|自動/運転/モード|自動/運転/モード|
|冷凍みかん|冷凍/みかん|冷凍/みかん|
|業務用エアコン|業務/用/エアコン|業務用/エアコン|
|業務用|業務/用|--|
|がん対策基本法|がん/対策/基本/法|がん/対策/基本法|
|基本法|基本/法|--|
|国際基督教大学|国際/基督/教/大学|国際/基督教/大学|
|基督教|基督/教|--|
|JR東日本|JR/東/日本|JR/東日本|
|東日本|東/日本|--|
|支払い請求書|支払い/請求/書|支払い/請求書|
|請求書|請求/書|--|
|痩せの大食い|痩せ/の/大食い|痩せ/の/大食い|

※"/" は、構成語の境界。以下同様。


## 顕著なカテゴリについて特記

### 人名

* 姓と名に分割します。（A単位でもB単位でも同様です）

|見出し|A単位分割情報|B単位分割情報|
|:-----|:---|:---|
|渋沢栄一|渋沢/栄一|渋沢/栄一|
|リオネル・メッシ|リオネル/・/メッシ|リオネル/・/メッシ|


### 住所地名

* 「都,道,府,県,市,町,村,州」を含む単位はB単位とし、これらの前で区切った単位をA単位とします。

例
|見出し|A単位分割情報|B単位分割情報|
|:-----|:---|:---|
|東京都三鷹市中原|東京/都/三鷹/市/中原|東京都/三鷹市/中原|
|東京都|東京/都|--|
|三鷹市|三鷹/市|--|
|ニュージャージー州|ニュージャージー/州|--|


### 駅名

* 「駅」の前で分割します。（A単位でもB単位でも同様です）

|見出し|A単位分割情報|B単位分割情報|
|:-----|:---|:---|
|新宿駅|新宿/駅|新宿/駅|
|那須塩原駅|那須塩原/駅|那須塩原/駅|


### 動植物名

* 動植物の名称は分割しません。
* 「親～」「子～」は、「親」「子」で区切った単位をA単位とします。
* 動植物名を含む比喩表現は分割しません。


|見出し|A単位分割情報|B単位分割情報|
|:-----|:---|:---|
|カジキマグロ|--|--|
|春虎の尾|--|--|
|親ツバメ|親/ツバメ|--|
|子海豚|子/海豚|--|
|タコ足|--|--|
|とんぼ返り|--|--|


## 和語について補足

上で述べたように、

> 和語については、結合している語数にかかわらず基本的に単独の語として扱いますが、語ごとに判断し複合語とする場合があります。

とする方針ですが、そもそも和語のみで結合するケースは、ほとんどが2語の結合です。多くてもせいぜい3語までです（例「火打ち石」「底引き網」）。これより多い語数になると、句になります（例「身から出た錆」「弱り目に祟り目」）。
混種語になれば、バリエーションは格段に増えます（例「引換券」「打切補償」「生コン車」「お好み焼きソース」「現金自動預け払い機」…）。

複合語と見なす（＝分割情報を付ける）基準は、構成語が検索に有用かどうかで判断しています。
例えば「菜種油」「うがい薬」は、「菜種/油」「うがい/薬」とすることで、「菜種」「油」、「うがい」「薬」で検索できます。なお、「菜種」を「菜」「種」の単位にまで分割する必要はないと考えます。

概して、漢語系複合語や混種語系複合語は、構成語の意味がそのまま継承されていますが、和語による結合の場合は、構成語から全体の意味を推測できないものも多くあります。それが、"結合している語数にかかわらず基本的に単独の語" とする理由です。
和語を含む混種語の場合でも、和語部分については同様です。例えば「お好み焼きソース」は、「お好み焼き」と「ソース」から成りますが、「お好み焼き」をさらに構成語に分けることはせず、一塊の語と見なしています。


以上、今回は、体言系の分割情報について見てきました。
次回は、用言系の分割情報について紹介します。今回あえて触れなかった転成名詞については、用言との絡みで、次回お話したいと思います。
知らなかったCookieの2つの属性について

Cookieの操作で初めて知ったことがあったので共有と備忘録の意味を込めて記事にします。

業務でCookieの有無によってDOMの操作（表示切り替えなど）を行うこともしばしばあると思います。
その時に「何で表示がきりかわらないんだ？」となってその理由がCookieの属性によるものでした。


## Cookieの属性について
Cookieには　2つの属性があります。
JavaScriptの観点から見ると2つの属性は`document.cookie`でアクセスできるかできないかの違いがあります。

JavaScriptでアクセスするためには`Secure`で追加する必要があります。

:::note alert
ただ、アクセスされてしまう危険性があるのでCookieの付与する際の処理は十分な注意が必要です。
:::

https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies

Cookieを操作する時には属性によってJavaScriptでは操作できないので注意してください！

## おまけ：Cookieを操作するときの便利なライブラリ
簡単にCookieの取得処理がかけます。

https://github.com/js-cookie/js-cookie

```javascript:ライブラリを使う前
const result = new Array();
const allCookies = document.cookie;

if(allCookies) {
  const cookies = cookies.split('; ');
  for(let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i].split('=');
    result[cookie[0]] = decodeURIComponent(cookie[1]);
  }
}

if(result['hoge']) {
  // 特定のcookieがあった時の処理
}
```

```javascript:ライブラリを使った後
import Cookies from 'js-cookie';
const cookie = Cookies.get('hoge');

if(cookie) {
  // 特定のcookieがあった時の処理
}
```
Jest React TypeScript デバッグツール　logRoles

# 概要
デバッグツールとして、ReactTestingLibraryのlogRolesメソッドを導入します。

# logRolesでできること
テスト完了時にテスト対象の情報をコンソール上に表示します。
今回の場合に当てはめるとテスト完了時に要素、名前、色をコンソール上に表示します。。

# 実装

## React Testing Libraryの導入
```bash
npm install --save-dev @testing-library/react
```

## logRoleの実装
赤色のボタンを作成するコードです。
### プロダクトコード
``` App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div >
    <button style={{backgroundColor: 'red'}}>Change to blue</button>
    </div>
  );
}

export default App;

```

### テストコード
ボタンの色が赤色であることを確認するテストコードです。

Rolelog有りの場合
``` App.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import { logRoles } from '@testing-library/react';
import App from './App';


test('button has correct initial color', () => {
    //コンテナ化する
	const { container } = render(<App />);
	logRoles(container);

    // find an element with a role of button and text of 'Change to blue'
   const colorButton = screen.getByRole('button',{ name:'Change to blue' });

   //　ボタンの初期色が赤色であることを確認
    expect(colorButton).toHaveStyle({backgroundColor: 'yellow'})
});

test('button turns blue when clicked', () => {});

```

Rolelog無しの場合
``` App.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';


test('button has correct initial color', () => {
	render(<App />);
    // find an element with a role of button and text of 'Change to blue'
   const colorButton = screen.getByRole('button',{ name:'Change to blue' });

   //　ボタンの初期色が赤色であることを確認
    expect(colorButton).toHaveStyle({backgroundColor: 'yellow'})
});

test('button turns blue when clicked', () => {});

```

## 動かしたときの挙動
左側側がIDE,右側がreactの様子です。
テストコードのredをyellowに変えてPASS Failを比較しています。コンソール画面に注目
### logRoleの場合

![RolelogPattern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/e63ee51b-a827-a918-f9f2-d2fbf66dc73e.gif)

### logRoleを使っていない場合

![NoRolelogPattern.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/91b23a5a-3969-c265-8e3e-7fd2b4e68648.gif)

## 二つの比較（静止画）
左側がlogRole有　右側がlogRole無し
Passする場合、logRole有だとボタンの情報が表示されるが、logRoleは表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/48f0ec4d-7f53-d3f2-bcb1-3be06507481d.png)

Failの場合もPassと類似した結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/9ff42472-74e6-6c23-7416-4c88acdef823.png)



## github


# 参考
section2 14
https://www.udemy.com/course/react-testing-library/

logRoles リファレンス

https://testing-library.com/docs/dom-testing-library/api-debugging/#logroles
自動テストを浸透させたかった（できなかった）

(2023/02/07追記)
[Qiita Advent Calendar 2022 プレゼントカレンダー 結果発表！](https://blog.qiita.com/adventcalendar-2022-presents-winners/#:~:text=%E3%81%A6%E3%81%84%E3%81%8D%E3%81%BE%E3%81%99%EF%BC%81-,%E3%83%90%E3%83%AB%E3%83%86%E3%82%B9%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE%EF%BC%88T%2DDASH%EF%BC%89,-%E5%AF%BE%E8%B1%A1%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC)にて`記事投稿ありがとう 参加賞`に当たりました。
バルテス株式会社様本当にありがとうございます！

# 自動テスト導入の経緯

これは前社で開発に携わっていたプロジェクトに自動テストを導入し、広げることができなかった経緯をまとめたものです。
このプロジェクトではRailsで作られた動画配信プラットフォームを開発、運営していました。動画を見た視聴者数やPRページといった機能を持っており複雑なシステムが出来上がっていました。機能開発、バグ修正を隔週でリリースしておりとても忙しいプロジェクトでした。
複雑なシステムゆえにバグを含むコードが増えており、バグ修正の修正を緊急リリースするといった危ない橋を渡る時もありました。
ある時期から`手動テスト`を徹底的にしようとPLから号令がかかったので、更新が少なくなり開発が停滞していきました。これを打破するために自動テストを導入することになりました。
私は自動テストを別プロジェクトで自動テストを導入した経験を買われこのプロジェクトでも導入することになりました。

# 自動テストの導入

RubyのテストフレームワークといえばRSpecとminitestがあります。テスト結果の見やすさ、テストの階層化が容易な点からRSpecを選択しました。
`x.to eq y`という直感的に理解しやすいアサーションの書き方も好きな点です。
導入自体はGemからライブラリを追加し、テスト用DBとの接続、Fixtures、Specファイルを記述するだけだったのでスムーズでした。
この時プロジェクト内にいる開発者で自動テストの経験者は私だけだったのでサンプルで作成したSpecファイルに丁寧にコメントを書きファイルを見れば書けるようにし、導入準備は万全でした。

# それからどうなった？

テスト導入後PRを確認するとテストコードが追加されてないリクエストが出ていました。当然ですが、作業者にコード追加の依頼を出しました。が、PLから重要な修正なのでリリースを急ぐためテストコードは省略となりそのままマージされてしまいました…
そのような状態が続き、アプリのコード量は増えるがテストコードは増えない状況が常態化してしまいました。
私自身は細々とテストを書いていましたが、残念ながらプロジェクトを離脱することになり自動テストを普及させるミッションは失敗してしまいました。

# 何が悪かったのか
プロジェクト離脱直前のミーティングでメンバーにテストを書かない理由を聞いてみると下記の点が上がりました。

- 時間がない
- 書き方がわからない
- 書く理由がわからない

## 時間がない

コロナの流行で動画配信プラットフォームの需要が増加し、開発が忙しくなったため、新しい知識を習得する時間がなったことが原因でした。
CEO、営業からの催促が凄かったのでしょうがない部分ではありました。

## 書き方がわからない

これは時間がないため知識習得期間が取れなかったためです。また、モノリシック構造になっていたため、ViewでModelを直接呼び出していたりと複雑な処理になっていたことも原因かなと思います。
Cookieに保存した値を頻繁に呼び出す構造になっていたため、事前処理の設定も手間がかかり大変だった思い出があります。
このプロジェクトのテストを初心者に書かすことはハードルが高ったように思いました。週1時間程度でいいので勉強会を開けばよかったと今更ながら思いました。

## 書く理由がわからない

これは単純に`テストコードを書くことはソフトウェアの品質を上げることになり、結果的に開発期間が短くなる`ことを伝えきれなかったことが原因です。私のエバンジェリスト力不足が原因です。

# まとめ

- テストコードは未来の自分のために積極的に書こう！
- できればプロジェクト立ち上げと当時に書くと導入コストが下がる
- TDDはイイゾ

拙文最後までお読みいただきありがとうございます。
気軽にいいね！、Twitterフォローをお願いします。
VSCode 最短インストール　Windows編

## 目標
- コマンド一発でVSCodeをインストールする
    - wingetを使用
    - コンテキストメニューへの追加設定も行う
- （個人的に便利だと思う初期設定を行う）

## 1. インストール
1. PowerShellを開き，次のコマンドを実行
    ```:PowerShell
    winget install vscode --override "/silent /mergetasks=""addcontextmenufiles,addcontextmenufolders"""
    ```

## 2. オートセーブ設定
1. Ctrl + , で設定を開く
2. 検索窓に`files.autosave`と入れる
3. Auto save を After Delayに変更

## 3. 改行コードの設定
1. Ctrl + , で設定を開く
2. 検索窓に`files.eol`と入れる
3. Eolの設定を`/n`に変更する
InfluxDB v1.8: データベースのバックアップとリストア

参考ページ
[Back up a specific database](https://docs.influxdata.com/influxdb/v1.8/administration/backup_and_restore/#back-up-a-specific-database)
[Restore a specific database](https://docs.influxdata.com/influxdb/v1.8/administration/backup_and_restore/#restore-a-specific-database)

## バックアップ

```bash
influxd backup -portable -db example /tmp/backup
```

実行結果

```text
$ influxd backup -portable -db example /tmp/backup
2022/12/08 09:56:35 backing up metastore to /tmp/backup/meta.00
2022/12/08 09:56:35 backing up db=example
2022/12/08 09:56:35 backing up db=example rp=autogen shard=9 to /tmp/backup/example.autogen.00009.00 since 0001-01-01T00:00:00Z
2022/12/08 09:56:35 backup complete:
2022/12/08 09:56:35 	/tmp/backup/20221208T005635Z.meta
2022/12/08 09:56:35 	/tmp/backup/20221208T005635Z.s9.tar.gz
2022/12/08 09:56:35 	/tmp/backup/20221208T005635Z.manifest
```

## データベースを削除

データベースがあることを確認

```bash
influx -execute 'show databases'
```

削除

```bash
influx -execute 'drop database example'
```

削除されたことを確認

```bash
influx -execute 'show databases'
```

## リストア

```bash
influxd restore -portable -db example /tmp/backup
```

実行結果

```text
$ influxd restore -portable -db example /tmp/backup
2022/12/08 10:00:28 Restoring shard 9 live from backup 20221208T005635Z.s9.tar.gz
```

データの確認

```text
$ influx -precision rfc3339
Connected to http://localhost:8086 version 1.8.10
InfluxDB shell version: 1.8.10
> use example
Using database example
> show measurements
name: measurements
name
----
Data
> 
```
【Unity】toioのSimulatorをUnityEditorでのみ読み込む

## 本記事について

[Sample_ConnectType](https://github.com/morikatron/toio-sdk-for-unity/tree/v1.5.1/toio-sdk-unity/Assets/toio-sdk/Samples/Sample_ConnectType)のサンプルでは、ConnectTypeを切り替えることによって、
UnityEditorではSimulator, iOSアプリでは実機のCubeと切り替えることが可能。

ただ、iOSアプリでSimulatorを動かさないのであればそもそもCubeやStageをSceneに置きたくない。
=> SimulatorをSceneごと分離できるかどうかやってみよう

## 環境
mac os 12.5 silicon
toio SDK for Unity v1.5.1
Unity 2021.3.7f1

## 結論
![スクリーンショット 2022-12-07 20.09.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/4b8bd45d-fb6f-d35d-16b6-92723e06e01a.png)

特に問題なくUnityEditorではSimulation, iosアプリではSimulationSceneをロードせずに実機Cubeを動かすことができた。

## 別シーンのCubeに接続できるか調査

[ドキュメント 3.1. 検索(Scanner)](https://github.com/morikatron/toio-sdk-for-unity/blob/v1.5.1/docs/sys_cube.md#31-%E6%A4%9C%E7%B4%A2scanner)

toioの検索はScannerクラスが行なっているとのこと。

> シミュレータ実装：
シミュレータのCubeプレハブから作成された GameObject を検索

とあるのでその具体的な部分をコードから読み解く。

[検索箇所](https://github.com/morikatron/toio-sdk-for-unity/blob/v1.5.1/toio-sdk-unity/Assets/toio-sdk/Scripts/Cube/CubeScanner.cs#L252) 

[Object.FindObjectsOfType](https://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html)を使ってるので、別シーンからでも読めるはず。
(toio SDKではGameObject.FindObjectsOfTypeと書いているけれど, [GameObject](https://docs.unity3d.com/ScriptReference/GameObject.html)で定義されたクラスメソッドではないため本記事ではObject.FindObjectsOfTypeと呼ぶ)

## シーンの用意

2つのシーンを作る

ToioScene: CubeManagerを置く。
SimulationCubeScene: StageとCubeを置く。

#### SimulationCubeScene

Sample_ConnectType.sceneをコピー
「scene」オブジェクトについてる「Sample_ConnectType」コンポーネントを外すor非アクティブにする。
StageにCameraとEventSystemがあるが、これらはSimulationCubeSceneに配置したくないのでStageから消したい。
が、オリジナルのプレハブを変えると他のSample動かなくなるため、Stageプレハブを別フォルダにコピーしてから編集。

![スクリーンショット 2022-12-07 20.46.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/2d80dafe-3735-85aa-28be-ea62df99ebc5.png)

これでSimulation側の準備OK


#### ToioScene

1. SceneロードしたらSimulationCubeSceneを追加
2. CubeManager起動

実際に私が動かしたコードではなく、本記事用に書いたコードだが多分以下のような感じで動く

```.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using toio;
using UnityEngine.SceneManagement;
using Cysharp.Threading.Tasks;

public class ToioSceneSample : MonoBehaviour
{
    public ConnectType connectType;

    CubeManager cm;
    async void Start()
    {

#if UNITY_EDITOR
            await SceneManager.LoadSceneAsync("SimulationCubeScene", LoadSceneMode.Additive);
#endif

        // ConnectType.Auto - ビルド対象に応じて内部実装が自動的に変わる
        // ConnectType.Simulator - ビルド対象に関わらずシミュレータのキューブで動作する
        // ConnectType.Real - ビルド対象に関わらずリアル(現実)のキューブで動作する
        cm = new CubeManager(connectType);
        await cm.MultiConnect(2);
    }

    void Update()
    {
        foreach(var cube in cm.syncCubes)
        {
            cube.Move(50, -50, 100);
        }
    }
}
```

## 注意点
SimulationSceneを読み込まないのはできたけど、toio SDKがResourcesを使ってるのでこれらのリソースが全てアプリに入ってしまう。
[Resources for simulator included in build even if simulator not used. シミュレータ使わないのに関連ファイルがビルドに含まれる #262](https://github.com/morikatron/toio-sdk-for-unity/issues/262)

ビルド時にフォルダ名変えて差分多く出るのは好みじゃないので、
現状手っ取り早く対応するなら「Simulatorを使わない」が一番な気はする。
rails server したところ sqlite3関係のエラーが出たときの対処法

```$ rails new app_name```した後```$ rails s```したところ、

```
Puma caught this error: Error loading the 'sqlite3' Active Record adapter. Missing a gem it depends on? can't activate sqlite3 (~> 1.3.6), already activated sqlite3-1.4.0. Make sure all dependencies are added to Gemfile. (LoadError)
```
こんなエラーが出てしまいました。


https://qiita.com/Kta-M/items/254a1ba141827a989cb7

上記の記事のようにRails側のsqlite3のバージョン指定が原因のようなので、`sqlite3`のバージョンを変えてみたのですがうまくいない。

それならばと、rubyのバージョンの方を変えてみたところエラーが出なくなりました。

***rubyのバージョンの変え方***
①現在のバージョンを確認する
```
$ ruby --version
```

②rbenvでインストールしてあるrubyのバージョン確認する
```
$ rbenv versions
```

③rbenvでインストールできるrubyのバージョンを確認する
```
$ rbenv install -l
```

④インストール
```
$ rbenv install 2.1.5
```

⑤インストールしたバージョンに変更する
```
$ rbenv local 2.1.5
$ ruby --version
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin12.0]
```
備忘録８

日本時間の表示を揃える（汎用できる）	
	
SharePointリストの「更新日時」などシステム値とPowerapps上での時間表示が異なるので、Powerapps上での表示に統一する	
	
更新日のデフォルト表示	
	
	
	
DataCardValue***のプロパティで「表示」を「オフ」にする	
	
	
	
	
上部メニューの「挿入」→　「入力」→　「ラベル」をクリック。　データーロックを解除して挿入する	
	
	
	
	
	
	
Label＊＊　が挿入されるので、適宜サイズや位置を編集	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
関数の左辺で「Text」の関数を全部消して、「Text(DateTimeValue(DataCardValue＊＊.Text), "m/d/yyyy h:mm AM/PM","en-US") 」にする	
	
	
	
	
	
Text(DateTimeValue(DataCardValue20.Text), "m/d/yyyy h:mm AM/PM","en-US")	
	
	
	
	
	
	
時刻表示がPowerapps上でのほかの時刻表示と同じ形式となる
備忘録７

編集が必要な関数（汎用できるが、現状はサポートはされていない。ネットではこの方法が用いられている）	
	
「通貨」はSharepoint リスト上で問題ないが、Powerappsでは通貨表示できない仕様のためPowerapps上で実装する	
	
通貨表示したい親カードの関数の初期値は「Parent.Default 」のため、数字表示になっている	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
親カードの関数の左辺で「Default」の関数を全部消して、「Text(ThisItem.'支出金額(経費に関する場合のみ)',"￥###,##") 」にする	
	
	
	
	
プロパティの「書式」を「テキスト」に変更する。　通貨のままにしない。	
	
	
	
通貨表示に変わる	
	
	
	
	
	
	
	
	
特にエラーとはならない。
備忘録６

編集が必要な関数（独自性がつよい）						
						
「備考」はSharepoint リスト上で日付の差分を数式で出しているが、Powerappsに集計値は持ってこれない仕様のためPowerapps上で実装する		

＝DATEIF(申請日,完了日,"D")					
	Sharepoint リスト上の設定

				
    
								
						
						
						
						
親カードの関数の左辺で「Text」の関数を全部消して、「DateDiff(DateValue(DataCardValue●), DateValue(DataCardValue▲) )」にする						
						
						
						
						
						
						
						
						
						
						
						
						
リストと同じ値が表示される
フロントエンドエンジニアになるんやったらアウトプット怠ったらあかんで。

25日間アドベントカレンダーを1人で埋めてみて感じたことを最後に共有したいと思います。

## 改めてのお礼
購読してくださった方、いいねやコメントくださった方**本当にありがとうございました**。
1つ1つが励みになり今日までアウトプットができました。

## 1人アドベントカレンダーをやってみて
個人としては思い切ったチャレンジでした。
子供が産まれ時間がないと感じながらも**本当に25日インプットとアウトプットを続けられるか不安でした**。

電車、バス、ちょっとした待ち時間など1分1秒をインプットに当てる生活してきました。
今では**息をするごとくインプットするのが習慣になり始めてきた**と感じています。

アドベントカレンダーという取り組みは、**何かを習慣化するにはとても良いフレームワーク**だと思いました。

:::note info
正直かなりキツかったですが、毎日新しいことをインプットすることで成長できている実感を持てました！
:::

## アウトプットが大切な理由
アドベントカレンダーの取り組みを通して自分の**知識が浅いこと**や**アウトプットの大切さ**に気がつきました。
アウトプットが大切な理由は2つあると思います。

- 理解が深まる
- インプットが加速する

### 理解が深まる
アウトプットする時に自分の知識に間違いがないか、曖昧な理解のものは調べ直します。
そうすることで**知識の深度や幅が広がり、これまで理解できていなかったことが理解できる**ことです。

:::note info
成長が停滞していると感じたならどんな形でもいいのでアウトプットしてみるのがいいと考えます！
:::

### インプットが加速する
人に共有することで共有したことが古い情報だったり、間違っていたりした場合フィードバックとして返ってきます。

リファレンスを読んで理解するより圧倒的にわかりやすいので**知識のアップデートがめちゃくちゃ早い**です！

:::note info
共有することのハードルの1つに「間違ったことを発信するのが嫌」というのがあると思います。
知らないことがあるのは当然です。
恐れず共有して、フィードバックをもらってください！
:::

アウトプットは知識を深めるだけでなく、誰かの持っている知識を引き出して自分のものにできることに気がつきました。

なのでアウトプットはとても大切だと考えています。

## アウトプットに身が入らない場合
インプットしたいけど、いまいち身が入らなくて困っている人もいると思います。

:::note info
記事を書くことではなく、**誰かに今日知ったことを共有する**ことから始めてほしいと思います。
:::

口頭でもチャットツールで自分の思ったことを共有する場を作っても良いですし、SNSでもいいです。
昨日読んだマンガ、今朝見たニュース、ブログの記事なんでも良いです。
まずは**誰かに何かを伝える**ことを癖づけることから始めればいいと考えています。

:::note info
個人として**大切にしている考え方は「明日からやる」ではなく「今日だけやる」という気持ち**です。
人は何かと理由をつけて怠ける生き物だと思っています。（自戒も込めて）
:::

自分をコントロールする術も身につけられるとより素晴らしいと思います。
一緒に頑張っていきましょう！


## まとめ
次は、インプットとアウトプットが一過性のものにならないために「定着」させることを目指したいと思っています。

ライフステージや家庭の状況によってインプットに使える時間は限られてきます。
だからといって**諦める理由にはならない**とも感じます。

私が頑張ろうと行動する時に思い出すマンガのセリフを紹介したいと思います。

> 日本一にもなってへん俺らが去年を・昨日を守って明日何になれる？
何かひとつでいい。今日挑戦しいや。
引用：ハイキュー 稲荷崎高校監督のセリフより

これからもインプットを怠らず、技術者としての高みを目指し挑戦していきます！

ここまで読んでくださり誠にありがとうございました！
メリークリスマス🎄そして良い年を迎えてください！🎍
備忘録５

申請日など、初期状態を空白にするカスタマイズ（汎用できる）	
	
前作業で追加したDatePicker＊は、日付が表示される	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
「DatePicker＊＊」の関数の左辺で「 InputTextPlaceholder 」の関数を全部消して、「If(IsBlank(Self.SelectedDate), Text(" ")) 」にする	
	
	
	
	
	
	
	
	
日付がブランクになる	
	
	
	
	
	
新規登録時に日付欄がブランクになる	
	
＊日付入力項目について、作業を繰り返す
UIKitとCombineを使ってデモ作成

### 概要
`Combine`と`UIKit`を組み合わせて使う時のメモです。
`SwiftUI`と`Combine`を組み合わせた実装経験はあったのですが、`UIKit`と一緒に使ったことがありませんでした。
今回、`UIKit`と`Combine`を一緒に使ってデモを作成してみます。

### 環境
`macOS Monterey 12.6`
`Xcode 14.1`

### 主な使用技術
`UIKit`
`Combine`

### 完成形
想定しているのは、GitHubのリポジトリを検索・表示するアプリです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/e7dc2718-044f-d988-57ce-cf9d1f489096.png" width="200" />

### ざっくりとした流れ
`UITableView`の組み方や外部との通信の箇所は割愛します。
最後に全体のソースコードを載せるので、是非確認してみください。

#### ディレクトリ構造
`UITableView`を表示する`HomeViewController`とそれに対応する`HomeViewModel`があります。
`HomeViewController`にGithubのリポジトリ一覧を保持し、`HomeViewController`でそれを表示する感じです。

#### `ViewModel`の実装

必要な箇所だけ抜き出します。
通信をし、レスポンスを受け取ったタイミングでリポジトリの一覧を更新します。

```swift:HomeViewModel.swift
import Combine

class HomeViewModel {
    ...
    private(set) var githubRepositoriesSubject: CurrentValueSubject<[GitHubRepository], Never> = .init([])
    ...

    private func updateGithubRepositores() {
        ...
        let response = try await apiService.searchGithubRepository(query: query)
        let repositories = response.items
        githubRepositoriesSubject.send(repositories)
        ...
    }
}
```

#### `ViewController`の実装

`ViewModel`からの通知を受け取り次第、テーブルを更新します。

```swift:HomeViewController.swift
import Combine

class HomeViewController: UIViewController {
    ...
    private let viewModel: HomeViewModel = .init()
    private var cancellables: Set<AnyCancellable> = []
    ...

    init() {
        subscribeGithubRepositores()
    }

    deinit {
        cancellables.forEach { $0.cancel() }
    }

    private func subscribeGithubRepositores() {
        viewModel.githubRepositoresSubject
            .receive(on: DispatchQueue.main)
            .sink { [weak self] _ in
                guard let self = self else { return }
                self.tableView.reloadData()
            }
            .store(in: &cancellables)
    }
}
```

### まとめ
全てのソースコードは[こちら](https://github.com/h-taro/UIKit-MVVM)にまとめてあります。
`Combine`に慣れてくるとクラス間の通知にすごく重宝します。

### 参考記事
https://www.fuwamaki.com/article/255
備忘録４

日付入力のカスタマイズ（汎用できる）	
	
「申請日」のデフォルトでは、以下のデーターカード状態	
DataCardValue***のプロパティで「表示」を「オフ」にする	
	
	
	
	
	
	
	
	
	
	
上部メニューの「挿入」→　「入力」→　「日付の選択」をクリック。　データーロックを解除して挿入する	
	
	
	
	
	
	
	
	
	
DatePicker＊＊　が挿入されるので、適宜サイズや位置を編集	
	
	
	
	
	
	
	
	
	
	
申請日＊(親のカード)の関数の左辺で「 Update 」の関数を、「 DataCardValue＊＊ 」から、追加した[DatePicker＊]に変更する	
DatePicker1の１とかは挿入順の番号なので、カード内で揃える必要はない	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
DatePicker＊の関数の左辺で「 DefaultDate 」の関数を、「 Today() 」から、[Parent.Default]に変更する	
	
	
	
	
＊承認完了希望日にも同様の作業を行う
備忘録３

編集されたくない項目を編集不可にする	
	
自動で登録される項目を編集不可にする	
	
「確認No」の関数の左辺で「DisplayMode」の関数を全部消して、「View 」にする		
	
	IDの桁数
	
	@{formatNumber(variables('ID'), '00000000000', 'ja-jp')}
配番の桁数

@{formatNumber(variables('確認'),'00000000000', 'ja-jp')}


@equals(triggerBody()?['StopRun'],null)


@not(equals(float(triggerBody()?['{VersionNumber}']),1.0))


If(IsBlank(Self.SelectedDate), Text(" "))


If(IsBlank(Self.SelectedDate), Text(Date(2001,12,31), Self.Format, Self.Language))

@format@[variabled(@{variables('確認')}),'00000000000','ja-jp')]



@format@{variables('確認'), '00000000000', 'ja-jp')}