OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】 scopeについて



# Railsにおけるscopeの定義方法

scopeは、よく使うクエリを簡単に定義し、再利用可能にするための機能です。この記事では、scopeの定義方法や使い方について、通常のメソッドとの違いを交えて説明します。また、scopeの使用に対する現場での考え方の違いについても触れます。

## scopeの基本構文

scopeは通常のメソッドと少し異なりますが、シンプルに定義できます。基本構文は以下の通りです。

```ruby
scope :スコープ名, -> { 処理 }
```
###### :スコープ名
scopeの名前を指定します。メソッドのように呼び出し時に使います。
###### -> { 処理 }
無名関数（ラムダ）を使って、処理内容を記述します。whereやorderなどのActiveRecordメソッドを組み込むことができます。

無名関数（ラムダ）の詳細については、こちらを参照してください。
https://qiita.com/Yaaaaa_meat/items/a7a5502b890ab4c5e181


以下の例では、価格が500円以下の本を取得するscopeを定義しています。

例1: 単純なscope
```ruby
class Book < ApplicationRecord
  # 価格が500円以下の本を取得するスコープ
  scope :cheap, -> { where('price <= ?', 500) }
end

# 使用例
books = Book.cheap  # 価格が500円以下の本を取得
```
例2: 引数を取るscope

引数を取るscopeを定義すると、動的に条件を変更できます。
```ruby
class Book < ApplicationRecord
  # 指定した価格以下の本を取得するスコープ
  scope :under_price, ->(price) { where('price <= ?', price) }
end

# 使用例
books = Book.under_price(1000)  # 価格が1000円以下の本を取得
```
### 通常のメソッドとの違い

scopeを使うメリット

	1.	宣言的でわかりやすい
	•	scopeを使うと、クエリの定義がよりシンプルで宣言的に書けます。これは、コードの読みやすさにおいてメリットです。
	•	scopeを使用することで、「これはクエリメソッドである」と明確に示すことができ、他の開発者にも理解しやすくなります。
	2.	読みやすくて短い
	•	scopeは、無名関数（ラムダ）で定義するため、短くシンプルに書けます。クラスメソッドに比べてコードの量が減り、メンテナンス性が高まります。
	3.	コードの整合性
	•	scopeは、ActiveRecord::Relationを返すことが前提になっているため、データベース関連の処理に関しては意図が明確です。一方、通常のメソッドは配列やその他のオブジェクトも返せるため、意図しない結果を返す可能性があります。
	•	クエリだけを扱うならscopeを使うことで、余計な操作が入らず堅牢になります。

通常のメソッドとの比較

通常のメソッド
```ruby
class Book < ApplicationRecord
  def self.cheap_books
    where('price <= ?', 500)
  end
end

# 使用例
books = Book.cheap_books
books.order(:title)  # 実際にはエラーにはならないが、チェーンできるとは限らない
```
scope
```ruby
class Book < ApplicationRecord
  scope :cheap, -> { where('price <= ?', 500) }
end

# 使用例
books = Book.cheap
books = books.order(:title)  # チェーン可能
```
通常のメソッドは結果として配列が返されることがあり、その場合はクエリメソッド（order, whereなど）をチェーンすることができません。しかし、scopeは常にActiveRecord::Relationを返すため、クエリメソッドをチェーンして追加することが可能です。

#### scopeの使用に関する考え方の違い

開発の現場では、scopeを使うか通常のメソッドを使うかについて意見が分かれることがあります。


scopeはシンプルでわかりやすく、宣言的に書けるため、クエリの再利用やメンテナンスがしやすいです。特にクエリメソッドを多用するようなコードでは、scopeを使うことでコードの意図を明確にしやすくなります。

プロジェクトによっては、通常のクラスメソッドの方が柔軟で読みやすいと感じる場合もあります。また、scopeはあくまでActiveRecord::Relationを返すことを前提としているため、別のオブジェクトや配列を返したい場合には通常のメソッドの方が適しています。

結論として、scopeの使用を強制せず、状況やプロジェクトの規模、チームの文化に合わせて選択することが重要です。

##### まとめ

scopeを使うことで、Railsのモデルでクエリを簡単に定義・再利用できるようになります。コードの可読性も向上し、複雑なクエリをシンプルに記述することが可能です。特に大規模なアプリケーションでの開発においては、scopeを上手に活用することで、メンテナンス性が大きく向上します。一方で、通常のメソッドの方が適している場面もあるため、適材適所で使い分けることが大切です。
CoE Starter Kitのデータが最新になっていないときの対処法


CoE Starter Kitのアプリ内やダッシュボード内のデータが最新になっていない場合があるかと思います。

そんなときには、時間がたってからアクセスしなおしてみる方法とこちらで紹介する、原因を特定する方法があります。
原因を特定したい場合はこちらをいちど試してみてください。

以下のPowerApps Studioで[アプリ]ページに移動し、管理コマンドセンターアプリを再生モードで選択します。

https://make.powerapps.com/


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/494ab00f-fcb0-e68a-0a50-9a01a569bd43.png)


左のメニューで、[CoE フロー] を選択します。
[インベントリ]タブをクリックしてください。

①オフになっているフローがないこと、②管理されていないソリューションレイヤーがないことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/d62d18d6-4871-28ee-8566-6fc64580ce0f.png)

管理されていないソリューションレイヤーがある場合は、以下のようにアイコンが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/5f62f5d8-2282-51af-0b37-689874a85f00.png)

https://github.com/microsoft/coe-starter-kit/issues/8950



[同期フロー エラー]メニューをクリックし、③エラーがあるかどうかを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/0b6b9254-4af8-4068-9b92-44ca08eebf03.png)
エラー詳細や、フローの実行についていたい場合はURL列の値をクリックすると、詳細画面を開くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/9ffa5eb5-2a79-8384-b582-b5c989e8d25a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/7410d40e-b4c4-7b7a-6e34-8ddc59f32347.png)


①②がうまくできていない場合
アプリの中でオンにすることも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/32d88ede-a116-93e3-0728-536192de56b4.png)

セットアップウィザードアプリで設定することもおすすめです。
https://learn.microsoft.com/ja-jp/power-platform/guidance/coe/setup-core-components#set-up-the-inventory-components-using-the-setup-wizard

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/d78987c4-abb9-0898-a4b8-3311384571cf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/da8f2b2b-4e86-2126-9e38-6da91beea359.png)

こちらがうまくいかない場合、フロー名で検索して個別に設定することも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/e1ce7cef-ec90-585d-96dc-480607c26d81.png)

フロー詳細画面で[オンにする]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/b3bc3821-3331-fdce-b3a7-03fded886f86.png)
AWS CDKでS3,VPC,EC2等を構築する

# CDKに慣れるために
前の記事でLambdaの構築を行うことができたので今度はS3,VPC,EC2などを立ち上げていきます。
EC2の構築にはVPC周辺の設定が必須なので勉強になりそうです。

# コーディング
構築したいリソースについて記載方法を調べていきます。
今回はVPCに２つのAZを作成し、それぞれのAZにパブリック、プライベートサブネットを設置します。
セキュリティグループの設定がされたEC２をパブリックに配置し、データ保存の為のS3を作成して基本的なサーバ構成を構築していきます。

EC2はプライベートサブネットに置いた方が安全ですが、外部からアクセスする設定について少し知識が必要なので次回挑戦します。
（パブリックに置いた踏み台サーバを使ったり、AWS Direct Connectなどを使ってアクセスできるようにするようです。）

## VPC
ネットワーク環境です。
可用性の為アベイラビリティゾーンを２つ用意します。この中にパブリック、プライベート２つのサブネットを作成します。
パブリックサブネット：SubnetType.PUBLIC
プライベートサブネット：SubnetType.PRIVATE_WITH_EGRESS
パブリックはどこからでもアクセスできる設定、
プライベートはNATを介してインターネットに出れるよう設定します。

## セキュリティグループ
リソースへのアクセス制御の為のファイヤーウォールの設定です。
allowAllOutbound:true
インスタンスから出ていくネットワークを許可します
addIngressRule
個の設定でインスタンスへのTCP接続を許可します。

## EC2
サーバの設定です。vpc,インスタンスタイプ、マシーンイメージ、セキュリティグループ、vpcサブネットを設定します。

## S3
versioned:true
で変更履歴を保持するようにしています。


lib/○○.ts
```ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as s3 from 'aws-cdk-lib/aws-s3';

export class MyArchitectureStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPCの作成
    const vpc = new ec2.Vpc(this, 'MyVpc', {
      maxAzs: 2, // アベイラビリティゾーンを2つ使用
      subnetConfiguration: [
        {
          name: 'PublicSubnet',
          subnetType: ec2.SubnetType.PUBLIC,
        },
        {
          name: 'PrivateSubnet',
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
        }
      ]
    });

    // セキュリティグループの作成
    const securityGroup = new ec2.SecurityGroup(this, 'MySecurityGroup', {
      vpc,
      allowAllOutbound: true,
    });
    securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'Allow SSH access');

    // EC2インスタンスの作成
    const instance = new ec2.Instance(this, 'MyInstance', {
      vpc,
      instanceType: new ec2.InstanceType('t2.micro'),
      machineImage: ec2.MachineImage.latestAmazonLinux2(),
      securityGroup,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PUBLIC
      },
    });

    // S3バケットの作成
    const bucket = new s3.Bucket(this, 'MyBucket', {
      versioned: true,
    });
  }
}

```

# デプロイ
デプロイします。
```powershell
cdk deploy
```

# 気を付けること
S3のバケット名は重複が禁止されているので、唯一無二な名前を付けるようにしてください。
重複しているとエラーが発生して、そのほかのリソースの構築ができないことがあります。

こんなにたくさんリソースを構築してもかかる時間は一瞬です。
すごいですね。

![Screenshot 2024-10-25 142111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722467/17ec7f13-594a-c662-6f39-a2f4f2e01250.png)
Windows11のRegistryをWindows10風に寄せる

# 右クリックしたときに「その他のオプションを表示」を有効または無効にする

## 有効化
```sample.ps1
reg add “HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32” /f /ve
shutdown /r /t 0
```

## 無効化
```sample.ps1
reg delete “HKEY_CURRENT_USER\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}” /f​
shutdown /r /t 0

```

##### 下記リンクを参照
https://jp.minitool.com/news/disable-show-more-options-windows-11.html
ブラウザで上にスクロールした時のリロードを制限する方法

## はじめに
ブラウザの上スクロールでリロードされることを防ぎたいと思ったことはありませんか？特にフォーム入力中やデータ編集中に、意図せずリロードが発生してしまうと、ユーザーの作業が消えてしまいます。この記事では、そのような問題を可能な限り抑える実装方法を紹介します。

:::note warn
必ずスクロールによるリロードを制限できるものではありません。

Androidでリロード可能な場合があることを確認しています。
リロードで消えたら困るものに関しては、リロード時に確認を挟むような処理を追加しましょう。
:::

## 実装のポイント
1. **上方向のスクロールのみを制御**
この実装の特徴は、全てのスクロール動作を制限するのではなく、上方向のスクロールのみを制御する点です。これにより、通常のスクロール操作に影響を与えることなく、意図しないリロードを防ぐことができます。<br /><br />

2. **CSSによる制御**
overscroll-behavior: none; というCSSプロパティを使用することで、ブラウザのデフォルトのオーバースクロール動作を制御します。このプロパティは、スクロールチェーンなどを防ぐために使用されます。<br /><br />
3. **スクロールイベントを使用**
JavaScriptのscrollイベントを使用して、ユーザーのスクロール位置を常に監視します。これにより、適切なタイミングでoverscroll-behaviorの切り替えを行うことができます。<br /><br />

## コードの詳細な説明(Vue.jsのコード)

私はVue.jsを用いて開発をする機会が多いのでVue.jsのコードを用いますが、基本的なJavaScriptの側面が大きく、HTML,CSS,JSや、Reactなどの場合でも問題なく使用できるものです。

```ts:app.vue
// 上方向へのスクロールを制限する処理
const blockScrollUp = () => {
  // 1pxに設定していますが、縦幅に余裕があるページは
  // もっと大きめに設定した方が安定します。
  if (document.documentElement.scrollTop <= 1) {
    document.documentElement.style.overscrollBehavior = 'none'
  } else {
    document.documentElement.style.overscrollBehavior = 'auto'
  }
}
```
スクロール位置が最上部（1px以下、つまり画面の一番上にいる時）の場合にoverscroll-behavior: none;を適用し、それ以外の場合はautoに設定します。

```ts:app.vue
// コンポーネントがマウントされたタイミングで実行
onMounted(() => {
  window.addEventListener('scroll', blockScrollUp)
  // 初期化時にも実行（最初はスクロールされていない状態のため、
  // 処理が実行されずリロードができてしまう為）
  blockScrollUp()
})
```
コンポーネントのマウント時に、スクロールイベントのリスナーを登録します。また、初期状態を設定するためにblockScrollUpを即時実行します。


```ts:app.vue
onBeforeUnmount(() => {
  window.removeEventListener('scroll', blockScrollUp)
})
```
コンポーネントのアンマウント時には、メモリリークを防ぐためにイベントリスナーを解除します。

## 注意点

- スクロールイベントだけでカバーしきれない場合：

setIntervalを使用すると、実行間隔を狭めすぎた場合にパフォーマンスに影響を与える可能性がありますが制限の精度を高めることができます。requestAnimationFrameなどを使用しても良いと思います。

- CSSのみでの実装：

下スクロールも制限してよい場合や、空白ができても問題ない場合は、以下のようなCSSだけで実装することも可能です


```css
html {
  overscroll-behavior: none;
}
```

「空白ができても問題ない場合は」と上で書きましたが、CSSだけで実装するとブラウザのツールバー部分が空白（ピンクの部分）ができてしまいますので、許容できる範囲であればCSSで1行追加するだけで済むのでとても簡単だと多います。

![scroll-error.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734276/6be3812b-4bc0-15da-7b9b-bd1ec3c674ad.gif)


## サンプルページ

開発者ツールだと正常な動きが確認できないと思いますが、ブラウザのサイズを変更して、ご確認いただくとなんとなくのイメージができるかと思います。

https://block-scroll-top.vercel.app/?ver=1.0

## まとめ
この実装により、ユーザーの意図しないリロードを防ぎつつ、通常のスクロール操作への影響を最小限に抑えることができます。特にフォーム入力やデータ編集を伴うWebアプリケーションにおいて効果的なアプローチになるかと思いますので適切に使用していただければと思います。
Youtubeのアドセンスの申請が2か月近く通らなかったのに一発で通った方法

# 前提
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3701202/45ad5a86-c875-bf82-fedc-884f8a4b4499.png)
Youtube収益化のチャンネル登録者数や再生時間の条件を満たして、アドセンスの申請を2024年9月頃にしたのですがずっと申請が通らず困っていました。色々解決方法を調べて「個人情報を正しく設定する」「カスタマーサポートに助けを求める」などしてきましたが、だめでした。しかしある方法で通すことができました。

# 解決した方法
結局 **「今のアドセンスアカウントを閉鎖して、昔使ってたアカウントで申請」** というのをしたら一発で通りました。今活動しているYoutubeチャンネルよりも活動をしていたことがあり、そのチャンネル用でアドセンスアカウントを作成していました。そのアカウントはアドセンス申請したときに閉鎖し、現チャンネル用の新しいアドセンスアカウントを使用していたのですがそれが原因だったようです。

とあるブログで、「アドセンスアカウントを複数作ってしまったときは一番古いアカウントを使った方がいい」というのを見たことがあり、既にYoutubeアカウントと紐づけているアドセンスアカウントを削除して別のアカウントと紐づけするというのが少々怖かったですが、それ以外に何も解決策が思いつかなかったためそれで規約違反的なのになったら収益化を諦めるつもりでいました。

これは私の考察ですが、IPアドレスなどを使用して、アドセンスアカウントの重複を監視しているのではないかと思います。「IPアドレスが被っているアドセンスアカウントがどちらも個人情報が被っている」という状況がGoogle側で見られていて、その場合「古いアカウント(初めて個人情報を登録した方)じゃないと審査が通らないようにする」のようなルールがあるのかなと思います。

# まとめ
**「複数アドセンスアカウントを作ってしまった場合は古いアカウントで申請しましょう」** 
~~申請が通らない原因を少しでもいいから教えて欲しかった~~
Python: Tkinter で日付入デジタル時計を作って画面に表示する (2024.10.25)

## はじめに
久しぶりの投稿である。
どうしても日付と時刻の両方が表示される時計をスクリーンに配置したくて、自作することにした。

当方の環境は以下の通り。

M1 Pro MacBook Pro 14"
macOS Sequoia 15.0.1
Python 3.13.0
Tcl/Tk 8.6.15

## やったこと
やったことは以下の通り。

1. Python Tkinterを用いてデジタル時計を表示するプログラムを作成。
2. MacのAutomatorで作成したプログラムを起動するシェルスクリプトをapp化（Pythonのありかと実行するプログラム名はフルパスで記載）
3. Elgato Stream Deckに入れ込んでワンタッチでいつでも表示できるようにする。

### （注意事項）
私は、MacBookにpyenvでPython環境を作っているが、同様の環境の方は以下に注意。
+ tcl-tkが入っていないとTkinterは使えないこと
+ tcl-tkをインストールするにはopenssl@3が必要であること
+ tcl-tk導入前のpythonは一度削除し、tcl-tk導入後に新たにpyenvでpythonを入れ直す必要があること

## 参考サイト
参考にさせてもらったサイト（記事）は以下の通り。なおStream Deckへの配置は持っている人にとっては特に説明の必要もないと思うので省略。ただしStream Deckに入れ込むことでとても便利になる。

Pythonで時計アプリを作ってみた
[https://qiita.com/Chihiro_0808/items/d978a671358fcaf859bb](https://qiita.com/Chihiro_0808/items/d978a671358fcaf859bb)

time --- 時刻データへのアクセスと変換
[http://docs.python.jp/2/library/time.html](http://docs.python.jp/2/library/time.html)

Macでシェルスクリプトを .appアイコン化する方法
[https://qiita.com/KurosawaTsuyoshi/items/425cd484e8d7759af460](https://qiita.com/KurosawaTsuyoshi/items/425cd484e8d7759af460)

## 動作中写真
動作中の写真は以下の通り。見やすい。文字の大きさもコードをいじることにより自由に変えられる。app化してはいるが、Pythonコードを実行するシェルスクリプトを実行しているだけなので、Pythonのシステムはコンピュータ内に存在している必要がある。その分ソースコードをいじってもautomatorでのapp作り直しは必要ないところが良いところか。

![IMG_2143.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129300/3b68d930-570a-83e1-83ae-f15548ac99f0.jpeg)


## コード
コードは以下の通り。独自性はほとんどありません。時刻と日付の表示はもっと効率的にできそうな気がしますが、とりあえず私の実力ではここまで。

```python
import tkinter as tk
import time

def show_time():
    now = time.strftime('%H:%M')
    clock1.config(text=now)
    clock1.after(1000, show_time)

def show_date():
    now = time.strftime('%a %d %b %Y')
    clock2.config(text=now)
    clock2.after(1000, show_date)

root = tk.Tk()
root.title('tk_clock')
root.geometry('180x90')
clock1 = tk.Label(root, font=('consolas', 40, 'bold'))
clock2 = tk.Label(root, font=('consolas', 20, 'bold'))
clock1.pack()
clock2.pack()
show_time()
show_date()
root.mainloop()
```

## 追記（2024.10.25 21:25）
@shiracamus(しらかみゅ)さんから、以下のコード修正案をいただきました。```root.after```で再帰させればいいのですね。とてもスッキリしました。ありがとうございます。

```python
import time
import tkinter as tk

def update():
    clock_time['text'] = time.strftime('%H:%M')
    clock_date['text'] = time.strftime('%a %d %b %Y')
    root.after(1000, update)

root = tk.Tk()
root.title('tk_clock')
root.geometry('180x90')
clock_time = tk.Label(root, font=('consolas', 40, 'bold'))
clock_time.pack()
clock_date = tk.Label(root, font=('consolas', 20, 'bold'))
clock_date.pack()
update()
root.mainloop()
```


以上
[Windows11]タスクバーの検索ボックスが正常に動作しない（FIXED）

10月頭くらいから発生していた現象。
検索ボックスが開かない、あるいは開いても何も表示されない、他のウィンドウに重なる、等々。

仕事用・私用PCの両者で発生していた。
OSはWindows11 23H2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777804/fd550f82-5aba-419c-dbce-bc232d5d21ec.png)

`タスクマネージャー > 詳細`から`SearchHost.exe`なるプロセスを確認すると「応答なし」。

どうやら、「Google 日本語入力IME」が原因の模様。
10月3日周辺から同症例が散見され始めているようだが、手元のGoogleIMEの更新タイムスタンプを確認すると10月2日となっていた。
このアプデが悪さをしていた可能性が高そう。

当該の問題はGoogleにも報告され、最新のバージョンではFIXEDの模様。
[Windows 11 + Google日本語入力 2.30.5590.0 の環境で、Windows スタートメニューの検索ボックスに文字入力できなくなる - Gboard コミュニティ](https://support.google.com/gboard/thread/300465502/windows-11-google%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%85%A5%E5%8A%9B-2-30-5590-0-%E3%81%AE%E7%92%B0%E5%A2%83%E3%81%A7%E3%80%81windows-%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC%E3%81%AE%E6%A4%9C%E7%B4%A2%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AB%E6%96%87%E5%AD%97%E5%85%A5%E5%8A%9B%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%82%8B?hl=ja)

ということで、GoogleIMEを再インストールすることで同問題は解消。
一旦備忘録。

[WindowsSearchHostが中断または応答なしとなり検索ができない。 - Microsoft コミュニティ](https://answers.microsoft.com/ja-jp/windows/forum/all/windowssearchhost%E3%81%8C%E4%B8%AD%E6%96%AD/03d7f11c-f73d-4b0f-b161-e4b90dd371c4)
rails g serializer の再発明。(jsonapi_serializerでも使えることを知らなかった)

# はじめに
みなさん、こんにちは **torihazi**です

今日はもしかしたら車輪の再発明みたいなことをしてしまったかもしれません。

あるの知りませんでした。

jsonapi_serializerを使っていて

`rails g serializer user`みたいなことをするときに

できないんじゃね？と思ってしまってあーだこーだしながら作ってみました。

今調べたらあったみたいです。

# 経緯
rails g serializer hogeみたいにしたらserializersディレクトリ配下に

hoge_serializer.rbみたいなファイルができて欲しかったので

それをコマンドラインからできる術を調べていました。

なにしろめんどくさかったので。

とりあえず`rails generate generator hoge`を使うと

`lib/generaters/hogeディレクトリ`とか色々作られることがわかりました。

んで、active_model_serializersだとそれがあるけど

jsonapi_serializerだとそれがないから作るしかない、みたいな結論に

その時はなったので今回作りました。

# ゴール
今回は`rails g serializer hoge/hoge/hoge`としたら

app/serializers/hoge/hogeディレクトリ配下にhoge_serializer.rbができることまでをゴールにします。

# 手順
```
rails generate generator serializer
```
=> lib配下に色々ファイルができる。

lib/generaters/serializerのserializer_generator.rbに下記を追記

```rb
class SerializerGenerator < Rails::Generators::NamedBase
  source_root File.expand_path("templates", __dir__)

  def create_serializer_file
    template 'serializer.erb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
  end

  def run_rubocop
    # ジェネレートしたファイルのパス
    generated_file = File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
    
    # コード整形のためにRubocopを実行
    system("bundle exec rubocop -a #{generated_file} > /dev/null 2>&1")
  end
end
```

そしてlib/generaters/serializer/templates配下のserializer.erbを作って

```rb
# frozen_string_literal: true
<% module_namespaces = class_path.map(&:camelize) %>
<% if module_namespaces.any? %>
<%= module_namespaces.map{|namespace| "module #{namespace}"}.join("\n")%>
  class <%= file_name.camelize %>Serializer
    include JSONAPI::Serializer

    attributes :id
  end
<%= "end\n"*module_namespaces.size %> 
<% else %>
class <%= file_name.camelize %>Serializer
  include JSONAPI::Serializer

  attributes :id
end
<% end %>
```

と記載

使うときは `rails g serializer hoge/hoge/hgoe`とか`rails g serializer hoge`です。

namespaceつけたいなら前者だし、そうじゃないなら後者みたいな。

そうすれば前者だとこんなのできる

```
# frozen_string_literal: true

module Hoge
  module Hoge
    class HogeSerializer
      include JSONAPI::Serializer

      attributes :id
    end
  end
end
```

# 説明
説明とまではいかないかもしれません。

コード整形はrubocop使ってます。

で標準出力でるとなんかダサいと思ったので全部/dev/nullに流してます。

あとは自信が詰まった箇所を箇条書きで。

- メソッドは上から順に実行される
lib/generaters/serializerのserializer_generator.rbに defで色々メソッド書きましたが 上から実行されます。
- `__dir__`
その実行ファイルがあるディレクトリの絶対パス
- `templateメソッド`
 template(templateファイルがあるパス, 出力先のパス)

詳しいこと書いてます
https://railsguides.jp/generators.html

# 終わりに
まぁ新しく知識増えたのでよしとしましょう。

rails g generatorなんて知りませんでした。
JavaScript以外でもどんどん変数を定数として宣言しようという話

# はじめに
JavaScriptだとかなり認知が広まりつつある「変数はできるだけ`const`で宣言して、厳しい場合だけ`let`を使おう」という話。  
なぜかJavaScript限定で話されがちですが、よく考えたらJava等でも同じようにしたほうが良いのでは？

# 例
Salesforceの文法なので厳密には違うかもしれませんが、まあJavaと似たようなもんのはず。
```java
public static void testMethod(String inputValue) {

    Boolean isXXX = checkValue(inputValue);
    
    // 色んな処理がずらっと何十行

    if (isXXX) {
        // 色んな処理
    }
}
```

さあこの時、下の`if`分岐のときに`isXXX`が最初の宣言通りかどうかは、きちんとコードを全部見ないといけません。  
（検索したら良いというのはもちろんですが、それは一旦置いておいて）

こういうのを避けるためにJavaScriptでは「`const`を使おう！」運動が広まっているわけですが、Javaでもやっていいはず。

```java
public static void testMethod(String inputValue) {

    final Boolean isXXX = checkValue(inputValue);
    
    // 色んな処理がずらっと何十行

    if (isXXX) {
        // 色んな処理
    }
}
```
これで`isXXX`が宣言時の値のままであることが確実になりました。  
みんなハッピー。

# おわりに
Salesforce、もといApexにはJavaScriptと比べて、Array関数のような配列をまとめて処理する関数がないので、実際にはちょっと難しかったりするんですが・・。  
できる限り、コードを読むときの懸念点を減らしていきたい。
PixiJSに開発用のChrome機能拡張があるのを今日知った その２

Pixi.js開発用機能拡張には同じ名前の機能拡張が２種類あり、こちらのほうが高機能。
Chrome ウェブストアでの見分け方は`DevTools`の`T`が大文字。

大文字の機能拡張のほうが、より詳細なプロパティの検査と編集や、アセットの中身を確認、パフォーマンスのモニタリングができます。
PixiJS v7, v8 のデバッグをサポート。

## 機能拡張のインストール

インストールすると、開発者コンソールに`PixiJS DevTools`というタブが出現する

https://chromewebstore.google.com/detail/pixijs-devtools/dlkffcaaoccbofklocbjcmppahjjboce

![スクリーンショット 2024-10-25 15.19.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73196/8b8fbdf5-e71a-0266-287d-9fa891e9537e.png)


## パッケージをインストールする場合

TypeScriptのサポートが必要な場合こちらを使う。
プロジェクトに`@pixi/devtools`パッケージをインストールする
```bash
npm install @pixi/devtools
```

Pixi.jsを初期化した後に以下のコードを追加する
```javascript
import { initDevtools } from "@pixi/devtools"; // ← 追加！

const app = new PIXI.Application(...) // Pixi.jsを初期化

initDevtools({ app }); // ← 追加！
```

## パッケージをインストールしない場合

Pixi.jsを初期化した後に以下のコードを追加する
```javascript
const app = new PIXI.Application(...) // Pixi.jsを初期化

window.__PIXI_DEVTOOLS__ = { app }; // ← 追加！
```


## できること
- 要素の表示非表示
- 要素のプロパティを変更
- 要素をダブルクリックすると、コンソールドロワーに要素を追加できる
- 要素を選択してからコンソールドロワーで`$pixi`と入力すると要素のプロパティにアクセスできる


## 高機能版でさらにできること
- 要素を直接クリックして検査
- より詳細なプロパティの検査と編集
- アセットの中身を確認
- パフォーマンスのモニタリング

## その他詳細はこちら

https://pixijs.io/devtools/

## 前の記事はこちら

https://qiita.com/TAAARRRO/items/ef384d63f8dc5bb6f093
【MLBの試合予測を独自開発システムで実現】

機械学習とオープンソース技術を活用し、MLB試合の結果を予測するシステムを開発しました！🎯

今回、10月26日のニューヨーク・ヤンキース vs ロサンゼルス・ドジャース戦を対象に、独自のモデルで予測を行い、ドジャースが4.67得点、ヤンキースが3.99得点と結果が出ています。

👉 技術的には、Pythonとオープンソースの機械学習ライブラリ（Scikit-learnなど）を用いて、データ前処理やモデル構築、評価指標の改善に取り組んでいます。データサイエンスに興味のある方、ぜひ一緒に技術を深めませんか？

興味がある方はコメントやメッセージお待ちしています！

![名称未設定のデザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917980/643046e0-aa5c-ef64-c37d-307cdec0f852.png)
人工知能（AI）技術をリードする企業「MILLIONFY」、DA整形外科とMOU締結

![배너JP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784576/8c80cf24-0bac-4683-809e-3ab7a1629a92.jpeg)

人工知能技術をリードする企業、MILLIONFYの「MAi」は17日、DA整形外科と戦略的業務提携（MOU）を締結し、協力事業を積極的に推進していくと発表しました。両社は今回の提携を通じて、友好的なパートナーシップを構築し、企業間の専門性を資源として活用し、相互発展を目指していくとともに、共通の目標を達成するためのさまざまな協力方策を模索していく計画です。

「MAi」は最新の医療データベースや論文に基づいたAIメディカルチャットボットです。「MAi」は専門的でありながらも理解しやすい言葉で、ユーザーの健康状態を確認し、個人の健康データを医療情報と照らし合わせ、病院の推薦、健康食品や生活習慣の改善など、軽い症状から食習慣、睡眠、ストレス、肌の診断、整形相談まで、まるで主治医が手元にいるかのようなケアを提供します。

これは、PubMed、MedlinePlus、Mayo Clinic、Google Scholarなどの最新の医療データベースや論文を基に、個人化されたデータや公共医療データの収集により、最適なソリューションを提供できるものです。「MAi」は、ユーザーの携帯電話のカメラを利用して簡単に肌の状態を分析し、改善に必要な医療情報や病院、食事、サプリメント、化粧品を提案するだけでなく、瞳の色、肌の明度、唇の色などを分析して、ユーザー自身が気付いていない健康サインを見つけることができます。これにより、初期の疾患を発見したり、予防することが可能であり、慢性疾患を持つユーザーの治療スケジュールをサポートしたり、治療過程を理解させ、管理と回復を助けるガイドを提供します。さらに、気軽な美容相談も可能で、写真を撮って希望する仮想の顔に変換し、整形や皮膚美容のソリューションを受けることができます。「MAi」は膨大な整形データに基づいてユーザーのイメージを修正し、整形外科や皮膚クリニックを推薦し、施術や管理まで提案します。このように、日常生活で疑問に思っていた医療情報を「MAi」に尋ねれば、最新の医療データに基づいた専門的かつ最適な回答を、ユーザーが理解しやすい言葉で得ることができます。

「MAi」独自のアルゴリズムで設計されたAIディープラーニング技術は、ユーザーの食習慣や生活パターンなどのデータが蓄積されるほど、より価値のあるデータと回答に結びつき、精密なカスタマイズソリューションを提供できるため、無限の成長可能性を秘めています。MILLIONFYの関係者によれば、現在アプリケーションはグローバルリリースを目指しており、2025年の第1四半期にユーザーに提供される予定です。

一方、韓国の業界トップであるDA整形外科は、2025年までに2つの海外支店を含む、国内外合わせて30の支店拡大を目標にしており、美容整形のトレンドをリードしています。整形外科のみならず、皮膚美容クリニック、DAドクターコスメティック、バイオ製薬など多岐にわたる分野でもDAブランドを使用し、総合的な美容整形医療ブランドとしての地位を確立しています。DAの非医療派生ブランドであるDAバイオテックは、2023年に病院専用化粧品「エクソソーム製品」を皮切りに、計30種類以上の製品を発売し、ベトナム、タイ、日本、中国、台湾、香港、ミャンマー、ラオスなど、アジアおよびグローバル市場で既に大きな影響力を発揮しています。

MILLIONFYの代表であるオ・サンフン氏は、MAiの革新的なAI技術によって実現されるビッグデータと活性化されたプラットフォームを、業界トップクラスのDA整形外科の医療サービスやネットワークと緊密に協力し、AI技術の高度化をさらに加速させる意向を示しました。また、DA整形外科と連携して、ユーザーが効率的な先端医療サービスを受けられるようサポートするという抱負を語りました。さらに、現在MAi SEOULショールームが江南区三成洞に位置しており、MAi BUSANとMAi TOKYOショールームもまもなくオープンする予定だそうです。

【お問い合わせ先】
メディア関係者連絡先
会社：MILLIONFY
担当者：Justin Chang
ウェブサイト：[https://maigpt.ai/](https://maigpt.ai)
Native Memory Tracking を使用した Java プロセスのメモリ消費内訳の紹介

# Native Memory Tracking を使用した Java プロセスのメモリ消費内訳の紹介

2024年10月27（日）開催の [JJUG CCC 2024 Fall](https://ccc2024fall.java-users.jp/) にて発表した資料の共有です。

![スライド0.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/375970b7-0663-e1e6-245c-77c7d524c8e4.png)

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/ed357ad8-334f-9151-c0c1-11f5db057375.png)

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/0b9ab9d4-081e-073f-47d9-43abac394aca.png)

![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/92653583-9d49-ebec-ffe4-97bf6bb0736b.png)

![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/449d005d-fdd6-b1c5-7f9d-fa1526fcb7c4.png)

![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/5d092948-94c3-8ad4-d0c2-7b622f88e379.png)

![スライド6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/a2e07485-b8d8-bb18-9f0c-69944917ccf7.png)

![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/e8a3f379-8b8a-d197-16e1-c83ea4ae1245.png)

![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/b2c80d74-2183-de21-f250-e002a13dca03.png)

![スライド9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/fb098302-677a-4286-a305-d067120bdfc5.png)

![スライド10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/9d00bf2c-8588-6210-16ce-eb6e129022a0.png)

![スライド11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/a63f9ee3-0025-14bb-0480-7ac6ad3d53b4.png)

![スライド12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/ed409263-2e9b-36ac-fe0a-af60235ff262.png)

![スライド13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/09f6f673-4f8b-af33-2095-210f1be21db0.png)

![スライド14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/ac7b7639-48bc-da9a-ac0b-1d1db775a889.png)

![スライド15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/c2855fdb-e81e-6407-8923-74bbaa816b08.png)

![スライド16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/1ded29a5-42af-6424-2796-89b158075d3e.png)

![スライド17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/9ad79e09-daac-90e1-d070-d02bc1b16a32.png)

![スライド18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622281/33e918f4-cc95-9875-fea1-f640085c8056.png)
Rubyで`URI.escape`エラーを解決するパッチの紹介

## はじめに

Rubyを使用しているプロジェクトで、`URI.escape`メソッドを使っていないにもかかわらず、以下のエラーが発生しました。

```
undefined method `escape' for URI:Module
```
###### escapeの使用箇所が見当たらないで、探すのは諦めてパッチを当てることにしました。
`URI.escape`はRuby 2.7以降で非推奨となり、Ruby 3.0で削除されています。そのため、古いコードや依存ライブラリが`URI.escape`に依存しているとエラーが発生することがあります。この記事では、`URI.escape`が使えない環境でこのエラーを解決するためにパッチを当てる方法を紹介します。

## 解決方法

以下のコードを使用して`URI.escape`メソッドを自前で定義することで、エラーを解決できます。このパッチは`config/initializers/functions_overrides.rb`に追加します。

### コード

```ruby:config/initializers/functions_overrides.rb
require 'uri'

module URI
    class << self
        def escape(str)
            alpha = "a-zA-Z"
            alnum = "#{alpha}\\d"
            unreserved = "\\-_.!~*'()#{alnum}"
            reserved = ";/?:@&=+$,\\[\\]"
            unsafe = Regexp.new("[^#{unreserved}#{reserved}]")
            str.gsub(unsafe) do
                us = $&
                tmp = ''
                us.each_byte do |uc|
                    tmp << sprintf('%%%02X', uc)
                end
                tmp
            end.force_encoding(Encoding::US_ASCII)
        end
    end
end
```

### 解説

- **`require 'uri'`**: `URI`モジュールを拡張するために、`uri`ライブラリを読み込みます。
- **`module URI`**: `URI`モジュールを再オープンし、`escape`メソッドを再定義します。
- **`escape`メソッド**:
    - エスケープ対象の文字列を受け取り、正規表現を用いてエスケープ処理を行います。
    - 使用できる文字（英数字、予約文字、アンパサンドなど）以外を`%XX`形式に変換します。
    - 最後に、エンコーディングを`US-ASCII`に変換して返します。

## 使用方法

このパッチを`config/initializers/functions_overrides.rb`に保存することで、`URI.escape`メソッドが再び使えるようになります。Railsアプリケーションなどであれば、初期化時に自動で読み込まれるため、特別な設定は不要です。

### ファイルの場所

```
config/initializers/functions_overrides.rb
```

上記のパスにファイルを作成し、先ほどのコードを貼り付けて保存してください。

## まとめ

Ruby 3.0以降で削除された`URI.escape`を使用している古いコードやライブラリがある場合に、手軽にエラーを回避するための方法を紹介しました。この方法を使用することで、コードの修正量を最小限に抑えつつ、既存のコードを動かし続けることができます。

この記事が同様の問題に直面している方の助けになれば幸いです。もし他の方法や改善点があれば、コメントで教えてください。
PixiJSに開発用のChrome機能拡張があるのを今日知った

Pixi.js開発用機能拡張には同じ名前の機能拡張が２種類あり、こちらは簡易版。
Chrome ウェブストアでの見分け方は`Devtools`の`t`が小文字。

## 機能拡張のインストール
インストールすると、開発者コンソールに`PixiJS`というタブが出現する

https://chromewebstore.google.com/detail/pixijs-devtools/aamddddknhcagpehecnhphigffljadon?pli=1

![スクリーンショット 2024-10-25 15.28.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73196/8ea704ac-4951-d1ad-ffcf-15c10c850894.png)



## コードに追記
Pixi.jsを初期化した後に以下のコードを追加する
```javascript
const app = new PIXI.Application(...) // Pixi.jsを初期化

globalThis.__PIXI_APP__ = app; // ← 追加！
```

## できること
- 要素の表示非表示
- 要素のプロパティを変更
- 要素をダブルクリックすると、コンソールドロワーに要素を追加できる
- 要素を選択してからコンソールドロワーで`$pixi`と入力すると要素のプロパティにアクセスできる

## その他詳細
https://github.com/bfanger/pixi-inspector

## この記事の続き
https://qiita.com/TAAARRRO/items/0a525966bcf026f31370
AWSの開発環境構築手順

とあるWebアプリケーションのスクラッチ開発で、インフラを全面的に任せて頂く機会がありました。

開発環境の構築手順書を兼ねて執筆します。
ボリュームが大きくなるので、複数記事に分けて執筆します。

プロジェクト名やIPアドレスなど、所々ブラックアウトさせている箇所があります。
適宜ご自身のプロジェクトの内容に読み替えてください。

# 本番環境の構成図

![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/be6d8a68-d552-7157-a343-bb4daea4b618.png)

- 現状、アクセス数が多くなることを想定していない＆費用を抑えるためにEC2は1台
- 将来的なEC2の追加可能性と、SSL/TLSサーバー証明書の必要性からELB(ALB)を採用
- 開発環境ではDBのレプリカを作成しない

# 環境

- フロントエンド
　Node 18.20.2
　React 18.3.1
- バックエンド
　Python 3.12.3
　Django 5.0.4
- DB
　PostgreSQL 16.3
- Webサーバー
　Nginx 1.24.0

- OS
　Amazon Linux 2023
　※DB以外はこのインスタンス上に構築

# 前提

ローカル環境が既に存在していたので、EC2インスタンスの構築はDockerfileに極力合わせ、かつPythonとReactのソースコードがgitに存在している前提で構築を進めています。
あくまでインフラ作業を担当しているので、プログラミングに関する内容はノータッチです。

# 作業手順

1. [VPCとセキュリティグループ編](https://qiita.com/shin-gee/items/3d4c79e55c4e534e929a)
1. [EC2編](https://qiita.com/shin-gee/items/f61db62287fcd4948c99)
1. [ALB編](https://qiita.com/shin-gee/items/525b1d0737779626cc5a)
1. [Route53とSSL/TLSサーバー証明書編](https://qiita.com/shin-gee/items/404661c3ff8b40aad747)
1. [RDS編](https://qiita.com/shin-gee/items/06199f56bdc4643d30e6)
1. [EC2インスタンス内で諸々設定編](https://qiita.com/shin-gee/items/487d1fc391aa4f12fe35)
1. [SES編](https://qiita.com/shin-gee/items/f85587e6cc4142fb0214)
Raycastを使って物書堂辞書を選択したテキストで検索する。

Macのランチャーが凄いということで、最近、AlfredからRayCastに乗り換えた者です。最近、Alfredのほうはバグがあるのか、workflowのホットキーで次に渡す変数の入力にselected textを選んでもQueryに入ってくれません。それでRayCastでコマンドを作ってみたのですが、こちらはコンパイルプロセスが特殊でnpm run devで動いていたコマンドをbuildしてインポートしてもjsファイルが無いといって動きませんでした。もっと、コマンドは作り方を勉強しないといけなそうです。ところが物書堂の辞書検索だけならば、
１，Settingを開く
２．Extenstionタブを開く
３．Extensionタブの中からQuicklinksを選ぶ
4.+ボタンからcreate QuickLinksを選ぶ
5.Nameにmonokaido dictionary searchなど適当な名前を入れて、Linkにmkdictionaries:///?text={selection}といれてやります。
後は好きなショートカットをふるなり、Add Aliasに"md"などと入れて素早く呼び出せるようにしてやると、textの入力をスキップして選択したテキストで検索してくれます。
実はRayCastのQuickLinkはダイナミックプレースホルダーという仕組みを採用していて、searchQueryをいちいちコピーしなくても、clipboardの中身やselectedText、その他、色々なもので埋めてくれるのです。これで一件落着。
ExtenstionはTypeScriptとReactを使って書く方法をとっていますので、Alfredより敷居は高いですが既に高機能なExtensitionが多くリリースされている模様。
暇な時にどんどん触って使い倒してみたいツールになりました。
X のURLスキーム(Universal Links)を作成した場合、Androidで「入力した単語の検索結果はありません。しばらく…」のメッセージが出る場合の対処法

## はじめに
Xが開かれるか、シェアボタンを押したWeb上で出るかは環境によって異なるようですが、「入力した単語の検索結果はありません。しばらく…」のメッセージが表示され適切にシェアが出来ない場合があります。

## 原因
このエラーは、使用しているURLスキームが不適切な場合に発生します。

## 注意すべき点
X のURLスキームを実装する際、`https://twitter.com/share?`の使用は避けるべきです。このスキームは一部の状況(iPhone,AndroidのWeb版 X)で動作するものの、現在ではAndroidのアプリ版の X でエラーを引き起こす可能性があります。代わりに、以下のURLを使用することで解決できます。

- **誤ったスキーム**： `https://twitter.com/share?`
- **推奨スキーム**： `https://twitter.com/intent/tweet?`

使用例）
```html
// 「%0a」は改行をURL用にエンコードしたもの
<a href="https://twitter.com/intent/tweet?text=Googleのトップに遷移します%0a&url=https://www.google.com/" target="_blank">Twitterでシェアする</a>
```

`https://twitter.com/intent/tweet?`は、Androidの X アプリ上でも正しく動作しするので、きちんと設定した文言が適用されたポスト画面が開かれます。

![スクリーンショット 2024-10-25 13.19.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734276/840ea553-e4a2-33c3-4f29-b06c16c42fb3.png)


## 結論
Androidでのシェアボタン実装時に発生するエラー「入力した単語の検索結果はありません。しばらく…」については、適切なURLスキームを使用することで解決できます。現象自体はだいぶ前からあるようですが、同様のエラーに遭遇した方の一助になれば幸いです。
Power Automate で Outlook 予定表のイベントの色（分類）を更新する方法

ごきげんよう、百合宮桜です。
今日は Outlook の予定表の分類を Power Automate で自動更新ってどうやるんだっけ？という自由研究です。
なお、イベント作成時の設定方法は オモシロドリブン 氏の記事をご確認ください。

https://qiita.com/n2Mj7Lg3cxNcFtJ/items/9bc6e01d33e3cca12c4a

# 概要
お客様から招かれた会議のように、自分以外がたてたイベント（予定）に対して、分類の付与を自動化したいというニーズです。その為、トリガーは「新しいイベントが作成されたとき」を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/e31fd30a-d57e-89d2-b6a7-3d7fa1a7787f.png)



# 実装方法
1. トリガーの予定表ID に自分の予定表を設定します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6559a24d-6cba-9419-3401-5c761d04cf05.png)

2. ＋ > アクションの追加 をクリックします

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/b03d6dc1-5364-d146-9a45-116980bd4d57.png)

3. 「Office 365 Outlook」を選択します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/4215fe95-4f27-e2bc-3501-c4665d73f0ac.png)

4. 「Http 要求を送信します」を選択します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/54602a39-3a02-8024-545a-2fbda6751de1.png)

5. URI で以下を入力します

    ```
    https://graph.microsoft.com/v1.0/me/events/
    ```

6. URI の最後にカーソルを置き、動的なコンテンツをクリックします

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/d1b94908-1a16-bf53-1a90-76fdcfb62021.png)


7. URI に ID を入れ込みます

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/a0698136-c1eb-895f-9f6c-43e9a0843561.png)


8. メゾットを「Patch」に変更します

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/027a786c-729c-fbbb-9204-83bdb21e6261.png)

9. 詳細パラメーターで「本文」にチェックを入れます

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/bcc24279-0e44-0f8b-9b53-1c1323a57010.png)

10. 本文に以下を入力します

    ```
    { 
        "categories": ["分類名称"]
    }
    ```
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/18a7f347-e985-87be-561c-d8e44b607117.png)


    分類名称はココ↓で表示されている名前です
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/65ad71ef-28f0-3097-9279-5c61e3fa4810.png)

これで予定がたった時に分類を更新することができます。
私は会社のテナント→自分のテナントに会議招待を送って、テストしてみました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/39dccd92-7c57-b7ad-3b4b-eafa80e73af5.png)

# おわりに
わざわざ Power Automate を使わなくても、ビューの設定 > ルールから分類を自動化することもできます。
このあたりは好みが色々あるようにも思います(笑)
[js]誕生日から日本で一般的な星座を割り出す


コメントありがとうございます。
こっちのほうがシンプルです！

```
const getZodiacNumber = (month, day) => (
  month = `${month}`.padStart(2, '0'),
  day = `${day}`.padStart(2, '0'),
  new Date(`2000-${month}-${day}`).getDate() === +day && ([
    '0321', '0420', '0521', '0622', '0723', '0823',
    '0923', '1024', '1123', '1222', '0120', '0219',
  ].filter(v => v <= `${month}${day}`).length + 9) % 12 + 1) || null;

const zodiacSigns = [
  '魚座',
  '牡羊座',
  '牡牛座',
  '双子座',
  '蟹座',
  '獅子座',
  '乙女座',
  '天秤座',
  '蠍座',
  '射手座',
  '山羊座',
  '水瓶座',
];

// 例: 誕生日が4月15日なら牡羊座（1）
const birthMonth = 4;
const birthDay = 15;
const zodiacNumber = getZodiacNumber(birthMonth, birthDay);
console.log(`星座番号: ${zodiacNumber}`);
console.log(`星座名: ${zodiacSigns[zodiacNumber]}`);


```

最初のコード
```
function getZodiacNumber(birthMonth, birthDay) {
  const zodiacSigns = [
    { name: '魚座', number: 12, start: [2, 19], end: [3, 20] },
    { name: '牡羊座', number: 1, start: [3, 21], end: [4, 19] },
    { name: '牡牛座', number: 2, start: [4, 20], end: [5, 20] },
    { name: '双子座', number: 3, start: [5, 21], end: [6, 21] },
    { name: '蟹座', number: 4, start: [6, 22], end: [7, 22] },
    { name: '獅子座', number: 5, start: [7, 23], end: [8, 22] },
    { name: '乙女座', number: 6, start: [8, 23], end: [9, 22] },
    { name: '天秤座', number: 7, start: [9, 23], end: [10, 23] },
    { name: '蠍座', number: 8, start: [10, 24], end: [11, 22] },
    { name: '射手座', number: 9, start: [11, 23], end: [12, 21] },
    { name: '山羊座', number: 10, start: [12, 22], end: [1, 19] },
    { name: '水瓶座', number: 11, start: [1, 20], end: [2, 18] }
  ];

  for (const zodiac of zodiacSigns) {
    const [startMonth, startDay] = zodiac.start;
    const [endMonth, endDay] = zodiac.end;

    if (
      (birthMonth === startMonth && birthDay >= startDay) ||
      (birthMonth === endMonth && birthDay <= endDay) ||
      (birthMonth > startMonth && birthMonth < endMonth)
    ) {
      return zodiac.number;
    }
  }

  return null; // 該当しない場合
}

// 例: 誕生日が4月15日なら牡羊座（1）
const birthMonth = 4;
const birthDay = 15;
const zodiacNumber = getZodiacNumber(birthMonth, birthDay);
console.log(`星座番号: ${zodiacNumber}`);
```
もらったrequirements.txtでなんか動かない（泣

### いつもの僕

上司「githubのリポジトリはここだから。それぞれで仮想環境を作って、動かしてね」
僕「わかりました！（わかってない）」

僕「それじゃあ、仮想環境を作ろうっと。
仮想環境のVSCodeに任せることにするか。
Pythonのバージョン？　いくつだっけ？
えーっと、python 3.12でいいか。
pip install -r requirements.txt　っと……」

！エラー！　なんかいろいろ、バージョンがダメ！

僕「ふええ……」

## 対処法
### まず、Pythonのバージョンを確認する
Dockerだったら、中にPythonも入ってるんだけど、ただのvenvだとPythonを選ばないといけない。
「すみません、今回使うPythonのバージョンいくつですか？」と聞くのである。

僕「なるほど、python3.10か。それで、requirements.txtのバージョンが合わなかったんだな」
僕「じゃあPythonのバージョンを3.10にするか」

### エラーログに合わせて、パッケージのバージョンを要求に合わせる

上司「せっかくだからpython3.12にしたら？」
僕「ふええ……」

このバージョンのエラーを解消しなくてはならない。
エラーをよく見て、指定されているバージョンのものを導入するのだ。

ものすごい雑感だが、numpyがよくエラーを起こす。
（そして一個下のメジャーバージョンを要求される。いっそいったんrequirements.txtから消すと、ほかのパッケージとの兼ね合いでうまくいくことが多い。ひどい。）

僕「バージョンを落とさなきゃいけないんだけど、マイナーバージョンいくつなんだろう。
勘でいいですか？」
上司「いいわけないだろ」
僕「最新版ってどこで確認すればいいんですか？」
上司「[PYPI](https://pypi.org/)とかよ。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/81d284d5-2096-763f-b53f-d019f449fc03.png)

上司「バージョンを落としたくて、古いバージョンを知りたいときはリリース履歴とかからね。」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/b1f1dc52-bef0-4aa6-0405-b34e242f14c5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/afaa0d2b-fb87-08a3-b89f-7e9a6226475c.png)


たまにgithubの履歴を追わなきゃいけないパッケージもある。
プログラミングの記号のタイピング練習ができるコースを作成した話（UnTyping）

## はじめに

以下のプログラミング練習用のタイピングゲームに、記号練習用のコースを作成しました。

https://untyping.jp/?from=qiita

こちらが、記号コースです。

https://untyping.jp/game/99


ランダムに表示される記号を、タイピングしていくことになります。

難易度は、かなり難しめに設定しました。自分も、そこそこ打ち逃します。

## 記号コースについて
以下の画面で、タイピングをスタートします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/6ea5f71d-e811-0e66-0535-46a43ba701bc.png)


ランダムに記号が表示されるので、一生懸命打っていきましょう。
各々のコードに、制限時間が設けられています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/878229c8-b6ce-304d-7257-08f9e241cdb6.png)

そこそこ長いコードも有ります。表示される記号を全て

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411258/dba6e993-16da-c7fc-4333-0539df199513.png)


## 記号コースを作成した感想
私自身、4 年ほどコーディングの経験があるので、タイピングにはそこそこ自信が有ります。

しかし、いざ記号コースをプレイしてみると、**意外と記号を覚えていない**ということに気づきました。

30 分ほど遊んでみると、記号が身体に馴染んでくる間隔が有ります。

エンジニア歴が長い人にも、お勧めできるゲームだと感じました。

## 目標スコア
記号コースを遊んでみた感覚ですが、4000 点を超えれば、かなり凄いです。

現在世界ランキング 1 位の方のスコアは 12000 点を超えていますが、もはや人外の領域だと思います。

皆さんも、4000 点を目指して遊んでみてください。

## 終わりに

今回は、新しく作成したプログラミングの記号練習用のコースについて紹介しました。

是非、遊んでみて下さい。

最後まで読んで頂き、ありがとうございました。

https://untyping.jp/game/99
【Java】関連記事まとめ

# 概要
私が投稿したJavaに関する記事のまとめです。

# 記事

https://qiita.com/ramgap/items/8d6849133ddc9dbc0be9

https://qiita.com/ramgap/items/d410160094cb7ee31228

https://qiita.com/ramgap/items/f561ab23bfb43f632bd3

https://qiita.com/ramgap/items/5038103af48042539430

https://qiita.com/ramgap/items/989ed1d5992217532e24

https://qiita.com/ramgap/items/0b9234c1b325d6716049

https://qiita.com/ramgap/items/e02ac6f122a138c858bb

https://qiita.com/ramgap/items/5ce9d27256198876d0c5

https://qiita.com/ramgap/items/76793e1ea9a826771804

https://qiita.com/ramgap/items/0066cf2d4bdb5aa718c3

https://qiita.com/ramgap/items/734b23f8187444de5c60

https://qiita.com/ramgap/items/857c1a0503496e2fc354

https://qiita.com/ramgap/items/22199918f39e697f8713
結果数は、1 つの一括実行要求で実行されたインタビュー数と一致しません。


過去にも同じエラーで躓いた

+ [Apex を呼び出すフロー、コレクション変数を渡すことができません](https://qiita.com/Keiji_otsubo/items/5f9eb4f0598fc911c109)
+ [フローを使ってスケジュール済みレポートに似せたメールを送信する](https://qiita.com/Keiji_otsubo/items/d4230c6198519ad06fab)

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

:::note alert
結果数は、1 つの一括実行要求で実行されたインタビュー数と一致しません。
:::

以下のようなJson形式で返される明細データを１件づつのレコードとしてList変数で返すApexをフローで呼び出しています。


```
[
[{"column_number":"0","value":"収入印紙"},{"column_number":"1","value":"600 円 × 5 枚 = 3,000"}],
[{"column_number":"0","value":"収入印紙"},{"column_number":"1","value":"1,000 円 × 3 枚 = 3,000"}],
[{"column_number":"0","value":"切手"},{"column_number":"1","value":"460 円 × 3 枚 = 1,380"}]
]
```



```Java
//入力のList<List<String>> inputStringと出力のList<List<hiyoumeisai__c>> を同じような２重のList変数にしましたが、結果数が違うというエラーになります。

    @InvocableMethod(label='JSON_deserialize')
    public static List<List<hiyoumeisai__c>>  test001(List<List<String>> inputString) {
        List<List<hiyoumeisai__c>>  RetList = new List<List<hiyoumeisai__c>>();   
        List<hiyoumeisai__c>  RetList0 = new List<hiyoumeisai__c>();   
        String resBody = inputString[0][0];
        List<List<colval01>> l = (List<List<colval01>>)JSON.deserializeStrict(resBody,List<List<colval01>>.class);
        for (List<colval01> l2 : l ){
            String formula = l2[1].value;
            List<String> formulas = formula.split('=');
            system.debug(Logginglevel.INFO,'=====> ' + formulas[1].replaceAll(',','') );
            
            hiyoumeisai__c m2 = new hiyoumeisai__c();
            m2.Field01__c = l2[0].value;
            m2.Field02__c = l2[1].value;
            m2.amount__c = Decimal.valueOf(formulas[1].replaceAll(',','').trim());
            RetList0.add(m2);
            RetList.add(RetList0);
        }
        
        return RetList;
    }
```

+ [フローのインタビュー数とはなんぞや](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HEezXSAT)

 >①フローインタビュー数とはフローの開始条件に該当しそのフローが作動したレコードの数のこと ②（①の認識があっていると仮定して）ガバナ制限を考慮するには、開始条件をしっかり決めてインタビュー数をなるべく増やさないようにする。  

 上記を考慮すると今回はJsonのテキストレコードは１件、結果が３件返ってくるので一致しないということですよね。

 Jsonの中身が何件あるかが最初に分かっていれば無理やり入力用のListにダミーの値を追加すればいいけど、今回はできないですね。

 仕方ないApexの中でレコードを追加するように変更するしかないです。
GitHubに作ったリポジトリをローカルにクローンしてEclipseのプロジェクトを新規登録する

# 概要
表題の作業をしたときの備忘録です。その後のプッシュやプルなどその他操作は対象としていません。文字のみの記事ですが、もし誰かのお役に立てたら幸いです。
Eclipse(pleiades all in one)のバージョンは2023です。

# 事前にアクセストークンを取得する
1. GitHubのマイページから、Settings>Developer settings>Personal access tokens>Tokens(classic)と辿り、tokenを生成する。この際もclassicで作成し、適切な権限を設定する。（今回、私の場合は個人的な開発練習のためのリポジトリだったので、repoとdelete_repoのみチェックしました。）
1. 生成された文字列を控えておく。後ほど使用する

# GitHubにリポジトリを作成する
1. GitHubにログインし、Home画面から新規リポジトリを登録する
1. リポジトリのCode画面のHTTPSに表示されているアドレスを控えておく。後ほど使用する

# Eclipseでローカルにリポジトリをクローンする
1. Gitパースペクティブを表示し、左カラムのメニューから、「Gitリポジトリをクローンし、このビューへ追加」をクリック
1. 「クローンUR」を選択して次へ
1. URIに、先ほど控えておいたGitHubのリポジトリのアドレスを入力する
1. 認証のユーザーにGitHubのユーザ名を、パスワードに先ほど控えておいたtoken文字列を入力する
1. 「セキュア・ストアに保管」にチェックをいれる。次から自動でアクセスできる
1. 現時点では中身は空なので、次へをクリック
1. 完了をクリック
1. ビューの表示に新規リポジトリが表示される

# プロジェクトの登録
1. javaパースペクティブに戻り、リポジトリに追加したいプロジェクトで右クリック
1. チーム>プロジェクトの共用へと進む
1. Gitを選択し、次へ
1. リポジトリーから、先ほど追加したリポジトリを選択する（ここで、「プロジェクトの親フォルダー内のリポジトリーを使用または作成」にはチェックを入れませんでした。Eclipseのワーキングフォルダ内には作りたくなかったので。）
1. 完了をクリック

# 以上です！

# 関連リンク

https://qiita.com/ramgap/items/c04e59cc4a66a149d620
「エンジニア騎士とクエリの魔女」を2年目エンジニアがやってみた

# はじめに
「勉強ってなかなかやる気が起きない、、、どうせやるなら少しでも楽しく勉強できないだろうか」と思い、このゲームにたどり着きました。
それはpaizaの **「エンジニア騎士とクエリの魔女」**
![スクリーンショット (33).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/195fe46f-ad1d-fcd4-e032-479e60fefedc.png)
paizaには他にもたくさんの学習用ゲームがありましたが、今の現場でDBサーバを扱っていることもあり、SQLに興味が出てきたのでこちらをやってみることにします。
# やってみよう
#### まずはマイページを見てみる
![スクリーンショット (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/5e82d5b1-5341-b1fa-32e4-025543d24f85.png)
うーーんいかにも初期装備！！
プレイヤーは騎士or魔女になって各地を冒険をする、という流れのようです。
騎士はコード問題、魔女はSQL問題を解くことでレベルアップします。
ちなみにコード問題はJava, PHP, Ruby, Python2, Python3, Perl, C, C++, C#, JavaScript, Objective-C, Scala, Go, Swift, Kotlinから選ぶことができ、いろんな言語に触れられます。
#### 冒険に出てみよう
マップを開くとこんな感じで地区ごとにD～Sまで難易度が分かれています。
青はコード問題、紫はSQL問題になっていました。
![スクリーンショット (35).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/0787cd2b-784d-ffbf-88dc-1d84ad21699f.png)
まずはSQLのDランク問題を解いてみます。
#### 魔法使いの街（Dランク）
問題はこのように表示されます。モンスターを召喚するため問題に挑みます！
![スクリーンショット (36).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/e72a793f-835b-6a01-a93b-6aa86ce5683f.png)
![スクリーンショット (37).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/d1ff0551-2006-6d12-c522-0ed31cb8305e.png)
私の解答はこれだ！
```
SELECT id,name FROM Hell;
```
結果は・・・
無事成功しました！
![スクリーンショット (39).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/8c8289fb-f897-4b74-a981-05e27f0287a9.png)
クエストに成功することで装備を手に入れることができました。
次はCランクの問題に挑戦してみます。
#### 禁断の洞窟（Cランク）
Cランクの問題はこちら
![スクリーンショット (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/53ca2c37-a594-01ed-3ec7-08422e3b241b.png)
明らかにさっきの問題よりも難しい・・・！
結合などが必要ですが、忘れてしまったので書き方を調べながら答えを出しました。
```
SELECT Hell.id, Hell.name, Element.name AS element
FROM Hell JOIN Element ON Hell.element_id = Element.id
WHERE Element.name = 'Earth';
```
これで無事成功し、土属性のモンスターを召喚できました！
#### 装備を変えてみる
いくつか問題を解いたことで装備が集まったので装備を変えてみました。
![スクリーンショット (43).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329745/99375898-98b7-d690-a153-6e548f3b0165.png)
これは全部集めたくなってしまいますね。
# 感想
ファンタジーな世界観で勉強ができてなかなか面白かったです。ただ、やることは単調なのでゲームとしての楽しさは今一つだったかなと思います。
教材としては結構良いと思いました。いろんな難易度の問題が少しずつあるので「とりあえず勉強したいけど何から手をつければいいかわからない、、、」という人にはピッタリかもしれません。
ただ、ヒントが無い（一部有料であり）ので完全な初学者は調べる力が必要になるかな、と思いました。
まだ全部の問題をクリアできていないので、時間があるときに手をつけたいと思います！
絶対パスと相対パス

## はじめに
開発の際に、基本的にはnode.js上で作業をしており、ファイルをローカルに落としてブラウザ表示するようにと指示が出たときに、CSSが上手く当たらず原因を調べたところ、サーバー上で作業をしていた時のコードは絶対パスになっており、ローカルでは相対パスにするべきだと気づいたので、今回現場で学んだことをアウトプットするために下記記事を投稿いたします。

### パスとは
PC上のファイルの住所のこと
ファイルの場所がどこにあるのかをPCが理解できるようにパスが存在しており、パスは「絶対パス」と「相対パス」の大きく2種類に分かれる

### 絶対パス
「http://」もしくは「https://」の後にドメイン、フォルダ名、ファイル名を順番に記述する。
「ドメイン/フォルダ名/ファイル名」のように階層の区切りは「/」を使い、ファイルの居場所を最初から最後まで書くことを「フルパス」という。
外部のリソースを参照する場合に便利。

### 相対パス
絶対パスがファイルまでの道のりを順番に記載するのに対し、相対パスは今いるファイルから対象ファイルまでの道のりを記述する。
「./」が今いるファイルを指し、「./フォルダ1/フォルダ2/対象ファイル」のような書き方になる。
同じプロジェクト内でのリンクの際によく使われる。

### 絶対パスのメリット・デメリット
<dl>
<dt>メリット</dt>
<dd>・ルートディレクトリから自分の居場所まですべての道のりが書かれているため、だれが見てもサーバ上のファイルの位置や構造が把握しやすい</dd>
<dd>・絶対パスはこの書き方しかないため、ファイルが移動されない限りリンク切れを起こさない</dd>
</dl>
<dl>
<dt>デメリット</dt>
<dd>・ルートディレクトリから自分の居場所までの道のりを記述するため、ファイルの場所によってはコードが長くなり処理が重くなる可能性もある</dd>
<dd>・サーバー上でのファイルの居場所までの道のりになるので、ローカル環境では使うことができない</dd>
<dd>・サイトの引っ越しをするとなると、ドメインから全て住所を変更しなくてはならない</dd>
</dl>

### 相対パスのメリット・デメリット
<dl>
<dt>メリット</dt>
<dd>・必要最低限の記述になるため、作業効率が上がりやすい</dd>
<dd>・サーバー上でのファイルの住所ではないのでローカル環境でもテストや作業が可能</dd>
<dd>・サイトの引っ越しやドメイン変更があっても、サイト内の構造が変わらなければパスを変更する必要がない</dd>
</dl>
<dl>
<dt>デメリット</dt>
<dd>階層の変更があるとすぐにリンク切れを起こすため、ファイルを移動させる場合はパスの変更も必要になる</dd>
<dd>フォルダやファイルが増えると「../」や「./」が増え、どこに何のファイルがあるか分かりにくくなる</dd>
</dl>

### ルート相対パスとは
相対パスの仲間で、「ルート」とは一番上のディレクトリのことを指す。
一番上のフォルダから目的のファイルまでの道のりを表記する、絶対パスと相対パスのいいところを掛け合わせたようなパスの記述方法。
ドメイン名の記述が必要なく、ドメインが変更された時もパスの変更は必要がない。
また、ローカル環境でも作業することができる。

## まとめ
絶対パス、相対パス、相対ルートパスはいずれも参照したいファイルまでの道のりを示す記述のこと。
外部のサイトを参照するのに適しているパス、サイトの一貫性を保つのに適しているパスなど、種類によって特性があり開発の内容や環境によって使い方が異なる。
[初心者 - 備忘録]TypeScriptとは

# TypeScriptとは
JSを拡張したスーパーセットプログラミング言語のこと。

スーパーセットとは、JSでは書けないような記法を保管したようなもの。例えばクラスのアクセス権（private, public, protected）は、JSでは定義できないがTypeScriptでは可能になる。

# TSの特徴
①JSに変換してから実行
→TSはブラウザ上で直接実行することはできないため、JSに変換する手順が必要。コードはTSで書いていても、実際に実行されるコードは、JSに変換されたものになる。

②型の定義が可能
→JSは動的型付け言語であり、設定された値によって方が自動的に変更される。TSでは型を明示して設定することができる。

③JSにない記述が使用可能

## メリット
- 型定義によるチーム開発の円滑化
- 公開用ライブラリへの型定義
- 厳密な型定義によるバグの事前検知
- VSCodeの自動補完

## デメリット
- 型の記述が面倒
- JavaScript特有の柔軟で簡易な記述の喪失
組み合わせが膨大なテストケースを減らす方法

# なぜやるのか

パラメータとパラメータが取りうる値の組み合わせが膨大で、人力でテストしきれない場合にテストケースを減らす必要があった
直交表とペアワイズがメジャーな様なので両方お試し

直交表やペアワイズが何なのかや文中に出てくる強さについては各自調べてください

# どうやったのか

まぁLLMに聞くよね
結果、直交表はNICTのACTS、ペアワイズはMicrosoftのpictを使うことにした

## 直交表

LLMでは実装に辿り着けなかったのでググった
結果、論文関連のページに辿り着く

[NISTのACTS](https://www.nist.gov/privacy-framework/nist-acts)というツールを使用  
上記リンクの「Guideline/Tool」の先のページの[FREELY AVAILABLE SOFTWARE](https://csrc.nist.gov/projects/automated-combinatorial-testing-for-software/downloadable-tools)の[Java .jar file.](https://csrc.nist.gov/csrc/media/Projects/automated-combinatorial-testing-for-software/documents/acts_basic_1.0%203.jar)リンクからDL  
ダウンロードページの[ACTS User Guide](https://csrc.nist.gov/csrc/media/Projects/automated-combinatorial-testing-for-software/documents/acts_user_guide_for_basic1.0_and_advanced3.3_versions_nov23.pdf)を参考に動作させた

バージョンが古い気がするけどこれより新しいのパッと手に入らない。（GUI版や最新のは作者にメールすればもらえそうではある）
まぁ組み合わせ生成するだけだし、このアプリのメインの機能だから古くても理論が間違ってなければ大きく間違いは無いでしょう。

jarファイルをDLしたらそれに食わせる組み合わせ表(モデルファイルとかいうみたい)を作る
詳細は上記マニュアルみてくれ
Systemの部分は必須。
はっきり言って要らない情報だと思うが必須なので適当に入れてください。

```
$ cat orthogonal_model.csv
[System]
Name: TCAS
[Parameter]
parameter1(int):1,2,3,4,5
parameter2(int):1,2,3,4,5
parameter3(int):1,2,3,4,5
parameter4(int):1,2,3,4,5
parameter5(int):1,2,3,4,5
```

つくったモデルを強さ３で食わせる

```
$ java -Ddoi=3 -Doutput=csv -jar ./acts_basic_1.0\ 3.jar orthogonal_model.csv ~/Desktop/orthogonal_test_pattern.csv

System Name: TCAS

Strength: 3
Mode: scratch
Algorithm: ipog
Constraint Handling: Ignored
Verify Coverage: off

Parameters	: 7
Constraints	: 0
Covered Tuples	: 4375 (3-way: 4375) 
Number of Tests	: 239
Time (seconds)	: 0.032 

Output file: orthogonal_test_pattern.csv
```

orthogonal_test_pattern.csvが生成される（毎回同じ組み合わせみたいね）

## ペアワイズ

Microsoftが[ツール](https://github.com/microsoft/pict)を公開している

```
git clone https://github.com/microsoft/pict.git
cd pict
make
```

pictバイナリが生成されたら組み合わせのファイルを作って食わせる
下記はパラメータが5つあって、それぞれ１〜５の値を取る場合

```
$ cat pict_model.txt
parameter1: 1, 2, 3, 4, 5
parameter2: 1, 2, 3, 4, 5
parameter3: 1, 2, 3, 4, 5
parameter4: 1, 2, 3, 4, 5
parameter5: 1, 2, 3, 4, 5
```

強さ３で食わせる

```
$ ./pict pict_model.txt /o:3 > pattern.csv
```

pattern.csvが生成される（毎回同じ組み合わせみたいね）


# まとめ

直交表はNICTのACTS、ペアワイズはMicrosoftのpictで組み合わせを減らすことができた。
大体1/100以下には出来るみたい。
めっちゃ助かる
機械的にチェックできるならそれ用のプログラム作ってチェックすれば良いけど、事前に見るべき組み合わせがわからないとか出力結果が妥当かどうか結果を人が見る必要がある場合は有効な手段だと思う。

出力形式がそれぞれ違うのでパースは各自やってくださいね。