My PUMP can (inflate) my BALLOON. No problem! But when I try to use my PUMP to (pop) the BALLOON, it really doesn't work very well. I can keep using my PUMP and, eventually, it will (pop) the balloon, but my arm is getting really tired, and I want to (pop) it now. So, instead, I get my POINTY STICK and (pop)! Of course, my POINT STICK is even less effective at (inflate)ing my BALLOON, than the PUMP is at (pop)ing it.
Class Balloon
{
Private int _volume = 0;
Private bool _popped = false;
Public Balloon() { }
//Restrict calling to only a PUMP object
Internal Inflate()
{
if (_popped) return;
_volume += 1;
if (volume > 10) this.Pop();
}
//Restrict calling to only a POINTY STICK object
Internal Pop()
{
if (!_popped) _popped = true;
}
Public string GirlHappiness
{ get
{
if (!_popped)
{
if (_volume < 3)
return "......";
if (_volume < 6)
return "Ooohhh";
else
return "Ahhhh! Yay!";
}
else
return "WaAaAaAaHhHhHh";
}
}
Public string BoyHappiness
{ get
{
if (!_popped)
{
if (_volume < 3)
return "zzzzzz";
if (_volume < 6)
return "zzzzzz";
else
return "zzzzzz";
}
else
return "Ahahaha YAY!";
}
}
}
So, is there any way to achieve this? I cannot achieve the desired result via separating assemblies, and the other method I've explored, using reflection and tracing the stack, is unreliable outside of debugging. What to do?!
Two ways that pop up in my mind: Use explicit interface implementation or events.
With explicit interfaces, you hide the implementation for those who do not threat the instance 'as is'. Example:
interface IPumpable
{
void Pump();
}
interface IPoppable
{
void Pop();
}
class Balloon :IPumpable, IPoppable
{
private void IPumpable.Pump()
{
throw new NotImplementedException();
}
private void IPoppable.Pop()
{
throw new NotImplementedException();
}
}
public static void PopMethod(IPoppable poppable)
{
poppable.Pop();
}
public static void PumpMethod(IPumpable pumpable)
{
pumpable.Pump();
}
static void Main(string[] args)
{
Balloon balloon = new Balloon();
PumpMethod((IPumpable)balloon);
PopMethod((IPoppable)balloon);
}
Note that the Pump and Pop implementations can be marked private. They are only visible when you threat the balloon as IPumpable or IPoppable respectively.
Related
There are two classes that interact in this problem. I'd like to note I'm using Unity:
TaskHandler
public class TaskHandler{
public event Action<GameObject> TaskResponses;
private void Update(){
if (someCondition){
TaskResponses?.Invoke(taskObj);
}
}
}
TaskBase
public class TaskBase: MonoBehaviour{
private TaskHandler taskHandler;
private void Start(){
taskHandler = gameObject.GetComponent<TaskHandler>();
taskHandler.TaskResponses += TaskResponse;
}
private void TaskResponse(GameObject taskObj){
//if check so that only specific TaskResponses run.
if (taskObj == gameObject){
//functions
}
}
}
The problem I'm facing is with methods that extend TaskResponse().
public class SpecificTask{
public override void TaskResponse(GameObject taskObj)
{
base.TaskResponse(taskObj);
//another if check
if (taskObj == thisTaskObj){
//some other functionality
}
}
}
I don't want to do another if check. I tried the following:
public class TaskBase: MonoBehaviour{
//Start() method omitted
private void TaskResponse(GameObject taskObj){
//if check so that only specific TaskResponses run.
if (taskObj == gameObject){
//functions
}
else{
//Effectively stops code from SpecificTask to continue running,
//But other Actions are no longer called.
return;
}
}
}
But the return statement stops TaskReponses() from other classes to run. By that, I mean that if I had Class Task1 and Task2, and Task1's TaskResponse() runs first, but it runs the else statement, it stops and does not run Task2's TaskResponse().
How can I improve my code to stop writing repetitive if checks, while have my code check all Action like I want it to? Should I not be using event for this scenario at all?
Thank you!
You could make it not void but rather bool which indicates if the method was successfully terminated or aborted like e.g.
public class TaskBase
{
public virtual bool TaskResponse(GameObject taskObj)
{
if(taskObj != thisObj) return false;
// Default stuff to happen
return true;
}
}
Then you can do
public class MyTask
{
public override bool TaskResponse (GameObject taskObj)
{
if(!base.TaskResponse(taskObj)) return false;
// Default stuff already happened
// Now you can add additional stuff here
return true;
}
}
Alternatively if you want to avoid that if check entirely what I also do often is using separate methods like
public class TaskBase
{
public void TaskResponse (GameObject taskObj)
{
if(taskObj != thisObj) return;
TaskResponseInternal();
}
protected virtual void TaskResponseInternal()
{
// Default stuff to happen
}
}
And then simply override that instead
public class MyTask
{
protected override void TaskResponseInternal ()
{
// If you want also the default stuff
base.TaskResponseInternal();
// Additional stuff to happen
}
}
So I have a class Doorcontrol that can have 4 states
public enum DoorControlState
{
DoorClosed,
DoorOpening,
DoorOpen,
DoorBreached
}
To open the door an accescode is needed, the code is then validated and if it's correct the door is opened. If the door is not in the Closed state nothing should happen. It should go like this RequestEntry(id)[Doorcontrol]->ValidateEntryRequest(id)[IUserValidation]->OK[Doorcontrol]->Open[IDoor]->change state to DoorOpening. Idoor then calls DoorOpen and the state changes to DoorOpen and so on.
I have implemented the DoorControl class as follows
public class DoorControl
{
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
private int _id;
public DoorControl(IDoor door, IEntryNotification entryNotification, IUserValidation userValidation, DoorControlState doorControlState)
{
_door = door;
_entryNotification = entryNotification;
_userValidation = userValidation;
_doorControlState = doorControlState;
}
public void Run()
{
switch (_doorControlState)
{
case DoorControlState.DoorClosed:
bool foo = RequestEntryId();
if (foo)
{
_door.Open();
_doorControlState = DoorControlState.DoorOpening;
}
break;
case DoorControlState.DoorOpening:
_door.Close();
_doorControlState = DoorControlState.DoorOpen;
break;
case DoorControlState.DoorOpen:
// Do stuff....
break;
case DoorControlState.DoorBreached:
// Do stuff
break;
default:
throw new InvalidEnumArgumentException();
}
}
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
public void DoorOpened()
{
//
}
public void DoorClosed()
{
//
}
}
}
The UserValidation and Door classes are implemented as Interfaces
public interface IUserValidation
{
bool ValidateEnetryRequest();
}
public interface IDoor
{
void Open();
void Close();
}
I am testing my code using Nunit and NSubstitute
namespace DoorControl.Unit.Test
{
[TestFixture]
public class DoorControlUnitTest
{
private DoorControl _uut;
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
[SetUp]
public void SetUp()
{
_door = Substitute.For<IDoor>();
_entryNotification = Substitute.For<IEntryNotification>();
_userValidation = Substitute.For<IUserValidation>();
_doorControlState = DoorControlState.DoorClosed;
_uut = new DoorControl(_door, _entryNotification, _userValidation, _doorControlState);
}
[Test]
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.RequestEntryId(); // Can't called that cause it's private
_door.Received().Open();
}
}
}
I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state.
Edit: What state the Doorcontrol is in should be hidden from everybody else.
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
if(_doorControlState == DoorControlState.DoorClosed){
_uut.RequestEntryId(); // Make it public
}
_door.Received().Open();
}
Or into the doorcontrol class like:
case DoorControlState.DoorClosed:
RequestEntryId();
I'm not sure exactly what you're asking: when you say "I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state." do you mean the unit test? I can't figure out why you would want to do that. Please provide more info and I'll update this answer if I can help.
I did notice a couple of things that might help you though. First RequestEntryId has a problem:
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
Here maybeFoo = true is an assignment which overwrites the result of ValidateEntryRequest(). I think you intended a comparison with ==, but the whole method can be simplified to:
private bool RequestEntryId()
{
return _userValidation.ValidateEnetryRequest();
}
With that fixed we can run a few tests to check how the public Run method behaves. Given your SetUp creates a doorcontrol already in a Closed state, we can test that the door opens for valid users, and doesn't open for invalid users.
[Test]
public void ClosedDoorOpensWhenUserIsValid()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_door.Received().Open();
}
[Test]
public void ClosedDoorDoesNotOpenWhenUserInvalid()
{
_userValidation.ValidateEnetryRequest().Returns(false);
_uut.Run();
_door.DidNotReceive().Open();
}
We can also check the validation is not repeated for an already opened door:
[Test]
public void OpenDoorDoesNotRevalidate()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_userValidation.ClearReceivedCalls();
_uut.Run();
_userValidation.DidNotReceive().ValidateEnetryRequest();
}
Hope this gives you some ideas for testing this.
I have some small mp3 files that I want to play as notification sounds in my application. Just to be clear, I have already created a "raw" folder under Resources and added my mp3 files there. As a first pass, I was just using the MediaPlayer like this:
MediaPlayer mPlayer;
mPlayer = MediaPlayer.Create(context, Resource.Raw.warning);
mPlayer.Start();
And that worked but it seemed a little clunky when all I want to do is use them as notifications, not for playing audio tracks. I also think there is more overhead with that approach to make sure the player is done playing, disposed, etc...
So, I found the SoundPool and implemented that. There were some early questions, for example, when you load a sound into the SoundPool, it returns an int for the SoundID which you then use later as a reference to the sound you want to play. Therefore, I had to create a separate class to handle those properties as well.
This is what I have so far and it seems to be working but I am wondering if this is the best way still?
First, I created a class to wrap the SoundPool up and it has a class for the SoundID as well.
using Android.Content;
using Android.Media;
namespace PocketPacTracAndroid.Media
{
public class Sounds
{
SoundPool soundPool;
Context context;
int maxStreams = 1;
bool isLoaded = false;
public bool IsLoaded
{
get { return isLoaded; }
}
public Sounds(Context oContext)
{
soundPool = new SoundPool(maxStreams, Stream.Music, 0);
context = oContext;
loadSoundPool();
}
public Sounds(Context oContext, int streams)
{
maxStreams = streams;
soundPool = new SoundPool(maxStreams, Stream.Music, 0);
loadSoundPool();
}
private void loadSoundPool()
{
soundPool.LoadComplete += SoundPool_LoadComplete;
SoundIDs sid = new SoundIDs();
sid.Scan = soundPool.Load(context, Resource.Raw.scan, 1);
sid.PackageAdded = soundPool.Load(context, Resource.Raw.packageAdded, 1);
sid.HubTransfer = soundPool.Load(context, Resource.Raw.hubtransfer, 1);
sid.Alert = soundPool.Load(context, Resource.Raw.alert, 1);
sid.Warning = soundPool.Load(context, Resource.Raw.warning, 1);
sid.ScanChange = soundPool.Load(context, Resource.Raw.scanchange, 1);
}
private void SoundPool_LoadComplete(object sender, SoundPool.LoadCompleteEventArgs e)
{
isLoaded = true;
}
public void playSound(int sid)
{
if (isLoaded)
{
soundPool.Play(sid, 1f, 1f, 1, 0, 1f);
}
}
}
public class SoundIDs
{
int scan;
int packageAdded;
int hubTransfer;
int alert;
int warning;
int scanChange;
public int Scan
{
get { return scan; }
set { scan = value; }
}
public int PackageAdded
{
get { return packageAdded; }
set { packageAdded = value; }
}
public int HubTransfer
{
get { return hubTransfer; }
set { hubTransfer = value; }
}
public int Alert
{
get { return alert; }
set { alert = value; }
}
public int Warning
{
get { return warning; }
set { warning = value; }
}
public int ScanChange
{
get { return scanChange; }
set { scanChange = value; }
}
}
}
Then, from anywhere in my app, I instantiate the classes:
Sounds sounds;
SoundIDs sid;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
context = Context;
getServiceTypes();
sounds = new Sounds(context);
sid = new SoundIDs();
}
and finally, I can call this to play the sound based on my soundID that was returned when I loaded in the files. I also exposed IsLoaded in case I want to check that externally but it is checked internally when playSound is called.
sounds.playSound(sid.Scan);
Does this seem like a good approach? Is it the best? Any suggestions would be appreciated. It does seem to work but I just want to make sure I won't have any resource issues or playback issues if I call the same or different notifications over and over again during the application lifecycle.
Thanks!
Yes SoundPool is the way to go. Just watch out for threads playing different sounds at the same time. Unless you build in a queue, some sounds will block others as there is only one speaker.
Is there a way to prevent a method from execution if it is in design time or the method can only be executed at runtime.
I got this problem while creating a custom control because there is a method call in the constructor that will only work at runtime.
now at design time while designing the form and use that control, then the form will generate the error.
now i tried this at the constructor of the user control
public ctrl_information()
{
InitializeComponent();
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)) return;
SomeMethod();
//Other code
}
what i want to achieve now is something like this.
[ExecuteOnlyAtRuntime]
public void SomeMethod()
{
//Code here
}
Then call it like this.
public ctrl_information()
{
InitializeComponent();
//if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)) return; -- removing this line
SomeMethod();
}
Is it possible?
Please shed some light on this.
Thank you
Assuming that someMethod is in a control, you may use Component.DesignMode.
So a simple approach could be
public void SomeMethod()
{
if (this.DesignMode == false)
{
//Code here
}
}
Incase the Some function is not in a control, you may implement something like this -
public void SomeFunciton()
{
if(VisualStudioUtility.IsRunningInVisualStudio == false)
{
}
}
static class VisualStudioUtility
{
private const string IDE_EXE = "devenv.exe";
public static bool IsRunningInVisualStudio
{
get
{
return Environment.CommandLine.Contains(IDE_EXE);
}
}
}
I'm making a game where workers perform actions based on a current Task. Each worker will be assigned a list of tasks, in a preferred order (which is influenced by the player's decisions).
When a task is completed (e.g. take item from X to Y), the worker needs to start a new task by checking through their list of possible tasks, see if each can be performed, and if so, set their current task to that task and start it (the last task - "Wander Around" is always going to be available).
I currently have this working using a big switch statement and Enums, but now want to generalise this code to create a Task class, and give the workers a list of preferred Tasks, a GetNextTask() function, and in the worker's Update() method, call currentTask.update() (this will get the worker to do whatever he's required to do under the current task, and which will call worker.GetNextTask() when the task is complete).
What I'm unclear on is the best way to store Tasks in the worker.
Should I use:
1) Reflection. Store the possible Tasks as a list of types, then use reflection to a) call a static method public static virtual bool CanPerformThisTask() which is overridden in each subclass, and b) Create an instance of that task for the worker?
(example attempt at code for this below - but unable to test yet)
2) Instantiate all the Tasks whenever a worker needs to get a new task (probably using Activator), and check (Task)task.CanPerformThisTask() for each one - if true, do that task. Instantiating them all seems inefficient though?
3) Generics. Can this be done using generics? If so, how?
Here is a snippet of my classes to give the idea of what I'm trying to do:
Worker Class:
protected List<Point> waypoints = new List<Point>();
public bool reachedDestination { get { return waypoints.Count == 0; } }
protected Task task;
public List<Type> possibleTasks;
public Worker(Task initialTask, List<Type> initialPossibleTasks ...)
: base(...)
{
task = initialTask;
possibleTasks = initialPossibleTasks;
}
public override void Update()
{
base.Update();
if (!reachedDestination) Move();
task.Update();
}
public void GetNextTask()
{
foreach (Type t in possibleTasks)
{
//reflection code here - will this work and can we do this with generics instead?
Bool canDoT = (bool)t.GetMethod("CanPerformThisTask", BindingFlags.Static | BindingFlags.Public).Invoke(null, null);
if (canDoT)
{
task = Activator.CreateInstance(t);
return;
}
}
}
Here is some incomplete code for my base Task class (which shouldn't be instantiated):
public class Task
{
public Worker worker;
public virtual static bool CanPerformThisTask()
{
//never call this from here - always from subclasses
return false;
}
public Task()
{
//set up code here
}
public virtual void Update()
{
//make worker do relevant activities here
//call finish task when done
}
public void FinishTask()
{
worker.GetNextTask();
}
}
and here is an example of a Task the worker will have in its list of possible tasks:
public class T_WorkerWander : Task
{
public static override bool CanPerformThisTask()
{
//can always wander (other Tasks will have conditions here)
return true;
}
public T_WorkerWander()
: base()
{
}
override public void Update()
{
//make the worker wander here
if (worker.reachedDestination) FinishTask();
}
}
Update: here is the code I've now got working
Task Class:
public abstract class Task
{
//the entity holding this task
public TaskableEntity taskEntity;
public List<TaskStage> taskStages;
public TaskStage currentTaskStage { get { return taskStages[0]; } }
public Task(TaskableEntity t) { taskEntity = t; }
/// <summary>
/// the conditions for the Task to be started
/// </summary>
public virtual bool CanStart()
{
return true;
}
public void Start()
{
taskStages = new List<TaskStage>();
InitialiseTaskStages();
taskStages[0].Start();
}
public abstract void InitialiseTaskStages();
public void Update()
{
currentTaskStage.Update();
if (currentTaskStage.IsComplete()) TaskStageComplete();
}
public void TaskStageComplete()
{
taskStages.RemoveAt(0);
if (taskStages.Count == 0) taskEntity.TaskComplete();
else currentTaskStage.Start();
}
public void SetTaskStages(params TaskStage[] t)
{
taskStages = t.ToList();
}
public void Interrupt()
{
currentTaskStage.Interrupt();
}
}
TaskStage class:
public sealed class TaskStage
{
private Task task;
private List<Point> pointsToMoveTo;
public void SetPointsToMoveTo(Point p) { pointsToMoveTo = new List<Point>() { p }; }
public void SetPointsToMoveTo(params Point[] p) { pointsToMoveTo = p.ToList(); }
public void SetPointsToMoveTo(List<Point> p) { pointsToMoveTo = p; }
public Action actionToApply;
private float timeToWait;
public void SetWait(float wait) { timeToWait = wait; }
private IReservable[] itemsToReserve;
public void SetItemsToReserve(params IReservable[] items) { itemsToReserve = items; }
private IReservable[] itemsToUnreserve;
public void SetItemsToUnreserve(params IReservable[] items) { itemsToUnreserve = items; }
private Emotion emotionToSet;
public void SetEmotionToSet(Emotion e) { emotionToSet = e; }
private TaskStage _interrupt;
public void SetInterruptAction(TaskStage t) { _interrupt = t; }
public void Interrupt() { _interrupt.Start(); }
public TaskStage(Task t)
{
task = t;
}
public void Start()
{
if (actionToApply != null) actionToApply();
if (itemsToUnreserve != null) UnreserveItems();
if (itemsToReserve != null) ReserveItems();
if (pointsToMoveTo != null)
{
//this will need changing after pathfinding sorted out...
if (pointsToMoveTo.Count == 1) task.taskEntity.SetWaypoints(pointsToMoveTo[0]);
else task.taskEntity.waypoints = pointsToMoveTo;
}
if (emotionToSet != null) emotionToSet.StartEmotion();
}
public void Update()
{
if (timeToWait > 0) timeToWait -= GV.elapsedTime;
}
public bool IsComplete()
{
if (pointsToMoveTo != null && !task.taskEntity.reachedDestination) return false;
if (timeToWait > 0) return false;
return true;
}
public void ReserveItems()
{
foreach (IReservable i in itemsToReserve)
{
i.reserved = true;
}
}
public void UnreserveItems()
{
foreach (IReservable i in itemsToUnreserve)
{
i.reserved = false;
}
}
}
Example Task:
public class T_WorkerGoToBed : Task
{
public FactoryWorker worker { get { return taskEntity as FactoryWorker; } }
public T_WorkerGoToBed(TaskableEntity t)
: base(t) { }
public override bool CanStart()
{
return Room.Available<Bed>(GV.Bedrooms);
}
public override void InitialiseTaskStages()
{
Bed bedToSleepIn = Room.NearestAvailableFurniture<Bed>(GV.Bedrooms, taskEntity.X, taskEntity.Y);
//stage 1 - reserve bed and move there
TaskStage ts1 = new TaskStage(this);
ts1.SetItemsToReserve(bedToSleepIn);
ts1.SetPointsToMoveTo(bedToSleepIn.XY);
//stage 2 - sleep in bed
TaskStage ts2 = new TaskStage(this);
ts2.SetWait((worker.maxEnergy - worker.energy) / worker.energyRegeneratedPerSecondWhenSleeping);
ts2.SetEmotionToSet(new E_Sleeping(worker, false));
//stage 3 - unreserve bed
TaskStage ts3 = new TaskStage(this);
ts3.SetItemsToUnreserve(bedToSleepIn);
ts3.SetEmotionToSet(new E_Happy(worker, false));
SetTaskStages(ts1, ts2, ts3);
}
}
It sounds like you need to reverse responsibility between task and worker. Instead of asking whether the task can be performed, ask the worker if he can perform a given task:
class Worker
{
bool CanPerformTask<T>() where T : Task
{
var type = typeof(T);
// code to determine whether worker can perform the task T
}
// alternative with instance parameter
bool CanPerformTask<T>( T task ) where T : Task
{
// code to determine whether worker can perform the task passed in
}
}
This solution avoids the "instantiate all tasks or call static method" problem.
Also, consider using the built-in collection classes. Things such as queues and stacks can greatly simplify the code needed to schedule execution of things.
I think you are abusing the point of static classes. The "Task" class should be standard (not static). Your "Worker" class is not static therefore implying that there is more than one "Worker" instance. Given this paradigm, these workers can probably have the same task assigned to them.
Your "Worker" class needs to have this property modified from:
public List possibleTasks;
to
public List _possibleTasks;
You probably should not have public access to this property either. You can modify "CanPerformThisTask" as necessary.