|  | import { DataTable } from 'primereact/datatable' | 
					
						
						|  | import { Column } from 'primereact/column' | 
					
						
						|  | import { FilterMatchMode } from 'primereact/api' | 
					
						
						|  | import { MultiSelect } from 'primereact/multiselect' | 
					
						
						|  | import { useState, useEffect } from 'react' | 
					
						
						|  | import { Slider } from 'primereact/slider' | 
					
						
						|  | import ScoreColumns from './ScoreColumns' | 
					
						
						|  |  | 
					
						
						|  | const LanguageTable = ({ data, selectedLanguages, setSelectedLanguages, totalModels = 0 }) => { | 
					
						
						|  | const [filters, setFilters] = useState({ | 
					
						
						|  | language_name: { value: null, matchMode: FilterMatchMode.EQUALS }, | 
					
						
						|  | family: { value: null, matchMode: FilterMatchMode.IN }, | 
					
						
						|  | speakers: { value: null, matchMode: FilterMatchMode.BETWEEN } | 
					
						
						|  | }) | 
					
						
						|  |  | 
					
						
						|  | const families = [...new Set(data.map(item => item.family))].slice(0, 10) | 
					
						
						|  | families.push('Other') | 
					
						
						|  | const familyRowFilterTemplate = options => { | 
					
						
						|  | return ( | 
					
						
						|  | <MultiSelect | 
					
						
						|  | value={options.value} | 
					
						
						|  | options={families} | 
					
						
						|  | onChange={e => { | 
					
						
						|  | options.filterApplyCallback(e.value) | 
					
						
						|  | setFilters(prevFilters => ({ | 
					
						
						|  | ...prevFilters, | 
					
						
						|  | family: { value: e.value, matchMode: FilterMatchMode.IN } | 
					
						
						|  | })) | 
					
						
						|  | }} | 
					
						
						|  | placeholder='All families' | 
					
						
						|  | /> | 
					
						
						|  | ) | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const formatPopulation = population => { | 
					
						
						|  | if (population === null) { | 
					
						
						|  | return '' | 
					
						
						|  | } else if (population < 1000) { | 
					
						
						|  | return population.toFixed(0) + '' | 
					
						
						|  | } else if (population < 10 * 1000) { | 
					
						
						|  | return (population / 1000).toFixed(1) + 'K' | 
					
						
						|  | } else if (population < 1000 * 1000) { | 
					
						
						|  | return (population / 1000).toFixed(0) + 'K' | 
					
						
						|  | } else if (population < 10 * 1000 * 1000) { | 
					
						
						|  | return (population / 1000 / 1000).toFixed(1) + 'M' | 
					
						
						|  | } else if (population < 1000 * 1000 * 1000) { | 
					
						
						|  | return (population / 1000 / 1000).toFixed(0) + 'M' | 
					
						
						|  | } else { | 
					
						
						|  | return (population / 1000 / 1000 / 1000).toFixed(1) + 'B' | 
					
						
						|  | } | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const SliderWithLabel = ({ value, onChange }) => { | 
					
						
						|  | const p = 10 | 
					
						
						|  | const min = 4 | 
					
						
						|  | const max = 9.3 | 
					
						
						|  | const start = value === null ? min : Math.log(value[0]) / Math.log(p) | 
					
						
						|  | const stop = value === null ? max : Math.log(value[1]) / Math.log(p) | 
					
						
						|  | const [_value, _setValue] = useState([start, stop]) | 
					
						
						|  | useEffect(() => { | 
					
						
						|  | const timer = setTimeout(() => { | 
					
						
						|  | onChange({ | 
					
						
						|  | value: | 
					
						
						|  | _value[0] <= min + 0.1 && _value[1] >= max - 0.1 | 
					
						
						|  | ? null | 
					
						
						|  | : [p ** _value[0], p ** _value[1]] | 
					
						
						|  | }) | 
					
						
						|  | }, 1000) | 
					
						
						|  | return () => clearTimeout(timer) | 
					
						
						|  | }, [_value, onChange]) | 
					
						
						|  | return ( | 
					
						
						|  | <div style={{ minWidth: '20rem' }}> | 
					
						
						|  | <div>{formatPopulation(p ** _value[0])}</div> | 
					
						
						|  | <div>{formatPopulation(p ** _value[1])}</div> | 
					
						
						|  | <Slider | 
					
						
						|  | value={_value} | 
					
						
						|  | onChange={e => _setValue(e.value)} | 
					
						
						|  | placeholder='All sizes' | 
					
						
						|  | min={min} | 
					
						
						|  | max={max} | 
					
						
						|  | step={0.01} | 
					
						
						|  | range | 
					
						
						|  | style={{ marginTop: '5rem' }} | 
					
						
						|  | /> | 
					
						
						|  | </div> | 
					
						
						|  | ) | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const speakerFilterTemplate = options => { | 
					
						
						|  | return ( | 
					
						
						|  | <SliderWithLabel | 
					
						
						|  | value={options.value} | 
					
						
						|  | onChange={e => { | 
					
						
						|  | options.filterApplyCallback(e.value) | 
					
						
						|  | setFilters(prevFilters => ({ | 
					
						
						|  | ...prevFilters, | 
					
						
						|  | speakers: { value: e.value, matchMode: FilterMatchMode.BETWEEN } | 
					
						
						|  | })) | 
					
						
						|  | }} | 
					
						
						|  | /> | 
					
						
						|  | ) | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const speakerBodyTemplate = rowData => { | 
					
						
						|  | const populationStr = formatPopulation(rowData.speakers) | 
					
						
						|  | return <div style={{ textAlign: 'center' }}>{populationStr}</div> | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | const languageBodyTemplate = rowData => { | 
					
						
						|  | return ( | 
					
						
						|  | <div> | 
					
						
						|  | <div style={{ fontWeight: 'bold' }}>{rowData.autonym}</div> | 
					
						
						|  | <div style={{ fontSize: '0.8rem', color: 'gray' }}> | 
					
						
						|  | {rowData.language_name} | 
					
						
						|  | </div> | 
					
						
						|  | </div> | 
					
						
						|  | ) | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | return ( | 
					
						
						|  | <DataTable | 
					
						
						|  | value={data.filter( | 
					
						
						|  | item => !selectedLanguages.some(l => l.bcp_47 === item.bcp_47) | 
					
						
						|  | )} | 
					
						
						|  | header={ | 
					
						
						|  | <span> | 
					
						
						|  | <span style={{ fontWeight: 'bold', fontSize: '1.1em' }}>Languages</span> | 
					
						
						|  | <span style={{ fontSize: '0.85em', marginLeft: '0.5rem' }}> | 
					
						
						|  | Average performance of {totalModels} evaluated AI models | 
					
						
						|  | </span> | 
					
						
						|  | </span> | 
					
						
						|  | } | 
					
						
						|  | sortField='speakers' | 
					
						
						|  | removableSort | 
					
						
						|  | filters={filters} | 
					
						
						|  | filterDisplay='menu' | 
					
						
						|  | selectionMode='checkbox' | 
					
						
						|  | selection={selectedLanguages} | 
					
						
						|  | onSelectionChange={e => setSelectedLanguages(e.value)} | 
					
						
						|  | frozenValue={selectedLanguages} | 
					
						
						|  | virtualScrollerOptions={{ itemSize: 60 }} | 
					
						
						|  | scrollable | 
					
						
						|  | scrollHeight='600px' | 
					
						
						|  | id='language-table' | 
					
						
						|  | style={{ width: '100%', minHeight: '650px' }} | 
					
						
						|  | > | 
					
						
						|  | <Column selectionMode='multiple' headerStyle={{ width: '3rem' }} /> | 
					
						
						|  | <Column | 
					
						
						|  | field='language_name' | 
					
						
						|  | header='Language' | 
					
						
						|  | body={languageBodyTemplate} | 
					
						
						|  | style={{ minWidth: '10rem' }} | 
					
						
						|  | frozen | 
					
						
						|  | /> | 
					
						
						|  | <Column | 
					
						
						|  | field='speakers' | 
					
						
						|  | header={<i className='pi pi-users' title='Speakers' />} | 
					
						
						|  | headerTooltip='Number of speakers of the language (according to CLDR 2018)' | 
					
						
						|  | body={speakerBodyTemplate} | 
					
						
						|  | filter | 
					
						
						|  | filterElement={speakerFilterTemplate} | 
					
						
						|  | showFilterMatchModes={false} | 
					
						
						|  | sortable | 
					
						
						|  | style={{ minWidth: '5rem' }} | 
					
						
						|  | /> | 
					
						
						|  | <Column | 
					
						
						|  | field='family' | 
					
						
						|  | header='Family' | 
					
						
						|  | headerTooltip='Language family' | 
					
						
						|  | filter | 
					
						
						|  | showFilterMatchModes={false} | 
					
						
						|  | filterElement={familyRowFilterTemplate} | 
					
						
						|  | style={{ minWidth: '10rem' }} | 
					
						
						|  | /> | 
					
						
						|  | {ScoreColumns()} | 
					
						
						|  | </DataTable> | 
					
						
						|  | ) | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | export default LanguageTable | 
					
						
						|  |  |