-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodingame_crawl.rb
executable file
·110 lines (93 loc) · 3.08 KB
/
codingame_crawl.rb
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#! /usr/bin/env ruby
require 'json'
require 'set'
REMEMBERME = ENV['COOKIE']
USER_ID = 2802859
def request(method: 'POST', endpoint: nil, data: nil)
req = [
'curl',
'-sSL',
'-X', method,
endpoint,
'-H', '"Content-Type: application/json"',
'-d', JSON.dump(data),
'--cookie', "'rememberMe=#{REMEMBERME}'",
].join(' ')
JSON.parse(`#{req}`)
end
def formatted(pb)
pb['title'][0..27].ljust(30) +
pb['solvedCount'].to_s.rjust(6) + " " +
"https://www.codingame.com#{pb['detailsPageUrl']}"
end
def by_language(all_problems)
easiest = all_problems.select { |p| p['level'] == 'easy' || p['level'] == 'tutorial' }.sort_by { |p| p['solvedCount'] }.last(20).reverse
progress = request(
endpoint: 'https://www.codingame.com/services/Puzzle/findProgressByIds',
data: [easiest.map { |p| p['id'] }, USER_ID, 2],
)
by_language = Hash.new { |h, k| h[k] = Set.new() }
progress.each do |pb|
submissions = request(
endpoint: 'https://www.codingame.com/services/TestSessionQuestionSubmission/findAllSubmissions',
data: [pb['testSessionHandle']],
)
submissions.each do |submission|
next unless submission['score'] == 100
by_language[submission['programmingLanguageId']] << pb['id']
end
end
by_language.each do |lang, solved|
next if solved.size >= 15
next_up = easiest.select { |pb| !solved.include?(pb['id']) }.map { |pb| pb['id'] }
next_up = next_up.map { |id| progress.find { |pb| pb['id'] == id } }
puts "#{lang.ljust(15)} (#{solved.size}):"
next_up.first(5).each { |pb| puts "\t#{formatted(pb)}" }
end
end
all_problems = request(
endpoint: 'https://www.codingame.com/services/Puzzle/findAllMinimalProgress',
data: [USER_ID],
)
if (ARGV.include?('--lang'))
by_language(all_problems)
exit 0
end
levels = all_problems.map { |r| r['level'] }.uniq
unsolved = {}
c = {}
ids = []
levels.each do |l|
problems = all_problems.select do |problem|
problem['level'] == l && problem['validatorScore'] < 100
end
c[l] = {
total: all_problems.count { |p| p['level'] == l },
unsolved: problems.size,
}
c[l][:solved] = c[l][:total] - c[l][:unsolved]
unsolved[l] = problems
ids += problems.sort_by { |p| p['solvedCount'] }.last(5).map { |p| p['id'] }
ids += problems.sort_by { |p| p['creationTime'] }.last(5).map { |p| p['id'] }
end
ids.uniq!
res = request(
endpoint: 'https://www.codingame.com/services/Puzzle/findProgressByIds',
data: [ids, USER_ID, 2],
)
c.keys.sort_by { |l| -c[l][:unsolved] }.each do |l|
problems = unsolved[l]
next if l == 'optim' || l == 'multi'
next if problems.empty?
solved_percent = (100 * c[l][:solved] / c[l][:total]).round
puts "\n#{l}\t\t#{solved_percent}% solved\t#{c[l][:unsolved]} / #{c[l][:total]} left\n\n"
problems.sort_by { |p| p['solvedCount'] }.last(5).reverse_each do |problem|
pb = res.find { |e| e['id'] == problem['id'] }
puts formatted(pb)
end
puts "\n\tNewest:"
problems.sort_by { |p| p['creationTime'] }.last(5).reverse_each do |problem|
pb = res.find { |e| e['id'] == problem['id'] }
puts "\t#{formatted(pb)}"
end
end