Created
September 30, 2018 09:03
-
-
Save hakatashi/b428d6e2db5d932a1a1f553933194fa9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const {promisify} = require('util'); | |
const {get} = require('lodash'); | |
(async () => { | |
const json = await promisify(fs.readFile)('dynamo-archive-sandbox-messages-201808280017.json'); | |
const data = json.toString().split('\n').filter((line) => line.length).map((line) => JSON.parse(line)); | |
data.sort((a, b) => a.ts.S.localeCompare(b.ts.S)); | |
const battles = []; | |
let timestamp = new Date(0); | |
let theme = ''; | |
let meanings = []; | |
let matches = null; | |
let url = ''; | |
for (const message of data) { | |
const user = get(message, ['bot_id', 'S']); | |
const ts = get(message, ['ts', 'S']); | |
const text = get(message, ['text', 'S'], ''); | |
const attachments = get(message, ['attachments', 'L'], []).map(({M}) => M); | |
if (text === 'たほいや') { | |
timestamp = new Date(parseFloat(ts) * 1000); | |
continue; | |
} | |
if (user !== 'B7PBPKTLP') { | |
continue; | |
} | |
if ((matches = text.match(/^\*(.+?)\* の正しい意味/m))) { | |
theme = matches[1]; | |
if ((matches = text.match(/^<(http.+?)>$/m))) { | |
url = matches[1]; | |
} | |
continue; | |
} | |
if (text.startsWith('今回の対戦結果')) { | |
meanings = attachments.map((attachment) => { | |
const title = get(attachment, ['title', 'S'], '').replace(/^\d+\. /, ''); | |
const textContent = get(attachment, ['text', 'S'], ''); | |
const info = {}; | |
if ((matches = title.match(/^(.+?) by <@(.+?)>$/))) { | |
info.text = matches[1]; | |
info.type = 'user'; | |
info.user = matches[2]; | |
} else if ((matches = title.match(/^(.+?) \((.+?)\)/))) { | |
info.text = matches[1]; | |
info.type = 'dummy'; | |
info.source = matches[2].includes(':') ? matches[2].split(':')[0].trim() : 'wikipedia'; | |
info.title = matches[2].includes(':') ? matches[2].split(':')[1].trim() : matches[2].trim(); | |
} else if ((matches = title.match(/^(.*?) :o:/))) { | |
info.text = matches[1]; | |
info.type = 'correct'; | |
} else { | |
console.log(title); | |
throw new Error(); | |
} | |
if (textContent === '-') { | |
info.betters = []; | |
} else { | |
matches = textContent.match(/<@.+?> \(.+?枚\)/g) || []; | |
info.betters = matches.map((match) => { | |
const submatches = match.match(/^<@(.+?)> \((.+?)枚\)$/); | |
return { | |
user: submatches[1], | |
coins: parseInt(submatches[2]), | |
}; | |
}); | |
} | |
return info; | |
}); | |
if (meanings.length !== 0) { | |
battles.push({timestamp, theme, meanings, url}); | |
} | |
} | |
} | |
await promisify(fs.writeFile)('battles.json', JSON.stringify(battles)); | |
console.log('done'); | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const battles = require('./tahoiya-data.json'); | |
const moment = require('moment'); | |
for (const [i, {timestamp, theme, meanings, url}] of battles.entries()) { | |
const users = meanings.filter(({type}) => type === 'user').map(({user}) => user); | |
const urlTitle = decodeURI(url.match(/([^/]+)$/)[1]); | |
const urlSource = url.startsWith('https://ja.wikipedia.org') ? 'Wikipedia' : 'ウィクショナリー日本語版' | |
console.log(` | |
# 第${i + 1}回 「**${theme}**」 | |
* **日時** ${moment(timestamp).utcOffset('+0900').format('YYYY-MM-DD HH:mm:ss')} | |
* **参加者** ${users.map((user) => `@${user}`).join(' ')} (${users.length}人) | |
${meanings.map((meaning, i) => `${i + 1}. ${meaning.text}`).join('\n')} | |
<details> | |
<summary>答え</summary> | |
${meanings.map((meaning, i) => { | |
let text = ''; | |
if (meaning.type === 'user') { | |
text = `${i + 1}. ${meaning.text} (@${meaning.user})`; | |
} else if (meaning.type === 'dummy') { | |
text = `${i + 1}. ${meaning.text} (${meaning.source}: ${meaning.title})`; | |
} else if (meaning.type === 'correct') { | |
text = `${i + 1}. ⭕️**${meaning.text}**`; | |
} | |
return text; | |
}).join('\n')} | |
出典: [${urlTitle} - ${urlSource}](${url}) | |
</details> | |
`.replace(/^\t+/gm, '')); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const battles = require('./battles.json'); | |
const moment = require('moment'); | |
const ratings = new Map(); | |
let previousTimestamp = null; | |
for (const [i, {timestamp, meanings}] of battles.entries()) { | |
if (previousTimestamp === timestamp) { | |
continue; | |
} | |
const users = meanings.filter(({user}) => user).map(({user}) => user); | |
const newRatings = new Map(users.map((user) => [user, 0])); | |
const correctMeaningIndex = meanings.findIndex(({type}) => type === 'correct'); | |
for (const user of users) { | |
const betMeaning = meanings.findIndex(({betters}) => betters.some((bet) => bet.user === user)); | |
const bet = betMeaning !== -1 ? meanings[betMeaning].betters.find((bet) => bet.user === user) : []; | |
const betting = betMeaning !== -1 ? {meaning: betMeaning, coins: bet.coins} : {meaning: null, coins: 1}; | |
if (betting.meaning === correctMeaningIndex) { | |
newRatings.set(user, newRatings.get(user) + betting.coins); | |
} else { | |
newRatings.set(user, newRatings.get(user) - betting.coins - 1); | |
if (betting.meaning !== null) { | |
const misdirectedUser = meanings[betting.meaning].user; | |
if (misdirectedUser) { | |
newRatings.set(misdirectedUser, newRatings.get(misdirectedUser) + betting.coins); | |
} | |
} | |
} | |
} | |
for (const [user, rating] of newRatings.entries()) { | |
if (!ratings.has(user)) { | |
ratings.set(user, []); | |
} | |
ratings.get(user).push({timestamp, rating}); | |
} | |
previousTimestamp = timestamp; | |
} | |
const data = {}; | |
for (const [user, rating] of ratings.entries()) { | |
data[user] = rating.slice(-5); | |
} | |
console.log(JSON.stringify(data)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment