OmniAICreator/Qiita-1.07M huggingface dataset:
Mac OS インストール用メディアの作り方

# はじめに
Macをインストールするときとか、Hackintoshするときとかに使えるUSBのMacOSインストールメディアの作り方
Macで作業しましょう

# 1. インストールツールをダウンロード

AppStoreから入れたいOSの名前を検索して入手してダウンロードします
ソフトウェアアップデートからダウンロードされますが気にせずダウンロードします。

Applicationsに`.app`としてダウンロードされます。
そこに到達するまでのパスを覚えておいてください

# 2. USBをフォーマットする

インストールに使用するUSBメディアをMacに接続し、ディスクユーティリティを使用してフォーマットします。

フォーマットは`MacOS拡張（ジャーナリング）`で、方式が`GUIDパーティションマップ`を選択します

# 3. メディアを作成

メディアを作成するためのアプリケーションはダウンロードしたインストールツールの中に入っているためそちらを使用して作成します。

パスは下記の通りです
メディアの名前を `installtool`
ツールの名前を`macOS install.app`、
場所を`/Applications`にあるとします

```
sudo "/Applications/macOS install.app/Contetns/Resources/createinstallmedia" --volume /Volumes/installtool
```

こんな感じで実行して、yで同意して終わるまで待ちます
C#でクラス新規作成時のテンプレートを編集する

# はじめに

C#でクラスを新規作成すると標準では以下のようになっていると思います。

``` DefaultClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    internal class DefaultClass
    {
        //...
    }
}
```

これを新規作成時に以下になるよう編集します。

``` UpdateClass.cs
namespace ConsoleApp1;

public class UpdateClass
{
    //...
}
```

変わった点としては以下になります。
1. ImplicitUsingsに定義されているusingの削除
    - [暗黙的な `using` ディレクティブ](https://learn.microsoft.com/ja-jp/dotnet/core/tutorials/top-level-templates#implicit-using-directives)
2. namespaceをファイルスコープに変更
3. クラスのアクセス修飾子をpublicに変更

# やること

## 不要なusingの削除とアクセス修飾子をpublicに変更

こちらはクラスのテンプレートファイルがVSのインストール時に用意されているので、それを編集します。
自分の環境では以下に保存されていました。(VS2022, Professional)

> C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\ItemTemplates\CSharp\Code\1041\Class\Class.cs

このファイルを開くと以下のようになっています。

``` Class.cs
using System;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ >= 3.5)using System.Linq;
$endif$using System.Text;
$if$ ($targetframeworkversion$ >= 4.5)using System.Threading.Tasks;
$endif$
namespace $rootnamespace$
{
    class $safeitemrootname$
    {
    }
}
```

不要なusingを削除し、アクセス修飾子を追加します。(編集には管理者権限が必要)

``` Class.cs
namespace $rootnamespace$
{
    public class $safeitemrootname$
    {
    }
}

```

## namespaceをファイルスコープに変更

これを行うにはソリューションの.editorconfigファイルを編集します。

> csharp_style_namespace_declarations=file_scoped:suggestion

以上です。

# おわりに

クラス新規作成時に毎回作業を減らすことができました。
テンプレートファイルにはクラス以外にinterfaceもあったので、必要に応じて手を加えることができそうです。
【Web Crypto API】共通鍵暗号方式で暗号化と復号化をしてみた！

# はじめに
javascriptの暗号化で検索をかけるとcrypto-jsを使用した暗号化、復号化の記事がまずヒットします。
ただ、Webの標準機能できないか探していたところ「Web Crypto API」を見つけました。
今回はこれを使用した暗号化、復号化を試してみます。

# 注意
Web Crypto APIを使用して暗号化する場合には注意が必要です。
詳細は下記を参照してください。
[mdn web docs：Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)

# プログラム上の注意
`iv`ですが特定のkeyで再利用をしてはいけないです。
詳しくはAesGcmParamsのPropertiesをご確認下さい。
[mdn web docs：AesGcmParams#properties](https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams#properties)

# 結論
※今回は試すだけでしたので一つのプログラム上で暗号、復号しています。
```jsx
document.addEventListener('DOMContentLoaded', async function() {
  const iv = await window.crypto.getRandomValues(new Uint8Array(12));
  const commonKey = await generateCommonKey();
  const encodedMessage = await encodingMessages();
  const encryptMessage = await encryptingMessages(commonKey,iv,encodedMessage);
  const decryptMessage = await decryptingMessages(commonKey,iv,encryptMessage);
  const decodedMessages = await decodingMessages(decryptMessage);
  console.log(decodedMessages); // encodeした「hello」が出力された
});

/**
 * 共通鍵の生成
 *
 * @return CryptoKey
 */
async function generateCommonKey() {
  let key = await window.crypto.subtle.generateKey(
    {
      name: "AES-GCM",
      length: 256
    },
    true,
    ["encrypt", "decrypt"]
  );
  return key;
}

/**
 * メッセージをencode
 *
 * @return Uint8Array
 */
function encodingMessages() {
  const message = "hello";
  const enc = new TextEncoder();
  return enc.encode(message);
}

/**
 * encodeしたメッセージ暗号化
 *
 * @param {CryptoKey} commonKey 共通鍵
 * @param {Uint8Array} iv
 * @param {Uint8Array} encodedMessage encodeされたメッセージ
 * @return ArrayBuffer
 */
async function encryptingMessages(commonKey,iv,encodedMessage) {
  return await window.crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    commonKey,
    encodedMessage,
  );
}

/**
 * 暗号化したメッセージを復号
 * 
 * @param {CryptoKey} commonKey 共通鍵
 * @param {Uint8Array} iv
 * @param {Uint8Array} encryptMessage 暗号化されたメッセージ
 * @return ArrayBuffer
 */
async function decryptingMessages(commonKey,iv,encryptMessage) {
  return await window.crypto.subtle.decrypt(
    { name: "AES-GCM", iv },
    commonKey,
    encryptMessage,
  );
}

/**
 * encodeされているメッセージをdecode
 * 
 * @param {ArrayBuffer} decryptMessage 復号されたメッセージ
 * @return string
 */
function decodingMessages(decryptMessage) {
  const dec = new TextDecoder();
  return dec.decode(decryptMessage);
}
```

# 参考文献
[mdn web docs：Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
[mdn web docs：SubtleCrypto.generateKey()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey)
[mdn web docs：Crypto.getRandomValues()](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
[mdn web docs：TextEncode.encode()](https://developer.mozilla.org/ja/docs/Web/API/TextEncoder/encode)
[mdn web docs：TextDecoder.decode()](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode)
[mdn web docs：SubtleCrypto.encrypt()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt)
[mdn web docs：SubtleCrypto.decrypt()](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt)
AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.

SqlException: A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught)

ADO.NETでSQLServerに接続を試みると、Errorとなった。

AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.

"リモート証明書は、提供された RemoteCertificateValidationCallback によって拒否されました。"
と表示された。

##### 実行環境
- .NET6
- Microsoft.Data.SqlClient 5.0.0

![Screen Shot 2022-09-27 at 4.00.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482880/06ac99fc-3413-f5b7-6fb0-fba0f8b77181.png)

`RemoteCertificateValidationCallback`は、リモートSSL (Secure Sockets Layer) 証明書を検証してbooleanを返すメソッドだった。

## DB接続文字列を修正
`connectionString`に渡す接続文字列に`TrustServerCertificate=True`を追加した。
"TrustServerCertificate を true に設定した場合、トランスポート層に SSL が使用されてチャネルが暗号化されます"とのこと。

```
"Server={server};Database={database};User Id={id};Password={password};" +
"TrustServerCertificate=True;"
```

## Reference
https://learn.microsoft.com/ja-jp/dotnet/api/system.net.security.remotecertificatevalidationcallback?view=net-6.0

https://learn.microsoft.com/ja-jp/dotnet/api/system.data.sqlclient.sqlconnectionstringbuilder.trustservercertificate?view=dotnet-plat-ext-6.0

https://learn.microsoft.com/ja-jp/sql/connect/jdbc/connecting-with-ssl-encryption?view=sql-server-ver16
Javascriptのmapとreduce

# Javascriptのmapとreduceの動きが<br>ややこしいので、動きだけをまとめる

# map()
mapは配列から中身を１つずつ取り出して、処理を行う。

>map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。(MDN Web docsより)

``` map.js
const array = [1, 3, 5, 7, 9];

const fn = array.map(function (value) {
  return value + 1;
});
 ```

結果

```
>>[2,4,6,8,10]
```
### なにが起きているか？
1. 配列から"1"が取り出される
2. functionの引数"value"に値が渡される
3. value + 1が実施される（初回では1 + 1)
4. 結果が返される (return)
5. 結果の配列に格納される (この時点で[2])
6. 配列の次の値がfunctionの引数"value"に渡される
7. value + 1が実施される（この時点では3 + 1)
8. 結果が返される (return)
9. 結果の配列に格納される (この時点で[2, 4])

以降配列の値分だけ繰り返される...

### メモ
上記コードのfunctionは所謂コールバック関数である。
「return」を書かないと、どうなるか？
``` map.js
const array = [1, 3, 5, 7, 9];

const fn = array.map(function (value) {
  value + 1;
});
```

結果
```
>>[undefined, undefined, undefined, undefined, undefined]
```

戻り値がないため、各配列の結果がundefined(値が未定義)となる。

## 追記
コメントで教えていただきました、アロー関数を使用することで、returnがなくても返ってくる

```map.js
onst array = [1, 3, 5, 7, 9];

const mapped = array.map(value => value + 1);
console.log(mapped);
```
結果
```
>>[2,4,6,8,10]
```

各配列に対して共通の処理をした結果を配列に格納して返してくれる。
その後の処理で処理後の配列の値を使いたいときに使うと便利。
forEachという非常に似たものもあるが、こちらは戻り値がないため、
各配列の値に処理をした結果をその後の処理で使えない。

```forEach.js
const array = [1, 3, 5];

const fn1 = array.forEach(function (value) {
  return value + 1;
});
```
結果
```
>>undefined
```

# reduce()

reduceとは、、、？
>reduce() メソッドは、配列のそれぞれの要素に対して、ユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素における計算結果の返値を渡します。配列のすべての要素に対して縮小関数を実行した結果が単一の値が最終結果になります。(MDN Web docsより)

いまいちわからんのでコードを確認する。

```reduce.js
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const fn = array.reduce(function (sumValue, value) {
  return sumValue + value;
});
```
結果
```
>>55
```

### なにが起きているか？
1.  配列から1番目の値がsumValue, 2番目の値がvalueに渡される
 （今回の場合、sumValueは1、valueは2)
2.  sumValue + value (1 + 2)が行われる
3.  結果が返る
4.  結果はsumValueに代入される
5.  ３番目の値がvalueに渡される
6.  sumValue(3) + value(3) が行われる
7.  結果が返る
8.  結果はsumValueに代入される
9.  以降配列の値がすべて処理されるまで繰り返し
10. 最終的にすべてが足されたsumValueが結果として返される

リファレンスを確認してみると、indexだとか、引数は4つだとかあるが、
とりあえず動きを理解したいだけなので、ここまでとする。

### メモ
こちらも同様「return」がないとどうなるか？

```reduce.js
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const fn = array.reduce(function (sumValue, value) {
  sumValue + value;
});
```
結果
```
>>undefined
```
## 追記
こちらもアロー関数を使用して書けば返ってくる
```reduce.js
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const fn = array.reduce((sumValue, value) => sumValue + value);

console.log(fn);
```
結果
```
>>55
```


# ほんとうは
もっと詳細に理解する必要があると思うが、とりあえずなにが起きてるん？を<br>理解するためにまとめてみた。
【随時更新】Qiitaで勉強になったと思った記事など

## 背景
- Qiitaを漁っているといろんな意味で勉強になったと思う記事がある。
- 自分用の備忘録用としてもすごいと思った記事を順次記載しておく。

## Qiitaで勉強になった記事たち
- Qiitaのサービスを統計的に俯瞰して分析した記事。
    何気にちょっと頑張って記事を書いていると上位者になれることがわかる。

https://qiita.com/Qiita/items/28e1aa0967e607d145fa

## 参考資料

## 個人ブログ

https://takuma-tech.com/2023/01/17/377/
Google UXデザイン：プラットフォームを跨いだデザイン

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

# プラットフォームを念頭におく

UXデザイナーがユーザー体験を構築する際に、なぜさまざまなプラットフォームを念頭に置く必要があります。

プラットフォームとは、
- デスクトップ
- モバイルWeb
- モバイルアプリ
- タブレット
- ウェアラブル
- テレビ
- スマートディスプレイ

など、ユーザーが製品を体験する媒体を指します。

ユーザーは、どのプラットフォームを使用していても、製品が同じように見え、同じように感じられることを望んでいるからです。

# UXデザイナーが考えるべきこと

- 新しい製品を作るときには、<font color="Teal">まず1つのプラットフォームに集中する</font>ことが重要です。選択するプラットフォームは、エンドユーザーのニーズを最もよく満たすものであるべきです。
- そのあとで、追加のプラットフォームに対応するデザインを行えばよいのです。
- <font color="Teal">プラットフォーム間で一貫したユーザーエクスペリエンス</font>を実現することに加え、<font color="Teal">一貫したブランドアイデンティティ</font>を持つことも重要です。Google検索は、デスクトップパソコンでも携帯電話でも同じように見え、同じように感じられるはずです。

# 携帯電話やデスクトップPCでのユーザの動き

ユーザーが携帯電話で過ごす時間は、デスクトップPCと比較して大きな差があります。

- 携帯電話の平均セッション：　72秒
- デスクトップPCの平均セッション：　150秒

で、2倍以上の長さです。

なぜこれが重要なのか？

<font color="Teal">モバイルユーザーは目標志向が強く、1つのタスクを完了することに集中する</font>傾向があります。

# モバイル端末向けのデザインで考慮すべきこと

以前は、ほとんどのモバイル向けウェブサイトがデスクトップ向けサイトのミニバージョンであったため、モバイル向けウェブサイトが使いにくいものになっていることがよくありました。現在では、ほぼすべてのウェブサイトで<font color="MediumVioletRed">レスポンシブ・ウェブデザイン</font>が採用されています。

レスポンシブWebデザインは、デバイスのサイズに応じてWebサイトが自動的に変化するようにするものです。

- デスクトップパソコンで体験する場合、ホームページは複数のカラムで構成されていることがあります。
- しかし、レスポンシブWebデザインでは、ユーザーが携帯電話で同じWebサイトにアクセスすると、複数のカラムが自動的に1カラムに凝縮され、より小さな画面にフィットするようになります。コンテンツはそのままに、使い勝手が格段に向上します。

# モバイルのユーザー体験をデザインする際のベストプラクティス

- <font color="Teal">コールトゥアクションボタンを前面中央</font>に配置し、ユーザーが簡単に目的のタスクを完了できるようにします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/fe91cfbe-b338-829b-b75d-1a4707e15a8d.png" width="200">


- <font color="Teal">ナビゲーションメニューは短く、シンプル</font>であるべきです。モバイルでのユーザーエクスペリエンスをシンプルにしたいからです。そのため、メニューのオプションは、製品のコアな機能のみを強調する必要があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/e6f529f2-1e6f-dbb0-3168-c0ec2f3f0979.png" width="200">

- タップやスワイプなど、ユーザーがすでに行っている<font color="Teal">ジェスチャーを使用する</font>ことです。ジェスチャーは、ユーザーにとって直感的でなじみのあるものであるべきです。

- 携帯電話を持つときの<font color="Teal">両方の方向を想定したデザイン</font>です。携帯電話の縦長表示と横長表示の両方を考慮する必要があります。どのような持ち方をしても、効果的な体験ができるようにしたいものです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/34c34e21-6363-4309-20ea-073b8222b486.png" width="300">

- 視覚的な乱雑さを減らすことです。携帯電話の画面サイズは小さいので、視覚体験をシンプルに保つことが重要です。

# さいごに

ユーザーはデバイスによって異なる振る舞いをします。

UXデザイナーは、その変化をできるだけシームレスに実現する手助けをします。UXデザイナーはその役割を担っているのです。
PythonのVSCodeのデバッグ構成についての備忘録

「実行とデバッグ」のタブメニューより、
「launch.jsonを作成」で自動生成できるが痒い部分をカスタマイズ

```launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            // デバッグ構成の表示名
            "name": "Python: 表示名",
            "type": "python",
            "request": "launch",
            // デバッグしたいファイル名を設定しておけば開いていなくともF5でデバッグ可
            "program": "hoge.py",
            // 外部コンソールでデバッグ
            "console": "externalTerminal",
            "justMyCode": true,
            // 作業ディレクトリの指定
            "cwd": "hoge/fuga/HogeHogeProject"
            // 仮想環境などの場合に任意のpython実行ファイルを指定可能
            "python": "C:/hoge/fuga/python.exe"
        }
    ]
}
```
SQLでVALUESを使ってJOINやEXISTSをする

# はじめに
valuesはinsertでしか使ってきませんでしたが、selectとかupdateとかでも普通に使えるみたいなので、書き残しメモ。
UNION ALL で固定値つなげれば同じことができるのは知っていましたが、、、

# 確認環境
PostgreSQL 14.0
※他のDB環境でも可能かと

# 前提条件
以下のような test_data テーブルがあるとします
```sql
select * from test_data;
+----+---------+---------+
| id | colom_A | colom_B |
+----+---------+---------+
| 1  | 001     | A1      |
| 2  | 002     | A2      |
| 3  | 003     | A3      |
| 4  | 001     | B1      |
| 5  | 002     | B2      |
+----+---------+---------+
```

## JOINの例
```sql
SELECT td.*
FROM test_data td
JOIN(
	VALUES
	('001', 'A1'),
	('002', 'B2')
) AS temp_values(colom_A, colom_B)
ON td.colom_A = temp_values.colom_A 
AND td.colom_B = temp_values.colom_B;
+----+---------+---------+
| id | colom_A | colom_B |
+----+---------+---------+
| 1  | 001     | A1      |
| 5  | 002     | B2      |
+----+---------+---------+
```

## (NOT) EXISTSの例
```sql
SELECT td.*
FROM test_data td
WHERE NOT EXISTS(
	SELECT 'X' FROM
	(VALUES
		('001', 'A1'),
		('002', 'B2')
	) AS temp_values(colom_A, colom_B)
	WHERE td.colom_A = temp_values.colom_A
	AND td.colom_B = temp_values.colom_B
);
+----+---------+---------+
| id | colom_A | colom_B |
+----+---------+---------+
| 2  | 002     | A2      |
| 3  | 003     | A3      |
| 4  | 001     | B1      |
+----+---------+---------+
```

# 最後に
使えそうな状況はパッとは浮かびませんが、意外とスッキリかけて良い気がしています。
「Windows Hello サインインを要求する」がオンになっている状態でmsconfigをいじるとログインできなくなる件の解決法（Windows10 / Windows11）

掲題の件が発生すると、場合によってはシステム復元やリカバリをしなければならないが、
下記方法を試すことでそういった面倒をせずに解決できるかもしれません。
先人の記事では、レジストリをいじる OR システム復元 OR リカバリ というものしか見当たらなかったので、
それ以外の解決法として記しておきます。

# 事象が発生する条件

OS: Windows10（Windows11でも起こるらしい）

- 条件1
設定 > サインインオプション > 「MicrosoftアカウントにWindows Helloサインインを要求する」
こちらがオンになっていること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510573/efca7462-2933-d071-22f0-d0b0e0de8e62.png)

- 条件2
msconfig（システム構成）で通常スタートアップ以外を選択したことで、
Windows Helloに必要なサービスが読み込まれない状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510573/e87edb86-8e8d-b7a4-fd56-ae7cc3c81779.png)

# 発生した事象

再起動すると、サインイン画面で「問題が発生し、暗証番号(PIN)を使用できません」と表示され、ログインできない。
参照：https://answers.microsoft.com/ja-jp/windows/forum/all/%E5%95%8F%E9%A1%8C%E3%81%8C%E7%99%BA%E7%94%9F/f7cc7405-57d0-4969-954e-ee827a3c90e9

# 解決法

ざっくりとした手順は以下となります。
1. Windows起動時のトラブルシューティングからコマンドプロンプトを起動する
1. サインイン画面の右下の簡単操作アイコンにコマンドプロンプトの起動を割り当てる
1. 簡単操作アイコンからコマンドプロンプトを起動し、msconfigで通常スタートアップを選択する

### 1. Windows起動時のトラブルシューティングからコマンドプロンプトを起動する

1. サインイン画面でShiftを押しながら再起動をクリックし、「お待ちください」と表示されるまで待つ
1. 「オプションの選択」画面が開くので、トラブルシューティング > 詳細オプション > コマンドプロンプト を選択
1. 再起動され、パスワードを入力後、コマンドプロンプトが起動する

### 2. サインイン画面の右下の簡単操作アイコンにコマンドプロンプトの起動を割り当てる

1. windows¥system32の格納先ディレクトリを調べる（ここではDドライブとします）
1. カレントディレクトリを移動
`cd /d D:¥windows¥system32`
1. 簡単操作の起動ファイルをバックアップ
`ren utilman.exe utilman.exe.org`
1. 簡単操作の起動ファイルにコマンドプロンプトを割り当てる
`copy cmd.exe utilman.exe`
1. 再起動する
`shutdown /r /t 0`

ここまでの詳しい手順はパソブルさんの記事がとても参考になりました。
https://www.pasoble.jp/windows/10/signin-sippai.html
※「サインイン画面でコマンド操作を有効にする設定」まで

### 3. 簡単操作アイコンからコマンドプロンプトを起動し、msconfigで通常スタートアップを選択する

ここまで来たらもうすぐで完了です。
1. 再起動後、サインイン画面が開く
1. 右下の簡単操作アイコンをクリックすると、コマンドプロンプトが起動
1. 下記コマンドでシステム構成を起動
`msconfig`
1. 通常スタートアップを選択し、再起動



# 所感

場合によっては積むので、「Windows Helloサインインのみを許可する」をオフにして、
複数のログイン方法を確保したほうがいいのかなと。
ただ、セキュリティは下がるのでそこは自己責任って感じですかね。
正規表現のメモ PHP

## 正規表現とは
文字の集合を一つの文字列で表現する方法です。

簡単に言うと抜き出したい文字列だけとってくるということです。

例：電話番号は000-0000-0000におかけください。
みたいな文章があったとして 電話番号は<font color="red">000-0000-0000</font>におかけください。
赤文字のみデータとして取得したい場合などに正規表現を使って取得します。

## 具体例
正規表現は様々なパターンがあるのでいくつかのみパターンを表示します。
```
\d{2,4}-\d{2,4}-\d{4} 電話番号取得の正規表現
[0-9]　　　　　半角の数字を検索
[ぁ-ん]　　　　全角ひらがなを検索
[ァ-ヶ]　　　　全角カタカナを検索
([^"]*) １区切り全て表記
([\s\S(.*)]*) 全て表記
```


## 利用ツール
実際に取得できる文字を確認できるツールを以下に貼っておきます。
※正規表現チェッカーは他にもたくさんあるので使いやすいものを使えばよい
http://okumocchi.jp/php/re.php

## まとめ
正規表現はパターンが状況で違うので全て暗記しなくてよいと思う。
その都度チェッカーで試して確認することをおすすめします。
【Salesforce】担当したSalesforce案件で実際使った技術・使ってない技術

# はじめに
私は約1年前から、Sales Cloudを利用した金融機関向けCRMシステムの構築・エンハンス案件に携わっております。

担当案件に配属される前にTrailheadでSales Cloudの基礎を事前に勉強しましたが、
・Trailheadで勉強して担当案件でも実際に利用している技術
・せっかく勉強したのに担当案件では使ってない技術
がそれぞれありました。

本記事ではそれぞれについて幾つかピックアップして、箇条書き感覚で共有します。
（今後も、随時更新していく予定です。）

もちろん、案件によって利用する技術は違いますが、一つのリアルな案件事例をご紹介して
Salesforce学習時の利用イメージアップに繋がればいいなと思います。

### 対象読者
以下のような方です。
・Salesforce初心者でTrailhead等で勉強中の方
・Salesforce案件で実際どんな技術を使っているかが気になる方


# 実際につかった技術要素
### ①プロファイル、ロール、共有ルール（権限周り）
これはどの案件でも重要かと推察してますが、担当案件でも非常に重要視されています。
CRUD権限の要件を顧客としっかり擦り合せ、プロファイル・ロール・共有ルールでしっかり設定してます。

### ②レポート、ダッシュボード
担当案件の発足経緯として、Excelで管理してた業務をSalesforceで改善したいという背景がありました。
そのため、これまで利用していたExcelのように表形式でレコード一覧を見たいという要望があります。

レポートの種類としては、表形式・サマリー・マトリックス・結合の4種全部利用してます。
また一部のレポートではvisualforceを利用してレポート画面を作成しました。

### ③APEXトリガ、バッチ（イベント駆動型処理、バッチ処理）
レコード作成/更新/削除時に駆動する処理としてApexトリガを利用しています。
ApexはSalesforceでのプログラミング言語であり、Javaによく似た言語です。
Javaを書ける人であれば、Apexでのコーディングもすぐにできるようになると思います。

また、Salesforce上のバッチ処理としては、Apexバッチを使ってます。

### ④Visualforce, Lightning Web Components, Aura Components（画面開発系コーディング）
ホーム画面やレコード詳細画面について、標準で用意されているコンポーネントだけでなく、
各種コーディングによって作成したコンポーネントもがっつり利用しています。

### ⑤Shield Platform Encryption（暗号化）
Salesforceを利用するということは顧客情報や機密情報をクラウド上に置くことになります。
情報流失時のリスクを懸念した顧客の要求により、Shield Platform Encryption（暗号化）を利用してます。

ただしSOQLクエリにてあいまい検索(LIKE句)が使えないなどの制約があるので注意です。
参考までにShield Platform Encryption利用時制約事項のリファレンスを貼っておきます。

https://help.salesforce.com/s/articleView?id=sf.security_pe_considerations.htm&type=5

### ⑥カスタムオブジェクト、カスタム項目
オブジェクト、項目はほぼカスタムで作成しています。

### ⑦Salesforce API (REST API)
他システムとの日次のデータ連携処理で利用しています。insert/update/upsert/delete全部やってます。

データ連携バッチ処理はSalesforceとは別のシステムで稼働させています。
json形式のデータをAPI連携するバッチ処理をShellとPythonを利用して実装しました。

HTTPリクエストのURI・形式・メソッド等は、以下リンクのページやその配下の各ページを参考にしてました。

https://developer.salesforce.com/docs/atlas.ja-jp.232.0.api_rest.meta/api_rest/resources_composite_sobjects_collections.htm

# 使ってない技術要素
### ①商談・リード
Salesforceでは、取引先オブジェクトや取引先責任者オブジェクトに並ぶメイン級の標準オブジェクトですが、担当案件では全く使ってないです。

担当案件は顧客情報管理(CRM)の側面が強く、営業支援(SFA)の側面が薄いです。
商談/営業における各プロセスをシステム上でリアルタイムに管理したいという要望が無かったのです。




### ②ワークフロー、プロセスビルダー（イベント駆動型処理）
Salesforceのイベント駆動型処理のノーコードツールとして、ワークフローやプロセスビルダーが提供されていますが、全然使ってないです。

イベント駆動型処理については、先述のApexトリガで実装してます。Apexトリガの方がより自由度が高いです。

ちなみに、ワークフロー、プロセスビルダーとAPEXトリガ処理を併用するのは良くないそうです。レコード作成/更新/削除時に駆動する処理が多くなるためです。
イベント駆動型処理を実装するなら、プロジェクト開始初期にどっちかに統一しましょう。
無気力エンジニアのAWS SAP合格体験記

# 概要
AWS Certified Solutions Architect - Professional 認定に合格したのに、リモートワークのせいで誰にも褒められないので、Qiitaで自慢します。
あくまでも私見ながら、わかりみが深い合格のノウハウも記載していきます。
要チェックやでぇ！！

# 目次
- プロフィール
- ガバガバ時系列
- 実施した対策
- 合格するためのポイント（私見）
- まとめ

# プロフィール
- SIer
- 3年目
- インフラエンジニア
- AWS歴は1y3m
- 根性/気力/精力が無


# ガバガバ時系列
- 2021/06
    - AWSの現場に異動
- 時期不明
    - AWS Certified Cloud Practitionerに落ちる
    - オンライン受験にはアルファベット表記の名前と顔写真の個人証明が必要と突っぱねられる
    - 直近で海外旅行をしていなかったため、不合格に
- 2021/後半
    - Practitionerはクソ資格と見切りをつけ、AWS SAAに合格
    - 特に対策はせず、ここはノリと地力で突破
- 2022/09
    - 9月頭にAWS SAP勉強開始
    - 末に合格

# 実施した対策
## amazonで買った本（紙）
amazonで[本](https://www.amazon.co.jp/gp/product/4865942483/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1)を買いました。
どこかの合格体験記で「紙で買った方が書き込みとかできて幸せ！」と買いてあったので紙版を買いましたが、これは完全に失敗でした。
日々の業務ですり減りながら、ペンを持って机に向かう人がいるでしょうか。
否、否否否。

肝心の本の内容は、
- 主要サービスとかの参考書っぽい説明
- 問題例と回答・解説の一問一答エリア
- 模試１セット
- その解答・解説

といった感じでした。
試験範囲の網羅度や出題の難易度は低いが、とにかく読みやすい。
対策の入りとしてはいいが、出口ははるかに遠い、そんな内容でした。
結局ページを開いたまま抑えておくのがしんどく、模試のパートには一切触れませんでした。
半分くらい返金されないかな...。

## 自腹udemy
udemyで[講座](https://www.udemy.com/share/1020WG3@GJgjSSKMe5_ZwysmYikOfgC9Ty34lWVFHZ4Zo2CblXN97T6kjQOiNH65xV1LkUTgiw==/)を取りました。
1600円なり。
こちらも、ミスでした。
自分的には、本当に買わない方がよかったです。
1600円あれば嫁さんと大戸屋に行けたと思うと涙が出ます...。

内容は、75問の模試が5セット。

よかった点
- 問題がたくさん
- udemyで勉強してるのナウいやん↑↑
- 自腹で金を出したことによる、「勉強してる感」

悪かった点
- 模試形式なので、一問一答ではない→75問解かないと解答見られない
    - 10問くらい解いて、解答見て、という方法もあるが、10問も結構しんどい（1問2~3分くらい費やすので）
    - 1問ごとにテスト終了して解答確認し、という方法はあまりにもクレイジー
- 問題の内容が重箱の隅をツンツンする系orひっかけ問題系
    - 難題ではあるが、方向性がいまいちで対策としては筋が良くない
    - 「そんなん出るか？？？」と雄叫びながら進めたが、実際出なかった

結局こちらは1セット（75問）だけ解いて、心が折れました。
その後は放置・塩漬け・お茶漬け。

## 自腹web問題集
[web問題集](https://techstock.jp/)を買いました。
6000円くらい？
しかも90日くらい限定。
鬼ですわ。
小学生だったら泣いてますわ。

内容は、7問1セットの問題が70セット（#1は無料で解ける）くらい。
一問一答形式での演習と、ランダム75問選出の模試形式を選択して実施できる。

ああああああ、高い...。
ただ、これが、正解でした。

よかった点
- 問題のレベルが適正（というか、結構そのまま出た）
- 一問一答なので心が折れないで継続できる
- 1セット解くたびに「結果を記録」的なボタンを押下することで各問の正誤を記録可能
    - 逆に、押下しないと記録されない仕様は謎

悪かった点
- たかすぎ、足元見過ぎ
- 期限付き、足元見過ぎ
- 足元見過ぎ

こちらのweb問題集は、新しく追加された問題ほどセット数番号が大きいようで、巷では「#30以降が価値が高い」といった噂も。
自分もそのアドバイス通り、#30,31,32,33,34,35,67,68,69を解きました。
というか、そこで力尽きました。
4000円くらい返金してくれないかな...。

## AWS公式の問題20問
[AWS skill builder](https://aws.amazon.com/jp/training/digital/)とやらで、問題がタダで解けるようなので、解いてみました。
やってもやらなくても同じだったな、と思います。
が、自分の場合は解いた問題の母数が少ないので、実は効果的だったのかもしれません。
まぁ、これやる時間があったら前述のweb問題集解くかな。

## 某社の研修（３日間）
弊社のお金で、某社の研修を受けました。
こういったもの受けるたびに思いますが、試験対策にはまっっっっっったくならないんですよね。
爆速ハンズオンも、やりたかったら個人的にやるよ（やりたくないのでやらない）と毎回思います。
もちろん合格には一切寄与せず。

# 合格するためのポイント（私見）
- [web問題集](https://techstock.jp/exam/sap/)を解きましょう
    - 出費は痛いですが、不合格の方が痛いです
- 最新の問題（執筆現在では#70）から遡って解きましょう
    - そのまま出る率が高いですし、最新の試験範囲に則って作成されている感があります
- わからない問題に当たったら、答えを見る前に自分でgoogle先生に問い合わせましょう
    - 解答を見ると、分かった気になってしまうので、その前に頭を動かすためです
    - blackbelt見たり、実際にマネコンから設定値を確認したら最高です
- 尿意コントロールを徹底
    - 3時間という悠久の試験時間の中、ラスト30分はどんな方でも尿意との戦いになります
    - 普段から尿意のコントロールを徹底しましょう
    - もしくは、おむつこそがソリューションかもしれません

# まとめ
web問題集を後ろから解きましょう。

ちなみに、750点合格のところ、803点合格だったので、まぁ安心ラインかなといったところで、本記事の信憑性もグンと高まるかと思います。

以上、モチベが底をついた無気力エンジニアのAWS SAP合格体験記でした。
とっぴんぱらりんぽん。
UnityでIME

# はじめに

UnityでIMEで入力したい。InputFieldとかじゃなくて。

# 前提

Unity 2021.3.4 f1
New Input System
Windows 10
とりあえず、Editorでの動作確認

# やったこと

InputSystemのKeyboardでIME制御してみた。

```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using TMPro;

public class KeyboardTest : MonoBehaviour
{
    Keyboard _keyboard;

    public TMP_Text m_Text;

    // Start is called before the first frame update
    void Start()
    {
        Input.imeCompositionMode = IMECompositionMode.On;
        _keyboard = Keyboard.current;
        _keyboard.onIMECompositionChange += OnIMECompositionChange;
        _keyboard.SetIMEEnabled(true);
        _keyboard.SetIMECursorPosition(new Vector2(100, 100));
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log(Keyboard.current.imeSelected.isPressed);
    }

    private void OnIMECompositionChange(IMECompositionString compositionString)
    {
        Debug.Log(compositionString);
    }

    public void OnEnable()
    {
        Keyboard.current.onTextInput += OnTextInput;
    }

    public void OnDisable()
    {
        Keyboard.current.onTextInput -= OnTextInput;
    }

    private void OnTextInput(char c)
    {
        m_Text.text += c;

    }
}
```
このスクリプトを、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30257/1b140a9c-ecf1-8580-48fc-85c3f7a30cbc.png)

このヒエラルキーを作って、EventSystemにはりつけ。
Text(TMP)の参照を設定した。
もちろん、日本語表示可能なフォントアセットを設定してある。

# 結果わかったこと

IME入力を有効にするには、
```csharp
Input.imeCompositionMode = IMECompositionMode.On;
```
これがいる。

`Keyboard.current.imeSelected.isPressed`は、IMEが日本語モードで文字を入力しているときに（≒IMEウインドウが出ているとき）にしかTrueにならないっぽい。

`SetIMECursorPosition`と`OnIMECompositionChange`は想像した通りの動きをしていた。

enterなどは、`OnTextInput(char c)`には入ってこないので、別の手段で取得して、改行コードを入れるなりしてやらないといけない。

# TODO

- Windowsビルドや、他のプラットフォームビルドではどのような挙動になるかの検証
- HoloLens2, Quest2 とかでどこまでこれが動くかの検証

テキストエディタ自前で作るか…
paizaラーニング レベルアップ問題集 巡回セールスマン問題メニュー  JavaScript ユークリッド距離

ユークリッド距離 (paizaランク D 相当)

https://paiza.jp/works/mondai/tsp_problems/tsp_problems__euclidean_distance

JavaScriptで解いてみました。
問題文にしたがって実装します。
>ユークリッド距離は、√((x_1-x_2)^2 + (y_1-y_2)^2)です。
# 解答例
平方根はMath.sqrt()で、二乗を**で計算します。
```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [x_1, y_1] = lines[0].split(" ").map(Number);
const [x_2, y_2] = lines[1].split(" ").map(Number);
console.log(Math.sqrt((x_1 - x_2) ** 2 + (y_1 - y_2) ** 2))
```
# 解答例（C++の場合とPython3の場合参考)
ユークリッド距離の計算式を、関数定義しています。
二乗の計算は、Math.pow()を使います。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

//ユークリッド距離の計算式を、関数定義
const dist = (a, b) => {
  return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));    
}; 

const [x_1, y_1] = lines[0].split(" ").map(Number);
const [x_2, y_2] = lines[1].split(" ").map(Number);

console.log(dist([x_1, y_1], [x_2, y_2]));
```
Googleフォトからエクスポートした写真の撮影日時を修正する

# 覚書き
GoogleフォトからTakeout機能で，全写真をエクスポートしたものの，写真の日付がダウンロード日になっている・・・
どうやら写真ファイルそれぞれにJSONファイルが作られていて，そこに日付情報が入っているらしい．

コチラの記事を参考にやってみたものの，ファイル数が多く，分割してダウンロードしたのでフォルダが多くめんどくさい．
https://qiita.com/Fox_Kei/items/d375fbbc029462880294


何かないかと調べていたら，GooglePhotosTakeoutHelperなるツールを発見．

https://github.com/TheLastGimbus/GooglePhotosTakeoutHelper


コレだ！！

まずは，ZIPでおとしてきたのを全部展開．
そしてインストール．
```
pip install -U google-photos-takeout-helper
google-photos-takeout-helper -i [INPUT TAKEOUT FOLDER] -o [OUTPUT FOLDER]
```

私の環境では
python3 /Users/XXXXXX/Library/Python/3.8/lib/python/site-packages/google_photos_takeout_helper
にインストールされたので．パスを通すのも面倒なのでそのまま実行．

--guess-timestamp-from-filename
オプションをつけると，JSONがなくてもファイル名とかから日付を推測してくれるらしい．詳細は上記GitHub参照．




```
python3 /Users/XXXXXX/Library/Python/3.8/lib/python/site-packages/google_photos_takeout_helper  -i '/Users/XXXXXX/Documents/Google/Takeout' -o '/Users/XXXXXX/Documents/Google/OUT'  --guess-timestamp-from-filename
```

できた！
【Dart】EnumとStringのスマートな変換実装方法まとめ [2022年9月版]

# はじめに
dart上でのEnum/String 変換に関する記事をよく見かけるのですが、内容が古いものが多い印象があったので2022年9月最新版ということで記事にしておきます。

# Enum → Stringの変換
Dart2.17以降ではこのように実装できます。

```dart
void main() {
  var name = Align.left.displayName;
  print(name);  // 「左」
}

enum Align{
  left('左'), // Enumのメンバ宣言部分でフィールドも定義できる！
  center('中央'),
  right('右'),
  ;
  
  const Align(this.displayName);

  // フィールド生やし放題
  final String displayName;
}
```

2.17より古いバージョンだともう少しガチャガチャする必要がありこんなかんじ。

```dart
void main() {
  var name = Align.left.name;
  print(name);　 // 「左」
}

enum Align{
  left,
  center,
  right,
}

extension AlignExtensions on Align{
  String get name  {
    switch(this){
      case Align.left:
        return '左';      
      case Align.center:
        return '中央';
      case Align.right:
        return '右';
    }
  }
}
```


### ちなみに
単にenum定義の文字列が必要なだけの場合、dart 2.15以降では「name」プロパティが利用できます。

```dart
void main() {
  var name = Align.left.name;
  print(name);  // 「left」
}
```

# String→Enumの変換
2.17以降のバージョンではSDK純正のメソッドが用意されていますのでこちらを使いましょう。

```dart
var left = Align.values.byName('left');
```
昔は[こんな感じ](https://qiita.com/mkosuke/items/9a9579e08e6d143e4b81)にこねくりまわす必要があったみたいです。便利な世の中になりました。

### ちなみに
byNameメソッドは大文字小文字を区別しています。諸事情によりdartの定義と判定文字列の大文字小文字が異なる場合は自分で拡張メソッドをはやしてあげる必要がありそうでした。

```dart
void main() {
  var leftNG = Align.values.byName('LEFT');
  // ⇒ Uncaught Error: Invalid argument (name): No enum value with that name: "LEFT"
  
  var leftOK = Align.values.byNameIgnoreCase('LEFT');
  // OK
}

extension EnumByNameIgnoreCase<T extends Enum> on Iterable<T> {
  T byNameIgnoreCase(String name) {
    for (var value in this) {
      if (value.name.toLowerCase() == name.toLowerCase()) return value;
    }
    throw ArgumentError.value(name, "name", "No enum value with that name");
  }
}
```

### ちなみに（その２
どうしても2.17を使えない場合...2.14以上であればenumがEnum抽象クラスを継承するようになっているので自力での実装も可能のようです

https://twitter.com/_mono/status/1411850741040308231?lang=ja


# 参考資料
- https://medium.com/dartlang/dart-2-15-7e7a598e508a
- https://medium.com/dartlang/dart-2-17-b216bfc80c5d
ワールドカップが近いので、サッカーの盛り上がりを測るために関連記事数を通知するBOTを作ってみた



![1E8B8040-BFB9-4F33-9D95-D900A16913DF_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847044/7787995a-4e84-f70a-97d8-49e9600c2b1d.jpeg)
　
＃なぜ企画したか
皆さん、サッカーは好きですか？私は大好きです。そして、サッカーの祭典といえば、ワールドカップ！ということで、ワールドカップが近くなったので、サッカーの盛り上がりをQiita内のサッカー関連記事数で測ろうと思い、LINEBOTを企画しました。

＃完成デモ

＃環境

＃作り方

＃おわりに

＃サンプルコード
、、、
const line = require('@line/bot-sdk');
const axios = require('axios');

const config = {
    channelSecret: '', //チャネルシークレットで置き換え
    channelAccessToken: '' //チャネルアクセストークンで置き換え
};

const client = new line.Client(config);

const main = async () => {
    const result = await axios.get(
        'https://qiita.com/api/v2/tags/JavaScript' //この部分を打ち替えて取得するデータを変更する
    );
    const text = result.data.followers_count; //この部分を打ち替えて取得したJSONを操作する

    const messages = [{
        type: 'text',
        text: text
    }];

    try {
        const res = await client.broadcast(messages);
        console.log(res);
    } catch (error) {
        console.log(`エラー: ${error.statusMessage}`);
        console.log(error.originalError.response.data);
    }
}

main();

、、、
App Service で zip ファイルを作成する

App Service の中で zip ファイルを作成する方法について。

# はじめに
App Service はサンドボックスでの提供のため、アプリケーションの追加や一部標準コマンドの実行に制限があります。

例えば [Compress-Archive](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.archive/compress-archive?view=powershell-7.2) コマンドレットに関しても、 'Write-Progress : Win32 internal error' が応答されるため zip ファイルを作成することが出来ません。

![webapp-zip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/1f37f869-708c-a7b5-1e9b-768c0e94ee06.png)

そのため、App Service 内で (WebJob などから) zip ファイルを作成するためには、C# や Node.js, Java などのアプリから作成するか、外部の実行ファイルを使用することが必要です。

# 7-zip の使用
おそらく広く使われており、App Service 上でも動作する処理系として OSS で公開されている [7-zip](https://7-zip.org) があります。
App Service 上で 7-zip を使用する方法として以下の手順が使用できます。

(1). 7-zip のダウンロード: \home\bin に配置することにします。
```
mkdir %HOME%\bin
cd %HOME%\bin

// 7-Zip 22.01 (2022-07-15) を使用する場合
curl -OL https://7-zip.org/a/7zr.exe

// 7-Zip 9.20 (2010-11-18) を使用する場合
curl -OL https://7-zip.org/a/7za920.zip
unzip 7za920.zip
 -> 7za.exe を含むいくつかのファイルが展開されます。
```

(2). 圧縮の実行
7-zip の日本語解説にもありますが、a オプションと出力先になる zip ファイル、格納するファイルを指定するだけです。
以下の例は \home\LogFiles フォルダを圧縮して \home\LogFiles.zip を作成する例です。
```
cd %HOME%
// 7-Zip 22.01 (2022-07-15) を使用する場合
%HOME%\bin\7zr.exe a LogFiles.zip .\LogFiles

cd %HOME%
// 7-Zip 9.20 (2010-11-18) を使用する場合
%HOME%\bin\7za.exe a LogFiles.zip .\LogFiles
```
以下のように作成されます。zip ファイルの中に配置される際のパスは、最後に指定するファイル、フォルダのパスの指定方法に依存します。
zip フォルダ内に格納したい方法に合わせて調整してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349915/bd0c5f24-7cb8-4de4-e9e9-14b756b44c6c.png)

あちこちのフォルダを 1 つの zip に、決まったフォルダ構成で配置したい場合は、特定のフォルダにコピーして配置したファイルを zip でまとめるか、プログラムを書いて zip ファイルを作る必要があります。
OpenCVのaccumulateWeighted()の引数と処理の確認

## 内容
動体検知で使われるaccumulateWeighted()の処理がいまいちよくわからなかったので、簡単に検証してみた。

## 結論
accumulateWeighted()で行われる処理は、第二引数である移動平均の値を更新していくというもの。
第一引数には最新の値を入れる。
第三引数は過去のデータの忘れやすさに相当していて、この値が大きいほど最新のデータの影響が大きくなる。
この値の逆数が移動平均の項の数とだいたい同じ意味になる。

## 検証方法
まっ黒の画像とまっ白の画像を用意して、それらを処理していったときに処理後の値がどう変わっていくかを調べた。

## コード
~~~python
import os
import cv2

# 画像の読み込み
fl = os.getcwd()
white = cv2.imread(fl + r'\white.png')
black = cv2.imread(fl + r'\black.png')

white = cv2.cvtColor(white, cv2.COLOR_BGR2GRAY)
black = cv2.cvtColor(black, cv2.COLOR_BGR2GRAY)

# 読み込んだ画像は白と黒
print(white[0][0], black[0][0])
# 255 0

avg = None
forget = 0.1

for i in range(10):
    if avg is None:
        avg = black.copy().astype("float")
        
    # 黒に白を混ぜていく
    cv2.accumulateWeighted(white, avg, forget)
    print(i, avg[0][0])
    # forget=0.1 -> 25.5 48.45 69.105 ...
    # forget=0.5 -> 127.5 191.25 223.125 ...
    # forget=0.9 -> 229.5 252.45 254.745 ...
~~~

## 解釈
accumulateWeighted()では、
$avg = (1-forget)×avg＋forget×white$
という処理をやっているらしい。

これはたぶん、k+1番目～k+n番目までのn項の移動平均をk+2番目～k+n番目の(n-1)項の移動平均とほぼ同じものと考えることで、過去のデータを記憶しないで簡単に新たな移動平均の値を計算しているんだと思う。

どういうことかというと、
k番目の数を$a_k$、k+1から始まるn項の移動平均を
```math
A^n_{k+1} = \frac{1}{n}\sum_{i=k+1}^na_i
```
としたとき、

```math
A^n_{k+2} = \sum_{i=k+2}^na_i \\
= \frac{1}{n}(\sum_{i=k+2}^{n-1}a_i +a_{k+n+1}) \\
= \frac{1}{n}((n-1)A_{k+2}^{n-1} +a_{k+n+1}) 
```
と変形できる。
先ほどの近似を使うと、
```math
A^n_{k+2} = \frac{1}{n}((n-1)A_{k+1}^n +a_{k+n+1}) 
```
となるんで、一つ前の移動平均と最新の値から新たな移動平均を計算する式になる。
ついでに$f=1/n$とすると、
```math
A^n_{k+2} = (1-f)\,A_{k+1}^n +f\:a_{k+n+1}
```
となって、第三引数の逆数が移動平均の逆数に相当することがよくわかる。

accumulateWeighted()で行われる処理がわかってめでたしめでたしという話。

## 参考URL
OpenCVを利用して動画（カメラ）から動体検知をする方法について
https://developers.cyberagent.co.jp/blog/archives/12666/
golang+ginでreact router対応してみた

## 問題
`r.StaticFile("/", "./dist")`などの書き方だと、ルートページから遷移する場合には動作するが、URL直打ちのように直接アクセスすると404が返ってくる
## 結論
file path + request uriで対応できる
```golang
r.NoRoute(func(c *gin.Context) {
	_, file := path.Split(c.Request.RequestURI)
	ext := filepath.Ext(file)
	//ディレクトリアクセス（ファイル名がない）かパスクエリ（拡張子がない）
	if file == "" || ext == "" {
		c.File("./dist" + "/index.html")
	} else {
		c.File("./dist" + c.Request.RequestURI)
	}
})
```
react routerのような静的fileをserveするときなら全部これで対応できるかなと思います。
たとえsolidjsやvueなども可能。
実際主もsolidjs + vite + vite-plugin-pagesの環境でテストしているいけたので、多分この方法で可能かと思います。
## 参考記事

https://blog.narumium.net/2019/05/27/%E3%80%90go%E3%80%91ginreact%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0/
PHPカンファレンス2022参加した！

# オフライン参加しました

各社システムで使用されているPHP周辺の話を聞くのはとても新鮮で、1日目の一部のみの参加ではありましたが良い経験でした。
開催有難うございます。鉄は熱いうちに打て、という事で一部箇条書きでの投稿お許し下さい。見にくいかもです…スミマセン。

# ****17年続くWebサービスを改善する 〜新卒2年目からみるカラーミーショップ〜****

https://fortee.jp/phpcon-2022/proposal/6669e288-563e-49c5-be45-3871c730b6ab
- 一つ一つ丁寧に説明頂けた
- そのおかげで自分の中に落とし込めました
- とても聞きやすい発表でした

## Webアプリケーションレイヤにおける改善の取り組み
**[@yammerjp やんまーさん](https://twitter.com/yammerjp)**

- 「漸進的に」がキーワード、まさに「漸進的に」取り組まれている様子に全私が（完璧やん…。）となった
- 完璧な裏側には色んな人のアイデアや失敗もあったのかしら、なんて想像を膨らませた
- 是非機会があれば、そういった部分も聞いてみたいと思った

## **カラーミーショップの改善におけるSRE活動について**
**[@h0mirun_deux ほみるんさん](https://twitter.com/h0mirun_deux)**

- SREなんて仕事があるのか（まずそこ）
- 他部署間の連携になってくる仕事って敵同士になりがちなところをしっかり対策打たれていて、
こちらも全私が（完璧やん…。）になった

# ****リリースして11年経過したPHPアプリケーションにPHPStanを導入した****
**[@task2021　tasukuさん](https://twitter.com/task2021)**

https://fortee.jp/phpcon-2022/proposal/0028a971-21f5-4d3f-aea7-63e1279f39b2
- Railsのrubocopに似てると思った
- 別物とは言え、使用した経験があった＆細かなエピソードを聞けて、
めっちゃリアルに自分事として聞けて良かった
- 個人開発でしか使ったこと無かったので、実務で使用する時の話はとても興味深かった
- ちゃんと使う側の事を思い遣った運営で学ぶべきところが多かった
- 仕事でチャットワークを実際に使用していて、色んな人の工夫が詰まったサービスを
毎日使ってるんだな…としみじみしてしまった
- PHPStan使ってみたい

# ****フラットなPHPからオブジェクト指向で自動テストのあるPHPへ、そしてフレームワークへ****
[@77web　ななうぇぶさん](https://twitter.com/77web)

https://fortee.jp/phpcon-2022/proposal/ef41a5ba-4efd-4a9f-b6a8-ae456df00541
- オブジェクト指向、半年前くらいにめっちゃ考えたなぁ（遠い目）
- とても良質な復習ができた
- 個人的に印象に残ったのが後半部分のフレームワークの話
- 「自分が今なにを作ろうとしてるのか。個人開発なのか。業務上の開発なのか。状況によって使用するべきフレームワークは変わるはずです。」
「フレームワークは使っても使われるな。」（記憶から呼び起こしたので、少し異なるかも。すみません。）
- 使用する前に自分がフレームワークを使用して達成したい事を意識する、
フレームワークの事をもっと知ろうとする姿勢が必要なんだと学んだ

# ****PHPで学ぶシステム設計　依存関係のコントロール編****
[@nrslib　nrsさん](https://twitter.com/nrslib)

https://fortee.jp/phpcon-2022/proposal/2a07ae7f-0b02-42d5-a5f3-53d397a7dcfc
- 成瀬さんを見て（本物や…震）となるワタシ
- 何故依存関係が発生するのか、どうしたら依存関係が解消されるのか、プログラムレベルの話から組織レベルの話まで話があった
- ヒントは得た、じゃあ自分を取り巻く環境にある依存関係をどうやったら駆逐できるのか考えたけど、難しすぎてすぐに答え出なかった
- これは本当に色んな場面で使える考え方だから、もっと自分の言葉にして落とし込みたいと思った
- アーキテクトとして自覚を持って、考えたい
- 最後成瀬さんが出演されてるCMが流れて楽しい締めくくりだった
【NestJS】Prismaでマイグレーションが実行できないエラー

<h2>前提</h2>
NestJS、PostgreSQL、ORMとしてPrismaを使用しています。
Dockerで環境構築しています。

Prismaでマイグレーションをしようとしたのですが、エラーが発生しました。

<h2>エラー</h2>
以下コマンドでエラーが発生しました。

`npx prisma migrate dev --name init`

```
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mydb", schema "public" at "localhost:5432"

Error: P1001: Can't reach database server at `localhost`:`5432`

Please make sure your database server is running at `localhost`:`5432`.
```

<h2>原因</h2>

docker-compose.ymlとenvファイルの設定が問題でした。
私の場合、コンテナを削除して一から設定し直しました。

<h2>再現手順</h2>
①それぞれ以下のように記述する

```docker-compose.yml
version: '3.1'

services:
  db:
    image: postgres:13-alpine
    container_name: blitz-blog-postgres
    ports:
      - '5432:5432'
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      POSTGRES_DB: testdb
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:
```

```.env
POSTGRES_PASSWORD="password"
POSTGRES_USER="postgres"

DATABASE_URL=postgresql://admin:password@localhost:5432/testdb
```

②`docker-compose up -d`を入力

③`npx prisma migrate dev --name init`を入力

マイグレーションが成功
【macでwifiに繋がらなくなった時に試したこと】設定ファイルの削除

以前使っていた計算機から今の計算機に移行した際にwifiに繋がらなくなってしまったので解決方法をメモとして残しておきます

## 症状
wifiに接続はしているがインターネット接続がありませんと表示される
前の計算機からtime machine経由で移行したためwifiの設定等はそのまま引き継がれていた

## 計算機のスペック
MacBook Pro（13インチ、M2、2022）
OS: Monterey ver12.6

## 対処方法
**ネットワークの設定ファイルの削除**
手順１：
wifiを切っておく
手順２:
`/Library/Preferences/SystemConfiguration/`
にある以下の５つのファイルを消去する
```
com.apple.airport.preferences.plist
 com.apple.network.identification.plist
com.apple.wifi.message-tracer.plist
NetworkInterfaces.plist
preferences.plist
```
**もしものことがあるためバックアップは取っておく！！**

手順３:
計算機を再起動してwifiを再接続する

この一連の手順によって削除した設定ファイルが新しく作成される

## 最後に
私は登録されているネットワークを削除して繋ぎ直したり再起動してみたりと色々試したがこれできちんと繋がるようになった.
設定ファイルの削除にはある程度のリスクが伴うので試す際はバックアップ等をとってすることをお勧めする.
[参考](https://minatokobe.com/wp/os-x/mac/post-61159.html)
[mac Reports](https://macreports.com/how-to-reset-network-settings-on-mac/)
Selenium使ったらスクレイピングでつまずいた話

こんばんは。
Doryです。

Webスクレイピングをしていたんですけど、今回はSeleniumを使った方法で行ってみたんですね。
自分のプログラミング環境にSeleniumをインストールしたら使いたいものが出てこなかったんですよ。。。
どういうことかっていうと

```
example = a.find_element_by_name()
```

みたいにしたかったんですけど、find.elementの先が出てこなくて使用できなかったんです。

結論を申し上げると、**Selenium4**ではなく**Selenium3**を使えばタグごとの括りができるみたいです！

私は一旦Selenium4をアンストしてSelenium３を入れたら解決しました。

同じような方がいればご参考までに:)
if if　と　if else　は違う

タイトルの通り、if文についての個人的に勘違いしていたことです。

# やりたかったこと
1~30までの数字を出し、3の倍数の時は「あほ」になり、5の倍数の時は「犬」になる。

## 最初に書いたコード
    var number;

    for (var i = 1; i <= 30; i++) {
      number = i;
      if (i % 3 == 0) {
        number = number + "あほ";
      } else if (i % 5 == 0) {
        number = number + "犬";
      }
      document.write(number + "<br>");
    }

これで、実際に出たのはこちら。
1
2
3あほ
4
5犬
6あほ
7
8
9あほ
10犬
11
12あほ
13
14
15あほ
16
17
18あほ
19
20犬
21あほ
22
23
24あほ
25犬
26
27あほ
28
29
30あほ

一見できてるっぽいけど、<font color="red">3の倍数でもあり5の倍数でもある</font>15と30に「あほ」としか表示されていません。
つまり、現時点では「3の倍数」であると判断されているということ。

    var number;

    for (var i = 1; i <= 30; i++) {
      number = i;
      if (i % 3 == 0) {
        number = number + "あほ";　//ここで終わっている
      } else if (i % 5 == 0) {
        number = number + "犬";
      }
      document.write(number + "<br>");
    }

## なぜこうなるのか？
`if{...}else if{...}`文は、複数ある{...}のうち、<font color="red">1つしか処理されない。</font>
つまり、今回のコードでは、まず
`if(i % 3 == 0){...}`を処理して、trueだったら　**「当てはまるやんけ〜！終わり！」**　で、その下の処理は全く見ない。





## ではどうしたらいいのか
答えは非常に簡単だった。
`else if`を`if`に変えるだけ。

    var number;
    
    for (var i = 1; i <= 30; i++) {
      number = i;
      if (i % 3 == 0) {
        number = number + "あほ";
      }
      if (i % 5 == 0) { //ここをifにする
        number = number + "犬";
      }
      document.write(number + "<br>");
    }

こうすると、ifの中身はとりあえず全部処理しようとするので、
一つ目の処理が当てはまっても、 **「当てはまったで〜！ほな、次の条件は...おっ、これも当てはまる！」** という感じで、
当てはまるもの全ての処理をする。

今回の式で言うと、

    var number;
    
    for (var i = 1; i <= 30; i++) {
      number = i;
      if (i % 3 == 0) {
        number = number + "あほ"; //当てはまったで〜　→ 「あほ」を出力
      }
      if (i % 5 == 0) { 
        number = number + "犬";　//当てはまったで〜　→ 「犬」を出力
      }
      document.write(number + "<br>");
    }

    //２つにあてはまったら「あほ」「犬」の順番で出力される。


と言うこと。

if文は全部else ifで処理したことしかなかったので、勉強になりました。
Excel セル式でRの%in%, Pythonのin(pandasのisin)のような処理をする

## まとめ

- XMATCH
- ISNA

を組合せて使うとよい。

## 前提

- Office 365 の Excel

Filter などと併用しない場合は古いバージョンでもinのような処理自体はできる気はするが、未確認です。

## お話

Excelでpower query, power pivot を使うと便利ですが、Filter, Sort, Unique のような dynamic array (?) を処理する関数群も使ってみると非常に便利です。

ある配列がほかの配列に含まれるかどうかを返すような処理が必要になり、調べてみるとCOUNTIFセル関数を使う例が出てきました。が、これはどうも「セル範囲」に対する参照を引数に取るものであって、「配列」は取れないため使えません。

さらに調べると、isnaとmatchを使った例が紹介されていました。要点は次の2点です。

- match(もしくはxmatch) を使うことで、セル参照ではなく配列を引数に取れる
- matchの結果でmatchしないものは#N/Aとなるので、isna関数でtrue, false の配列に変換する

### 不満

ちょっと脇にそれますが、愚痴です。

- Letで使える変数名に数値が含められないことと、含めたときにエラーメッセージが表示されること
- countifが配列に対して使えると明らかにシンプルになる場合があるので、何とかしてほしい...

## 例題&コード例

### 例題

共通のvalueを持つkeyが何件あるか。

### Excel

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269702/955c613d-2726-922c-442c-e0b8a2299d51.png)


``` Excel
=LET(
x, $A$1:$B$10,
xx, INDEX(x,,1),
xxx, INDEX(x,,2),
v, FILTER(xxx, xx=D6),
vv, NOT(ISNA(XMATCH(xxx, v,0,1))),
vvv, (ISNA(XMATCH(xx,D6,0,1))),
SUM(IF(vv=vvv,1,0))
)
```

### R

``` R
d <- data.frame(key=c(1,1,1,2,2,3,3,3,3), value=c(10,20,30,20,40,10,20,50,60))
result <- sapply(unique(d$key), function(v) {vv <- d$value[d$key == v]; sum(d$value %in% vv) - length(vv)})
```

R最近書いてないのでこんな感じになりましたが、もっといいコード例を気軽にコメントしてくださいね！

### Python

時間に余裕ができたら書きます...

## 参考

https://www.excelforum.com/excel-formulas-and-functions/1374187-dynamic-array-in-countif.html
[Python][Tips] さくっと現在日時を取得したい場合

さくっと現在日時を取得したい時に便利なTips。
大量のデータを扱う場合、現在日時をファイル名先頭に付与することで新旧でソーティングできるのでよく利用しています。
```Python
import datetime

now = datetime.datetime.now() # 現在日時を取得
dt = now.strftime('%Y%m%d%H%M%S') # YYYYMMDDhhmmssの書式に整形
print(dt) #20220927221536
```
Safariでoverflow:autoした要素の中のmix-blend-modeが効かないバグ

まず、解決方法。
Stack Overflowからの引用です。

> Is to add `transform: translate3d(0,0,0);`

https://stackoverflow.com/questions/70891365/css-mix-blend-mode-difference-issue-in-safari

こちらで解決できました。

# サンプル

`mix-blend-mode`をかけた要素の親に`overflow:auto`が適用されていて、かつスクロールが発生している場合にSafariだけ`mix-blend-mode`の効果が適用されませんでした。

<p data-height="265" data-theme-id="0" data-slug-hash="OJZzvMB" data-default-tab="js,result" data-user="yukihirog-the-animator" data-embed-version="2" data-pen-title="OJZzvMB" class="codepen">See the Pen <a href="https://codepen.io/yukihirog-the-animator/pen/OJZzvMB">OJZzvMB</a> on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

上記のCodepenのサンプルでは、ピンクの四角の中に、少し大きな青い四角を少しズラして配置しています。青い方の四角には`mix-blend-mode:multiply`を適用されており、両方が重なっている部分は濃い群青色になっています。

3つ並んだサンプルは、左が`overflow`無し、真ん中が親のピンクの四角に`overflow:auto`、右が親のピンクの四角に`overflow:auto`を適用しつつ青い四角に`transform:translate3d(0,0,0)`を適用したものです。

左の`overflow`無しのサンプルは、親の四角の部分はピンクに表示され、はみ出した部分は青く表示されます。`mix-blend-mode:multiply`の効果で重なり部分は濃いめの群青色で表示されており、これが正常です。
また、Safari以外のブラウザでは正常に表示されています。

真ん中のサンプルは、親に`overflow:auto`を追加しています。
Safariだとピンクの四角と青い四角が重なっている部分の色が左右のサンプルよりも明るく、色が乗算されていないことが分かります。

右のサンプルは、さらに青い四角の部分に`transform:translate3d(0,0,0)`を追加しています。
親の`overflow:auto`は生かしつつ、重なり部分も色が濃くなって乗算で描画されていることが分かります。

Safari以外のブラウザでは真ん中のサンプルも正常に表示され、また、`transform:translate3d(0,0,0)`で修正できることからSafariのバグであると思われます。
そのうちSafariが修正されて対策不要になるかもしれません。
HTMLのonclickが動作しなくて5時間悩んだから僕の５時間をこの記事１つにまとめる。

## 初めに
本日、とあることでHTMLのonclickを使用することになりました。
HTMLのonclick要素は、その要素がクリックされたときにjavascriptの関数を発火させることができる便利な機能。
javascriptからやるにはイベントリスナーを参照する必要があり3行クライのコードが必要だけれど、onclickを使用すると何文字かで完成！
これを使わない手はありません。

## コード1
僕は以下のようなコードを立てました。
```html
<button onclick="onclick();">絶対押すなよ</button>

function onclick(){
    var i = 0
    while(i<20){
        if (i%15 == 0){
            alert("＾＠＾");
        }
        else if (i%3 == 0){
            alert("＾￥＾");
        }
        else if (i%5 == 0){
            alert("＾ー＾");
        }
        else {
            alert(i);
        }
    }
}
```
ただ、動きません。

### 対処法
onclickの```;```を消す。
onclickでは、javascriptの関数の;は必要ないのです。
```html
<button onclick="onclick()">絶対押すなよ</button>

function onclick(){
    var i = 0
    while(i<20){
        if (i%15 == 0){
            alert("＾＠＾");
        }
        else if (i%3 == 0){
            alert("＾￥＾");
        }
        else if (i%5 == 0){
            alert("＾ー＾");
        }
        else {
            alert(i);
        }
    }
}
```

**あれ、でも動かない...**
なぜだ。

### 対処法
関数名を直す！

以上のコードを実行すると、エラーが出ます。
なぜか？
関数名がonclickだから！！！

以下のように直しましょう。
```html
<button onclick="onclicked()">絶対押すなよ</button>

function onclicked(){
    var i = 0
    while(i<20){
        if (i%15 == 0){
            alert("＾＠＾");
        }
        else if (i%3 == 0){
            alert("＾￥＾");
        }
        else if (i%5 == 0){
            alert("＾ー＾");
        }
        else {
            alert(i);
        }
    }
}
```
これで正しく動くようになりました。

## 考察
なぜ、関数名がonclickだと動かなかったのか。
ここからはあくまで考察ですが。おそらくonclick要素で、関数onclickを指定するとonclickイベントが発生するのではないでしょうか。
onclickをonmouseoutに変えてみましたが関数名がonmouseoutだと発火しませんでした。

## 終わりに
5時間の成果。
取得した資格をExcelで管理するのを辞めたいので管理アプリを開発してみる(ユースケース編)

# 事の起こり
筆者は資格取得を**趣味**としています．資格取得が趣味というのも変な話かもしれませんが，気付けば数ヶ月に1回のペースで何かしらの資格試験を受験していることに気付きました．よってQiitaでの投稿記事も資格に関する投稿が多い様に思います．そんなことも有ってか，友人から資格について聞かれることもしばしば有ります．時には今まで取った資格の一覧(最新の状況)を是非見せてくれと言われたりします．ところが，現状筆者は資格をExcelのブックファイルで管理しています．関数とフィルターを利用してそれらしき一覧表を出力出来る様にはしていますが，使いやすいとは言えません．数が増えていく度に記録出来る行を増やしていますが，正直こういった作業は大変面倒くさい上に，管理方法としてあまりスマートとは言えません．数が少ない時はそれでも何とかなっていましたが，数が39個[^certify]にもなると級を更新(3級→2級)や資格その物の更新の管理などが大変になってきました．よってこの際思い切って資格管理アプリを開発してみることにしました．今回は管理アプリに欲しい機能(ユースケース)について考えます．

[^certify]: 2022/09現在の取得数

# ユースケース
PlantUMLを使ってユースケース図を作成してみました．ここで各機能の詳細についてまとめてみます．

```plantuml

@startuml
left to right direction
title: 資格取得管理システムユースケース図
rectangle 資格取得管理システム {
	usecase 資格取得情報入力
	usecase 資格取得記録管理
   	usecase 最新取得状況管理
	usecase 更新期限管理
    usecase 記録検索
    usecase 検索結果出力
    usecase 目標管理
}

:User: -down-> 資格取得情報入力 : 情報入力
資格取得情報入力 -[hidden]left- 資格取得記録管理
資格取得記録管理 -[hidden]left- 最新取得状況管理
最新取得状況管理 -[hidden]left- 更新期限管理
更新期限管理 -[hidden]left- 記録検索
記録検索 -[hidden]left- 検索結果出力
検索結果出力 -[hidden]left- 目標管理

更新期限管理 -up-> :User: : 更新期限通知
:User: -down-> 記録検索
検索結果出力 -up-> :User:
:User: -up-> 目標管理 : 目標設定
目標管理 -up-> :User: : 目標達成状況通知
@enduml

```

## 資格取得記録情報入力
今回開発するアプリでは資格の取得情報をデータベース(特にRDB)で管理するアプリにしようと思っています．よって資格取得記録情報入力機能では取得した資格の情報を入力するとデータベースに情報が蓄積されます．

## 資格取得記録管理
入力された取得済資格の記録を管理する機能です．これ以降登場する様々な情報参照機能用のデータベースはテーブルを作るのではなく，この資格取得記録管理機能データベースからビューを作成することで実現しようと思っています．

## 最新取得状況管理
最新の取得状況を参照出来るようにします．例えば同じ資格でも3級と2級に合格している場合，最新の状況では2級のみ表示されれば十分です．先述のように取得管理表からビューを作成することでこの機能を実現します．

## 更新期限管理
資格には定期的に更新を必要とする資格が有ります．更新期限を持つ資格のみ参照出来ると共に，更新期限が近付いたらアラート通知が来る様な機能も実装したいと考えています．

## 記録検索
記録を追加出来ても検索が出来なくては大変不便です．過去の取得資格から特定の資格の取得記録を検索出来る様にする機能です．

## 検索結果出力
上記検索機能で検索した結果を表示する機能です．

## 目標管理
これは実装するか分かりませんが，過去の取得記録の管理だけでなく，今後取得したい目標とする資格といつ取得したいかその期限を管理する目標管理機能も有ると便利だなと思いました．

# まとめ
思いつく限りの欲しい機能をユースケース図でまとめてみました．漏れが有るような気もしますが，これは製品開発ではなく，あくまで娯楽なので，このまま設計・開発フェーズに入って足りない機能に気付いた時点で加筆修正していくこととします．
FizzBuzz問題を解いた備忘録

今日も学んだことを忘れない為にメモします。

## FizzBuzz問題とは
英語圏の有名な言葉遊びである “Fizz Buzz” （フィズバズ）のルールをコンピュータプログラムに実装したもの。
ルールは、1から順に数を数え上げていき、3の倍数なら「Fizz」、5の倍数なら「Buzz」、両方の倍数（15の倍数）なら「Fizz Buzz」、いずれでもなければその数を言う。
```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
```
与えられている仕様を整理すると以下のようになる。

・数字の1~100を出力する
・値が3の倍数のときだけ、"Fizz"という出力に置き換える
・値が5の倍数のときだけ、"Buzz"という出力に置き換える
・値が3と5の倍数のときだけ、"FizzBuzz"という出力に置き換える


## 記述内容
```
def fizz_buzz
  num = 1
  while num <= 100 do
    if num % 15 == 0
      puts "FizzBuzz"
    elsif num % 3 == 0
      puts "Fizz"
    elsif num % 5 == 0
      puts "Buzz"
    else
      puts num
    end

    num = num + 1
  end
end

fizz_buzz
```
```:出力結果
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
```

まずは、1〜100までの数字をターミナルに出力するためのプログラムを書く。
条件を指定して繰り返し処理をしたいので、whileメソッドを使う。
whileメソッドは条件式が真(true)の間は繰り返し実行される。
```
def fizz_buzz
  num = 1
  while num <= 100 do
    puts num

    num = num + 1
  end
end
```

次に"Fizz"、"Buzz"、"FizzBuzz"を出力する条件式を書く。
```
def fizz_buzz
  num = 1
  while (num <= 100) do
    if num % 15 == 0    # 15の倍数のとき
      puts "FizzBuzz"
    elsif (num % 3) == 0    # 3の倍数のとき
      puts "Fizz"
    elsif (num % 5) == 0    # 5の倍数のとき
      puts "Buzz"
    else    # それ以外のとき
      puts num
    end

    num = num + 1
  end
end
```
「3の倍数であるか」「5の倍数であるか」という条件式が先にあると「15の倍数であるか」が適用されなくなってしまい"Fizz"か"Buzz"が出力されてしまうので先に「15の倍数であるか」の条件式を書く。
「〇〇の倍数」を導き出す時は剰余演算子（％）を用いる。

以上になります。

最初はeach分で書いてみたのですが

```
def fizz_buzz
  (1..100).each do |n|
    if n % 15 == 0
      print "FizzBuzz"
    elsif n % 3 == 0
      puts "Fizz"
    elsif n % 5 == 0
      puts "Buzz"
    else
      puts n
    end
  end
end

fizz_buzz
```
結果としてはルール通り数字と"Fizz"、"Buzz"、"FizzBuzz"は出力できたのですがなぜか"FizzBuzz"の隣に次の数字が出てきました。
```:出力結果
FizzBuzz16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz31
```

どなたか理由がわかる方、ご教授ください。