-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsweepstakes.ts
84 lines (72 loc) · 2.17 KB
/
sweepstakes.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { readFileSync, writeFileSync } from 'fs'
import { parse } from 'csv-parse/sync'
const IGNORE_USERS = './data/ignoreUsers.txt'
const OUTPUT_FILE = './data/winners.json'
type Profile = {
id: number
email: string
point: number
ticket: number
}
function readFile(filePath: string): string | null {
try {
return readFileSync(filePath, 'utf-8')
} catch {
return null
}
}
function readProfileCsv(filePath: string): Profile[] {
const buf = readFileSync(filePath, 'utf-8')
let profiles: Profile[] = parse(buf, { columns: true })
if (profiles.length === 0) {
throw new Error('no data')
}
const { id, email } = profiles[0]
if (!id || !email) {
throw new Error('missing required fields')
}
const ignoreUsres = readFile(IGNORE_USERS)?.split('\n')
if (!ignoreUsres) {
return profiles
}
profiles = profiles.filter((p) => !ignoreUsres.includes(p.email))
const prevResult = readFile(OUTPUT_FILE)
if (!prevResult) {
return profiles
}
const buf2: Profile[] = JSON.parse(prevResult)
const winners = buf2.map(({ email }) => email)
return profiles.filter((p) => !winners.includes(p.email))
}
async function main() {
const [filePath, numWinners] = process.argv.slice(2)
if (!filePath) {
console.info(
'Usage: yarn run --silent sweepstakes [filePath] [numOfWinners]\n\n',
)
throw new Error('filepath is required.')
}
let profiles = readProfileCsv(filePath).filter((i) => i.ticket > 0)
const n = parseInt(numWinners)
if (isNaN(n)) {
throw new Error('numOfWinners is not a number.')
}
const winners: Profile[] = []
for (let i = 0; i < n; i++) {
const candidates: Profile[] = []
profiles.forEach((p) => {
for (let j = 0; j < p.ticket; j++) {
candidates.push(p)
}
})
const winner = candidates[Math.floor(Math.random() * candidates.length)]
winners.push(winner)
profiles = profiles.filter((p) => p.id !== winner.id)
}
const winnersView = winners
.sort((a, b) => a.id - b.id)
.map((p) => ({ id: p.id, email: p.email, point: p.point }))
console.info(JSON.stringify(winnersView, null, ' '))
writeFileSync(OUTPUT_FILE, JSON.stringify(winnersView))
}
main()