Target a Object Variable in a different Class - class

So, without posting my entire project in here, I will sum it up as best I can:
class Program
{
static void Main(string[] args)
{
Thing one = new Thing();
one.addTimer(10);
one.addTimer(4);
one.addTimer(2);
one.addTimer(8);
}
}
class Counter
{
private int Seconds;
private int TimerNum;
public Counter(int SecondsX)
{
Seconds = (SecondsX * 1000);
}
public void TimerCall(){
Thread.sleep(Seconds);
CounterCallBack();
}
public void CounterCallBack()
{
Console.WriteLine("Timer " + TimerNum + " Done");
//Then the time is up the call back is executed
//The issue I am having is how do I trigger the next timer for the list timers to go from hear automatically. It would send back TimerNum to Thing.Continue
}
}
class Thing
{
List<int> timers = new List<int>();
public Thing()
{
}
public void addTimer(new Timer(int SecondsToAdd))
{
timers.Add(SecondsToAdd);
}
public void StartTimers(){
timers[0].TimerCall();
}
public void Continue(int LastRun){
if(timers.count()-1>= LastRun){
timers[LastRun].TimerCall();
}
}
}
So I need to access the Continue method from counter to kick off the next timer.
Or I need to find a way to do the same thing.
However, the user needs to be able to edit, add, and remove timers (Which happens from the Program class)
Remember that in my program (this is a simplified version) Counter is a timer Call and CallBack that runs asynchronously.
Is it even possible to do? Or do I need to scrap this approach and start from square one?
Also, I know this is rough, but this a project is for charity and I plan to clean it up once I get this prototype working. Also I am 16. So please, any help you can give would be well appreciated.

Okay It's a dirty answer but I am going to Use a dictionary to store the Object variables, and have an assessor method that is passed the ID of Correct set of timers, and the Index of the next timer to run. That then calls the next timer, and so on and so fort.
Dirty but functional for a Prototype.

Related

OOP avoid unnecessary repeated calls

so I have a question on OOP class design. I have read that we should "Tell, don't ask" and not use Exceptions for "Flow control". However in this particular case I see some redundant code being executed!
Lets assume Person have a list of events that he will be attending, and it must be enforced that he cannot attend an event that overlaps with his current schedule. So I have the following Java code
public class Person {
// this arraylist of events must not have overlapping events!
ArrayList<Events> eventsToAttend;
// checks if a person is free to attend a new event by viewing all events he is attending
public boolean canAttendEvent(Event newEvent) {
for(int i = 0; i < eventsToAttend.size(); i++) {
if (newEvent.isSameDayAndTime(eventsToAttend.get(i))) {
return false;
}
}
return true;
}
public void attendEvent(Event newEvent) {
// enforce the validity of the newEvent
if (!canAttendEvent(newEvent)) {
// throw exception and return
}
eventsToAttend.add(newEvent);
}
public static main(String[] args) {
// just an example usage!
Person person = somePersonWithEventsAlready;
Event event = new Event();
if (person.canAttendEvent(event)) {
// !!!
// Notice that canAttendEvent() is called twice!! how do you prevent this?
// !!!
person.attendEvent(event);
}
// Alternatively I could just try - catch around person.attendEvent(), but is that bad practise?
}
}
The issue I am facing in general with this way of doing things, is that "canAttendEvent()" is being called twice. However it is good practice according to OOP design patterns?
What would be a better way to do something like this? Thank you for reading this.
try - catch in the main is the best way to achieve what you are trying to avoid: call twice the function canAttendEvent

Bukkit How to change an int in the config file then be able to change it again without reloading (Custom config file class.))

Okay so I am making a custom feature for my OP-Prison server, one of the things that I need to do is get an integer from the players.yml file, check if it is >= one, if it is take away one, save it and then if it is still above one then they can repeat the action untill it's 0.
The issue comes with the fact that I have to restart the server for the file to change, and even when I do, it will only go down by one integer at a time, before having to reload it again.
GUI Creation code:
Main main = Main.getPlugin(Main.class);
#SuppressWarnings("unused")
private FileControl fc;
#SuppressWarnings("unused")
private FileControl playerfc;
public static String inventoryname = Utils.chat(Main.pl.getFileControl().getConfig().getString("Backpacks.White.InventoryName"));
public List<Player> WhiteOpened = new ArrayList<>();
public static Inventory whiteBackpack(Player player) {
Inventory whiteBackpack = Bukkit.createInventory(null, 27, (inventoryname));
UUID uuid = player.getUniqueId();
whiteBackpack.setItem(10,
new ItemCreator(Material.INK_SACK).setData(8)
.setDisplayname(Utils.chat("&fCommon Packages &8ยป &f&l" + Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common")))
.getItem());
return whiteBackpack;
}
Code for updating the config + item when the Commonpackage is clicked:
#EventHandler
public void whiteBackpackInteract(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
UUID uuid = player.getUniqueId();
ItemStack clicked = event.getCurrentItem();
String title = event.getInventory().getName();
if (title.equals(inventoryname)) {
// Making it so that the item cannot be moved
event.setCancelled(true);
if (clicked != null) {
if (event.getSlot() == 10) {
// Getting the user's common packages section in the config and checking if it is greater than or equal to 1.
if (Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common") >= 1) {
// Saving the user's common package section to 'currentCommon'
Integer currentCommon = Main.pl.getPlayerFile().getConfig().getInt("Users." + uuid + ".Packages.Common");
// Taking away one from 'currentCommon' and saving it to 'newCommon'
Integer newCommon = currentCommon - 1;
// Getting the 'players.yml' file
File file = new File(main.getDataFolder(), "players.yml");
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
// Checking if the current common keys is greater than or equal to 1
if (currentCommon >= 1) {
try {
//Now, Here's where the error lies.
//Gets the player's common package count and sets it to the 'newCommon' count
config.set("Users." + uuid + ".Packages.Common", newCommon);
//Saves the players.yml file
config.save(file);
} catch (IOException e) {
e.printStackTrace();
}
// Updates the inventory they're currently in (Atleast it's meant to...)
player.updateInventory();
// Sends them a message (This is just for testing purposes, making sure it's working.)
player.sendMessage(Utils.chat("&8(&9Vexil&8) &fCommon Package"));
}
}
}
}
}
}
If there is any other code that you need, just ask I'll happily provide it for you.
Right now, you need to restart the server for it to save the data to the file. This should not happen, since you are calling the method config.save(file). The following is simply speculation, but it's the only cause that I think can easily explain what is going on.
In the object that is returned by getPlayerFile().getConfig(), there is likely a variable that stores a FileConfiguration object. That variable houses all the data from the players.yml file. In your whiteBackpackInteract() method, you load the data all over again. You then continue on to write to this NEW FileConfiguration variable, rather than the one that is stored in getPlayerfile().getConfig(). Since you then proceed to save to the file directly, the variables stored in the getPlayerfile().getConfig() is never told that you changed some values around. To fix this, you need to change the following:
config.set("Users." + uuid + ".Packages.Common", newCommon);
config.save(file);
to this:
Main.pl.getPlayerFile().getConfig().set("Users." + uuid + ".Packages.Common", newCommon);
Main.pl.getPlayerFile().getConfig().save(file);
and then delete this line of code:
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
This should solve your problem entirely. If it does not, I would recommend not using your friend's custom config API and instead just use the ones that are built in. Using third party code that you don't properly understand can very often lead to problems such as this.
The following are not the bugs, but are suggestions to help improve your code:
You should be sure to put your comments ABOVE or to the RIGHT over the code they describe. People read from top to bottom, so the comments (before I made the suggested edit to your post) were all below the code they describe.
Typically, you want to try to make sure that if code doesn't need to be run, it isn't. Since the int newCommon is not used until inside that if statement, you should move it in there.
You are using Main.getPlugin();
Now while that doesn't seem like such a bad thing, your getting an unassigned variable, I have no idea how it is working but you're assigning Main to Main. There are 2 proper ways to actually get the main class.
The first, and generally best way, is to use dependency injection.
So basically,
public class Main extends JavaPlugin {
#Override
public void onEnable() {
BackpackListener listener new Backpacklistener(this);
getServer().getPluginManager().registerEvents(listener, this);
}
}
public class BackpackListener implements Listener {
private Main instance;
private BackpackUtil util;
public BackpackListener(Main instance) {
this.instance = instance;
util = new BackpackUtil();
}
#EventHandler
public void onClick(InventoryClickEvent event) {
//code
util.whiteBackpack(instance);
}
public class BackpackUtil {
public Inventory whiteBackpack(Main instance) {
FileConfiguration config = instance.getConfig();
//Do things
instance.saveConfig();
}
}
The next way you can do it is less optimal, and frowned upon, but still an easier option.
public class Main() {
public static Main instance;
#Override
public void onEnable() {
instance = this;
}
}
public class ConfigHelper() {
Main instance = Main.instance;
FileConfiguration config = instance.getConfig();
//Do things
instance.saveConfig();
}
It's good to get out of the habit of using the second method (It's called a singleton), because normally the main class will change, or have multiple instances, etc... but with Spigot there can only be one main instance and one thread.

How to make wait some time in GWT after the Async call

In my code, I am making async call to do validation. Depeding upon return value of the validation, I need to execute some lines.
But I am not able to put that lines in the callback method of Async = public void success(Boolean valid).
Since one of the line is super.onDrop(context) which is method of another class that can't be called inside Async callback method.
Please see the below line. I need super.onDrop(context) will be executed after async call is completed.
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
//super.onDrop(context);
}
};
});
//condition is here
super.onDrop(context);
Is there any way, i will tell gwt wait 1 or 2 seconds before super.onDrop(context) is executed. Right now what happening is,
super.onDrop(context) is executed before the call back method is completed.
You can do:
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
drop();
}
};
});
private void drop() {
super.onDrop(context);
}
An alternative solution would be, like mentioned from Thomas Broyer in the comments:
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
ContainingClass.super.onDrop(context);
}
};
});
Eclipse does not suggests this solution when using the code completion, but it works.
Also i would possibly reconsider your design, because it can get very tricky (by experience) when you have many Callbacks which are connecting/coupling classes. But this is just a quick thought, i neither know the size of your project nor the design.

Actionscript in a single class or in multiple scenes?

I am completely new to Actionscript and Adobe Flash CS6 and for a little bit of fun I have decided to try and make a little game. I had a few newbie (or noob-y) questions to ask about a general implementation approach.
The documentation I've been reading so far suggests creating a new flash project, and then create a document class so:
package {
import flash.display.MovieClip;
public class MyMainClass extends MovieClip {
public function MyMainClass() {
}
}
}
and I am wondering if I use this MainClass to code the whole game or include actionscript within a scene and have multiple scenes, or some combination of both.
Lets say I had a wanted 5 Levels in my game, would I do something like:
package {
import flash.display.MovieClip;
public class MyMainClass extends MovieClip {
public function MyMainClass() {
StartLevel1();
StartLevel2();
StartLevel3();
StartLevel4();
StartLevel5();
}
public function StartLevel1() {
// Do something
}
public function StartLevel2() {
// Do something
}
public function StartLevel3() {
// Do something
}
public function StartLevel4() {
// Do something
}
public function StartLevel5() {
// Do something
}
}
}
or create 5 scenes with actionscript in each scene?
Can anyone provide me with a bit of a starting point?
Thanks
I don't know of anyone who has anything good to say about scenes.
However, as you intuit, the timeline itself is a wonderful tool for managing the state of your Flash assets over time. If you use it, you also get the hidden advantage that you don't have to download 100% of your file to be able to use it (so you can reduce or even eliminate the need for a preloader by unchecking "Export in frame N" on your library symbols.
Lars has quite rightly pointed out that there are very few developers who understand this technique, and I know of exactly one who can and will help people who are interested in exploring this technique. That person is helping you right now. So if you choose to go that way, keep in mind you are mostly on your own except if I happen to notice your post and respond to it.
I am not in favor of timeline scripts, with a very few exceptions. What I suggest is a "both and" approach, where you use a Document Class to control timeline instances.
Your document Class might look something like this:
public class Game extends MovieClip {
protected var _level:ILevel;//Interface your Level MovieClips will implement
protected var levelController:LevelController = new LevelControler();
protected var currentLevel:int;
protected var maxLevels:int = 5;
public function Game() {
levelController.addEventListener(LevelEventKind.LEVEL_COMPLETE, nextLevel);
levelController.addEventListener(LevelEventKind.LEVEL_FAILED, gameOver);
startLevel(currentLevel);
}
public function startLevel(levelNumber:int):void {
goToLabel('Level' + String(levelNumber));
}
public function get level():ILevel {
return _level;
}
public function set level(value:ILevel):void {
_level = value;
//internally, this should release all listeners to the last
//level object (if any) so you don't get a memory leak
levelController.level = _level;
}
protected function nextLevel(e:Event):void {
if (currentLevel < maxLevels) {
startLevel(++currentLevel);
} else {
//do you won logic here
}
}
protected function gameOver(e:Event):void {
//do bombed out logic here
}
protected function goToLabel(label:String):void {
for each (var frameLabel:FrameLabel in currentLabels) {
if (frameLabel.name==label) {
//if your swf is media-heavy, may want to check that frame
//is loaded if you chose to reduce/eliminate preloader
goToAndStop(label);
return;
}
}
trace('no such label as', label);
}
}
What this gets you is a game where you can change how the different levels look without changing a single line of ActionScript, and you can change how they work by assigning different Base Classes that implement ILevel slightly differently. You can also change your functionality by swapping out different flavors of LevelController, but your Main Document Class (Game in this instance) would be aware of this change (wheras the other changes could be made without altering Game at all).

What's the best way to get a return value out of an asyncExec in Eclipse?

I am writing Eclipse plugins, and frequently have a situation where a running Job needs to pause for a short while, run something asynchronously on the UI thread, and resume.
So my code usually looks something like:
Display display = Display.getDefault();
display.syncExec(new Runnable() {
public void run() {
// Do some calculation
// How do I return a value from here?
}
});
// I want to be able to use the calculation result here!
One way to do it is to have the entire Job class have some field. Another is to use a customized class (rather than anonymous for this and use its resulting data field, etc.
What's the best and most elegant approach?
I think the Container above is the "right" choice. It could be also be genericized for type safety. The quick choice in this kind of situation is the final array idiom. The trick is that a any local variables referenced from the Runnable must be final, and thus can't be modified. So instead, you use a single element array, where the array is final, but the element of the array can be modified:
final Object[] result = new Object[1];
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result[0] = "foo";
}
}
System.out.println(result[0]);
Again, this is the "quick" solution for those cases where you have an anonymous class and you want to give it a place to stick a result without defining a specific Container class.
UPDATE
After I thought about this a bit, I realized this works fine for listener and visitor type usage where the callback is in the same thread. In this case, however, the Runnable executes in a different thread so you're not guaranteed to actually see the result after syncExec returns. The correct solution is to use an AtomicReference:
final AtomicReference<Object> result = new AtomicReference<Object>();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result.set("foo");
}
}
System.out.println(result.get());
Changes to the value of AtomicReference are guaranteed to be visible by all threads, just as if it were declared volatile. This is described in detail here.
You probably shouldn't be assuming that the async Runnable will have finished by the time the asyncExec call returns.
In which case, you're looking at pushing the result out into listeners/callbacks (possibly Command pattern), or if you do want to have the result available at a later in the same method, using something like a java.util.concurrent.Future.
Well, if it's sync you can just have a value holder of some kind external to the run() method.
The classic is:
final Container container = new Container();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
container.setValue("foo");
}
}
System.out.println(container.getValue());
Where container is just:
public class Container {
private Object value;
public Object getValue() {
return value;
}
public void setValue(Object o) {
value = o;
}
}
This is of course hilarious and dodgy (even more dodgy is creating a new List and then setting and getting the 1st element) but the syncExec method blocks so nothing bad comes of it.
Except when someone comes back later and makes it asyncExec()..