package de.tud.kom.socom.web.server.database.achievement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import de.tud.kom.socom.web.client.sharedmodels.Achievement;
import de.tud.kom.socom.web.client.sharedmodels.AchievementGame;
import de.tud.kom.socom.web.client.sharedmodels.AchievementLevel;
import de.tud.kom.socom.web.client.sharedmodels.AchievementProgress;
import de.tud.kom.socom.web.client.sharedmodels.AchievementReward;
import de.tud.kom.socom.web.client.sharedmodels.GlobalConfig;
import de.tud.kom.socom.web.server.database.HSQLAccess;
public class HSQLAchievementDatabaseAccess implements
AchievementDatabaseAccess, GlobalConfig {
private static AchievementDatabaseAccess instance = new HSQLAchievementDatabaseAccess();
private static HSQLAccess db;
private HSQLAchievementDatabaseAccess() {
db = HSQLAccess.getInstance();
}
public static AchievementDatabaseAccess getInstance() {
return instance;
}
@Override
public List<AchievementGame> getGames(long userID) throws SQLException {
List<AchievementGame> games = new ArrayList<AchievementGame>();
PreparedStatement selectGamesQuery =
db.getPreparedStatement("SELECT games.gameid, games.name " +
"FROM games, achievement " +
"WHERE games.gameid = achievement.gameid " +
"GROUP BY games.gameid;");
ResultSet result = selectGamesQuery.executeQuery();
while(result.next()) {
long gameID = result.getLong("gameid");
List<Achievement> achievements = getAchievements(userID, gameID);
AchievementGame game = new AchievementGame(
gameID,
result.getString("name"),
achievements);
games.add(game);
}
return games;
}
private List<Achievement> getAchievements(long userID, long gameID) throws SQLException {
PreparedStatement selectAllAchievementsQuery =
db.getPreparedStatement("SELECT * " +
"FROM achievement " +
"WHERE gameid = ?;");
selectAllAchievementsQuery.setLong(1, gameID);
ResultSet result = selectAllAchievementsQuery.executeQuery();
List<Achievement> achievements = new ArrayList<Achievement>();
while(result.next()) {
long achievementID = result.getLong("achievementid");
String categoryName = getAchievementCategoryName(result.getLong("categoryid"));
List<AchievementLevel> levels = getAchievementLevels(achievementID);
AchievementProgress progress = getAchievementProgress(userID, achievementID, levels);
int currentRewardPoints = getCurrentRewardPoints(levels, progress.getCurrentLevel());
Achievement achievement = new Achievement(
achievementID,
gameID,
levels.get(levels.size() - 1).getCounterMax(),
result.getString("name"),
result.getString("description"),
result.getString("image"),
categoryName,
currentRewardPoints,
levels,
progress);
achievements.add(achievement);
}
return achievements;
}
private String getAchievementCategoryName(long categoryID) throws SQLException {
PreparedStatement selectQuery =
db.getPreparedStatement("SELECT * " +
"FROM achievementcategory " +
"WHERE categoryid = ? ");
selectQuery.setLong(1, categoryID);
ResultSet result = selectQuery.executeQuery();
if(!result.next()) {
return "";
}
return result.getString("name");
}
private List<AchievementLevel> getAchievementLevels(long achievementID)
throws SQLException {
List<AchievementLevel> levels = new ArrayList<AchievementLevel>();
PreparedStatement selectQuery =
db.getPreparedStatement("SELECT * " +
"FROM achievementlevel " +
"WHERE achievementid = ? " +
"ORDER BY level ASC;");
selectQuery.setLong(1, achievementID);
ResultSet result = selectQuery.executeQuery();
while(result.next()) {
long levelID = result.getLong("levelid");
List<AchievementReward> rewards = getRewards(levelID);
AchievementLevel level = new AchievementLevel(
result.getLong("levelid"),
achievementID,
result.getLong("countermax"),
result.getInt("level"),
result.getInt("rewardpoints"),
rewards);
levels.add(level);
}
return levels;
}
private List<AchievementReward> getRewards(long levelID)
throws SQLException {
List<AchievementReward> rewards = new ArrayList<AchievementReward>();
PreparedStatement selectQuery =
db.getPreparedStatement("SELECT achievementreward.* " +
"FROM achievementreward, achievementrewardrelations " +
"WHERE achievementrewardrelations.rewardid = achievementreward.rewardid " +
"AND achievementrewardrelations.levelid = ?;");
selectQuery.setLong(1, levelID);
ResultSet result = selectQuery.executeQuery();
while(result.next()) {
AchievementReward reward = new AchievementReward(
result.getLong("rewardid"),
result.getLong("value"),
result.getString("name"),
result.getString("description"));
rewards.add(reward);
}
return rewards;
}
private AchievementProgress getAchievementProgress(long userID, long achievementID,
List<AchievementLevel> levels) throws SQLException {
PreparedStatement selectQuery = db
.getPreparedStatement("SELECT * " +
"FROM achievementprogress " +
"WHERE userid = ? " +
"AND achievementid = ?;");
selectQuery.setLong(1, userID);
selectQuery.setLong(2, achievementID);
ResultSet result = selectQuery.executeQuery();
AchievementLevel maxLevel = levels.get(levels.size() - 1);
AchievementProgress progress;
if(result.next()) {
long counter = result.getLong("counter");
AchievementLevel currentLevel = getCurrentAchievementLevel(levels, counter);
progress = new AchievementProgress(
userID,
achievementID,
counter,
currentLevel.getCounterMax(),
result.getTimestamp("timeCompleted"),
result.getBoolean("isCompleted"),
currentLevel.getLevel(),
maxLevel.getLevel());
}
else {
AchievementLevel firstLevel = levels.get(0);
progress = new AchievementProgress(
userID,
achievementID,
0,
firstLevel.getCounterMax(),
null,
false,
1,
maxLevel.getLevel());
}
return progress;
}
private AchievementLevel getCurrentAchievementLevel(List<AchievementLevel> levels, long counter)
throws SQLException {
for(AchievementLevel level : levels) {
if(counter < level.getCounterMax()) {
return level;
}
}
return levels.get(levels.size() - 1);
}
private int getCurrentRewardPoints(List<AchievementLevel> levels, int currentLevel) {
int currentRewardPoints = 0;
for(int i = 0; i < (currentLevel - 1); i++) {
currentRewardPoints += levels.get(i).getRewardPoints();
}
return currentRewardPoints;
}
}