mirror of
https://github.com/BradNut/awesome-uses
synced 2025-09-08 17:40:31 +00:00
100 lines
2.7 KiB
JavaScript
100 lines
2.7 KiB
JavaScript
import { name } from 'country-emoji';
|
|
import people from '../data.js';
|
|
|
|
function merge(prop) {
|
|
return function(acc, obj) {
|
|
// Remove duplicated values.
|
|
const values = [...new Set(obj[prop])];
|
|
return [...values, ...acc];
|
|
};
|
|
}
|
|
|
|
function countInstances(acc, tag) {
|
|
acc[tag] = acc[tag] ? acc[tag] + 1 : 1;
|
|
return acc;
|
|
}
|
|
|
|
export function normalizeTag(tag) {
|
|
return (
|
|
tag
|
|
// Common mispellings currently seen in the data
|
|
// Do we want to go this far?
|
|
.replace(/frontend/i, 'Front End')
|
|
.replace(/backend/i, 'Back End')
|
|
.replace(/fullstack/i, 'Full Stack')
|
|
.replace(/a11y/i, 'Accessibility')
|
|
.replace(/next.?js/i, 'Next')
|
|
.replace(/react.?js/i, 'React')
|
|
|
|
// Or is lowercase enough?
|
|
.toLowerCase()
|
|
);
|
|
}
|
|
|
|
export function countries() {
|
|
const data = people
|
|
.map(person => ({
|
|
name: name(person.country),
|
|
emoji: person.country,
|
|
}))
|
|
.reduce((acc, country) => {
|
|
if (acc[country.name]) {
|
|
// exists, update
|
|
acc[country.name].count += 1;
|
|
} else {
|
|
acc[country.name] = {
|
|
...country,
|
|
count: 1,
|
|
};
|
|
}
|
|
return acc;
|
|
}, {});
|
|
|
|
const sorted = Object.entries(data)
|
|
.map(([, country]) => country)
|
|
.sort((a, b) => b.count - a.count);
|
|
|
|
return sorted;
|
|
}
|
|
|
|
export function tags() {
|
|
const allTags = people.reduce(merge('tags'), []);
|
|
const counts = allTags.reduce(countInstances, {});
|
|
// sort and filter for any tags that only have 1
|
|
const tags = Object.entries(counts)
|
|
.sort(([, countA], [, countB]) => countB - countA)
|
|
// Only show the tag if this topic has 3 or more people in it
|
|
.filter(([, count]) => count >= 3)
|
|
.map(([name, count]) => ({ name, count }));
|
|
|
|
const lowercaseTagMap = tags.reduce((acc, tag) => {
|
|
const normalizedName = normalizeTag(tag.name);
|
|
const currentCount = acc[normalizedName] || 0;
|
|
acc[normalizedName] = currentCount + tag.count;
|
|
return acc;
|
|
}, {});
|
|
|
|
// Merge tags like "JavaScript" and "Javascript" based on the
|
|
// count… Event though it's obviously JavaScript!
|
|
const normalizedTags = tags.reduce((acc, { name }) => {
|
|
const normalizedName = normalizeTag(name);
|
|
if (typeof lowercaseTagMap[normalizedName] !== 'undefined') {
|
|
acc.push({ name, count: lowercaseTagMap[normalizedName] });
|
|
delete lowercaseTagMap[normalizedName];
|
|
}
|
|
return acc;
|
|
}, []);
|
|
|
|
return [{ name: 'all', count: people.length }, ...normalizedTags];
|
|
}
|
|
|
|
export function devices() {
|
|
const all = [
|
|
...people.map(person => person.computer),
|
|
...people.map(person => person.phone),
|
|
];
|
|
|
|
return Object.entries(all.reduce(countInstances, {}))
|
|
.map(([device, count]) => ({ name: device, count }))
|
|
.sort((a, b) => b.count - a.count);
|
|
}
|