diff --git a/.github/updateLeaderboard.js b/.github/updateLeaderboard.js index 988d783..7c88e94 100644 --- a/.github/updateLeaderboard.js +++ b/.github/updateLeaderboard.js @@ -1,135 +1,127 @@ const fs = require('fs'); module.exports = async ({ github, context }) => { - const query = `query($owner:String!, $name:String!, $issue_number:Int!) { - repository(owner:$owner, name:$name){ - issue(number:$issue_number) { - title - bodyText - author { - avatarUrl(size: 24) - login - url + try { + console.log('Starting leaderboard update...'); + + const query = `query($owner:String!, $name:String!, $issue_number:Int!) { + repository(owner:$owner, name:$name){ + issue(number:$issue_number) { + title + bodyText + author { + avatarUrl(size: 24) + login + url + } + updatedAt + } } - updatedAt + }`; + + const variables = { + owner: context.repo.owner, + name: context.repo.repo, + issue_number: context.issue.number, + }; + + const result = await github.graphql(query, variables); + console.log(JSON.stringify(result, null, 2)); + + const issue = result.repository.issue; + + const nameMatch = /👤 Name:\s*(.*?)\n-/.exec(issue.bodyText); + const githubLinkMatch = /🔗 GitHub Profile Link:\s*(.*?)\n-/.exec(issue.bodyText); + const messageMatch = /💬 Message:\s*(.*?)\n-/.exec(issue.bodyText); + const scoreMatch = /Score:\s*(\d+)/.exec(issue.title); + const dateMatch = /Game Result Submission:\s*(.*?) - Score:/.exec(issue.title); + const modeMatch = /Mode:\s*(\d+)/.exec(issue.title); + const winMatch = /Win:\s*(\d+)/.exec(issue.title); + + // Extract values or fallback to author details if null + const name = nameMatch ? nameMatch[1].trim() : issue.author.login; + const githubLink = githubLinkMatch ? githubLinkMatch[1].trim() : issue.author.url; + const message = messageMatch ? messageMatch[1].trim() : ''; + const score = scoreMatch ? parseInt(scoreMatch[1].trim()) : null; + const date = dateMatch ? dateMatch[1].trim() : null; + const mode = modeMatch ? parseInt(modeMatch[1].trim()) : null; + const win = winMatch ? parseInt(winMatch[1].trim()) : null; + + // Check for null values + if (score === null || date === null || mode === null || win === null) { + console.log('One or more required fields are missing. Stopping further processing.'); + return false; } - } - }`; - - const variables = { - owner: context.repo.owner, - name: context.repo.repo, - issue_number: context.issue.number, - }; - - const result = await github.graphql(query, variables); - console.log(JSON.stringify(result, null, 2)); - - const issue = result.repository.issue; - - const nameMatch = /👤 Name:\s*(.*?)\n-/.exec(issue.bodyText); - const githubLinkMatch = /🔗 GitHub Profile Link:\s*(.*?)\n-/.exec(issue.bodyText); - const messageMatch = /💬 Message:\s*(.*?)\n-/.exec(issue.bodyText); - const scoreMatch = /Score:\s*(\d+)/.exec(issue.title); - const dateMatch = /Game Result Submission:\s*(.*?) - Score:/.exec(issue.title); - const modeMatch = /Mode:\s*(\d+)/.exec(issue.title); - const winMatch = /Win:\s*(\d+)/.exec(issue.title); - - - // Extract values or fallback to author details if null - const name = nameMatch ? nameMatch[1].trim() : issue.author.login; // Use author's GitHub login if name not found - const githubLink = githubLinkMatch ? githubLinkMatch[1].trim() : issue.author.url; // Use author's URL if not found - const message = messageMatch ? messageMatch[1].trim() : ''; // Default message if not found - const score = scoreMatch ? parseInt(scoreMatch[1].trim()) : null; // Extract score - const date = dateMatch ? dateMatch[1].trim() : null; // Extract date - const mode = modeMatch ? parseInt(modeMatch[1].trim()) : null; // Extract mode - const win = winMatch ? parseInt(winMatch[1].trim()) : null; // Extract win status - - // Check if any of the extracted values are null, if so, stop processing - if (score === null || date === null || mode === null || win === null) { - console.log('One or more required fields are missing. Stopping further processing.'); - return; // Exit or stop further execution as needed - } - // Map mode values to difficulty levels - const modeMapping = { - 0: 'Easy', - 1: 'Medium', - 2: 'Hard' - }; + // Map mode values to difficulty levels + const modeMapping = { + 0: 'Easy', + 1: 'Medium', + 2: 'Hard' + }; - // Get the corresponding difficulty level or 'N/A' if not found - const difficulty = modeMapping[mode] || ''; + const difficulty = modeMapping[mode] || ''; + const gameOutcome = win === 1 ? 'Win' : 'Game Over'; - // Determine game outcome based on win value - const gameOutcome = win === 1 ? 'Win' : (win === 0 ? 'Game Over' : ''); + const newLeaderboardItem = `| ${score} | ${difficulty} | [${issue.author.login} ${name}](${githubLink}) | ${message} | ${date} |\n`; + const newEntry = `| ${date} | [${issue.author.login} ${name}](${githubLink}) | ${message} | ${difficulty} | ${score} | ${gameOutcome} |`; - const newLeaderboardItem = `| ${score} | ${difficulty} | [${issue.author.login} ${name}](${githubLink}) | ${message} | ${date} |\n`; + const readmePath = 'README.md'; + let readme = fs.readFileSync(readmePath, 'utf8'); - const newEntry = `| ${date} | [${issue.author.login} ${name}](${githubLink}) | ${message} | ${difficulty} | ${score} | ${gameOutcome} |`; + // Update Recent Plays + const recentPlaysSection = /[\s\S]*?/.exec(readme); + if (recentPlaysSection) { + let recentPlaysContent = recentPlaysSection[0]; - const readmePath = 'README.md'; - let readme = fs.readFileSync(readmePath, 'utf8'); + let recentPlaysRows = recentPlaysContent + .split('\n') + .filter(row => row.startsWith('|') && !row.includes('Date | Player | Message | Game Mode | Score | Status ') && !row.includes('|------|--------|---------|-----------|-------|--------|')); - // Update Recent Plays - const recentPlaysSection = /[\s\S]*?/.exec(readme); - if (recentPlaysSection) { - let recentPlaysContent = recentPlaysSection[0]; + recentPlaysRows.unshift(newEntry); + if (recentPlaysRows.length > 20) { + recentPlaysRows = recentPlaysRows.slice(0, 20); + } - let recentPlaysRows = recentPlaysContent - .split('\n') - .filter(row => row.startsWith('|') && !row.includes('Date | Player | Message | Game Mode | Score | Status ') && !row.includes('|------|--------|---------|-----------|-------|--------|')); + const updatedRecentPlays = `\n| Date | Player | Message | Game Mode | Score | Status |\n|------|--------|---------|-----------|-------|--------|\n${recentPlaysRows.join('\n')}\n`; + readme = readme.replace(recentPlaysSection[0], updatedRecentPlays); + } + // Update Leaderboard + const leaderboardSection = /[\s\S]*?/.exec(readme); + if (leaderboardSection && win === 1) { + let leaderboardContent = leaderboardSection[0]; - recentPlaysRows.unshift(newEntry); + let leaderboardRows = leaderboardContent + .split('\n') + .filter(row => row.startsWith('|') && !row.includes('Score | Game Mode | Player | Message | Date') && !row.includes('|-------|-----------|--------|---------|------|')); - console.log("Current length of recentPlaysRows after sorting:", recentPlaysRows.length); - if (recentPlaysRows.length > 20) { - recentPlaysRows = recentPlaysRows.slice(0, 20); - } + leaderboardRows.unshift(newLeaderboardItem); + leaderboardRows.sort((a, b) => { + const scoreA = parseInt(a.split('|')[1].trim(), 10); + const scoreB = parseInt(b.split('|')[1].trim(), 10); + const dateA = new Date(a.split('|')[5].trim()); + const dateB = new Date(b.split('|')[5].trim()); - const updatedRecentPlays = `\n| Date | Player | Message | Game Mode | Score | Status |\n|------|--------|---------|-----------|-------|--------|\n${recentPlaysRows.join('\n')}\n`; - readme = readme.replace(recentPlaysSection[0], updatedRecentPlays); - } + return scoreB - scoreA || dateB - dateA; + }); - // Update Leaderboard - const leaderboardSection = /[\s\S]*?/.exec(readme); - if (leaderboardSection && win === 1 ) { - let leaderboardContent = leaderboardSection[0]; - leaderboardContent = leaderboardContent.replace(//, `${newLeaderboardItem}`); - - let leaderboardRows = leaderboardContent - .split('\n') - .filter(row => row.startsWith('|') && !row.includes('Score | Game Mode | Player | Message | Date') && !row.includes('|-------|-----------|--------|---------|------|')); - - leaderboardRows.sort((a, b) => { - const scoreA = a.match(/^\| (\d+) \|/); - const scoreB = b.match(/^\| (\d+) \|/); - const dateA = a.match(/\| (\d+) \| ([^|]+) \| ([^|]+) \| ([^|]+) \| ([^|]+) \|/)[5].trim(); - const dateB = b.match(/\| (\d+) \| ([^|]+) \| ([^|]+) \| ([^|]+) \| ([^|]+) \|/)[5].trim(); - - if (scoreB && scoreA) { - const scoreDiff = parseInt(scoreB[1]) - parseInt(scoreA[1]); - if (scoreDiff !== 0) { - return scoreDiff; - } + if (leaderboardRows.length > 20) { + leaderboardRows = leaderboardRows.slice(0, 20); } - return dateB.localeCompare(dateA); - }); - - console.log("Current length of leaderboardRows after sorting:", leaderboardRows.length); - - if (leaderboardRows.length > 20) { - leaderboardRows = leaderboardRows.slice(0, 20); + const updatedLeaderboard = `\n| Score | Game Mode | Player | Message | Date |\n|-------|-----------|--------|---------|------|\n${leaderboardRows.join('\n')}\n`; + readme = readme.replace(leaderboardSection[0], updatedLeaderboard); } - const updatedLeaderboard = `\n| Score | Game Mode | Player | Message | Date |\n|-------|-----------|--------|---------|------|\n${leaderboardRows.join('\n')}\n`; - readme = readme.replace(leaderboardSection[0], updatedLeaderboard); - } + fs.writeFileSync(readmePath, readme, 'utf8'); + console.log('README.md updated successfully.'); - fs.writeFileSync(readmePath, readme, 'utf8'); - console.log('README.md updated successfully.'); + return true; + } catch (error) { + console.error('Error:', error); + return false; + } }; diff --git a/.github/workflows/update_leaderboard.yml b/.github/workflows/update_leaderboard.yml index f80a870..ef86a0c 100644 --- a/.github/workflows/update_leaderboard.yml +++ b/.github/workflows/update_leaderboard.yml @@ -11,22 +11,28 @@ jobs: permissions: contents: write issues: write + pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Update leaderboard from comments + - name: Run updateLeaderboard script + id: update_leaderboard uses: actions/github-script@v7 with: script: | const updateLeaderboard = require('./.github/updateLeaderboard.js'); - updateLeaderboard({github, context}); + const result = await updateLeaderboard({ github, context }); + return result; - - name: Commit changes - run: | - git config --global user.name 'Github Actions' - git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add README.md - git commit -m ':sparkles: Update leaderboard' || echo "No changes to commit" - git push https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${{ github.repository }} HEAD:main + - name: Create Pull Request + if: steps.update_leaderboard.outputs.result == 'true' + uses: peter-evans/create-pull-request@v5 + with: + branch: update-leaderboard + commit-message: ':sparkles: Update leaderboard' + title: 'Update Leaderboard' + body: | + This PR updates the leaderboard based on the latest game results. + base: main