Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Poll Options #1

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions backend/API/Controllers/PollController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Dab.API.Models.Poller;
using Dab.API.Models;


namespace Dab.API.Controllers;

/// <summary>
Expand Down Expand Up @@ -76,6 +77,7 @@ public async Task<IActionResult> GetAllPolls(int page = 1, int pageSize = 10, st
.Take(pageSize)
.ToList();


var nPages = (int)Math.Ceiling(totalItems / (double)pageSize);

var ret = new PagedResult<PollDTO>
Expand All @@ -86,6 +88,7 @@ public async Task<IActionResult> GetAllPolls(int page = 1, int pageSize = 10, st
TotalItems = totalItems,
};


return Ok(ret);
}
catch (Exception e)
Expand Down Expand Up @@ -133,7 +136,7 @@ public async Task<IActionResult> GetPoll(string pollId, bool ignoreCache = false
try
{
var result = await _pollService.GetPoll(pollId, ignoreCache);
var votesDTO = _mapper.Map<PollDTO>(result);
var votesDTO = _mapper.Map<PollDTO>(result); //result.PollOptions.Select(e => new PollOptionDTO(e));
var ret = new ServiceResult { HasErrors = false, JsonString = Utils.JsonPrettify(votesDTO) };
return Ok(ret);
}
Expand Down Expand Up @@ -304,7 +307,7 @@ public async Task<IActionResult> GetPollVotes(
int pageSize = 10,
string? search = null,
bool sortByPollingPower = false,
PollOptions? actionFilter = null,
string? actionFilter = null,
bool ignoreCache = false)
{
try
Expand All @@ -321,18 +324,11 @@ public async Task<IActionResult> GetPollVotes(
}

// Apply action filter if provided
if (actionFilter.HasValue)
if (!string.IsNullOrEmpty(actionFilter))
{
var actionString = actionFilter.Value switch
{
PollOptions.Approve => "approved",
PollOptions.Reject => "refused",
PollOptions.Abstain => "abstention",
_ => throw new ArgumentOutOfRangeException()
};

votesDTO = votesDTO
.Where(v => v.Action.Equals(actionString, StringComparison.OrdinalIgnoreCase))
.Where(v => v.Action.Equals(actionFilter, StringComparison.OrdinalIgnoreCase))
.ToList();
}

Expand Down
7 changes: 3 additions & 4 deletions backend/API/Models/AccountVoteStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ public class AccountVoteStats
{
public string Account { get; set; } = "";
public int TotalVotes { get; set; }
public int VotesYes { get; set; }
public int VotesNo { get; set; }
public int Abstentions { get; set; }
public decimal CurrentPollingPower {get; set;}
public int OngoingVotes {get; set;}
public int VotesWon {get; set;}
public int VotesLost {get; set;}
// public int EndedPolls {get; set;}
// public int ApprovedPolls {get; set;}
// public int RejectedPolls {get; set;}
Expand Down
57 changes: 20 additions & 37 deletions backend/API/Models/Poller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,15 @@ public class Poll
[JsonPropertyName("bond-id")]
public string BondId { get; set; } = "";

[JsonPropertyName("votes-yes")]
public JsonElement _votesYes { get; set; }

[JsonPropertyName("votes-no")]
public JsonElement _votesNo { get; set; }

[JsonPropertyName("votes-abstentions")]
public JsonElement _votesAbstentions { get; set; }
[JsonPropertyName("options")]
public List<PollOption> PollOptions {get; set;} = new();

[JsonPropertyName("election-end")]
public PactDateTimeP ElectionEnd { get; set; } = new();

[JsonPropertyName("election-start")]
public PactDateTimeP ElectionStart { get; set; } = new();

public decimal VotesYes
{
get { return Utils.GetDecimal(_votesYes); }
}

public decimal VotesNo
{
get { return Utils.GetDecimal(_votesNo); }
}

public decimal VotesAbstentions
{
get { return Utils.GetDecimal(_votesAbstentions); }
}

[JsonPropertyName("number-votes")]
public JsonElement _numberVotes { get; set; }
public decimal NumberVotes { get { return Utils.GetInteger(_numberVotes); }}
Expand All @@ -66,15 +45,28 @@ public decimal VotesAbstentions
public JsonElement _quorum { get; set; }
public decimal Quorum { get { return Utils.GetDecimal(_quorum); }}

}

public class PollOption
{

[JsonPropertyName("option-name")]
public string _optionName { get; set; } = "";
public string OptionName { get { return _optionName; }}
[JsonPropertyName("option-index")]
public JsonElement index {get; set;}
public decimal OptionIndex { get { return Utils.GetInteger(index); }}
[JsonPropertyName("votes-polling-power")]
public JsonElement _votesPollingPower {get; set;}
public decimal VotesPollingPower { get { return Utils.GetDecimal(_votesPollingPower); }}
}


public enum PollStatus
{
Open = 0,
Approved = 1,
Refused = 2,
Review = 3
Closed = 1,
Review = 2
}

public class PollDTO
Expand All @@ -85,9 +77,7 @@ public class PollDTO
public string PollId { get; set; } = "";
public DateTime CreationTime { get; set; }
public string BondId { get; set; } = "";
public decimal VotesYes { get; set; }
public decimal VotesNo { get; set; }
public decimal VotesAbstentions { get; set; }
public List<PollOption> PollOptions { get; set; } = new();
public DateTime ElectionStart { get; set; }
public DateTime ElectionEnd { get; set; }
public decimal Quorum {get; set;}
Expand All @@ -106,7 +96,7 @@ public PollStatus Status
return PollStatus.Open;
}

return VotesYes > VotesNo ? PollStatus.Approved : PollStatus.Refused;
return PollStatus.Closed;
}
}
}
Expand Down Expand Up @@ -139,13 +129,6 @@ public decimal PollingPower
}
}

public enum PollOptions
{
Approve,
Reject,
Abstain
}

public class PollVoteDTO
{
public string BondId { get; set; } = "";
Expand Down
29 changes: 13 additions & 16 deletions backend/API/Services/AnalyticsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,32 +166,35 @@ public async Task<decimal> GetBondTVL(bool ignoreCache = false)

}


public async Task<string> GetMostVotedPoll(bool ignoreCache = false)
{
try
{
var allPolls = await _pollService.GetAllPolls(ignoreCache);

var maxVotes = allPolls.OrderByDescending(p => p.VotesNo + p.VotesYes + p.VotesAbstentions).FirstOrDefault();
// Get the poll with the maximum total votes
var maxVotesPoll = allPolls.OrderByDescending(p => p.PollOptions.Sum(o => o.VotesPollingPower)).FirstOrDefault();

if (maxVotes == null)
if (maxVotesPoll == null)
{
return "No polls available";
}

string formattedPollId = maxVotes.PollId.Length > 6
? $"{maxVotes.PollId.Substring(0, 3)}...{maxVotes.PollId.Substring(maxVotes.PollId.Length - 3)}"
: maxVotes.PollId;
string formattedPollId = maxVotesPoll.PollId.Length > 6
? $"{maxVotesPoll.PollId.Substring(0, 3)}...{maxVotesPoll.PollId.Substring(maxVotesPoll.PollId.Length - 3)}"
: maxVotesPoll.PollId;

var totalVotes = maxVotes.VotesNo + maxVotes.VotesYes + maxVotes.VotesAbstentions;
var totalVotes = maxVotesPoll.PollOptions.Sum(o => o.VotesPollingPower);
return $"{formattedPollId} ({totalVotes:N0} VP)";
}
catch (Exception e)
catch (Exception)
{
return "No polls available";
}
}


public async Task<string> GetAverageLockup(bool ignoreCache = false)
{
var allLockups = await _bondService.GetAllLockupEvents(ignoreCache);
Expand Down Expand Up @@ -498,16 +501,10 @@ public async Task<List<VoteDistributionDTO>> GetPollNumberofVotes(string pollId,
var allVotes = await _pollService.GetPollVotes(pollId, ignoreCache);

var voteDistribution = allVotes
.GroupBy(vote => vote.Action.ToLower())
.GroupBy(vote => vote.Action)
.Select(group => new VoteDistributionDTO
{
Type = group.Key switch
{
"approved" => "Yes",
"refused" => "No",
"abstention" => "Abstention",
_ => "Unknown"
},
Type = group.Key,
VoteCount = group.Count(),
PollingPower = group.Sum(vote => vote.PollingPower)
})
Expand Down Expand Up @@ -585,7 +582,7 @@ public async Task<List<LockupDistributionDTO>> GetLockupDistributions(string bon
.GroupBy(lockup => lockup.LockupLength)
.Select(group => new LockupDistributionDTO
{
OptionName = Utils.GetOptionName(bond, group.Key),
OptionName = Utils.GetOptionName(bond, group.Key),
OptionLength = group.First().LockupLength,
LockupCount = group.Count(),
Amount = group.Sum(lockup => lockup.Amount)
Expand Down
33 changes: 20 additions & 13 deletions backend/API/Services/PollService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Text.Json;
using Dab.API.Interfaces;
using Dab.API.Models;
using Dab.API.Models.Poller;
using Dab.API.Models.Cache;
using Dab.API.AppSettings;
using AutoMapper;

namespace Dab.API.Services;

Expand All @@ -15,10 +15,12 @@ public class PollService : IPollService
private readonly DabContractConfig _dabConfig;
private readonly string chain;
private readonly string ns;
private readonly IMapper _mapper;
private readonly int expirySeconds = 20;

public PollService(ILogger<PollService> logger, ICacheService cacheService, IPactService pactService, IConfiguration configuration)
public PollService(ILogger<PollService> logger, ICacheService cacheService, IMapper mapper, IPactService pactService, IConfiguration configuration)
{
_mapper = mapper;
_logger = logger;
_cacheService = cacheService;
_pactService = pactService;
Expand Down Expand Up @@ -75,18 +77,18 @@ private async Task<List<Poll>> GetAccountVotedPolls(string account, bool ignoreC
}
}

public async Task<List<Poll>> GetAllPolls(bool ignoreCache = false)
public async Task<List<Poll>> GetAllPolls(bool ignoreCache = false)
{
try
try
{
var cacheKey = CacheKeys.AllPolls();
var cacheKey = CacheKeys.AllPolls();

if (!ignoreCache && await _cacheService.HasItem(cacheKey))
{
var cached = await _cacheService.GetItem<string>(cacheKey);
return JsonSerializer.Deserialize<List<Poll>>(cached) ?? new();
}
var code = $"(select {ns}.poller.polls (constantly true))";
var code = $"({ns}.poller.read-all-polls)";
var resp = await _pactService.RunLocalCommand(chain, code);

await _cacheService.SetItem(cacheKey, Utils.JsonPrettify(resp), expirySeconds);
Expand All @@ -101,7 +103,7 @@ public async Task<List<Poll>> GetAllPolls(bool ignoreCache = false)

}

public async Task<List<PollVote>> GetAllVotes(bool ignoreCache = false)
public async Task<List<PollVote>> GetAllVotes(bool ignoreCache = false)
{
try
{
Expand Down Expand Up @@ -271,17 +273,22 @@ public async Task<AccountVoteStats> GetAccountVoteStats(string account, bool ign

var votes = await GetAllAccountVotes(account, ignoreCache);
var polls = await GetAccountVotedPolls(account, ignoreCache);
var pollingPower = await GetMaxPollingPower(account, ignoreCache);
var pollsDto = _mapper.Map<List<PollDTO>>(polls);
var results = new List<bool?>();
foreach(var v in votes)
{

results.Add(Utils.GetElectionResultForVote(v, pollsDto));

}

var stats = new AccountVoteStats
{
Account = account,
TotalVotes = votes.Count(),
VotesYes = votes.Where(e => e.Action == "approved").Count(),
VotesNo = votes.Where(e => e.Action == "refused").Count(),
Abstentions = votes.Where(e => e.Action == "abstention").Count(),
CurrentPollingPower = pollingPower,

OngoingVotes = results.Where(e => e == null).Count(),
VotesWon = results.Where(e => e == true).Count(),
VotesLost = results.Where(e => e == false).Count()
};
await _cacheService.SetItem(cacheKey, Utils.JsonPrettify(stats), expirySeconds);
return stats;
Expand Down
31 changes: 31 additions & 0 deletions backend/API/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using PactSharp.Types;
using Dab.API.Models;
using Dab.API.Models.Bonder;
using Dab.API.Models.Poller;

namespace Dab.API
{
public static class Utils
Expand Down Expand Up @@ -43,6 +45,35 @@ public static string GetOptionName(BondSale bond, decimal optionLenght){

}

public static bool? GetElectionResultForVote(PollVote vote, List<PollDTO> polls)
{
var poll = polls.Where(e => e.PollId == vote.PollId).First();

if(poll.Status != PollStatus.Closed){

return null;

}
else{

var mostVotedOption = poll.PollOptions.OrderByDescending(e => e.VotesPollingPower).FirstOrDefault();

if(mostVotedOption?.OptionName == vote.Action) {

return true;
}
else
{
return false;

}


}


}

public static string MapTxError(PactError error)
{
TxErrorData txError = new()
Expand Down
Loading
Loading