using System; using System.Collections.Generic; using System.Linq; using Dapper; using FSO.Server.Common; namespace FSO.Server.Database.DA.Elections { public class SqlElections : AbstractSqlDA, IElections { public SqlElections(ISqlContext context) : base(context) { } public DbElectionCandidate GetCandidate(uint avatar_id, uint cycle_id, DbCandidateState state) { return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE candidate_avatar_id = @avatar_id " + "AND election_cycle_id = @cycle_id AND state = @state", new { avatar_id, cycle_id, state = state.ToString() }).FirstOrDefault(); } public List GetCandidates(uint cycle_id, DbCandidateState state) { return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE election_cycle_id = @cycle_id AND state = @state", new { cycle_id, state = state.ToString() }).ToList(); } public List GetCandidates(uint cycle_id) { return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE election_cycle_id = @cycle_id", new { cycle_id }).ToList(); } public List GetActiveCycles(int shard_id) { return Context.Connection.Query("SELECT *, n.neighborhood_id AS 'nhood_id' " + "FROM fso_election_cycles JOIN fso_neighborhoods n ON election_cycle_id = cycle_id " + "WHERE current_state != 'shutdown' " + "AND cycle_id IN (SELECT election_cycle_id FROM fso_neighborhoods WHERE shard_id = @shard_id)", new { shard_id }).ToList(); } public DbElectionCycle GetCycle(uint cycle_id) { return Context.Connection.Query("SELECT * FROM fso_election_cycles WHERE cycle_id = @cycle_id", new { cycle_id = cycle_id }).FirstOrDefault(); } public List GetCycleVotes(uint cycle_id, DbElectionVoteType type) { return Context.Connection.Query("SELECT * FROM fso_election_votes WHERE election_cycle_id = @cycle_id AND type = @type", new { cycle_id = cycle_id, type = type.ToString() }).ToList(); } public List GetCycleVotesForAvatar(uint avatar_id, uint cycle_id, DbElectionVoteType type) { return Context.Connection.Query("SELECT * FROM fso_election_votes WHERE election_cycle_id = @cycle_id AND type = @type " + "AND target_avatar_id = @avatar_id", new { avatar_id = avatar_id, cycle_id = cycle_id, type = type.ToString() }).ToList(); } public DbElectionVote GetMyVote(uint avatar_id, uint cycle_id, DbElectionVoteType type) { //this isn't as straightforward as you might think. //we also need to include votes from: // - other sims on our user // - other sims on other users that share login ip //note that this criteria is duplicated in the database in the form of a BEFORE INSERT check. var query = "SELECT * from fso_election_votes v INNER JOIN fso_avatars va ON v.from_avatar_id = va.avatar_id " + "WHERE v.election_cycle_id = @cycle_id AND v.type = @type AND va.user_id IN " + "(SELECT user_id FROM fso_users WHERE last_ip = " + "(SELECT last_ip FROM fso_avatars a JOIN fso_users u on a.user_id = u.user_id WHERE avatar_id = @avatar_id)" + ")"; return Context.Connection.Query(query, new { avatar_id = avatar_id, cycle_id = cycle_id, type = type.ToString() }).FirstOrDefault(); } public bool CreateCandidate(DbElectionCandidate candidate) { try { var result = Context.Connection.Execute("INSERT INTO fso_election_candidates (election_cycle_id, candidate_avatar_id, comment) " + "VALUES (@election_cycle_id, @candidate_avatar_id, @comment)", candidate); return (result > 0); } catch (Exception) { return false; } } public bool SetCandidateState(DbElectionCandidate candidate) { try { var result = Context.Connection.Execute("UPDATE fso_election_candidates SET state = @state, comment = @comment " + "WHERE election_cycle_id = @election_cycle_id AND candidate_avatar_id = @candidate_avatar_id" , new { state = candidate.state.ToString(), candidate.comment, candidate.election_cycle_id, candidate.candidate_avatar_id}); return (result > 0); } catch (Exception) { return false; } } public bool DeleteCandidate(uint election_cycle_id, uint candidate_avatar_id) { try { var result = Context.Connection.Execute("DELETE FROM fso_election_candidates " + "WHERE election_cycle_id = @election_cycle_id AND candidate_avatar_id = @candidate_avatar_id", new { election_cycle_id = election_cycle_id, candidate_avatar_id = candidate_avatar_id }); return (result > 0); } catch (Exception) { return false; } } public uint CreateCycle(DbElectionCycle cycle) { var result = Context.Connection.Query("INSERT INTO fso_election_cycles (start_date, end_date, current_state, election_type) " + "VALUES (@start_date, @end_date, @current_state, @election_type); SELECT LAST_INSERT_ID();", new { cycle.start_date, cycle.end_date, current_state = cycle.current_state.ToString(), election_type = cycle.election_type.ToString() }).FirstOrDefault(); return result; } public bool CreateVote(DbElectionVote vote) { try { var result = Context.Connection.Execute("INSERT INTO fso_election_votes (election_cycle_id, from_avatar_id, type, target_avatar_id, date) " + "VALUES (@election_cycle_id, @from_avatar_id, @type, @target_avatar_id, @date)", new { vote.election_cycle_id, vote.from_avatar_id, type = vote.type.ToString(), vote.target_avatar_id, vote.date }); return (result > 0); } catch (Exception) { return false; } } public void UpdateCycleState(uint cycle_id, DbElectionCycleState state) { Context.Connection.Query("UPDATE fso_election_cycles SET current_state = @state WHERE cycle_id = @cycle_id", new { cycle_id = cycle_id, state = state.ToString() }).ToList(); } public DbMayorRating GetSpecificRating(uint from_user_id, uint to_avatar_id) { return Context.Connection.Query("SELECT * FROM fso_mayor_ratings WHERE from_user_id = @from_user_id " + "AND to_avatar_id = @to_avatar_id", new { from_user_id = from_user_id, to_avatar_id = to_avatar_id }).FirstOrDefault(); } public DbMayorRating GetRating(uint rating_id) { return Context.Connection.Query("SELECT * FROM fso_mayor_ratings WHERE rating_id = @rating_id ", new { rating_id = rating_id }).FirstOrDefault(); } public List GetRatings(uint to_avatar_id) { return Context.Connection.Query("SELECT rating_id FROM fso_mayor_ratings WHERE to_avatar_id = @to_avatar_id ORDER BY rating", new { to_avatar_id = to_avatar_id }).ToList(); } public float? GetAvgRating(uint to_avatar_id) { return Context.Connection.Query("SELECT AVG(CAST(rating as DECIMAL(10,6))) FROM fso_mayor_ratings WHERE to_avatar_id = @to_avatar_id", new { to_avatar_id = to_avatar_id }).FirstOrDefault(); } public uint SetRating(DbMayorRating rating) { //first let's try insert our rating. try { var result = Context.Connection.Execute("INSERT INTO fso_mayor_ratings (from_user_id, to_user_id, rating, comment, " + "date, from_avatar_id, to_avatar_id, anonymous, neighborhood) " + "VALUES (@from_user_id, @to_user_id, @rating, @comment, " + "@date, @from_avatar_id, @to_avatar_id, @anonymous, @neighborhood)", rating); return 0; } catch (Exception) { //didn't work? probably because the rating is already there. try updating instead. Context.Connection.Execute("UPDATE fso_mayor_ratings SET rating = @rating, comment = @comment, date = @date " + "WHERE from_user_id = @from_user_id AND to_user_id = @to_user_id", rating); var id = Context.Connection.Query("SELECT rating_id FROM fso_mayor_ratings WHERE from_user_id = @from_user_id " + "AND to_user_id = @to_user_id", rating).FirstOrDefault(); return id; } } public bool DeleteRating(uint id) { var result = Context.Connection.Execute("DELETE FROM fso_mayor_ratings " + "WHERE rating_id = @id", new { id = id }); return (result > 0); } public bool EmailRegistered(DbElectionCycleMail p) { return Context.Connection.Query("SELECT count(*) FROM fso_election_cyclemail WHERE cycle_id = @cycle_id AND avatar_id = @avatar_id AND cycle_state = @cycle_state", new { p.avatar_id, p.cycle_id, cycle_state = p.cycle_state.ToString() }).First() > 0; } public bool TryRegisterMail(DbElectionCycleMail p) { try { return (Context.Connection.Execute("INSERT INTO fso_election_cyclemail (cycle_id, avatar_id, cycle_state) VALUES (@cycle_id, @avatar_id, @cycle_state)", new { p.avatar_id, p.cycle_id, cycle_state = p.cycle_state.ToString() }) > 0); } catch { //already exists, or foreign key fails return false; } } public bool EnrollFreeVote(DbElectionFreeVote entry) { try { return (Context.Connection.Execute("INSERT INTO fso_election_freevotes (avatar_id, neighborhood_id, cycle_id, date, expire_date) " + "VALUES (@avatar_id, @neighborhood_id, @cycle_id, @date, @expire_date)", entry) > 0); } catch { //already exists, or foreign key fails return false; } } public DbElectionFreeVote GetFreeVote(uint avatar_id) { var result = Context.Connection.Query("SELECT * FROM fso_election_freevotes WHERE avatar_id = @avatar_id", new { avatar_id }).FirstOrDefault(); if (result != null && result.expire_date < Epoch.Now) { //outdated. delete and set null. try { Context.Connection.Execute("DELETE FROM fso_election_freevotes WHERE avatar_id = @avatar_id", new { avatar_id }); } catch (Exception) { } result = null; } return result; } public DbElectionWin FindLastWin(uint avatar_id) { return Context.Connection.Query("SELECT n.neighborhood_id AS nhood_id, n.name AS nhood_name " + "FROM (fso_election_candidates e JOIN fso_election_cycles c ON e.election_cycle_id = c.cycle_id) " + "JOIN fso_neighborhoods n ON c.neighborhood_id = n.neighborhood_id " + "WHERE e.candidate_avatar_id = @avatar_id AND state = 'won' " + "ORDER BY e.election_cycle_id DESC LIMIT 1", new { avatar_id = avatar_id }).FirstOrDefault(); } } }