I am stuck at trying to decide something in my class design. This is the overview of what I need to design:
Robot that paints blocks on a square grid (a grid is collection of n blocks).
Let's say there are 4 types of blocks in a grid and each block could cost different amount to paint.
User will input command to instruct robot which block to paint.
If block was already painted, there will be penalty to repaint it.
Finally, report total cost (split by block types), and commands issued by the user.
Some of the things that I have modeled are as follows:
class Robot {
// get current location
// place it at given location
}
class Grid {
// Grid is a collection of blocks
Block[][] blocks;
}
class Block {
// each block has it's coordinates,
// has paint status (painted or unpainted),
// and accepts a visitor to determine price to paint
}
class SquareBlock extends Block {
}
class RectangularBlock extends Block {
}
For issuing commands, I modeled them as Command design pattern.
Question:
I am getting confused on is in which class should the visited (aka painted) blocks be stored (to handle #4 and #5 above)?
Should I store them in Robot? (I didn't thing it belonged in Robot because it felt like tight coupling between the notion of Robot and paintable block.)
I didn't want to store it in Grid as well because, again, I don't think that Grid needs to know what action is being taken on it (not too sure about this though).
I could've stored in different class (say Foo) but then I thought that may be user can issue a command like where ever Robot is, paint next 2 blocks. In this case, since this would be executed in PaintCommand (handled by CommandPattern), Foo wouldn't know what blocks have been painted.
Please let me know your thoughts.
Related
I'm trying to make a game but I need something like a global variable for it to work. Is there a way in GDscript that you can make a variable that works across all nodes with scripts. I need a button that makes you buy a gun which would set a variable to true and with that variable being true, you could equip the gun.
This question doesn't really fit this section where it says: What did you try and what were you expecting? so I'm just gonna skip it.
Is there a way in GDscript that you can make a variable that works across all nodes with scripts.
You could use an autoload.
Go to the Project menu, the Project Settings option, in the Autoloads tab… And there you can set a script, and give it a name. It will be available for every node in the scene tree.
For example, you can have a "globals.gd" script that looks like this:
extends Node
var has_gun := false
Then you make it an autoload with the name "Globals". So in any other script you can use it. For example:
extends Node
func _ready() -> void:
print(Globals.has_gun)
And yes, autoloads will stay there even if you change the current scene.
You might also be interested in the Signal bus (Event bus) pattern, which involves defining signals in an autoload, such that other scripts emit them or connect to them.
Technically the autoload is not a true global. As I said, the autoload will be available for the nodes in the scene tree.
This also means the autoload will not be available for a script that is not a Node (e.g. a Resource), or otherwise not in the scene tree.
Unless you use a hacky workaround to get a reference to the autoload, which I will not go into.
Instead, I will give you an alternative: resource based communication.
This time you create a "global_resource.gd" that look like this:
class_name GlobalResource
extends Resource
var has_gun := false
And then you can use the context menu on the FileSystem panel to create a new resource. When Godot asks you for the type, you select GlobalResource, and give it a name such as "globals.tres".
Then you can use it like this:
extends Node
const Globals := preload("res://globals.tres")
func _ready() -> void:
print(Globals.has_gun)
Everywhere you preload that same resource file ("globals.tres") you will get the same Resource instance. It does not matter if it is in the same scene, or if you changed the current scene.
And yes, this does not depend on the scene tree. And yes, you can put signals in there too.
For completeness sake, I'll also mention that there is another hacky workaround which involves defining a Dictionary or Array as const in a script with a class name. Since in Godot 3 const does not imply inmutable (don't count on this on Godot 4). That is how some people currently work around the lack of static variables. However, I believe you won't find it necessary.
While executing my script in RFT, my script got failed due to the slight position change of a button. (This button's position slightly changes according to the option selected for previous combo box due to the label appearing near the button)
As there are 2 positions for this button in window, one of my script fails while other passes.
Please suggest how to identify this same object in 2 different places in RFT?
If you're alright with not using pre-mapped values and instead work with objects directly in code (which I've personally found to be extremely useful... it's allowed me to do great and wondrous things with RFT :), the following ought to work fine:
private void clickObject(String uniqueIdentifier) {
// Find object
RootTestObject root = RootTestObject.getRootTestObject();
TestObject[] matchingObjs = root.find(atProperty(".id", uniqueIdentifier));
if (matchingObjs.length > 0) {
// Click the object
((GuiTestObject) matchingObjs[0]).click();
}
// Clean-up
unregister(matchingObjs);
}
Feel free to replace ".id" with whatever property is best suited for the situation... since I work primarily with a web application, the ".id" property has worked splendidly for me.
Because the method finds the object anew each time, it'll grab the object's position wherever it's at at the time the method's called. The clean-up will also prevent any weird, horrible, and otherwise unfortunate UnregisteredObjectExceptions from cropping up.
Without looking at your pages I cannot be sure, but I think the buttons are actually two different buttons. Maybe they are generated by javascript, or they are just un-hidden after the option you select in the combobox.
If they are two different buttons (record them both and look at the recognition properties) you can either replace some properties with a regular expression or check wich button is visible/exists and then click it:
if (btn_button1.exists()) {
btn_button1.click();
} else if (btn_button2.exists()) {
btn_button1.click();
}
Here's a more complete tutorial on Object Recognition.
You can increase the tolerance of Rational Performance Tester AssureScript in the properties tab or you could set the description but hide the value. You can also make a custom code that updates the object map to prepare for this change in a java IF structure
I am implementing a view model that is shared by applications on multiple platforms. I am using MvvmCross v3 that has its own MvxEventToCommand class, but I believe the challenge is the same for other frameworks like MVVM Light. As long as the event is used without parameters, the implementation is straightworward, and this is the case for simple interactions like tapping the control.
But when the command needs to handle event arguments things become more complicated. For example, the view model needs to act on certain scroll bar changes (and load more items in the associated list view). Here is the example of XAML:
<cmd:EventToCommand
Command="{Binding ScrollChanged}"
CommandParameter="{Binding EventArgs}" />
(MvvmCross uses MvxEventToCommand, but the principle is the same).
Then in my model I can have the following command handler:
public ICommand ScrollChanged
{
get
{
return new RelayCommand<ScrollChangedEventArgs>(e =>
{
MessageBox.Show("Change!");
});
}
}
(MvxCommand in MvvmCross).
The problem is that ScrollChangedEventArgs is platform specific and this code simply will not compile in a portable class library. This is a general problem with any command that needs not only a push when an event was fired but requires more specific event details. Moving this code in platform-specific part is silly because it more or less kills the concept of portable view models and code-behind-free views. I tried to search for projects that share view models between different platforms, but they all use simple events like "Tap" with no attached event details.
UPDATE 1 I agree with Stuart's remark that view models should only deal with higher level abstractions, so I will rephrase the original concern: how to map results of low-level interactions to a platform-neutral event that triggers a business logic command? Consider the example above: the business logic command is "load more items in a list", i.e. we deal with a list virtualization where a limited number of items from a large collection are loaded initially, and scrolling down to a bottom of a list should cause additional items to be loaded.
WinRT can take care of list virtualization by using observable collections that support ISupportIncrementalLoading interface. The runtime detects this capability and automatically requests extra items from a respective service when the user scrolls down the list. On other platforms this feature should be implemented manually and I can't find any other way than reacting on ScrollViewer ScrollChanged event. I can see then two further options:
Place OnScrollChanged handler in a code-behind file and call the portable view model higher level event (such as "OnItemsRequested");
Avoid code-behind stuff and struggle to wire the ScrollChanged event directly to a view model, then we will need to remap the platform-specific event first.
As long as there is no support for second option, putting event handler in code-behind file is OK as long as it is done for the sole purpose of event mapping. But I would like to investigate what can be done using the second option. MvvmCross has MapCommandParameter class which seems to be able to help, so I wonder if I should exploit that one.
UPDATE 2 I tried MapCommandParameter approach, and it worked allowing me to insert a platform-specific adapter that would map low-level events to view model-specific commands. So the second option worked without any struggle. Stuart also suggested listview-subclassing so there is no need to care about scrolling events. I plan to play with it later.
I agree that viewmodel commands should normally be expressed in terms of viewmodel concepts - so it would be 'strange' to send the viewmodel a command about the scrollbar value changing, but it might be ok to send the viewmodel a command about the user selecting certain list elements to be visible (which she does via scrolling)
One example where I've done this type of thing previously is in list selection.
I originally did this across multiple platforms using a cross-platform eventargs object -
https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/Commands/MvxSimpleSelectionChangedEventArgs.cs
this was then used on WindowsPhone (for example) via an EventToCommand class like https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Commands/MvxSelectionChangedEventToCommand.cs
However... I have to admit that this code hasn't been used much... For list selection we have instead mainly used selecteditem binding, and there simply haven't been any apps that have needed more complex parameterized commands (so far) - you might even need to go back to very old v1 mvvmcross code to find any samples that use it.
I've come across the this problem dealing with subclasses of the Windows.UI.Xaml.Button class in C++/CX, and I'd like to know what's going on.
If I add a control instance to a grid, everything works as expected.
If I subclass the control and add an instance of the subclass, everything works as expected.
But if I subclass my subclassed control and add an instance of it to the grid I get E_INVALIDARG thrown during Grid::Children::Append(). What gives?
My code looks roughly like this (LayoutRoot is a Grid in MainPage.xaml, this sample has been tested in an empty simple metro application):
// Scenario 1: This works (duh!)
LayoutRoot->Children->Append(ref new Button());
// Scenario 2: This works
LayoutRoot->Children->Append(ref new MyButton1());
// Scenario 3: This doesn't work, it will cause an E_INVALIDARG to be thrown by the collection
LayoutRoot->Children->Append(ref new MyButton2());
// This is how MyButton1 and MyButton2 is defined
public ref class MyButton1 : public Button {
public:
MyButton1() {};
~MyButton1() {};
};
public ref class MyButton2 : public MyButton1 {
public:
MyButton2() {};
~MyButton2() {};
};
Note that this question is slightly similar to this question, but the error and the scenario is sufficiently different for me to post this one separately.
UPDATE: I think I'm on the right track understanding this problem after reading this article by Ian Griffiths, but I need to know more regarding the behavior of this specific example. Full code to repeat this problem can be found here, see the 3rd post in the thread.
UPDATE: From what I've learned so far, not all WinRT types support inheritance. I have no reliable source references for this, but I've read that the Windows.UI.Xaml classes should support inheritance, but other WinRT types won't. The Windows.UI.Xaml.Controls.Button class obviously does, while my own MyButton1 doesn't. I'd like to know what I'd have to do to make MyButton1 'inheritable' the way the Button class is.
I've found that replacing the Windows.UI.Xaml.Controls.Button class with Windows.UI.Xaml.Controls.ProgressBar will make scenario 2 fail, which tells me that the ProgressBar class isn't (yet) possible to subclass. This observation is what makes me believe that a class need to do something explicit in order for it to be inheritable.
See Also:
understanding events and event handlers in C#
As a web dev, I don't typically have to get into building my own events for objects, since most are inherent in the page. However, now I'm into a pretty complex (web) project where I think I may have to use them. I just read a chapter out of Pro VB 2008 and the .NET 3.5 Platform regarding events, delegates and lambdas (ch. 11) and while I have a better idea of what's going on, I am still having trouble wrapping my mind around when exactly to use them and how to use them. I understand their implementation, but the example in the book is a bit contrived.
I was hoping someone with a bit more understanding on the subject of events could provide me with a really solid example.
For my real-world application, I'm trying to use an event that would let me know when an item (some class, named OrderItem) has been updated and perform actions based on whether or not it's been updated. I considered using a flag/boolean property, but I know this doesn't smell right, and it's high-time I learn about how to use events correctly.
Thanks a lot!
EDIT Ok, so I guess to clarify a bit, what is the point of calling an event when all it is doing is calling a method? Why not simply call the method? This isn't a duplicate either, as I'm talking conceptually and she wants to know about handlers specifically. Also, I want to know what the difference would be between using an event or a "flag" property. And what do people mean by "subscribe" to an event?
Lets say you had an elevator system, and the part that moves up and down is called the ElevatorCar. When a person pushes a button to go to the 5th floor, it would make sense for the ElevatorController to call the ElevatorCar.RequestToFloor(5) method. Now when the car actually arrives at the 5th floor, it makes sense for it to raise an event like ArrivedAtFloor, passing 5 as the argument. The ElevatorController class would subscribe to the ArrivedAtFloor event of the ElevatorCar class.
This is all becauase the ElevatorCar class doesn't "know" anything about the ElevatorController class, but the ElevatorController class does know about the ElevatorCar class. Therefore the ElevatorCar class is given instructions by means of Methods, and it notifies the outside world of stuff that happens by means of events.
Does that make any sense?
EDIT:
Ok, first, go read the excellent answer listed in the See Also link (assume you've done that). An event is basically an object saying "if you want me to call you whenever X happens, then register your method here". Registering an event handler with the event is "subscribing". This allows encapsulation. So you can write, for instance, your ElevatorCar class once, and use it many times by many other classes.
As for the difference between using an event, or just calling a method, you have to ask yourself, should the ElevatorCar know about the ElevatorController class. If ElevatorController calls ElevatorCar.GoToFloor(x), how could the ElevatorCar class "call back" to ElevatorController without storing a reference to ElevatorController? That means the call has to become ElevatorCar.GoToFloor(int floor, ElevatorController ctrlr). Then the ElevatorCar class eventually has to call ctrlr.ArrivedAtFloor(floor). But you get into a lot of complexities... what if there's more than one car? You probably have to call ctrlr.ArrivedAtFloor(floor, this). Passing around references to yourself isn't optimal.
As for just setting a property, how does the other class know to come and read the property? The only way is to poll the property over and over to check for it to change. You can solve this, of course, by implementing INotifyPropertyChanged, but then again you're back to events!
Events are a specific case of the Inversion of Control (IoC) pattern. The traditional control flow, the caller invokes a method on the callee (like you are suggesting). With IoC (and thus events), we change around the application control and instead of tell the callee what to do, we tell the callee to notify us when something we are interested in happens.
Consider the case of a Timer. I want to be notified every 5 seconds (say). I don't want to constantly poll the timer ("is it time yet? is it time yet? is it time yet?"). Instead, I want to invert the flow control of my application. I want to tell the timer: "When it's time, please tell me by calling this method." That way, control is "inverted", the callee is invoking a method on the caller!
Consider the following code ...
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
// tell the timer, "when it's time, call TimerGoesOff method"
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// wait
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
}
}
Rather than call a method on the Timer to ask when it will go off again (as you suggest), I tell it, "when you go off, call the TimerGoesOff" method. Now, instead of just waiting for the Timer to go off, I could do some work. Consider this code ...
using System;
using System.Threading;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// do some work while timer is going
new Thread(() => DoWork()).Start();
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
public static void DoWork()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine( "Working ..." );
Thread.Sleep( 1000 );
}
}
}
}
Now, I get output something like ...
Working ...
The Time is 8/25/2009 1:05:59 PM
Working ...
Working ...
The Time is 8/25/2009 1:06:00 PM
Working ...
The Time is 8/25/2009 1:06:01 PM
Working ...
The Time is 8/25/2009 1:06:02 PM
The Time is 8/25/2009 1:06:03 PM
I have used the Timer.Elapsed Event to change the control flow of my application. I can go off and do work while "waiting" for the timer event to pulse. This is made possible by IoC and Events.
This is particularly visible (hehe) in User Interfaces. I don't want to keep asking "has the user done anything yet? has the user done anything yet?" (that's the way it used to be done way back when). Instead, I tell Controls for example, "when the user clicks you, let me know". That way, I can go off and do other great stuff and still be responsive to the user.