-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGraphNode.java
More file actions
359 lines (329 loc) · 12.8 KB
/
GraphNode.java
File metadata and controls
359 lines (329 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
package graphvisualizer;
import SwingElements.Base;
import SwingElements.Canvas;
import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Random;
/**
* Nodes on the grid. Each one has a list of connected nodes.
*/
public class GraphNode extends Rectangle {
private final ArrayList<GraphTuple> connections = new ArrayList<>(); //Node-specific adjacency list. GraphTuple items hold both nodes, as well as other information
// This node is the fromLocation, while the other node is the toLocation
private final int id; //Node ID #
private final int iLoc; //Y-axis coordinate
private final int jLoc; //X-axis coordinate
private int food; //The amount of food this node currently has
private final int foodVar = 10; //The maximum amount of food the node can start with
private final int regenVar = 3; //The maximum rate at which this the regenerates food each turn
private final int regenThreshold = 1; //The minimum amount of food required for the node to regenerate food
private int regenRate; //The rate at which the node regenerates food
private Color color; //The color of the node. Should only be one of the static color variables
private boolean updated = true; //If true, the node should be drawn. If false, don't draw the node. Intended to help speed up the process
/**
* @param xloc The xLocation on the {@link Canvas} object
* @param yloc The yLocation on the {@link Canvas} object
* @param width The display width of the node on the {@link Canvas} object
* @param height The display height of the node on the {@link Canvas} object
* @param id The ID of the node, generated by the {@link Graph} object
* @param iLoc The Y coordinate of the node in the {@link Graph} matrix
* @param jLoc The X coordinate of the node in the {@link Graph} matrix
* @param food Determines if the node should be given a random amount of
* food
*/
public GraphNode(int xloc, int yloc, int width, int height, int id, int iLoc, int jLoc, boolean food) {
super(xloc, yloc, width, height);
if (food) {
Random rand = new Random();
this.food = rand.nextInt(foodVar);
this.regenRate = rand.nextInt(regenVar);
}//end if
else {
this.food = 50;
}//end else
this.id = id;
this.iLoc = iLoc;
this.jLoc = jLoc;
}//end constructor
/**
* Connects the node to another, using elements from a given
* {@link GraphTupleInfo} object
*
* @param to The {@link GraphNode} to connect to
* @param gti The {@link GraphTupleInfo} to get connection information from
* @return True if successful, false if not
*/
boolean connect(GraphNode to, GraphTupleInfo gti, int direction, double severity, boolean redundant) {
if (!isConnected(to)) { //Only try connecting to a node if it's not already connected
GraphTuple newConnection = new GraphTuple(to, this, gti);
if (Canvas.curveEnabled) {
newConnection.generateCurve(direction, severity);
newConnection.redundant = redundant;
}//end if
connections.add(newConnection);
return true;
}//end if
return false;
}//end connect
/**
* Adds a connection to the node's list of connections.
*
* @param in The {@link GraphTuple} to add
*/
void addConnection(GraphTuple in) {
connections.add(in);
}//end addConnection
/**
* Regenerates food on this node
*/
private void regenFood() {
food += regenRate;
}//end regenFood
/**
* Prints the node ID, along the IDs of connected nodes
*/
public void print() {
System.out.println("This node id: " + id);
System.out.println("Connected ids: ");
for (int i = 0; i < connections.size(); i++) {
GraphTuple gt = connections.get(i);
System.out.print(gt.getToLocation().id + " ");
}//end for
System.out.println();
}//end print
/**
* Returns a string of node coordinates, in the format x,y
*
* @return A string, containing the x and y coordinates for the node
*/
public String printCoordinates() {
return (jLoc + "," + iLoc);
}//end printCoordinates
/**
* Maps the node to new coordinates determined by click-and-drag on the
* {@link Canvas}
*
* @param x The change in the {@link Canvas} x axis
* @param y The change in the {@link Canvas} y axis
* @return A rectangle with the new coordinates, to be displayed on the
* {@link Canvas} object
*/
public Rectangle mapMovement(int x, int y) {
return new Rectangle(this.x + x, this.y + y, this.width, this.height);
}//end mapMovement
/**
* Checks if a given node is present in the node's adjacency list
*
* @param target The node to check for
* @return True if target is in the adjacency list, false if not
*/
public boolean isConnected(GraphNode target) {
for (int i = 0; i < connections.size(); i++) {
GraphTuple gt = connections.get(i);
if (gt.getToLocation() == target) {
return true;
}//end if
}//end for
return false;
}//end isConnected
/**
* Returns the first connection to this node, the "parent" connection
*
* @return The first {@link GraphTuple} object in the adjacency list.
*/
GraphTuple getParentLine() {
return connections.get(0);
}//end getParentLine
/**
* Gets the connection in the node's adjacency list at the given index
*
* @param i The index of the node to be retrieved
* @return The {@link GraphTuple} object at the given index in the adjacency
* list
*/
public GraphTuple getConnection(int i) {
return connections.get(i);
}//end getConnection
/**
* Gets the connection leading to a given node
*
* @param gn The node to be looked for
* @return The {@link GraphTuple} object connecting the node to the given
* node. Returns null if no such connection exists
*/
public GraphTuple getConnection(GraphNode gn) {
for (int i = 0; i < connections.size(); i++) {
GraphTuple gt = connections.get(i);
if (gt.getToLocation() == gn) {
return gt;
}//end if
}//end for
return null;
}//end getConnection
/**
* Removes the node's connection with a given node, on both nodes
*
* @param gn The node to sever the connection with
*/
void severConnection(GraphNode gn) {
if (isConnected(gn)) {
for (int i = 0; i < connections.size(); i++) {
if (connections.get(i).getToLocation() == gn) { //Uses toLocation because the node calling severConnection is always the fromLocation
connections.remove(i);
break;
}//end if
}//end for
}//end if
}//removeConnection
/**
* Removes all connections from the node, and removes the node from the
* adjacency lists of all connected nodes
*/
void clearConnections() {
for (int i = 0; i < connections.size(); i++) {
GraphTuple gt = connections.get(i);
Base.graph.disconnect(gt.getFromLocation(), gt.getToLocation());
i--;
}//end for
}//end clearConnections
/**
* Gets the number of connections the node has
*
* @return The number of connections the node has
*/
public int getNumberOfConnections() {
return connections.size();
}//end getNumberOfConnections
/**
* Compares the X values of the node, and the toLocation of its parent
* {@link GraphTuple}.
*
* @return The distance between the X values of the node and the toLocation
* of its parent {@link GraphTuple}
*/
int compareX() {
return jLoc - getParentLine().getToLocation().getJLoc();
}//end compareX
/**
* Compares the Y values of the node, and the toLocation of its parent
* {@link GraphTuple}
*
* @return The distance between the Y values of the node and the toLocation
* of its parent {@link GraphTuple}
*/
int compareY() {
return iLoc - getParentLine().getToLocation().getILoc();
}//end compareX
/**
* Checks if the given node is adjacent to the node. Adjacent nodes are no
* more than one space away in any direction.
*
* @param in The node to check for adjacency to
* @return True if the given node is adjacent to the node, false if not
*/
boolean isAdjacentTo(GraphNode in) {
int i = Math.abs(in.getILoc() - iLoc);
int j = Math.abs(in.getJLoc() - jLoc);
return ((i == 1 && j == 1) || (i == 1 && j == 0) || (i == 0 && j == 1));
}//end isAdjacentTo
/**
* Reduces food amount by the number of connections involving this node.
*
* @param graph The {@link Graph} object to check edges against
*/
void consume(Graph graph) {
for (int i = 0; i < connections.size(); i++) {
GraphTuple gt = connections.get(i);
if (!gt.isEdge(graph)) { //Only non-edge connections should reduce node food count
food--;
}//end if
if (food < 0) { //Food should never go negative
food = 0;
}//end if
if (food >= regenThreshold) {
regenFood();
}//end if
}//end for
}//end consume
//////////////////////////////
// Setters/Getters //
//////////////////////////////
/**
* Sets the color of the node, using a {@link Color} object. Should only use
* the static color variables for {@link GraphNode}s
*
* @param in The new color for the node
*/
public void setColor(GraphNodeColors in) {
if (color == null || (color.equals(Color.WHITE) && !in.getColor().equals(Color.WHITE))) {
updated = true;
}//end if
color = in.getColor();
}//end setColor
/**
* Sets the color of the node, using RGB values. Should not be used unless
* necessary. Instead use static {@link GraphNode} Color variables.
*
* @param rin
* @param bin
* @param gin
*/
public void setColor(int rin, int bin, int gin) {
if (color.equals(Color.WHITE) && !(new Color(rin, gin, bin)).equals(Color.WHITE)) {
updated = true;
}//end if
color = new Color(rin, gin, bin);
}//end setColor
/**
* Gets the color of the node.
*
* @return The current color of the node
*/
public Color getColor() {
return color;
}//end getColor
/**
* Gets the remaining amount of food for the node.
*
* @return The food remaining on the node
*/
int getFood() {
return food;
}//end getFood
/**
* Gets the I, or Y axis, location of the node in the {@link Graph} object
* matrix.
*
* @return The I value for the node
*/
public int getILoc() {
return iLoc;
}//end getILoc
/**
* Gets the J, or X axis, location of the node in the {@link Graph} object
* matrix.
*
* @return The J value for the node
*/
public int getJLoc() {
return jLoc;
}//end getJLoc
/**
* Returns if the node's graphics should be updated.
*
* @return The value of updated, which is true if the node needs to be
* re-drawn, and false if not
*/
public boolean isUpdated() {
return updated;
}//end isUpdated
/**
* Sets updated to reflect if the node needs to be re-drawn
*
* @param in The new value for updated
*/
public void setUpdated(boolean in) {
updated = in;
}//end updated
}//end GraphNode