OmniAICreator/Qiita-1.07M huggingface dataset:
VSCode×GoでGOROOT or GOPATHが見つからない大量エラーの解消。

こんにちは。

フロントエンドエンジニアでバックエンドも頑張りたいみつです:relaxed:

GoをVS Codeで書いているのですが、直接的な問題もなく見て見ぬふりをしていた下記のエラー。

```
could not import XXX (cannot find package "XXX" in GOROOT or GOPATH)
```

赤い線が多すぎてついに、VS Codeでエラータブでエラー数が10kに到達したのでそろそろやばいでしょ...という焦りと何が起きていたんだろうを記事にしたものです。

ちなみに、自分の場合は、Goのインストールも出来ているのと、ターミナルでGoを認識もしていたので、go.modファイルがあるディレクトリでワークスペースを開くだけでエラーの文言は消えました。

## 目次
- [最近起きてた嫌なこと:frowning2:](#最近起きてた嫌なことfrowning2)
- [BrokenImportってなんだろう？](#brokenimportってなんだろう)
- [GOROOTとかGOPATHってなんだろう？](#gorootとかgopathってなんだろう)
- [「Using Go Modules」ドキュメントを読む](#using-go-modulesドキュメントを読む)
- [VS Codeのエラーに対応する。](#vs-codeのエラーに対応する)
- [まとめ](#まとめ)

## 最近起きてた嫌なこと:frowning2:
terminalで`go version`コマンドを叩くと、Goを認識する。

ただ、エディタ画面や問題のタブにはBrokenImportの大量エラーが発生している。

[terminal画面]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/9289c36a-4ea0-a632-3f2b-9d44a4b6faae.png)

[エディタ画面と問題タブ]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/d81c253e-cdb1-c4f5-3135-6ea8245a575e.png)

## BrokenImportってなんだろう？
```go
// BrokenImport occurs when importing a package fails.
//
// Example:
//  import "amissingpackage"
BrokenImport
 ```
 
BrokenImportは、ファイルインポートに失敗した時に起きる。

うん、それはそう。

ImportがBrokenしているみたい。

## GOROOTとかGOPATHってなんだろう？
```
could not import XXX (cannot find package "XXX" in GOROOT or GOPATH)
```

> GOROOT は、Go SDK の場所を定義する変数です。
異なる Go バージョンを使用する予定がない限り、この変数を変更する必要はありません。

> GOPATH は、ワークスペースのルートを定義する変数です。

https://pleiades.io/help/go/configuring-goroot-and-gopath.html

GoLandドキュメントによると、GOROOTはGo SDKの場所を定義する変数。
GOPATHは、ワークスペースのルートを定義する変数。

envを見ると、GOPATHもGOROOTも設定されるね。よしよし。
```sh
> go env
・・・
GOPATH='/Users/okada.mitsuhiro/go'
GOROOT='/opt/homebrew/Cellar/go/1.21.4/libexec'
・・・
```

自分の場合、異なるGoバージョンを使用することはあまりなさそうなので、GOPATHが認識されずにBrokenImportを起こしているのかなというところです。

## 「Using Go Modules」ドキュメントを読む
なるほどなと思ったところだけをピックしてみます。

>A module is a collection of Go packages stored in a file tree with a go.mod file at its root.

モジュールは、ファイルツリー内のGoのパッケージ群。

>As of Go 1.11, the go command enables the use of modules when the current directory or any parent directory has a go.mod, provided the directory is outside $GOPATH/src.

go commandのモジュールが有効になるのは、カレントディレクトリか親ディレクトリにgo.modがあるのと、$GOPATH/srcの外であることが条件。

[公式ドキュメント]

https://go.dev/blog/using-go-modules

## VS Codeのエラーに対応する。
特に何をした、というわけではないんですが・・・

go.modがあるディレクトリに移ることで、モジュールモードが有効になってPATHが認識されたという感じでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/d81c253e-cdb1-c4f5-3135-6ea8245a575e.png)

## まとめ
一番上の階層から開いて大量に赤文字のエラーが出てただけ。

でもエラーを通して、GOPATHやGOROOT、go.modなどへの理解が深められたのが嬉しいなと思います。

ただ、10kもエラーの個数が出てくるまで放置していたのもやばいなと思うのでもっと早くからエラー調査する癖をつけようと思います。

おわり。
Youtubeのチャンネルトップで自動再生されるビデオを止めるだけのchrome拡張

## 毎回止めるの面倒
タイトルの通りです。お粗末な出来ですが折角ですので公開します。
(間違ってたらすみません)YoutubeはSPA(Single Page Application)が実装されているらしくページを移動しても再読み込みするまで`content.js`が反応しないので`background.js`でurlの遷移を検知してそれを基に`content.js`を動かしてます。
## コード

```manifest.json
{
    "name": "youtubeチャンネルページ動画ストッパー",
    "description": "チャンネルページのトップで自動再生される動画を停止します",
    "version": "1.0",
    "manifest_version": 3,
    "background": {
      "service_worker": "background.js"
    },
    "content_scripts": [
        {
          "js": ["content.js"],
          "run_at": "document_end",
          "matches": ["https://www.youtube.com/*"]
        }
    ],
    "permissions": [
      "tabs"
    ]
}

```

```background.js
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
  if(changeInfo.url !== void 0){
    if(changeInfo.url.indexOf("https://www.youtube.com/channel") === 0 || changeInfo.url.indexOf("https://www.youtube.com/@") === 0){
      chrome.tabs.query({active:true, currentWindow:true}, function(tabs){
        chrome.tabs.sendMessage(tabs[0].id,changeInfo.url,function(response){
        });
      });
    }
  }
});

```

```content.js
const observer = new MutationObserver(callback);
const config = {
    childList: true,
    subtree: true
};

function callback(mutations){
    if(document.querySelector("ytd-channel-video-player-renderer .html5-video-container > video") != null){
        video = document.querySelector("ytd-channel-video-player-renderer .html5-video-container > video");
        video.addEventListener("canplay",function(){
        	video.pause();
      	})
        observer.disconnect();
    }
}

url = window.location.href;
if(url.indexOf("https://www.youtube.com/channel") === 0 || url.indexOf("https://www.youtube.com/@") === 0){
  	observer.observe(document.body, config);
}

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
    observer.observe(document.body, config);
    sendResponse();
});
```


## 終わりに
chrome拡張は私のようなプログラミング初心者でも動いて実際に役に立つ(？)ものが簡単に作れるので同じく初心者の方に是非おすすめしたいです。
そのうちchrome拡張の作り方と頻繁に使うAPI等まとめて記事にするつもりです。
学習ロードマップ作成でやる気アップ

アウトプット初心者です。初投稿です。
手始めに現在、取得に向けて学習中のJavaSilverの学習ロードマップを作成したことについて書きたいと思います。

# 作成した経緯
1.勉強で何度も挫折した経験から
　目的とゴールを定めることの必要性を感じたから
2.可視化することで計画的に学習を進められると考えたから

# JavaSilver取得をゴールにした理由

Javaに関しては数年前に会社からの指示でオンライン研修を受講したものの、技術として習得できた実感がなかったためずっともう一度学習したいという思いがあった。
習得できた実感がなかった理由として簡易的なテストはあったものの座学の振り返りテストのようなもので実践的でなかったことと、受講後、実務でJavaにふれる機会が一切なかったことだと思っている。
現状、Windows用業務システム開発がメインでVB.netとC#は書ける。
今後の会社の展開としてWeb系の開発にも力を入れていこうとしている中で、学習タイミングとして今だ！と感じたこと。
学習するからには自分の知識を証明できるものがほしいと思いJavaSilverの取得を目指すことにした。

# JavaSilver取得に向けた学習ロードマップ

1.書籍学習
　スッキリわかるJava入門
　　Java入門書のレビューを読み漁って選定
　　３周すればある程度の知識は身につくというレビューを信じて３周する

2.対策問題集
　黒本
　　認定試験対策といえば！！
　　こちらは最低２周

3.試験対策
　Oracle公式HPサンプル
　　SE11で追加されたモジュール問題は黒本でしっかり対策する

# 具体的な学習計画

スッキリ(１周目)
　　実施予定期間：５週間
　　３部構成になっていたので
　　１、２部は１週間ずつ３部は３週間でこなす想定

　スッキリ(２周目)　
　　実施予定期間：４週間　
　　２周目も１、２部は１週間、３部を２週間でこなす想定

　黒本(１周目）
　　実施予定期間：４週間

　スッキリ(３周目)　
　　実施予定期間：３週間　　
　　黒本1周目で見えた課題、弱点中心に振り返り

　黒本(２周目）
　　実施予定期間：３週間
　　１周目で間違えた問題、苦手分野中心

　Oracle公式HP
　　実施予定期間：２週間

１日に取れる学習時間は１h～1.5h
半年かけてしっかりと学習できる計画

# さいごに

実際このロードマップで学習を進めてJavaSilver取得できるのか！？
学習記録も公開していきたいです。
Proxmoxとclonezillaを使ってP2Vする

# TL;DR
物理マシンで運用していたサーバを、ハードの老朽化のためマシンを変えることになった。
これを機に、運用に柔軟性を持たせるために仮想化を行うことにした。
ハイパーバイザとしてProxmox VEを、ストレージのコピーにはclonezillaを使うことで簡単に仮想化を達成できた。

# 手順

## Proxmox

公式の手順通りにインストールを行う。

## clonezilla

USBメモリ等に書き込み起動ディスク(?)を作成する。

## 移行先の仮想マシンを作成

ほぼデフォルト設定のシンプル構成でVMを作成する。
移行元のマシンがUEFIブートの場合はBIOSをONVIFに変更するのを忘れないように注意する。

## 移行元マシンの準備

今回は移行元のディスクサイズが移行先と同一であったため、パーティションの縮小が必要になった。

幸いclonezillaには`resize2fs`コマンドが組込まれていたので、clonezillaの起動ディスクで起動後にコマンドラインに移行し`resize2fs`を実行することで縮小ができた。

## clonezillaの実行(移行元マシン)

clonezillaを起動後のモード選択で`remote-source`を選択しIPなどを指定する。
準備が完了するとコピー先からの接続待ち状態になる。

## clonezillaの実行(移行先VM)

VMの起動ディスクにclonezillaのisoイメージを指定し起動する。
モード選択で`remote-dest`を選択し移行元マシンのIPを指定するとコピーが開始される。

__※ 移行元と移行先のディスクサイズが異なる場合はパーティションテーブルを適切に設定する選択を行う__

## VMの起動

移行先のVMを再起動し動作を確認する。

# あとがき

ディスクのコピーにclonezillaを使うこととパーティションテーブルの設定でつまずいたが、結構簡単に物理マシンの仮想化を行うことができた。
TextMeshProでOSにインストールされたフォントを使いたい

こんにちはcoconeでクライアントエンジニアをしているものです。
ここ最近ローカライズについて考える機会が増えておりましてそこで得た知見を記事にしてみようかと思います。

本記事 [Cocone Advent Calendar 2023](https://qiita.com/advent-calendar/2023/cocone) 15日目の記事となります。

# 記事の内容
UIデザイナーさんに「言語毎に使用するフォントを変えたいです」と言われたときにTextMeshProでどうにか頑張ってみた知見のまとめです。

# 問題点
TextMeshProを使用する場合ダイナミックフォントを使用することがあると思います。
（ダイナミックフォントの必要性や使用方法は調べればたくさん記事があると思うので省略します）

ダイナミックフォントはRuntimeでMeshを生成するために大本のフォントデータ(.ttf等)への参照が必要となります。
ローカライズ機能を搭載したアプリで言語毎にフォントを変えたいとなるとダイナミックフォントで使用するために使用するフォントがすべて必要となってしまい使用するフォントによってはかなり大きなAssetデータを扱うことになってしまいます。
フォントをすべてビルドに含めるとアプリサイズがかなり大きくなってしまうし、AssetBundle等で配信したとしても大きなデータをダウンロードすることになってしまいます。

そこで、TextMeshProのダイナミックフォントの参照先をOSにインストールされているフォントにできれば無駄にフォントデータを持つ必要がなくなるのでは？という発想のもといろいろ試してみました。

# 環境
以下のコードではTextMeshPro `3.2.0-pre6` のversionを使用しています。

この実装をおこなった環境(Unity2022.3.10f1)ではTextMeshProの推奨versionが `3.0.6` となっており以下の実装とは少しインターフェイスが変わっているのとどうやらメモリリークが発生するという情報もあり(自分では未検証) preview versionを使用しています。
https://forum.unity.com/threads/issue-with-removing-fonts-from-fallbackfontassettable-memory-leak.1045936/

# 実装したコード
前置きが長くなってしまいがしたがとりあえず完成したコートです
```csharp
void AddDynamicFont(TMP_FontAsset baseFont, string fontName)
{
    // OSにインストールされているFontPathを取得する
    var paths = Font.GetPathsToOSFonts();

    // 取得したFontPathから使用したいフォントパスを取得する
    var fontPath = paths.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x).Contains(fontName));
    if (string.IsNullOrEmpty(fontPath))
    {
        return;
    }

    // あらかじめ生成してあるMeshと同じ設定となるようにダイナミックフォントを生成
    var fontAsset = TMP_FontAsset.CreateFontAsset(fontPath, 0, baseFont.creationSettings.pointSize, baseFont.atlasPadding, GlyphRenderMode.SDFAA, 512, 512);

    // 生成したダイナミックフォントにfallbackされるように設定
    baseFont.fallbackFontAssetTable.Add(fontAsset);
}
```

# コード解説
コメントの通りOSにインストールされているフォント一覧のパスを取得し、使用したいフォントのパスを検索しています。
当たり前ですがOS内に存在しないフォントを使用することはできないので対応するプラットフォーム毎に必ず存在するフォントを使用するか指定したフォントが存在しなかったときに使用する第2候補などがあるとより安全だと思います。
```csharp
    // OSにインストールされているFontPathを取得する
    var paths = Font.GetPathsToOSFonts();

    // 取得したFontPathから使用したいフォントパスを取得する
    var fontPath = paths.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x).Contains(fontName));
```

TextMeshProのDefaultFontAssetなどデフォルトのMeshをあらかじめ生成していると思うのでそのFontAssetと同じ設定になるようにダイナミックフォントを生成します。
512は生成するAtlasサイズです。
ダイナミックフォントを生成したら実際使用されるようにBaseとなるフォントのfallbackに設定します。
```csharp
    // あらかじめ生成してあるMeshと同じ設定となるようにダイナミックフォントを生成
    var fontAsset = TMP_FontAsset.CreateFontAsset(fontPath, 0, baseFont.creationSettings.pointSize, baseFont.atlasPadding, GlyphRenderMode.SDFAA, 512, 512);

    // 生成したダイナミックフォントにfallbackされるように設定
    baseFont.fallbackFontAssetTable.Add(fontAsset);
```

# まとめと注意
TextMeshProでOSにインストールされているフォントを使用する例の紹介でした。
フォントデータを増やすことなくOSにインストールされているフォントであれば自由に使用することができるようになると思います。

最後に注意点ですが、この実装ではTextMeshProのpreview versionを使用しており実際のメモリ消費量などはちゃんと検証していない状態となりますので参考にされる方は自己責任でお願いいたします…。
tiktokenをCrystalで使う

## はじめに

Crystalのアドベントカレンダーのネタがないので、最近Crystalで作ったツールの紹介をしています。ChatGPTをコマンドラインから使うツールの [chatgpt-cli](https://qiita.com/kojix2/items/f30cbf1120d9947d26e8)を自分用に作っているのですが、消費したトークン数が表示できないという問題がありました。その問題自体は今も解決できていないのですが、Crystalから `GTP-2` のトークン数を表示するという課題は[tiktoken-cr](https://github.com/kojix2/tiktoken-cr/)の作成である程度解決したので記事にします。

## 背景

今の社会を象徴するAIサービス「ChatGPT」を使ったことがない人はいないと思います。
このChatGPTで重要なのが「トークン」という概念です。ChatGPTは、入力された文章をトークンに分割して、それぞれのトークンに数値を割り当てます。

図：[tokenizer](https://platform.openai.com/tokenizer) で文章をトークンに分割したところ

![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/09e29b91-5f15-c23e-06f1-df539b242ff7.png)


そうすることでAIは入力と出力を処理することができます。ChatGPTが受け付けることができるトークンの数は決まっています。無料版の GPT-3.5-turboでは、最大4096トークンまで。GPT-4 では 8192トークンまで受け付けることができます。

だから、ChatGPTを利用してプログラムを生成するようなケースではこのトークン数の制限をにらめっこして、すべての処理が8192トークンに収まるようにしなければなりません。

文章とトークンの変換にはいくつかのライブラリがあります。[BlingFire](https://github.com/microsoft/BlingFire)や、[tokenizer](https://github.com/huggingface/tokenizers)、[tiktoken](https://github.com/openai/tiktoken)です。このうち、BlingFireはC++で実装されていますが、残りの２つはRustで実装されているため、Crystalから呼び出すのが難しい状況がありました。

## BlingFireのバインディングを作ってみた

僕はCrystalから利用できるTokenizerがどうしても欲しかったのでいくつか作ってみました。まず最初にBlingFireのバインディングを作りました。

https://github.com/kojix2/blingfire-crystal

Ankaneさんの[](https://github.com/ankane/blingfire-ruby)を参考にCrystalに直訳しました。

## Tiktokenのバインディングを作ってみた

さて、問題は残りの２つです。どうすればRustを呼び出せるのかわかりませんでした。

そんなときに次のフォーラムを見ました。

https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/16

CrystalからRustを呼ぶときは、まずRustのライブラリからC言語と互換性のある共有ライブラリを出力して、それをCrystalから呼べばいいということでした。

そこで、まずはtiktokenをRustのライブラリとして利用できるようにした [tiktoken](https://github.com/zurawiki/tiktoken-rs) のC APIを作成することにしました。Rustについてはほとんど何も知らなかったのですが、ChatGPTに質問＆依頼しまくって、tiktoken-rs の C APIを作りました。

https://github.com/kojix2/tiktoken-c

さらにこのC APIをRustから呼べるようにした、tiktoken-cr を作成しました。

https://github.com/kojix2/tiktoken-cr

## 最後に

Rustのライブラリは増加し続けており、RubyやCrystalといった言語では、Rustのライブラリの資産をどのように活用するべきかということが課題となっています。Rubyでは、[magnus](https://github.com/matsadler/magnus) というライブラリが開発されています。これはRustとCrystalの型の変換を容易にします。

一方でCrystalからRustを呼び出すことは簡単でなく、一度 C API に落とし込む必要があります。WASMを出力して、WASMランタイムを呼び出せばよいという議論もありますが、この場合も C API を利用する必要があるでしょう。

C言語の「関数呼び出し」を機械語でどのように表現するかルールを定めたものをABIと呼びます。今後はそういった領域も勉強してみたいと思いました。

今回紹介したリポジトリは、あまりテストされていませんので、不具合が残っている可能性はあります。そういったものをプルリクエストで指摘して頂けると嬉しいです。

よいCrystalライフを。この記事は以上です。
PLCのバッテリー交換について（MELSEC）

# PLCのバッテリーとは？

PLC（プログラマブルロジックコントローラ）はプログラムをメモリに格納して実行しますが、電源がオフになるとデータが消失します。保持するためにはバッテリーを接続する必要があります。
※バッテリー不要な型式もありますので要確認

# PLCのバッテリー交換

PLCのバッテリーは定期的に新しいものに交換が必要です。使用状況に応じて計画する必要があります。
電源OFFの時間が長いほどバッテリーの減りが早くなるので、長期間の停電が予定されている場合には事前にバックアップを取っておきましょう。

# 電源ONのままバッテリー交換しても良いの？

バッテリーの交換は必ずシーケンサの電源をOFFにした状態で実施してください。
感電やシーケンサの誤動作・故障の原因になります。

バッテリーを外した瞬間にデータが消失するわけではなく、コンデンサによって一時的にデータが保持されるようです。バッテリー交換の作業は速やかに行いましょう。


# 参考ページ

https://fa-faq.mitsubishielectric.co.jp/faq/show/13629?category_id=771&site_domain=default
Python+REST APIでGaroonから会議室が含まれるデータを抽出する。

# Garoonの指定した会議室が含まれるデータを取得する
kintoneは要素の指定に自分で指定したIDを指定できるので、garoonもそうだろうと思っていたら数字でした。
そこが分かった記念にメモをあげておきます。
ただ、なんとなく、SOAPがかっこよさそうなので、SOAPで始めましたが、requestのデータ形式の定義がうまくいかずRESTにしました。

```python: GetSchedule.py
import requests
import json

URL = 'https://（サブドメイン）.cybozu.com/g/api/v1/schedule/events'

headers = {
     # 「ログイン名:パスワード」をBASE64エンコードした値をxxxxxxxxxに指定。
    'X-Cybozu-Authorization': 'xxxxxxxxx'
}

def main():
    res=GetSchedule(5) #IDは番号（garoonで指定したIDではない）
    jres=res.json() #json形式で取り出し
    print(jres)

def GetSchedule(f_id):
    params = {
        'target':f_id, #引数で指定した施設ID
        'targetType':'facility', #ターゲットを施設に指定
        'orderBy':'start desc', #スタート時間でソート
        'rangeStart':'2023-12-01T09:00:00+09:00', #会議開始時間（範囲）
        'rangeEnd':'2023-12-31T18:00:00+09:00' #会議終了時間（範囲）
    }

    response = None

    try :
        response = requests.get(URL, headers=headers, params=params)
        
    except Exception as e:
        print(e)
    
    return response

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

# json形式に変換する前のRESPONSE番号
あと、さいしょprint(respose)をやってもResponse [200]やResponse [400]しか返ってこなくて意味が分からなかったけど、それぞれ下表のとおりです。

| Num | 意味 |
|:-:|:-|
| 200  |問い合わせ成功   |
| 400  |ちょっと何言ってるかわからない   |

ただ、Response [400]のときは、responseをjsonに変換するとエラーメッセージを返してくれます。

# 参考資料
https://qiita.com/yamashi6/items/64955fe340bd90270c9d
https://qiita.com/yamashi6/items/3a6fe96a6a2efb8a52e1

https://cybozu.dev/ja/garoon/docs/rest-api/schedule/get-schedule-events/
https://cybozu.dev/ja/garoon/docs/overview/schedule-object/#schedule-object-propetry
旧版：「IBM Cloud 構成パターン」集 （24年7月版）


<b>FYI. 最新版はこちらの記事にあります
https://qiita.com/dicekm-i/items/158e1853cfe557c5e048
</b>

## 「IBM Cloud 構成パターン」 集とは

IBM Cloud は、ウェブサイト・ウェブアプリケーションとしてはもちろん、基幹系業務アプリケーションからファイルサーバー、社内業務アプリケーション、IoT、AI/機械学習、災害対策までにいたるまで、非常に多くのお客様に数多くの用途で活用されています。

そうした中で、今回、IBM Cloudの主要サービスを利用した代表的なソリューションごとの「構成パターン」と「料金の試算例」を１つの<b>「IBM Cloud 構成パターン」</b>集という資料としてまとめましたので、ご紹介いたします。<br><br>


実際の「IBM Cloud構成パターン」集の資料がこちらになります。

<br>
<b>2024年 7月12日：第三版に更新されています！！
ただし、VMwareのVCFライセンスの箇所は更新されておりません。
もうしばらくお待ち下さい</b>

#### <INS>「IBM Cloud 構成パターン」集

<iframe src="https://drive.google.com/file/d/1w5uTXgIUksq9sBxvyuwTItyT8qIYihI6/preview" width="640" height="480" allow="autoplay"></iframe>

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRPHg7WgrTKVlO1RfJ64OBI86FpgrOJOd1MP-gCtfqfZU8dVbQTALeBWGeK4f9ckQBOWkMl1OKLHKOE/embed?start=false&loop=false&delayms=3000" frameborder="0" width="1200" height="440" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>



※こちらの資料は、24年7月版のものとなります。

<b>最新版はこちら: [https://ibm.box.com/v/ibmcloud-pattern](https://ibm.box.com/v/ibmcloud-pattern)

## 「IBM Cloud 構成パターン」集の内容

2023年12月現在、以下の25種類くらいの構成パターンが資料としてまとまっています。

#### <INS>構成パターンの一覧（目次）</INS>

<b>VPC / コンテナ基盤(OpenShift) / VMWare / PowerVS / AI (watsonx)</b> など主要ソリューションごとに章立てして構成パターンをまとめております。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239309/53484edf-cb5a-ab06-b2af-d1dd68184fb3.png)

#### <INS>各構成パターンの中身

「IBM Cloud 構成パターン」集は、それぞれの構成パターンごとに以下の２ページからなっております。

1. 構成パターンのイメージ図／構成のポイント／システム構成要素　
1. 構成パターンの概算費用

構成イメージとともに、構成するときのポイントや必要なサービスコンポーネントなどが簡単に理解できるようになっております。またそれぞれの構成パターンに対する概算費用も提示することで、費用感をイメージしやすくできるようになっております。
<br>

<b>【例：構成パターンのイメージ図/構成ポイント/システム構成要素】</b>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239309/68e4d43d-b2e1-3c01-d2d4-e0ec985c6da3.png)


<b>【例：構成パターンの概算費用】</b>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239309/cd8b16eb-b8f6-9925-b164-76cea987df9f.png)

## 「IBM Cloud 構成パターン」集のダウンロード
<b>「IBM Cloud 構成パターン」</b>集の最新版は、以下のサイトよりダウンロードできます。

https://ibm.box.com/v/ibmcloud-pattern

　<b>URL:</b> [https://ibm.box.com/v/ibmcloud-pattern](https://ibm.box.com/v/ibmcloud-pattern)


## 今後について

来年(2024年)はいろいろなところで、この <b>「IBM Cloud 構成パターン」集</b>を紹介していきたいと考えております。また役立ちそうな構成パターンもどんどん増やし、資料も充実させていく予定ですので、ぜひ定期的にチェックいただければと思います。<br>

IBM Cloud導入検討時の情報として、ご利用目的に応じたかたちで、是非ご活用ください。

<b> （活用例） </b>
・構成パターンをベースとしたお客様要件に合わせた構成の検討
・構成パターンを参考にしたCloudの構成概要図の作成
・主要なCloudサービスの料金見積方法の確認

###  _Have_ _a_ _great_ _"IBM Cloud"_ _journey_ _!!_
～memo～ Rspecでメソッドの呼び出し回数をテスト時に実際にメソッドも呼び出したい場合

メソッド呼び出し回数をテストしたいけど、モックにしてしまうのではなくて、実際にメソッドも呼び出してその結果も確認したいー！
ということがあり、色々調べたらブロックで呼び出しが出来ました。

```ruby
  before do
    org_method = xxx_instance.method(:xxx_method)
    allow(xxx_instance).to receive(:xxx_method) { |*args| org_method.call(*args) }
  end

  it "" do
    subject
    expect(xxx_instance).to have_received(:xxx_method).once
    # expect ～
  end
```

ありがとうブロック
GX Works3でスキャンタイムを確認する方法

# 実行中のプログラムの処理時間、スキャンタイムを確認する方法

[オンライン]→[モニタ]→[プログラム一覧モニタ]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/e7047d3a-6d78-bc76-a60d-e0c325b3bd71.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/18f6fd90-12d0-57c7-803e-f96562497f40.png)



# 特殊デバイス(SD520,521)

SD520:スキャンタイム現在値(ms)
SD521:スキャンタイム現在値(μs)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/d4d2a110-c985-837d-2282-d9f693c2ed25.png)

# 参考ページ

https://fa-faq.mitsubishielectric.co.jp/faq/show/18256?back=front%2Fcategory%3Asearch&category_id=1966&commit=&keyword=%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0&page=1&search_target=0&site_domain=default&site_id=1&sort=sort_keyword&sort_order=desc

https://fa-faq.mitsubishielectric.co.jp/faq/show/24173?back=front%2Fcategory%3Asearch&category_id=694&commit=&keyword=SD520&page=1&search_target=0&site_domain=default&site_id=1&sort=sort_keyword&sort_order=desc
ポイントアンドプリントの制限

プリントサーバーで共有しているプリンターがノータッチ展開されなかったことが解決したのでメモ。

【環境】
プリントサーバー
Windows Server 2012R2（←サポート切れ、、、更改サーバーは注文済だが6か月経っても来ない）

クライアント
Windows10 pro 22H2

プリンター
京セラとシャープの複合機

【顛末：読み飛ばしてOK】
2年ほど前、2台あるネットワークプリンタの片方に接続できないという職員がちらほらと出ていた。
サーバー側のプリンタドライバーをアップデートをするも、接続できず。事務機器業者の担当にも来てもらったが、原因がわからないままだった。

そして最近購入したPCにプリンタが展開されず四苦八苦。
Windowsのバージョンが新しい(Windows10 Pro 22H2)から展開しているドライバを更新する必要があるのかと思い、サーバー側のプリンタドライバーをアップデート。するとその他大勢のPCに「ドライバーのアップデートが必要です」と表示され、アップデートしないと印刷できなくなってしまった。しかも、ドライバーのアップデートに確認プロンプトが表示され、管理者権限が必要。地獄の入り口が垣間見える。


【原因】
2021年8月のKB5005652で、PrintNightmare対策としてプリンタードライバーの新規インストール、更新に管理者権限が要求されるようになっていた。-->ポイントアンドプリントの制限

ここ2年半は新しいPCは購入しておらず、プリンタドライバーのアップデートも行っていなかったから表面化していなかっただけだった。


【解決策】
（１：推奨）グループポリシーの管理用テンプレートからポイントアンドプリントの制限を構成
　・プリントサーバーを許可リストに追加
　・プリンターの新規インストールと更新時にプロンプトを非表示
以下のCanonのFAQが参考になる
https://faq.canon.jp/app/answers/detail/a_id/89301/~/%E3%80%90color-imagerunner%E3%80%91%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%99%82%E3%81%AB%E7%AE%A1%E7%90%86%E8%80%85%E6%A8%A9%E9%99%90%E3%82%92%E8%A6%81%E6%B1%82%E3%81%95%E3%82%8C%E3%82%8B%E3%80%90%E5%85%B1%E6%9C%89%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF%E3%83%BC(%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%82%A2%E3%83%B3%E3%83%89%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88%E7%92%B0%E5%A2%83)%E5%88%A9%E7%94%A8%E6%99%82%E3%80%91

・・・できませんでした。グループポリシーは結局のところレジストリキーの配布。該当のレジストリが降りてこない。

（２：一時的な対策）グループポリシーでレジストリキーを配布
https://support.microsoft.com/ja-jp/topic/kb5005652-%E6%96%B0%E3%81%97%E3%81%84%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%82%A2%E3%83%B3%E3%83%89%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88%E3%81%AE%E6%97%A2%E5%AE%9A%E3%81%AE%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%AE%E5%8B%95%E4%BD%9C%E3%82%92%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B-cve-2021-34481-873642bf-2634-49c5-a23b-6d8e9a302872
上記のように、レジストリキーを新規作成するグループポリシーを展開

グループポリシー管理エディター
コンピュータの構成
　基本設定
 　　Windowsの設定
　　　　レジストリ→右クリック→新規作成→レジストリウィザード

レジストリキー
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint

DWord名
RestrictDriverInstallationToAdministrators
画面に従って操作し、アクションは「作成」。
（事前にクライアントのレジストリを確認し、上記のDWard名が存在すれば「更新」）

値
0（ポイントアンドプリントの制限は無効：従来通り）
1（ポイントアンドプリントの制限が有効：制限）

作成したグループポリシーオブジェクトは忘れずに適用しよう。
これでクライアントを再起動すればOK。

セキュリティ上の挙動変更なので、このままの状態で通常営業しない方が良い。
ひと通りのPCにドライバーのアップデートが走れば、
グループポリシーを変更し、上記のDWord名の値を1に更新しておこう。

【未確認情報】
該当のDWordが存在すれば、管理用テンプレートから変更できるようになるかも。
KintoneとAWSのS3の連携

# 要件
    Kintoneで作業しているユーザー全てS3に保存しているオブジェクトを参照可能にしたい

# 方法
## 1. Access key IDとSecret access keyの作成
ここでは詳細述べませんが、AWS公式サイトで参考お願いします。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_access-keys.html#access-keys_required-permissions

## 2. IAMバケットポリシーを作成する
IAMバケットポリシーを以下のように作成します。
```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "s3:*",
			"Resource": [
				"arn:aws:s3:::バケット名/*"
			],
			"Condition": {
				"IpAddress": {
					"aws:SourceIp": [
						"特定のIPアドレス"
					]
				}
			}
		}
	]
}
```
## 3. KintoneのJavaScript作成
### 準備
・AWSのSDKをしようするために、```https://sdk.amazonaws.com/js/aws-sdk-2.1503.0.min.js``` を事前に「JavaScript / CSSでカスタマイズ」機能で導入する必要があります。
・またボタンを作成する際にkintone UI Component 使用しましたので```https://unpkg.com/kintone-ui-component@1.11.0/umd/kuc.min.js```も事前に導入する必要があります。

今回私は自分で作成したボタンの中で、AWSコマンドでAWS S3オブジェクトに訪問するようにしました、コードは以下となります。
事前に、AWSの**URI**を記入する用のフィールドとボタンを作成するためのスペースフィールドを用意する必要があります。**（※オブジェクのURLではなくて、URIを使用してください）**

### kintone上のコード
``` JavaScript
(() => {
  'use strict';
  const Kuc = Kucs['1.11.0'];
  kintone.events.on('app.record.detail.show', (event) => {
    // ボタン要素を作成
    const field = kintone.app.record.getSpaceElement('事前に設置したスペースフィールド名');
    const button = new Kuc.Button({
      text: 'ボタン名',
      type: 'submit',
    });
    
    // Presigned URLを生成するためのパラメータのKeyを作成する
    const formatFieldValue = () => {
      const record = kintone.app.record.get().record;
      const fieldURI = ; // S3のURIを記入するフィールドレコード
      const Key = fieldURI.split( 's3://バケット名/' );
      return Key;
    };

    // ボタンがクリックされた時の処理
    button.addEventListener('click', () => {
      // 値を整形
      const formattedValue = formatFieldValue();

      // ここでフィールドの値を整形する処理を実装する

      //AWS SDKをインポートする
      const AWS = window.AWS;

      // AWS認証情報の設定
      AWS.config.update({
        accessKeyId: '作成したAccess key ID',
        secretAccessKey: '作成したSecret access key',
        region: 'ap-northeast-1' // AWSのリージョン
      });

      const s3 = new AWS.S3();
      // Presigned URLを生成するためのパラメータ
      const params = {
        Bucket: 'バケット名',
        Key: formattedValue[1],
        Expires: 10 // 有効期限（秒）（仮に10秒）
      };

      // Presigned URLの生成
      const url = s3.getSignedUrl('getObject', params, (err, url) => {
        if (err) {
          console.error('Error creating presigned URL:', err);
        } else {
          console.log('Generated presigned URL:', url);
          window.open(url);
          // ここで取得したURLを使用する処理を記述する（例えば、リンクを生成するなど）
        }
      });
    });

    // ボタンを詳細画面のフィールドに追加
    field.appendChild(button);
    return event
  });
})();

```
【Android】FragmentにComposeViewを乗っける場合は、ViewCompositionStrategyを指定しなければいけない【Jetpack Compose】

# はじめに

無限に忘れてしまうので、戒めの記事を書きます。

公式ドキュメントの[この部分](https://developer.android.com/jetpack/compose/interop/interop-apis?hl=ja#composition-strategy)についてです。

## 本題

FragmentやカスタムViewでComposeViewを使用する場合は、それらのライフサイクルに合わせてCompositionを破棄する必要があります。
それを実現してくれるのが、ViewCompositionStrategyになります。

```kotlin:公式のサンプル
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
    MaterialTheme {
        // In Compose world
        Text("Hello Compose!")
    }
}
```

デフォルトでは[DisposeOnDetachedFromWindowOrReleasedFromPool](https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool?hl=ja)が使用されているので、[DisposeOnViewTreeLifecycleDestroyed](https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)、または[DisposeOnLifecycleDestroyed](https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewCompositionStrategy.DisposeOnLifecycleDestroyed)を使ってあげるようにしましょう。

# まとめ

- FragmentやカスタムViewの上にComposeViewを乗っける場合は、ViewCompositionStrategyを指定しよう。

おわり。

## おまけ

DisposeOnViewTreeLifecycleDestroyedは一番近いlifecycleOwnerを、DisposeOnLifecycleDestroyedは渡したlifecycleOwnerを使う。
明示的にlifecycleOwnerを指定したい場合はDisposeOnLifecycleDestroyedを、そうじゃない場合はDisposeOnViewTreeLifecycleDestroyedを使うとよさそう。
【Day 17】API 環境構築 - Rust Hello World

## はじめに

![スライド18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/6b080079-3378-d09e-1b96-e7a7367e3b23.png)

---

**2023年アドベントカレンダー17日目**です。

https://qiita.com/advent-calendar/2023/life-sync-app

本日から「開発者はAPIの開発を進めることができる」を進めています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/2b71c2cf-703a-c8de-0753-e49bd0512782.png)

## Rust

APIにはRustを採用しようと思います

### Rustとは

> 「Rust」は、Mozilla社が開発したプログラミング言語です。
Rustの大きな魅力は、C言語やC++に匹敵する実行速度を備えていながら、優れた安全性を実現していることです。
> 
> そのため、システム開発、Web開発、AI開発など幅広い分野で注目されており、将来性も高いと考えられています。

https://www.rust-lang.org/ja

https://freelance-start.com/articles/1110

ではRustの環境をrustupで構築していきましょう

### rustup

> GPT
> Rustupは、Rustプログラミング言語のインストールやバージョン管理を簡単にするツールです。
:::note info
`asdf`でもRustは入れられますが、自分の環境ではVScodeのRust Analyzerが動かなかったので、rustupで入れています。
:::

https://rustup.rs/

公式のInstall方法に従っていきます。

```bash
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

$ cargo version
cargo 1.73.0 (9c4383fb5 2023-08-26)
```

これでrustupがinstallできました。

## Hello World

cargo initでRustプロジェクトを作成していきます

```bash
$ cargo init
Created binary (application) package
```

これでサンプルプロジェクトができました
実行してみましょう

```bash
$ cargo run
   Compiling rust-tmp v0.1.0 (/home/masashiooka/study/rust-tmp)
    Finished dev [unoptimized + debuginfo] target(s) in 0.17s
     Running `target/debug/rust-tmp`
Hello, world!
```

Hello Worldが出力されました 👍

明日は接続するDBを作成していきます
Next.jsでuseRouterを使ってページ遷移する！

## はじめに
これからNext.jsでuseRouterというものを使ってページ遷移する方法について説明します。
とても簡単なので使う機会があればぜひ参考にしてください！

## やり方
今回はボタンを押したらページ遷移するものを作ります。
まず、ページ遷移させるボタンが記述されているファイルの上にuseRouterをインポートしてください。
```javascript
import { useRouter } from 'next/router'
```

次にコンポーネントの中でuseRouterを呼び出してrouterオブジェクトを作ります。
```javascript
  const router = useRouter();
```
ボタンを押したときに実行される関数handleClickを作ります。
```javascript
  const handleClick = () => {
    
  }
```
ここで、 **router.push('URL')** でそのURL先にページ遷移させることが出来るのでhandleClick関数の中にrouter.pushを挿入します。
```javascript
  const handleClick = () => {
    router.push('/new_page')
  }
```
今回はnew_pageという新しいページに遷移させます。
最後にJSXのボタンタグの中にonClickを使用して、ボタンを押したときにhandleClick関数が呼び出されるようにすれば完成です！

全体の流れは次のようになります。
```javascript
import { useRouter } from 'next/router'

export default function Home() {
  const router = useRouter();

  const handleClick = () => {
    router.push("/new_page")
  }

  return (
    <main>
      <h1>これは最初のページです</h1>
      <button onClick={handleClick}>新しいページに遷移します</button>
    </main>
  )
}
```
## 

完成したページはこんな感じになりました。
![スクリーンショット (89).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959525/58cd9e28-bc72-239a-3fd6-9c3f81d92f2e.png)
ボタンを押すと新しいページに遷移します。
![スクリーンショット (90).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959525/b2bba9d3-cf75-e9cf-4a9f-f6475720fcd0.png)

## 最後に
これでuseRouteを使ってページ遷移させることが出来ました！
簡単にできたので是非使ってください！
【GPT付き】1年目データサイエンティストがレポート作るときに読むやつ

この記事は[リンクアンドモチベーション Advent Calendar 2023](https://qiita.com/advent-calendar/2023/lmi)の14日目の記事です。
データユニットのマネージャーをしてる東山です。

今回は、ほぼ毎年データサイエンティスト（志望）の新卒に教えていることをまとめてみました！
**新卒に「分析」業務をアサインするときに「まずコレ読んで！」** と渡せるものになったらなと思います！
（読むのが面倒な人は「[分析レポートレビューくん](https://chat.openai.com/g/g-Dgb6qFRLp-fen-xi-repotorebiyukun)」というGPTを作ってみたので使ってみてください。あくまでこの記事を参考にさせただけなので、レポート内容については責任はおえません。）

さて、中に入るのですが、教える側と新卒側であるあるの問題の構図として、
1. 分析目的やデータの出し方を伝えたけど、出てきたレポートがよくわからない
1. 段取りを細かくレビューしないといけない

などがあるかなと思っています。

**ざっくり渡しすぎると1のように結局手戻りになって、細かく教えすぎると2のように自分の時間がなくなる** ことになります。

この溝を埋めるために、**そもそもなぜ分析をするのか？この目的を果たすために必要な要素は何か？各要素をどう伝えるか？** についてまとめてみました。

# そもそもなぜ分析をするのか？
ビジネスの文脈においては、**意思決定とその合意形成のため** だと思います。[^1]
大学の研究などとの大きな違いは「真理の探求」ではなく、「**収益を生み出す見込みのある具体的な行動を選び、関係者が合意できること**」が重要です。
学生時代の思考様式とは、ここが決定的に違うことを理解しておく必要があると思います。
極論を言えば、みんなの意見がまとまっているときにはそれほど分析の出番はないと思います。[^2]

# 目的を果たすためにレポートに必要な要素は何か？
では、意思決定と合意形成の実現には何が必要でしょうか。
下のような要素で合意を取り付けていくのが大事だよと弊社では話しておりまっす。

1. 意見の分かれうる切り口（=**論点**）を洗い出す
    - ex) あるSaaSサービスにおけるダウンセル。年間の事業計画に無視できない影響がある！という人もいれば、そもそものチャーンを減らすためのプロダクト改善の方が大事！という人もいる。
        - ダウンセルは対処すべき大きい問題か？が論点
2. 論点ごとに、代表する**指標**を定める
    - ex) 年間のダウンセル額、ダウンセル額とMRRの比率
        - 事業計画を構成する値とそこへの与える影響が分かる指標を設定する
3. **可視化**の方法を決める
    - ex) 積み上げ棒グラフ（ダウンセル額 vs MRR）
        - ダウンセルの影響度が視覚的に把握できる手法を選ぶ
4. 指標の結果に合わせて**ネクストアクション**を決める
    - ex) ダウンセルはMRRの0.1%程度でしかなく、この改善幅にであればチャーン自体を減らす取り組みに注力しましょう!と提案
        - ここで意思決定の合意を取り付ける
5. 1~4の手続きを通して、合意形成が得られるまで論点を解消していく

これらをまとめることで、**関係者にとって「何が問題か？」と「問題をどうするか？」の議論を進める**ことができると思います。


# 各要素をレポートでどう伝えるか？
最後に、これまでの分析の要素をどう関係者に伝えるか？ですが、実は「**学生時代によく書いていたであろう文書の形と似てるよ!**」がこの記事のオチになります。


|段落|書くこと|
|-|-|
|背景| ● **論点**を明確にするために必要な情報や、これまでの問題を整理した内容|
|目的| ● 分析で取り扱うゴールとして、**論点**を提示し、どのような意思決定を行うか|
|方法| ● **指標**の定義<br>● どのようなデータ抽出、加工、分類を行うのか<br>● 何と何を比較するのか|
|結果| ● **可視化**のための図表<br>● 図表の読み方（単位、軸などの説明）<br>● ※認定できる事実を記述し、解釈を入れない|
|考察| ● 結果を受けて**ネクストアクション**の提案 |
|展望| ● 合意形成に至らない場合、追加で論証すべき論点|

この形式は[APAなどの論文構成](https://psych.or.jp/manual/manual03/#:~:text=%E3%81%AB%E5%89%87%E3%82%8B%E3%80%82-,1.2%20%E8%AB%96%E6%96%87%E3%81%AE%E6%A7%8B%E6%88%90,-%E8%AB%96%E6%96%87%E3%81%AE%E4%B8%BB)とも結構近いと思いますし、これまでの経験をそのまま活かせると思います！

あと、合意形成のために複数の分析が必要になることもあると思うので、そういうときは↓みたいなパターンもオッケーかなと。

- 背景：割愛
- 目的：割愛
- 分析1
    - 目的：割愛
    - 方法：割愛
    - 結果：割愛
    - 考察：割愛
- 分析2
    - ...
- 総括
    - 分析1と分析2の考察をもとに、全体へのネクストアクションの提案
- 展望：割愛

# おわりに
ちょっと長ったらしく書いてしまいましたが、せっかく分析をお仕事にしていくのですから、迅速に的確に意思決定を行ってビジネスに貢献しましょう！
そしてそのやり方を実は多くの人がすでに学習済みなので、安心して挑戦しましょう。
そういえば、昔書いた[野見くん](https://qiita.com/tohyama_eiji/items/96ecb15d4f7590247df8)ですが、ここらへんの勘所を掴んで今でも大活躍しております。
最近では取締役と密に連携を取ってデータドリブン経営を推進してくれています。
ただ、多分まだ彼の当初の目標である年収3,000万円は達成してないかな？


[^1]: [DMBOK](https://amzn.asia/d/4A8XTkg)の14章「ビッグデータとデータサイエンス」の1.1「ビジネス上の意義」にも、「ビジネスチャンスを見つけ出して行動できることにある」とあります。
[^2]: 「収益を生み出す見込み」を見積もらないでいいのか？分析はそこも役に立つのでは？という指摘が当然あるとは思いますが、分析の時間とのトレードオフとして、（不可逆でないなら）意思決定を早くして、効果を検証するという方法もあるかなと。
Windowsのregファイル内にコメント入れたい時

# やり方

```:コメントを入れたregファイル例
Windows Registry Editor Version 5.00

//regファイルにはこんなふうにスラスラでコメント入れられるよ。

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ODBC\ODBC.INI\ODBC Data Sources]
"XXXXX"="XXXXXX"
```

# 参考サイトさん

https://mebee.info/2022/06/18/post-71173/

# バージョン

Microsoft Windows [Version 10.0.19045.3803]
starship direnv プロンプトの表示が遅い問題

direnv
https://direnv.net

ディレクトリ毎に環境変数を読み込んでくれるやつ

```
[WARN] - (starship::utils): Executing command "ruby" timed out.
[WARN] - (starship::utils): You can set command_timeout in your config to a higher value to allow longer-running commands to keep executing.
```

starshipで実行するコマンドが遅いという警告が表示される。
毎回出るのは煩わしい。

https://tech.buty4649.net/entry/2021/07/29/201613

starship + asdf を使ってると遅いらしい。

```shell
$ brew uninstall direnv

$ asdf plugin-add direnv
$ asdf direnv setup --shell zsh --version latest
```

## それでも警告が表示される場合

https://starship.rs/ja-jp/config/

デフォルトは500msみたいなので1000msまで許容します。

```:~/.config/starship.toml
command_timeout = 1000
```

コマンドの実行時間が長くなってるだけで、実行できてない訳じゃないのでヨシとします。

## 関連記事

https://qiita.com/ucan-lab/items/0b854cfaa9d7c8ede106
【API】APIの種類について知っておこう

# はじめに

この記事は、株式会社スピードリンクジャパン Advent Calendar 2023 の13日目の記事です。

https://qiita.com/advent-calendar/2023/slj

# 対象の読者

* 若手エンジニア
* 未経験エンジニア
* これから開発を始める方
* APIについて理解を深めたいと思っている方

# APIとは

以下の記事で、APIとは何かについてまとめています。
短い記事になりますので、よかったら見ていってください。

https://qiita.com/suga_slj/items/f012bc9dd58c3aa2cc8b

# APIの種類

先にご紹介させていただいたように、異なるソフトウェア同士が連携するにはAPIが重要になってきます。
その中でもAPIには、用途によって幾つかの種類が存在します。
今回は、以下3つのAPIについてご紹介します。

## ランタイムAPI

### ランタイムAPIとは

ランタイムAPIとは、名前の通り**プログラムの実行時に使用されるAPI**で、**動的な操作が可能**になるAPIです。

わかりやすく言うと、プログラムの実行時間だったり、メモリの使用量を実行時に取得することができるといったところですね。

### メリット

上記でも説明した通り、プログラムの実行中に動的な操作が可能になるため、アプリケーション自身の状態をリアルタイムでモニタリングが可能になるのがメリットのひとつとなります。

これによって、問題発生時に早期に適切なアクションを行うことができるため、運用レベルアップにつながります。

## WebAPI

### WebAPIとは

WebAPIとは、Webサービスやアプリケーションが、HTTPプロトコルを通じて**Web上でAPIのやり取りが可能**になるAPIです。

代表的なもので言うと、RESTful APIなんかは1度は聞いたことがあるのではないでしょうか？
これも2つのコンピュータシステムをインターネットを介して情報のやり取りを行なっているため、WebAPIの1つと言えます。

SMSを使った認証サービスなんかにも使われているらしく、意外と身近にみなさんも触れています。


### メリット

プログラミング言語の依存関係に関わらず、誰でも簡単に異なるサービスやアプリケーション間でデータを簡単に共有できます。

基本的に、JSONやXMLなどの軽量なデータ形式を使用するため、データの効率的な転送を可能としていて、1度の通信量の削減の効果も期待できます。

開発を行っている人なら、外部のライブラリを自身のプログラムに取り込んで使用することもあるのではないでしょうか？
ライブラリの提供形式にもよりますが、あれもWebAPIを介して取り込んでいます。
従って、比較的短いコードで効率的に開発をすることが可能になることもメリットですね。


## OSのAPI

### OSのAPIとは

OSのAPIとは、アプリケーションが**OSの情報を取得・操作することが可能**になります。
ファイル操作やメモリ管理などがこれに含まれ、アプリケーションからそれらの操作が可能になります。

### メリット

OSのAPIを使用することで、アプリケーションはファイルシステムにアクセスできます。

同時に、それらのリソースに適切にアクセスすることから、不正アクセスや悪意のあるファイル操作を制限することが可能になり、セキュリティの向上にもつながります。


# 最後に

どうでしたか？
自分は未経験から入社した身なので、これを理解することは簡単ではありませんでしたが、
開発をしていく上であたりまえのように書いていたコードが、裏ではこんなAPIによって成り立っていたのかなんてことが見えてきました。

正直、現代では知らなくても動かせるものではありますが、今回紹介したそれぞれのメリットだけではなく、デメリットも存在していることを忘れてはいけません。

この機に調べてみるといいかもしれませんね。(僕も含め)
【必須級】隠れた便利ツール クリップボードアプリ

この記事は、[Lancers（ランサーズ）Advent Calendar 2023](https://qiita.com/advent-calendar/2023/lancers)  の14日目の記事です。
今日は私が常に使っている、でもそれがあまりにも **当たり前すぎて、特に取り上げることが少なかったツール** について皆さんに紹介したいと思います。それは、 **クリップボードアプリ** です。先に言ってしまいますと、普段の業務に欠かせないほどこのアプリです。

## クリップボードアプリとは?

クリップボードアプリとは、 **コピーした文字列や画像などを一時的に保存し、その後ペーストするためのツール** です。ただし、一般的なコピー＆ペーストとは異なり、 **複数のアイテムを保存しておくことができます。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637500/0026ad26-4a84-6784-ee75-ac7411cae20c.png)

## 主要なクリップボードアプリ
そんな便利なクリップボードアプリを紹介するにあたり、今回は「Clipy」「Clibor」の2つのクリップボードアプリを取り上げます。

もちろん、これから紹介するクリップボードアプリ以外にも多くのアプリが存在しますので、詳しく知りたい方は他の記事や製品レビューも見てみてください。

### 1. Clipy
Clipyは **Mac OS専用** のクリップボード拡張アプリで、シンプルながら強力なクリップボード管理機能を備えています。

### 2. Clibor
Cliborは **Windows** 対応の軽量でハイパフォーマンスなクリップボードアプリです。多彩な設定項目が用意されており、使い方次第でさまざまな用途に対応できます。

## クリップボードアプリの活用法とメリット
基本的な活用法としては、あなたが何かをコピーするとそのアイテムがクリップボードアプリに保存されます。その後、あなたがペーストしたい場所で当該アプリを開き、保存されたアイテムを選んでペーストするだけです。

このようなクリップボードアプリの利点は、 **複数のテキストや画像を一時的に保存** できるため、何度でもペーストすることが可能となる点です。また、一度に多くの情報をコピーしておけば、 **必要な情報をすぐに取り出すことができます。** これにより、仕事の効率を向上させたり、リサーチやブログ記事の作成などがスムーズに進むことでしょう。 **クリップボードアプリを入れていない方は試しにアプリを入れてみましょう!**

## まとめ
この記事を通じて、今まで気づかなかった方やクリップボードアプリの存在に気づいていただけたら嬉しいです。今までなかった効率よく作業できる体験を、ぜひクリップボードアプリで体感してみてください!
Crystalのツールを維持するためにGitHub Actionsに毎週ビルドを追加しよう

## はじめに

[以前の記事](https://qiita.com/kojix2/items/fbc27b2d354cd4ffba45)にCrystalのライブラリは壊れやすいのではないかと書きました。これに対する定番の対策を見つけたので記事にします。

## Crystalでは品質保証に定期的なビルドが求められる

Crystalの素晴らしいライブラリを集めたキュレーションリスト[awesome-crystal](https://github.com/veelenga/awesome-crystal)に、[マンデルブロ集合の描写](https://qiita.com/kojix2/items/011d48a8e1d9cf04d3bd)で利用した、[CrystalVips](https://github.com/naqvis/crystal-vips)を追加しようと思い、[プルリクエスト](https://github.com/veelenga/awesome-crystal/pull/630)作成したところ、次のチェックリストが表示されました。

> ### Checklist
> * [x] - Shard is at least 30 days old.
> * [x] - Shard has CI implemented.
> * [x] - Shard has daily/weekly periodic builds (ideally with Crystal latest and nightly).

３番めの項目は、日本語では

> * [ ] シャードには毎日／毎週定期的にビルドがある（最新版およびナイトリーのCrystalが理想）

っていう感じになると思います。
つまり、Awesome Crystalでは、リスト掲載に「定期的なビルド」が行われていることを求めているのです。

私の知識不足かもしれませんが、RubyのGemでは定期的なビルドを行っているものは多くないと思います。GitHub Actionsで定期的にビルドを行えば、動作しなくなったときに早期に気がつくことができそうです。例えリポジトリが放置されていても、過去の結果を追跡すればどこで動作しなくなったのか、修正にどの程度の手間がかかりそうか見積もることもできるでしょう。

## 実際に CI に定期的なビルドを追加してみた

練習のため、前回の記事で紹介した[deepl-cli](https://github.com/kojix2/deepl-cli)に定期的なビルドをつけてみました。
やり方は簡単で、`on:` に `schedule:` を追加して `cron:` で時間を指定すればよいです。

```yaml
name: build

on:
  push:
  pull_request:
  schedule:
    - cron: '51 3 * * 6'  # Runs at 03:51, only on Saturday
```

ここでは、なるべく利用者が少なそうな時間を狙って、土曜日の3時51分にビルドするように設定してみました。

残りの部分はこんな感じです。Crystalのバージョンとして `latest` を指定しました。これによって、毎週最新のCrystalによってビルドできるかのチェックが行われます。

```yaml
jobs:
  build:
    name: ${{ matrix.os }}
    runs-on: ${{ matrix.os }}-latest
    strategy:
      matrix:
        os: ["ubuntu", "macos", "windows"]
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: true
      - uses: crystal-lang/install-crystal@v1
        with:
          crystal: latest
      - name: Install dependencies
        run: shards install --without-development --release
      - name: Build executable
        run: shards build --release
      - uses: actions/upload-artifact@v3
        with:
          name: deepl-cli-${{ matrix.os }}
          path: bin/${{ matrix.os == 'windows' && 'deepl.exe' || 'deepl' }}
```

## おわりに

Crystal言語ではツールやライブラリが動作しなくなるケースが多いと感じていました。しかし、定期的にCIを回し続けていれば不具合の検出が容易になります。コンピュータを使う上で感じる痛みを、道具を上手に使うことで緩和すればよいという話でした。

この記事は以上です。
オフショア開発の現場で共同開発してきた


## 自己紹介と部門の紹介
こんにちは。JINSのITデジタル部の坂口です。
私は１年ほど前にJINSにJoinしDigital CommerceのIT基盤開発Teamのマネジメントをしています。
元々はメーカでHWやサービス開発の仕事をしていましたが、

・もっとお客様に近く
・お客様の価値につながっている
・生きているサービスの開発に関わりたい

と思い異業種に飛び込みました。
今は気のいい仲間と、お客様に感動と安心を届けられるシステムをモットーに日々業務に取り組んでいます。

JINSでは事業をGlobalな視座で考えることを基本とすることを心がけています。
実際に海外５つの国と地域で店舗を展開しています。
IT開発メンバーとしては事業の展開だけではなく、一緒に開発をしていくパートナー様や利用するPFやサービス、個人のスキル成長に関してもGlobalな視点を持って考えています。
まだ道半ばではありますが、過度なプレッシャーには感じず、日本でだけ仕事していてもねぇ、くらいの感覚で進めています！

![スクリーンショット 2023-12-11 8.48.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626837/fb602c59-aa73-3db3-6dcf-502eefa0e402.png)

## 実施したこと
今回は開発活動の中で、ご協力いただいているベンダーさんのオフショアの開発拠点にて共同で業務をさせていただいた内容について書かせていただきます。

そもそもなぜ？共同開発？ですが、単純に遠く離れた海外で開発しているベンダーさんと、日本で働いているJINS開発チーム間での、開発速度を加速させる目的で約3週間セブの拠点にお世話になりました。

ベンダーさんとはほぼデイリーで会話させていただいています。

ただ感じていたのはベンダーさんが受けてくれている仕事が現地のエンジニアの皆さんでどのように実行されているか？もっと深掘りすると、どういうMindでその仕事に向かっていただいているのか？

について、若干の認識の齟齬があると感じ、同じプロジェクトのパートナー関係として不健康と感じそのギャップを埋めるべく伺わせていただきました。ちなみに行こう！決めてその日には許可が降りるJINSの意思決定の速度は最高に大好きです！（上司に感謝。）

## 学び
結果として判断は正しかったと認識しています。
初日にたくさんの気づきがありました。

具体は出しにくいのですが、例を挙げると複数ある課題に対し、どれが根本課題なのかをJINS側が捉えきれていなかったことです。距離、言語、立場、状況によってコンテクストの伝わり方って変わってくるのだなぁと改めて認識しました。

また海外の開発会社の雰囲気の良さを感じて自分の組織にも取り入れたいと思いました。
みなさんの仕事の仕方を見ていると会議が少ない。どうやっているの？と聞くと近くに座っているからそこで話して済ましている場合もあるとのことでした。ちなみにTeleWorkの日と出社の日を分けていて、TeleWorkの方が比率多いようです。
良し悪しははあると思いますが、集まって仕事をして、その場で決めて進めるというスピード感は大事かなと思いました。

またみなさん楽しそうなんです。仲が良い。我々も仲の良さでは負けていないと思っていますが、彼らの方が勢いがあるんです。根源はなんなのかな？と思って見ていたのですが、出社日や金曜日の仕事が終わった後は、会社にそのまま残って、その場でポーカーやオンラインゲームをみんなで楽しんでいるんです。
すごく盛り上がっていて、時に一晩やってしまうくらいとのことでした。若いというのもあるのですが、会社をこういう場としても使って、Team Workを高めていくというのは、アリかなと思いました。実際離職率の低下や出社へのモチベーションにもつながっているようです。

![IMG_4293.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626837/470ae824-f3cb-173d-2253-32cd69e6f29a.jpeg)


## 反省点
学びは多かったし、課題は進捗したものの個人としてはもっと語学力を高めたいと改めて感じました！グローバルと言っているのであれば英語くらいはもう少し頑張りたいと。実際JINSの仲間でも外国語得意な方も多いですし。伸び代ですね。

## まとめ
昭和的で恐縮ですが、目で見るとか直接話すとかやっぱ価値深いなぁと。そして学びが多いなぁと。いつでもそうしたコミュニケーションが取れるわけではないものの、このままうだうだやっていても感を感じたら、自ら足を運ぶことは大事と再確認しました。

その機会に備え、語学力はもちろん、文化の違い、考え方の違いなどを素直に受け入れられる寛容性、柔軟性も持ち続けたいと思いました！

![IMG_4386.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626837/43dd81be-c61b-e7ad-b2f0-66dd35b5c17a.jpeg)
Account Engagement（Pardot）とMW WP Formを連携

## やりたいこと
既存のMW WP Formで作成したフォームに登録された情報を自動でAccount Engagementのプロスペクトとして登録したい
## 参考
https://kohimoto.com/labo/study/system/6483/
https://webmemolog.com/web/20230506_1027
## 詰まるまでにやったこと
上記の記事を参考にAccount Engagementでフォームハンドラーを作成。
このときの注意点としては、
- フォームのname属性を正確にAccount Engagementの名前属性に転記する
- Account Engagmementで必須項目でないものが必須項目チェックされていないか確認する

プロスペクト作成時のエラーは通知されないとのサポート回答もあり。特に上記2点は引っ掛かりやすい。
## 詰まったところ
フォームに実際入力すると、完了ページに遷移せず入力画面に戻される。
URLの遷移を見て、エラー発生場所はなんとなく把握。

WPフォーム確認画面
▽
Account Engagementへの情報送信
▽　←どうもここの遷移が上手く動かず、MW WP Formがリダイレクトを繰り返しフォーム入力画面に戻されているようだった。
WPフォーム完了画面

このエラーが起きた時はプロスペクトだけ作成され、WordPressのデータベースには登録されていない。MW WP Formからの自動返答メールも発出されていない。
シークレットモードでは問題なくフォーム入力完了・プロスペクト作成・自動返答メール受信ができる。
## 解決
先例も少なくどうにも詰まっていたが、function.phpの記述を変更することで解決した。
詰まっていた時、function.phpには下記コードを記述していた。

``` php
elseif ( 'mwform_formkey' == $tag && isset( $attr['key'] ) && 'フォームID' == $attr['key'] && $_SERVER['REQUEST_URI'] == '確認画面URI' ) {
		$output = str_replace(
			'<form method="post" action="" enctype="multipart/form-data">',
			'<form action="https://go.pardot.com/l/XXX/XXXX/XXX" method="post">',
			$output
		);
	}
```

この時の`<form action="https://go.pardot.com/l/XXX/XXXX/XXX" method="post">`内にあるURLのドメインを、汎用の`go.pardot.com`ドメインからカスタムしたトラッカードメインに変更したところ解決。
何故これで解決するのか、理由まではわからなかった。

## 仮説
トラッカードメインがWEBサイトドメインの子ドメインだったためエラーが起きなくなったのだろうか？
デジタルKJ法

## 背景
2022/10に作成したアプリケーションです。
AWSで稼働させていたのですが、維持費高いので現在停止中(2023/8 -)

## アピールポイント
実装例が載っていないドラッグ&ドロップで3層にネストしたカンバン方式を実現したこと(vue.js)
TDD形式で開発したこと

## サービス説明
・作成秘話
https://www.youtube.com/watch?v=XRuQ5ReowqY

・サービスの使用方法
https://www.youtube.com/watch?v=anR6QVQtaCM

## ソースコード
https://github.com/motoya0118/kj_method
docker for macでwebサーバーが立ち上がらなかった話


# はじめに
新しい案件にアサインされた時に、dockerで環境構築中にwebサーバーが立ち上がらなくて困ったことがあった。
先輩にサポートもらいながら解決できたので備忘録。

# 事象
通常、git管理されているプロジェクトのソースたちをclone後に
```
docker compose up -d
```
するとすぐに環境ができてブラウザでlocalhostにアクセスできる。

今回、上記コマンドを実行すると、特にエラーは起きずdockerは起動する（実際にはしていない）のだが、localhostへアクセスと下記の画面が出る。

![image-64.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587166/daf6ac82-d718-9c31-630e-a564c2f97c85.png)

「ERR_EMPTY_RESPONSE」エラーはブラウザに関連する問題で、サイトへのアクセス要求に対してサーバーが応答しなかったことを意味する。

ちなみにdocker環境は
- mysql
- phpmyadmin
- memcached
- webサーバー
で構成されていて、phpmyadminには無事にアクセスができた。

## ポート番号が被ってるかも
よくある（自分だけかも）のがdockerで環境を複数立ち上げていてポート番号使ってるパターン。
（でもこれの場合はdocker起動時にエラー出る）
一応ポート番号を確認してみたが今回のものしか使っていなかった。
```
sudo lsof -P -i:8080
COMMAND     PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
com.docke 76016 01054883  149u  IPv6 0xfb61021c3152318d      0t0  TCP *:8080 (LISTEN)
```

## docker立ち上げ直す
dockerをキャッシュなしで立ち上げ直す
```
docker-compose build --no-cache
```
これも特に変わらずだった。

## curlで直接入ってみる
curlコマンドで直接localhostへアクセスするがもちろんエラー。
```
curl http://localhost:8080/
curl: (7) Failed to connect to localhost port 80 after 9 ms: Connection refused
```

## webサーバーを疑う
エラーはないが、webサーバーが立ち上がってないのかとなったので、dockerに入ってwebサーバーを起動してみると下記のエラーが出た。
```
systemctl start httpd
Failed to get D-Bus connection: No such file or directory
```

# 原因
このエラーで原因がわかった。
```
Failed to get D-Bus connection: No such file or directory
```
今回、Docker for macを使って環境構築を行なっていて、Docker for macで使用する「systemd」というコマンドはLinuxの起動処理やシステム管理を行うコマンドで、21年12月からsystemd247以上を使う必要があるらしい。

systemdのverを確認する。(docker内で)
```
rpm -q systemd
systemd-219-78.el7_9.7.x86_64
```
systemd219で古かった。

この場合、ダウングレードする必要があったそうだが、settings.jsonの設定を変えることで対応ができるらしい。
~/Library/Group Containers/group.com.docker/settings.json
```
{
  "deprecatedCgroupv1": false, // ← ここをtrueにする
}
```

これで再起動後に無事にアクセスすることができた！

こちら参考にさせていただきました:thumbsup_tone1:
https://qiita.com/NaoyaMiyagawa/items/22a870112377a91e1c99
Office Scriptsでできなかったことまとめ

Offics scriptsで出来なかったことをつらつら足していこうと思います。（2023/12/13時点）

|できないこと|代替手段|
|---|---|
|セルの選択|（手動）ロックをかけないセルを選択しておく。<br>※ ```selectionMode: ExcelScript.ProtectionSelectionMode.none```は効かない。<br>```selectionMode: ExcelScript.ProtectionSelectionMode.unlocked```は有効。<br> cf. シートの保護設定は可能```sheetProtection.protect(protectionOptions)```|
|既にあるテーブルを解除する|（手動）解除したいテーブル範囲内の適当なセルを選択した状態で、[テーブルデザイン]＞[範囲に変換]をする|
|既にあるテーブルを含んで新しいテーブルを定義する|1.（手動）解除したいテーブル範囲内の適当なセルを選択した状態で、[テーブルデザイン]＞[範囲に変換]をする<br>2.（スクリプトで可能）テーブルの範囲を再定義する|
|テーブルの色変え（＝無色にできない）|（手動）テーブルデザインタブから好みのものに変更。<br>※Office Scriptsでテーブルを作成するとテナント・もしくは個人契約利用で既定としている色合いになります|
Googleカレンダーへの作業時間登録をアドオンで簡単にした

本記事は[リンクアンドモチベーション Advent Calendar 2023](https://qiita.com/advent-calendar/2023/lmi)の19日目になります。

# はじめに
弊社では、PJTごとの稼働時間を集計するために活動時間をGoogleカレンダーに記録しています。
これがまあ~~めんどくさい~~大変なのです。

**大変ポイント**
- 入力フォーマットを間違えると正しく集計されない
- PJTコードを間違えると正しく集計されない
- 作業 | mtg | 作業　のような時に2つに分けて作業を入力しないといけない

これがあまりにも~~めんどくさい~~大変だったので、なるべく楽に・正確に登録できるようにするためにGoogleカレンダーへ作業時間を登録するアドオンを作りました。

Google Workspace Add-onsにしたのは
- Googleカレンダーで開けるから
- 同じことで困っている人に配布しやすい
- **作ってみたかったから**

です。

# どんなアドオン？

こういう画面がGoogleカレンダーの右に表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/811dfedc-3435-5284-17ba-487dd7f8e339.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/09debbb2-b071-edc7-932c-8198e1bcaad2.png)


入力フォームに各種情報を入力し、「登録を実行」することで開始時刻〜終了時刻まで**すでに入っている予定は避けて**作業時間を登録してくれます。

# どうやって作るの？
ざっくりこんな感じです。
- GASで実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/5796a366-5c88-2bb1-36df-b69ac387cf8f.png)
  - UIは[ビルダー](https://gw-card-builder.web.app/)でコード生成してコピペするだけ
- Google Workspace Marketplaceに内部アプリとして公開

実装や公開方法の詳細に関しては[弊社のテックブログ](https://link-and-motivation.hatenablog.com/entry/2023/07/21/120000)でエンジニアが記載した記事があるのでそちらをご参照ください。
私はこの記事を見ながら作りました。

ここからは、今回作る際に工夫したポイントをご紹介します。

# 工夫ポイント１：大体入力する情報が同じものはUserPropertiesに保存しておく
以下のように、指定のキーで永続化することができます。
ユーザーごとに保存されるので、別のブラウザでログインした場合なども引き継がれます。
```js
const USER_PROPERTY_PJTCODE = 'pjtCode';
const USER_PROPERTY_DESCRIPTION = 'description';
const USER_PROPERTY_OVERRIDE = 'override';

function loadUserProperty(key) {
  const prop = PropertiesService.getUserProperties();
  return prop.getProperty(key);
}

function saveUserProperty(key, value) {
  const prop = PropertiesService.getUserProperties();
  prop.setProperty(key, value);
}
```

# 工夫ポイント2：自分が主催者の予定のステータス判定はゲストステータスを見る

主催者だった場合、getMyStatus()ではOWNERと返却されてしまいます。
そのため、ゲストステータスを見るようにしました。
（もっとスマートな方法あれば知りたい）

```js
  // 勤務時間のうち、予定が入っている時間帯を取得
  // 終日の予定、除外する予定は省いて返す
  return events.filter(event => {
    // 終日予定は除く
    if (event.isAllDayEvent()) {
      return false;
    }
    // 上書き対象の予定(ex) NO MTG DAY)は除く
    if (overrideTitles.includes(event.getTitle())) {
      return false;
    }

    // 参加していない予定は除く
    let myStatus = event.getMyStatus();
    if (myStatus === CalendarApp.GuestStatus.OWNER) {
      // 主催者だった場合は、ゲストステータスを見ないと判別できない
      const email = Session.getActiveUser().getEmail();
      const guest = event.getGuestList(true).filter(
        guest => guest.getEmail() === email
      );
      if (guest.length === 0) {
        // 自分だけの予定は作業時間とみなすので参加判定
        myStatus = CalendarApp.GuestStatus.YES;
      } else {
        myStatus = guest[0].getGuestStatus();
      }
    }

    return !excludeStatus.includes(myStatus);
  });
```

# おわりに
社内でも喜んでもらえたので、作って良かったです。
今後も、身近なめんどくさいを撲滅していく際に使ったことがない技術を採用して楽しんでいこうと思います。
UiPathでExcelのアクティブなセルに対して操作

# Excelのアクティブなセルの操作する方法が無い

UiPath Studioでプロセスを作成する際、モダン・クラシックの２つのモードがあります。
現在最新バージョン(23.10.0)を使用するとデフォルトではモダンのプロセスとなります。
そして、モダンのプロセスではExcelのアクティブなセルの操作する方法がありません。（見つかりませんでした）

## Excelのアクティブなセル（行）を非表示にしたいが…
例えば、下記のようなシートがあったとします。
![Excel_pre.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631520/bc8cb27c-f830-03ac-9992-4cf67a4a317a.png)

このシートの
**A列：条件　が0の場合、行を非表示にしたい** 
という要件があった場合をモダンアクティビティだけでは実装することができません。

アクティブなセルに対して[Ctrl+9]（行の非表示）という
キーボードショートカットを効かせることができれば良いのですが、
そもそも「セルをアクティブにする」ということがモダンアクティビティではできないようです。

## クラシックアクティビティ「範囲を選択」
実は、モダンのプロセスからでもクラシックアクティビティを使用することができます。
下記画像のように、アクティビティのペインの漏斗のマークをクリックし、
「クラシック」にチェックします。
![pain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631520/612b3314-5f6e-e8bb-7e34-8919fe38a1e0.png)

すると、アクティビティに「クラシック」が表示されます。ここでは
* クラシック > アプリの連携 > Excel > 範囲を選択

を使用してセルをアクティブにします。

## コード全体
![Source1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631520/df7ee55b-a52d-1b58-0a2c-ce14a48a6388.png)

![Source2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631520/c43af3fa-3d1f-ce38-277a-566da03192fc.png)

## コード解説
### 代入
* RowNo・・・アクティブにしたい行数（初期値=2)

### Excelプロセススコープ > Excel ファイルを使用

* 繰り返し（後判定）
    * 範囲を選択
        * 表示・非表示を判定するためにA列のセルをアクティブにします（**ここが今回の肝**）
        * （見えていない部分："A"+RowNo.ToString）
    * セルを読み込み
        * 表示・非表示を判定するためにA列のセルを読み込みます（CellValueに出力）
    * 条件分岐
        * セルを読み込み結果＝0　の場合、行を非表示にします（Ctrl+9）
    * 代入
        * 行数RowNoをインクリメントします
* （後判定）
    * セルの入力が空であれば繰り返し終了

## 結果
以下のようにA列：条件　が0の場合のみ非表示にすることができました。
![Excel _after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631520/88b6acb0-b599-537b-26db-76e97ff7183a.png)


## この方法の賞味期限について
今回はセルをアクティブにしてそのアクティブなセルや行に対して操作する方法を紹介しました。
しかし、UiPathはこれらをクラシックとしているためいずれサポートされなくなるかもしれません。

UiPathのExcel操作の基本思想は
* 表をデータテーブルとしてメモリに読み込み
* UiPath上で各種演算
* その結果をまたExcelに吐き出す

というものだと考えられます。このため、この方法はあくまで応急処置的な方法だと捉えてください。