-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdatabase_persistence.rb
142 lines (114 loc) · 3.66 KB
/
database_persistence.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
require 'pg'
class DatabasePersistence
def initialize
@db = connect_to_database
end
def disconnect
db.close
end
def query(statement, *params)
db.exec_params(statement, params)
end
def get_players
sql = <<~SQL
SELECT * FROM players;
SQL
result = query(sql)
result.map do |tuple|
{ name: tuple['name'], id: tuple['id'] }
end
end
def add_player(name)
sql = "INSERT INTO players (name) VALUES ($1);"
query(sql, name)
end
def get_leaderboard_stats
sql = <<~SQL
SELECT matches.player_id, players.name AS name, COUNT(matches.player_id) AS matches_played,
(SELECT winners FROM (SELECT player_id, COUNT(placement) AS winners FROM matches WHERE placement = 1 GROUP BY player_id) AS win_count WHERE win_count.player_id = matches.player_id) AS wins,
ROUND(AVG(matches.placement)) AS avg_place, SUM(points.point_value) AS total_points,
SUM(matches.eliminations) AS total_elim, ROUND(AVG(matches.eliminations)) AS avg_elim
FROM players JOIN matches ON players.id = matches.player_id
JOIN points ON points.id = matches.point_id
GROUP BY players.name, matches.player_id
ORDER BY total_points DESC;
SQL
result = query(sql)
result.map do |tuple|
leaderboard_hash(tuple)
end
end
def get_overall_stats(id)
sql = <<~SQL
SELECT players.name AS name, COUNT(matches.player_id) AS matches_played,
(SELECT COUNT(placement) FROM matches WHERE placement = 1 AND player_id = $1) AS wins,
ROUND(AVG(matches.placement)) AS avg_place, SUM(points.point_value) AS total_points,
SUM(matches.eliminations) AS total_elim, ROUND(AVG(matches.eliminations)) AS avg_elim
FROM players JOIN matches ON players.id = matches.player_id
JOIN points ON points.id = matches.point_id
WHERE players.id = $1
GROUP BY players.name
ORDER BY total_points;
SQL
result = query(sql, id)
result.map do |tuple|
leaderboard_hash(tuple)
end
end
def get_player_matches(id)
sql = <<~SQL
SELECT matches.placement, points.point_value,
matches.eliminations
FROM matches JOIN points
ON points.id = matches.point_id
WHERE matches.player_id = $1
ORDER BY date_played;
SQL
result = query(sql, id)
result.map do |tuple|
match_stats(tuple)
end
end
def add_match_data(player_id, placement, elims)
point_id = get_point_id(placement)
sql = <<~SQL
INSERT INTO matches
(player_id, point_id, placement, eliminations)
VALUES ($1, $2, $3, $4);
SQL
query(sql, player_id, point_id, placement, elims)
end
def get_player_name(id)
sql = "SELECT name FROM players WHERE $1 = id;"
result = query(sql, id)
result.map { |tuple| tuple['name'] }.first
end
private
attr_reader :db
def connect_to_database
if Sinatra::Base.production?
PG.connect(ENV['DATABASE_URL'])
else
PG.connect(dbname: "solo_test")
end
end
def leaderboard_hash(tuple)
{ name: tuple['name'],
matches: tuple['matches_played'].to_i,
wins: tuple['wins'].to_i,
avg_place: tuple['avg_place'].to_i,
points: tuple['total_points'].to_i,
total_elim: tuple['total_elim'].to_i,
avg_elim: tuple['avg_elim'].to_i }
end
def match_stats(tuple)
{ place: tuple['placement'],
points: tuple['point_value'],
elims: tuple['eliminations'] }
end
def get_point_id(placement)
sql = "SELECT id FROM points WHERE ($1)::integer <@ place;"
result = query(sql, placement)
result.map { |tuple| tuple['id'] }.first.to_i
end
end