File size: 3,600 Bytes
972026c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34b05c6
972026c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { useRef, useEffect } from 'react'
import * as Plot from '@observablehq/plot'

const LanguageTierHistoryPlot = ({ data, width = 750, height = 500 }) => {
  const containerRef = useRef()
  
  const tierHistory = [...(data.language_tier_history || [])]
    .filter(d => d.proficiency_score !== null && d.creation_date !== null)
    .sort((a, b) => new Date(a.creation_date) - new Date(b.creation_date))
  
  // Get unique tiers from data, dynamically
  const tiers = [...new Set(tierHistory.map(d => d.tier))]
  
  // Add " languages" suffix for legend display
  const tierWithSuffix = (tier) => `${tier} languages`
  
  // Calculate max proficiency over time for each tier
  const tierRecords = {}
  
  tiers.forEach(tier => {
    const tierData = tierHistory.filter(d => d.tier === tier)
    const records = []
    let maxScore = 0
    
    tierData.forEach(curr => {
      if (curr.proficiency_score > maxScore) {
        maxScore = curr.proficiency_score
        records.push({
          ...curr,
          maxScore: maxScore,
          newRecord: true
        })
      } else {
        records.push({
          ...curr,
          maxScore: maxScore,
          newRecord: false
        })
      }
    })
    
    tierRecords[tier] = records
  })
  
  // Flatten for plotting - only show dots for new records
  // Add " languages" suffix to tier for display
  const recordBreakingDots = Object.values(tierRecords)
    .flat()
    .filter(d => d.newRecord)
    .map(d => ({ ...d, tierDisplay: tierWithSuffix(d.tier) }))
  
  // Create step function data for each tier
  const stepData = tiers.flatMap(tier => {
    const records = tierRecords[tier].filter(d => d.newRecord)
    if (records.length === 0) return []
    
    return [
      ...records.map(d => ({ ...d, tierDisplay: tierWithSuffix(d.tier) })),
      {
        tier: tier,
        tierDisplay: tierWithSuffix(tier),
        creation_date: new Date(),
        maxScore: records[records.length - 1]?.maxScore || 0
      }
    ]
  })
  
  useEffect(() => {
    const plot = Plot.plot({
      width: width,
      height: height,
      subtitle: 'Model performance on language tiers over time',
      x: {
        label: 'Date',
        type: 'time',
        tickFormat: '%Y-%m'
      },
      y: {
        label: 'Overall Score by Language Tier'
      },
      color: {
        legend: true,
        domain: tiers.map(tierWithSuffix)
      },
      marks: [
        Plot.dot(recordBreakingDots, {
          x: d => new Date(d.creation_date),
          y: d => d.proficiency_score,
          fill: 'tierDisplay',
          stroke: 'tierDisplay',
          title: d =>
            `${d.provider_name} - ${d.name} (${
              d.size?.toLocaleString('en-US', { notation: 'compact' }) || '?B'
            })\nTier: ${d.tier}\nPublished: ${new Date(
              d.creation_date
            ).toLocaleDateString()}\nScore: ${d.proficiency_score.toFixed(2)}`,
          tip: true
        }),
        Plot.line(stepData, {
          x: d => new Date(d.creation_date),
          y: d => d.maxScore || 0,
          stroke: 'tierDisplay',
          curve: 'step-after',
          strokeOpacity: 0.5,
          strokeWidth: 2
        })
      ]
    })
    containerRef.current.append(plot)
    return () => plot.remove()
  }, [recordBreakingDots, stepData, width, height, tiers])

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

export default LanguageTierHistoryPlot