Skip to content

Commit

Permalink
feat(CONTRIBUTING_EXPENSE): Open Collectiveの手引きを追加 (#1764)
Browse files Browse the repository at this point in the history
* feat(CONTRIBUTING_EXPENSE): Open Collectiveの手引きを追加

* update

* update
  • Loading branch information
azu authored Aug 25, 2024
1 parent e950330 commit e3574fa
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 0 deletions.
141 changes: 141 additions & 0 deletions CONTRIBUTING_EXPENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Contributing Expenses Policy

JavaScript Primer(jsprimer)はOpen Collectiveを通じて資金を募っています。
この資金は、jsprimerへContributeしてくれた方々に対して、費用を支払うために使われます。

- [JavaScript Primer - Open Collective](https://opencollective.com/jsprimer)
- [JavaScript Primerスポンサー · JavaScript Primer #jsprimer](https://jsprimer.net/intro/sponsors/)

このガイドでは、jsprimerへのContributeした場合の費用をOpen Collectiveで請求する方法について説明します。

## 費用の計算方法

jsprimerへのContributeしたタスクに対してPointを設定し、そのPointに基づいて金額を計算します。

### タスクに対するPoint

作業量に対する基準としてフィボナッチ数列のPointを設定する

| Point | Description |
|-------|-----------------------|
| 0 | 些細な変更 |
| 1 | 2 よりは簡単 |
| 2 | 大体1日分やると終わる想定 |
| 3 | 2 よりは難しい |
| 5 | かなり難しい |
| 8 | 難易度がとても高いので、できる人は限られる |

Issueが適切に分割されていれば、5や8はほとんど出てこない想定です。
5以降はブレが大きいので、参考程度のPointとして扱います。

📝 元ネタはLinearの[Estimates – Linear Docs](https://linear.app/docs/estimates)

### Pointの例

Pointはやや主観的になってしまうが、既存のIssueを比較してどの程度のPointになるかを判断する。

- Point 1:
- [fix(nodecli): update to marked@14 by azu · Pull Request #1760 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1760)
- ほとんど置換で終わるような変更
- [fix: Node.js v18.12.0 LTSにアップデート by azu · Pull Request #1496 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1496)
- やり方がだいたい定型化されてる変更
- Point 2:
- [feat(ecmascript): Stage 2.7を追加 by azu · Pull Request #1743 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1743)
- 文章自体はほとんどないが、多少調べる必要がある
- [mocha を`node:test`に変更する by windchime-yk · Pull Request #1737 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1737)
- 1 つのセクションを書き直すような変更
- [feat(map-and-set): `Map.groupBy`静的メソッドの追加 by azu · Pull Request #1751 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1751)
- 1 つのセクションを追加する変更
- [feat: ErrorCause への対応 by himanoa · Pull Request #1732 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1732)
- 1 つのセクションを追加する変更
- Point 3:
- [feat(array): Change Array by copy の対応 by azu · Pull Request #1679 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1679)
- 複数のセクションにまたがる変更
- Point 5:
- [fix(nodecli): commander パッケージ を `node:util``parseArg` に変更 by azu · Pull Request #1757 · asciidwango/js-primer](https://github.com/asciidwango/js-primer/pull/1757)
- 章全体にまたがる変更
- かなり影響範囲が広く、書き直しも多い変更

### 金額の計算方法

金額は次のツールで計算できる。

```bash
$ node ./tools/calc-contribute-expense.mjs --point <number>
```

#### 金額の計算式

jsprimerの年間更新コストは、だいたい30日分の作業量になるように設定している。

- [JavaScript Primer 改訂2版をリリースしました!/JavaScript Primerはなぜ更新され続けるのか? | Web Scratch](https://efcl.info/2023/06/09/jsprimer-v2/)

Pointに直すと、年間の作業量のPointは60 Point程度になる。

年間の予算はOpen Collectiveの"推定年間予算(Estimated annual budget)"を参照する

- [JavaScript Primer - Open Collective](https://opencollective.com/jsprimer)

1 Pointあたりの金額は次の計算式で求める。

```js
const yearlyEstimatedBudget = _; // Open Collectiveの推定年間予算($ドル)
const yearlyWorkloadPoints = 60; // 1年間のPoints
const onePointCost = yearlyEstimatedBudget / yearlyWorkloadPoints;
console.log({ onePointCost }); // => 1 Pointあたりの金額($ドル)
const taskPoint = _; /// タスクのPoint
const cost = onePointCost * taskPoint;
console.log({ cost }); // => タスクの金額($ドル)
```

Example: 推定年間予算が $2,367 で、タスクが 2 Points の場合

```js

const yearlyEstimatedBudget = 2_367; // Open Collectiveの推定年間予算($ドル)
const yearlyWorkloadPoints = 60; // 1年間のPoints
const onePointCost = yearlyEstimatedBudget / yearlyWorkloadPoints;
console.log({ onePointCost }); // => $39.45

const costOfPoint = 2; /// 2 Points
const cost = onePointCost * costOfPoint;
console.log({ cost }); // => $78.9
```

### 金額を確定するタイミング

作業が終わったタイミングで計算して、その月のコストをまとめて申請する。
Open Collectiveからの支払いは2週間ごとに行われるため、月ごとにまとめて請求する。

## 費用の請求方法

計算式に基づいた金額をOpen Collectiveで請求する手順

1. <https://opencollective.com/jsprimer/expenses/new> にアクセス
2. "Invoice"を選択
3. 請求者の情報と支払い先(銀行口座またはPayPal)を入力
4. "Next"をクリック
5. 請求書の画面で "Expense title" に `Development and maintenance (YYYY-DD)` と入力
6. 請求書の画面で "Set invoice details"の "Description" に `Contribute to jsprimer (YYYY-DD)` と入力
7. 請求書の画面で "Date" には 今日の日付を入力
8. 請求書の画面で "Amount" は USD を選択し、計算した金額を入力
- 自動的にExpense Currencyで選択したJPYに変換された金額が表示されます
9. "Next"をクリック
10. Add notesに次の内容を入力
```
Contribute to jsprimer
- Commits: https://github.com/asciidwango/js-primer/commits?author=<GitHubアカウント>&since=月の初めの日&until=月の最終日
```
```
Contribute to jsprimer
- Commits: https://github.com/asciidwango/js-primer/commits?author=azu&since=2024-08-01&until=2024-08-31
```
11. 確認して "Submit expense"をクリック

あとは管理者がApproveするまで待つと、その後Open Collectiveから支払われます。

Note:

- 入力した個人情報は公開されません
- 公開されるのは、Expense titleとDescriptionとOpen Collectiveのアカウント情報のみです
73 changes: 73 additions & 0 deletions tools/calc-contribute-expense.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env node

import { parseArgs } from "node:util";

const HELP = `
コラボレーターの請求額を計算するツール
Usage: ./calc-contribute-expense.js --point <number>
Options:
--point, -p <number> 計算したいポイント数
--help, -h ヘルプを表示
`;
const cli = parseArgs({
options: {
point: {
type: "string",
alias: "p",
},
help: {
type: "boolean",
alias: "h",
}
}
});
if (cli.values.help) {
console.log(HELP);
process.exit(0);
}

const point = cli.values.point ? parseInt(cli.values.point, 10) : null;
if (!point) {
console.error("--point <number> を指定してください");
process.exit(1);
}
const query = `query account($slug: String) {
account(slug: $slug) {
name
slug
stats{
yearlyBudget {
currency
value
valueInCents
}
}
}
}`;
const slug = "jsprimer";
const response = await fetch("https://api.opencollective.com/graphql/v2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables: { slug },
}),
});
const { data } = await response.json();
const yearlyBudgetCents = data.account.stats.yearlyBudget.valueInCents;
const yearlyWorkloadPoints = 60; // 1年間のPoints
const onePointCostCents = yearlyBudgetCents / yearlyWorkloadPoints;
const costCents = onePointCostCents * point;
console.log(`コラボレーターの請求額: $${costCents / 100}`);
console.table({
"1年間の予算": `$${yearlyBudgetCents / 100}`,
"1年間のWorkload Points": yearlyWorkloadPoints,
"1ポイントあたりのコスト": `$${onePointCostCents / 100}`,
"請求額": `$${costCents / 100}`,
});

0 comments on commit e3574fa

Please sign in to comment.