File size: 2,328 Bytes
867080c
 
b4a0c57
7cdde63
 
 
 
 
 
 
92d8154
 
 
7cdde63
 
 
92d8154
 
 
 
7cdde63
 
 
 
 
 
92b2164
 
00e463a
867080c
00e463a
b4a0c57
 
00e463a
867080c
00e463a
867080c
b4a0c57
867080c
92d8154
 
 
 
 
 
867080c
a9e6b9b
867080c
7cdde63
867080c
 
92d8154
 
 
00e463a
867080c
00e463a
 
7cdde63
00e463a
 
 
92d8154
7cdde63
 
 
00e463a
867080c
 
 
92d8154
867080c
7cdde63
 
 
 
 
 
 
 
92d8154
7cdde63
 
 
867080c
b4a0c57
867080c
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { useRef, useEffect, useState } from 'react'
import * as Plot from '@observablehq/plot'

const smoothProgressBar = fraction => {
  const blocks = ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '█']
  const width = 10
  const totalUnits = width * 8
  const filledUnits = Math.round(fraction * totalUnits)
  const fullBlocks = Math.floor(filledUnits / 8)
  const remainder = filledUnits % 8
  return (
    '█'.repeat(fullBlocks) + (remainder > 0 ? blocks[remainder - 1] : '') || '▏'
  )
}

const makeTitle = data => d => {
  const languages = data[d.properties?.ISO_A2_EH]?.languages.toSorted(
    (a, b) => b.population - a.population
  )
  const pop = languages?.map(a => a.population).reduce((prev, a) => prev + a, 0)
  const langstring =
    languages
      ?.slice(0, 10)
      .map(a => `${smoothProgressBar(a.population / pop)} ${a.name}`)
      .join('\n\n') + (languages?.length > 10 ? `\n\n...` : '')
  return `${d.properties.ADMIN}\n\n${langstring}`
}

const WorldMap = ({ data }) => {
  const containerRef = useRef()
  const [mapData, setMapData] = useState()

  useEffect(() => {
    fetch('/world.geo.json')
      .then(res => res.json())
      .then(setMapData)
  }, [])

  useEffect(() => {
    console.log('countries', data)
    if (mapData === undefined || data === undefined) return
    const countriesDict = data.reduce((acc, country) => {
      acc[country.iso2] = country
      return acc
    }, {})
    const plot = Plot.plot({
      subtitle: 'Language Proficiency Score by Country',
      width: 750,
      height: 500,
      projection: 'equal-earth',
      marks: [
        Plot.geo(mapData, {
          fill: d => countriesDict[d.properties?.ISO_A2_EH]?.score,
          title: makeTitle(countriesDict),
          tip: true
        })
      ],
      color: {
        scheme: 'Greens',
        unknown: 'gray',
        label: 'Score',
        legend: true,
        domain: [0, 0.7]
      },
      style: {
        fontFamily: 'monospace'
      }
    })
    containerRef.current.append(plot)
    return () => plot.remove()
  }, [mapData, data])

  return (
    <div
      ref={containerRef}
      style={{
        width: '100%',
        height: '100%',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center'
      }}
    />
  )
}

export default WorldMap