File size: 2,176 Bytes
e522b66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import Papa from "papaparse";

export async function loadStackOverflowCSV(path, fetchOptions = {}) {
  const url = path + (path.includes("?") ? "&" : "?") + "t=" + Date.now();
  const res = await fetch(url, fetchOptions);
  if (!res.ok)
    throw new Error(`Failed to load CSV: ${res.status} ${res.statusText}`);
  const text = await res.text();
  const { data } = Papa.parse(text, {
    header: true,
    skipEmptyLines: true,
    transformHeader: (header) => header.trim(),
  });
  return { rows: data.map(normalizeRow) };
}

function normalizeRow(r) {
  const clone = { ...r };

  // Normalize numeric fields for Stack Overflow data
  clone.Age = safeNumber(r.Age);
  clone.YearsCode = safeNumber(r.YearsCode);
  clone.YearsCodePro = safeNumber(r.YearsCodePro);
  clone.ConvertedCompYearly = safeNumber(r.ConvertedCompYearly);
  clone.WorkWeekHrs = safeNumber(r.WorkWeekHrs);
  clone.CompTotal = safeNumber(r.CompTotal);

  // Keep string fields as is
  clone.Country = r.Country || "";
  clone.Gender = r.Gender || "";
  clone.EdLevel = r.EdLevel || "";
  clone.DevType = r.DevType || "";
  clone.RemoteWork = r.RemoteWork || "";
  clone.JobSat = r.JobSat || "";
  clone.LanguageHaveWorkedWith = r.LanguageHaveWorkedWith || "";
  clone.LanguageWantToWorkWith = r.LanguageWantToWorkWith || "";
  clone.DatabaseHaveWorkedWith = r.DatabaseHaveWorkedWith || "";
  clone.DatabaseWantToWorkWith = r.DatabaseWantToWorkWith || "";
  clone.PlatformHaveWorkedWith = r.PlatformHaveWorkedWith || "";
  clone.PlatformWantToWorkWith = r.PlatformWantToWorkWith || "";
  clone.OrgSize = r.OrgSize || "";
  clone.LearnCode = r.LearnCode || "";
  clone.AISelect = r.AISelect || "";
  clone.AIAccompany = r.AIAccompany || "";
  clone.AIWantToWorkWith = r.AIWantToWorkWith || "";

  return clone;
}

function safeNumber(v) {
  if (v === null || v === undefined || v === "") return 0;

  const cleaned = String(v).replace(/,/g, "").replace(/\s+/g, "").trim();

  // Handle K for thousands
  if (cleaned.endsWith("K")) {
    const num = parseFloat(cleaned.slice(0, -1));
    return Number.isFinite(num) ? num * 1000 : 0;
  }

  const n = Number(cleaned);
  return Number.isFinite(n) ? n : 0;
}