Skip to content

Instantly share code, notes, and snippets.

@0x666c6f
Last active April 27, 2023 15:12
Show Gist options
  • Select an option

  • Save 0x666c6f/cc020f0ac4cb603b044e69b1a8893008 to your computer and use it in GitHub Desktop.

Select an option

Save 0x666c6f/cc020f0ac4cb603b044e69b1a8893008 to your computer and use it in GitHub Desktop.
OD Committee scripts
const Airtable = require('airtable');
// Configure the Airtable base
const apiKey = '<API_KEY>';
const baseId = '<BASE_ID>';
const committeeId = '<COMMITTEE_ID>';
const base = new Airtable({ apiKey: apiKey }).base(baseId);
// Define the tables
const committeesTable = base('Committees');
const jurorsTable = base('Jurys');
const projectsTable = base('Projects');
const votesTable = base('Votes');
function chunkArray(array, size) {
return Array.from({ length: Math.ceil(array.length / size) }, (_, index) =>
array.slice(index * size, (index + 1) * size)
);
}
// Define a function to shuffle an array
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
// Retrieve all records from the committees table
committeesTable
.select({ view: 'Grid view' })
.all()
.then(committees => {
// Retrieve all records from the jurors table
jurorsTable
.select({ view: 'Grid view' })
.all()
.then(jurors => {
// Retrieve all records from the projects table
projectsTable
.select({ view: 'Grid view' })
.all()
.then(projects => {
const committee_projects = projects.filter(project => {
return project.fields.Committee && project.fields.Committee.includes(committeeId);
});
// Create an array of all the project IDs
const projectIds = committee_projects.map(project => project.id);
// Create an array to store all the votes to create
let votesToCreate = [];
// Assign projects to jurors ensuring even distribution
const assignedProjects = new Map();
for (let i = 0; i < projectIds.length; i++) {
assignedProjects.set(projectIds[i], []);
}
// Assign projects to jurors
const assignments = new Map();
jurors.forEach(jury => {
assignments.set(jury.id, []);
});
// Assign projects to jurors using a round-robin approach
let jurorIndex = 0;
for (let i = 0; i < 12 * jurors.length; i++) {
const projectId = projectIds[i % projectIds.length];
const jurorId = jurors[jurorIndex].id;
if (!assignments.get(jurorId).includes(projectId)) {
assignedProjects.get(projectId).push(jurorId);
assignments.get(jurorId).push(projectId);
} else {
i--;
}
jurorIndex = (jurorIndex + 1) % jurors.length;
}
// Ensure each project has at least 4 jurors
projectIds.forEach(projectId => {
const jurorsAssigned = assignedProjects.get(projectId);
let attempts = 0;
while (jurorsAssigned.length < 4 && attempts < 1000) {
const randomJurorIndex = Math.floor(Math.random() * jurors.length);
const randomJurorId = jurors[randomJurorIndex].id;
if (!jurorsAssigned.includes(randomJurorId) && assignments.get(randomJurorId).length < 12) {
jurorsAssigned.push(randomJurorId);
assignments.get(randomJurorId).push(projectId);
}
attempts++;
}
});
// Create vote objects for each juror-project assignment
for (const [projectId, jurorIds] of assignedProjects.entries()) {
jurorIds.forEach(jurorId => {
const vote = {
fields: {
Committee: [committeeId], // Only one committee available in example data
Jury: [jurorId],
Project: [projectId],
},
};
votesToCreate.push(vote);
});
}
// Chunk the votes into groups of 10 to create them in batches
const chunkedVotesToCreate = chunkArray(votesToCreate, 10);
// Create the votes in batches
chunkedVotesToCreate.forEach(chunk => {
votesTable.create(chunk, (err, records) => {
if (err) {
console.error(err);
return;
}
});
});
}).catch((error) => {
console.log(error);
});
}).catch((error) => {
console.log(error);
});
}).catch((error) => {
console.log(error);
});
import csv
import locale
# Set the locale to use a comma as the decimal separator
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
# Open the CSV file for reading
with open('votes.csv', newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile, delimiter=';')
# Create a dictionary to store the total note and count for each project
project_totals = {}
# Iterate over each row in the CSV file
for row in reader:
# Check if the row has missing data
if not row['Project name'] or not row['Note']:
print(f'Skipping row with missing data: {row}')
continue
# Extract the project name and note from the row
project_name = row['Project name']
note = float(row['Note'].replace(',', '.'))
# If this is the first vote for the project, create a new entry in the dictionary
if project_name not in project_totals:
project_totals[project_name] = {'total_note': note, 'vote_count': 1}
# If the project already exists in the dictionary, update the total note and vote count
else:
project_totals[project_name]['total_note'] += note
project_totals[project_name]['vote_count'] += 1
# Calculate the average note for each project
project_averages = {project_name: totals['total_note'] / totals['vote_count'] for project_name, totals in project_totals.items()}
# Sort the projects by descending order of the average note
sorted_projects = sorted(project_averages.items(), key=lambda x: x[1], reverse=True)
# Write the results to a CSV file
with open('average_notes.csv', 'w', newline='', encoding='utf-8') as outfile:
writer = csv.writer(outfile, delimiter=';')
writer.writerow(['Project', 'Average Note'])
# Sort the lines in the output by descending order of the average note
for project_name, average_note in sorted(sorted_projects, key=lambda x: x[1], reverse=True):
writer.writerow([project_name, locale.format_string('%.2f', average_note, grouping=True)])
import csv
import os
def create_raw_text_file(row):
raw_text = ""
raw_text += f"{row[2]}\n\n\n" # project name
raw_text += f"Project lead\n{'-' * len('Project lead')}\n{row[1]}\n\n" # project lead
raw_text += f"Project description\n{'-' * len('Project description')}\n{row[3]}\n\n" # project website
raw_text += f"Project repositories\n{'-' * len('Project repositories')}\n{row[4]}\n\n" # project repositories
raw_text += f"Project website\n{'-' * len('Project website')}\n{row[5]}\n\n" # project website
raw_text += f"Project lead and team members\n{'-' * len('Project lead and team members')}\n{row[6]}\n\n" # project lead and team members
raw_text += f"How does the project add value to the Starknet ecosystem?\n{'-' * len('How does the project add value to the Starknet ecosystem?')}\n{row[7]}\n\n" # how does the project add value
raw_text += f"Project status\n{'-' * len('Project status')}\n{row[8]}\n\n" # project status
raw_text += f"Project license\n{'-' * len('Project license')}\n{row[9]}\n\n" # project license
raw_text += f"Project timeline and milestones\n{'-' * len('Project timeline and milestones')}\n{row[10]}\n\n" # project timeline and milestones
raw_text += f"Funding request and usage\n{'-' * len('Funding request and usage')}\n{row[11]}\n\n" # funding request and usage
raw_text += f"Funding or grants received\n{'-' * len('Funding or grants received')}\n{row[12]}\n\n" # funding or grants received
raw_text += f"Project metrics\n{'-' * len('Project metrics')}\n{row[13]}\n\n" # project metrics
raw_text += f"Additional information or comments\n{'-' * len('Additional information or comments')}\n{row[14]}\n\n" # additional information or comments
filename = row[2][:30] + ".txt" # max 30 characters for filename
with open(os.path.join("output", filename), "w") as f:
f.write(raw_text)
if not os.path.exists("output"): # create output directory if it doesn't exist
os.mkdir("output")
with open("input.csv", newline="", encoding="utf-8") as csvfile:
reader = csv.reader(csvfile, delimiter=",", quotechar='"')
next(reader) # skip header row
for row in reader:
create_raw_text_file(row)
const Airtable = require('airtable');
// Configure the Airtable base
const apiKey = '<API_KEY>';
const baseId = '<BASE_ID>';
const committeeId = '<COMMITTEE_ID>';
const base = new Airtable({ apiKey: apiKey }).base(baseId);
// Define the tables
const jurorsTable = base('Jurys');
const projectsTable = base('Projects');
const votesTable = base('Votes');
// Initialize counts
const projectsAssignedByJurors = {};
const jurorsPerProject = {};
// Retrieve all records from the jurors table
jurorsTable
.select({ view: 'Grid view' })
.all()
.then(jurors => {
// Retrieve all records from the projects table
projectsTable
.select({ view: 'Grid view' })
.all()
.then(projects => {
// Retrieve all records from the votes table
votesTable
.select({ view: 'Grid view' })
.all()
.then(votes => {
const committee_votes = votes.filter(vote => {
return vote.fields.Committee && vote.fields.Committee.includes(committeeId);
});
// Process the votes
committee_votes.forEach(vote => {
const jurorId = vote.get('Jury')[0];
const projectId = vote.get('Project')[0];
// Count the number of projects assigned by jurors
projectsAssignedByJurors[jurorId] = (projectsAssignedByJurors[jurorId] || 0) + 1;
// Count the number of jurors per project
jurorsPerProject[projectId] = (jurorsPerProject[projectId] || 0) + 1;
});
// Output the number of projects assigned by jurors
console.log('Projects assigned by jurors:');
Object.entries(projectsAssignedByJurors).forEach(([jurorId, count]) => {
const juror = jurors.find(j => j.id === jurorId);
console.log(`${juror.get('Name')}: ${count} projects`);
});
console.log('\n');
// Output the number of jurors per project
console.log('Jurors per project:');
Object.entries(jurorsPerProject).forEach(([projectId, count]) => {
const project = projects.find(p => p.id === projectId);
if (project != undefined) {
console.log(`${project.get('Name')}: ${count} jurors`);
}
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment