OmniAICreator/Qiita-1.07M huggingface dataset:
【Bun】writeで親ディレクトリが無ければ作成してくれる件

Bun の v1.0.6のリリースノートというかブログを見てたら、「Bun.writeってば、親ディレクトリが存在しない場合は作成するようになりました」とあったので、今回はそれを軽く試してみます。

Bun >  v1.0.6のリリースノート

https://bun.sh/blog/bun-v1.0.16

たとえば、
```
./hoge
```
にいる時に
```
./hoge/huga/foo/piyo.txt
```
な piyo.txt ファイルを書き込みたいときには、一般的には、まずは、例えば次のようにしてシェルやプログラム内で huga/foo までのディレクトリを予め作ります。

```sh:シェルでディレクトリを予め作る
$ mkdir -p huga/foo
```
予め huga/foo を作らずに、例えば次のような write 関数を走らせる write.js スクリプトなどを作り
```js:write.js
import { write } from "bun";
await write("huga/foo/piyo.txt", "Hello, world!");
```
実行すればエラーになります。まぁ、Node.jsでもそうです。
```sh:エラーになる 
$ bun write.js
1 | import { write } from "bun";
2 | await write("huga/foo/piyo.txt", "Hello, world!");
          ^
ENOENT: No such file or directory
   path: "huga/foo/piyo.txt"
 syscall: "open"
   errno: -2

      at /home/tato/bun/create-path-by-write/write.js:2:7
      at asyncModuleEvaluation (:1:33)
      at asyncModuleEvaluation (:1:33)
```
まぁ、普通はここで泣きながらディレクトリを作る作業にいそしむわけです。

でも安心してください。Bun v1.0.16 からはエラーにならず write 関数だけで huga/foo/piyo.txt まで一気に作ってくれます。

予めディレクトリを作る必要もなく、エラーに泣かされることもありません。

まず、バージョンを v1.0.16 に上げてみましょう。

```sh:
$bun upgrade v1.0.16
$ bun -v
1.0.16
```
今度は、実行してもエラーになりません。
```sh:実行する
$ bun write.js
```

```sh:tree でディレクトリを見るとちゃんとできてる
$ tree
.
├─ huga
│   └─ foo
│       └─ piyo.txt
└─ write.js
```

めでたしめでたし。
でも、こんな魔法の杖を使いたくないときもあります。そんな時は、createPath: false を付けてこう書きます。

```js:write.js
import { write } from "bun";
await write("huga/foo/piyo.txt", "Hello, world!", { createPath: false });
```
今日はここまで。

# 最近 Qiita に書いた Bun 関連の記事10選

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

https://qiita.com/toshirot/items/a5dc53ef191d20bbeb42

https://qiita.com/toshirot/items/74476af27e67d8534c5a

https://qiita.com/toshirot/items/94961b6dde72be80ab0c

https://qiita.com/toshirot/items/7a0555b46b3a64a4f643

https://qiita.com/toshirot/items/c4d090bc38f9b85d8cdd

https://qiita.com/toshirot/items/4e8e571dd50a45c651f0

https://qiita.com/toshirot/items/e4eb635596ae4f63bdfd

https://qiita.com/toshirot/items/a81f2073e373b0351493

https://qiita.com/toshirot/items/06a992af8cf8aca9ff95

https://qiita.com/toshirot/items/3af83303f95ac7baa546
S\/MIMEとはなんなのか

# S\/MIMEとは
メールについて
* 暗号化して送信する
* 電子署名する

このふたつを実現できるヤツです。

## メリット
* 通信内容を傍受された際に情報が漏洩する可能性が低下する
* 内容が改ざんされていないか検証することができる。
* なりすましを防ぐことができる

## デメリット
* 運用コストが高い
* 証明書の管理がめんどくさい

# S\/MIMEを導入する課題
メリットを見れば素晴らしいS\/MIMEですがデメリットのように導入には課題がかなりあります。
### 証明書
CA(認証局)に発行してもらいますが、割と値段が高いです。一枚で済むというわけではないので値段がかさみます。

### 管理
証明書の管理も大変です。外部に漏れないようにするのでセキュリティ的な知識が必要になります。

### メールクライアント
企業などで導入する際にPCにメールクライアントを入れてそれに設定する必要があります。S\/MIMEに対応している必要性があります。

PPAPだめ!!みたいなのが叫ばれていますが、メールの安全性の担保は課題ですね...
【AWS】署名付きURLの生成＆アップロード処理

## はじめに
AWS S3の署名付きURLを使用してファイルアップロード処理をする方法について紹介します。
背景としてはAPI Gateway→Lambdaを介してS3にファイルをアップロードする機能を作成していたのですが、API Gatewayでは10MBまでのファイルしか受け付けない仕様となっており10MB以上のファイルをアップロードするケースがでてきたためこの問題を解消する必要がありました。そこで、画面から直接S3にファイルをアップロードするよう、S3の署名付きURLを使うアップロード処理に変更しました。

## 処理の流れ
1.画面からAPI Gateway→Lambdaを経由して、S3から署名付きURLを取得する。
2.取得したURLを使用していアップロードを実施。

## ソースコード
### 署名付きURL取得処理
API Gatewayの設定は割愛して、Lambdaに設定するソースコードのみ紹介します:point_up_tone1:言語にはNode.jsを採用しています。

```javascript
// 必要なnodeモジュールを読み込む
const { S3Client, PutObjectCommand } = require('@aws-sdk/client');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

const client = new S3Client({
    region: 'ap-northeast-1',
    signatuteVersion: 'v4' // 署名付きURLを取得するにはv4の指定が必要
})

exports.handler = async (event, context) => {
    const params = {
        Bucket: S3のバケット名を指定,
        Key: S3のオブジェクトの取得場所を指定
    }
    const expires = 署名付きURLでのアクセスの許可時間を指定

    try {
        // 署名付きURLを取得
        const url = await getSignedUrl(client, new PutObjectCommand(parmas), {
            expires
        })

        return {
            headers: {
                'Access-Control-Allow-Origin': '*'
            },
            body: url
        }
    } catch(error) {
        return {
            headers: {
                'Access-Control-Allow-Origin': '*'
            },
            body: null
        }
    }
}
```

### アップロード処理
フロントの言語にはReact(Next.js)を採用しています。TypeScriptも使用していますが、ここでは割愛しています。
画面から署名付きURL取得処理の呼び出しから、アップロード処理までを紹介します。

```javascript
const axios from 'axios';

export async function upload( file ) {
    // 署名付きURLの取得
    const getUrlResponse = await getSignedUrl();
    const url = getUrlResponse.body;

    // URLが取得できていない場合の処理内容を記載する
    if (!url) return;

    // S3にファイルをアップロードする
    await uploadFile(url,file);
}

// 署名付きURLの取得
export async function getSignedUrl() {
    const result = await axios.get('APIGatewayのURL').then((response) => {
        return {
            body: response.data
        }
    }).catch((err) => {
        return {
            body: null
        }
    })

    return result;
}

// ファイルアップロード処理
export async function uploadFile(url,file) {
    const result = await axios.put(url, file, {
        headers: {
            'Content-Type': file.type
        }
    }).then((response) => {
        return {
            body: response.data
        }
    }).catch((err) => {
        return {
            body: null
        }
    })

    return result;
}
```

## S3側の設定
実装時に悩まされたのが、CORSエラーです:joy:
下記の設定をS3のアクセス許可のCORS設定でしました。
```json
{
    "AllowedHeaders": [
        "*"
    ],
    "AllowedMethods": [
        "POST"
    ],
    "AllowedOrigins": [
        "http://localhost:3000"
    ]
}
```
AllowedOriginsにローカル環境のポート番号を設定します。

## さいごに
こちらの記事参考になれば幸いです:woman_tone1::point_up_tone1::dizzy:
AWS SSO PortalにサインインしたことをSlackに通知したい

この記事は<a href="https://qiita.com/advent-calendar/2023/tsukulink">ツクリンク プロダクト部 Advent Calendar 2023</a> 16日目の記事です。


## はじめに

ツクリンクのエンジニアのkariyaです!!
インフラ領域を担当しています！最近インフラをAWSに移行したのですがAWSはまだまだ初心者で日々キャッチアップに勤しんでいます。。。

---

AWSに移行してアカウント増えたのでIdentity Center(旧AWS SSO)を導入検討中で、
SSOポータルのサインインをSlackに通知するようにしてみました。


もともと弊社のインフラはHerokuでしたが、今年AWSへ移行しました。
移行する前からSNSやS3など一部AWSを利用していたので、ログイン通知はSlackにすでに連携していました。
AWS移行後はSTG,本番とAWSアカウントを複数管理することになったのでIdentity Center検証中で、
ポータルへのログイン通知も行えるか確認したらできそうだったのでやってみました。


## 使用したサービス
- Slack Incoming Webhook
- Lambda
- Cloud Watch
- CloudTrail


## 流れ
![スクリーンショット 2023-12-12 12.51.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591361/6ead5b94-30f6-33b1-9a86-bd0469333585.png)

1. CloudTrailからCloudWatch Logsへの配信を行う
2. サブスクリプションフィルターから条件を指定しLambdaにログを転送
3. LambdaでSlackのwebhookを叩く


サブスクリプションフィルターのフィルターパターンに下記検索文字列、送信先にLambdaのarnを指定。

```
{ $.eventName = "UserAuthentication" }
```


Lambdaは以下
```ruby:lambda_function.rb
require 'json'
require 'aws-sdk'
require 'zlib'
require 'base64'
require 'net/http'
require 'uri'

def lambda_handler(event:, context:)
    aws_account_name = ENV["awsaccountname"]
    gzip = Zlib::Inflate.new(Zlib::MAX_WBITS + 32) 
    event_gzip = Base64.decode64(event['awslogs']['data'].to_s)
    event_json = JSON.parse(gzip.inflate(event_gzip))
    event_json['logEvents'].each do |log|
      event_message_json = JSON.parse(log['message'])
      if event_message_json['eventName'] == "UserAuthentication"
        message = <<EOS
#{aws_account_name} のAWSアカウントにログイン処理が発生しました。
発生日時: #{event_message_json['eventTime']}
アカウント名: #{event_message_json['userIdentity']['userName']}
EOS
      else
        message = event_message_json.to_s
      end
        
      # webhookURLは環境変数から取得
      webhook_url = ENV["webhookURL"]
      uri = URI.parse(webhook_url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      
      request = Net::HTTP::Post.new(uri.path, {'Content-Type' => 'application/json'})
      request.body = { text: message }.to_json
    
      response = http.request(request)
      {
        statusCode: response.code.to_i,
        body: response.body
      }
    end
end
```
※webhookURLとaws_account_nameは環境変数に外出しします。

実際の通知はこんな感じ
![スクリーンショット 2023-12-11 20.20.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3591361/bb50188f-f902-4fc5-3c69-1d24a585561e.png)



## おわりに
またIdentity Centerや運用周りで気づきがあれば記事にしたいと思います。
<a href="https://qiita.com/advent-calendar/2023/tsukulink">ツクリンク プロダクト部 Advent Calendar 2023</a>
テストの自動化について

こんにちは！

T-DASHさんのアドベントカレンダー参加記事です！
テストの自動化は以前から興味があったので、投稿します！

# これまで経験したテスト関連タスク
テストに関するタスクで、今まで経験したのは以下の通りです。

- テスト項目作成
- Webサービスの手動テスト
- スマホアプリのテスト（主にゲーム）
- 位置情報のテスト（チャリで移動）
- web3サービスのテスト
- テストコード作成

# 自動化したいと思ったタスク
全てです。

位置情報は仕方がない（さすがに自動は危険）と思いますが、他のタスクは、全て自動化したいです。

### テスト項目作成
要件や設計に応じて、ある程度のパターンが自動生成されて欲しいです。

### Webサービスの手動テスト
これも自動化は必須ですね。
何パターンものユーザーを作成したり、メッセージの送受信や購入パターンなど、仕様に応じたパターンが欲しいです。

### スマホアプリのテスト
webサービスよりはライトだと思いますが、自動化できるのであれば、非常にありがたいです。
特にOSバージョンアップによる影響を早めにキャッチアップしたいです。

### 位置情報のテスト
先述の通り、これは仕方ないですね。
さすがに位置情報を偽装する訳にもいかないので、人力しかないかな、と思います。

### web3のテスト
ウォレットによる承認が必要になるので、少々厳しい気がします。
しかし、手間がかかるので、自動テストができるなら嬉しいです。
web3の負荷試験てどうやるんだろ、、

### テストコード作成
メンテナンスが大変なので、自動化できると嬉しいです。
コーディングしてるそばからAIでテストコードを自動生成、、、なんてことができたら最高ですね。（IDEに組み込まないと難しいかな？）

# T-DASHとは？
ここまで色々と書きましたが、T-DASHについて知りませんでした。
展示会で見かけた気もしますが、他の目的で訪れていたため、お話を伺っていないかもしれません。
せっかくなので、調べてみます。

### 公式サイト
[T-DASHの公式サイトはこちら](https://service.valtes.co.jp/t-dash/)です。

### テスト実行までの流れ
1. 日本語でテストケースを作成
2. 画面の要素をキャプチャ機能で取得
3. 要素に従って動作を設定

日本語でテストケースを作成できるのはいいですね。日本語のテストケースをそのまま実行することができるようです。

テスト実行までの流れを見るだけでも、導入しやすそうです。
![スクリーンショット 2023-12-11 20.13.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/d907557d-f6fd-0c30-8f2c-91dc8bd39570.png)

### 今後に期待できそう
2023年度にAIも組み込まれるようなので、楽しみですね！
![スクリーンショット 2023-12-11 20.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/f0c4abca-e261-c297-3599-2008995de6c0.png)

業務ではあちこち飛び回っているので、なかなか落ち着いて利用できませんが、個人開発で一度試してみたいな、と思います。

最近、React、ReactNativeを中心とした個人開発をしているので、開発が落ち着いたら利用してみます！

また改めて、利用した感想を書こうと思います！
例えば、駅７００m圏内にコンビニが何軒あるか集計する方法

施設を最適な場所に建てるためや、どのエリアでビジネスを始めるかを決めるために、例えば「駅から700m以内にコンビニが何軒あるか」といったことを調べることがあります。そういう時には、GIS（地図情報システム）を使うことが多いのですが、簡易な分析であればTableauでも簡単にできます。

## 用意するもの
- ポイントデータ２種類
  - ポイントデータは、緯度経度つきのCSV、shapefile、geojson、gdbなどTableauで読めるものなら何でもOKです。
  - ２種類必要なのは、片方が円の中心、もう片方がカウントする対象です。
  
以下では、例として、駅ポイントを円の中心、コンビニポイントをカウントする対象として説明します。


## 操作方法
### 方針
駅ポイントから全てのコンビニポイントへの距離を計算し、一定距離以下のものでフィルターしてカウントします。力技です。

![半径の判定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114658/6565ee08-6ceb-b1fa-ccc1-ac354fb93faa.png)

### ポイント間のリレーション設定
距離の計算をするためには、まず、駅ポイントとコンビニポイントにリレーションを設定する必要があります。通常、リレーションではキーになる項目を設定しますが、駅ポイントとコンビニポイントのすべての組み合わせについて距離を計算する必要があるため、以下の図のように、フィールドを選択するのではなく計算の編集で数字の「1」を入力します。
![relation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114658/f5ead9d0-7e04-38de-1454-de18650808f3.png)

### 距離の計算
駅とコンビニ間の距離の計算は`DISTANCE([駅ポイント],[コンビニポイント],"m")`とするだけです。なお、ジオメトリはポイントである必要があります（ラインやポリゴンはダメ）。緯度経度を含むCSVの場合は、`MAKEPOINT([緯度],[経度])`を使うことでポイントのジオメトリフィールドを作成することができます。

距離でフィルターするか、`[距離]<=700`といった判定式でフィルターして、コンビニポイントのカウントをすれば完成です。判定式`[距離]<=700`の700をパラメーターにすれば、円の半径を操作できるようになります。

## 別解
なお、別解として、物理テーブルの結合で行うこともできます。物理テーブルでの結合は、データソースの（論理）テーブルをダブルクリックすることでできます。
![結合１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114658/623d448c-a637-a818-1a28-a38bb8fd9b93.png)

そのうえで、計算の編集で駅ポイントのBUFFER（700m円）を作成し、それとコンビニポイントのintersectsで結合します。ちなみに「intersects」はジオメトリの結合をしようとする時しか出てこない親切設計なので、普通に使っているだけでは気づかないかもしれませんね。

![結合３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114658/c89076c2-4605-6397-9a2d-10897d799d84.png)

### 別解の欠点
標準機能のintersectsで実現するのは感覚的に理解しやすい操作ですが、次のような欠点もあるので、それを理解したうえで使う必要があります。
- BUFFERのサイズを動的に変更できない。
BUFFERのサイズ（この場合700）をフィルターやパラメーターを使って、動的に変更することができません。リレーションを使った場合は、距離のフィルターで変更することができますし「200m-700mの間」といった指定も可能です。
- 集計がしづらい
結合の特性を理解していないと、同じ値が何回も集計されてしまうことがあります。


## まとめ
以上のように、GISを使わなくても、Tableauで簡単な商圏分析ができます。ぜひ活用してみてください。
AtCoder初心者振り返りメモ ABC332

# ABC332の回
https://atcoder.jp/contests/abc332

# A-問題
https://atcoder.jp/contests/abc332/tasks/abc332_a

![332A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547298/701435fd-5bd3-88ce-9620-868a2dca184c.png)

シナリオを忠実にコードに反映させた

````Python:A.py
N,S,K = map(int,input().split())

all = 0

for _ in range(N):
    P,Q = map(int,input().split())

    # 購入費の総和を求める
    all += P * Q

# 送料が必要か判定する
if all < S:
    print(all + K)
else:
    print(all)
````

# B-問題
https://atcoder.jp/contests/abc332/tasks/abc332_b

![332B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547298/54db155f-f1a0-2c45-b65d-c74344b9626b.png)

この問題もシナリオを忠実にコードに反映させた

````Python:B.py
K,G,M = map(int,input().split())

# グラスとマグカップの初期値 0
g = 0
m = 0

# K回繰り返す
while K: 
    K -= 1

    # グラスが満杯なら空にする
    if g == G:
        g = 0
    
    # マグカップが空なら満杯する
    elif m == 0:
        m += M
    
    # グラスに注げる分だけ移動する
    elif (G - g) <= m:
        m -= (G - g)    
        g = G

    # マグカップに入っている分すべてをグラスに注ぐ
    elif (G - g) > m:
        g += m
        m = 0

print(g,m)
````

# C-問題
https://atcoder.jp/contests/abc332/tasks/abc332_c

![332C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547298/1a2c2855-39ce-b222-f4aa-edb18960cf5b.png)

洗濯済無地シャツが無かったり、イベントに行くときにロゴ入りシャツを購入する
丁寧に実装したつもりが本番では、16問WA でした。最後に洗濯済と購入したロゴ入りシャツを加算するのを
忘れていたかもしれません。

````Python:C.py
# 無地のTシャツM枚
N,M = map(int,input().split())
S = input()

# ストックしている無地のシャツ
m = M

# 無地を汚したシャツをカウントする
xm = 0

# ロゴ付きシャツ
l = 0

# ロゴ付きを汚したシャツをカウントする
xl = 0

for i in range(N):
    if(S[i]=="0"):

        # 汚したシャツを洗濯する
        m += xm
        xm = 0

        # 汚したシャツを洗濯する
        l += xl
        xl = 0

    elif(S[i]=="1"):

        # 無地が残っているとき
        if  m > 0:
            m -= 1
            xm += 1
        
        # ロゴが残っているとき
        elif l > 0:
            l -= 1
            xl += 1
        else:
            # ロゴを買って着る
            xl += 1

    elif S[i]=="2":
        # ロゴが残っているとき
        if  l > 0:
            l -= 1
            xl += 1
        else:
            # ロゴを買って着る
            xl += 1

# ロゴの枚数を集計
l += xl

print(l)
````
プロダクトマネージャー(PdM)としてやっていること

年末に追われています、[r_naka](https://qiita.com/r_naka)です。
外部向けに発信することがほぼ初めてなので簡単に自己紹介をさせてください。

### 自己紹介
システムエンジニア→Webディレクターを経て、
株式会社エイシス（現 株式会社viviON）にディレクターとして入社。
入社後一貫して、後述するクリエイター支援サイトCi-enを担当。ディレクション業務以外にもサービス運営、営業を担当後、今年からPdMに。

### 担当サービスの紹介
[クリエイター支援サイトCi-en](https://ci-en.net/)
イラストレーター、漫画家、VTuber、ゲーム開発などなど色々なジャンルで活動する「クリエイター」が「ファン」の方から継続的な支援を受けることができる支援サイト。
BtoCtoC（企業→クリエイター→ファン）サービスに該当。

### 諸注意

PdM向けの書籍や記事によく書かれていること、特にスキルセットの面はあまり書いておらず、マインドセットに偏った内容になっています。
キャリアの比較的早い段階で、エンジニアからビジネスサイドに寄っているので、Qiitaに投稿されたこの記事を読んでいただいた方のどこまで参考になるかは読めないのですが、少しでもご参考になれば幸いです。


### PdMになるまで

現職で務めるまでのシステムエンジニア、Webディレクターのいずれもクライアントワーク主体の会社だったこともあり、
いかに納期に間に合わせるか、その中でクライアントの要望を取り込んでクオリティアップに努めるかという観点が重視されていました。
それが業務である以上間違ってはいないのですが、
ビジネスサイドにも関わりエンドユーザーに近いところで仕事がしたいという思いで転職活動をし、立ち上げ直後だったのちの担当サービスのディレクターのポジションが空いていたのでそのまま入社。

それまでは「開発をするための仕様をつくってリリースする」という世界でやってきた人間にとって、「それ以外のことをやってもいい」環境は非常に刺激的でした。
ただ裏を返せば「それ以外のこともやる」ことでもあります。
つまり担当サービスをより多くの方に利用いただくという目的のために、ディレクション業に固執せず、営業やサービス運営に携わることになります。

このことから立ち上げ直後のサービスに関わるというのは

- 自分がこれまでやってきた職種やスキルに固執しない
- 泥臭いこともやる
- スベることもある 

という3点を学びました。

またスキルセットとしてキャリアの初期で
- Webアプリケーションの仕様をつくり、開発してリリースするまでの仕組み
- UI,UXデザインのプラクティス

の2点が拠り所になったのも大きかったです。

### PdMになってから

前任のPdMが退任してディレクターとして関わるようになり、それと合わせてPdMになりました。
その前からPdMを志向していたこともあり、世にあるPdM向けの書籍や記事は見つけ次第ストックしたり、度々読み返すようにはしていましたが、実際にPdMになってプロダクトをマネジメントするのは全然別モノでした。

特にtoCサービスの場合はそうだと思うのですが、
世の中の潮目を読み、短期的or長期的な視点でどう動くかを決めるのは、そのプロダクトにどっぷり浸かることで見えてくるものがありました。
ディレクターとして担当していた「企画してリリースして反応を見る」という枠から、より大きな枠で見ることの必要性を強く感じました。

### スタンス1. なんでもやる

そんな、PdMとして動いていくなかで固まっていったスタンスが **プロダクトを成長させるためならなんでもやる** です。

チーム専属のデザイナーとエンジニアがいるので、「デザインとプログラミング以外は全部が担当領域」というつもりでいます。
より具体的には、プロダクトの成長に必要なことであれば、たとえこれまで業務でやったことがない領域でもやる。自分がやる場合もあれば部署を超えてやる、ということを意識しています。
開発方面のキャリアを経たこともあり、最初の内は「機能で課題を解決する発想」をしがちだったのですが、本当にその手段しかないのか？と自問して徐々に切り替えました。

※プロジェクトマネジメント（PjM）やプロダクトマーケティングマネジメント（PMM）も取り込んだ「広義のPdM」の動きだと自分では思っています。


### スタンス2. 一次情報にあたる

さらにさらに具体的には、とにかく一次情報のインプットを絶やさないようにしました（今でもしています）
例えば、担当サービスを使ってくださっているユーザーさんの声を自分で見に行くことや、
まだ使ってくれていないユーザーさんだけど、どういうことがあれば使ってくれそうかといったこと。

そのアウトプットとして企画を立てることもあれば、さらに大きな粒度で、方向性を決めることに役立てたりしています。


### まとめ

かなりポエミーな内容になってしまったのですが、
PdMとしてやっていることは、これまでやってきたことに固執せずプロダクト成長を目指す だと考えています。
その取り組みの先で、より多くのユーザーさんに喜んでいただけるプロダクトをつくり続けたいです。
炎上案件が初PMだった去年の自分へ捧ぐ、プロジェクトマネジメントの勘所〜チーム内のルールを作る編〜

# はじめに
前回の続き
https://qiita.com/abe_shiro/items/59781017b2f999f01e18

### 急遽プロジェクトマネージャー就任
バックエンドエンジニアだった筆者、プロジェクトマネージャーの休職や退職により、突然複数の案件のプロジェクトマネージャーとして担当することになった。

### 大規模プロジェクトの遅延と問題
引き継ぎがない中で担当した案件は、n億円規模の新規モバイルアプリ開発。
プロジェクトは遅延しており、メンバーは高稼働状態。
ルールや責任範囲が不明瞭で、開発範囲も不確定な問題が多数存在していた。

### 経験の振り返りと改善点の考察
PMとしての立ち回りを振り返り、どのように対応すればよかったか、改善点を考察していきます。

# 問題
開発とテストメンバー（プロパー＆パートナー）の入れ替わりが激しく、それぞれが認識しているルールが違いコミュニケーションエラーが生じている状態だった。
また、誰が判断をするかも明確ではない状態で、判断待ちのチケットがかなりの数溜まっていた。
私が案件に入った時点だとメンバーは、開発とテストを合わせて40人くらいの規模。
人の入れ替わりが激しく、マネジメント職の人だけでも下記のような変遷があった。

PM①(退職)→PM②(休職)→PM代理のエンジニアリーダー(退職)→私

# 解決方法
社会あるところに法ありなので、案件に入ってる人が守る共通認識のルールを作って運用する。
抜粋ですが、下記の内容をまとめたドキュメントを作成。

・エスカレーションプロセス
・意見やフィードバックの共有方法
・タスク管理と進捗報告のルール
・進捗報告の頻度とフォーマット
・チームワークと対人関係のルール
・チケットのワークフローと対応する人

作るところまではよくても運用をしなければ意味が無い。
ルール運用は監視してチェックする人が居ないとだんだん形骸化していくので、ルールが浸透するまでは逐一アナウンスしていました。
ある程度ルールが共通認識になってくると、チーム内に社会性が出てきて自発的な動きが出てくるようになった。

# おわりに
炎上案件あるあるなのかもしれないが、炎上する一因としてコミュニケーション不足があると思った。
コミュニケーションを円滑にするにはルールが必要で、メンバーもあれやっていいのかな、誰に報告しないといけないのか悩んでしまい動きが遅くなる。
今回の件で思うのは、ルールは人数が多くなればなるほど必要。
案件に居るメンバーが5人くらいのプロジェクトなら、ガチガチのルールがなくてもその場その場で認識を合わせてやっていけるかもしれない。
ルールを作り案件全体で共通の認識を作る事で、トラブルを少なくして円滑に案件を進めることが出来る。
後は、ルールを形骸化させてないこと。
おいしいカレー作りに学ぶプロジェクト管理

# この記事の目的
プロジェクト管理についてゆるふわな感じで学びましょう。
あるある、と思いながら少しでも興味を持ってもらえればうれしいです。

プロジェクトリーダーを任されたんだけど、プロジェクト管理って何すればいいかわからない。
調べるのも面倒くさい。という方向けのレベル。

# 内容

### 導入
私はルームシェアをしていて3人で生活しています。
みんなズボラなので料理などは全くやりません。
そんなある日、徐(おもむろ)にカレーが作りたくなって居ても立っても居られなくなりました。

#### 統合マネジメント
思い立ったが吉日。
早速同居人に今晩のご飯にカレーを作ることを提案しました。
しかしながら、一様に面倒だと、食べに行けばいいじゃないかと却下されてしまいました。。。

そう、みんなにはカレーを作る意義がなかったのです。

そこで私は、なぜカレーを作りたいのか、作ることで得られる達成感、深まる絆、愛、など、私たちにもたらされるものを丁寧に説明し、みんなでカレー作りを始めることができることになりました。


#### スコープマネジメント
カレーと言ったらスパイス。
数百あるスパイスから何を選択するのかが醍醐味でしょう。
香り、辛味、色、まずは基本分野でそれぞれどのスパイスを選定するか早速作戦会議です。

・・・

なぜだか心なしかみんな怪訝な顔をしているように見えます。
それはみんなが求めるものではないと却下されてしまいました。

スパイスの調合は皆がカレー作りに求めることに対して必要ではなかったようです。また、スパイスから選定していたらそもそも夕食に間に合わないでしょう。
迸(ほとばし)る情熱の前に現実が見えていませんでした。
私の理想からは少し遠ざかってしまいますが、皆に説明したカレー作りの目的を果たせる要件、つまりみんなのニーズと実現性を勘案し、市販のルーと具材の選定を以ってカレーを完成させることで合意しました。


#### スケジュールマネジメント
あれこれ話していたらもうすぐ夕方です。
このまま行き当たりばったり作業していたら夕食に間に合いません。
下調べ(作り方すら知らない)、買い出し(調理道具すらない)、具材の選定、調達、準備、下ごしらえ、調理、... 必要な作業工程を洗い出し、夕食までの時間に間に合うように、それぞれの工程を行う時間を決めました。
調理道具と食材がまとめて購入できるスーパーを選定するなど、時間のロスを最小限にしてメンバー3人が無駄なく動ける導線を考えることで、なんとか夕食までの時間に完成できる目途が立ちました。


#### 調達マネジメント
調理経験値がない我々だけでは計画の遂行が困難を極めることが予想されます。
できればカレー有識者をメンバーに誘いたいところですが、あいにくスケジュールとタイミングの都合上かないませんでした。
料理道具も借りるという選択支もあったのですが、これも間に合わず今回は新規購入することにしました。
今回購入するものは調理道具一式と食材一式になりました。


#### 資源マネジメント
計画を遂行するための準備はまだまだ必要です。
スケジュール通りみんなが本当に動けるのかしっかり検討する必要があります。
それぞれが並列で動くので刻々と変化する状況に対して密に連絡を取りながら進める必要があります。
ちゃんと連絡が取れるようスマホを持ってもらい、買い出しで想定と違うことが起こったタイミングですぐに私に連絡をしてくれるよう伝えました。
また、料理経験値0なので、1人には野菜の切り方とか学習してもらう時間も設けることにしています。
そこの買い出しに行きたくないとごねているやつはまず精神の訓練からです。
カレー作りを成功させるためにはそれぞれの分担がカギとなること、加えてカレーのすばらしさを再び説いたらやる気が出たようです。


#### コミュニケーションマネジメント
連絡は問題が起きた時だけでは足りません。
買い出しが順調に推移しているのかリアルタイムでの状況把握が必要です。
状況にかかわらず定時連絡をすることに決めました。
新玉ねぎしかなかったからそれにした、みたいな些細なことが完成するカレーに大きな影響を与えます。


#### リスクマネジメント
このカレー作りは絶対に成功させたいです。
冷静さを取り戻した私は、不測の事態に備え様々な対応策を考えました。
もし、欲しい具材が売っていなかったら・・・
もし、調理に失敗してしまったら・・・
もし、・・・
買い出しのリストに代替食材もリストし、可能な限りリカバリ可能な選択肢を準備しました。


#### コストマネジメント
当初の要件の一つで、みんなで出せる金額の制限がありました。
私は最高のカレーを作るために費用は惜しまない思いだったのですが、1食の材料費に1000円以上出せないそうで諸々を加味した上限額を決めました。

そんな中困ったことが発生しました。
買い出し中に、具材が思いのほか1食分丁度で購入することができず、当初計画していた費用より多くかかってしまうことがわかりました。

しかし万全の準備をしていたので恐るるに足らずです。
調理道具買い出し係に連絡し、ダイソーの安い道具で揃えてもらうよう計画変更しました。


#### 品質マネジメント
各工程に抜かりはありません。
ついにカレーは完成間近です。
途中経過の味見もしっかりやっていきましょう。

・・・・

「なにこれ・・・？」
メンバーから発されたのは予想だにしない言葉でした。

「辛くて食べれない・・・・・」

　
　

カレーといえば辛さ。
勿論、食材係の私が用意したのはLEE辛さ20倍のルーと鷹の爪1袋。

どうやら”おいしい”という共通認識に齟齬があったようです。
客観的に見ると品質は最悪の状態です。

#### ステークホルダマネジメント

残念ながら今回のカレー作りは失敗してしまいました。
よくよく、今回のメンバー内のおいしいとは何かを定義してみると、
- 辛さこそ正義。サラサラのルーにパラパラの米。ルーを邪魔しない大粒の野菜。ルーと米は別盛り
- 適度なスパイスとドロドロのルー。いろんな具材てんこ盛り。米の上全体にルーをかける
- 常識的に考えて星の王子様が一般的なカレーに決まってるだろ

という様々な観点があることがわかりました・・・

振り返ってみると、作るカレーの方向性については殆どすり合わせをすることなく進めてしまったことに気づきました。
根本的なことですが、料理しないことが総じてか、料理の味付けにそれぞれの価値観があること自体に注意が向けられませんでした。
もし次の機会があれば、食材のリストなど必要な情報を細かく提供し、合意形成を得ながら進めていきたいです。

# さいごに

みんなの好みを聞く中で共通することとして、ほうれん草の夏野菜カレーみたいな野菜が多めに入っているカレーが好きだということがわかりました。
我々もこまめな報連相を大切にしていきましょう。

ステークホルダーとプロジェクトメンバーが一緒になってしまったので少々分かりづらいかも。

※この物語はフィクションです
csvファイルを読み込んでエンコードする（Julia編）

# はじめに
Juliaでcsvファイルで読み込んだファイルをエンコードする方法をまとめる。

# エンコードの方法
Juliaで文字コードをエンコードするには、`StringEncodings.jl`パッケージを使うみたいですが、csvファイルを読み込んで、その中身をエンコードする方法が見当たらなかったので、他の方法を試してみました。
Pythonで書くと以下の処理をJuliaで行いたいって感じです。
```python
import pandas as pd

df = pd.read_csv(file_path, encoding='shift-jis')  # UTF-8やcp932など
```

---

Juliaでは`CSV.jl`、`DataFrames.jl`、`StringEncodings.jl`を使用します。
まず、csvファイルを`open関数`を用いて読み取り、その後デコード（エンコードではない？）して、csvファイルをデータフレームとして出力するという流れになります。以下にコードを示します。
```julia
using CSV, DataFrames, StringEncodings

file = open(file_path, "r") do file
    read(file)
end

decode_file = decode(file, "Shift_JIS")

df = CSV.read(IOBuffer(decode_file), DataFrame)
```
もしくは、
```julia
file = open(file_path)

decode_file = decode(file, "Shift_JIS")

df = CSV.read(decode_file, DataFrame)
```

Doブロック構文やCSV.readの第一引数でIOBuffer関数を用いなくてもうまくいきますが、どちらでもいいんですかね…
どっちがいいとかあるのかな？
勉強します(;'∀')

# まとめ
Juliaの基礎から学んでいますが、やはり実践的なコード（主にデータサイエンス）も同時に書くことで経験を積むことができると思うので頑張ります！
Pythonのコードをそのまま？実行？することも可能？みたいなので、どんどんアウトプットしていこうと思います！
それでは！！！
Debian 12のデュアルブートインストールがうまくいかない方へ

# やろうとしたこと
Windows11インストール済みの端末にDebian12をインストール(デュアルブート)

# 構成
内蔵SSD:Windows11
外付けSSD:ここにDebianをインストール
USB:ここにISOを焼く

# 失敗時の症状
OS(Debian)を起動しても画面が真っ暗のまま動かなかった。

# 解決策
ISOを変えることで解決した。
* 失敗時のISO
debian-12.2.0-amd64-netinst.iso
https://www.debian.org/distrib/

* 成功時のISO
debian-12.2.0-amd64-DVD-1.iso
https://cdimage.debian.org/debian-cd/current/amd64/iso-dvd/
※ページ最下部の黄色でマークしたファイル
![1000001613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344302/0677e665-108a-2d79-45d5-de3f14c233be.png)

# 成功時の手順
1. 成功時のISOをインストール
2. RufusでUSBにISOを焼く
3. PCを再起動し、BIOS立ち上げ
4. ISOを焼いたUSBを優先起動先に選択し、BIOS設定を更新
5. Debianをセットアップ
https://qiita.com/Hietan/items/3f3867ffca1db341633e
※手順2以降は上記URLを参考にしています
LinuC Level2合格体験記

# はじめに
2023年12月、ついにLinuC Level2に合格したので合格体験記を書きます！


# 学習前の状況
#### 所有資格
応用情報
LinuC1
OSSDB Silver

# 使った教材
### 
- [Linux教科書 LinuCレベル2 Version 10.0対応(通称：小豆本)](https://amzn.asia/d/3rXnAUy)
- [Linux教科書 LinuCレベル2 スピードマスター問題集 Version 10.0対応](https://amzn.asia/d/gCZsNzW)
- [Ping-t](https://mondai.ping-t.com/)
- [学易](https://gakuyasu.byaku.jp/)

# やったこと
#### LinuC201
LinuC1に合格した3月から、その勢いのままLinuC201の勉強を始めました。
小豆本を通読→Ping-tをひたすら演習で無事、2か月ほどの勉強期間で合格できました。
業務がかなり厳しい時期だったのでコマンドを叩くなどもほとんどしないまま、ただひたすらに暗記を繰り返したと記憶しています。
内容としても、Level1で勉強したことを応用させていくものが多く、いつか業務で使うかもしれないな、と思いながら勉強出来たと思います。

#### LinuC202
##### 1回目
201合格後、すぐに勉強を始めたものの…業務その他に屈して完全に心が折れていたため、しばらく勉強していませんでした。再開したのは8月ごろ？
これまで同様、小豆本とPing-tのヘビーローテーションで10月に1度受験したものの無事撃沈。
##### 2回目
このあたりでモチベーションを保てなくなってきて先輩に相談した記憶。
> 私「もうモチベがないです。業務で使わないじゃないですかこんなん。そもそもサーバ触るときになんも調べないでいきなりコマンド打ち始めるやつやばすぎるでしょ。覚える必要あります？」
先輩「LinuC3まで持ってる人、うちの会社にほとんどいないからここ頑張れば評価されるよ！」

私は目立ちたがり屋なので、そういわれるとやる気が出ました。
追加の教材としてスピ問と学易を使い、Ping-tでの演習も重ねました。
12月、2度目の受験でようやく合格！


# 結果
#### LinuC201
スコア：546
仮想化とかやる気あんのか？というスコアですが、やはり業務で使っている部分のスコアが高くなって合格できたなという印象。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/9b144d13-d3d5-95a6-ac7c-ba2d9bebb94f.png)

#### LinuC202
##### 1回目
スコア：426
そりゃ落ちるよ、というスコア。特にシステムアーキテクチャの分野が66％なのはいただけない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/5ffb4995-1787-6112-33e2-e618a5ea4d0d.png)

##### 2回目
スコア：586
全体的に点数を伸ばし無事合格。Sambaを業務で触れたので一気に点数が伸びました。運がよかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/71861133-a3d2-777c-9ced-ec055d25c787.png)

# 感想
## やっぱりとにかく202がきつかった
正直二度とやりたくない。常に頭のどこかに「202勉強しなきゃ…合格しなきゃ…」と思っていたので相当ストレスでした。今日からは304合格しなきゃと思い続けます。
何をどこまで勉強すれば合格できるかもわからなくなっていたので、がむしゃらに問題演習するしかなかったと思うし、たぶん間違ってないと思います。
定量的に出せるところで言うと、Ping-tがこんな感じ。～201は18レベルくらいまでしか演習していないので、あきらかに202は勉強量がおかしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/a21b624a-8cd1-0d9d-d165-fe2fd0fdeb22.png)
Ping-t模擬演習で安定して9割取れるくらいまでになり（答え覚えてしまったのであまり意味はなかったかもしれない、でも本番で同じ問題が出ることを思うと合格するためという意味では答えの丸暗記にも価値があると思うなど云々）、参考書も2,3周したところでいい加減合格したい（そしてストレスから解放されたい）（あと報奨金欲しい）となって再受験に至りました。

本番ではスピ問、Ping-tで出た問題と全く同じ問題がそれなりに出たので即答できる問題も多く、2回目の受験の時は合格を確信して試験を終えました（とはいえPCの前でこぶしを握り締め、席から立つときに膝が震えていることに気が付きましたが）。

## モチベーションを保つのが大変
サーバを立てるコマンド覚える必要ないだろ！というのもそうですが、やはり業務で使わない単元が大半を占めるのがやはりきつかったです。上でも書きましたが、報奨金でもなんでもいいので人参ぶら下げてあげることが大切だと思いました。
諸事情で304まで取る必要があるので、少し休んでまた勉強していこうと思います。願わくばモチベーションが消えることのあらんことを。
社内のQ&Aフォーラムに寄せられて嬉しかったこと Part2

以前「[GitHub Discussionsで社内のQ&Aフォーラムを開設する](https://www.lifull.blog/entry/2022/02/24/100000)」でもご紹介した通り、LIFULLではGitHub Discussionsを使った社内向けのQ&Aフォーラムを有志で運営しています。

> このフォーラムは「あるシステムについて誰か詳しい人に相談したい」とか「設計についてチーム外にも相談したい」とか、エンジニアリングで困ったことをなんでも聞ける窓口になることを目指しています。最近ではアーキテクトチームや QA チームなどの公式の窓口としても利用でき、質問の内容に応じて適切な部署や人がアサインされる体制も整い始めました。

元々はQ&Aのみを想定していたのですが、予想していなかった嬉しい使われ方も行われています。今回はそれを紹介します。
（また、これを社内のエンジニアが見て、「こういう使い方をしてもいいんだ」と更に活性化することを期待しています！）

去年のアドベントカレンダーで、「[社内のQ&Aフォーラムに寄せられて嬉しかったこと](https://qiita.com/ninomiyt/items/09bd01d5cf9c907d5ea9)を書き、今年アップデートがあったことを書いていきます。

今年はこのフォーラムにおよそ200件程度の投稿がありました！ 昨年は300件くらい実はちょっとペース落ちてるかもしれません😱

## ChatGPT Retrieval Plugin（をベースとした社内AI）と連携した

keelaiという社内向けのAIアプリケーションが、このQ&Aフォーラムの内容を元に回答するように設定されました。

https://www.lifull.blog/entry/2023/11/16/170000

GitHubのAPIを叩いてDiscussionsやドキュメントのMarkdownを収集して、その内容を元に回答する機能があります。これは発足時はRetieval Pluginを社内のエンジニア向けに提供するプロジェクトでした。

次は、ソースとなったドキュメントのURL付きで質問に対して一次回答をする機能をつけてみたいです。


## 技術知見の共有の場になっている

去年に引き続き、Q&A以外に `Knowledge` というカテゴリを使って「皆に共有したい技術的な知見」を共有する方が現れました。

今日もちょうど「**良い自動テストを構成する4本の柱**」という記事が投稿されていました。

> 今回は以下について説明します
>
> * 良い自動テストを作るにはどうすれば良いのか？
> * 良い自動テストを構成する4つの柱

## 全体確認の場として使ってもらえている

特にレガシーシステムの廃止・改善時の調査に、本格的な調査の前に聞いてくれる人も多くなりました。この手の問題によくあることかもしれませんが、現在は詳しい人はいないようだということが分かるだけのことも多くありますが…。


## プルリクを何度か送ってもらえた

各部署への通知設定の改善についてプルリクや、ちょっとしたバグがあったときも、チーム外の方からすぐに修正のプルリクを送ってもらえました。

https://qiita.com/ninomiyt/items/7c835020c57d2b0d430e

こちらの記事でも別の文脈で書いた通り、効率の良い開発のためには、透明性のある意思決定やオープンな相談が重要だと思っています。このフォーラムが多少なりとも役立てていたら嬉しいです。

[昨年](https://qiita.com/ninomiyt/items/09bd01d5cf9c907d5ea9)は「提案や意見集約の場として使ってもらえている」と書いたのですが今年はそこまで目立ちませんでした。全く無いわけではなかったのですが、こうした動きはもう少しありえるんじゃないかと思ってます。

> 開発プロセスの中で「何かちょっとイケてないけど、どこに提案すればいいか分からない。誰に修正してもらえばいいか分からない」というモヤモヤがあることもあると思います。そうした提案もいくつか行なってもらえています。


## 今後の展望

ChatGPTが盛り上がって以降、とりあえずAIに聞いて解決する問題も増えてきたと思います。LIFULLでは気軽にSlackから呼び出せる環境も整備しているため、投稿が減った要因はこれが大きいんじゃないかなと思ってます。

ただ、オープンな議論や意見集約の場としての役割は今より果たせる可能性があると思います。もしLIFULL社員が読んでいたら、その可能性を一緒に探っていって頂けると嬉しいです。
Salesforce活用で意識している考え方

[Hubble Advent Calendar 2023](https://qiita.com/advent-calendar/2023/hubble)の8日目[^1]の記事です🎄
[@kareem](https://qiita.com/kareem/items/5cfec65f54423813c5fe) さんからのバトンです！

# はじめに

こんにちは、健康診断で2年連続1kg増えている[Shogo](https://twitter.com/shogo_embokoir)です。[^2] 久々のQiitaです。
2023年から現在のポジションでデータドリブンな事業開発に取り組んでいます。

- [BAO（Business Analytics & Operations）を立ち上げました！](https://note.hubble-docs.com/n/n2eecd1fcf74e)
- [BAO 立上げ半年の振返り](https://scrapbox.io/shogo/BAO_%E7%AB%8B%E4%B8%8A%E3%81%92%E5%8D%8A%E5%B9%B4%E3%81%AE%E6%8C%AF%E8%BF%94%E3%82%8A)

Hubbleでは普段いわゆるビジネスサイドの仕事に従事しており開発はやっていない身ですが、ちょっとしたきっかけから開発チームのアドベントカレンダーに参加する機会をもらいました。
今回は私が日々使っている[Salesforce](https://www.salesforce.com/jp/)というサービスを題材に、ビジネスとエンジニアリング双方の観点が関わる話をしてみたいと思います！

# RDBとしてのSalesforce

Salesforceは世界的に著名なCRM・SFAです。詳しい説明は割愛しますが、システムはRDBとしての性質を持ちます。[^3]
Salesforceでいう「オブジェクト」はRDBでいうところの「テーブル」、「項目」は「カラム」、「レポート」は「クエリ」などとそれぞれ解釈でき、その拡張性が大きな特長の一つとなっています。

# ビジネスにおける構造化データ

さて、ビジネスに関するデータも構造化ができます。たとえば「取引先の情報」と「商談で取り交わされたやり取りの情報」は性質が異なるためテーブルとして区別しつつ、取引先のIDをキーとしてリレーションを持たせる、といったイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181283/5dd88247-640e-5574-1592-f38bf8d883b8.png)
（[「Salesforce サクセスナビ」](https://successjp.salesforce.com/article/NAI-000708)より）

それらのデータは構造化されることでより有用性が高まるため、Salesforceのようなシステムを使用する意義があります。仮に取引先との商談の情報がすべてフリーテキストで「メモ」として残っていたら数値化や分析がしづらいですし、情報の共有にも時間がかかってしまいます。[^4]
（ただし別の議論として、GPTといったLLMなどの技術革新も相俟って非構造化データであっても劇的に活用が進む方向もあり、こちらも非常に興味深い。）


# 複眼的に取り組むべき領域

SalesforceがRDBとしての性質を持つことから、データベース設計の上では開発者的なバックグラウンドを活かすことができます。（といってもSQLの基礎的な知識があればOK）

- どういった性質の情報をどのオブジェクトに持たせるか
- 新しいオブジェクトを作る上でリレーションをどうするか

など、適切にオブジェクト・項目構成を設計できれば、分析や可視化におけるスループット・アウトプットを高められます。

そして当然、ビジネス上の要請を実現して初めて「活用」が叶う分野でもあります。
自社の事業や営業活動の特質を理解しつつ、どのような分析や可視化が効果的なのかを見定め、各部門と対話を重ねて日常のオペレーションに落とし込み、入力を励行するといった活動がなければ成り立ちません。多面的な楽しさがある領域だと感じます。

# Hubbleでも絶賛活用中

Hubbleの事業開発でも「データをビジネスの武器に」という趣旨からSalesforceの活用を促進し、着実に環境は良くなってきました。一つずつ挙げれば枚挙に暇がありませんが、たとえば以下などは特に成果に直結しています。

- 商談オブジェクトの項目を工夫して、ファネル&コホート分析を可能に。ボトルネックの特定や受注金額予測に活用
- MRR管理の基盤となるカスタムオブジェクトを構築。営業・CS・経理・ファイナンスなど多部署が同じデータを参照できるように
- 自社プロダクトのデータベースと結合するためのキーを保持する運用に。データソースとしてTableau Prepに接続し、分析軸がさらに豊富に
    - Tableauについては（筆が進めば）またどこかで詳しく書けたらと思います

引き続き取り組み事業に寄与していきます！
明日は [@imarm](https://qiita.com/imarm) さんです！🎅

[^1]: 平日のみの投稿なので12日ですが8日目の記事としています。
[^2]: 身長は変わっていません。
[^3]: 参照：[Integrate.io「Salesforceのデータベースについて」](https://www.integrate.io/jp/blog/the-salesforce-database-explained-ja/)
[^4]: 特に一つの案件にさまざまなチームの人間が関わる[THE MODEL体制を敷いている](https://note.hubble-docs.com/n/nee4cc39d5615)当社にとっては死活問題です。
electronのCD

# はじめに
この記事は2023年度の振り返りです。

前回electronの自動更新機能を設けたので、Code Deployを設置した備忘録です

# CD(Code Deploy)
会社ではgitlabを利用してるので、gitlab-runnerを利用した内容になります

```sh:一部抜粋
build_job:
  stage: build
  image: electronuserland/builder:18-wine
  rules:
    - if: $CI_COMMIT_TAG
  before_script:
    - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    - unzip awscliv2.zip
    - ./aws/install -i /usr/local/aws-cli -b /usr/local/bin
    - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
    - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
    - aws --version
  script:
    - sed "s/0.0.0/${CI_COMMIT_TAG}/g" package.json > _package.json && mv _package.json package.json
    - cat package.json
    - npm run build:win:publish
```
before_scriptでaws CLIをインストール
scriptで、package.jsonのバージョンを書き換えて、buildすることで自動でS3にアップロードするようにしています

# さいごに
これでCI・CDができたので、gitにプッシュするだけで自動で最新バージョンがリリースされ、各自で最新バージョンを取得するという運用フローができたので、大変楽になりました。
electron-updaterを使って自動アップデートに対応

# はじめに
この記事は2023年度の振り返りです。

# 問題点
アプリを作成しては、都度都度配布していたのですが、リリースの都度行うのが面倒だったため、electron-updaterを利用して自動更新機能を設けることにしました

# 解決策
electron-updaterにつきましては、過去にzennで記事を記入してますので、こちらをご参照ください。

https://zenn.dev/youfuku/articles/b816a9cd521c33

# さいごに
electronアプリの自動更新記事をすることで、配布はぐっと楽になりました。
ただ、アプリ生成部分が手動だったので、そこも改善しようかと思います。
S3互換のminIOで実験

# はじめに
この記事は2023年度の振り返りです。

electronのリリースを検討したときの調査内容です。

# 問題
electronの自動更新機能として「electron-updater」というものがあります。
指定の場所に保存されたものを起動時に確認し、自分より新しいものがある場合は更新フェーズを起動するというものです。
更新ファイルの保存場所として、githubやs3が指定可能ですが、社内のみで利用することを想定した場合、どちらも利用しづらい状況でした
(社内案件でgithubの利用は禁止なので)

# 解決策
社内にs3互換のファイルサーバーを建てる方向で検討。

# minIOを構築

```sh:compose.yml
services:
  minio:
    image: minio/minio:RELEASE.2023-09-07T02-05-02Z
    container_name: minio
    ports:
      - "9001:9000"
      - "9002:9001"
    environment:
      - MINIO_ROOT_USER=minio
      - MINIO_ROOT_PASSWORD=minio123
    entrypoint: sh
    command: -c "/opt/bin/minio server /export --address :9000 --console-address :9001"
    volumes:
      - ./data:/export
    restart: always
```
```sh:コマンド
docker compose up -d
```

![image10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/6d672e76-e481-639c-5414-526244e6a303.png)
ユーザー名は、「minio」
パスワードは、「minio123」

# minIOの準備
![image11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/d3db35be-bc2f-979e-b8c1-fd06c637cee8.png)
左メニューの「Access Keys」を選び「Create access key」を押す
![image12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/2ecd5cb2-c777-c84d-a8de-5fb99e42c947.png)
「Create」ボタンを押す

ここで発行される「Access Key」「Secret Key」は後々利用しますので、大事に記憶しといてください

# AWS CLIから利用テスト
以下のコマンドでプロファイルを登録
```
aws configure --profile minio
```
登録したプロファイルを利用することで、以下のAWSコマンドで確認することができました！
```
aws --profile minio --endpoint-url http://hogehoge:9001 s3 ls
```


# さいごに
次回は、これを利用した自動更新を組み込んだ記事になると思います。
ローカルのS3があるだけでも、利用色々利用価値があるように思いますので、今後も利用していきたいと思っています。
wsl(ubuntu)にasdfを導入

# はじめに
この記事は2023年度の振り返りです。

zennでも書きましたが、最近asdfを利用するようになりましたので、それについての備忘録です

# インストール方法
https://zenn.dev/youfuku/articles/a8177d420db979

# AWS CLI インストール
インストール
```
sudo apt-get install -y zip
asdf plugin add awscli
asdf install awscli 2.14.4
asdf global awscli  2.14.4
```
確認
```
$ aws --version
aws-cli/2.14.4 Python/3.11.6 Linux/5.15.133.1-microsoft-standard-WSL2 exe/x86_64.ubuntu.22 prompt/off
```
# AWS SAM CLI インストール
先にpythonが必要だったため、最新をインストール
```
asdf plugin add python
asdf install python 3.12.0
asdf global python  3.12.0
```

```
asdf plugin add aws-sam-cli
asdf install aws-sam-cli 1.103.0
asdf global aws-sam-cli 1.103.0
```

```
$ sam --version
SAM CLI, version 1.103.0
```

# さいごに
rubyインストールで色々模索してasdfに行きつきましたが、aws cliまで対応してるとは驚きでした。
dockerも対応してくれると嬉しいのですけどね・・・
二次元コード・QRコードをExcelまたはスプレッドシートで作成

## 方法
合同会社ハトライズ様のAPIで作成できます

https://excelapi.org/docs/other/qrcode/

## サンプル
https://docs.google.com/spreadsheets/d/1_jyjryDYWk3xTuPqov7LGJWnfRcWheKosBDX8-87OQs/edit?usp=sharing


※QRコードは(株)デンソーウェーブの登録商標です
「画像のwidth, heightに小数点っていいんだっけ」を細かく理解する



こんにちは！[Ateam LifeDesign Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ateam-life-design) 15日目を担当します、加能です。
フロントエンド実務2年目、絶賛勉強中です :pray:

## これは何

今回は、
**「画像のwidth, heightに小数点って、HTML・CSSの仕様上使っていいの？」**
についてお話しします。（2023年12月現在の情報です）


## ✍️結論

- **HTML：imgタグのwidth, height属性では、小数点NG❌です！**
    - 例えば`<img src="path" width="30" height="40">`としなければいけない
    - 単位のない整数である必要があります
- **CSS：width, heightでは、小数点OK⭕️です！**
    - 例えば`<img src="path"　style="width: 30.3px">`はOK
    - ただしブラウザ間の細かい数値の違いに注意です

ざっとこんな感じですが、順番にお話ししていこうと思います。

## ①imgタグのwidth, height属性では小数点NG🙅‍♀️

[imgタグに関するMDNのページ](https://developer.mozilla.org/ja/docs/Web/HTML/Element/img)では、widthも、heightも、

> ピクセル値で指定します。単位のない整数でなければなりません。

と記載されています。
なので **imgタグのwidth, height属性は単位のない整数でなければいけません**。

昔、HTML5の頃はパーセントでの指定も許容されていたようですが、
今では整数値（px値）のみです。

## ②CSSでのwidth, heightは小数点OK🙆‍♀️

[CSSのwidthに関するMDNのページ](https://developer.mozilla.org/ja/docs/Web/CSS/width)では、

> `<length>` 絶対的な値で幅を定義します。

と記載されています。
`<length>`？と思い、[`<length>`のページ](https://developer.mozilla.org/ja/docs/Web/CSS/length)を見てみると、

>`<length>` データ型は一つの `<number>` とそれに続く以下に挙げる単位の一つから成ります。

さらに`<number>`……？となるので、
[`<number>`のページ](https://developer.mozilla.org/ja/docs/Web/CSS/number)を見てみると……

> CSS の `<number>` データ型は、整数または小数部分のある数値を表します。

なので、
CSSのwidthは、整数または小数部分のある数値と、それに続く単位の1つから成り立つ、絶対的な値であるということです。（長い！）

つまり、**CSSのwidth, heightでは、厳密なルールで言うと小数点で問題ありません[^1]**。 
（そういえば、実際remやemなどの相対的に変わるものは小数点になることもありますね）

[^1]:細かく言うと、この仕様はimgタグに限った話ではなくいろんなタグでも同様です。

### 注意点⚠️

CSSでwidth, heightを指定するのは一見良さそうに見えますが、
**ブラウザごとに数値が微妙に違う結果になる** のでお気をつけください。

例えば、Googleの画像を小数点第1位まで指定してみます。

Chromeでは、小数点第1位で計算後の数値がずれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250162/4fb98b78-1438-9d11-331e-fb523292f455.png)


Firefoxは、小数点第1位までの指定では大丈夫ですが、第2位以降から計算後の数値がずれ始めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250162/c9b40fd5-202e-c880-1984-ead9a4edce1f.png)



小数点第何位とかの細かい世界の話ではありますが、
ブラウザ間の挙動を揃える上でも、画像はなるべく整数値がいいかもしれないですね。


## おわりに

**どうしても画像サイズで小数点を使う場合は、CSSで書きましょう。**
私はwidthの読み方はウィズ、heightはハイトと呼んでます。（諸説ありそうですね）

Ateam LifeDesign Advent Calendar 2023では、
その他にもたくさんの記事を投稿しています。ぜひ読んでみてください！　ではまた:wave_tone1:

https://qiita.com/advent-calendar/2023/ateam-life-design

## 参考

https://developer.mozilla.org/ja/docs/Web/HTML/Element/img

https://developer.mozilla.org/ja/docs/Web/CSS/width

https://developer.mozilla.org/ja/docs/Web/CSS/height

https://developer.mozilla.org/ja/docs/Web/CSS/length

https://developer.mozilla.org/ja/docs/Web/CSS/number
AtCoder Beginner Contest 332 B Glass and Mug を Elixir と C で解いてみた

AtCoder Beginner Contest 332 B Glass and Mug を Elixir と C で解いてみたので，ご報告します．

## アルゴリズムの解説

アルゴリズムはごく単純で，問題に書かれている通りに組んだだけです．

Cの場合にはループにしたのですが，1点，注意点があって，グラスとマグの更新の順番に気をつける必要があります．まずい更新の順序だと，正しい結果を得られなくなります．

Elixirの場合には，素直に再帰で解きました．Elixir向きの問題だと思います．

## Cでの解答

https://atcoder.jp/contests/abc332/submissions/48427429

```c
#include <stdio.h>

int main()
{
  int k, g, m;
  int d1 = scanf("%d", &k);
  int d2 = scanf("%d", &g);
  int d3 = scanf("%d", &m);
  
  int p = 0, q = 0;
  for(int i = 0; i < k; i++) {
    if (p == g) {
      p = 0;
    } else if (q == 0) {
      q = m;
    } else if (g - p >= q) {
      p += q;
      q = 0;
    } else {
      q -= (g - p);
      p = g;
    }
  }
  printf("%d %d\n", p, q);
}
```

## Elixirでの解答

https://atcoder.jp/contests/abc332/submissions/48427107

```elixir
defmodule Main do
  def main() do
    [k, g, m] =
      IO.read(:line)
      |> String.trim()
      |> String.split(" ")
      |> Enum.map(&String.to_integer/1)
    
    solve({k, g, m}, {0, 0})
    |> Enum.join(" ")
    |> IO.puts()
  end
  
  def solve({0, _, _}, {p, q}), do: [p, q]
  
  def solve({k, g, m}, {g, q}) do
    solve({k - 1, g, m}, {0, q})
  end
  
  def solve({k, g, m}, {p, 0}) do
    solve({k - 1, g, m}, {p, m})
  end
  
  def solve({k, g, m}, {p, q}) when g - p >= q do
    solve({k - 1, g, m}, {p + q, 0})
  end
  
  def solve({k, g, m}, {p, q}) do
    solve({k - 1, g, m}, {g, q - (g - p)})
  end
end    
```
LINE通知メッセージの導入のメソッド

# はじめに
皆さまはじめまして。

今年新卒でミロゴス株式会社に入社した四釜と申します。

入社後はセールスに配属、その後9月から納品チームに異動し、プロジェクトの進行〜納品までの管理に従事しています。

本記事では納品チームに所属していくつかLINE通知メッセージの進行に携わった経験から、

LINE通知メッセージの導入に向けた注意点やフローについて簡単に説明させていただきます。

# LINE通知メッセージとは？
LINE通知メッセージとは、ユーザーの電話番号を指定してLINEのメッセージを送信できるサービスです。

LINE公式アカウントからユーザーへメッセージを送る際、基本的にユーザーがそのLINE公式アカウントを友だち追加している必要がありますが、
通知メッセージを利用することで、当該の公式アカウントを友だち追加していないユーザーに対してもメッセージを送信できます。

更に詳細を知りたい方は以下のLINE社公式の記事をご参照ください。

https://guide.line.me/ja/services/notification-message.html

https://developers.line.biz/ja/docs/partner-docs/line-notification-messages/overview/

# LINE通知メッセージの利用にあたり注意すること
LINE通知メッセージは友だち追加していないユーザーに対してもメッセージが送信できるため、使い方では友だち数を爆発的に伸ばすことも可能です。

しかし利用用途には以下のような制限が設けられており、利用前にLINE社による審査への通過が必須になります。

前提として、LINE通知メッセージの利用用途は、LINE社がユーザーにとって利便性が高いもの（予約完了通知・購入完了通知など）に限定されていて、営利目的や広告目的の利用は不可能です。

また、配信の利用用途やメッセージ内容、フォーマットはLINE社指定のUXガイドラインに照らし合わせて作成する必要があり、
相違がある状態で審査に出すと差し戻しが発生する可能性があります。

また、もし審査通過後にメッセージの内容を変更する場合は変更箇所について再度審査が発生いたします。
そのためメッセージの内容（利用用途・配信項目）がしっかりと決まっている状態で審査に出すことを推奨いたします。

詳細についてはLINE社が提供している「LINE通知メッセージUXガイドライン」をご参照ください。
[LINE通知メッセージUXガイドライン](https://www.lycbiz.com/sites/default/files/media/jp/download/LINE%E9%80%9A%E7%9F%A5%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8UX%E3%82%AC%E3%82%A4%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3.pdf)

# LINE通知メッセージ導入までのフロー
LINE通知メッセージ導入までのフローを簡単にご紹介いたします。

### 1.LINE公式アカウント（認証アカウント）の取得
LINE通知メッセージは認証アカウントでのみ利用できます。
そのため、未認証の場合は認証アカウント※の取得又は申請をする必要があります。
※認証アカウントについての詳細は以下のLINE社記事をご参照ください。

https://www.lycbiz.com/jp/service/line-official-account/verified-account/

### 2.メッセージデザイン作成
UXガイドラインと照らし合わせながらメッセージ内容を決定します。
（例：利用用途・配信項目・メッセージ内の文言等）

### 3.UX審査
LINE社認定のパートナー企業（[LINE Biz Partner](https://www.linebiz.com/jp/partner/)）を経由して、LINE社に審査の申請を行います。
通常10営業日前後で結果が判明し、LINE社から通過可否の連絡が来ます。

### 4.テストアカウントへの通知メッセージ権限付与
テストアカウントにてテスト配信を実施する場合、別途テストアカウントへの通知メッセージAPI権限付与が必要になります。

### 5.配信ツールの設定
通知メッセージを配信するツールで設定を行います。

### 6.テスト配信
テスト配信を受信する方が、LINEアプリの設定上で「受信設定」が拒否になっていないか確認します。
拒否になっている場合、メッセージが届かない可能性があります。

### 7.本番アカウントで配信開始

# まとめ
LINE通知メッセージについて説明させていただきました。

私自身、LINE通知メッセージの納品経験を通してクライアント様の理想とLINE社の掲げる制限の両方を調整しながらプロジェクトを進行する難しさを実感いたしました。
進行が難しい一方、世の中に広く浸透しているサービスの構築に携われることにやりがいがあるため、
今後更にLINE通知メッセージの納品経験を積んでいきたいと考えております。

最後まで読んでくださりありがとうございました。
それではまた。
デザイナーのための言語化力の鍛え方

## 自己紹介
株式会社エイチームウェルネスのデザイナー / マネージャーです。
現在自社アプリのUIデザインを担当しております。

## こんな経験、ない？

- デザインの説明をしたけど、相手にしっかり伝えきれなくてもどかしい思いをした。
- 自分なりにデザインセオリーに則って正しいものを作って提案したはずなのに、受け入れて貰えなかった。
- A案B案を比較した時、圧倒的にA案が良いのだけどその良さを上手く伝えられずB案に決まってしまった。

これらはデザイナーなら誰しもが一度は経験があるのではないかと思います。
デザイナーはビジュアルを用いて情報を伝えることは得意ですが、
**言語での説明が苦手**な方が多い印象を持ちます。
今回は上記のようなことで悩んでいるデザイナーに向けて、言語化力の鍛え方をお伝えします。

言語化力を鍛えるのに一番手っとり早いのは、
**「自分でデザインを売る経験を積む」** です。
受注が決まってから作る経験ではなく、勝つためのデザインを行うという経験です。

なぜデザインを売る経験を積むことで言語化力が鍛えられるのか？
それは、コンペで勝ったり、クライアントに気に入ってもらう為の戦略として、デザインの言語化が必須になってくるからです。

とはいえ…フリーランスや営業会社でない限り、制作会社でも事業会社でも基本はある程度分業なので、自分のデザインを自分で売るという経験は積みにくいのが現状です。
しかし、今から紹介するトレーニングを日々の業務や日常生活の中に取り入れることで、
言語化力を鍛えて伸ばすことが可能になります。

## STEP1. まずは、状況説明をしてみる。
何でも良いので適当な素材（情報要素が多めの広告クリエイティブ推奨）を準備し、
Googleドキュメントなどに貼り付けておきます。
そして、何かしらの理由でその素材を見ることができない相手がいると仮定します。
その相手に対して、どんな広告クリエイティブなのかを相手がイメージできるよう、言葉で伝える練習をします。

例）
- 背景はxとxのグラデーションで、下の方がx色で上の方がx色。
- メインコピーは「xxx」というテキストで中央より少し上に配置されている。
- 中央にxxxに似ているキャラクターが配置されている。色はx色。x頭身くらいのサイズ。
- 注釈文が◯色で右下に「xxx」と書かれている。

最初はこのくらいの粒度でOKです。
各要素のサイズ感や位置関係をなるべく相手がイメージしやすいように言語化していきます。
これを毎日なるべく数をこなしていきます。

実はたったこれだけでも最初はスムーズに説明できないことも多いです。
この段階では声に出してアウトプットするだけでも良いですが、次のステップからはテキストで残しておけると後で見返した時に自分の成長が目に見えてわかるので面白いと思います。
このトレーニングをしておくと、業務でデザイン要素の特徴や位置関係を説明する時にスムーズに言葉が出てきやすくなります。

また、このトレーニングは手元にPCがなくてもいつでもできるのが良いところです。
通勤時に目にする電車内の広告・繁華街のデジタルサイネージ・スマホのターゲティング広告等、身近に使える素材が溢れていますので、隙間時間を活用してチャレンジしてみましょう。

## STEP2. 仮説を言語化してみる。

次に、Step1で使用したクリエイティブを使い、1つひとつの要素に対してなぜこのフォントなのか、なぜこのサイズなのか、なぜこの色なのか、なぜこの位置なのか…というのを考えていきます。
そうすると、「きっとこういう理由だからこうしたんだろう」という理由が頭に浮かんでくると思います。
これはデザイナーなら割と日常的にやっていることであり、それを言語化しないままテクニックとして意識的に取り入れたりしているはずです。

しかし、ここで一旦しっかりと**言語化するというプロセスを挟む**ことで、クリエイティブを研究する際ビジュアルとして見せるテクニックの習得だけでなく、ビジュアルを言語化して説明する力も一緒に付けることが可能になります。
そうすることで、自分が作ったクリエイティブやデザインの説明を求められた際に、しっかりと言語で伝えることができるようになっていきます。

慣れてくると、デザインカンプ等を作る際に「この部分はどうやって説明しようかな？」と頭の中でビジュアルを言語にトランスレートしながら手を動かせるようになってきますので、グラフィックやUIに対してツッコミが入った際にある程度納得感を与えられる打ち返しができるようになります。

## STEP3. 実務で実践してみる。

目に見えるものをある程度言語化できるようになってきたら、早速実務で実践してみましょう。
いきなりプレゼンの場に出て試してみる…というのも良いですが、まずは身近な人を頼りましょう。

デザイン業務ではレビュー体制を設けているチームも多いはずです。
普段デザインレビューは作ったものを先輩や上司に見てもらってフィードバックをしてもらうという流れが一般的かと思いますが、ただカンプのURLを投げてフィードバックを貰うだけで終わっていないでしょうか？
それではもったいなさすぎます。レビューの時間の使い方や工夫１つで言語化能力をより鍛えることができます。

レビューをしてもらう際、最初に必ず自分で説明をすることを徹底して下さい。
仮に前提情報がわかっている相手だったとしても、時間の許す限り言語化のトレーニングに付き合って欲しいという話を事前に通しておくとスムーズです。
そして、今回このアウトプットに至った経緯やデザインの意図を説明してみて下さい。
勘の働く相手ならば、更にいろいろ突っ込んで質問をしてくれるはずですので、それに対して自分なりに頑張って言語化してみて下さい。

デザイナー相手への説明に慣れてきたら、次は他の職能のメンバー相手にもチャレンジしてみて下さい。特にデザインにおける知識や経験が少ないノンデザイナー相手では、より具体的且つ詳細な説明が求められますので難易度は非常に高いです。
時には百戦錬磨のプロでもなかなか言語化できないようなことまで突っ込まれることもあるので、そういう場合はどう振る舞うと相手に不快な思いをさせずにことを前に進められるかといったことも学ぶことができます。
とにかく**職場では言語化する機会を積極的に設ける**、ということを徹底して行ってみて下さい。

以上がデザイナーが言語化力を鍛えるための3ステップです。
文中でもトレーニングと称していますが、やはり筋トレと一緒で継続して鍛えることで力が付いていきます。日々の業務の中に強制的に仕組みとして組み込み、ぜひ継続してみて下さい。

## さいごに。

ただ、デザイナーが一生懸命頑張ったところで、**言語だけでは伝えられない部分も多く存在する**のがデザインの難しいところでもあります。
特に職能の異なるメンバーでチームを組んで業務を進める上では、デザイナーだけに言語化能力を求めるのではなく、ノンデザイナーも目を養い、クリエイティブの良し悪しくらいは判断できるくらいの審美眼を持つことが重要だと考えています。
その為にも、デザイナーが言語という「共通言語」を使って説明し続けることは、チームのデザインに対する理解の促進につながるのではないかと思っています。
Linux備忘録

# Linux備忘録01　2022/11/07~
## ディレクトリ、ファイル操作の基本
### ディレクトリの記号 2022/11/08

|  記号  |  説明  |
| ---- | ---- |
|  .  |  カレントディレクトリ  |
|  ..  |  一つ上の階層  |
|　/　|ルートディレクトリ|
|~|ホームディレクトリ|
|-|一つ前にいたディレクトリ|

### パス(path)
パス(path)とは、ファイルまでの道のりを表すもの。

#### 絶対パス
ルートディレクトリを起点として、ファイルのある場所を表したパスのこと。
例: user/local/lib

#### 相対パス
カレントディレクトリを起点としてファイルのある場所を表したパスのこと。

#### パスを通す
全てのLinuxコマンドの実態は実行ファイルである。その実行ファイルは/binや /usr/bin、/usr/local/binなどのディレクトリに置くことになっている。

例えば、catコマンドのフルパスは/bin/catであり、このフルパスとcatのみをコマンドとして実行することは同じである。

しかし、このときシェルがそれらの実行ファイルがどのディレクトリにあるのかを把握していないとコマンド名のみで実行することができない。
例:<コマンド名>: command not found というエラーが出る。

あらかじめ、ファイルのある場所までの道のり(パス)をシェルに






## ディレクトリ・ファイルの移動と複製

### mvコマンド
`mv`はディレクトリやファイルを別のディレクトリへ移動したり、ディレクトリ名やファイル名を変更する際に使用するコマンドである。
#### 使い方
```
$ mv [オプション] [移動させたいディレクトリ(またはファイル名)名] [移動先のディレクトリ名]
```
### 主なオプション
| オプション   |  説明  |
| ---- | ---- |
|  -f  |  移動先に同名のファイルがある場合、強制的に上書きされる  |
|  -i  |  移動先に同名のファイルがある場合、確認メッセージが表示される  |
|  -b  |  移動により上書きされるファイルのバックアップを作成する  |
|  -n  |  移動先に同名のディレクトリがある場合は、処理を実行しない。  |
|  -v  |  移動処理を行う際の詳細情報を表示する  |

`mv`コマンドはディレクトリやファイルの中身は変更せず、名前だけを変更することもできる。その際、新しく指定するディレクトリ名は、そのディレクトリに存在しない名前でなければならない。既存の名前を指定してしまうと、そのディレクトリやファイルが対象ディレクトリファイルの内容で上書きされてしまうので注意が必要。

ファイルを任意のディレクトリに移動する場合には、移動先のディレクトリ名に`/.`をつけることで、より安全に作業を行える。もし、`/.`をつけずにmvコマンドを指示し、移動先ディレクトリ名が存在しない場合、hoge.txtはhogehogeというファイル名にリネームされるという挙動をとる。
```bash
#hoge.txtをhogehogeディレクトリに移動
$ mv hoge.txt hogehoge/.
```



## sudoコマンド
r
## suコマンド
一般ユーザーではアクセス権がなく、rootユーザーとしてコマンドを実行しなければ行けないとき、suコマンド、もしくはsudoコマンドを使用して一時的にrootユーザー権限を使用することができます。
【SwiftUI】Widgetで表示しているViewか判定する

# はじめに
メインアプリとウィジェットアプリで共通のViewを使用している時に、メインアプリで表示しているのかウィジェットで表示しているのかをView側で知りたいといった場面がありました。

公式からそのような機能は提供されてなく、どうにか実現できないかと考えた結果今回の方法に辿り着いたので記事にしておきます。

# 実装
```swift
import SwiftUI

struct IsWidgetEnvironmentKey: EnvironmentKey {
    static var defaultValue: Bool {
        Bundle.main.bundlePath.hasSuffix("appex")
    }
}

extension EnvironmentValues {
    var isWidget: Bool {
        get { self[IsWidgetEnvironmentKey.self] }
        set { self[IsWidgetEnvironmentKey.self] = newValue }
    }
}
```

# 使い方
```swift
import SwiftUI

struct ContentView: View {
    @Environment(\.isWidget) private var isWidget

    var body: some View {
        if isWidget {
            Text("ウィジェットです")
        } else {
            Text("メインアプリです")
        }
    }
}
```

# 解説
`Bundle.main.bundlePath`で判定しています。
メインアプリは`ターゲット名` + `.app`なのに対して、
ウィジェットは`ターゲット名` + `.appex`になっています。

これを利用して、ウィジェット判定を行うことにしました。

末尾の文字を`hasSuffix`を用いて調べます。

https://developer.apple.com/documentation/swift/string/hassuffix(_:)

# おわり
この方法は公式が提案している方法ではないので、通知なく変更が入る可能性があります。
Lua でモンキーパッチ

以下のような Redis にアクセスする Lua のプログラムがあります。このプログラムの動作をテストしたいです。

```lua
local function main()
  local redis = require('redis')

  -- Redis に接続
  local client = redis.connect('redis://localhost:6379/0')

  -- 値を set する
  client:set('test_key', 'test_value')

  -- 値を get する
  local result = client:get('test_key')

  return result
end
return main
```

Redis が起動していない開発環境で、以下のようなテスト用のプログラム（`test1.lua`）で上の関数を呼び出してみます。

```lua
local function test()
  local main = require('main')
  print(main())
end
test()
```

実行してみると、以下のようなエラーが発生しました。

（`redis.connect` 関数で Redis に接続できずにエラーになったようです。）

```sh
$ lua test1.lua
lua: /usr/local/share/lua/5.3/redis.lua:764: could not connect to localhost:6379 [closed]
stack traceback:
        [C]: in function 'error'
        /usr/local/share/lua/5.3/redis.lua:802: in function 'redis.error'
        /usr/local/share/lua/5.3/redis.lua:764: in function </usr/local/share/lua/5.3/redis.lua:760>
        (...tail calls...)
        /usr/local/share/lua/5.3/redis.lua:836: in function 'redis.connect'
        ./main.lua:4: in function 'main'
        test1.lua:3: in local 'test'
        test1.lua:5: in main chunk
        [C]: in ?
```



このプログラムを以下のように変更しました。

```lua
local function test()
  local redis = require('redis')

  -- redis.connect 関数をオーバーライドして、Redis に接続しないように変更
  redis.connect = function()
    return {
      -- set したときの動作を定義
      set = function(self, key, value)
        print(string.format('[debug] set called (key: %s, value: %s)', key, value))
      end,

      -- get したときの動作を定義
      get = function(self, key)
        print(string.format('[debug] get called (key: %s)', key))
        return 'injected value'
      end,
    }
  end

  local main = require('main')
  print(main())
end
test()
```

このプログラムは Redis を立ち上げなくても動作しました。

```sh
$ lua test2.lua
[debug] set called (key: test_key, value: test_value)
[debug] get called (key: test_key)
injected value
```

このような方法は Redis が利用できない環境でテストするときなどに便利そうです。

（モンキーパッチは予期せぬ副作用やバグを引き起こす可能性があるため、このようなコードは本番環境では使用しないほうがよさそうです。）
知っていると良い実装ができるかもしれない小ネタ集

## `list-style-type:none`が当たっている時の注意点
`list-style-type:none`を利用するとアクセシビリティツリー状でリストとして認識されなくなります。

https://developer.mozilla.org/ja/docs/Web/CSS/list-style#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B7%E3%83%93%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AE%E8%80%83%E6%85%AE

リセットCSSを利用している場合、リストのデフォルトスタイルがキャンセルされていることが多いと思います。

:::note info
アクセシビリティを意識する場合は`role="list"`を付与してください！
:::

## JSXの中で文字列を展開するときは…
ブラウザのdevツールで確認した際の見え方まで意識できていませんでした…

:::note warn
表示が変わるわけではないのですが、不要なものがレンダリングされてしまうのは不本意ですよね…
:::

実際のコードで書くと下記の通りです！
```diff_typescript
- ※{number}
+ {`※${number}`}
```

少し冗長的に感じるかもしれませんが、綺麗な方がいいですよね！
詳細は下記の記事に書いてありますのでよろしければご覧ください！

https://qiita.com/xrxoxcxox/items/530109609e5f53f77661

## ORは最初の真値を返す
1つ目は「1」、2つ目は2番目の「1」、3番目は1番目の「2」が返る。

```javascript
alert( 1 || 0 ); // 1
alert( null || 1 ); // 1
alert( 2 || null || 1 ); // 2
```

https://ja.javascript.info/logical-operators


## インクリメント/デクリメントの記述位置によって反映のタイミングが違う

設置位置が違うだけで数値の増減のタイミングが違います。

```javascript:前置呼び出し
let counter = 1;
let a = ++counter;

alert(a); // 2
```

`++counter`はcounterを増加させ、2という新しい値を返します。

```diff_javascript:後置式
let counter = 1;
- let a = ++counter;
+ let a = counter++;

alert(a); // 1
```

後置式`counter++`はcounterを増加させますが、増加する前の値を返します。そのため、alertは1を表示します。

:::note warn
インクリメント/デクリメントの記述は変数に対してのみ有効なので、`5++`のように値に対して使おうとするとエラーになります…
:::