📈

診断結果を診断する

4 min read

TLで見かけたエンジニア年収診断にみんなザワザワしてる感じだったので、どうなってるのか知りたくなって調べた。

https://job-draft.jp/diagnosis

TL;DR

  • エンジニア的にプログラミング言語の違いとか気にするけど、これはほぼ項目内容関係なさそう
  • 調べるのはpuppeteerで自動でやりたい
  • 実際やってみたら高くなる項目を見つけられた

検証したい

初めに手作業で全部の項目にチェックを入れたら900万円、最低限のチェック状態だと500万円という結果になることが分かった。これ全部できても900万??みたいに感じられたこともあり、じゃあどれがどのくらいの配分なのかというのを知りたくなった。

どう検証するか?

Q1の経験年数は択一で選択必須、Q2の得意分野とQ3の経験については1個以上選択必須で複数選択可、Q4は必須ではない。なのでQ1,Q2,Q3を一つずつチェックするのがバリデーションが通る最低限の状態で結果は500万円になる。とりあえずこれをベースにQ2,Q3の選択個数を増やしていって結果を見てみたい。

もちろんzennに書くくらいなので手でブラウザ操作するわけにはいかない。手でコードを書いてpuppeteerを動かします。

コード

puppeteerでページを作成

import puppeteer from "puppeteer";

const init = () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
}

診断ページを開き、選択肢をセットする処理

Q1-Q4の各セクションのinput要素を取得し、引数で指定したぶんだけチェックをつける。

const setOptions = async (page: puppeteer.Page, options: number[]) => {
  const sectionList = await getSectionList(page);
  const [q1, q2, q3, q4] = sectionList;

  await Promise.all([
    // q1: 経験年数
    // 択一, required
    q1.$$eval(
      "input",
      (elements, arg) => {
        const index = arg as number;
        const inputList = elements as HTMLInputElement[];
        inputList[index].checked = true;
      },
      options[0]
    ),

    // q2: 得意分野
    // multi, required
    q2.$$eval(
      "input",
      (elements, arg) => {
        const count = arg as number;
        const inputList = elements as HTMLInputElement[];
        inputList.every((input, i) => {
          if (i > count) return false;
          input.checked = true;
          return true;
        });
      },
      options[1]
    ),
    // q3: 経験
    // multi, required
    q3.$$eval(
      "input",
      (elements, arg) => {
        const count = arg as number;
        const inputList = elements as HTMLInputElement[];
        inputList.every((input, i) => {
          if (i > count) return false;
          input.checked = true;
          return true;
        });
      },
      options[2]
    ),
    // q4: その他
    // multi
    q4.$$eval(
      "input[type='checkbox']",
      (elements, arg) => {
        const count = arg as number;
        const inputList = elements as HTMLInputElement[];
        inputList.every((input, i) => {
          if (i > count) return false;
          input.checked = true;
          return true;
        });
      },
      options[3]
    ),
  ]);
};

診断結果ページに遷移して結果を取得する処理

選択肢をセット後、結果表示ボタンを押してページ遷移を待ち、結果ページからテキストを取得する。

const getSalary = async (page: puppeteer.Page): Promise<string> => {
  const submitBtn = await page.$(".diagnosis-btn");
  if (!submitBtn) {
    throw new Error("selector incorrect.");
  }
  await Promise.all([page.waitForNavigation(), submitBtn.click()]);

  return await page.$eval(".diagnosis-result-num", (result) => {
    return result.textContent || "";
  });
};

選択肢のパターンを作って上述の選択肢セット関数と結果取得関数を実行する

  const answers = [];
  const options = [
    ...Array.from(new Array(4), (_, i) => [i, 0, 0, -1]), // Q1
    ...Array.from(new Array(23), (_, i) => [0, i, 0, -1]), // Q2
    ...Array.from(new Array(17), (_, i) => [0, 0, i, -1]), // Q3
    ...Array.from(new Array(4), (_, i) => [0, 0, 0, i]), // Q4
  ];
  for (let option of options) {
    await setOptions(page, option);
    const salary = await getSalary(page);
    answers.push({ option, salary });
  }

  return answers;

これがまあ書き捨てで超絶分かりづらいのだが、何をやってるのかというとQ1-Q4の選択肢をどのように選択するかというパターンを作ってる。

たとえば [2,5,0,2] だとQ1はindex2を選択、Q2はindex5まで選択、Q3は0まで選択、Q4は2まで選択という指定。
(Q1だけradioボタンなので択一、他は指定indexまで頭から選択していくようにしている)

結果

そんなわけで回したパターンが50件ほど。このくらいなら手作業でも良かったかもしれないが、まあ回したかった。

で、思ったとおり選択数が増えるとそのまま直線的に上がるというのが確認できた。つまりプログラミング言語などの選択肢の差は特に無さそうだ。

…というpuppeteer使ってみただけの記事で終わるつもりだったのだが、

グラフの中で特徴的なところがある。Q3の選択肢を一つずつ増やしていくと14個目の選択肢(index:13)で急に上がっていた。

この選択肢にあたる項目を見てみると「エンジニアリングマネージャ」だった。確かにこの項目を選択するだけで高くなる。

まとめ

  • コードを書くのやめよう
  • エンジニアリングマネージャーになろう