aoc-copilot
Version:
Advent of Code automatic runner for examples and inputs
127 lines • 5.72 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.avoidedAttempt = avoidedAttempt;
exports.finish = finish;
exports.incorrectAttempt = incorrectAttempt;
exports.print = print;
exports.solvedElsewhere = solvedElsewhere;
exports.startPart1 = startPart1;
exports.sync = sync;
const promises_1 = require("node:fs/promises");
const cache_1 = require("./cache");
const site_1 = require("./site");
let deleteOldLocation = false;
function readStatsFile(year) {
let newLocation = true;
return (0, promises_1.readFile)(`stats_${year}.json`, { encoding: 'utf-8' })
.catch(() => {
newLocation = false;
return (0, cache_1.read)(`${year}/stats.json`);
}).then(file => {
if (!newLocation)
deleteOldLocation = true;
return JSON.parse(file);
}).catch(() => []);
}
function getDayStats(stats, day) {
return stats.find(stat => stat.day === day) || (stats.push({ day, part1Started: '', part1Finished: '', part2Finished: '', part1AvoidedAttempts: 0, part2AvoidedAttempts: 0, part1IncorrectAttempts: 0, part2IncorrectAttempts: 0, part1SolvedElsewhere: false, part2SolvedElsewhere: false }), stats.at(-1));
}
async function updateStatsFile(year, stats) {
if (deleteOldLocation) { // Move to new location (delete then write)
await (0, cache_1.remove)(`${year}/stats.json`);
deleteOldLocation = false;
}
return (0, promises_1.writeFile)(`stats_${year}.json`, JSON.stringify(stats), { encoding: 'utf-8' });
}
async function startPart1(year, day) {
const stats = await readStatsFile(year);
const dayStats = getDayStats(stats, day);
if (dayStats.part1Started === '')
dayStats.part1Started = new Date().toJSON();
return updateStatsFile(year, stats);
}
async function finish(year, day, part) {
const stats = await readStatsFile(year);
const dayStats = getDayStats(stats, day);
const timestamp = new Date().toJSON();
if (part === 1 && dayStats.part1Finished === '')
dayStats.part1Finished = timestamp;
else if (part === 2 && dayStats.part2Finished === '')
dayStats.part2Finished = timestamp;
await updateStatsFile(year, stats);
return dayStats;
}
async function avoidedAttempt(year, day, part) {
const stats = await readStatsFile(year);
const dayStats = getDayStats(stats, day);
if (part === 1)
dayStats.part1AvoidedAttempts++;
else
dayStats.part2AvoidedAttempts++;
return updateStatsFile(year, stats);
}
async function incorrectAttempt(year, day, part) {
const stats = await readStatsFile(year);
const dayStats = getDayStats(stats, day);
if (part === 1)
dayStats.part1IncorrectAttempts++;
else
dayStats.part2IncorrectAttempts++;
return updateStatsFile(year, stats);
}
async function solvedElsewhere(year, day, part) {
const stats = await readStatsFile(year);
const dayStats = getDayStats(stats, day);
const timestamp = new Date().toJSON();
if (part === 1) {
dayStats.part1SolvedElsewhere = true;
if (dayStats.part1Finished === '')
dayStats.part1Finished = timestamp;
}
else {
dayStats.part2SolvedElsewhere = true;
if (dayStats.part2Finished === '')
dayStats.part2Finished = timestamp;
}
return updateStatsFile(year, stats);
}
async function print(year) {
const stats = await readStatsFile(year);
const times = stats.map(stat => [
stat.day.toString().padStart(3, ' '),
stat.part1Finished === '' ? '' : (0, site_1.hms)(Date.parse(stat.part1Finished) - Date.parse(stat.part1Started)),
stat.part2Finished === '' ? '' : (0, site_1.hms)(Date.parse(stat.part2Finished) - Date.parse(stat.part1Finished))
]);
// Print table
const width1 = times.reduce((pv, cv) => Math.max(pv, cv[1].length), 6);
const width2 = times.reduce((pv, cv) => Math.max(pv, cv[2].length), 6);
const col1 = '-'.repeat(Math.ceil((width1 - 6) / 2)) + 'Part 1' + '-'.repeat(Math.floor((width1 - 6) / 2));
const col2 = '-'.repeat(Math.ceil((width2 - 6) / 2)) + 'Part 2' + '-'.repeat(Math.floor((width2 - 6) / 2));
console.log(`Day ${col1} ${col2}`);
times.toReversed().forEach(time => console.log(`${time[0]} ${time[1].padStart(width1, ' ')} ${time[2].padStart(width2, ' ')}`));
}
/**
* Sync local stats file to site leaderboard service
* @param year Year
* @param id Leaderboard ID
* @param memberId (optional) Member ID; defaults to same as Leaderboard ID
*/
async function sync(year, id, memberId = id, syncIfPossible = false, force = false) {
const stats = await readStatsFile(year);
const leaderboard = await (0, site_1.getLeaderboard)(year, id, syncIfPossible);
for (let [day, stars] of Object.entries(leaderboard.members[memberId].completion_day_level)) {
const stat = getDayStats(stats, parseInt(day));
for (let [part, star] of Object.entries(stars)) {
if (part === '1' && (force || stat.part1Finished === ''))
stat.part1Finished = new Date(star.get_star_ts * 1000).toJSON();
else if (part === '2' && (force || stat.part2Finished === ''))
stat.part2Finished = new Date(star.get_star_ts * 1000).toJSON();
}
if (stat.part1Finished < stat.part1Started || stat.part2Finished < stat.part1Finished) {
console.error(`Your local stats file has start time(s) that are after your actual`, `finish time(s). This can happen when you use multiple development environments`, `so try syncing with your repository and trying again.`);
return;
}
}
await updateStatsFile(year, stats);
}
//# sourceMappingURL=stats.js.map