Browse Source

Fix documentation and naming for `VotingModel`

pull/12/head
Anton Tarasenko 2 years ago
parent
commit
028c2eaf83
  1. 8
      sources/BaseAPI/API/Commands/Voting/TEST_Voting.uc
  2. 77
      sources/BaseAPI/API/Commands/Voting/VotingModel.uc

8
sources/BaseAPI/API/Commands/Voting/TEST_Voting.uc

@ -115,7 +115,7 @@ protected static function MakeFaultyYesVote(
id = UserID(__().memory.Allocate(class'UserID')); id = UserID(__().memory.Allocate(class'UserID'));
id.Initialize(__().text.FromString(voterID)); id.Initialize(__().text.FromString(voterID));
Issue("Illegal vote had unexpected result."); Issue("Illegal vote had unexpected result.");
TEST_ExpectTrue(model.AddVote(id, true) == expected); TEST_ExpectTrue(model.CastVote(id, true) == expected);
} }
protected static function MakeFaultyNoVote( protected static function MakeFaultyNoVote(
@ -127,7 +127,7 @@ protected static function MakeFaultyNoVote(
id = UserID(__().memory.Allocate(class'UserID')); id = UserID(__().memory.Allocate(class'UserID'));
id.Initialize(__().text.FromString(voterID)); id.Initialize(__().text.FromString(voterID));
Issue("Illegal vote had unexpected result."); Issue("Illegal vote had unexpected result.");
TEST_ExpectTrue(model.AddVote(id, false) == expected); TEST_ExpectTrue(model.CastVote(id, false) == expected);
} }
protected static function VoteYes(VotingModel model, string voterID, ExpectedOutcome expected) { protected static function VoteYes(VotingModel model, string voterID, ExpectedOutcome expected) {
@ -136,7 +136,7 @@ protected static function VoteYes(VotingModel model, string voterID, ExpectedOut
id = UserID(__().memory.Allocate(class'UserID')); id = UserID(__().memory.Allocate(class'UserID'));
id.Initialize(__().text.FromString(voterID)); id.Initialize(__().text.FromString(voterID));
Issue("Failed to add legitimate vote."); Issue("Failed to add legitimate vote.");
TEST_ExpectTrue(model.AddVote(id, true) == VFR_Success); TEST_ExpectTrue(model.CastVote(id, true) == VFR_Success);
if (expected == TEST_EO_Continue) { if (expected == TEST_EO_Continue) {
Issue("Vote, that shouldn't have ended voting, ended it."); Issue("Vote, that shouldn't have ended voting, ended it.");
TEST_ExpectTrue(model.GetStatus() == VPM_InProgress); TEST_ExpectTrue(model.GetStatus() == VPM_InProgress);
@ -155,7 +155,7 @@ protected static function VoteNo(VotingModel model, string voterID, ExpectedOutc
id = UserID(__().memory.Allocate(class'UserID')); id = UserID(__().memory.Allocate(class'UserID'));
id.Initialize(__().text.FromString(voterID)); id.Initialize(__().text.FromString(voterID));
Issue("Failed to add legitimate vote."); Issue("Failed to add legitimate vote.");
TEST_ExpectTrue(model.AddVote(id, false) == VFR_Success); TEST_ExpectTrue(model.CastVote(id, false) == VFR_Success);
if (expected == TEST_EO_Continue) { if (expected == TEST_EO_Continue) {
Issue("Vote, that shouldn't have ended voting, ended it."); Issue("Vote, that shouldn't have ended voting, ended it.");
TEST_ExpectTrue(model.GetStatus() == VPM_InProgress); TEST_ExpectTrue(model.GetStatus() == VPM_InProgress);

77
sources/BaseAPI/API/Commands/Voting/VotingModel.uc

@ -21,52 +21,46 @@
*/ */
class VotingModel extends AcediaObject; class VotingModel extends AcediaObject;
//! Class for counting votes according to voting policies it was configured with. //! This class counts votes according to the configured voting policies.
//! //!
//! Its main purpose is to separate voting logic from the voting interface, simplifying its //! Its main purpose is to separate the voting logic from the voting interface, making
//! implementation and making actual logic easily testable. //! the implementation simpler and the logic easier to test.
//! //!
//! # Usage //! # Usage
//! //!
//! 1. Allocate instance of [`VotingModel`]; //! 1. Allocate an instance of the [`VotingModel`] class.
//! 2. Call [`Initialize()`] to set required policies; //! 2. Call [`Initialize()`] to set the required policies.
//! 3. Use [`UpdatePotentialVoters()`] to specify which users are allowed to vote. //! 3. Use [`UpdatePotentialVoters()`] to specify which users are allowed to vote.
//! This set can be changed at any point in time later. //! You can change this set at any time. The method used to recount the votes will depend on
//! How votes will be recounted will depend on policies set in previous [`Initialize()`] call. //! the policies set during the previous [`Initialize()`] call.
//! 4. Use [`AddVote()`] to add a vote from users. //! 4. Use [`CastVote()`] to add a vote from a user.
//! 5. Check [`GetStatus()`] after either [`UpdatePotentialVoters()`] or [`AddVote()`] calls to //! 5. After calling either [`UpdatePotentialVoters()`] or [`CastVote()`], check [`GetStatus()`] to
//! check whether voting has concluded. //! see if the voting has concluded.
//! You can release [`VotingModel`]'s reference after you've gotten the result, since once //! Once voting has concluded, the result cannot be changed, so you can release the reference
//! voting has concluded, its result cannot be changed. //! to the [`VotingModel`] object.
/// Describes how [`VotingModel`] must react to user making potentially illegal reactions. /// Describes how [`VotingModel`] should react when a user performs potentially illegal actions.
/// ///
/// Illegal here means that either corresponding operation won't be permitted or any vote made /// Illegal here means that either corresponding operation won't be permitted or any vote made
/// would be considered invalid. /// would be considered invalid.
///
/// Leaving means simply no longer being in a potential pool of voters, which includes actually
/// leaving the game and simply losing rights to vote.
enum VotingPolicies { enum VotingPolicies {
/// Consider illegal anything that can be illegal. /// Anything that can be considered illegal actions is prohibited.
/// ///
/// Leaving during voting will make a vote invalid. /// Leaving (or losing rights to vote) during voting will make a vote invalid.
/// Leaving means losing rights to vote.
/// ///
/// Changing vote is forbidden. /// Changing vote is forbidden.
VP_Restrictive, VP_Restrictive,
/// Leaving during voting is legal, everything else potentially illegal is still illegal. /// Leaving during voting is allowed. Changing a vote is not allowed.
///
/// Changing vote is forbidden.
VP_CanLeave, VP_CanLeave,
/// Changing one's vote is allowed, everything else potentially illegal is still illegal. /// Changing one's vote is allowed. If a user leaves during voting, their vote will be invalid.
///
/// Leaving during voting will make a vote invalid.
/// Leaving means losing rights to vote.
VP_CanChangeVote, VP_CanChangeVote,
/// Leaving during voting and changing a vote is allowed, everything else potentially illegal is /// Leaving during voting and changing a vote is allowed. Leaving means losing rights to vote.
/// still illegal.
///
/// Leaving means losing rights to vote.
/// ///
/// Currently this flag means that every option it provides is allowed, but this might change in /// Currently, this policy allows all available options, but this may change in the future if
/// the future if more options would be added. /// more options are added.
VP_CanLeaveAndChangeVote VP_CanLeaveAndChangeVote
}; };
@ -150,7 +144,7 @@ public final function Initialize(VotingPolicies policies) {
/// Returns current status of voting. /// Returns current status of voting.
/// ///
/// This method should be checked after both [`AddVote()`] and [`UpdatePotentialVoters()`] to check /// This method should be checked after both [`CastVote()`] and [`UpdatePotentialVoters()`] to check
/// whether either of them was enough to conclude the voting result. /// whether either of them was enough to conclude the voting result.
public final function VotingModelStatus GetStatus() { public final function VotingModelStatus GetStatus() {
return status; return status;
@ -178,19 +172,19 @@ public final function UpdatePotentialVoters(array<UserID> potentialVoters) {
/// ///
/// Adding a vote can fail if [`voter`] isn't allowed to vote or has already voted and policies /// Adding a vote can fail if [`voter`] isn't allowed to vote or has already voted and policies
/// forbid changing that vote. /// forbid changing that vote.
public final function VotingResult AddVote(UserID voter, bool forSuccess) { public final function VotingResult CastVote(UserID voter, bool voteForSuccess) {
local bool votesSameWay; local bool votesSameWay;
local PlayerVoteStatus currentVote; local PlayerVoteStatus currentVote;
if (status != VPM_InProgress) { if (status != VPM_InProgress) {
return VFR_VotingEnded; return VFR_VotingEnded;
} }
if (!AllowedToVote(voter)) { if (!IsVotingAllowedFor(voter)) {
return VFR_NotAllowed; return VFR_NotAllowed;
} }
currentVote = HasVoted(voter); currentVote = HasVoted(voter);
votesSameWay = (forSuccess && currentVote == PVS_VoteFor) votesSameWay = (voteForSuccess && currentVote == PVS_VoteFor)
|| (!forSuccess && currentVote == PVS_VoteAgainst); || (!voteForSuccess && currentVote == PVS_VoteAgainst);
if (votesSameWay) { if (votesSameWay) {
return VFR_AlreadyVoted; return VFR_AlreadyVoted;
} }
@ -199,7 +193,7 @@ public final function VotingResult AddVote(UserID voter, bool forSuccess) {
} }
EraseVote(voter); EraseVote(voter);
voter.NewRef(); voter.NewRef();
if (forSuccess) { if (voteForSuccess) {
votesFor[votesFor.length] = voter; votesFor[votesFor.length] = voter;
} else { } else {
votesAgainst[votesAgainst.length] = voter; votesAgainst[votesAgainst.length] = voter;
@ -208,12 +202,15 @@ public final function VotingResult AddVote(UserID voter, bool forSuccess) {
return VFR_Success; return VFR_Success;
} }
/// Checks if provided user is allowed to vote. /// Checks if the provided user is allowed to vote based on the current list of potential voters.
///
/// The right to vote is decided solely by the list of potential voters set using
/// [`UpdatePotentialVoters()`].
/// However, even if a user is on the list of potential voters, they may not be allowed to vote if
/// they have already cast a vote and the voting policies do not allow vote changes.
/// ///
/// The right to vote is decided solely by what was provided into [`UpdatePotentialVoters()`]. /// Returns true if the user is allowed to vote, false otherwise.
/// Voting can still fail for [`voter`] that is allowed to vote if, for example, they already voted public final function bool IsVotingAllowedFor(UserID voter) {
/// and policies forbid vote change.
public final function bool AllowedToVote(UserID voter) {
local int i; local int i;
if (voter == none) { if (voter == none) {

Loading…
Cancel
Save