OmniAICreator/Qiita-1.07M huggingface dataset:
Nuxtで環境変数を分ける

開発時とビルト時で環境変数を分けたかった。



まず、runtimeConfigで変数を使えるようにする。
```nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiTest: 'hogehoge',
    },
  },
...

```

これで任意の場所で変数が使えるようになる。

```typescript
const runtimeConfig = useRuntimeConfig();
console.log(runtimeConfig.public.apiTest);
```


次に、.env.devと.env.productionの２つのファイルを作って、
変数の中身をそれぞれ書き込む。

この時に、頭にNUXT_をつけて、
nuxt.config.tsのruntimeConfigの変数と名前を合わせると、
runtimeConfigが.envで上書きされる。

```.env.dev
NUXT_PUBLIC_API_TEST = "https://test-dev.com/api/"

```

```.env.production
NUXT_PUBLIC_API_TEST = "https://test-production.com/api/"

```


コマンド実行時に.envファイルを使い分ける。
```package.json
"scripts": {
    "dev": "nuxt dev --dotenv .env.dev",
    "generate": "npx nuxi generate --dotenv .env.production",
...
  
```


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


参考


https://tyotto-good.com/nuxtjs/environment-variable



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


やっぱり上記のやり方よりこっちの方がいいかも

https://qiita.com/Ancient_Scapes/items/0ad01d4641c2a8afc875

https://zenn.dev/arkwknsk/articles/f092b7ea77d112

https://qiita.com/y-temp4/items/84bb16e2ccf8efaf82fc
コマンドの"-force"について 

## "-force" について

:::note
"-force" は、ある操作を強制的に実行するために使用される
:::

## 使用例

### ファイルの削除
ファイルの削除コマンド（"rm"）を実行すると、削除の確認プロンプトが表示されることがある
__"-force" オプションを使用すると、確認プロンプトをスキップして、ファイルを強制的に削除できる__

### ファイルの上書き
ファイルのコピー（"cp"）や移動（"mv"）を実行すると、同名のファイルが既に存在する場合、上書きの確認が求められることがある
__"-force" オプションを使用すると、確認プロンプトをスキップして、既存のファイルを強制的に上書きできる__

### インストールやアップデート
ソフトウェアのインストールやアップデートの際に "-force" オプションが使用されることがある
→依存関係のチェックやバージョンの競合などの問題を無視して、強制的にインストールやアップデートを行うため
☆注意が必要☆
TypeScriptでinterfaceをimplementsするときのカプセル化がよく分からなかった

社内研修で初めてTypeScriptを使ったアプリを作ることになった。
カプセル化ってよく聞く言葉だったが、実際に取り入れようと思うと躓く点があったので、自分なりの解釈をまとめておく。

### カプセル化とは
- データとそれに関連するメソッド（操作）をオブジェクトとしてまとめ、外部からの直接的なアクセスを制限することを指す。

### 初心者の考え
とりあえずオブジェクトのプロパティに片っ端から`private`をつけていけばそれっぽくなるんやろ、という認識だった。が、JavaScriptにはprivate修飾子が用意されておらず、クロージャを使って実質的なprivateを実装するしかないらしい…。

と思ったら、TypeScriptには`private`が用意されているらしい！なーんだ、簡単じゃん！

### 実際にコーディングしていると…
コンソール上で動作するブラックジャックを作っていた。
```ts:Player.ts
import type { Card } from './Card'
import type { Deck } from './Deck'

export interface Player {
  hand: Card[] // これと
  playerName: string // これを外部からアクセスできないプロパティにしたい
  drawCard: (deck: Deck) => void
  calcTotalNum: () => number
  displayHand: () => Card[]
}
```
上記のinterfaceを、実際にインスタンス化して使うことはない親クラスにimplementsして、それを子クラスで継承して使おうとすると、どこに`private`をつければいいのだろう…と悩んだ。

親クラス、子クラスはこんな内容。
```ts:ImpPlayer.ts
export class ImpPlayer implements Player {
  hand: Card[] = []
  playerName: string = ''
// 以下省略
```
```ts:Human.ts
import { ImpPlayer } from './ImpPlayer'

export class Human extends ImpPlayer {
  playerName: string = 'あなた'
}
```
```ts:Computer.ts
import { ImpPlayer } from './ImpPlayer'

export class Computer extends ImpPlayer {
  playerName: string = '相手'
}
```

#### さて、どれをprivateにしたらよいだろう…全部のファイルのプロパティにつけてみるか。
- interfaceにアクセス修飾子はつけられないよって怒られた。存在するプロパティ・メソッドの宣言をするだけの機能なんだから当たり前か。privateプロパティが存在するよって宣言とかはできないらしい…！
#### interfaceだけ外して、親クラスと子クラスにつけてみた。
- `Class 'Human' incorrectly extends base class 'ImpPlayer'.
  Types have separate declarations of a private property 'playerName'.ts(2415)`ってエラー。親クラスと子クラスで同じ変数名なのにそれぞれprivateを宣言してるって怒られた。
#### 親クラスも外して、子クラスだけつけてみた。
- `Class 'Human' incorrectly extends base class 'ImpPlayer'.
  Property 'playerName' is private in type 'Human' but not in type 'ImpPlayer'.ts(2415)`ってエラー。親クラスと子クラスでアクセス修飾子の属性が違うって怒られた。
#### 子クラスで外して、親クラスでつけてみた。
- `Class 'ImpPlayer' incorrectly implements interface 'Player'.
  Property 'playerName' is private in type 'ImpPlayer' but not in type 'Player'.ts(2420)`ってエラー。interfaceとimplementsクラスでアクセス修飾子の属性が違うって怒られた。え、interfaceでアクセス修飾子つけられないなら、implementsするプロパティはprivateにしようがないじゃん…！

ということで、調べてみたらそれっぽい記事が見つかった。

https://stackoverflow.com/questions/37791947/how-to-define-a-private-property-when-implementing-an-interface-in-typescript

ふむふむ、何となくわかったぞ。


### 分かった事まとめ
- InterfaceはPublicなメソッド・プロパティを宣言するためのもの。`private`をつける余地はない
- 抽象クラスを使えば同じような用途でPrivateの記述もできる（？）っぽいけど、Interfaceとの使い分けが全く想像できない
- そもそも、今回のようにplayerNameだけをインスタンスごとに変えたいならインスタンス化する際にコンストラクタに受け取る引数で変えてあげることもできた。（勉強のためということで、それ以外の解決策を調べた）
#### 解決策１
- Implementsクラスでprivateなプロパティを用意したいなら、Interfaceに`getter`や`setter`メソッドを用意して、プロパティは書かない。Implementsクラスで初めて`private`属性のプロパティを宣言する。
#### 解決策２
- TypeScript2.0以降だとreadonly修飾子が使える。public readonlyにすることで、どこからでも読み取れるが、変更はできないプロパティを簡単に用意できる

（ちなみにreadonlyを配列に設定するとその中身まで変更できなくなるらしい）

いまはreadonlyを使う方が主流っぽい？のと、ESLintを入れるとなんでもかんでもreadonlyをつけろと言われるので、これで実装してみることにした。もちろん、privateと違って参照自体はできちゃうので、そこは気をつけたい。
設定の通知、追加の設定にあるウェルカムエクスペリエンス、デバイスの設定完了、提案の非表示（コマンドで行う方法）

ウェルカムエクスペリエンスは、SubscribedContent-310093Enabled
デバイスの設定完了は、ScoobeSystemSettingEnabled
提案は、SubscribedContent-338389Enabled

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628314/7c0ff00b-52c3-ab9b-37cf-3c5ec9552744.png)

```
@echo off

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-310093Enabled" /t REG_DWORD /d "0" /f
reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\UserProfileEngagement" /v "ScoobeSystemSettingEnabled" /t REG_DWORD /d "0" /f
reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338389Enabled" /t REG_DWORD /d "0" /f

pause
exit
```
Ruby silver 模擬問題解説5

Ruby silverの模擬問題を抜粋して解説をしていきます。

下記コードの出力結果を4択から選ぶ問題になっています。
```ruby
a = "victory"
b = "victory"
c = a

（１）p a.eql?(b)
（２）p a.eql?(c)
（３）p a.equal?(b)
（４）p a.equal?(c)
```
1.（１）true （２）true （３）false （４）true
2.（１）false （２）false （３）true （４）true
3.（１）true （２）true （３）false （４）false
4.（１）true （２）true （３）true （４）true

まず、変数a b cにそれぞれの値を代入してます。
```ruby
a = "victory"
b = "victory"
c = a
```
次に'.eql?'のメソッドは、それぞれのオブジェクトの値が等しいかどうかを比較します。
等しいときは'true',等しくないときは'false'を返します。
['.eql?'の公式リファレンス](https://docs.ruby-lang.org/ja/latest/method/String/i/eql=3f.html)

(1)は変数'a'と変数'b'の値は等しいですので出力結果は'true'になります。
```ruby
a = "victory"
b = "victory"
c = a

（１）p a.eql?(b)
```

(2)は変数'a'と変数'c'の値は等しいですので出力結果は'true'になります。
```ruby
a = "victory"
b = "victory"
c = a

（２）p a.eql?(c)
```

次に'.equal?'のメソッドは、それぞれのオブジェクトが同じオブジェクトかどうかを比較します
等しいときは'true',等しくないときは'false'を返します。
['.equal?'の公式リファレンス](https://docs.ruby-lang.org/ja/latest/method/Object/i/equal=3f.html)

(3)は変数'a'と変数'b'は同じオブジェクトではないので出力結果は'false'になります。
```ruby
a = "victory"
b = "victory"
c = a

（３）p a.equal?(b)
```

(4)は変数'a'と変数'c'は変数'c'変数'a'を代入しているので、同一のオブジェクトになりますので出力結果は'true'になります。
```ruby
a = "victory"
b = "victory"
c = a

（４）p a.equal?(c)
```
解答は、１番が正解になります。
windowsにて、毎日自動的にgit pull 実施する方法

毎日git pullで最新のソースコードを取得するのは面倒だと思って、windowsでも毎日自動的にコードを更新する方法を探し出しました。
一、先ずは.batファイル作成。
例として、test.txtの新規ファイルを作成して、編集します。
内容：

---------------------------
　@echo off
　D:
　cd \git_test
　git pull
//追加コマンドしていい

-------------------------
ここのpathはローカル　ブランチの箇所（git pull実施するところ）。
複数のブランチを同期する場合は上記コードの下に追加すればいいです。（pathの変更も忘れずに）
そして、保存したらファイル拡張子を.batに変更して、実行してみてください。

二、Windowsのタスクスケジューラにて設定する。
基本タスクの作成を選択して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467477/eee1bf86-cc2b-1fd1-7214-6673f19e3805.png)


タスクの情報を入力して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467477/c535811a-a6f9-0fe1-f5f5-78760700daf6.png)

タスク開始するタイミングを選択する。私の場合はwindows起動時です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467477/ad666fbf-42c5-2dc1-bb5c-a1485395f0b3.png)

プログラムの開始を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467477/497c3a5b-13c3-175d-694d-735c73b7962a.png)

先作成した.batを選択して、完了させる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3467477/09fa390f-33da-7b0b-0ada-af979b4e0a5d.png)

これでタスク作成完了。PCを再起動して検証してみましょう。
[Backend Developer] 学習ロードマップ

## 概要

エンジニア5年目を迎え、1年目の頃から学んだことの基礎をさらに固める為（忘れていることもありそう）に、この記事を書いていきます！！

範囲は幅広く、インターネットのことから、プログラミング言語、GitやRDBなど、バックエンドエンジニアとして働いていく上で、必要なことを中心に書いてきます。

具体的には、[バックエンドロードマップ](https://roadmap.sh/backend "バックエンドロードマップ")を元に、自分の言葉で学んだことを中心に書いていければと思います。

このロードマップを元に、基本的には進めていきます。
ただ、もっと深掘りして理解しておこと思った箇所があれば、ドキュメントや書籍を参考に深掘りもしていこうかなと思います。

## ロードマップ

|  ジャンル  |  URL |
| ---- | ---- |
|  Internet  |  https://qiita.com/Sam_yk/items/a048a1255866c3d106c3  |
|  PG（Proglaming language）  |  未作成  |
|  Git |  未作成  |
|  OS  |  未作成  |
|  RDB（DB）  |  未作成  |
|  NoSQL（DB）  |  未作成  |
|  API  |  未作成  |
|  Cache  |  未作成  |
|  Web Security  |  未作成  |
|  Test  |  未作成  |
|  CI/CD  |  未作成  |
|  Design and Development Principles  |  未作成  |
|  Architectural Patterns  |  未作成  |
|  Containerization vs. Virtualization  |  未作成  |
|  Graphql  |  未作成  |
|  Web sockets |  未作成  |
|  Server Sent Event |  未作成  |
|  Web Server |  未作成  |
|  Building for Scale |  未作成  |
新人の頃個人的にありがたかったプラクティス「ザッソウ」

# はじめに

入社5年目の私が、新人の頃にありがたかったチームの雰囲気やプラクティスを思い出して書きます。
チームができてまだ2年目ぐらいのころ、新人として配属になりました。
その頃は正直、チームには雑談をしない雰囲気がありました。（今はそんなこと無いです。）
そんな雰囲気もあって今回のテーマである「ザッソウ」というプラクティスを導入してもらえたのは、ありがたかったです。

## ザッソウとは

「ザッソウ」とは雑談と相談を合わせた造語です。業務において報告だけではなく雑談も重視するコミュニケーションプラクティスの一つです。
また、雑な相談という意味もあり、しっかり結論や質問内容を考えてから相談に行くのではなく、早めに軽い相談をします。
軽い相談なため、相談する側もされる側も心理的な負担が少なく、また、早い段階で成果物のずれに気づき、大きな手戻りを防ぐことができます。

「ザッソウ」を考案したソニックガーデンの倉貫 義人さんの記事が出ています。
詳しくは以下を参照ください。
https://kuranuki.sonicgarden.jp/archives/25159
https://kuranuki.sonicgarden.jp/archives/29640
https://kuranuki.sonicgarden.jp/archives/29669

## 「ザッソウ」を取り入れてみて

特に新人の頃は、チームメンバとの人間関係もできておらず、ちょっとした質問や相談も心理的なハードルがありましたし、タイミングもよくわからず、躊躇することも多かったように思います。
同じような方も多いのではないでしょうか。
「ザッソウ」の考え方を取り入れたことにより、チームメンバ全体で、以下の共通認識が生まれました。
- 雑談は大事。雑談で互いの為人を知った方が、話しかけやすくなり、仕事がしやすい
- 結論や質問内容がまとまっていなくても、だれかに話しかけてOK
- 小さな相談を繰り返したほうが、手戻らずに済む

この共通認識ができたおかげで、先輩社員に話しかける心理的なハードルはかなり下がりました。
雑に話しかけすぎることもありましたが、繰り返すことで、良い塩梅が見つけられたと思います。
また、先輩社員は相談に行った際に、考え方を一緒に伝えてくださったため、以前は相談に行っていた所が、だんだんと自分で結論を出せるよう成長できました。

経験が浅い人とザッソウするには、考え方をセットで伝えることがとても重要だと感じました。
もし、そうでなければ、自分で考えることができないまま今に至っていたかもしれません。
それを快くしてくださった先輩方には、とても感謝しています。

「ザッソウ」を取り入れることで、自分だけで考えて時間がかかりすぎたり、成果物が大きくずれたりすることはほとんど無くなりました。
今でも早めに相談・報告するという習慣が残っているので、とてもよかったです。

# さいごに

もし、自分がチームメンバに仕事を任せる立場だったら、少しずつ相談してくれた方が進捗具合が見えますし、成果物の認識が合っているかも確認できて安心できると思います。
その雰囲気づくりのために、「ザッソウ」という考え方を、相談をする側もされる側もお互いに理解すること重要だと感じました。
また、ザッソウに限らずですが、相談される側は解だけ与えるにならないよう注意しないといけないですね。

冒頭で、「チームには雑談をしない雰囲気がありました」と書いていますが、これは、たまたま雑談が苦手なメンバが揃っていたからで、雑談は悪のような考えではありませんでした。
雑談の重要性をみんな理解したので、朝会で雑談をして慣れたり、雑談が得意な新規メンバの加入により、以前よりどんどん良い雰囲気になっていると感じます。
【Node.js】TypeScript+Puppeteerでスクレイピングしてみる

# はじめに

PythonのSeleniumでのスクレイピングはやったことありましたが、Node.jsでは経験がなかったので、Puppeteerで試してみました。

# Puppeteerとは

Googleが開発したツールで、ウェブブラウザを制御し自動化するためのライブラリです。ウェブページの操作やスクレイピングなどのタスクを簡単に実行することができます。

https://pptr.dev/

# 試してみる

[Qiitaのpuppeteerタグページ](https://qiita.com/tags/puppeteer)のトレンド1位のタイトルを取得してみます

試した環境

```shell
node -v
v18.16.0
```

必要なモジュールをインストール

```shell
$ npm i puppeteer typescript ts-node
```

`tsconfig.json`ファイルを生成

```shell
$ ./node_modules/.bin/tsc --init
```

`package.json`ファイルに以下を追加

```json:package.json
"scripts": {
  "dev": "ts-node main.ts"
}
```

`main.ts`ファイルを作成

```typescript:main.ts
import puppeteer from 'puppeteer'

(async () => {
  // ブラウザを起動
  const browser = await puppeteer.launch({ headless: 'new' })
  // 新しくページを開く
  const page = await browser.newPage()
  // 対象のページへ遷移
  await page.goto('https://qiita.com/tags/puppeteer')

  const result = await page.evaluate(() => {
    // ページの最初のh2タグのテキストを返す
    return document.querySelector('h2')?.textContent?.trim()
  })

  // ブラウザを閉じる
  await browser.close()

  console.log(result)
})()

```

実行してみる（2023/05/30時点）

```shell
$ npm run dev

> dev
> ts-node main.ts

Puppeteerのセットアップから使い方まで〜ブラウザ操作の自動化〜
```

トレンド1位のタイトルが取得できました🥳

# まとめ

簡単にスクレイピングできました。特に要素を取得する際のコードがTypeScriptで書けるのが良いですね。この他にもフォームの入力やスクリーンショットの取得もできるので気になる方は調べて試してみてください。


# 最後に
### GoQSystemでは一緒に働いてくれる仲間を募集中です！

ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=d05a5be545f1dd224d89
Proxmox Web GUIをポート443にリダイレクトする

Proxmoxのポート8006からリダイレクトします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/14e2693e-6a6f-d3cc-0d14-c1975ed8dd73.png)
```
apt install iptables-persistent -y
```
確認ではYesにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/4e14e5aa-1576-1675-27bb-73c1f3b61d06.png)

```
/sbin/iptables -F
/sbin/iptables -t nat -F
/sbin/iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8006
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/c229678f-66e7-1f8a-e3b3-0f952f07e05f.png)

# 経緯
Azure Application Proxy経由でProxmoxがうまく動かなかったため切り分けのため。

# 参考にさせていただいたサイト
https://i12bretro.github.io/tutorials/0435.html
Herokuログイン時、API Unavailableと表示されるところから解決まで

## 事象
いつも通り、リモートにpushし、Herokuに自動デプロイされていると思い、アプリを確認してみると、全く更新されてない事に気がつきました。それで気になり、GithubのDeployment historyを確認したところ、先程の自動デプロイがされてない事に気づきました。

これらの経緯を元に、次はHerokuにログインしてみる事に致しました。
そしたら以下のように表示されました。
![スクリーンショット 2023-05-31 11.41.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961835/e65e6ebb-0997-3a1a-71ed-6adba01f3d51.png)

>API Unavailable
Our apologies, but there seems to have been a problem communicating with the Heroku API. Please check Heroku Status for more details.
If this problem persists, please e-mail support@heroku.com.
>>APIが利用できません。
申し訳ありませんが、Heroku APIとの通信に問題があったようです。更なる詳細はHeroku Statusを確認して下さい。
もしこの問題が存続する場合は、support@heroku.com にメールを送って下さい。

文言のとおり、[Heroku Status](https://status.heroku.com/)を確認致しましたがall green。
困り果てて、「何か対処法はないか」と思い、この事象について検索する事と致しました。

## 検索結果

調べてみると数週間前にも全く同じような事例を見つけました。

https://twitter.com/cj_iom/status/1653322320751083520?s=20

上記の方も、everything is working OKだがweb dashboard, CLIにログインできないと言っています。
redditにもこの事について言及されてたりしました。

https://www.reddit.com/r/Heroku/comments/1357s4t/api_unavailable_and_intermittent_application/

## 進展 / 解決
四の五の言っておりましたら、Twitterの[Heroku Status](https://status.heroku.com/)を確認の上、Twitterアカウントの[Heroku Status](https://twitter.com/herokustatus?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1663753856172593153%7Ctwgr%5Ee4ef77a4bb3205b9a3ccdd880352fbf940782127%7Ctwcon%5Es2_&ref_url=https%3A%2F%2Fqiita.com%2Fembed-contents%2Ftweetqiita-embed-content__03a95150d3d490ea22709c5b7e9b5e97)が新たにpostし、問題を把握したとの事でした。

https://twitter.com/herokustatus/status/1663738648729382919?s=20

とにかく手を合わせて、Heroku Statusの更新を待つ事と致しました。
全く復旧されそうになければ support@heroku.com　にメールで問い合わせる事を検討しておりました。

**その後**
Heroku Statusの更新がありました。
内容は以下のようになります。

https://x.com/herokustatus/status/1663757872461910016?s=20

このpostを確認後、Herokuにログインし直したところ、
**問題なくログインできました。**

無事解決した事もあり、Heroku Statusに感謝を述べ、この話は締めくくる事となりました。

## 最後に
今回の問題に直面した際は、[Heroku Status](https://status.heroku.com/)を確認の上、Twitterアカウントの[Heroku Status](https://twitter.com/herokustatus?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1663753856172593153%7Ctwgr%5Ee4ef77a4bb3205b9a3ccdd880352fbf940782127%7Ctwcon%5Es2_&ref_url=https%3A%2F%2Fqiita.com%2Fembed-contents%2Ftweetqiita-embed-content__03a95150d3d490ea22709c5b7e9b5e97)を確認する事をお勧め致します。
対応がなければ、support@heroku.com に一報入れるのが良いでしょう。

蛇足かもしれませんが、私の場合は、問題を把握してから1時間後程で、Heroku StatusはissueについてのTweetをし、更に1時間強程でresolveされたと報告を受けました、合計の所要時間は2時間程でした。ご参考までに。
openvscode-serverを導入しました

研究室の深層学習マシンにopenvscode-serverを入れて、同じネットワーク内のどのデバイスからでもアクセスできるように、簡単に設定しました。本文はその手順のメモです。

# openvscode-serverのインストール

https://github.com/gitpod-io/openvscode-server の説明に沿って簡単にインストールできます。最新版のtarファイルをダウンロードして解凍したら完成です。
試しに起動してみる、解凍したディレクトリで実行します：
`$ ./bin/openvscode-server --host 0.0.0.0 --without-connection-token`

`--host 0.0.0.0`は外からのアクセスを許可するという意味、`--without-connection-token`はトークンなしでIPとポートだけでアクセスできるようにする、ただし安全性は下がるので、信頼できるネット環境じゃないと推奨しません。今回は研究室内部の限られてるメンバーで使うので便利性を重視します。
起動すると他のパソコンから`インストールしたマシンの内部IP:3000`でアクセスすれば開くはずです。

# openvscode-serverの自動起動

毎回毎回手動で起動するのはやはりめんどい、そしてsshで手動起動しても、sshのsessionが死んだらopenvscode-serverも死ぬというのはまだ面倒臭い、なのでservice化にしてOSが立ち上がったら自動的にopenvscode-serverも起動させるように設定します。

今回はsystemdの仕組みを利用して設定します。参考サイトはこちらです：
https://github.com/microsoft/vscode-remote-release/issues/7125
https://qiita.com/tkato/items/6a227e7c2c2bde19521c
まず`/opt/openvscode-server/bin`というディレクトリ構造を作り、その中に`openvscode-server.sh`というスクリプトを置きます。`/home/username/openvscode-server-v1.78.2-linux-x64/`というのは今回解凍したファイルの場所です。
```openvscode-server.sh
#!/bin/sh
exec /home/username/openvscode-server-v1.78.2-linux-x64/bin/openvscode-server --host 0.0.0.0 --without-connection-token
```
`openvscode-server.sh`に755権限を付与しときます：
`$ sudo chmod 755 /opt/openvscode-server/bin/openvscode-server.sh`
これで半分の準備ができました。

次はsystemdが管理するserviceを定義するファイルを作成します。
`/etc/systemd/system/`に`openvscode-server.service`というファイルを作成します：
```openvscode-server.service
[Unit]
After = network-online.target
Description = Open VSCode Server

[Service]
User = username
Group = usergroup
ExecStart = /opt/openvscode-server/bin/openvscode-server.sh
Restart = on-failure
RestartSec = 30
KillMode = mixed

[Install]
WantedBy=default.target
```
`After`は「〇〇のサービスが起動した後にこのサービスを起動する」という意味で、ここで`network-online.target`を入れると、ちゃんとネットに繋がった後にopenvscode-serverを起動するということになります。
`Description`は自分がこのサービスはなんのサービスなのかが分かるように記入した説明文で、内容はなんでもいいです。
`User`と`Group`は実際のユーザ名とユーザグループ名を記入します。
`ExecStart`はこのサービスを具体的に何を実行するかを指定します。ここではさっき作ったopenvscode-serverの起動コマンド`openvscode-server.sh`を入れます。
`Restart`はもしなんらかの状況で再起動を試みる必要があるかの設定です。ここは`on-failure`に設定して、サービスが起動失敗している場合は再起動を試みる。
`KillMode`はサービスを停止するとき、このサービスが立ち上げたプロセスを殺す時の挙動を設定するところです。openvscode-serverの実行時は複数のプロセスを作成するので、ここは`mixed`設定して、漏れないように殺します。
`WantedBy`の役割と`default.target`の意味はあまり分かりませんでした。
そして`openvscode-server.service`に644権限を付与したらOK。

最後にサービスを使えるようにする手順：
```
# サービスのリストをリロード
$ sudo systemctl daemon-reload

# openvscode-server.serviceの状態を確認、このコマンドの出力に「disabled」という単語が入ってるはず
$ sudo systemctl status openvscode-server.service

# openvscode-server.serviceをenabledにする
$ sudo systemctl enable openvscode-server.service

# もう一回状態を確認したら、「enabled」になっているはず
$ sudo systemctl status openvscode-server.service

# サービスを起動します
$ sudo systemctl status openvscode-server.service
```
これでopenvscode-serverは常時起動しているようになりました。
[Swift] CIImage の Exif を書き換える方法

## 概要

`CIImage` の `properties` を書き換える実装をする機会があったのですが、ネットを調べると `CGImageDestinationAddImage` を使って書き換える方法を紹介している記事が大半でした。

新卒のときに務めていた会社で、僕が尊敬しているシニアエンジニアの方から、イミュータブルプログラミングを心がけるようにと言われていた影響もあって、この方法はイミュータブルプログラミングっぽくなく可読性が悪いと感じており、あまり好きではありませんでした。

先日、Apple Developer Documentation を眺めていたときに、たまたまもっと簡単に、イミュータブルに出来る方法があることを知ったので記事にしました。

## やり方

### 用意するもの

- 書き換えたい画像 (CIImage)
- `CIImage.properties`

### 使用するAPI

[`CIImage.settingProperties`](https://developer.apple.com/documentation/coreimage/ciimage/1645895-settingproperties)

<https://developer.apple.com/documentation/coreimage/ciimage/1645895-settingproperties>

### 手順

- `CGImageDestinationAddImage` のやり方同様、`CIImage.properties` を別の変数に代入して、その変数の辞書を書き換える流れとなっております。

- コピーした辞書を書き換えてそれを適用する点は一緒ですが、指定された画像の変数を書き換えるか (`CGImageDestinationAddImage`)、Exif が書き換えられた CIImage を新規で生成するか (`CIImage.settingProperties`)、という点が異なっています。

1. `CIImage.properties` をコピーする

    ```swift
    let ciImageFromURL: CIImage = .init(contentsOf: URL(string: "https://hoge.com/fuga.png"))
  
    //  MARK: 後の手順で書き換えるので、var で宣言
    var ciImageProperties: Dictionary<String, Any> = ciImageFromURL.properties
  
  
    ```
  
1. 書き換えたいプロパティの辞書をコピーする

    <https://developer.apple.com/documentation/imageio/image_properties>

    こちらのドキュメントに掲載されている辞書のキーを使って、書き換えたいプロパティの辞書をコピーします。
    今回は Exif を書き換えたいので、`kCGImagePropertyExifDictionary` を指定します。

    ```swift
    var exifDictionary: Dictionary<String, Any>? = ciImageProperties[kCGImagePropertyExifDictionary as String] as? [String: Any] 
    ```

1. 書き換える

   - 今回は、`kCGImagePropertyExifDateTimeDigitized` を書き換えてみたいと思います。
   - なお、Exif の日付フォーマットは特殊なので、`DateFormatter.dateFormat` をいじっています。

    ```swift
    var dateFormatterForExif: DateFormatter {
        let formatter: DateFormatter = .init()
        
        formatter.locale = NSLocale.system
        formatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
        
        return formatter
    }
    
    exifDictionary?[kCGImagePropertyExifDateTimeDigitized as String] = dateFormatterForExif.string(from: Date.now)
    
    ```

1. `CIImage.settingProperties(_:)` を使い、Exif が書き換えられた CIImage を生成する

    ```swift
    // コピーした properties に、書き換えた Exif の辞書を代入
    ciImageProperties[kCGImagePropertyExifDictionary as String] = exifDictionary
    
    let exifModifiedCIImage: CIImage = ciImageFromURL.settingProperties(ciImageProperties)    
    ```

以上で、Exif が書き換えられた CIImage を新規で生成することができます。
WSLってなに

## WSL（Windows Subsystem for Linux）

:::note
Windows 10やWindows Server 2019以降のWindowsオペレーティングシステムで提供される機能
→Windows上でLinuxカーネルを実行し、Linuxプログラムやツールを直接実行できる
:::

WSLを有効にすると、Windows上でLinuxディストリビューション（Ubuntu、Debian、SUSEなど）を実行できる
→Windows環境でLinux向けの開発やタスクを実行できる

## WSLのメリット

### 直感的なLinux環境
- WindowsターミナルやコマンドプロンプトなどのWindowsインターフェース内でLinuxコマンドやツールを実行できる
Linuxシェル（Bashなど）を使用して、一般的なLinuxタスクを実行したり、Linuxパッケージをインストールしたりできる

### 開発環境の統合
- Windows上でLinuxベースの開発環境を構築できる
→Linux向けの開発ツールやフレームワークを使用してアプリケーションを開発できる

### ファイルシステムの相互運用性
- WindowsファイルシステムとLinuxファイルシステムの相互運用性が提供
Windowsファイルシステムにアクセスしながら、Linux環境からファイルを操作したり、WindowsアプリケーションからLinuxファイルにアクセスしたりできる

### パフォーマンス
- 仮想化技術を使用せずにLinuxカーネルを直接実行するため、高速なパフォーマンスを提供
→開発やタスクの実行がスムーズに行われる
Pythonで行数不明の標準入力を受けとる

# Pythonで行数不明の標準入力を受けとる

__<例外処理をする>__

whileで繰り返しながらtry, exceptで例外処理をすることでEOFを監視できる。

~~~inputEOF.py
input_line = []
while True:
    try:
        tmp = input()
        input_line.append(tmp)     
    except EOFError:
        break
print(input_line)
~~~
input()を直接splitすると二次元配列になるのでそこは注意。

paiza.ioで問題なく動作しました。昨日同じようにやったら失敗したんだけど何でだろう...。
必ず行数指定してくれるpaizaラーニングは優しいと思いました。
___
参考：[Pythonで標準入力 ~入力行数が指定されていないとき](https://qiita.com/kazukazukazukazu/items/1a03376d06a3ef59a006)
Reactについての備忘録

# Reactについて（完全自分用）

# この記事について
新しいプロジェクトで、reactを使うといわれたので今更ながら勉強。

# reactとは？
UIフレームワーク。
代表的なものにreact.js、vue.js、riot.jsなどがある。

reactの特徴として、以下があげられる。
・SPA
・コンポーネント指向
・仮想DOM
・宣言型

# SPA
Single Page Applicationの略

SPAのメリット
　・ライブラリの読み込みが最初の一回だけでいいから早い。
　（SSR化しない限り、サーバーに読み込みに行かない）
　・レンダリングが豊富

SPAのデメリット
　・作り方によっては、むしろ遅くなる。
　・SEOに弱い。


# 参考URL

### 公式
https://react.dev/learn

### reactについて
#### なぜconstructorにsuperを書くの？
https://qiita.com/hand-dot/items/61a4b808f110b12e4281

### イベントについて
https://qiita.com/jima-r20/items/839da7c2f26366491298

# 最後
参考にした記事があれば多分追加していく
WSL よく使うコマンド


WSL（Windows Subsystem for Linux）では、Linux環境で一般的なコマンドを使用できる

## ディレクトリの移動

```
cd <ディレクトリパス>
```
指定したディレクトリに移動します。相対パスや絶対パスを使用できる

## ファイルやディレクトリのリスト表示

```
ls
```
カレントディレクトリ内のファイルやディレクトリの一覧を表示

## ファイルの作成

```
touch <ファイル名>
```
指定した名前の空のファイルを作成

## ファイルの編集

```
nano <ファイル名>
```
指定したファイルをテキストエディタで開き、編集できる
他のエディタも利用可能
EX) vim、emacs

## ディレクトリの作成

```
mkdir <ディレクトリ名>
```
指定した名前のディレクトリを作成

## ファイルのコピー

```
cp <元ファイル> <コピー先>
```
指定したファイルを別の場所にコピー

## ファイルの移動または名前の変更

```
mv <元ファイル> <移動先または新しい名前>
```
指定したファイルを別の場所に移動したり、名前の変更をする

## ファイルの削除

```
rm <ファイル名>
```
指定したファイルを削除
🔰Djangoでちょっと便利な技


便利だと気付く人がいるかもしれないので残しておきます。

DjangoをVSCodeで編集している初心者に向けて発信します。
VSCodeでDjangoのprojectフォルダを開いたとき、最初にすることとしてターミナルで仮想環境とpathの移動が発生しますが、その時に少し楽をする小技。

# 1.「manage.py」と同じフォルダにダミーのファイルを作る
「manage.py」と同じフォルダに「a」というダミーファイルを作ります。拡張子は無くてもいいです。projectフォルダを作成していない場合は開いたその場所でファイルを作ります。
![ファイルa0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781392/58f00a13-d9ad-a881-0e27-e8d3110a703a.png)

# 2.仮想環境へ入るコマンドを入力
仮想環境を構築したら、仮想環境へ入るコマンドを、さきほどの「a」ファイルに記載しておきます。

ターミナルでWSLを使っていると、windowsのpathの書き方と違ってくるので単純にコピペができません。
VSCodeのショートカット「Shift」+「Ctrl」+ Nで新規ウインドウを立ち上げて、仮想環境のフォルダを開き、「activate」ファイルを探します。

![venv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781392/dc43c356-b6f7-cc1c-279f-8c8a770089a1.png)
activateファイルで右クリックして「パスをコピー」をクリックします。

![venv1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781392/a39e016a-94d2-f04d-4f65-5f0be01b1fa6.png)
コピーしたら元のウインドウに戻って、「a」ファイルに「source 」と打ってその後にパスをペーストします。
![venv2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781392/c6a59047-0939-b169-bbaf-4ebcc1ef42e7.png)

あと、この「a」ファイルはgit管理外にしておくことをお忘れなく。

ここまでが下準備です。

# 3.「a」ファイルを利用する
この「a」ファイルを作っておくと、仮想環境に入る、projectフォルダへの遷移が楽に行えます。

# 仮想環境に入る
「a」ファイルを開いて仮想環境に入るコマンドが記載されているとことでカーソルを __置いて__（__選択しない__）「Ctrl」+ C（これで行をコピーできます）、ターミナルにペーストで仮想環境に入れます。


# projectフォルダ（manage.pyと同列）に移動
VSCodeのエクスプローラの「a」ファイルを右クリック、「パスをコピー」をクリック。
ターミナルで「cd」+「スペース」と打ってペーストし、最後のファイル名の「a」を削除してリターンで移動します。

小ネタでした。
ABC303 - C - Dash 自己解法

# 問題

https://atcoder.jp/contests/abc303/tasks/abc303_c

# 解説
体力を無くすことなく指定されたルートをたどり切ることができるか判定してくださいという問題です。移動中にアイテムを拾うこともあるようです。まず、1歩ごとに愚直に全てのアイテムに対して拾うことがあるか判定する実装を仮に組んだ場合を考えます。これだと、移動回数Nは$N≦10^5$でアイテムの数Mも$M≦10^5$であることから実行時間制限に間に合わないことが予想されます。そこで別の実装方法を考えます。
ここで、高橋君の移動した点に存在するアイテムを小さい計算量で検索できないかを考えます。これは連想配列と呼ばれるものを使えば実現できそうです。連想配列のキーに各アイテムの「位置」を、値に「消費されたかどうか」という情報を持たせます。そして高橋君が移動するたび、高橋君の位置に消費されていないアイテムがあるかを連想配列に対して確認しにいきます。あとは題意にそって実装を組むことで計算量が$O(NlogM)$となり、十分間に合いそうです。C++の場合、連想配列として`map`が使えます。

# 提出コード(コンテスト後)

https://atcoder.jp/contests/abc303/submissions/41863486

ご不明点などがあれば教えていただけると幸いです。
【UiPath】マウススクロールアクティビティを使ってみた

# １．はじめに
　リストボックス形式になっている要素をクリックしようとした際に、対象が画面上に表示されておらず、クリックができないという場面に出くわすことがあります。解決方法としては、人の操作と同じようにマウススクロールをするという方法がありますが、マウススクロールアクティビティの上手な使い方がわからず、うまく実装できないという悩みをお持ちの方も多いと思います。
以下のようなユースケースを考え、実装方法を確認してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/e39e811c-ddb2-bb5a-a767-44390bf02759.png)
　上図のようなデスクトップアプリケーションにおいて、現在表示されていない「メロン」をスクロールしてクリックしたいというユースケースを想定します。

# ２．環境情報
利用する環境は以下の通りとなります。
| ソフトウェア名 | バージョン情報 |
| :--- | :--- |
| OS | Windows10 |
| UiPath Studio | 22.10.5 |
| UiPath.UIAutomation.Activities | 22.10.5 |

# ３．実装方法
### ◆実装の説明
　クリック対象の「メロン」が**完全に表示されているか**を確認し、表示されていない（出現していない）場合スクロールを繰り返し行うという方法をとります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/3a00e942-78c4-e0fc-b10e-a366137133d4.png)
　今回は指定回数繰り返しを利用し、「メロン」が表示されていない（出現しない）場合は「マウススクロール」アクティビティにより、スクロールを行います。一方で、「メロン」が表示されている（出現した）場合は「繰り返しを終了」アクティビティにより繰り返し処理を抜けた後に、「メロン」をクリックします。
　また、10回に到達しても「メロン」が表示されていない（出現しない）場合は、例外が発生するようにしています。これは、無限ループになることを防ぎ、ロボット実行の安全性を考慮した実装をしています。実際の最大数は選択項目の数などを考慮して設定していただくことをお勧めいたします。

### ◆設定のポイント
#### 設定ポイント①：可視性の確認
　「アプリのステートを確認」アクティビティでは、プロパティ内「入力」 -「可視性を確認」を「完全に表示されている」にすることで、画面上に可視できるかを判断することが可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/3339c1de-db1c-6744-73ec-88e2301ad723.png)

#### 設定ポイント②：スクロール対象の指定
　「マウススクロール」アクティビティでは、以下に示すようにリストボックスの要素を指定することが必要となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/d2fb7b3f-3d96-cc03-0267-7f574624b600.png)
　画面上のどの部分をスクロール対象とするかしっかりと対象の画面要素がどこかを考えましょう。
画面全体であれば、フォーム全体（デスクトップAPの場合）、Webページ全体（WebAPの場合）というように正しい位置を指定しましょう。

# ４．最後に
　要素の存在確認ロジック（クリック要素が出現しているかの確認や出現していない場合の対処）と操作ロジック（実際のクリック操作）を分離することで、以下のような効果があると考えています。
　・保守性向上：対抗システムに変更が発生した場合も対処がしやすい
　・可読性向上：処理の目的がパーツごとにわかりやすい
皆様も完成したワークフローに対して○○性という言葉を意識して評価すると、良いワークフローが何かということを考えるきっかけになると思いますので、参考にして頂ければと思います。
CloudFront がワンクリックセキュリティ保護をリリース

# ■概要

CloudFrontの構築にてワンクリックでのWAF適用が可能となりました。
ディストリビューション作成時、作成済みディストリビューションの設定画面にも変更がありました。

Amazon CloudFront がワンクリックセキュリティ保護をリリース
https://aws.amazon.com/jp/about-aws/whats-new/2023/05/amazon-cloudfront-one-click-security-protections/

# ■ディストリビューション作成時

AWSコンソールより、CloudFront → ディストリビューション作成に進むと下記のような項目が追加となっているようです。

![CF1_20230531100543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/d56b8cfe-15f2-f94c-a6d7-0485dc2b6eb4.png)

↓ 「セキュリティ保護を有効にする」を選択すると、これだけで適用が完了となります。

![CF2_20230531110508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/aeb5142f-b411-82ed-7a9e-16c936ea8375.png)

ちなみに、この段階で設定変更出来るのは「Use monitor mode」のオンかオフのみとなっています。
これはWAF設定によりブロックされるリクエスト数をカウントするモードで、実際にブロックを開始するにはこちらはオフにしておく必要があるようです。

最後の方には価格の見積もりが表示されます。
想定リクエスト数の入力で即座に見積もりが出来るので、ユーザーに優しい仕様ですね。

# ■設定変更時

概要にも記載しましたが、作成済みディストリビューションの設定画面にも変更がありました。
WAFの設定は画面上部の方に来たみたいですね。アップデートを知らずに設定を見たら知っている場所にWAFがなくて驚きました…。

![設定変更_20230531111817.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/dc8f4eeb-5aed-7c5d-7301-a0a9c81f68b4.png)

Web ACLを適用する場合は下記の通り既存のWAFを使用するよう設定します。

![webACL_1_2023-05-18_20h47_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/2b6705a5-1bf6-0729-abda-fb05902bb339.png)

# ■最後に
導入が簡単に分かりやすくなったのはとてもいいですね。
料金も使用ケースによってはとてもお安く済みそうです。
React + TypeScript: flexDirectionをstyleに設定すると怒られる

スタイルをオブジェクト(`style`)に定めて、要素の`style`属性に与えたら、`flexDirection`だけ認めてもらえず怒られました。


# 変数にオブジェクトで定めたCSSの`flexDirection`が要素の`style`属性に設定できない。
絞り込んだ問題のコードはごくシンプルです。何がいけないのか、よくわかりません。

```react
const style = {
	flexDirection: 'column'
};
export default function App() {
	return (
		<div style={{ ...style }}>

		</div>
	);
}
```

エラーメッセージはつぎのとおりです。`flexDirection`の型`string`が弾かれているらしいことはわかります。

> (property) React.HTMLAttributes<HTMLDivElement>.style?: React.CSSProperties | undefined
>
> Type '{ flexDirection: string; }' is not assignable to type 'Properties<string | number, string & {}>'.
  Types of property 'flexDirection' are incompatible.
    Type 'string' is not assignable to type 'FlexDirection | undefined'.ts(2322)


# 結論: オブジェクトを`React.CSSProperties`で型づけする
はじめに結論を示してしまいましょう。スタイル(CSS)のオブジェクトは、`React.CSSProperties`で型づけしてください。

```react
import { CSSProperties } from 'react';

const style: CSSProperties = {
	flexDirection: 'column'
};
```


# 他のCSSプロパティは通る
でも、他のCSSプロパティは通ります。さらに、要素の`style`属性にインラインで`flexDirection`を加えれば、何も怒られません、

```react
const style = {
	display: 'flex',
	// flexDirection: 'column'
	justifyContent: 'space-evenly',
	alignItems: 'center'
};
export default function App() {
	return (
		// <div style={{ ...style }}>
		<div style={{ ...style, flexDirection: 'column' }}>

		</div>
	);
}
```


# 型を定数にする
問題は、`flexDirection`の型が`string`と推論されてしまうことです。`string`では広すぎ、絞り込んだ定数にしなければなりません。

>  Types of property 'flexDirection' are incompatible.
    Type 'string' is not assignable to type 'FlexDirection | undefined'.ts(2322)

そこで、型注釈により定数にすれば、あっさりと通ります。

```react
const style = {
	// flexDirection: 'column'
	flexDirection: 'column' as 'column'
};
```

さらに、オブジェクト(`style`)の定め全体を`as const`で限定しても構いません(「[TypeScript usage](https://mui.com/system/getting-started/the-sx-prop/#typescript-usage)」参照)。

```react
const style = {
	flexDirection: 'column',
// };
} as const;
```

それでも、改めて結論として、スタイルを定めるオブジェクトは`React.CSSProperties`で型づけするのがよいでしょう。型推論によるリテラル型の拡張や限定については、「[Literal Type Widening in TypeScript](https://mariusschulz.com/blog/literal-type-widening-in-typescript)」が参考になります。
WebにおけるUAとGA4の主な違いまとめ

# はじめに
ユニバーサル アナリティクス プロパティ（以降UA）は2023年10月1日に終了します（有料版のUA360は2024年7月1日に終了）。

そのため「ユニバーサル アナリティクス プロパティ」から「Google Analytics 4 プロパティ（以降GA4）」に移行が必要となります。

WebにおけるUAとGA4の主な違いについて以降に記載します。
（スマホアプリや動画に関してはここで触れません）

## 全てイベントに統一された
UAの計測はページビューが基本でしたが、全て同じイベントという概念で統一されました。

![スクリーンショット 2023-05-30 22.46.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246392/4aa78dbf-8baa-cb3c-afc8-97cd989ebf58.png)

## 自動で計測できる項目が増えた
1. スクロール数
ページの長さの90%まで辿り着いた時に自動で計測されます。

2. 離脱クリック
ユーザーが自社ドメイン以外のリンクをクリックした時に、どのページでどのリンク先のリンクをクリックしたかを自動で取得してくれます。

3. ファイルのダウンロード
ユーザーがリンクをクリックしたファイルをダウンロードした時に、どのページでどのファイルが何回ダウンロードされたかを計測する事ができます。

## 直帰率がなくなりエンゲージメント率が追加された
GA4からは「直帰数（率）」（1ページだけみた離脱した数や割合）という概念がなくなりました。
ページやサイト全体の直帰率を見ることはできません。

GA4が新たに用意したのが「エンゲージ数（率）」になります。
訪問時に「サイトと関係性を持った」という意味合いになります。

以下のいずれかの条件を満たした場合、その訪問は「エンゲージがあった」と判断します。

・滞在時間が10秒以上（この秒数は10～60秒の間で変更可能）
・2個以上のイベントが発生した（例：複数ページ閲覧した）
・閲覧したページやアクションがコンバージョン（成果）として登録していた

つまりエンゲージ数や率が高いほど、より関係を持てた回数や率が多いことを意味します。

## 離脱率の定義が変更された
ページを閲覧後に離脱した割合を見るための「離脱率」が、GAでは分母がページビュー数でしたが、GA4ではセッション数に変わっています。

![スクリーンショット 2023-05-31 10.22.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246392/e182d265-ac6c-152e-3cdd-8503eb8dff70.png)

### UAの場合のページAの離脱率
・ページAが最後だった回数＝1回
・ページAのページビュー数＝4回
よって、ページAの離脱率＝1÷4=25%

### GA4の場合のページAの離脱率
・ページAが最後だった回数＝1回
・ページAが存在するセッション数＝3回
よって、ページAの離脱率＝1÷3=33%　

こちらの変更に伴い、GA4での離脱率はUAより高くなります。

## セッションの定義が変わった
セッション（いわゆる訪問）の定義も変わりました。

代表的なところとしては

・日をまたいでもセッションが切れなくなった
（UAでは日をまたいだ訪問は2セッション扱いになっていた）

・サイト外に出ても30分以内に戻ってくれば1セッションとしてカウントする
（UAでは別サイトに移動して戻ってきた場合は別セッションとなっていた）

などが挙げられます。

## インサイトの機能が大幅に強化された

過去データをもとに機械学習から異常値を通知する「自動インサイト」の機能が大幅に強化されました。

急激にトラフィックが増えた参照元や減少したページなどがインサイトの画面にいち早く表示されるため、気づきやすく、調査時間も大幅に短縮できます。

インサイトには、異常な変化や新たな傾向を自動で通知する「自動インサイト」のほかに、通知条件を自身で設定することができる「カスタムインサイト」があります。

# 引用・参考文献
- [[GA4] 次世代のアナリティクス、Google アナリティクス 4 のご紹介](https://support.google.com/analytics/answer/10089681)
- [GA4のイベントの基本的な考え方](https://ayudante.jp/column/2022-07-07/11-00/)
- [新しいGoogleアナリティクス「GA4」、変化とその価値](https://www.mediatechnology.jp/entry/2022/04/04/110000)
- [いちばんやさしいgoogleアナリティクス4の教本](https://prtimes.jp/main/html/rd/p/000004741.000005875.html)
【Tips】エンジニアのための命名規則 🔰



初めてプログラミングに触れる方や、経験者でも名前をつけることに迷うことはあります。
この記事では、エンジニアが知っておくべき命名方法について紹介します。 （初心者向け🔰）

## 1. 名前は具体的で簡潔に

関数や変数の名前はその目的や機能を明確に表すようにしましょう。適当な名前よりも、具体的で簡潔な名前が理解しやすく、保守もしやすいです。 

例えば、関数名には動詞を使うと良いです。

- `calculateSum()` - 合計を計算する
- `printMessage()` - メッセージを印刷する

## 2. 名前の長さと範囲

一般的に、変数や関数のスコープが広いほど、名前は長くて具体的にします。逆にスコープが狭い場合、名前は短くても大丈夫です。

例えば、ループ変数は `i`, `j` のように短く、一方で、グローバル変数は `totalNumberOfUsers` のように具体的にします。

## 3. 一貫性のある命名規則

プロジェクト全体で一貫性のある命名規則を使用することも重要です。これにより、他の開発者がコードを読む際に迷わないようにします。

例えば、一部ではキャメルケース(`myVariable`)を使用し、一部ではスネークケース(`my_variable`)を使用すると、混乱を招く可能性があります。

## 4. 略語を使わない

特に必要がなければ、略語は避けましょう。略語は作者にとっては理解しやすいかもしれませんが、他の開発者にとっては必ずしも明らかでないことがあります。

例えば、`calcSum()` ではなく、 `calculateSum()` のようにします。

命名はプログラミングの中でとても重要な要素です。はっきりとした名前をつけることで、他の開発者にコードの意図を伝え、バグを減らすことができます。
ルーターの熱対策

FON2405のSOC(RT3050)にヒートシンクを貼って放熱するようにしてみました。ケースに収まらなくなるので、あまり厚くないものがよいです。

![Fon3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/5dc03a4f-0130-13da-ac42-00165c4fda46.jpeg)

このモジュールの場合、上部には通気用のスリットがなく底面にはあり、またSOCが裏面になるので、逆さま置くのが良さそうです。

上と下のケースの間に微妙なスリットがあるので、そこから空気が入り上に抜けていくようになります。

FON2405は熱対策をまったく無視して、デザインされています。結構壊れているものも多く、そのためではないでしょうか。

設置面と空間を作るために、とってあった日本酒のふたを逆さまに置くための足にします。

![Fon2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d730b3f7-d6fe-9642-b8e5-2e41c65de4c6.jpeg)

廃物利用は小さい頃に見ていたと思う、「できるかな」の精神かもしれません。

![Fon1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d8e65036-35f3-2536-7cbe-c66eac233e63.jpeg)

逆さまに置くとLEDが見えなくなるのが、ちょっと残念です。

以前は長期間稼動させると、起動しなくなるモジュールがありましたが、これらの対策を行ってからは、無くなりました。

バッファローのルーターは縦に基板が入っているので立てておくのがよいので、足を作ってみました。

![写真（2023-09-11 10.22）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/718c8ea8-7641-e0a2-9910-408f3c445551.jpeg)

すこし切ってくぼみにはまるようにしてあります。ハードオフで買って来たものなので、スタンドがありません。

これはよく倒れて安定しないので、結局横にして下に日本酒のふたを置きました。
VSCodeで2つファイルを比較、差分を表示する

記念すべき第1回目の投稿です。

エンジニア転職を目指して１ヶ月たちましたが、Qittaの発信をまったくしていませんでした。
初回の投稿は身の上話であったり、転職活動の意気込みなどを書かなければと思うと重い腰がなかなか上がりませんでした。
このまま投稿せずに時間だけが経つのならと、捨て鉢でどこにも需要のないであろうVSCode　Tips記事を投稿します。

「VSCodeで2つのファイルの差分を表示する」
まず比較する二つのファイルを開き、いずれか一つをアクティブにする。

コマンドパレットを開く。「表示」メニューの中にある「コマンドパレット」をクリックしてください。ショートカットキーの場合は、Shift + Command + P。

コマンドパレットが表示されたら「比較」と入力。

比較する 2 つ目のファイルをクリック。

以下のようになれば成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322243/5bce318f-e70b-2868-43d9-9b4c7f237189.png)

参考文献
JavaDrive_2つのファイルの内容を比較して差分を表示する
https://www.javadrive.jp/vscode/editor/index3.html
【その４】具体的な処理を入れる

<br>[【その１】RPA初心者と歩むPower Automate活用日記【ポイ活】](https://qiita.com/tantanshio/items/2b741584f65d8ce967f8)


# ◆具体的な処理を入れる

今回の選択対象はタグ情報が取得できないアプリ上の項目を選択させるため、
画像をもとにクリックさせる「マウスを画像に移動」を使用する



loopとEndの間にドロップする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/812803b4-d603-7a7e-2acb-dae1874cff2f.png)


すると以下の設定画面が表示されるので
「画像を選択してください」をクリック


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/c6f11453-75f3-08ce-42f2-619a4e624a94.png)

「画像のキャプチャ」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/721837f5-5b15-29b0-aef4-ea8c3a66d3f1.png)





マウスカーソルが十字カーソルに切り替わるので
範囲設定で　クリックさせたい場所が分かる画像を設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/692d064d-eefa-181a-e22a-414de16111ce.png)

設定した画像が表示されるので、問題なければ名前を付けてOKをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/6dd146ad-30d6-ac33-d366-29d7bb0a3a6b.png)




これにより、このステップは

設定した画像を見つけたら、マウスカーソルをその画像の中心に移動させるという設定になる

しかし、移動だけでは処理が足りないため、

「マウスの移動後にクリックを送信します」をクリックし、有効にして　クリックまで実行させるようにする

そして、「保存」をする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/c4be0b9b-6ecb-624a-b497-70ea66cd0321.png)



これで1つのステップが完成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/748e8618-6896-0c34-996c-9ac873a3dfcc.png)


このままの実行だと無限ループで同じ個所をクリックし続けてしまうので
防ぐためにループを抜ける処理を1つ入れてあげて実行テストをしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/6e1b36d9-af95-2d48-8c05-0b2dbe2535e2.png)

マウスがホーム上まで移動し、クリックを行い　ロボットは正常に終了した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/22773013-ccaf-1108-1802-6e6e14943a0e.png)


次はミッションにある以下の項目があった場合のみクリックさせる処理を入れたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523511/8431ac3f-d108-22d5-9551-ff79926e2282.png)


# ◆次回　【その５】分岐処理を入れる
初学者メモ　シャッフル

# はじめに
投稿2回目！
「画面上で複数人をランダムに2グループに分けたい」
「特定の条件の比率を揃えたい」
Rubyのメソッドを調べて試行錯誤した記録です

# 手順
1. 条件を設ける
1. ランダムにシャッフル
1. シャッフルした者をグループに割り当てる

# 実装
### ①特定の条件に分ける
selectメソッドを使用
```
配列.select { |要素| 条件式 }
```

今回は男女比率を合わせる
```:controller.rb
male = students.select { |student| student.gender == "male" }
female = students.select { |student| student.gender == "female" }
```

### ②各グループの人数を決定
グループ数は2とします
```:controller.rb
group_count = 2
```
各グループの男女の人数を計算
```:controller.rb
male_per_group = (male.size.to_f / group_count).ceil
female_per_group = (female.size.to_f / group_count).ceil
```
Floatクラスのceilメソッドを使用
```
浮動小数点数.ceil
```
浮動小数点数を切り上げできます

### ③いよいよシャッフル！
```:contoroller.rb
male.shuffle!
female.shuffle!
```
元の配列自体を並び替えたいため破壊的メソッドを使用
```
配列.shuffle!
```

### ④グループごとに割り当てる
あとは、配列を用意し、割り当てるだけ
```:controller.rb
# グループ分けの結果を格納する配列
groups = []

# グループごとにそれぞれ割り当てる
group_count.times do |i|
  group = []

  # maleから割り当て
  group.concat(male.shift(male_per_group))

  # femaleから割り当て
  group.concat(female.shift(female_per_group))

  groups << group

end

# グループ分け結果をビューに渡す
@grouped = groups
```
メモ①「concatメソッド」
```
group.concat（引数）
```
concatで指定した引数がgroup配列に追加される

メモ②「shiftメソッド」
concatの引数
```
male.shift(数値)
female.shift(数値)
```
配列の先頭から指定した数の要素を取り出せる
メモ③演算子「<<」で 要素を追加
```
こちらに追加　<< こちらから
```

# まとめ
- selectメソッドで配列から特定の条件に合うものを選べる
- ceilで浮動点小数点を切り上げできる
- shuffle!で配列自体を並び替えられる
- concat メソッドで指定したものを配列に追加できる
- shiftメソッドで、配列の先頭から指定した要素を取り出せる

Rubyの文法が大切だと身に染みて感じました
2回目の投稿
ご指導、ご指南いただけると幸いです
[自分用] TypeScript を使用するメリットと基礎的な知識

# 記事の目的
- 自分が学習したことを忘れないようにするための備忘録
- TypeScriptを学んだことがない方に概要を知ってもらう

## 目次
- ### TypeScriptを使用するメリット
- ### TypeScriptの型
- ### 設定ファイルについて
## TypeScriptを使用するメリット
- ソースをコンパイルするので、アプリケーションを実行する前にエラーを発見することが出来る。
- 型や関数を明示的に宣言することができることにより、関数の引数に想定していない型の値が渡された際や戻り値などに想定していない値が返された際ににエラーとして見つけることが出来る。
また、他の人がコードを見たときにコードの意図を読み取りやすくなる。


## 主なTypeScriptの型
#### プリミティブ型
- string => 文字列
- number => 数値(整数、少数など全ての数値)
- boolean => 真偽(true,false)
- [] => 配列
- enum => 列挙型、複数の定数を格納する
- object => オブジェクト型、stringやnumber型などの要素を格納することが出来る

## 設定ファイルについて
### tsconfig.jsonでTypeScriptに関する設定を行っている
#### 主な設定内容
- include => コンパイルするtsファイルを指定
- exclude => コンパイルしないtsファイルを指定
###### 上記の二つは"compilerOptions"の外に記載


- target => コンパイルするjsのバージョンを指定
- lib => 使用するライブラリの指定(指定なしの場合デフォルトのlibの設定値を使用)
- sourceMap => Chromeの開発ツールなどでデバッグする際にTypeScriptのファイルでデバッグをすることが出来る(現在は非推奨、vscode内でデバッグすることが推奨されている)
参考：https://qiita.com/yuzukaki/items/68ca1aed777b296145d5
- outDir => コンパイルされ作成されるjsファイルの作成先フォルダの指定
- noEmitOnError => tsファイル内でコンパイルエラーが存在している際に、jsファイルをコンパイルするか否か

## まとめ
今回はあくまで、基本中の基本の知識を自分用のメモとして作成。
もしもこれからTypeScriptを学ぼうか迷っている方がいましたら、少しだけ参考になれば嬉しいです。

また、これ以外の知識も細かく切り分けて共有出来たらと思っています。
定期的にLambda関数を実行する方法

# はじめに
バッチ感覚でLambda関数を実行したい。
定期的に、そう、例えば1時間おきに、毎日0時に、毎週火曜日の9時に、とか、特定のタイミングでLambda関数を実行したい。
そんなときに使える方法を備忘録として残しておく。

# Lambda関数を作成する
何の変哲もないLambda関数を作成する。
コードはデフォルトのママとする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/29637611-3350-ece6-d1b3-fdb2993cf81f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/5eda21dc-a8d8-81ca-35d0-9d9ec133e7e0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/68d1749d-f4bb-054b-6eea-5c863f1836fa.png)

# トリガーを設定する
EventBridgeというサービスを使うと、cron式を書いて任意のタイミングでLambda関数を実行できる。
ただし、UTC時刻で動くので日本時刻と9時間ズレる。そこだけは注意が必要。

トリガーを追加をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/181f4ef2-4fcd-2dbd-201f-b7ea198fa80d.png)

EventBridgeを選択し、任意のルール名とcron式を入力する。
今回は1時間おきに実行を試してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/95ae90e5-55d4-5caf-0c12-aac5e0788c74.png)

トリガーが追加されたことを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/339fd304-ae11-b615-b3de-d60a9b5dc9d1.png)

# 検証
CloudWatchにてLambda関数の実行ログを確認する。
ちゃんと1時間おきに実行されているのが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/64d8f711-310f-4209-10db-e7ee8fd2e224.png)
非エンジニアがIT業界の用語に翻弄されながら培った知識_その②

# これは何?
- [前回の記事](https://qiita.com/yukihiro-toda/items/aefc38739608f8c56e2a)の続き
- 非エンジニアの自分がQiitaに勤めてから知ったIT関連の知識

# この記事の目的
- 非エンジニアの方
    - IT関連の用語について、ざっくりとしたイメージを持ってもらう
- エンジニアの方
    - 非エンジニアの人はこういう単語を知らないかもなーと感じてもらえればと思います。



# 知らなかった用語
### スクラム開発
- アジャイル手法の1つ
    - ざっくりいうと「少しずつ作りながら試して完成させていきましょう!」という開発方法 
- ラグビーの「スクラム」が語源らしい
### ライブラリ
- 色んな機能（プログラム）が入ったファイル
- 新しいサービスを開発する際に、0から全部コードを作るのは大変
- 「履歴情報を出す」など、**あるあるな処理コード**がライブラリに入っており、それを利用させてもらい開発作業を楽にする

### データサイエンティスト
- 新しい職種で定義がはっきりしていない
- 莫大なデータを分析・整理・考察して業務を良くする人
- 例えば
    - 回転ずしの皿にICチップを埋め込み、顧客データを集め改善させていく等

### 上流工程,下流工程
- 上流工程
    - システム開発の前半部分のこと
    - 企画、納期、条件などを考えて設計すること
    - イメージは「目的地まで時間重視で新幹線を使う、健康重視でチャリを使う等」の方針や方向性を決める
- 下流工程
    - システム開発の後半部分のこと
    - 上流工程で決まった事を実際にやること（コードをうつ、動作確認をする等）
## フロントエンドエンジニア
- 企業によって解釈が違う
    - インターネットサイトで利用者が目に見える部分を設定する事
    - 通販サイトで言うと、検索バーや商品などを分かりやすいように配置したりすること
- **バックエンド**というのもある
    - 通販サイトで言うと、注文確定時のクレジットカードや発注の処理など裏側（バック）を設定する事

## ローンチ（英単語はlaunch）
- 「新しいサービスやサイトを開始しました!」を恰好つけて言った事
- 例文
    - 新サービスを今からローンチします!!等

## SaaS（サースまたはサーズ）
- Software as a Serviceの略
- ネット経由でソフトを使うサービスの事
    - サービスの例
        - Slack、Chatwork、Zoom、Google カレンダー、マネーフォワード、Gmail、Dropbox、Salesforce等

## Docker
- 自分のPCに【仮想環境】を作るツール
- 仮想環境とは?
    - 自分のPC内に「もう1つPC」があるイメージ
    - 映画「ドラえもんのび太の新恐竜」に出てくる【飼育用ジオラマセット（恐竜を育てる為に小さな別世界を作る）】みたいな
- 仮想環境があると何がいいの?
    - アプリをインストールするとPC本体に影響を及ぼすこともあるが、仮想環境にインストールすれば本体のPCに影響が出ない
    - アプリを利用する為に動作環境を整えるケースもある。別の人にアプリのテストなどを依頼する場合、動作環境も含めて仮想環境を渡すことが出来る


## 最後に
- まだ知らない単語はありますし、新しい用語も出てきます。翻弄される日々は続きますが、めげずに頑張ります。
SharePointサイトでマークダウンを利用する備忘録

# はじめに
SharePointでサイトを作成し、マークダウンを利用することが出来ます。が少しクセがあるので備忘録をつくりました。
公式：[マークダウン web パーツを使用する](https://support.microsoft.com/ja-jp/office/use-the-markdown-web-part-6d73c06d-2877-4bc9-988b-f2896016c50b)

## 改行
`<br>`
が使えないので、2行以上段落を入れたい場合は
```
&nbsp;

```
を利用する。
単純に一段落入れる場合は、そのまま改行で大丈夫です。

## イメージファイル（画像）
画像をSharePoint内に保存して、マークダウンで表示する手順としては、次の通りです。

1. サイト作成後、任意の画像をサイト内に保存
2. サイト コンテンツ > サイトのリソースファイル > SitePages > 「作成したサイト名のDirectory」に画像を保存
3. 画像を開き、画面上部の三点リーダー「・・・」 > オリジナルを表示
4. URLをコピーして利用

## 一般的なMD
公式
```
マークダウン クイック リファレンス
よく使用されるマークダウン構文の例を示します。
ヘッダー
# ヘッダー1
## ヘッダー2
### ヘッダー3
#### ヘッダー4

強調
**太字**
Ctrl-B
_斜体_
Ctrl-I
~~取り消し線~~
Ctrl-Dash

段落
>      Blockquote
````コード````

リンクと画像
[Contoso](http://www.contoso.com/)
![代替テキスト](Contoso.png)
Ctrl-L

リスト
番号付きリスト
1. 最初の番号付きアイテム
2. 2 番目の番号付きアイテム
箇条書き
* 最初の箇条書き項目
* 2 番目の箇条書き項目

テーブル
| ヘッダー 1   |  ヘッダー 2  |   ヘッダー 3 |
|-----------|:---------:|----------:|
| 1       |    2    |     3 |
```
我々はRailsのTurboと向き合わなければならない

# Turboとは
Railsアプリの開発で直面する問題として、著名ないくつかのGemがインストールできないというものの他に、以下のようなものがあります。

・画面遷移が行われない
・Javascriptのloadイベント等が発火されない
等など

その他トラブルに関しては以下の記事で詳しくまとめてくださっています。

https://qiita.com/jnchito/items/5c41a7031404c313da1f#turbo%E3%81%8C%E3%81%84%E3%82%8D%E3%81%84%E3%82%8D%E3%81%A8%E5%8E%84%E4%BB%8B

これは、デフォルトでインストールされるTurboによって引き起こされている問題です。
Turboには以下のような機能があります。

・Ajaxで良さげに部分更新してくれる
・SPAっぽいものを手軽に書ける
・delete等のmethodでリクエストを投げられる
・確認ダイアログを手軽に出してくれる

しかし、自動で入って自動で動作するため、余計なおせっかいとなることも多く、とりわけ画面遷移が行われない問題とJavascriptのloadが発火されない問題に直面する人も多いと思います。
ところが、だからといってGemをインストールしなければ、各種methodを投げることや確認ダイアログを表示することが手間になってきます。

では、どうすればよいか。

# アプリ全体で無効化して部分的に有効化する
・想定外の箇所でのトラブルを無くしたい
・各種methodでのリクエストや確認ダイアログは意図して行うもの
上記を考えると、全体で無効化して部分的に有効化するオプトインの形を取ったほうが良いでしょう。

具体的な方法は以下のとおりです。

```ruby:app/javascript/application.js
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"

Turbo.session.drive = false; # この行を追加してTurboを無効化する
```
```html
  <div data-turbo="true"> <!-- 先祖要素に data-turbo="true"を追加 -->
    <%= link_to "ログアウト", destroy_user_session_path, data: { "turbo-method": :delete, "turbo_confirm": "ログアウトしますか？" } %>
  </div>
```

これだけでOK。
data-turbo="true"の内側のブロックでだけTruboが有効になります。

まぁ、実際問題向き合っていると言うよりは上手いこと逃げているだけですが、多分これが最良だと思います。
[PostgreSQL]pg_subscriptionはクラスタ内の全データベースで共有される

作成したサブスクリプションの情報はpg_subscriptionを参照することで確認できます。
```
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_subscription;
-[ RECORD 1 ]----+----------------------------------------------------------------------------------------
oid              | 284607
subdbid          | 17135
subskiplsn       | 0/0
subname          | sub
subowner         | 10
subenabled       | t
subbinary        | f
substream        | f
subtwophasestate | d
subdisableonerr  | f
subconninfo      | dbname=example host=example.com user=replication
subslotname      | sub
subsynccommit    | off
subpublications  | {pub}
```
pg_subscriptionはクラスタ内の全データベースで共有されます。
つまり、サブスクリプションを設定したデータベースでなくても、上記SQLを叩くと同じ出力が返ってきます。
[マニュアル](https://www.postgresql.jp/document/15/html/catalog-pg-subscription.html)に以下のように記載があります。
> ほとんどのシステムカタログとは異なり、pg_subscriptionはクラスタ内の全データベースで共有されます。 つまりクラスタごとにpg_subscriptionの実体は1つだけ存在し、データベースごとに1つではありません。

自分は、サブスクリプションを設定していないデータベースにpsqlで入って上記SQLを叩いてサブスクリプションが設定されて**いない**ことを確認しようとして、びびりました。あれ？なんで、レコードが出力されるのかな…と思いました。

subdbid列がサブスクリプションが存在するデータベースのOIDになるので、サブスクリプションが設定されていないことを確認するには
```
postgres=# SELECT oid, datname FROM pg_database;
  oid  |   datname
-------+--------------
     5 | postgres
 17135 | publicuserdb
     1 | template1
     4 | template0
(4 rows)
```
と合わせて確認すればOKです。
Cognos Analyticsで視覚化からのドリルスルーを実施する

# はじめに
Cognos Analyticsの視覚化からもドリルスルーができるようになっているので、その設定方法を紹介します。
本記事では11.1 の視覚化での設定方法とドリルスルーの実行を紹介していますが、11.0 の視覚化でも同様に、ドリルスルーを設定することが可能です。

# 視覚化のドリルスルーを設定する

視覚化にドリルスルーを設定する際は、「視覚化データ・セット」のプロパティから「ドリルスルー設定」を実施します。
※「視覚化データ・セット」のプロパティを選択する際は、赤点線枠のあたりをクリックすると選択できます。
または、「先祖を選択」から選択することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/5ca4c5c4-e589-7988-1b6f-d615ff1e98f6.png)


ドリルスルーの設定自体は今までのドリルスルー設定と同じように実施できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/89e12de5-fb49-ff0a-f6f8-3ae4a7e329b7.png)

# 視覚化からドリルスルーする

ドリルスルーを設定した視覚化からのドリルスルーは2か所から遷移することが可能です。
① 視覚化をダブルクリックする
② 閲覧アイコンからリンクする

## ① 視覚化をダブルクリックする

従来のグラフと同様、視覚化のプロットをダブルクリックすることでドリルスルー遷移が可能です。
データアイテムの値を引き渡す設定になっていれば、ドリルスルーパラメータとして引き渡すことが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/f793a012-bc79-c789-d41c-f2596babb612.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/b4308b45-314e-c85e-921c-a1ca0b9d2335.png)


## ② 閲覧アイコンからリンクする

ターゲットレポートで「完全な双方向性で実行」が有効な場合、レポート実行に表示される閲覧アイコンからドリルスルーすることが可能です。
事前に視覚化をクリックし引き渡すデータアイテムの値を選択しておいたり、フィルターを追加してデータを絞っておく必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/38c4a335-6312-3fa3-5afb-f101bcc46ede.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/d5e9b72a-a482-6a73-bf58-fc2c4f5f3c55.png)

# 従来のグラフとの相違点

## 「完全な双方向性での実行」が有効なレポートで実行できる

むしろ、視覚化11.1を使用している場合は、完全な双方向性での実行を有効にしておく必要があります。
無効にすると視覚化11.1が表示されなくなるので注意です。
また逆に、完全な双方向性での実行が有効の場合は、従来のグラフをクリックしてのドリルスルーは動作しなくなります。
この場合は、閲覧アイコンからのドリルスルーを実施する必要があります。

## ドリルスルーを設定できる箇所が1箇所のみ

従来のグラフでは、「グラフ全体」、「軸ラベル」、「凡例」の3箇所でドリルスルーを設定することが可能でした。
視覚化11.1では、先に紹介した「視覚化データ・セット」の1箇所のみになります。

(従来のグラフでドリルスルー設定が行える箇所)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/9ef20f8e-e0cb-7a91-3c98-d64f5a7ac54d.png)

## ドリルスルーで使用するデータアイテムは視覚化に配置する必要がある

従来のグラフでは、グラフ上に登場しない項目でも、「プロパティ」項目で設定することで、ドリルスルー設定で使用することが可能でした。
視覚化11.1のドリルスルーでは、「横棒」「長さ」「色」に配置している項目のみをドリルスルー設定で使用することができます。
視覚化11.1のプロパティには、「プロパティ」項目が存在しないので、必要な項目はすべて視覚化上に配置するする必要があります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/32e557d0-75a9-a638-cc32-ee8b167ac70a.png)


プロパティで設定をしていると、グラフ上に配置していなくても、ドリルスルーで使用可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/c064c45e-c70d-41f1-8be9-140a17f2904f.png)

視覚化には、「プロパティ」がないので、必要な項目は視覚化上に配置する必要がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146283/6b31243e-faf9-40f5-cf32-080be14ed3ee.png)


以上で視覚化からのドリルスルーの設定方法と遷移方法の紹介になります。