Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
smackfu
Jun 7, 2004

One good reason to have unit tests is so you can refactor and know that things still work.

Adbot
ADBOT LOVES YOU

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

smackfu posted:

Run a web server on a local port.

I actually considered that, but I want to run the thing independently of a web browser.

The "desktop application-ey" things I want it to be able to do are just notifications and playing sounds with those notifications, and I know browsers are capable of it.

But like... Not everything has to be a "web app" either these days.

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Wheany posted:

I actually considered that, but I want to run the thing independently of a web browser.

The "desktop application-ey" things I want it to be able to do are just notifications and playing sounds with those notifications, and I know browsers are capable of it.

But like... Not everything has to be a "web app" either these days.

That's true, but browsers are a truly cross platform presentation layer where the platform specific issues have basically been ironed out. Depending on what you're doing, it's not a bad route.

The comedy option LibGDX suggested earlier would actually give you the Android version too :unsmigghh:

HFX
Nov 29, 2004

smackfu posted:

One good reason to have unit tests is so you can refactor and know that things still work.

Even if you aren't refactoring code, unit tests can be great if you are modifying something to make sure you don't have unintended changes. Sadly, most people do not know how to write good unit tests.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Volmarias posted:

That's true, but browsers are a truly cross platform presentation layer where the platform specific issues have basically been ironed out. Depending on what you're doing, it's not a bad route.

The comedy option LibGDX suggested earlier would actually give you the Android version too :unsmigghh:

Swing it is, then

M31
Jun 12, 2012
JavaFX seems like the more modern option

I have never used either of them though.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Looked at a JavaFX hello world thing. Seems reasonable enough. I'm going to try it.

ExcessBLarg!
Sep 1, 2001
Swing basically still works. It's not super modern, but it could be worse. Plus, "modern" is a responsive-design browser-based webapp anyways.

JavaFX might be OK, but I found it a bit sluggish and its lack of popularity wasn't worth it being "more modern". Although it's a bit awkward to do so, JavaFX widgets can be used by Swing apps and vice-versa. If for some reason you're still stuck with Java SE 7 don't use the JavaFX that comes with it, it's pretty buggy compared to the one that ships with Java SE 8.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
It's a personal toy project, no way in hell am I not using the most bleeding edge version of every library #yolo :tubular:

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

ExcessBLarg! posted:

Plus, "modern" is a responsive-design browser-based webapp anyways.

phonegap for everyone

speng31b
May 8, 2010

carry on then posted:

phonegap for everyone

I think you misspelled "React Native".

EmmyOk
Aug 11, 2013

Where is a good place to start looking at Graph Theory?

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal
I'm learning Java and decided to build a little game for my son to figure out what I don't know in the programming process. I wanted to get some practice in hitting walls so I can figure out what I need to study. I had a breakthrough moment yesterday where my brain finally clicked in thinking about objects as literal things and my classes started coming together, and I have a little typing game that works and my kid loves.

I still have a very hard time determining which methods go into which classes. What I have is kind of a mess because I wrote the logic I knew I needed, then moved it around from class to class until I was able to access and pass the right variables. There is currently way too much logic in the Main method but moving it out makes top-level variables (such as level number and score counters that are persistent through the game) really hard to work with, such as getting them back into the GUI class.

Is there a good rule of thumb to think about when I'm trying to force square methods into round classes? Or is this more of a style skill that comes with practice?

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Sounds like your software has grown to the point where you need to impose some sort of architecture on it. I'd start looking into the idea of an architectural pattern--which is a preconceived idea or template of how to organize your software--especially Model-View-Controller.

In that architecture, you would have your game loop in the controller, and it would take data (your variables) from the model and use them to tell the view (the screen) what to display. It's not the only valid way to organize your program, and too heavy reliance on pre canned architecture patterns can lead to hard to follow or maintain code, but especially when you're just starting out, it's helpful to have some guidelines and be able to say "I don't know where to put this new functionality, but it feels related to data operations, so I'll try it over with the other Model objects and see how it fits in."

As for knowing what methods go where, it's helpful to think of the objects not just as things, but actors in a simulation. So they can have data, like a character has a position, like x = 100, y = 20, but they can also take actions when commanded by the controller, like a character can move to a new position that the controller calculates and provides.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Wheany posted:

Swing it is, then

Yeah swing with a good GUI designer is still my go-to for quick GUI desktop apps. Its not perfect but it sure works.

LibGDX rules but is there really that much GUI stuff for it? I feel like you'd be re-inventing the wheel. I love it for games but ehhhh.

Yeah JavaFX should work too and be more modern than Swing.

Judge Schnoopy posted:

I'm learning Java and decided to build a little game for my son to figure out what I don't know in the programming process. I wanted to get some practice in hitting walls so I can figure out what I need to study. I had a breakthrough moment yesterday where my brain finally clicked in thinking about objects as literal things and my classes started coming together, and I have a little typing game that works and my kid loves.

I still have a very hard time determining which methods go into which classes. What I have is kind of a mess because I wrote the logic I knew I needed, then moved it around from class to class until I was able to access and pass the right variables. There is currently way too much logic in the Main method but moving it out makes top-level variables (such as level number and score counters that are persistent through the game) really hard to work with, such as getting them back into the GUI class.

Is there a good rule of thumb to think about when I'm trying to force square methods into round classes? Or is this more of a style skill that comes with practice?

You need to learn OOP. You're just kinda kludging it together right now writing C-style code in Java, which forces you to be somewhat OOP (but not necessarily) and so you've got objects but you're not really using them like objects from the sound of things.

I did the same thing when I was younger and first learning Java. I couldn't figure out the difference between static and dynamic and I ended up changing a whole stack of classes to static just so I could pass the right reference to an object and get the logic done I needed to. (WRONG!)

Really there's no answer other than go study OOP, read some books or tutorial pages on the subject. There's a whole way of thinking and organizing your code which isn't exactly a short topic and its definitely worth understanding before you write much more Java code.

Its all about cohesion and coupling when it comes to knowing which object to put the method in. But it sounds more like your problem is you put the method in the right class but then you don't know how to access it so you end up moving it to the wrong class. Need to read up on how to store object references and then create the appropriate getter methods or whatever you need to access the data.

If you want some direct tips for your current program, dump it on pastebin and I can point you in the right direction for re-engineering the classes.

Zaphod42 fucked around with this message at 17:00 on Jun 14, 2016

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

EmmyOk posted:

Where is a good place to start looking at Graph Theory?

Wikipedia?

Can you give a little more detail?

EmmyOk
Aug 11, 2013

Yeah that was stupidly vague. I'm trying to do a HackerRank problem a day while I'm writing up my thesis in order to stay sharp and one of the few domains I haven't looked at is Graph Theory. The first question is one about a snakes and ladders game where you control the outcome of the die and have to choose the minimum number of rolls on a set size board with w/e snakes and ladders are generated for that test case. I don't want to just google a S&L algorithm and have never really done any GT stuff so I am wondering what type of problems or algorithms to look at initially.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
The fundamental question is "how do I turn my scenario into a graph?"

- What should the nodes represent?
- What should the edges represent?
- What sort of property of my graph am I looking for to solve the original problem?

Coming up with answers to those questions should lead you somewhere interesting.

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

Zaphod42 posted:

You need to learn OOP. You're just kinda kludging it together right now writing C-style code in Java, which forces you to be somewhat OOP (but not necessarily) and so you've got objects but you're not really using them like objects from the sound of things.

I did the same thing when I was younger and first learning Java. I couldn't figure out the difference between static and dynamic and I ended up changing a whole stack of classes to static just so I could pass the right reference to an object and get the logic done I needed to. (WRONG!)

Really there's no answer other than go study OOP, read some books or tutorial pages on the subject. There's a whole way of thinking and organizing your code which isn't exactly a short topic and its definitely worth understanding before you write much more Java code.

Its all about cohesion and coupling when it comes to knowing which object to put the method in. But it sounds more like your problem is you put the method in the right class but then you don't know how to access it so you end up moving it to the wrong class. Need to read up on how to store object references and then create the appropriate getter methods or whatever you need to access the data.

If you want some direct tips for your current program, dump it on pastebin and I can point you in the right direction for re-engineering the classes.

As a network and system admin I'm much more familiar with scripting, and I'm finally starting to get that OOP is an entirely different animal rather than a more in-depth and versatile version of scripts.

Thanks for the offer to review what I've got, I will definitely take you up on that for pointers. I want to re-write my Control class before sending it off though. I thought it was a good idea for the game logic to be controlled in it's own class, but ended up cannibalizing it between the Level class and the Main method. Then I started learning about object references a bit more when futzing with the GUI and I think I can offload a lot back into that Control class now.

The base of the thing is currently:
Main method creates a Level object, creates the GUI, then runs a Start method in the current level object.
Level passes info to GUI for display and waits on a synced variable, GUI gets response from user and notifies Level.
Level evaluates input and if correct will pass control back to Main Method, after which the Level object is destroyed.
Main Method keeps track of level number and loops the creation of level objects until the game is over.

Like I mentioned, I'd like a Control class to take over keeping track of level numbers so my Main method doesn't store variables. I also probably need to cut back on if/thens and loops, it's my go-to crutch.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Judge Schnoopy posted:

I thought it was a good idea for the game logic to be controlled in it's own class, but ended up cannibalizing it between the Level class and the Main method. Then I started learning about object references a bit more when futzing with the GUI and I think I can offload a lot back into that Control class now.

Yeah sounds like you're getting it.

Judge Schnoopy posted:

The base of the thing is currently:
Main method creates a Level object, creates the GUI, then runs a Start method in the current level object.
Level passes info to GUI for display and waits on a synced variable, GUI gets response from user and notifies Level.
Level evaluates input and if correct will pass control back to Main Method, after which the Level object is destroyed.
Main Method keeps track of level number and loops the creation of level objects until the game is over.

Like I mentioned, I'd like a Control class to take over keeping track of level numbers so my Main method doesn't store variables. I also probably need to cut back on if/thens and loops, it's my go-to crutch.

The way I usually do games is like this:

Main method which creates a game object and calls its main method with parameters for options. Very lightweight and possibly unnecessary (could go in game class)
Game class which holds references to other major classes (Input, Graphics, Sound) and game data (level data, player variables, etc.) and features the game loop.
If there's too much game data, then create a world or level class to hold that data, and then game class gets a reference to that world/level class.
Game class is instantiated by Main and then the play() method is called, which loops forever until the user selects a quit option.

code:
public void play()
{
 Loop(forever)
 {
  checkInputs();
  processInputs();
  render();
 }
}
Is the core of any game. You check the input, process it, and then render it. Then rinse-repeat.

So I would have an Input class which would have the checkInputs() method. This just checks the keyboard/controller state and then records it somewhere that other classes will be able to access.

Then I would have either a processInputs() method (or gameTick() or whatever) in the game class or in the level class, which would read the current state of inputs by using method calls on the input class. (Either game or level, whichever does the processing, should have a reference to the Input class so they can query as necessary to see if inputs are down)

So your processInputs() would end up doing something like
code:
Input playerInput; //reference to Input class somewhere, gets assigned during construction


if(playerInput.getButton("Jump")){ //method call to Input class to retrieve input variable state
 //handle jumping
}
This way the logic for handling jumping is separated from the logic for seeing if the jump button is held down. But the logic to handle jumping can easily check if the jump button was held down by using the method on the input class.

Your game sounds like its kinda a turn-based mouse-driven game? If so then it doesn't need to exactly follow that formula, its almost more of a GUI app than a proper real-time game, so you can do a different architecture. Just kinda giving you ideas.

Sounds like Level will be able to store the game state and do calculations on it and then when you finish the level you go back to main and either quit or load a new level? That should work fine. Normally I would avoid having Level do the actual drawing but depending upon your GUI setup it might make sense.

As for using lots of if/thens and loops, don't feel bad about that actually. You see lots of newer programmers feeling uncertain about using lots of if/then or whatever, like they should be fancier and find another way to do it. But that's not necessarily the case.

Even super professional programmers still write tons of if/then/else or loops. They're fundamental blocks of logic and almost everything comes down to if/then or loops.
Its more about organizing where the if/then/else or loops are rather than getting rid of them or replacing them with something else.

Eh that was a lot of words and it probably didn't really even help much but whatever.

Zaphod42 fucked around with this message at 18:01 on Jun 14, 2016

Judge Schnoopy
Nov 2, 2005

dont even TRY it, pal

Zaphod42 posted:

Even super professional programmers still write tons of if/then/else or loops. They're fundamental blocks of logic and almost everything comes down to if/then or loops.
Its more about organizing where the if/then/else or loops are rather than getting rid of them or replacing them with something else.

Thanks for taking the time with this, it's extremely helpful. In my experience every language has an initial barrier, some concept that's foreign but absolutely required, and I feel like I just got past it with Java. I'm trying to pick up as much information as I can now that I can internalize what it means and how it's used.

So as a bit more background, it's a very simple typing game. Display a word in a jlabel, accept typing in a text box, compare the typed word to the original word. If it doesn't match, it displays a new frame for 1.7 seconds that says "WRONG! You have (x) chances left", and after 3 wrongs it displays a Game Over frame (that exits the program on close but I'll eventually add a proper menu with new game / quit options). If the typed word matches, it displays a frame that says CORRECT! for 1.7 seconds and then the game moves on to the next level. After 5 levels, game says You Win! and I want it to eventually display a high score list (score being number of letters - misses for each level).

Based on your recommendations I think I'm going to tackle my issues with 2 classes - a Main Menu / high level controller class that instantiates the whole game and GUI, and a Control class that handles a current game / passing from level to level / keeping score.

I feel like I'm getting to "nesty" with these classes though. Instead of having a number of objects on the same level interacting with one-another, I'll have Main -> creates Menu -> creates Control (game) -> creates Level. Is this normal?

Again I'm very new at this so real-time is way out of my league. I'm still figuring out how to draw pictures within my frames to spruce up the UI, and play sounds with the Correct or Wrong frames.

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Judge Schnoopy posted:

I feel like I'm getting to "nesty" with these classes though. Instead of having a number of objects on the same level interacting with one-another, I'll have Main -> creates Menu -> creates Control (game) -> creates Level. Is this normal?

Yes, that's not only normal, it's good! It means you're breaking down your game into cohesive pieces that do one thing, and that only really know about the objects they need to in order to do that thing. This will make your code easier to follow, and easier to extend later.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.
Yeah like carry on said that's fine. The only issue is if menu creates control, and control creates level, if for some reason level needs a reference to menu or menu needs a reference to control, you'll have to find a way to pass that reference through the chain (or make one / all of them singletons lol)

But that may not even be something that you have to do. Its fine.

Like I said your use case is kinda different since its mostly just driven by GUI elements and halts until the user clicks on something.

But yeah, if anything "nesty" is probably a good way to go. Having a "god-class" that manages everything is generally a no-no, although if that god class simply invokes methods on other classes and delegates to them it can be okay too.

But even in the example I gave before where I had one big Game class that handled most things, it still doesn't touch several types of objects. The Game invokes a method call on World, and then World handles things from there. And then Game invokes something on the Sound class, but the Sound class actually handles playing the .wav or .mp3 files and the Game class never touches those objects and never needs to know anything about them.

The more you can break up the logic the better.

There's two major concepts involved here:

Coupling is how strongly two objects rely and interact with each other. Low coupling means the classes are highly independent, they each just kinda do their thing, and that's the ideal.

Cohesion is how strongly a single class belongs together. High cohesion means a class has a clear function and everything inside that class serves to fulfill that function and only that function.

High Cohesion and Low Coupling is a goal for almost all software. It means the software is easier to understand and maintain.

"God-classes" that end up micromanaging everything are very low cohesion. But a management class that dictates to other class' methods is okay.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

Zaphod42 posted:

You need to learn OOP. You're just kinda kludging it together right now writing C-style code in Java, which forces you to be somewhat OOP (but not necessarily) and so you've got objects but you're not really using them like objects from the sound of things.

I did the same thing when I was younger and first learning Java. I couldn't figure out the difference between static and dynamic and I ended up changing a whole stack of classes to static just so I could pass the right reference to an object and get the logic done I needed to. (WRONG!)

Thank you so much for your recent string of posts, it's really made me snap out of my old ways (I've been primarily using bash/korn) and reevaluate how to handle things in a more OOP way (and get my mind completely around getter/setters). I just reworked my recent code (which worked) into legitimate objects which handle private info instead of just a giant pile of public statics and it flows much better now.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

PierreTheMime posted:

Thank you so much for your recent string of posts, it's really made me snap out of my old ways (I've been primarily using bash/korn) and reevaluate how to handle things in a more OOP way (and get my mind completely around getter/setters). I just reworked my recent code (which worked) into legitimate objects which handle private info instead of just a giant pile of public statics and it flows much better now.

:yeah:

Glad to hear it. Its definitely confusing and overwhelming at first, but once you get the hang of thinking the OOP philosophy way, it ends up making everything more organized.

I totally did the giant pile of public static things once upon a time.

And like you mention, that can totally work! But for most applications doing some OOP makes it faster to write, easier to read, and easier to maintain/update.

Nude
Nov 16, 2014

I have no idea what I'm doing.

Judge Schnoopy posted:

Again I'm very new at this so real-time is way out of my league. I'm still figuring out how to draw pictures within my frames to spruce up the UI, and play sounds with the Correct or Wrong frames.

For what books to read when designing games/oop in general one I would recommend (free!) is this: Game Programming Patterns. Has a section on game loops which is what Zaphod mentioned if you are curious. When I first started this was kind of the only thing that made some sort of sense to me. And the article that made me "get" classes/objects was this one. If you can't tell I stumbled into programming cause I wanted to make a game ha ha.

Zaphod42 posted:

There's two major concepts involved here:

Coupling is how strongly two objects rely and interact with each other. Low coupling means the classes are highly independent, they each just kinda do their thing, and that's the ideal.

Cohesion is how strongly a single class belongs together. High cohesion means a class has a clear function and everything inside that class serves to fulfill that function and only that function.

I just realized that I only knew a vague idea what those two words meant (programming wise), and really happy that you cleared that up. Another term I could never get a clear definition on is "wrapping". When I finally looked it up I was like huh so I guess I'm not the only one who does that. Doesn't help that people use that term as both a design philosophy and for text.

Nude fucked around with this message at 04:37 on Jun 16, 2016

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord
What's the best way to combine multiple string arrays into clusters based on a contained value? I need to group "Task" items together with their "Predecessor"s into a master list that I can iterate through and apply the information elsewhere. The problem here is that Predecessors can vary between 1 and ~15. I'm sure there's a simple way to do it but I'm fresh enough to this that it's driving me crazy. I was thinking of <List<List<String[]>>> and addressing the various aspects of that aren't the issue, it's properly adding the inner List to the outer List when it's determined it's the end of a Task.

For instance:
code:
Task:::R02.JU.R02A_DORFW:::2:::2:::1
Predecessor:::1:::ANY_OK
Task:::R02.JU.R02P_DOMOQ:::2:::3:::2
Predecessor:::1:::ANY_OK
Task:::R02.JU.R02A_Q12FW:::3:::4:::1
Predecessor:::3:::ANY_OK
Predecessor:::62:::ANY_OK
Task:::R02.JU.R02A_12RS1:::4:::5:::1
Predecessor:::4:::ANY_OK
So ultimately I'm looking for:
code:
Outer List? Inner List?   String[]
1           1             Task:::R02.JU.R02A_DORFW:::2:::2:::1
            2             Predecessor:::1:::ANY_OK
2           1             Task:::R02.JU.R02P_DOMOQ:::2:::3:::2
            2             Predecessor:::1:::ANY_OK
3           1             Task:::R02.JU.R02A_Q12FW:::3:::4:::1
            2             Predecessor:::3:::ANY_OK
            3             Predecessor:::62:::ANY_OK
etc...

I'm sure it's something simple but I'd value some input both for help and to see if there's a better way to do this.

EmmyOk
Aug 11, 2013

Jabor posted:

The fundamental question is "how do I turn my scenario into a graph?"

- What should the nodes represent?
- What should the edges represent?
- What sort of property of my graph am I looking for to solve the original problem?

Coming up with answers to those questions should lead you somewhere interesting.

I thought about these when I went for my swim and they helped a lot, thanks so much!

pigdog
Apr 23, 2004

by Smythe

PierreTheMime posted:

What's the best way to combine multiple string arrays into clusters based on a contained value? I need to group "Task" items together with their "Predecessor"s into a master list that I can iterate through and apply the information elsewhere. The problem here is that Predecessors can vary between 1 and ~15. I'm sure there's a simple way to do it but I'm fresh enough to this that it's driving me crazy. I was thinking of <List<List<String[]>>> and addressing the various aspects of that aren't the issue, it's properly adding the inner List to the outer List when it's determined it's the end of a Task.

For instance:
code:
Task:::R02.JU.R02A_DORFW:::2:::2:::1
Predecessor:::1:::ANY_OK
Task:::R02.JU.R02P_DOMOQ:::2:::3:::2
Predecessor:::1:::ANY_OK
Task:::R02.JU.R02A_Q12FW:::3:::4:::1
Predecessor:::3:::ANY_OK
Predecessor:::62:::ANY_OK
Task:::R02.JU.R02A_12RS1:::4:::5:::1
Predecessor:::4:::ANY_OK
So ultimately I'm looking for:
code:
Outer List? Inner List?   String[]
1           1             Task:::R02.JU.R02A_DORFW:::2:::2:::1
            2             Predecessor:::1:::ANY_OK
2           1             Task:::R02.JU.R02P_DOMOQ:::2:::3:::2
            2             Predecessor:::1:::ANY_OK
3           1             Task:::R02.JU.R02A_Q12FW:::3:::4:::1
            2             Predecessor:::3:::ANY_OK
            3             Predecessor:::62:::ANY_OK
etc...

I'm sure it's something simple but I'd value some input both for help and to see if there's a better way to do this.

I think you might have something called Primitive Envy where you just see collections of primitive types, rather than objects. In Java it's okay to create a new class, inner or regular, for this kind of thing. Something like

code:

public class Task {
   private String name;
   private List<String> predecessors = new ArrayList<>();

   public Task(String name) {
      this.name = name;
   }

   public String getName() {
      return this.name;
   }

   public void addPredecessor(String predecessor) {
      this.predecessors.add(predecessor);
   }

   public List<String> getPredecessors() {
      return this.predecessors;
   }
}
Then you can just have a List<Task> you may populate, and later process using the Stream API or whatever. Can also do the parsing of the raw things in the same class.

pigdog fucked around with this message at 22:41 on Jun 16, 2016

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

PierreTheMime posted:

What's the best way to combine multiple string arrays into clusters based on a contained value? I need to group "Task" items together with their "Predecessor"s into a master list that I can iterate through and apply the information elsewhere. The problem here is that Predecessors can vary between 1 and ~15. I'm sure there's a simple way to do it but I'm fresh enough to this that it's driving me crazy. I was thinking of <List<List<String[]>>> and addressing the various aspects of that aren't the issue, it's properly adding the inner List to the outer List when it's determined it's the end of a Task.

If you just need a collection of Tasks and a bunch of things associated with each of them, you could use a Map with the Tasks as keys and a List of Predecessors as the values. So Map<Task, List<Predecessor>> (or String if they're both just strings)

If you need the Tasks to be in order, you could use a LinkedHashMap, and then the key iterator will spit them out in the order you added them. There might be a better way to do it (depending on exactly how you're processing things, speed and memory requirements etc) but that's a pretty simple lookup system

e- the above is a better way if you're fine with creating a type to organise things better, or you're able to modify an existing one without polluting it with another class's organisational junk. You can get clever with Collections but you eventually hit a point where you're just trying to macgyver a state object without any of the benefits

baka kaba fucked around with this message at 21:26 on Jun 16, 2016

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.
Yeah just like pigdog said, I'd have a class with an arraylist of predecessors, then you can add them easily one by one, and then later when you have to process them you just get the list and iterate through it. If there's nested predecessors then you can just look up the lists for each of those.

In fact you could change it from

private List<String> predecessors = new ArrayList<>();

to

private Map<String, Task> predecessors = new HashMap<String, Task>();

Then you can insert the string number along with a reference to the other Task object itself,

And then you can just

code:
For(String s : predecessors.keySet()){
    Task prerequisateTask = predecessors.get(s);
     //make nested call with prerequisateTask
     process(prerequisateTask);
}
//all predecessors handled
Something like that. Just be careful there's no circular references, or you'll have to add code to track the already completed list.

Hah, my approach is kinda a mix of pigdog's and Baka kaba's.

CPColin
Sep 9, 2003

Big ol' smile.
Except don't iterate over a Map's key set, calling Map.get() with each key. Instead, iterate over the Map's entry set and save yourself a pile of lookups.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

pigdog posted:

I think you might have something called Primitive Envy where you just see collections of primitive types, rather than objects. In Java it's okay to create a new class, inner or regular, for this kind of thing. Something like

code:


public class Task {
   private String name;
   private List<String> predecessors = new ArrayList<>();

   public Task(String name) {
      this.name = name;
   }

   public String getName() {
      return this.name;
   }

   public void addPredecessor(String predecessor) {
      this.predecessors.add(predecessor);
   }

   public void getPredecessors() {
      return this.predecessors;
   }
}

Then you can just have a List<Task> you may populate, and later process using the Stream API or whatever. Can also do the parsing of the raw things in the same class.

I most definitely need to get into a more "Java" mindset about my approaches. I'm sure it will come with time and experience.

Makes total sense, I really appreciate it. I'll play around with it in the office tomorrow. Thanks for letting me bounce my beginner's problems off you all.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

CPColin posted:

Except don't iterate over a Map's key set, calling Map.get() with each key. Instead, iterate over the Map's entry set and save yourself a pile of lookups.

That's true, unless you need the strings as well for some reason. But you don't here so there's no reason not to do that. :doh:

You could use the strings to track which you've already done but you can just keep a list of Task references too so yeah.

For that matter I guess there's no point even bothering with a map if you can do all the references ahead of time and don't need to check them. And you can always check the string number off the Task object itself... so just have a List<Task>

FateFree
Nov 14, 2003

Zaphod42 posted:

That's true, unless you need the strings as well for some reason. But you don't here so there's no reason not to do that. :doh:

You could use the strings to track which you've already done but you can just keep a list of Task references too so yeah.

For that matter I guess there's no point even bothering with a map if you can do all the references ahead of time and don't need to check them. And you can always check the string number off the Task object itself... so just have a List<Task>

The Entry object has access to the keys as well, its just entry.getKey and entry.getValue.

evilentity
Jun 25, 2010
How amusing, turns out I have a need to make gui app now. My first choice is gdx, but learning a bit about javafx thing probably wont hurt.

Anyway, how do you print stuff with java? Ive seen javax.print and awt.print, any of these any good? Or is there something nicer? All i need is to print a bitmap.

Volguus
Mar 3, 2009

evilentity posted:

How amusing, turns out I have a need to make gui app now. My first choice is gdx, but learning a bit about javafx thing probably wont hurt.

Anyway, how do you print stuff with java? Ive seen javax.print and awt.print, any of these any good? Or is there something nicer? All i need is to print a bitmap.

Yes, that's ok. And if you only have to print a bitmap is relatively easy. For a small tutorial: https://docs.oracle.com/javase/tutorial/2d/printing/

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

pigdog posted:

I think you might have something called Primitive Envy where you just see collections of primitive types, rather than objects. In Java it's okay to create a new class, inner or regular, for this kind of thing. Something like

Alright, I've reworked my processing to read through the initial file and create a String array and then assign the various split values to aspects of WorkflowTask and Predecessor objects. This seems to work well enough for my purposes:
code:
int tasknum = 0;
for (String line: array) {
			
	//Break current line array into constituent values
	String[] lineitems = line.split(":::");
			
	//If line contains Task information, create Task and fill info
	if (lineitems[0].contains("Task")) {
		WorkflowTask newtask = new WorkflowTask();
		newtask.setTaskname(lineitems[1]);
		newtask.setColumn(Integer.parseInt(lineitems[2]));
		newtask.setLnr(Integer.parseInt(lineitems[3]));
		newtask.setRow(Integer.parseInt(lineitems[4]));
		wfprof.addWorkflowTask(newtask);
		tasknum++;
	}
	//If line contains Predecessor information, create Predecessor and fill info
	if (lineitems[0].contains("Predecessor")) {
		Predecessor newpred = new Predecessor();
		newpred.setLnr(Integer.parseInt(lineitems[1]));
		newpred.setStatus(lineitems[2]);
		wfprof.getTask(tasknum).addPredecessor(newpred);
	}
}
My issue with this method is that I still feel there's a better way to verify which the line contains (task/predecessor) and assign it to the appropriate object. Is my simple loop/if logic okay or should I be considering something better? (My tasknum variable starts at 1 because the wfprof object already contains a "start" task as item 0 upon construction)

Right now my code is returning correct information, but I want to learn as much as I can through this whole ordeal so I'd love comments/opinions from more experienced people.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.
That seems okay, although rather than storing the primitive numbers, I would just directly store a reference to the other object.

code:
Predecessor newpred = new Predecessor();
newpred.setLnr(Integer.parseInt(lineitems[1]));
newpred.setStatus(lineitems[2]);
wfprof.getTask(tasknum).addPredecessor(newpred);
I would change it so that you have it more like

code:
newpred.setLnr(wfprof.getTask(Integer.parseInt(lineitems[1])));
You'd have to change it from an Int to a Task reference, but then you can just directly access and call methods on the task object of the predecessor rather than having to do a lookup off the number. Not really a big deal but can be more convenient.

Then in the future you can just do predecessor.getLnr().doStuff(); when you want to access a predecessor's task.

I dunno what .getLnr() is supposed to mean, line... number? so I'd make it like .setTask() and .getTask() instead.

Adbot
ADBOT LOVES YOU

pigdog
Apr 23, 2004

by Smythe
Looks pretty good. As Zaphod42 said, I would rather just have the whole newtask around, rather than just the index variable.

I might also get bored of reading all those Integer.parseInt()'s and overload methods in WorkflowTask and Predecessor to also accept String's.
code:
// in WorkflowTask.java

// existing setter
public void setColumn(Integer column) {
  ...
}

// added setter
public void setColumn(String column) {
  setColumn(Integer.parseInt(column)); // calls the one that accepts an Integer
}
So then you could just write newtask.setColumn(lineitems[2]); and it would be a bit clearer. Clarity is good. Always use nice and proper English names for things. You'll thank yourself when you need to change the code 6+ months later.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply