Professional Documents
Culture Documents
INGENIEURSWETENSCHAPPEN
TECHNOLOGIECAMPUS GENT
Pieter DEPAMELAERE
Simon DESCHUYTTER
Academiejaar 2015-2016
Inhoudstafel
/CubeThesis
/src
/cbthFileChooser
/CBTHFileChooser .java ............................................. 1
/CBTHFileView .java ................................................ 4
/EigExtFilter .java ................................................ 6
/FileIO .java ...................................................... 7
/ImageFilter .java ................................................ 12
/ImagePreview .java ............................................... 13
/Utils .java ...................................................... 15
/comparators
/IdCBTHSettingComparator .java .................................... 16
/LabelTextCBTHSettingComparator .java ............................. 16
/TypeCBTHSettingComparator .java .................................. 16
/connection
/connection.conWithCamera
/CamLiveStreamThread .java .................................. 17
/CamTakePicture .java ....................................... 19
/connection.conWithRobot
/CommunicationRobotThread .java ............................. 20
/console
/ConsoleCommands .java ............................................ 24
/ConsoleInputListener .java ....................................... 28
/ConsoleOutputStream .java ........................................ 30
/ViewConsolePanel .java ........................................... 32
/exceptions
/CubeletAlreadyAssignedException .java ............................ 39
/FaceletColorNoneException .java .................................. 40
/NoCaptureDevConnectionException .java ............................ 41
/NoImageForColorEstimationException .java ......................... 41
/NoMatchingSettingTypeException .java ............................. 42
/NonExistingCubeletException .java ................................ 43
/NoSuchSettingFoundException .java ................................ 44
/NotAvailableException .java ...................................... 44
/NotIntendedIPAddressException .java .............................. 45
/NoValidFileException .java ....................................... 45
/NumberNotFoundException .java .................................... 46
/WorkInProgressException .java .................................... 46
i CubeThesis™ Depamelaere-Deschuytter
/listeners
/aut
/B_AUT_AutomaticRoutineListener .java ....................... 47
/B_AUT_CommandToRobotListener .java ......................... 48
/B_AUT_StopAutoRoutineListener .java ........................ 48
/T_AUT_SubTasksItemListener .java ........................... 49
/cam
/B_CAM_ConnectCamListener .java ............................. 50
/B_CAM_ConnectRobotListener.java ............................ 50
/B_CAM_TakeAPictureListener .java ........................... 51
/T_CAM_LiveStreamItemListener .java ......................... 52
/cbthsettings
/MenuItemSortListener .java ................................. 55
/TF_SettingsCustomizerDocumentListener .java ................ 56
/TF_VisualCBTHSettingListener .java ......................... 57
/cube
/B_CUBE_AssignToMainCubeFaceListener .java .................. 58
/B_CUBE_BuildVirtualCubeListener .java ...................... 59
/B_CUBE_DeleteCubeFaceListener .java ........................ 60
/B_CUBE_NextCubeFaceListener .java .......................... 61
/B_CUBE_PreviousCubeFaceListener .java ...................... 62
/B_CUBE_TurnCFace90Degrees .java ............................ 63
/Co_CUBE_ColorsOnCubeFaceDropdownListener .java ............. 64
/Co_CUBE_MainCFacesDropdownListener .java ................... 66
/img
/B_IMG_BrowseImageListener .java ............................ 67
/B_IMG_ColorCalibrationListener .java ....................... 67
/B_IMG_ColorEstimationListener .java ........................ 68
/B_IMG_DeleteImageListener .java ............................ 69
/B_IMG_SaveImagesListener .java ............................. 69
/B_IMG_UpdateCropParamListener .java ........................ 70
/Co_IMG_CBTHImagesListDropdownListener .java ................ 71
/S_IMG_CropSpinnersListener .java ........................... 72
/menu
/MenuItemAboutListener .java ................................ 74
/MenuItemConsoleClearListener .java ......................... 75
/MenuItemCustomizeSettingsListener .java .................... 76
/MenuItemExitListener .java ................................. 77
/MenuItemExportSettingsToText .java ......................... 78
/MenuItemImportSettingsFromText .java ....................... 78
/MenuItemJavaDocListener .java .............................. 79
/MenuItemListCommandsListener .java ......................... 80
/MenuItemNewProjectListener .java ........................... 82
/MenuItemOpenProjectListener .java .......................... 83
/MenuItemRestoreFactorySettings .java ....................... 84
/MenuItemSaveAsProjectListener .java ........................ 84
/MenuItemSaveProjectListener .java .......................... 85
/MenuItemUserManualListener .java ........................... 86
/solv
/B_SOLV_BlenderGUIListener .java ............................ 88
/B_SOLV_CubeToSolverListener .java .......................... 89
/B_SOLV_EnumerateMovesListener .java ........................ 91
/B_SOLV_MoveSeqToRobotListener .java ........................ 92
/main
/Main .java ....................................................... 93
ii CubeThesis™ Depamelaere-Deschuytter
/model
/AutomaticRoutine .java ........................................... 96
/CBTHImage .java ................................................. 102
/CBTHImagesList .java ............................................ 106
/CBTHSetting .java ............................................... 109
/CBTHSettingsList .java .......................................... 112
/ColorEstimation .java ........................................... 129
/CommandSeq .java ................................................ 136
/CommonObjects .java ............................................. 145
/CubeConfiguration .java ......................................... 147
/CubeFace .java .................................................. 161
/CubeFacesList .java ............................................. 165
/solver.solverJS
/algorithm
/CubePosition .java ........................................ 169
/CubieSettings .java ....................................... 182
/MoveSequence .java ........................................ 183
/Solver .java .............................................. 190
/SolverAntiSlice .java ..................................... 194
/SolverKociemba .java ...................................... 203
/SolverSlice .java ......................................... 216
/SolverSquare .java ........................................ 224
/SolverTwoGen .java ........................................ 233
/viewSolverJS
/Cubie .java ............................................... 241
/SymButton .java ........................................... 255
/Viewer .java .............................................. 261
/Viewer3D .java ............................................ 265
/ViewerBox .java ........................................... 276
/ViewerDiag .java .......................................... 282
/ViewerFlat .java .......................................... 287
/view
/view.scrollImageView
/Corner .java .............................................. 290
/Ruler .java ............................................... 291
/ScrollablePicture .java ................................... 293
/ScrollImageJPanel .java ................................... 295
/TransparentSplashScreen .java ................................... 297
/ViewCubeThesis .java ............................................ 298
/ViewTabPanel0Cam .java .......................................... 304
/ViewTabPanel1Img .java .......................................... 306
/ViewTabPanel2Cub .java .......................................... 312
/ViewTabPanel3Sol .java .......................................... 316
/ViewTabPanel4Aut .java .......................................... 318
/ViewTabSubPanelAut .java ........................................ 322
/VisualCBTHSetting .java ......................................... 324
/VisualCBTHSettingsCustomizer .java .............................. 325
/VisualCubeFace .java ............................................ 327
1 package cbthFileChooser;
2
3 import java.awt.*;
4 import java.io.*;
5 import javax.swing.*;
6
7 import model.CBTHSettingsList;
8 import model.CommonObjects;
9
10 public class CBTHFileChooser extends JFileChooser {
11
12 private static final long serialVersionUID = 1L;
13 public static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private JFrame parent;
15
16 // Constructors:
17 public CBTHFileChooser() {
18
19 // Set up the file chooser by invoking the 'super'() constructor:
20 super();
21
22 /*
23 * To give pop-up filechooser-window the Rubik's logo, a custom
24 * parent-JFrame object is created.
25 */
26 parent = cbthsl.createCubeThesisFrame(null);
27 this.createDialog(parent);
28
29 // Add custom icons for file types:
30 this.setFileView(new CBTHFileView());
31
32 // Add the preview pane:
33 this.setAccessory(new ImagePreview(this));
34
35 // Set the defaultLocation:
36 this.setCurrentDirectory(cbthsl.getCurrentProject());
37
38 }
39
40 // Instance methods:
41 /**
42 * Spawns the 'browsing' window on the screen.
43 *
44 * @param mode
45 * Specifies whether an image=0/savefile=1 is to be loaded.
46 * @return Mere a File (=filepath) is returned, so the actual interpreting of
47 * the data happens elsewhere.
48 */
49 public File fcOpenFile(int mode) {
50
51 /*
52 * Depending whether a savefile or an image is to be loaded (modus-param),
53 * the other filefilters are applied. The default location is specified.
54 */
55 switch (mode) {
56 default:
57 this.setAcceptAllFileFilterUsed(true);
58 break;
59 case 0:
60 System.out.println("FileChooser will load an image...");
61 this.addChoosableFileFilter(new ImageFilter());
62 this.setFileSelectionMode(JFileChooser.FILES_ONLY);
63 this.setAcceptAllFileFilterUsed(false);
64 break;
65 case 1:
66 System.out.println("FileChooser will load a CubeThesis-Savefile...");
67 this.setCurrentDirectory(new File(cbthsl.getCurrentProject().getParent()));
68 this.addChoosableFileFilter(new EigExtFilter());
69 this.setFileSelectionMode(JFileChooser.FILES_ONLY);
70 this.setAcceptAllFileFilterUsed(true);
71 break;
72 }
73
74 // Pop-up the dialog:
75 int returnVal = this.showDialog((Component) parent, "Open");
76
77 // Process the results:
78 File file = null;
79 if (returnVal == JFileChooser.APPROVE_OPTION) {
80 file = this.getSelectedFile();
81 if (mode == 1) {
82 cbthsl.setCurrentProject(new File(file.getParent()));
83 }
84 }
85
86 else {
87 System.out.println("FileChooser cancelled.");
88 }
89 // Reset the file chooser for the next time it's shown:
90 this.setSelectedFile(null);
91
92 /*
93 * There's is only 1 CBTHFileChooser object in CubeThesis, that is recycled
94 * all the time. Opening/Saving of different file-formats require their
95 * proper FileFilters. So at the end of use, we remove all the applied
96 * FileFilters.
97 */
98 while (this.getFileFilter() != null) {
99 this.removeChoosableFileFilter(this.getFileFilter());
100 }
101
102 return file;
103 }
104
105 /**
106 * This method will be invoked when 'Saving As...', as is to say, when the
107 * name of the file or location needs to be changed.
108 *
109 * @param mode
110 * The modus alters certain settings of the filechooserobject.
111 * @return The File (=Filepath) where user wants CubeThesis to write the file.
112 */
113 public File fcSaveFile(int mode) {
114 // At this point, there's no switch construction required here.
115 // Only mode/case 0 is addressed.
116 switch (mode) {
117 default:
118 this.setAcceptAllFileFilterUsed(true);
119 break;
120 case 0:
121 System.out.println("FileChooser will save images...");
122 this.setCurrentDirectory(cbthsl.getCurrentProject());
123 this.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
124 this.addChoosableFileFilter(new ImageFilter());
125 this.setAcceptAllFileFilterUsed(true);
126 break;
127 case 1:
128 System.out.println("FileChooser will save current project...");
129 this.setCurrentDirectory(cbthsl.getCurrentProject());
130 this.setFileSelectionMode(JFileChooser.FILES_ONLY);
131 this.addChoosableFileFilter(new EigExtFilter());
132 this.setAcceptAllFileFilterUsed(true);
133 break;
134 }
135
136 File fileToSave = null;
137 this.setSelectedFile
138 (new File("- Don't type here, navigate into the folder where "
139 + "the project needs to be saved. -"));
140 int returnVal = this.showDialog((Component) parent, "Save img/proj");
141
142 if (returnVal == JFileChooser.APPROVE_OPTION) {
143
144 fileToSave = this.getCurrentDirectory();
145 cbthsl.setCurrentProject(fileToSave);
146 switch (mode) {
147 default:
148 break;
149 case 0:
150 FileIO.savePhysicalImages();
151 break;
152 case 1:
153 FileIO.saveProject();
154 break;
155 }
156 }
157
158 else {
159 System.out.println("FileChooser cancelled.");
160 }
161
162 this.setSelectedFile(null);
163
164 /*
165 * There's is only 1 CBTHFileChooser object in CubeThesis, that is recycled
166 * all the time. Opening/Saving of different file-formats require their
167 * proper FileFilters. So at the end of use, we remove all the applied
168 * FileFilters.
169 */
170 while (this.getFileFilter() != null) {
171 this.removeChoosableFileFilter(this.getFileFilter());
172 }
173 return fileToSave;
174 }
175 }
1 package cbthFileChooser;
2
3 import java.io.File;
4 import javax.swing.*;
5 import javax.swing.filechooser.*;
6
7 import model.CommonObjects;
8
9 public class CBTHFileView extends FileView {
10
11 private static ImageIcon jpgIcon = createImageIcon("JPG-icon.png");
12 private static ImageIcon gifIcon = createImageIcon("GIF-icon.png");
13 private static ImageIcon tiffIcon = createImageIcon("TIFF-icon.png");
14 private static ImageIcon pngIcon = createImageIcon("PNG-icon.png");
15 private static ImageIcon bmpIcon = createImageIcon("BMP-icon.png");
16 private static ImageIcon cbthExtensionIcon = createImageIcon("CBTH-icon.png");
17
18 // Constructors: Calling this constructor can be omitted. Nothing new happens.
19 public CBTHFileView() {
20 super();
21 }
22
23 // Getters:
24 public String getDescription(File f) {
25 return null; // let the L&F FileView figure this out
26 }
27
28 public Icon getIcon(File f) {
29 String extension = Utils.getExtension(f);
30 Icon icon = null;
31
32 if (extension != null) {
33 switch (extension) {
34 default:
35 break;
36 case Utils.jpeg:
37 case Utils.jpg:
38 icon = jpgIcon;
39 break;
40 case Utils.png:
41 icon = pngIcon;
42 break;
43 case Utils.gif:
44 icon = gifIcon;
45 break;
46 case Utils.tiff:
47 case Utils.tif:
48 icon = tiffIcon;
49 break;
50 case Utils.bmp:
51 icon = bmpIcon;
52 break;
53 case Utils.cbthExtension:
54 icon = cbthExtensionIcon;
55 break;
56 }
57
58 }
59 return icon;
60 }
61
62 public String getName(File f) {
63 return null; // let the L&F FileView figure this out
64 }
65
66 public String getTypeDescription(File f) {
1 package cbthFileChooser;
2
3 import java.io.File;
4 import javax.swing.filechooser.*;
5
6 public class EigExtFilter extends FileFilter {
7
8 // Instance methods:
9 /** Accepts directories and the cbthExtension. */
10 public boolean accept(File f) {
11 if (f.isDirectory()) {
12 return true;
13 }
14
15 String extension = Utils.getExtension(f);
16 if (extension != null) {
17 if (extension.equals(Utils.cbthExtension)) {
18 return true;
19 } else {
20 return false;
21 }
22 }
23 return false;
24 }
25
26 // Getters:
27 // The description of this filter:
28 public String getDescription() {
29 return "CubeThesis savefiles only (." + Utils.cbthExtension + ")";
30 }
31 }
1 package cbthFileChooser;
2
3 import java.io.*;
4 import java.text.DateFormat;
5 import java.text.SimpleDateFormat;
6 import java.util.Date;
7
8 import exceptions.NoValidFileException;
9 import model.*;
10
11 public class FileIO {
12
13 private static CBTHImagesList imgl;
14 private static CubeFacesList cfl;
15 private static CBTHSettingsList cbthsl;
16
17 // Constructors:
18 public FileIO(CBTHImagesList imgl, CubeFacesList cfl) {
19
20 // Als deze mappen nog niet zouden bestaan kunnen ze nog worden aangemaakt,
21 // bestonden ze wel imgl, dan worden ze niet overschreven
22 FileIO.imgl = imgl;
23 FileIO.cfl = cfl;
24 FileIO.cbthsl = CommonObjects.getCBTHSettingsList();
25 }
26
27 // Static methods:
28 /**
29 * Opens a project from a certain savefile.
30 *
31 * @param cbthFile
32 * The savefile was acquired by the cbthfilechooser.
33 */
34 public static void openProject(File cbthFile) {
35
36 try {
37 if (cbthFile == null) {
38 throw new NoValidFileException(".cbth");
39 }
40
41 FileInputStream fis = null;
42 DataInputStream dis = null;
43 System.out.println("Project will be loaded from file: " + cbthFile);
44
45 // Before reading the saveFile, current data is reset:
46 imgl.deleteAllCBTHImages();
47 cfl.deleteAllCubeFaces();
48 cfl.resetMainCubeFaces();
49 CubeConfiguration.setStartCubeletPerm(null);
50 CubeConfiguration.setStartCubeletOri(null);
51 CubeConfiguration.setStartFaceOri(null);
52 CubeConfiguration.setColorMapKey(null);
53 CommandSeq.stopAsQuicklyAsPossile();
54 CommandSeq.setSolutionCommandsMatrix(null, null, 0);
55
56 try {
57 boolean stop = false;
58 try {
59 fis = new FileInputStream(cbthFile);
60 dis = new DataInputStream(fis);
61 } catch (FileNotFoundException fnfe) {
62 stop = true;
63 System.err.println("ERROR: Specified file couldn't be found.");
64 }
65
66 boolean[] dataBlockSystem;
67
68 while (!stop) {
69 try {
70 int amountDataBlocks = dis.readInt();
71 dataBlockSystem = new boolean[amountDataBlocks];
72
73 for (int q = 0; q < amountDataBlocks; q++) {
74 dataBlockSystem[q] = dis.readBoolean();
75 }
76
77 // BLOCK 0: Read image-references +
78 // loading the images to the CBTHImagesList.
79 if (dataBlockSystem[0]) {
80 imgl.cbthImagesListFromSaveFile(dis);
81 System.out.println("Image-references were loaded properly.");
82 }
83
84 // BLOCK 1: Loading mainCubeFaces & CubeFaces to their
85 // respective lists.
86 if (dataBlockSystem[1]) {
87 // Loading MainCubeFaces:
88 cfl.mainCubeFacesFromSaveFile(dis);
89 System.out.println("Main-cubefaces were loaded properly.");
90
91 // Loading CubeFaces:
92 cfl.cubeFacesFromSaveFile(dis);
93 System.out.println("Cubefaceslist was loaded properly.");
94 }
95
96 // BLOCK 2: Potential Cube-configuration is loaded.
97 if (dataBlockSystem[2]) {
98 CubeConfiguration.cubeConfigFromSaveFile(dis);
99 System.out.println(
100 "Cube-configuration & colormapkey were loaded " + "properly.");
101 }
102
103 // BLOCK 3: Potential cube-solution is being loaded &
104 // info on the progress of the robot.
105 if (dataBlockSystem[3]) {
106 CommandSeq.commandSeqFromSaveFile(dis);
107 System.out.println(
108 "Cube-solution and the robot's progress " + "are loaded properly.");
109 }
110
111 System.out.println(
112 "Project \"" + cbthFile.getName() + "\" was loaded properly.");
113
114 } catch (EOFException eofe) {
115 stop = true;
116 }
117 }
118 } catch (IOException ioe) {
119 System.err.println("ERROR: An IOException occurred during opening "
120 + "the SaveFile.cbth. Our apologies for the inconvenience.");
121 }
122
123 finally {
124 if (dis != null) {
125 try {
126 dis.close();
127 } catch (IOException ioe) {
128 System.err.println(
129 "ERROR: An IOException occurred during closing \"dis\"."
130 + " Our apologies for the inconvenience.");
131 }
132 } else {
1 package cbthFileChooser;
2
3 import java.io.File;
4 import javax.swing.filechooser.*;
5
6 public class ImageFilter extends FileFilter {
7
8 // Instance methods:
9 /** Accepts directories and image formats (gif, jpg, tiff, bmp or png). */
10 public boolean accept(File f) {
11 if (f.isDirectory()) {
12 return true;
13 }
14
15 String extension = Utils.getExtension(f);
16 if (extension != null) {
17 if (extension.equals(Utils.tiff) || extension.equals(Utils.tif)
18 || extension.equals(Utils.gif) || extension.equals(Utils.jpeg)
19 || extension.equals(Utils.jpg) || extension.equals(Utils.bmp)
20 || extension.equals(Utils.png)) {
21 return true;
22 } else {
23 return false;
24 }
25 }
26
27 return false;
28 }
29
30 // Getters:
31 // The description of this filter
32 public String getDescription() {
33 return "Imageformats only (." + Utils.jpg + "; ."
34 + Utils.jpeg + "; ." + Utils.png
35 + ";" + " ." + Utils.gif + "; ." + Utils.bmp + "; ." + Utils.tif + "; ."
36 + Utils.tiff + ").";
37 }
38 }
1 package cbthFileChooser;
2
3 import java.awt.*;
4 import java.beans.*;
5 import java.io.File;
6 import javax.swing.*;
7
8 public class ImagePreview extends JComponent implements PropertyChangeListener {
9
10 private static final long serialVersionUID = -7707572607662984788L;
11 private ImageIcon thumbnail = null;
12 private File file = null;
13
14 // Constructors:
15 public ImagePreview(JFileChooser fc) {
16 setPreferredSize(new Dimension(100, 50));
17 fc.addPropertyChangeListener(this);
18 }
19
20 // Instance methods:
21 public void loadImage() {
22 if (file == null) {
23 thumbnail = null;
24 return;
25 }
26
27 // Don't use createImageIcon (which is a wrapper for getResource)
28 // because the image we're trying to load is probably not one
29 // of this program's own resources.
30 ImageIcon tmpIcon = new ImageIcon(file.getPath());
31 if (tmpIcon != null) {
32 if (tmpIcon.getIconWidth() > 90) {
33 thumbnail = new ImageIcon(
34 tmpIcon.getImage().getScaledInstance(90, -1, Image.SCALE_DEFAULT));
35 } else { // no need to miniaturize
36 thumbnail = tmpIcon;
37 }
38 }
39 }
40
41 protected void paintComponent(Graphics g) {
42 if (thumbnail == null) {
43 loadImage();
44 }
45 if (thumbnail != null) {
46 int x = getWidth() / 2 - thumbnail.getIconWidth() / 2;
47 int y = getHeight() / 2 - thumbnail.getIconHeight() / 2;
48
49 if (y < 0) {
50 y = 0;
51 }
52
53 if (x < 5) {
54 x = 5;
55 }
56 thumbnail.paintIcon(this, g, x, y);
57 }
58 }
59
60 public void propertyChange(PropertyChangeEvent e) {
61 boolean update = false;
62 String prop = e.getPropertyName();
63
64 // If the directory changed, don't show an image.
65 if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
66 file = null;
67 update = true;
68
69 // If a file became selected, find out which one.
70 } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
71 file = (File) e.getNewValue();
72 update = true;
73 }
74
75 // Update the preview accordingly.
76 if (update) {
77 thumbnail = null;
78 if (isShowing()) {
79 loadImage();
80 repaint();
81 }
82 }
83 }
84 }
1 package cbthFileChooser;
2
3 import java.io.File;
4
5 public class Utils {
6 public final static String jpeg = "jpeg";
7 public final static String jpg = "jpg";
8 public final static String gif = "gif";
9 public final static String tiff = "tiff";
10 public final static String tif = "tif";
11 public final static String png = "png";
12 public final static String bmp = "bmp";
13 public final static String cbthExtension = "cbth";
14
15 // Static methods:
16 /** Gets the extension of a file. */
17 public static String getExtension(File f) {
18 String ext = null;
19 String s = f.getName();
20 int i = s.lastIndexOf('.');
21
22 if (i > 0 && i < s.length() - 1) {
23 ext = s.substring(i + 1).toLowerCase();
24 }
25 return ext;
26 }
27 }
1 package comparators;
2
3 import java.util.Comparator;
4
5 import model.CBTHSetting;
6
7 /** Compares CBTHSettings on their iD. */
8 public class IdCBTHSettingComparator implements Comparator<CBTHSetting> {
9
10 public int compare(CBTHSetting s1, CBTHSetting s2) {
11 return s1.getiD() - s2.getiD();
12 }
13 }
1 package comparators;
2
3 import java.util.Comparator;
4
5 import model.CBTHSetting;
6
7 /** Compares CBTHSettings alphabetically on their labeltext. */
8 public class LabelTextCBTHSettingComparator implements Comparator<CBTHSetting> {
9
10 public int compare(CBTHSetting s1, CBTHSetting s2) {
11 return (s1.getLabelText()).compareToIgnoreCase(s2.getLabelText());
12 }
13 }
1 package comparators;
2
3 import java.util.Comparator;
4
5 import model.CBTHSetting;
6
7 /** Compares CBTHSettings alphabetically on their type. */
8 public class TypeCBTHSettingComparator implements Comparator<CBTHSetting> {
9
10 public int compare(CBTHSetting s1, CBTHSetting s2) {
11 return (s1.getType().compareTo(s2.getType()));
12 }
13 }
1 package connection.conWithCamera;
2
3 import java.awt.image.BufferedImage;
4 import java.awt.image.DataBufferByte;
5 import javax.swing.ImageIcon;
6 import javax.swing.JLabel;
7
8 import model.CBTHSettingsList;
9 import model.CommonObjects;
10 import org.opencv.core.Mat;
11 import org.opencv.videoio.VideoCapture;
12
13 public class CamLiveStreamThread implements Runnable {
14 /*
15 * Source: http://stackoverflow.com/questions/26535645/
16 * ip-camera-with-opencv-in-java visited the 30/09/2015. Source:
17 * https://www.youtube.com/watch?v=paYDSGtneDQ visited the 7/10/2015. Source:
18 * http://docs.opencv.org/3.0-beta/doc/tutorials/introduction/
19 * java_eclipse/java_eclipse.html visited the 7/10/2015
20 */
21
22 public static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
23 public volatile boolean runnable = false;
24 /*
25 * When two threads synchronously invert the same boolean, AtomicBoolean would
26 * have been a better choice, then the result is guaranteed to be the original
27 * boolean-value. More info? Source:
28 * http://stackoverflow.com/questions/15735366/
29 * accessing-boolean-in-a-multithreaded-environment
30 */
31
32 private volatile VideoCapture captureDevice;
33 private volatile JLabel l_CAM_StreamToLabel;
34 private volatile BufferedImage image;
35 private Mat frame;
36
37 // Constructor:
38 public CamLiveStreamThread(VideoCapture captureDevice, JLabel l_CAM_StreamToLabel) {
39 this.captureDevice = captureDevice;
40 this.l_CAM_StreamToLabel = l_CAM_StreamToLabel;
41 this.frame = new Mat();
42 this.image = null;
43 }
44
45 // Getter:
46 public BufferedImage getCurrentFrame() {
47 return image;
48 }
49
50 // Instance method:
51 public BufferedImage Mat2BufferedImage(Mat m) {
52
53 int type = BufferedImage.TYPE_BYTE_GRAY;
54 if (m.channels() > 1) {
55 type = BufferedImage.TYPE_3BYTE_BGR;
56 }
57 int bufferSize = m.channels() * m.cols() * m.rows();
58 byte[] b = new byte[bufferSize];
59 m.get(0, 0, b); // get all the pixels
60
61 BufferedImage img = new BufferedImage(m.cols(), m.rows(), type);
62 final byte[] targetPixels = ((DataBufferByte) img.getRaster().getDataBuffer())
63 .getData();
64 System.arraycopy(b, 0, targetPixels, 0, b.length);
65 return img;
66 }
67
68 /** This method describes the refreshing process of the cameraframes. */
69 public void run() {
70 synchronized (this) {
71
72 while (runnable) {
73 if (captureDevice.grab()) {
74 try {
75 /*
76 * captureDevice.grab(); is faster but does not respect
77 * camera-synchronisation, although it also works fine in this
78 * application.
79 */
80 if (captureDevice.retrieve(frame)) {
81 image = Mat2BufferedImage(frame);
82 if (image != null) {
83 l_CAM_StreamToLabel.setIcon(new ImageIcon(image));
84 }
85 }
86
87 if (runnable == false) {
88 // Show screen with camerapicture and message how
89 // to retrieve a livestream.
90 String[] pathComp = { "img", "icon", "CAMdfk23g445.png" };
91 String iconPath = cbthsl.makeSysIndepFilePath(pathComp, 2);
92 l_CAM_StreamToLabel.setIcon(new ImageIcon(iconPath));
93 l_CAM_StreamToLabel.setText(
94 " Toggle \"Camera livestream\" to "
95 + "retrieve a videostream from CaptureDevice.");
96 l_CAM_StreamToLabel.setFont(cbthsl.getFont("guiFont1"));
97
98 System.out.println("[CAMLINK]: Camera LivestreamTread stopped.");
99 this.wait();
100 }
101 } catch (Exception ex) {
102 System.out.println(ex);
103 }
104 } else {
105 System.err.println(
106 "[CAMLINK]: ERROR: There are no frames to be grabbed.");
107 }
108 }
109 }
110 }
111 }
1 package connection.conWithCamera;
2
3 import java.awt.image.BufferedImage;
4 import java.text.DateFormat;
5 import java.text.SimpleDateFormat;
6 import java.util.Date;
7
8 import exceptions.NoCaptureDevConnectionException;
9 import listeners.cam.T_CAM_LiveStreamItemListener;
10 import model.CBTHImage;
11 import model.CBTHSettingsList;
12 import model.CommonObjects;
13
14 public class CamTakePicture {
15
16 private static int shotID;
17 private static T_CAM_LiveStreamItemListener lsil;
18 private static DateFormat dateFormat;
19 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
20
21 // Constructor:
22 public CamTakePicture(T_CAM_LiveStreamItemListener lsiListener) {
23 shotID = 0;
24 lsil = lsiListener;
25 dateFormat = new SimpleDateFormat("_yyyy_MM_dd_HH_mm_ss");
26 // 2014/08/06 15:59:48
27 }
28
29 public static CBTHImage takePicture() throws NoCaptureDevConnectionException {
30 BufferedImage frame = lsil.getCurrentFrame();
31 CBTHImage a = null;
32
33 if (frame != null) {
34
35 Date date = new Date();
36
37 String bestandsNaam = "SnapshotId" + shotID + dateFormat.format(date);
38 shotID++;
39
40 a = new CBTHImage(bestandsNaam, frame);
41
42 int tempXCrop = cbthsl.getInt("xCoCrop");
43 int tempYCrop = cbthsl.getInt("yCoCrop");
44 int tempWidthCrop = cbthsl.getInt("widthCrop");
45 int tempHeightCrop = cbthsl.getInt("heightCrop");
46
47 // Avoid Raster error, i.e.: cropping an image with invalid coordinates.
48 if (tempXCrop + tempWidthCrop < lsil.getCapDeviceFrameWidth()
49 && tempYCrop + tempHeightCrop < lsil.getCapDeviceFrameHeight()) {
50 a.setNewCropped(tempXCrop, tempYCrop, tempWidthCrop, tempHeightCrop);
51 }
52 } else {
53 System.err.println(
54 "[CAMLINK]: ERROR: There was no frame " + "passed to process.");
55 }
56 return a;
57 }
58 }
1 package connection.conWithRobot;
2
3 import java.io.*;
4 import java.net.*;
5
6 import exceptions.NotIntendedIPAddressException;
7 import model.CBTHSettingsList;
8 import model.CommandSeq;
9 import model.CommonObjects;
10
11 public class CommunicationRobotThread extends Thread {
12 // Source:
13 // https://www.cs.uic.edu/~troy/spring05/cs450/sockets/EchoServer2.java
14
15 public static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
16 protected Socket clientSocket;
17 private ServerSocket serverSocket;
18 private int portNumber;
19 private PrintWriter out;
20 private DataInputStream dis;
21 private volatile boolean loopMaintained;
22 private volatile boolean linkRobotEstablished;
23 private volatile boolean robotIsBusy;
24
25 // Constructor:
26 public CommunicationRobotThread() {
27
28 this.serverSocket = null;
29 this.clientSocket = null;
30 this.portNumber = cbthsl.getInt("portNmbrServerSocket");
31
32 this.out = null;
33 this.dis = null;
34
35 this.linkRobotEstablished = false;
36 this.robotIsBusy = false;
37 }
38
39 // Getters:
40 public boolean getLinkRobotEstablished() {
41 return linkRobotEstablished;
42 }
43
44 public boolean getRobotIsBusy() {
45 return robotIsBusy;
46 }
47
48 // Setters:
49 public void initializeCommunicationRobot() {
50
51 loopMaintained = true;
52 }
53
54 public void stopCommunicationRobot() {
55 CommandSeq.stopAsQuicklyAsPossile();
56 CommandSeq.terminateRobotProgram();
57
58 // Wait till the robot has moved aside:
59 try {
60 Thread.sleep(3000); // 1000 milliseconds is one second.
61 } catch (InterruptedException ex) {
62 Thread.currentThread().interrupt();
63 }
64 loopMaintained = false;
65 }
66
133 */
134
135 currentCommand = CommandSeq.peekCommand();
136
137 if (currentCommand != noValidCommand) {
138
139 out.println(currentCommand);
140 System.out.println("[ROBOTLINK]: " + currentCommand
141 + " was successfully sent to the contoller.");
142 robotIsBusy = true;
143
144 // Instead of a fixed delaytime, the program waits
145 // for the robot's answer.
146 StringBuffer sb = new StringBuffer();
147
148 do {
149 inputChar = dis.read();
150 sb.append(Character.toString((char) inputChar));
151 } while (inputChar != 93);
152
153 System.out.println("[ROBOTLINK]: Robot replies: " + sb.toString());
154 robotIsBusy = false;
155
156 try {
157 int uitgevoerdCommando = textBetweenBrackets(sb.toString());
158
159 if (currentCommand == uitgevoerdCommando) {
160 CommandSeq.pollCommand();
161 }
162
163 } catch (NumberFormatException nfe) {
164 }
165 }
166
167 else {
168
169 /*
170 * When the commands run short in the queue, the queue is checked
171 * for new commands at 2Hz rate.
172 */
173 try {
174 Thread.sleep(500); // 1000 milliseconds is
175 // one second.
176 } catch (InterruptedException ex) {
177 Thread.currentThread().interrupt();
178 }
179 }
180
181 }
182
183 linkRobotEstablished = false;
184 out.close();
185 dis.close();
186 clientSocket.close();
187
188 } catch (IOException e) {
189 System.err.println(
190 "[ROBOTLINK]: ERROR: Problem with Communication Server");
191 } catch (NotIntendedIPAddressException niipae) {
192 System.err.println(niipae);
193 }
194
195 } catch (IOException exc1) {
196 System.err.println(
197 "[ROBOTLINK]: ERROR: Socketcreation: Could not listen on port "
198 + portNumber + " or socket was not accepted.");
199 try {
200 serverSocket.close();
201 System.out.println(
202 "[ROBOTLINK]: Socket was closed. Communication finished.");
203 } catch (IOException exc2) {
204 System.err.println(
205 "[ROBOTLINK]: ERROR: Port " + portNumber + " could not be shut down.");
206 }
207 }
208
209 finally {
210 // What happens after the try{}-block no matter whether an
211 // Exception occurred.
212 }
213 }
214 }
215
216 // Static method:
217 public static int textBetweenBrackets(String robotResponse)
218 throws NumberFormatException {
219
220 int temporary = cbthsl.getInt("noValidCommand");
221 temporary = Integer.parseInt(
222 robotResponse.substring(1, robotResponse.length() - 1));
223
224 return temporary;
225 }
226 }
1 package console;
2
3 import java.io.File;
4
5 import javax.swing.Icon;
6 import javax.swing.JFrame;
7 import javax.swing.JOptionPane;
8 import javax.swing.JPanel;
9
10 import cbthFileChooser.CBTHFileChooser;
11 import cbthFileChooser.FileIO;
12 import connection.conWithCamera.CamTakePicture;
13 import exceptions.*;
14 import listeners.solv.*;
15 import model.*;
16 import solver.solverJS.viewSolverJS.Cubie;
17
18 /**
19 * This class organizes some basic commands that can be executed from the
20 * commandprompt. If you might want to add extra functions, just add a new line
21 * in the "SUPPORTED_COMMANDS" and implement the extra line in the switch-case
22 * structure in "executeCommand". No indexes are to be changed and order
23 * shouldn't necessarily be kept alphabetical.
24 */
25 public class ConsoleCommands {
26
27 /* In Alphabetical order supported commands are listed. */
28 private static final String[][] SUPPORTED_COMMANDS = {
29 { "BUILDVIRTCUBE", "Builds virtual cube if mainCubeFaces are available." },
30 { "CLEARALL", "Clears all the images, cubefaces... (Resets current data.)" },
31 { "CUBETOSOLVER", "Transfers the virtual cube to the solver." },
32 { "OPEN", "Spawns dialog to open a project." },
33 { "SAVE", "Saves the project at the current location." },
34 { "SAVEAS", "Spawns the \"Save as\"-dialog." },
35 { "SNAPESTIM",
36 "If a cameraconnection was put up, this will take a "
37 + "snapshot & perform colorestimation." },
38 { "SOLTOROBOT", "Translates the solution for the Robot." },
39 { "SOLVE", "Cubie will try to solve the cube shown in visualization." }, };
40 private static CBTHImagesList imgl = null;
41 private static CubeFacesList cfl = null;
42 private static CBTHFileChooser cbthfc = null;
43 private static ViewConsolePanel p_vcp = null;
44 private static CBTHSettingsList cbthsl = null;
45 private static B_SOLV_CubeToSolverListener cts = null;
46 private static B_SOLV_MoveSeqToRobotListener mstr = null;
47 private static Cubie cubie = null;
48
49 public ConsoleCommands(CBTHImagesList imgList, CubeFacesList cfList,
50 CBTHFileChooser cbthFileChooser, ViewConsolePanel p_VCP) {
51 imgl = imgList;
52 cfl = cfList;
53 cbthfc = cbthFileChooser;
54 p_vcp = p_VCP;
55 cbthsl = CommonObjects.getCBTHSettingsList();
56 cts = CommonObjects.getCubeToSolver();
57 mstr = CommonObjects.getMoveSeqToRobot();
58 cubie = CommonObjects.getCubie();
59 }
60
61 // Getter:
62 public static String[][] getSupCommands() {
63 return SUPPORTED_COMMANDS;
64 }
65
66 // Static methods:
67 /**
68 * Checks whether the entered input is a real command.
69 *
70 * @param inputCommandPrompt
71 * User's input from the commandPrompt is passed here.
72 * @return The index at which the command is to be found.
73 */
74 public static int validCommand(String inputCommandPrompt) {
75 int returnValue = -1, index = 0;
76 boolean foundYet = false;
77
78 while (index < SUPPORTED_COMMANDS.length && !foundYet) {
79 // Commands are not case-sensitive:
80 if (inputCommandPrompt.equalsIgnoreCase(SUPPORTED_COMMANDS[index][0])) {
81 returnValue = index;
82 foundYet = true;
83 }
84 index++;
85 }
86 return returnValue;
87 }
88
89 /**
90 * Execute a specified command.
91 *
92 * @param commandIndex
93 * The index at which the command is to be found.
94 */
95 public static void executeCommand(int commandIndex) {
96
97 switch (SUPPORTED_COMMANDS[commandIndex][0]) {
98 case "BUILDVIRTCUBE":
99 try {
100 CubeConfiguration.buildVirtualCube(cfl.getAllMainCubeFaces());
101 } catch (FaceletColorNoneException fcne) {
102 System.err.println(fcne);
103 } catch (NonExistingCubeletException nece) {
104 System.err.println(nece);
105 } catch (CubeletAlreadyAssignedException caae) {
106 System.err.println(caae);
107 }
108 break;
109
110 case "CLEARALL":
111
112 int answer = showWarningMessage();
113
114 switch (answer) {
115 case JOptionPane.YES_OPTION:
116 imgl.deleteAllCBTHImages();
117 cfl.deleteAllCubeFaces();
118 cfl.resetMainCubeFaces();
119 CubeConfiguration.setStartCubeletPerm(null);
120 CubeConfiguration.setStartCubeletOri(null);
121 CubeConfiguration.setStartFaceOri(null);
122 CubeConfiguration.setColorMapKey(null);
123 CommandSeq.stopAsQuicklyAsPossile();
124 CommandSeq.setSolutionCommandsMatrix(null, null, 0);
125 break;
126
127 default:
128 break;
129 }
130 break;
131
132 case "CUBETOSOLVER":
133 try {
134 cts.cubeToSolver();
135 } catch (NotAvailableException nae) {
136 System.err.println(nae);
137 }
138 break;
139
140 case "OPEN":
141 File f = cbthfc.fcOpenFile(1);
142 if (f != null) {
143 cbthsl.setCurrentProject(new File(f.getParent()));
144 p_vcp.updateLogFilesByFlushConsole(true, false);
145 FileIO.openProject(f);
146 }
147 break;
148
149 case "SAVE":
150 FileIO.saveProject();
151 break;
152
153 case "SAVEAS":
154 cbthfc.fcSaveFile(1);
155 break;
156
157 case "SNAPESTIM":
158 try {
159 CBTHImage img = null;
160 img = CamTakePicture.takePicture();
161 if (img != null) {
162 imgl.addCBTHImage(img);
163
164 CubeFace cf = ColorEstimation.colorRecognition(img);
165 cfl.addCubeFace(cf);
166
167 JPanel content = cf.createVCubeFace();
168
169 // Pop-up resultaat kleurherkenning igv manuele
170 // klik op knop, in automatische mode, zal de vlakKubus
171 // niet meer pop-uppen.
172 JFrame frame = cbthsl.createCubeThesisFrame("Result color-estimation...");
173 frame.add(content);
174 frame.pack();
175 frame.setVisible(true);
176 }
177 } catch (NoCaptureDevConnectionException ncdce) {
178 System.err.println(ncdce);
179 }
180 break;
181
182 case "SOLTOROBOT":
183 mstr.moveSeqToRobot();
184 break;
185
186 case "SOLVE":
187 cubie.solve();
188 break;
189
190 default:
191 break;
192 }
193 }
194
195 /**
196 * Spawns a warning-dialog to get confirmation of the user.
197 *
198 * @return The user's reaction is returned by means of an int.
199 */
200 public static int showWarningMessage() {
201 String[] buttonLabels = new String[] { "Yes", "No" };
202 String defaultOption = buttonLabels[1];
203 Icon icon = null;
204
205 return JOptionPane.showOptionDialog(new JPanel(),
206 "Are you sure you want to clear all data? " + cbthsl.getString("newLine")
207 + "This operation cannot be undone when " + "the file was not saved yet.",
208 "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, icon,
209 buttonLabels, defaultOption);
210 }
211 }
1 package console;
2
3 import java.awt.event.*;
4 import javax.swing.*;
5
6 import console.ViewConsolePanel;
7 import model.CommonObjects;
8
9 /**
10 * This class receives the user's input on the commandPrompt, interprets it and
11 * puts it on the console.
12 */
13 public class ConsoleInputListener implements ActionListener {
14
15 private ViewConsolePanel vcp;
16 private static String newLine = CommonObjects.getCBTHSettingsList()
17 .getString("newLine");
18 private int officialSupCommand = -1;
19
20 public ConsoleInputListener(ViewConsolePanel vcp) {
21 this.vcp = vcp;
22 }
23
24 // Instance method:
25 /**
26 * This method is triggered every time [Enter] is hit in the commandpromptbar.
27 * Adds "<: " to start the line.
28 */
29 public void actionPerformed(ActionEvent e) {
30
31 JTextField conPrompt = vcp.getCommandPrompt();
32 JTextArea conOutput = vcp.getConsole();
33 String text = conPrompt.getText();
34
35 /*
36 * The method updateRecordsCounter() will increment the counter hosted in
37 * the actual ViewConsolePanel-object. That counter takes account of both
38 * lines accepted from the commandprompt (< : ) and lines being printed by
39 * the program (> : ). By incrementing a variable, the effort is saved to
40 * count all lines in the console every time a line is printed. (speed gain
41 * purposes)
42 */
43 vcp.updateRecordsCounter();
44
45 // Check whether the limit consoleRecordsMax is not exceeded.
46 // If so, the excessive records are flushed away:
47 vcp.updateLogFilesByHysteresis();
48
49 // Check whether input is an official supported CommandFromComPrompt:
50 if ((officialSupCommand = ConsoleCommands.validCommand(text)) != -1) {
51 text = text.toUpperCase();
52 // To approve that, the text is made "uppercase".
53 }
54
55 // Adding the text to the console, before executing the tasks it might
56 // imply:
57 conOutput.append(" < : " + text + newLine);
58
59 // Executes implied tasks if the input represented a supported command:
60 if (officialSupCommand != -1) {
61 ConsoleCommands.executeCommand(officialSupCommand);
62 officialSupCommand = -1;// Reset for next input.
63 }
64
65 // Make sure the console shows the most recent text:
66 conOutput.setCaretPosition(conOutput.getDocument().getLength());
67
68 // After [Enter] the specified text is highlighted to be easily overwritten:
69 conPrompt.selectAll();
70 }
71 }
1 package console;
2
3 import java.io.*;
4 import java.lang.StringBuffer;
5 import javax.swing.*;
6
7 import console.ViewConsolePanel;
8 import model.CommonObjects;
9
10 public class ConsoleOutputStream extends OutputStream {
11
12 private JTextArea textArea;
13 private ViewConsolePanel vcp;
14 private StringBuffer sb;
15 private static String newLine = CommonObjects.getCBTHSettingsList()
16 .getString("newLine");
17
18 // Constructor:
19 public ConsoleOutputStream(ViewConsolePanel vcv) {
20 this.vcp = vcv;
21 this.textArea = vcv.getConsole();
22 this.sb = new StringBuffer();
23 }
24
25 /*
26 * Instance methods below overwrite named alike methods from the class
27 * OutputStream. Strange enough the write(final int b)-method is obliged to
28 * implement, though never used. Only the write(byte[] b, int off, int
29 * len)-method is used & elaborated upon. This method will call for the
30 * writeToConsole(String temp)-method.
31 */
32
33 @Override
34 /**
35 * This method had to be implemented extending from the OutputStream-class,
36 * although never used.
37 */
38 public void write(final int b) throws IOException {
39
40 textArea.append(String.valueOf((char) b));
41 }
42
43 @Override
44 /**
45 * This method takes care of the usual System.out.print(ln)(); &
46 * System.err.println(); The System.out/err.println()-methods invoke this
47 * write method twice: Once to pass the actual text & once to pass an
48 * end-of-line command. The System.out.print()-method only calls once for this
49 * write method. The method was designed to be OS-independent, however it's
50 * functionality has never been tested but on Windows-computers.
51 */
52 public void write(byte[] b, int off, int len) throws IOException {
53
54 /*
55 * From the specified parameters, a String s is created. Caution: This
56 * string could represent multiple lines so possibly contains "newLine"
57 * characters.
58 */
59 String s = new String(b, off, len);
60
61 /*
62 * Unfortunately, line-separators are not OS-independent: Windows: '\r\n'
63 * "carriage return" - "line feed" etc... Mac (OS 9-): '\r' Mac (OS 10+):
64 * '\n' Unix/Linux: '\n'
65 *
66 * By making use of the CBTHSetting "newLine", instead of the character-
1 package console;
2
3 import java.awt.*;
4 import java.io.*;
5 import java.text.DateFormat;
6 import java.text.SimpleDateFormat;
7 import java.util.Date;
8 import javax.swing.*;
9 import javax.swing.text.BadLocationException;
10
11 import console.ConsoleInputListener;
12 import console.ConsoleOutputStream;
13 import model.CBTHSettingsList;
14 import model.CommonObjects;
15
16 public class ViewConsolePanel extends JPanel {
17
18 private static final long serialVersionUID = 1L;
19 public static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
20 private static final String newLine = cbthsl.getString("newLine");
21 private static int consoleRecordsMax = 500;
22 private static int consoleRecordsMin = 250;
23 private static int consoleRecordsCounter;
24
25 private JTextField commandPrompt;
26 private JTextArea console;
27 private JScrollPane scrollPane;
28
29 private PrintStream standardOut;
30 private PrintStream standardErr;
31 private ConsoleOutputStream consOutputStream;
32 private ConsoleInputListener consInputListener;
33
34 private static String fileNameLogGeneral;
35 private static String fileNameLogProj;
36
37 // Constructor:
38 public ViewConsolePanel() {
39
40 super(new BorderLayout());
41
42 updateRecordsMinMaxLimits();
43 consoleRecordsCounter = 0;
44
45 // Creation of the console & commandPrompt:
46 console = new JTextArea(4, 15);
47 commandPrompt = new JTextField(15);
48
49 console.setEditable(false);
50
51 /*
52 * For the console a 'monospaced' font is preferred, to lay out the text
53 * properly. Examples of such fonts: Lucida Console, Courier New,
54 * Consolas...
55 */
56
57 Font font = cbthsl.getFont("guiFont2");
58 console.setFont(font);
59 console.setBackground(Color.WHITE);
60 console.setForeground(Color.DARK_GRAY);
61 commandPrompt.setFont(font);
62 commandPrompt.setBackground(Color.WHITE);
63 commandPrompt.setForeground(Color.DARK_GRAY);
64 scrollPane = new JScrollPane(console,
65 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
66 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
67
68 this.add(scrollPane, BorderLayout.CENTER);
69 this.add(commandPrompt, BorderLayout.PAGE_END);
70
71 // At this point a header is written on the LogFiles.
72 fileNameLogGeneral = cbthsl
73 .makeSysIndepFilePath(new String[] { "LogFileGeneral.txt" }, 2);
74 updateLogFilesByFlushConsole(true, false);
75
76 // Organize communication user to pc: " < : "
77 consInputListener = new ConsoleInputListener(this);
78 commandPrompt.addActionListener(consInputListener);
79
80 // Organize communication pc to user: " > : "
81 consOutputStream = new ConsoleOutputStream(this);
82 PrintStream printStream = new PrintStream(consOutputStream);
83
84 // Backup of the old output/error-streams (to the console of the IDE):
85 standardOut = System.out;
86 standardErr = System.err;
87
88 /*
89 * IMPORTANT: Output- & Error-streams are redirected to the new printStream
90 * made: (If not, console won't display text)
91 */
92 try {
93 System.setOut(printStream);
94 System.setErr(printStream);
95 } catch (NullPointerException e) {
96
97 standardErr.println(e);
98 String errorMessage =
99 "ERROR: Redirecting StdOut- & " + "StdErr-stream failed."
100 + " Our apologies for the inconvenience.";
101 standardErr.println(errorMessage);
102 System.err.println(errorMessage);
103 }
104 }
105
106 // Getters:
107 public JTextField getCommandPrompt() {
108 return this.commandPrompt;
109 }
110
111 public JTextArea getConsole() {
112 return this.console;
113 }
114
115 public int getConRecordsCounter() {
116 return consoleRecordsCounter;
117 }
118
119 public PrintStream getStdErr() {
120 return standardErr;
121 }
122
123 public PrintStream getStdOut() {
124 return standardOut;
125 }
126
127 public String getTextCommandPrompt() {
128 return commandPrompt.getText();
129 }
130
131 // Setter:
132 /**
133 * Used by the commands menu to drop the selected text in the
134 * commandprompt-bar.
135 */
136 public void setTextCommandPrompt(String text) {
137 commandPrompt.setText(text);
138 }
139
140 // Instance methods, listed alphabetically:
141 public void clearConsole() {
142
143 console.setText("");
144 }
145
146 /**
147 * This method flushes all the text available in the console to the logFiles.
148 * By option, a header or footer could be written to the logFiles.
149 * Open_Project uses this as well to make sure the new project's logFile
150 * contains no info of a former opened project. The MenuItem "Flush and Clear"
151 * also uses this method.
152 *
153 * @param header
154 * Should a header be written to the logFiles?
155 * @param footer
156 * Should a footer be written to the logFiles?
157 */
158 public void updateLogFilesByFlushConsole(boolean header, boolean footer) {
159
160 String[] pathComponents = {
161 "LogFile" + cbthsl.getCurrentProject().getName() + ".txt" };
162 fileNameLogProj = cbthsl.makeSysIndepFilePath(pathComponents, 3);
163
164 // Write header:
165 if (header) {
166
167 String[][] logFileNames = { { fileNameLogGeneral }, { fileNameLogProj } };
168
169 // Make sure the LogFileGeneral.txt updates:
170 writeToLogFiles(logFileNames[0],
171 newLine + newLine + createHeaderText(null) + newLine);
172 // Make sure the LogFileProject.txt updates:
173 writeToLogFiles(logFileNames[1], newLine + newLine
174 + createHeaderText(cbthsl.getCurrentProject().getName()) + newLine);
175 }
176
177 // Flush remaining data from console, if flushing makes sense:
178 if (console.getLineCount() > 0) {
179
180 writeToLogFiles(new String[] { fileNameLogGeneral, fileNameLogProj },
181 console.getText());
182
183 clearConsole();
184 consoleRecordsCounter = 0;
185 }
186
187 // Write footer:
188 if (footer) {
189 writeToLogFiles(new String[] { fileNameLogGeneral, fileNameLogProj },
190 newLine + createFooterText());
191 }
192 }
193
194 /**
195 * Every line added to the console calls for updateLogFilesByHysteresis. This
196 * method will check itself whether flushing is needed according to the
197 * consoleRecordsMin/Max-limits. At the end it will check for new
198 * consoleRecordsMin/Max-limits.
199 */
200 public void updateLogFilesByHysteresis() {
201
202 fileNameLogProj = null;
203
204 if (consoleRecordsCounter > consoleRecordsMax) {
205
206 String[] pathComponents = {
207 "LogFile" + cbthsl.getCurrentProject().getName() + ".txt" };
208 fileNameLogProj = cbthsl.makeSysIndepFilePath(pathComponents, 3);
209
210 try {
211 /* The exact nmbrOfLinesToBeDeleted is calculated. */
212 int nmbrOfLinesToBeDeleted = console.getLineCount() - consoleRecordsMin;
213 int lineStartOffset = console.getLineStartOffset(nmbrOfLinesToBeDeleted);
214 standardOut.println("nmbrOfLinesToBeDeleted: " + nmbrOfLinesToBeDeleted);
215 standardOut.println("posOfLastLine: " + lineStartOffset);
216
217 writeToLogFiles(new String[] { fileNameLogGeneral, fileNameLogProj },
218 console.getText(0, lineStartOffset));
219
220 // First lines are replaced by an empty String:
221 console.replaceRange("", 0, lineStartOffset);
222
223 /*
224 * Counter is updated. Note this takes place within the try{}catch(){},
225 * so if an error might occur, the counter will not be updated.
226 */
227 consoleRecordsCounter = consoleRecordsMin;
228
229 } catch (BadLocationException ex) {
230 System.err.println("ERROR: " + ex);
231 }
232 /*
233 * Maybe these consoleRecorsMin/Max need an update from the CBTHSettings.
234 * NOTE: These are only updated when the if(){} above gets triggered using
235 * old parameters.
236 */
237 updateRecordsMinMaxLimits();
238 }
239 }
240
241 /**
242 * The consoleRecordsCounter is incremented when a new line is being added.
243 * Checking this counter (to determine wheter a flush is required), saves the
244 * effort of counting all the lines in the console each time a new line is
245 * added. The counter is reset after a flush.
246 */
247 public void updateRecordsCounter() {
248
249 consoleRecordsCounter++;
250 }
251
252 /**
253 * Updates the hysteresis record-limits of the console by the respective
254 * CBTHSettings if those make sense.
255 */
256 public void updateRecordsMinMaxLimits() {
257
258 int a = cbthsl.getInt("consoleRecordsMax");
259 int b = cbthsl.getInt("consoleRecordsMin");
260
261 if (a > b && b >= 0) {
262 consoleRecordsMax = a;
263 consoleRecordsMin = b;
264 }
265 }
266
267 /**
268 * This method will implement the actual writing to the logFiles.
269 *
270 * @param logFileNames
271 * To which fileNames is to be written
272 * @param text
273 * This text is written to the specified files.
274 */
275 public static void writeToLogFiles(String[] logFileNames, String text) {
276 FileWriter fw = null;
277 PrintWriter pw = null;
278
279 for (int i = 0; i < logFileNames.length; i++) {
280
281 if (logFileNames[i] != null && logFileNames[i] != ""
282 && logFileNames[i].endsWith(".txt")) {
283
284 try {
285
286 /*
287 * Writer objects are declared and initialized. "true" stands for
288 * appending to the original content, rather than overriding it.
289 */
290 fw = new FileWriter(logFileNames[i], true);
291 pw = new PrintWriter(fw);
292
293 /*
294 * Text is printed, and the writers are flushed to make sure no text
295 * remains in temporary buffers.
296 */
297 pw.print(text);
298 pw.flush();
299
300 } catch (IOException ioe) {
301 System.err.println(
302 "ERROR: An IOException occurred " + "during writing to LogFiles.");
303 for (StackTraceElement ste : ioe.getStackTrace()) {
304 System.err.println("STACKTRACE: " + ste);
305 }
306 ;
307 }
308
309 finally {
310 // Elaborated closing-procedure, allowing for
311 // IOExceptions due to closing:
312 if (pw != null) {
313 pw.close();
314 } else {
315 if (fw != null) {
316 try {
317 fw.close();
318 } catch (IOException ioe) {
319 System.err.println(
320 "ERROR: An IOException occurred during closing of FileWriter "
321 + "after writing to LogFiles.");
322 }
323 }
324 }
325 }
326 }
327 }
328 }
329
330 /*
331 * Static methods: They do not directly affect the object, but mostly perform
332 * other useful tasks. One could literally speak of "outsourcing tasks" - with
333 * stress on "source" - to auxillary methods.
334 */
335
336 /**
337 * This method provides footertext for the logFiles.
338 *
339 * @return The footer is returned by means of a String.
340 */
341 public static String createFooterText() {
342 String footer = null;
343
344 // Fetch current date/time for footer:
345 DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
346 String dateFooter = dateFormat.format(new Date());
347 String footerStatement = "* © CubeThesis was exited at: " + dateFooter + " *";
348 String amntOfStripes = signToSequence("–", footerStatement.length());
349
350 // Assembling the footer:
351 footer = amntOfStripes + newLine + footerStatement + newLine + amntOfStripes;
352
353 return footer;
354 }
355
356 /**
357 * createHeaderText, will create a projectName-dependent header for the
358 * logFiles.
359 *
360 * @param projectName
361 * Name of the current CBTHProject. (Available in the CBTHSettings)
362 * @return Header as a String-object.
363 */
364 public static String createHeaderText(String projectName) {
365
366 String header = null;
367 String projectDesignation = null;
368
369 if (projectName != null) {
370 projectDesignation = "PROJECT: " + projectName;
371 } else {
372 projectDesignation = "GENERAL";
373 }
374
375 // Fetch current date/time for header:
376 DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
377 String dateHeader = dateFormat.format(new Date());
378 String surroundingSign = "=";
379
380 // Title is presumed to be longer than the subtitle,
381 // since additional spaces are added to the subtitle.
382 String title = surroundingSign + " LOGFILE " + projectDesignation
383 + " © CubeThesis 2015-2016 Deschuytter Simon & Depamelaere Pieter "
384 + surroundingSign;
385 String subTitle = surroundingSign + " CubeThesis(-project) was started at: ";
386 String amountOfSpaces = signToSequence(" ",
387 title.length() - subTitle.length() - dateHeader.length() - 1);
388 String amntOfSurroundngSgn = signToSequence(surroundingSign, title.length());
389
390 header = amntOfSurroundngSgn + newLine + title + newLine + subTitle + dateHeader
391 + amountOfSpaces + surroundingSign + newLine + amntOfSurroundngSgn;
392
393 return header;
394 }
395
396 /**
1 package exceptions;
2
3 import model.CBTHSettingsList;
4 import model.CommonObjects;
5
6 public class CubeletAlreadyAssignedException extends Exception {
7
8 /*
9 * The first attribute serialVersionUID is a recommended attribute when
10 * "extending", however of no real importance.
11 */
12 private static final long serialVersionUID = 1L;
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private int cubeletID;
15 private String cubeletColors;
16 private String colorsLocation1;
17 private String colorsLocation2;
18
19 // Constructors:
20 public CubeletAlreadyAssignedException() {
21 super();
22 this.cubeletID = -1;
23 this.cubeletColors = null;
24 this.colorsLocation1 = null;
25 this.colorsLocation2 = null;
26 }
27
28 public CubeletAlreadyAssignedException(int cubeletID, String cubeletColors,
29 String colorsLocation1, String colorsLocation2) {
30 super();
31 this.cubeletID = cubeletID;
32 this.cubeletColors = cubeletColors;
33 this.colorsLocation1 = colorsLocation1;
34 this.colorsLocation2 = colorsLocation2;
35 }
36
37 @Override
38 public String toString() {
39 return "ERROR: Cubelet \"" + cubeletID + "\" with faceletcolors "
40 + cubeletColors
41 + " was identified twice or more. The issue "
42 + "occurred at the locations below:"
43 + cbthsl.getString("newLine") + "ERROR: " + colorsLocation1 + " & "
44 + colorsLocation2
45 + " (both expressed by the facelet colors of the cubelet that "
46 + "belongs there in solved cubestate.)" + cbthsl.getString("newLine")
47 + "ERROR: Attention to the errorlocations when middle-cubelets "
48 + "are involved: they're expressed without recolouring. "
49 + "Our apologies for the inconvenience. ";
50 }
51 }
1 package exceptions;
2
3 import model.CBTHSettingsList;
4 import model.CommonObjects;
5
6 public class FaceletColorNoneException extends Exception {
7
8 private static final long serialVersionUID = 1L;
9 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
10 private String mainCubeFaceName;
11 private int row;
12 private int column;
13
14 // Constructors:
15 public FaceletColorNoneException() {
16 super();
17 this.mainCubeFaceName = null;
18 this.row = -1;
19 this.column = -1;
20 }
21
22 public FaceletColorNoneException(String mainCubeFaceName, int row, int column) {
23 super();
24 this.mainCubeFaceName = mainCubeFaceName;
25 this.row = row;
26 this.column = column;
27 }
28
29 @Override
30 public String toString() {
31 return "ERROR: Main-cubeface \"" + mainCubeFaceName
32 + "\" reports a facelet at [row, column]: [" + row + ", " + column
33 + "] to be colorless." + cbthsl.getString("newLine")
34 + "ERROR: With not all faceletcolors differing from \""
35 + cbthsl.translateColorsIntToString(6)
36 + "\", CubeThesis won't achieve a virtual cube configuration."
37 + cbthsl.getString("newLine")
38 + "ERROR: Our apologies for the inconvenience.";
39 }
40 }
1 package exceptions;
2
3 public class NoCaptureDevConnectionException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6
7 // Constructor:
8 public NoCaptureDevConnectionException() {
9 super();
10 }
11
12 @Override
13 public String toString() {
14 return "[CAMLINK]: ERROR: Connection with CaptureDevice wasn't "
15 + "established. Our apologies for the inconvencience.";
16 }
17 }
1 package exceptions;
2
3 public class NoImageForColorEstimationException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6
7 // Constructor:
8 public NoImageForColorEstimationException() {
9 super();
10 }
11
12 @Override
13 public String toString() {
14 return "ERROR: There is no image available to apply color-estimation. "
15 + "Our apologies for the inconvenience.";
16 }
17 }
1 package exceptions;
2
3 public class NoMatchingSettingTypeException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String settingName;
7 private String receivedType;
8 private String expectedType;
9
10 // Constructors:
11 public NoMatchingSettingTypeException() {
12 super();
13 this.settingName = null;
14 this.receivedType = null;
15 this.expectedType = null;
16 }
17
18 public NoMatchingSettingTypeException(String settingName, String receivedType,
19 String expectedType) {
20 super();
21 this.settingName = settingName;
22 this.receivedType = receivedType;
23 this.expectedType = expectedType;
24 }
25
26 @Override
27 public String toString() {
28
29 return "ERROR: \"" + settingName + "\": Settingtypes don't match. Received: ["
30 + receivedType + "], while [" + expectedType
31 + "] expected. Our apologies for the inconvenience.";
32 }
33 }
1 package exceptions;
2
3 import model.CBTHSettingsList;
4 import model.CommonObjects;
5
6 public class NonExistingCubeletException extends Exception {
7
8 private static final long serialVersionUID = 1L;
9 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
10 private int[] notExistingColors;
11 private int[] colorsLocation;
12
13 // Constructors:
14 public NonExistingCubeletException() {
15 this.notExistingColors = null;
16 this.colorsLocation = null;
17 }
18
19 public NonExistingCubeletException(int[] notExistingColors, int[] colorsLocation) {
20 this.notExistingColors = notExistingColors;
21 this.colorsLocation = colorsLocation;
22 }
23
24 @Override
25 public String toString() {
26
27 StringBuffer sb = new StringBuffer();
28 sb.append("ERROR: On a official cube, there is no cubelet "
29 + "available with faceletcolors [");
30 int i = 0;
31
32 while (i < notExistingColors.length - 1) {
33 sb.append(cbthsl.translateColorsIntToString(notExistingColors[i]) + ", ");
34 i++;
35 }
36 sb.append(cbthsl.translateColorsIntToString(notExistingColors[i])
37 + "]. The issue occurred at the location below: [");
38
39 i = 0;
40 while (i < colorsLocation.length - 1) {
41 sb.append(cbthsl.translateColorsIntToString(colorsLocation[i]) + ", ");
42 i++;
43 }
44
45 sb.append(cbthsl.translateColorsIntToString(colorsLocation[i]) + "].");
46 sb.append(cbthsl.getString("newLine")
47 + "ERROR: (Expressed by the facelet colors of the cubelet "
48 + "that belongs there in solved cubestate.) Our apologies for "
49 + "the inconvenience.");
50
51 return sb.toString();
52 }
53 }
1 package exceptions;
2
3 public class NoSuchSettingFoundException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String nameSetting;
7
8 // Constructor:
9 public NoSuchSettingFoundException(String nameSetting) {
10 super();
11 this.nameSetting = nameSetting;
12 }
13
14 @Override
15 public String toString() {
16 return "ERROR: Attempt to reach for unexisting setting: \"" + nameSetting
17 + "\". Our apologies for the inconvenience.";
18 }
19 }
1 package exceptions;
2
3 public class NotAvailableException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String subject;
7 private String solution;
8
9 // Constructors:
10 public NotAvailableException() {
11 super();
12 this.subject = null;
13 this.solution = null;
14 }
15
16 public NotAvailableException(String subject, String solution) {
17 super();
18 this.subject = subject;
19 this.solution = solution;
20 }
21
22 @Override
23 public String toString() {
24 return "ERROR: There's no (vaild) \"" + subject
25 + "\" available. Our apologies for the inconvenience. " + solution;
26 }
27 }
1 package exceptions;
2
3 public class NotIntendedIPAddressException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String actualIPAddress;
7 private String intendedIPAddress;
8 private String deviceType;
9
10 // Constructor:
11 public NotIntendedIPAddressException(String actualIPAddress, String deviceType,
12 String intendedIPAddress) {
13 this.actualIPAddress = actualIPAddress;
14 this.intendedIPAddress = intendedIPAddress;
15 this.deviceType = deviceType;
16 }
17
18 @Override
19 public String toString() {
20 return "ERROR: Actual IP-address of " + deviceType + ": \"" + actualIPAddress
21 + "\" does not match intended address: \"" + intendedIPAddress
22 + "\". Our apologies for the inconvencience.";
23 }
24 }
1 package exceptions;
2
3 public class NoValidFileException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String fileType;
7
8 // Constructors:
9 public NoValidFileException() {
10 super();
11 this.fileType = null;
12 }
13
14 public NoValidFileException(String fileType) {
15 super();
16 this.fileType = fileType;
17 }
18
19 @Override
20 public String toString() {
21 return "ERROR: There was no valid \"" + fileType
22 + "\"-file selected. Our apologies for the inconvenience.";
23 }
24
25 }
1 package exceptions;
2
3 public class NumberNotFoundException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String errorMessageTail;
7
8 // Constructors:
9 public NumberNotFoundException() {
10 super();
11 this.errorMessageTail = null;
12 }
13
14 public NumberNotFoundException(String errorMessageTail) {
15 super();
16 this.errorMessageTail = errorMessageTail;
17 }
18
19 @Override
20 public String toString() {
21 return "ERROR: Number wasn't found in " + errorMessageTail
22 + ". Our apologies for the inconvenience.";
23 }
24
25 }
1 package exceptions;
2
3 public class WorkInProgressException extends Exception {
4
5 private static final long serialVersionUID = 1L;
6 private String errorMessage;
7
8 // Constructors:
9 public WorkInProgressException() {
10 super();
11 this.errorMessage = null;
12 }
13
14 public WorkInProgressException(String errorMessage) {
15 super();
16 this.errorMessage = errorMessage;
17 }
18
19 @Override
20 public String toString() {
21 return "[WIP] " + errorMessage + "will not function properly yet. "
22 + "Our apologies for the inconvenience.";
23 }
24 }
1 package listeners.aut;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.AutomaticRoutine;
7 import model.CBTHImagesList;
8 import model.CubeFacesList;
9 import view.ViewTabPanel4Aut;
10
11 public class B_AUT_AutomaticRoutineListener implements ActionListener {
12
13 private AutomaticRoutine autoRoutineThread;
14 private CBTHImagesList imgl;
15 private CubeFacesList cfl;
16 private ViewTabPanel4Aut vtpa;
17
18 // Constructor:
19 public B_AUT_AutomaticRoutineListener(CBTHImagesList imgl, CubeFacesList cfl,
20 ViewTabPanel4Aut vtpa) {
21 this.imgl = imgl;
22 this.cfl = cfl;
23 this.vtpa = vtpa;
24 }
25
26 /*
27 * Instance method: Implementing an ActionListener, this class should provide
28 * an actionPerformed(ActionEvent e)-method. This method will react on the
29 * JButton.
30 */
31 public void actionPerformed(ActionEvent e) {
32
33 // If a previous thread is running, try to stop it:
34 if (autoRoutineThread != null) {
35 try {
36 AutomaticRoutine.setRoutineNotAborted(false);
37 autoRoutineThread.join();
38 } catch (InterruptedException ie) {
39 System.err.println("ERROR: Interrupted exception occurred. "
40 + "Our apologies for the inconvenience.");
41 }
42 }
43
44 System.out.println("Automatic routine started...");
45
46 autoRoutineThread = new AutomaticRoutine(imgl, cfl, vtpa);
47 AutomaticRoutine.setRoutineNotAborted(true);
48 autoRoutineThread.start();
49 }
50 }
1 package listeners.aut;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import javax.swing.JOptionPane;
6
7 import model.CBTHSettingsList;
8 import model.CommandSeq;
9 import model.CommonObjects;
10
11 public class B_AUT_CommandToRobotListener implements ActionListener {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14
15 // Constructor:
16 public B_AUT_CommandToRobotListener() {
17 super();
18 }
19
20 // Instance method:
21 public void actionPerformed(ActionEvent e) {
22 String move = null;
23 try {
24 move = (String) JOptionPane.showInputDialog(null,
25 "Which cube(-reading/-solving) move is to be performed? "
26 + "Enter an integer number...",
27 "Manually add move to robot's queue...", JOptionPane.QUESTION_MESSAGE, null,
28 null, "3");
29 CommandSeq.addNewCommand(Integer.parseInt(move));
30 } catch (NumberFormatException nfe) {
31 CommandSeq.addNewCommand(cbthsl.getInt("noValidCommand"));
32 }
33 }
34 }
1 package listeners.aut;
2
3 import java.awt.event.ActionListener;
4 import java.awt.event.ActionEvent;
5
6 import model.AutomaticRoutine;
7 import model.CommandSeq;
8
9 public class B_AUT_StopAutoRoutineListener implements ActionListener {
10
11 // Constructor:
12 public B_AUT_StopAutoRoutineListener() {
13 super();
14 }
15
16 // Instance method:
17 public void actionPerformed(ActionEvent e) {
18 // Robot will stop as quickly as possible from the Java-software
19 // by throwing away it's queue.
20 CommandSeq.stopAsQuicklyAsPossile();
21
22 // AutomaticRoutine will discard its tasks:
23 AutomaticRoutine.setRoutineNotAborted(false);
24
25 }
26 }
1 package listeners.aut;
2
3 import java.awt.event.ItemListener;
4 import java.awt.event.ItemEvent;
5
6 import model.AutomaticRoutine;
7
8 public class T_AUT_SubTasksItemListener implements ItemListener {
9
10 private int indexBooleanToWatch;
11
12 // Constructor:
13 public T_AUT_SubTasksItemListener(int indexBooleanToWatch) {
14 this.indexBooleanToWatch = indexBooleanToWatch;
15 }
16
17 /*
18 * Implementing an ItemListener, this class should provide an
19 * itemStateChanged(ItemEvent e)-method. This method will 'react' on the
20 * JToggleButton.
21 */
22 public void itemStateChanged(ItemEvent e) {
23 if (e.getStateChange() == ItemEvent.SELECTED) {
24 AutomaticRoutine.setSubTaskNecessary(indexBooleanToWatch, true);
25 } else {
26 AutomaticRoutine.setSubTaskNecessary(indexBooleanToWatch, false);
27 }
28 }
29 }
1 package listeners.cam;
2
3 import java.awt.event.*;
4 import javax.swing.JOptionPane;
5
6 import model.CBTHSettingsList;
7 import model.CommonObjects;
8
9 public class B_CAM_ConnectCamListener implements ActionListener {
10
11 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
12
13 // Constructor:
14 public B_CAM_ConnectCamListener() {
15 super();
16 }
17
18 // Instance method:
19 public void actionPerformed(ActionEvent e) {
20 String camName = null;
21 camName = (String) JOptionPane.showInputDialog(null,
22 "Enter a number/name to specify the camera to be used:",
23 "Specify your capture device...", JOptionPane.QUESTION_MESSAGE, null, null, "0");
24 cbthsl.setString("captureDevice", camName);
25 }
26 }
1 package listeners.cam;
2
3 import java.awt.event.*;
4
5 import connection.conWithRobot.CommunicationRobotThread;
6 import model.CommonObjects;
7
8 public class B_CAM_ConnectRobotListener implements ActionListener {
9
10 // Constructor:
11 public B_CAM_ConnectRobotListener() {
12 super();
13 }
14
15 // Instance method:
16 public void actionPerformed(ActionEvent e) {
17
18 CommunicationRobotThread comRobot = CommonObjects.getCommunicatieRobot();
19 if (!comRobot.isAlive()) {
20 // "isAlive()" is a standard threadinstance-method
21 // to check whether it's running.
22 comRobot.start();
23 }
24 comRobot.initializeCommunicationRobot();
25 }
26 }
1 package listeners.cam;
2
3 import java.awt.event.*;
4
5 import connection.conWithCamera.CamTakePicture;
6 import exceptions.NoCaptureDevConnectionException;
7 import model.CBTHImage;
8 import model.CBTHImagesList;
9
10 public class B_CAM_TakeAPictureListener implements ActionListener {
11
12 private CBTHImagesList imgl;
13
14 // Constructor:
15 public B_CAM_TakeAPictureListener(CBTHImagesList imgl,
16 T_CAM_LiveStreamItemListener lsil) {
17 this.imgl = imgl;
18 new CamTakePicture(lsil);
19 }
20
21 // Instance method:
22 public void actionPerformed(ActionEvent e) {
23 try {
24 CBTHImage img = null;
25 img = CamTakePicture.takePicture();
26 if (img != null) {
27 imgl.addCBTHImage(img);
28 }
29 } catch (NoCaptureDevConnectionException ncdce) {
30 System.err.println(ncdce);
31 }
32 }
33 }
1 package listeners.cam;
2
3 import java.awt.event.*;
4 import java.awt.image.BufferedImage;
5 import javax.swing.*;
6
7 import org.opencv.core.Core;
8 import org.opencv.videoio.VideoCapture;
9 import org.opencv.videoio.Videoio;
10
11 import connection.conWithCamera.*;
12 import exceptions.NoCaptureDevConnectionException;
13 import model.CBTHSettingsList;
14 import model.CommonObjects;
15
16 public class T_CAM_LiveStreamItemListener implements ItemListener {
17
18 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
19 private JLabel l_CamView;
20 private CamLiveStreamThread clsThread;
21 private VideoCapture cam;
22 private Thread t;
23 private boolean linkCamEstablished;
24
25 // Constructor:
26 public T_CAM_LiveStreamItemListener(JLabel l_CamView) {
27 this.l_CamView = l_CamView;
28 this.linkCamEstablished = false;
29 }
30
31 // Getters:
32 public int getCapDeviceFrameHeight() {
33
34 int value = 0;
35 if (cam.isOpened() && cam != null) {
36 value = (int) cam.get(Videoio.CAP_PROP_FRAME_WIDTH);
37 }
38 return value;
39 }
40
41 public int getCapDeviceFrameWidth() {
42
43 int value = 0;
44 if (cam.isOpened() && cam != null) {
45 value = (int) cam.get(Videoio.CAP_PROP_FRAME_WIDTH);
46 }
47 return value;
48 }
49
50 public BufferedImage getCurrentFrame() throws NoCaptureDevConnectionException {
51 BufferedImage frame = null;
52
53 if (linkCamEstablished) {
54 frame = clsThread.getCurrentFrame();
55 }
56
57 else {
58 throw new NoCaptureDevConnectionException();
59 }
60 return frame;
61 }
62
63 public boolean getLinkCamEstablished() {
64 return linkCamEstablished;
65 }
66
67 // Instance methods:
68 public void connectToCapDevice() {
69
70 try {
71 // Happens when the livestream-button is hit:
72
73 System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
74
75 // Creation of the VideoCapture-object.
76 cam = new VideoCapture();
77 String capDeviceName = cbthsl.getString("captureDevice");
78 int capDeviceIndex = 0;
79 linkCamEstablished = false;
80
81 /*
82 * The CBTHSetting captureDevice is of the type String an not int because
83 * it was made ready to contain a full ip-adres to reach the camdevice.
84 * However this was not succeeded, so the cam is reached by it's device
85 * index. possible indexes 0 or 700, 1 or 701, ...
86 *
87 * (Port used by CAMERA 3956 <= learned from WireSharksoftware)
88 */
89 try {
90 /*
91 * At first, we try to reach the cam by its index. To do so, the
92 * capDeviceName is converted to a number if a NumberFormatException
93 * would occur, meaning that the capDeviceName is not a number, we try
94 * later on to open it by it's String name.
95 */
96
97 capDeviceIndex = Integer.parseInt(capDeviceName);
98 cam.open(capDeviceIndex);
99
100 } catch (NumberFormatException nfe) {
101
102 /*
103 * Another attempt to reach for the cam, using its capDeviceName as a
104 * String.
105 */
106
107 cam.open(capDeviceName);
108 }
109
110 if (cam.isOpened()) {
111 System.out.println("[CAMLINK]: Link to \"" + cam.toString()
112 + "\" as capture-device was established properly.");
113 linkCamEstablished = true;
114 l_CamView.setText("");
115 clsThread = new CamLiveStreamThread(cam, l_CamView);
116 t = new Thread(clsThread, "CBTH: Camera-stream.");
117
118 /*
119 * The Java Virtual Machine (JVM) only stops if all user-threads have
120 * finished. "daemon"="spook" means the thread is running in the
121 * background. Mr. Michiel Willocx told us this is not quite necessary.
122 */
123
124 // t.setDaemon(true);
125
126 clsThread.runnable = true;
127 t.start();
128 } else {
129 String newLine = cbthsl.getString("newLine");
130 System.err.println("[CAMLINK]: ERROR: Selected capture device couldn't be opened."
131 + newLine + "[CAMLINK]: Hint: Make sure prior to booting "
132 + "CubeThesis, \"IC-Capture\" was started and shut down again." + newLine
1 package listeners.cbthsettings;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.CBTHSettingsList;
7 import model.CommonObjects;
8
9 public class MenuItemSortListener implements ActionListener {
10
11 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
12 private int sortingCriterion;
13
14 // Constructor:
15 public MenuItemSortListener(int sortingCriterion) {
16
17 this.sortingCriterion = sortingCriterion;
18 }
19
20 // Instance method:
21 public void actionPerformed(ActionEvent e) {
22 cbthsl.sortCBTHSettings(sortingCriterion);
23 }
24 }
1 package listeners.cbthsettings;
2
3 import javax.swing.event.DocumentEvent;
4 import javax.swing.event.DocumentListener;
5 import javax.swing.JTextField;
6
7 import model.CBTHSettingsList;
8 import model.CommonObjects;
9
10 public class TF_SettingsCustomizerDocumentListener implements DocumentListener {
11
12 private static CBTHSettingsList cbthsl;
13 private JTextField tf_TextFieldToWatch;
14
15 // Constructor:
16 public TF_SettingsCustomizerDocumentListener(JTextField tf_textFieldToWatch) {
17
18 // Source: http://stackoverflow.com/questions/3953208/
19 // value-change-listener-to-jtextfield On 28/03/2016.
20 cbthsl = CommonObjects.getCBTHSettingsList();
21 this.tf_TextFieldToWatch = tf_textFieldToWatch;
22 }
23
24 // Instance methods:
25 public void changedUpdate(DocumentEvent e) {
26 update();
27 }
28
29 public void removeUpdate(DocumentEvent e) {
30 update();
31 }
32
33 public void insertUpdate(DocumentEvent e) {
34 update();
35 }
36
37 public void update() {
38 cbthsl.filterSettingsOnTextFragment(tf_TextFieldToWatch.getText());
39 }
40 }
1 package listeners.cbthsettings;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.CBTHSetting;
7 import view.VisualCBTHSetting;
8
9 public class TF_VisualCBTHSettingListener implements ActionListener {
10
11 private CBTHSetting cbths;
12 private VisualCBTHSetting visualCBTHS;
13
14 // Constructors:
15 public TF_VisualCBTHSettingListener() {
16 this.cbths = null;
17 this.visualCBTHS = null;
18 }
19
20 public TF_VisualCBTHSettingListener(CBTHSetting cbths, VisualCBTHSetting visualCBTHS) {
21 this.cbths = cbths;
22 this.visualCBTHS = visualCBTHS;
23 }
24
25 // Instance method:
26 public void actionPerformed(ActionEvent e) {
27 cbths.setAll(null, null, null, visualCBTHS.getTF_CBTHSValue().getText(), null);
28 }
29 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import model.CubeFace;
6 import view.ViewTabPanel2Cub;
7
8 public class B_CUBE_AssignToMainCubeFaceListener implements ActionListener {
9
10 private ViewTabPanel2Cub vtpc;
11
12 // Constructor:
13 public B_CUBE_AssignToMainCubeFaceListener(ViewTabPanel2Cub vtpc) {
14 this.vtpc = vtpc;
15 }
16
17 // Instance method:
18 public void actionPerformed(ActionEvent e) {
19
20 CubeFace cf = null, mcf = null;
21
22 mcf = vtpc.getSelectedMainCubeFaceFromCombo();
23 cf = vtpc.getCurrentCubeFace();
24
25 if (cf != null && mcf != null) {
26 mcf.setCubeFaceDeepCopy(cf.getColorsMatrix(), cf.getConfidenceMatrix());
27 vtpc.cubeFacePanelUpUpdate(mcf);
28 System.out.println("MainCubeFace \"" + mcf.toString() + "\" was updated.");
29 }
30 }
31 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import exceptions.CubeletAlreadyAssignedException;
6 import exceptions.FaceletColorNoneException;
7 import exceptions.NonExistingCubeletException;
8 import model.CubeConfiguration;
9 import model.CubeFace;
10 import model.CubeFacesList;
11
12 public class B_CUBE_BuildVirtualCubeListener implements ActionListener {
13
14 private CubeFacesList cfl;
15
16 // Constructor:
17 public B_CUBE_BuildVirtualCubeListener(CubeFacesList cfl) {
18
19 this.cfl = cfl;
20 }
21
22 // Instance method:
23 public void actionPerformed(ActionEvent e) {
24
25 CubeFace[] mainCubeFacesArray = cfl.getAllMainCubeFaces();
26 if (mainCubeFacesArray != null && mainCubeFacesDifferFromNull(mainCubeFacesArray)) {
27 try {
28 CubeConfiguration.buildVirtualCube(mainCubeFacesArray);
29 } catch (FaceletColorNoneException fcne) {
30 System.err.println(fcne);
31 } catch (NonExistingCubeletException nece) {
32 System.err.println(nece);
33 } catch (CubeletAlreadyAssignedException caae) {
34 System.err.println(caae);
35 }
36 }
37 }
38
39 // Static method:
40 public static boolean mainCubeFacesDifferFromNull(CubeFace[] hv) {
41 boolean notNull = true;
42 int index = 0;
43
44 while (notNull && index < hv.length) {
45
46 if (hv[index] == null) {
47 notNull = false;
48 }
49 index++;
50 }
51 return notNull;
52 }
53 }
1
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import exceptions.NumberNotFoundException;
6 import model.CubeFacesList;
7 import view.ViewTabPanel2Cub;
8
9 public class B_CUBE_DeleteCubeFaceListener implements ActionListener {
10
11 private ViewTabPanel2Cub vtpc;
12 private CubeFacesList cfl;
13
14 // Constructor:
15 public B_CUBE_DeleteCubeFaceListener(ViewTabPanel2Cub vtpc, CubeFacesList cfl) {
16 this.vtpc = vtpc;
17 this.cfl = cfl;
18 }
19
20 // Instance method:
21 public void actionPerformed(ActionEvent e) {
22 if (cfl.getSize() != 0) {
23
24 try {
25 int cfID = vtpc.getCurrentCubeFace().getID();
26
27 // Before deleting, the view is set to the previous CubeFace:
28 int indexInArrayList = -1;
29 try {
30 indexInArrayList = cfl.searchIndexOfCubeFaceOnID(cfID);
31 } catch (NumberNotFoundException exp) {
32 }
33
34 if (indexInArrayList != -1 && indexInArrayList > 0) {
35 this.vtpc.setCurrentCubeFace(cfl.getCubeFace(indexInArrayList - 1));
36 } else {
37 vtpc.setCurrentCubeFace(null);
38 }
39
40 cfl.deleteCubeFace(cfID);
41
42 System.out.println("CubeFace \"" + cfID + "\" was deleted properly.");
43 } catch (NumberNotFoundException nnfe) {
44 System.err.println(nnfe);
45 }
46 }
47 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import exceptions.NumberNotFoundException;
6 import model.CubeFace;
7 import model.CubeFacesList;
8 import view.ViewTabPanel2Cub;
9
10 public class B_CUBE_NextCubeFaceListener implements ActionListener {
11
12 private ViewTabPanel2Cub vtpc;
13 private CubeFacesList cfl;
14
15 // Constructor:
16 public B_CUBE_NextCubeFaceListener(ViewTabPanel2Cub vtpc, CubeFacesList cfl) {
17 this.vtpc = vtpc;
18 this.cfl = cfl;
19 }
20
21 // Instance method:
22 public void actionPerformed(ActionEvent e) {
23 CubeFace cf = vtpc.getCurrentCubeFace();
24 int indexInArrayList = -1;
25
26 if (cf != null) {
27 try {
28 indexInArrayList = cfl.searchIndexOfCubeFaceOnID(cf.getID());
29 } catch (NumberNotFoundException exp) {
30 /* System.err.println(exp); */}
31
32 if (indexInArrayList != -1 && indexInArrayList < (cfl.getSize() - 1)) {
33 vtpc.setCurrentCubeFace(cfl.getCubeFace(indexInArrayList + 1));
34 }
35 } else {
36 if (cfl.getSize() > 0) {
37 vtpc.setCurrentCubeFace(cfl.getCubeFace(0));
38 }
39 }
40 }
41 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import view.ViewTabPanel2Cub;
6 import model.CubeFace;
7 import model.CubeFacesList;
8 import exceptions.NumberNotFoundException;
9
10 public class B_CUBE_PreviousCubeFaceListener implements ActionListener {
11
12 private ViewTabPanel2Cub vtpc;
13 private CubeFacesList cfl;
14
15 // Constructor:
16 public B_CUBE_PreviousCubeFaceListener(ViewTabPanel2Cub vtpc, CubeFacesList cfl) {
17 this.vtpc = vtpc;
18 this.cfl = cfl;
19 }
20
21 // Instance method:
22 public void actionPerformed(ActionEvent e) {
23
24 CubeFace cf = vtpc.getCurrentCubeFace();
25 int indexInArrayList = -1;
26 if (cf != null) {
27 try {
28 indexInArrayList = cfl.searchIndexOfCubeFaceOnID(cf.getID());
29 } catch (NumberNotFoundException exp) {
30 /* System.err.println(exp); */}
31
32 if (indexInArrayList != -1 && indexInArrayList > 0) {
33 vtpc.setCurrentCubeFace(cfl.getCubeFace(indexInArrayList - 1));
34 }
35 } else {
36 if (cfl.getSize() > 0) {
37 vtpc.setCurrentCubeFace(cfl.getCubeFace(0));
38 }
39 }
40 }
41 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import model.CubeFace;
6 import view.ViewTabPanel2Cub;
7
8 public class B_CUBE_TurnCFace90Degrees implements ActionListener {
9
10 private ViewTabPanel2Cub vtpc;
11 private boolean clockwise;
12
13 // Constructor:
14 public B_CUBE_TurnCFace90Degrees(ViewTabPanel2Cub vtpc, boolean clockwise) {
15
16 this.vtpc = vtpc;
17 this.clockwise = clockwise;
18 }
19
20 // Instance method:
21 public void actionPerformed(ActionEvent e) {
22
23 CubeFace cf = vtpc.getCurrentCubeFace();
24 if (cf != null) {
25
26 vtpc.getCurrentCubeFace().rotateCubeFace(clockwise);
27 }
28 }
29 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import model.*;
6
7 public class Co_CUBE_ColorsOnCubeFaceDropdownListener implements ItemListener {
8
9 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
10 private int row;
11 private int column;
12 private CubeFace cf;
13 private boolean active;
14 // Prevent the listeners from getting triggerd,
15 // when the change is applied automatically.
16
17 // Constructor:
18 public Co_CUBE_ColorsOnCubeFaceDropdownListener(CubeFace cf, int row, int column) {
19 this.cf = cf;
20 this.row = row;
21 this.column = column;
22 this.active = true;
23 }
24
25 // Instance methods:
26 public void setActive(boolean active) {
27 this.active = active;
28 }
29
30 public void itemStateChanged(ItemEvent e) {
31
32 /*
33 * e.getStateChange() equals '2' on deselecting and 1 when selecting. '1' is
34 * represented by ItemEvent.SELECTED. Enabling using "active" was needed
35 * during an update of the respective VisualCubeFace.
36 */
37 if (e.getStateChange() == ItemEvent.SELECTED && active) {
38
39 int colorIntValue = cbthsl.translateColorsStringToInt((String) e.getItem());
40 double confidenceDoubleValue = 100.0;
41
42 /*
43 * The idea is: When the user manually adapts a facelet, the certainty of
44 * that facelet is 100% from then on. If the user would make it "None",
45 * then there's 0% certainty.
46 */
47 if (colorIntValue == 6) {
48 confidenceDoubleValue = 0.0;
49 }
50 cf.setOneColorOneConfidenceLevel(colorIntValue, confidenceDoubleValue, row, column);
51 }
52 }
53 }
1 package listeners.img;
2
3 import java.awt.event.*;
4 import java.io.*;
5
6 import cbthFileChooser.CBTHFileChooser;
7 import model.CBTHImage;
8 import model.CBTHImagesList;
9
10 public class B_IMG_BrowseImageListener implements ActionListener {
11
12 private CBTHFileChooser cbthfc;
13 private CBTHImagesList imgl;
14 private CBTHImage img;
15
16 // Constructor:
17 public B_IMG_BrowseImageListener(CBTHFileChooser cbthfc, CBTHImagesList imgl) {
18 this.cbthfc = cbthfc;
19 this.imgl = imgl;
20 }
21
22 // Instance method:
23 public void actionPerformed(ActionEvent e) {
24 File f = cbthfc.fcOpenFile(0);
25 if (f != null) {
26 img = new CBTHImage(null, f, -1, -1, -1, -1);
27 imgl.addCBTHImage(img);
28 }
29 }
30 }
1 package listeners.cube;
2
3 import java.awt.event.*;
4
5 import model.CubeFace;
6 import view.ViewTabPanel2Cub;
7
8 public class Co_CUBE_MainCFacesDropdownListener implements ItemListener {
9
10 private ViewTabPanel2Cub vtpc;
11
12 // Constructor:
13 public Co_CUBE_MainCFacesDropdownListener(ViewTabPanel2Cub vtpc) {
14 this.vtpc = vtpc;
15 }
16
17 // Instance method:
18 public void itemStateChanged(ItemEvent e) {
19
20 CubeFace cf = null;
21 /*
22 * e.getStateChange() equals '2' on deselecting and 1 when selecting. '1' is
23 * represented by ItemEvent.SELECTED. If another CubeFace is selected from
24 * the dropdown, this method is invoked twice on different objects.
25 */
26 if (e.getStateChange() == ItemEvent.SELECTED) {
27 cf = (CubeFace) e.getItem();
28 vtpc.cubeFacePanelUpUpdate(cf);
29 }
30 }
31 }
1 package listeners.img;
2
3 import java.awt.event.*;
4 import java.io.*;
5
6 import cbthFileChooser.CBTHFileChooser;
7 import model.CBTHImage;
8 import model.CBTHImagesList;
9
10 public class B_IMG_BrowseImageListener implements ActionListener {
11
12 private CBTHFileChooser cbthfc;
13 private CBTHImagesList imgl;
14 private CBTHImage img;
15
16 // Constructor:
17 public B_IMG_BrowseImageListener(CBTHFileChooser cbthfc, CBTHImagesList imgl) {
18 this.cbthfc = cbthfc;
19 this.imgl = imgl;
20 }
21
22 // Instance method:
23 public void actionPerformed(ActionEvent e) {
24 File f = cbthfc.fcOpenFile(0);
25 if (f != null) {
26 img = new CBTHImage(null, f, -1, -1, -1, -1);
27 imgl.addCBTHImage(img);
28 }
29 }
30 }
1 package listeners.img;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import exceptions.WorkInProgressException;
7
8 public class B_IMG_ColorCalibrationListener implements ActionListener {
9
10 // Constructor:
11 public B_IMG_ColorCalibrationListener() {
12 super();
13 }
14
15 // Instance method:
16 public void actionPerformed(ActionEvent e) {
17 try {
18 throw new WorkInProgressException("The button: \"Color calibration\" ");
19 } catch (WorkInProgressException wipe) {
20 System.out.println(wipe);
21 }
22 }
23 }
1 package listeners.img;
2
3 import java.awt.event.*;
4 import javax.swing.*;
5
6 import exceptions.NoImageForColorEstimationException;
7 import model.*;
8 import view.ViewTabPanel1Img;
9
10 public class B_IMG_ColorEstimationListener implements ActionListener {
11
12 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
13 private ViewTabPanel1Img vtpi;
14 private CubeFacesList cfl;
15
16 // Constructor:
17 public B_IMG_ColorEstimationListener(ViewTabPanel1Img vtpi, CubeFacesList cfl) {
18
19 this.vtpi = vtpi;
20 this.cfl = cfl;
21 }
22
23 // Instance method:
24 public void actionPerformed(ActionEvent e) {
25
26 try {
27 // Launch color-estimation upon the actual CBTHImage:
28 CBTHImage temporyImage = vtpi.getImgTemporary();
29
30 if (temporyImage == null) {
31 throw new NoImageForColorEstimationException();
32 }
33
34 else {
35 CubeFace cf = ColorEstimation.colorRecognition(temporyImage);
36 cfl.addCubeFace(cf);
37
38 JPanel content = cf.createVCubeFace();
39
40 /*
41 * Spawn obtained CubeFace from the color-recognition. In automatic
42 * routine, this is omitted.
43 */
44 JFrame f = cbthsl.createCubeThesisFrame("Result color-estimation...");
45 f.add(content);
46 f.pack();
47 f.setVisible(true);
48 }
49 } catch (NoImageForColorEstimationException nifcee) {
50 System.err.println(nifcee);
51 }
52 }
53 }
1 package listeners.img;
2
3 import java.awt.event.*;
4
5 import exceptions.NumberNotFoundException;
6 import model.CBTHImage;
7 import model.CBTHImagesList;
8 import view.ViewTabPanel1Img;
9
10 public class B_IMG_DeleteImageListener implements ActionListener {
11
12 private ViewTabPanel1Img vtpi;
13 private CBTHImagesList imgl;
14 private CBTHImage imgToDelete;
15
16 // Constructor:
17 public B_IMG_DeleteImageListener(ViewTabPanel1Img vtpi, CBTHImagesList imgl) {
18 this.vtpi = vtpi;
19 this.imgl = imgl;
20 }
21
22 // Instance method:
23 public void actionPerformed(ActionEvent e) {
24 if (imgl.getSize() != 0) {
25
26 try {
27 imgToDelete = vtpi.getImgCombo();
28 String imgToString = imgToDelete.toString();
29 imgl.deleteCBTHImage(imgToDelete.getID());
30 vtpi.updateImgCropSpinners(null);
31
32 System.out.println("Image \"" + imgToString + "\" was deleted properly.");
33 } catch (NumberNotFoundException nnfe) {
34 System.err.println(nnfe);
35 }
36 }
37 }
38 }
1 package listeners.img;
2
3 import java.awt.event.*;
4
5 import cbthFileChooser.FileIO;
6
7 public class B_IMG_SaveImagesListener implements ActionListener {
8
9 // Constructor:
10 public B_IMG_SaveImagesListener() {
11 super();
12 }
13
14 // Instance method:
15 public void actionPerformed(ActionEvent e) {
16
17 // Saves only the "physical" images, not the paths of references in
18 // the SaveFile.cbth:
19 FileIO.savePhysicalImages();
20 }
21 }
1 package listeners.img;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import javax.swing.SpinnerNumberModel;
6
7 import model.CBTHSettingsList;
8 import model.CommonObjects;
9 import view.ViewTabPanel1Img;
10
11 public class B_IMG_UpdateCropParamListener implements ActionListener {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private ViewTabPanel1Img vtpi;
15
16 // Constructor:
17 public B_IMG_UpdateCropParamListener(ViewTabPanel1Img vtpi) {
18 this.vtpi = vtpi;
19 }
20
21 // Instance method:
22 /**
23 * This method will update the respective CBTHSettings from the manual
24 * crop-parameters.
25 */
26 public void actionPerformed(ActionEvent e) {
27 cbthsl.setInt("xCoCrop",
28 (((SpinnerNumberModel) vtpi.getS_IMG_X_CO().getModel()).getNumber().intValue()));
29 cbthsl.setInt("yCoCrop",
30 (((SpinnerNumberModel) vtpi.getS_IMG_Y_CO().getModel()).getNumber().intValue()));
31 cbthsl.setInt("widthCrop",
32 (((SpinnerNumberModel) vtpi.getS_IMG_Width().getModel()).getNumber().intValue()));
33 cbthsl.setInt("heigthCrop", (((SpinnerNumberModel) vtpi.getS_IMG_Height().getModel())
34 .getNumber().intValue()));
35 System.out.println("Crop-parameters have been updated.");
36 }
37 }
1 package listeners.img;
2
3 import java.awt.event.*;
4
5 import model.CBTHImage;
6 import view.ViewTabPanel1Img;
7
8 public class Co_IMG_CBTHImagesListDropdownListener implements ItemListener {
9
10 private ViewTabPanel1Img vtpi;
11
12 // Constructor:
13 public Co_IMG_CBTHImagesListDropdownListener(ViewTabPanel1Img vtpi) {
14 this.vtpi = vtpi;
15 }
16
17 // Instance method:
18 public void itemStateChanged(ItemEvent e) {
19 CBTHImage imgSelected = null;
20 imgSelected = (CBTHImage) e.getItem();
21
22 /*
23 * e.getStateChange() equals '2' on deselecting and 1 when selecting. '1' is
24 * represented by ItemEvent.SELECTED. If another CBTHImage is selected from
25 * the dropdown, this method is invoked twice on different objects.
26 */
27 if ((e.getStateChange() == ItemEvent.SELECTED && imgSelected != null)) {
28
29 vtpi.updateImgCropSpinners(imgSelected);
30 vtpi.updateImgWindow(imgSelected);
31 // System.out.println("Windowupdate: CBTHImage \""+
32 // imgSelected.toString()+"\" and its spinners are loaded.");
33 } else {
34 vtpi.updateImgWindow(null);
35 }
36 }
37 }
1 package listeners.img;
2
3 import javax.swing.*;
4 import javax.swing.event.*;
5
6 import model.CBTHImage;
7 import view.ViewTabPanel1Img;
8
9 /**
10 * DISCLAIMER: This class is implementing functionality to react on the changes
11 * of the CBTHImage-spinners. It does the job, but there're probably better ways
12 * to cope with this.
13 */
14 public class S_IMG_CropSpinnersListener implements ChangeListener {
15
16 private ViewTabPanel1Img vtpi;
17 private CBTHImage currentImg;
18
19 private JSpinner s_IMG_X_CO;
20 private JSpinner s_IMG_Y_CO;
21 private JSpinner s_IMG_Width;
22 private JSpinner s_IMG_Height;
23
24 private int a;
25 private int b;
26 private int c;
27 private int d;
28
29 // Constructors:
30 public S_IMG_CropSpinnersListener(ViewTabPanel1Img vtpi) {
31
32 this.currentImg = null;
33 this.vtpi = vtpi;
34
35 this.s_IMG_X_CO = null;
36 this.s_IMG_Y_CO = null;
37 this.s_IMG_Width = null;
38 this.s_IMG_Height = null;
39
40 this.a = 0;
41 this.b = 0;
42 this.c = 0;
43 this.d = 0;
44 }
45
46 public S_IMG_CropSpinnersListener(ViewTabPanel1Img vtpa, CBTHImage afb,
47 JSpinner s_IMG_X_CO, JSpinner s_IMG_Y_CO, JSpinner s_IMG_Width,
48 JSpinner s_IMG_Height) {
49
50 this.currentImg = afb;
51 this.vtpi = vtpa;
52
53 this.s_IMG_X_CO = s_IMG_X_CO;
54 this.s_IMG_Y_CO = s_IMG_Y_CO;
55 this.s_IMG_Width = s_IMG_Width;
56 this.s_IMG_Height = s_IMG_Height;
57
58 this.a = 0;
59 this.b = 0;
60 this.c = 0;
61 this.d = 0;
62 }
63
64 // Instance method:
65 /**
66 * To avoid illegal coordinates when cropping an image, the upperlimit of the
67 * width and height have to be restricted and updated when moving x-co and
68 * y-xo.
69 */
70 public void stateChanged(ChangeEvent e) {
71
72 /*
73 * In former version each time this.spinners private attributes where
74 * refreshed
75 */
76
77 currentImg = vtpi.getImgTemporary();
78
79 if (currentImg != null) {
80 a = ((SpinnerNumberModel) s_IMG_X_CO.getModel()).getNumber().intValue();
81 b = ((SpinnerNumberModel) s_IMG_Y_CO.getModel()).getNumber().intValue();
82 c = ((SpinnerNumberModel) s_IMG_Width.getModel()).getNumber().intValue();
83 d = ((SpinnerNumberModel) s_IMG_Height.getModel()).getNumber().intValue();
84
85 if ((a + c) > currentImg.getWidthOriginal()) {
86 c = currentImg.getWidthOriginal() - a;
87 s_IMG_Width.setModel(new SpinnerNumberModel(c, 0, c, 1));
88 } else {
89 if (((SpinnerNumberModel) s_IMG_Width.getModel()).getMaximum()
90 .compareTo((currentImg.getWidthOriginal() - a)) < 0) {
91 s_IMG_Width.setModel(
92 new SpinnerNumberModel(c, 0, currentImg.getWidthOriginal() - a, 1));
93 }
94 }
95
96 if ((b + d) > currentImg.getHeightOriginal()) {
97 d = currentImg.getHeightOriginal() - b;
98 s_IMG_Height.setModel(new SpinnerNumberModel(d, 0, d, 1));
99 } else {
100 if (((SpinnerNumberModel) s_IMG_Height.getModel()).getMaximum()
101 .compareTo((currentImg.getHeightOriginal() - b)) < 0) {
102 s_IMG_Height.setModel(
103 new SpinnerNumberModel(d, 0, currentImg.getHeightOriginal() - b, 1));
104 }
105 }
106 currentImg.setNewCropped(a, b, c, d);
107 }
108 vtpi.updateImgWindow(currentImg);
109 }
110 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4 import javax.swing.*;
5
6 import model.CBTHSettingsList;
7 import model.CommonObjects;
8
9 public class MenuItemAboutListener implements ActionListener {
10
11 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
12
13 // Constructor:
14 public MenuItemAboutListener() {
15 super();
16 }
17
18 // Instance method:
19 public void actionPerformed(ActionEvent e) {
20
21 String[] iconPathComp = { "img", "icon", "RubiksCube220x210.png" };
22 String iconPath = cbthsl.makeSysIndepFilePath(iconPathComp, 2);
23 ImageIcon rubiksCubeLogo = new ImageIcon(iconPath);
24 String newLine = cbthsl.getString("newLine");
25 JOptionPane.showMessageDialog(null,
26 "© CubeThesis as a Java program was developed to generate a series " + newLine
27 + "of solving commands for the Rubik's Cube based on "
28 + "visual input from some webcam." + newLine
29 + "It was developed as part of the Masters' Thesis of "
30 + "Simon Deschuytter and Pieter Depamelaere." + newLine
31 + "Promotors: K. Bruggeman & R. Claeys" + newLine + newLine
32 + "CubeThesis uses:" + newLine
33 + "- an OpenCV-Library to retrieve streams from the cameradevices." + newLine
34 + "- the Kociemba-algorithm via the \"Cubie\" Java-software, "
35 + "which Jaap Scherphuis provided." + newLine
36 + "- a Standalone Blender Game to visualize the virtual Cube." + newLine
37 + "- generated Javadoc files to show in some webbrowser, "
38 + "that yield for basic internal structure." + newLine + newLine + newLine
39 + "Encountering problems about CubeThesis? Please contact:" + newLine
40 + "pieter.depamelaere@hotmail.com",
41 "About © CubeThesis...", JOptionPane.INFORMATION_MESSAGE, rubiksCubeLogo);
42 }
43 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4
5 import console.ViewConsolePanel;
6
7 public class MenuItemConsoleClearListener implements ActionListener {
8
9 private ViewConsolePanel p_vcp;
10
11 // Constructor:
12 public MenuItemConsoleClearListener(ViewConsolePanel p_vcp) {
13
14 this.p_vcp = p_vcp;
15 }
16
17 // Instance method:
18 public void actionPerformed(ActionEvent e) {
19
20 this.p_vcp.updateLogFilesByFlushConsole(false, false);
21 }
22 }
1 package listeners.menu;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.awt.event.KeyEvent;
6 import javax.swing.*;
7
8 import listeners.cbthsettings.MenuItemSortListener;
9 import model.CommonObjects;
10 import model.CBTHSettingsList;
11 import view.VisualCBTHSettingsCustomizer;
12
13 public class MenuItemCustomizeSettingsListener implements ActionListener {
14
15 private CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
16 private JMenuBar menuBar;
17 private JMenu menu_Sort;
18 private JMenuItem menuItem_SortById;
19 private JMenuItem menuItem_SortByLabelText;
20 private JMenuItem menuItem_SortByType;
21
22 // Constructor:
23 public MenuItemCustomizeSettingsListener() {
24 this.menuBar = new JMenuBar();
25
26 this.menu_Sort = new JMenu("Sort");
27 menu_Sort.setMnemonic(KeyEvent.VK_S);
28
29 menuItem_SortById = new JMenuItem("Sort by iD (logical order)");
30 menuItem_SortById.setMnemonic(KeyEvent.VK_I);
31 menuItem_SortById.addActionListener(new MenuItemSortListener(0));
32
33 menuItem_SortByLabelText = new JMenuItem("Sort by labeltext (alphabetic)");
34 menuItem_SortByLabelText.setMnemonic(KeyEvent.VK_L);
35 menuItem_SortByLabelText.addActionListener(new MenuItemSortListener(1));
36
37 menuItem_SortByType = new JMenuItem("Sort by type (alphabetic)");
38 menuItem_SortByType.setMnemonic(KeyEvent.VK_T);
39 menuItem_SortByType.addActionListener(new MenuItemSortListener(2));
40
41 menu_Sort.add(menuItem_SortById);
42 menu_Sort.add(menuItem_SortByLabelText);
43 menu_Sort.add(menuItem_SortByType);
44
45 menuBar.add(menu_Sort);
46 }
47
48 // Instance method:
49 public void actionPerformed(ActionEvent e) {
50 JFrame f_customCBTHSettings = cbthsl
51 .createCubeThesisFrame("Customize CBTHSettings...");
52 VisualCBTHSettingsCustomizer vcbthsc = new VisualCBTHSettingsCustomizer();
53 cbthsl.addObserver(vcbthsc);
54 f_customCBTHSettings.add(vcbthsc);
55 f_customCBTHSettings.setJMenuBar(menuBar);
56 f_customCBTHSettings.pack();
57 f_customCBTHSettings.setVisible(true);
58 }
59 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4
5 import cbthFileChooser.FileIO;
6 import connection.conWithRobot.CommunicationRobotThread;
7 import console.ViewConsolePanel;
8 import listeners.cam.T_CAM_LiveStreamItemListener;
9 import model.CBTHSettingsList;
10 import model.CommonObjects;
11
12 public class MenuItemExitListener implements ActionListener {
13
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15 private ViewConsolePanel p_vcp;
16
17 // Constructor:
18 public MenuItemExitListener(ViewConsolePanel p_vcp) {
19
20 this.p_vcp = p_vcp;
21 }
22
23 // Instance method:
24 public void actionPerformed(ActionEvent e) {
25
26 FileIO.saveProject();
27
28 // Close connections: camerastream and communication with the robot:
29 CommunicationRobotThread comRobot = CommonObjects.getCommunicatieRobot();
30 T_CAM_LiveStreamItemListener lsil = CommonObjects.getCamLSIL();
31
32 if (comRobot.getLinkRobotEstablished()) {
33 comRobot.stopCommunicationRobot();
34 }
35
36 // If the stream is not properly closed, a "hs_err_pidxxx.log"-file
37 // is created.
38 if (lsil.getLinkCamEstablished()) {
39 lsil.disconnectFromCapDevice();
40 }
41
42 if (cbthsl.getBoolean("saveCBTHSettingsOnExit")) {
43 // If true, CBTHSettings are exported at this point.
44 cbthsl.exportCBTHSettingsToTXT();
45 }
46
47 // Flush the whole console and add footers to the logFiles:
48 this.p_vcp.updateLogFilesByFlushConsole(false, true);
49
50 System.exit(0);
51 }
52 }
1 package listeners.menu;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.CommonObjects;
7 import model.CBTHSettingsList;
8
9 public class MenuItemExportSettingsToText implements ActionListener {
10
11 private CBTHSettingsList cbthsl;
12
13 // Constructor:
14 public MenuItemExportSettingsToText() {
15 cbthsl = CommonObjects.getCBTHSettingsList();
16 }
17
18 // Instance method:
19 public void actionPerformed(ActionEvent e) {
20 cbthsl.exportCBTHSettingsToTXT();
21 }
22 }
1 package listeners.menu;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.CBTHSettingsList;
7 import model.CommonObjects;
8
9 public class MenuItemImportSettingsFromText implements ActionListener {
10
11 private CBTHSettingsList cbthsl;
12
13 // Constructor:
14 public MenuItemImportSettingsFromText() {
15 cbthsl = CommonObjects.getCBTHSettingsList();
16 }
17
18 // Instance method:
19 public void actionPerformed(ActionEvent e) {
20 cbthsl.importCBTHSettingsFromTXT();
21 }
22 }
1 package listeners.menu;
2
3 import java.awt.Desktop;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.io.File;
7 import java.net.*;
8
9 import model.CBTHSettingsList;
10 import model.CommonObjects;
11
12 public class MenuItemJavaDocListener implements ActionListener {
13
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15
16 // Constructor:
17 public MenuItemJavaDocListener() {
18 super();
19 }
20
21 // Instance method:
22 public void actionPerformed(ActionEvent e) {
23
24 String[] pathStructure = { "doc", "overview-summary.html" };
25 String url = cbthsl.makeSysIndepFilePath(pathStructure, 2);
26
27 // Source:
28 // http://stackoverflow.com/questions/10967451/
29 // open-a-link-in-browser-with-java-button viewed on 21/03/2016
30 // Source:
31 // http://stackoverflow.com/questions/6098472/
32 // pass-a-local-file-in-to-url-in-java viewed on 21/03/2016
33
34 Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
35 if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
36 try {
37 URI uri = new File(url).toURI();
38 desktop.browse(uri);
39 } catch (Exception exc) {
40 System.err.println("ERROR: Some unexpected error occurred during "
41 + "opening the JavaDoc. Our apologies for the inconvenience.");
42 exc.printStackTrace();
43 }
44 }
45 }
46 }
1 package listeners.menu;
2
3 import java.awt.Dimension;
4 import java.awt.event.*;
5 import java.awt.GridLayout;
6 import javax.swing.*;
7 import javax.swing.table.TableColumn;
8
9 import console.ConsoleCommands;
10 import console.ViewConsolePanel;
11 import model.CBTHSettingsList;
12 import model.CommonObjects;
13
14 public class MenuItemListCommandsListener implements ActionListener {
15
16 private static CBTHSettingsList cbthsl = null;
17 private JTable table = null;
18 private ViewConsolePanel vcp = null;
19 private String[] columnNames = { "Console-command", "Description" };
20 private String[][] data = null;
21
22 // Constructor:
23 public MenuItemListCommandsListener(ViewConsolePanel p_vcp) {
24
25 cbthsl = CommonObjects.getCBTHSettingsList();
26 this.vcp = p_vcp;
27 data = ConsoleCommands.getSupCommands();
28 table = new JTable(data, columnNames);
29
30 TableColumn column = null;
31 for (int i = 0; i < columnNames.length; i++) {
32 column = table.getColumnModel().getColumn(i);
33 switch (i) {
34 case 0:
35 column.setPreferredWidth(100);
36 break;
37 case 1:
38 column.setPreferredWidth(450);
39 break;
40 default:
41 column.setPreferredWidth(200);
42 break;
43 }
44 }
45
46 table.addMouseListener(new MouseAdapter() {
47 public void mouseClicked(MouseEvent e) {
48 selectedCommandToPrompt();
49 }
50 });
51 }
52
53 // Instance method:
54 public void actionPerformed(ActionEvent e) {
55
56 table.setPreferredScrollableViewportSize(new Dimension(550, 200));
57 table.setFillsViewportHeight(true);
58
59 // Create the scroll pane/JPanel/JFrame and add the table to it.
60 JScrollPane sp_tableScroll = new JScrollPane(table);
61 JPanel p_tablepanel = new JPanel(new GridLayout(1, 0));
62 JFrame frame = cbthsl.createCubeThesisFrame("Supported console-commands");
63 // Add the scroll pane to this panel.
64 p_tablepanel.add(sp_tableScroll);
65 frame.add(p_tablepanel);
66 frame.pack();
67 frame.setVisible(true);
68 }
69
70 public void selectedCommandToPrompt() {
71 vcp.setTextCommandPrompt(data[table.getSelectedRow()][0]);
72 }
73 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4 import java.io.*;
5
6 import javax.swing.JOptionPane;
7
8 import console.ViewConsolePanel;
9 import model.*;
10
11 public class MenuItemNewProjectListener implements ActionListener {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private static String newLine = cbthsl.getString("newLine");
15 private static String fS = cbthsl.getString("fileSeparator");
16 private CBTHImagesList imgl;
17 private CubeFacesList cfl;
18 private ViewConsolePanel p_vcp;
19
20 // Constructor:
21 public MenuItemNewProjectListener(CBTHImagesList imgl, CubeFacesList cfl,
22 ViewConsolePanel p_vcp) {
23
24 this.imgl = imgl;
25 this.cfl = cfl;
26 this.p_vcp = p_vcp;
27 }
28
29 // Instance method:
30 public void actionPerformed(ActionEvent e) {
31
32 String newProjectName = (String) JOptionPane.showInputDialog(null,
33 "Enter a name for this new project. (Avoid spaces in projectname)" + newLine
34 + "Your project will saved to the " + fS + "CubeThesisProjects - folder."
35 + newLine + "The project could also be saved to some subfolder by adding "
36 + "this OS-specific fileseparator: \"" + fS + "\"",
37 "Creation of new project...", JOptionPane.QUESTION_MESSAGE, null, null,
38 "NieuwProject");
39
40 if (newProjectName != null) {
41 String[] pathStruct1 = { "CubeThesisProjects", newProjectName, "ImgOriginal" };
42 String[] pathStruct2 = { "CubeThesisProjects", newProjectName, "ImgCropped" };
43
44 File org = new File(cbthsl.makeSysIndepFilePath(pathStruct1, 2));
45 File cropped = new File(cbthsl.makeSysIndepFilePath(pathStruct2, 2));
46
47 org.mkdirs();
48 cropped.mkdirs();
49
50 imgl.deleteAllCBTHImages();
51 cfl.deleteAllCubeFaces();
52 cfl.resetMainCubeFaces();
53 CubeConfiguration.setStartCubeletPerm(null);
54 CubeConfiguration.setStartCubeletOri(null);
55 CubeConfiguration.setStartFaceOri(null);
56 CubeConfiguration.setColorMapKey(null);
57 CommandSeq.stopAsQuicklyAsPossile();
58 CommandSeq.setSolutionCommandsMatrix(null, null, 0);
59
60 cbthsl.setCurrentProject(org.getParentFile());
61 p_vcp.updateLogFilesByFlushConsole(true, false);
62
63 System.out.println("Project \"" + newProjectName + "\" was created succesfully.");
64 }
65 }
66 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4 import java.io.*;
5
6 import cbthFileChooser.CBTHFileChooser;
7 import cbthFileChooser.FileIO;
8 import console.ViewConsolePanel;
9 import model.CBTHSettingsList;
10 import model.CommonObjects;
11
12 public class MenuItemOpenProjectListener implements ActionListener {
13
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15 private CBTHFileChooser cbthfc;
16 private ViewConsolePanel p_vcp;
17
18 // Constructor:
19 public MenuItemOpenProjectListener(CBTHFileChooser cbthfc, ViewConsolePanel p_vcp) {
20
21 this.cbthfc = cbthfc;
22 this.p_vcp = p_vcp;
23 }
24
25 // Instance method:
26 public void actionPerformed(ActionEvent e) {
27
28 // Launch pop-up window to let user choose:
29 File f = cbthfc.fcOpenFile(1);
30
31 if (f != null) {
32
33 cbthsl.setCurrentProject(new File(f.getParent()));
34 p_vcp.updateLogFilesByFlushConsole(true, false);
35 FileIO.openProject(f);
36 }
37 }
38 }
1 package listeners.menu;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5
6 import model.CBTHSettingsList;
7 import model.CommonObjects;
8
9 public class MenuItemRestoreFactorySettings implements ActionListener {
10
11 private CBTHSettingsList cbthsl;
12
13 // Constructor:
14 public MenuItemRestoreFactorySettings() {
15 cbthsl = CommonObjects.getCBTHSettingsList();
16 }
17
18 // Instance method:
19 public void actionPerformed(ActionEvent e) {
20 cbthsl.restoreSituationSimonAndPieter();
21 }
22 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4
5 import cbthFileChooser.CBTHFileChooser;
6
7 public class MenuItemSaveAsProjectListener implements ActionListener {
8
9 private CBTHFileChooser cbthfc;
10
11 // Constructor:
12 public MenuItemSaveAsProjectListener(CBTHFileChooser cbthfc) {
13
14 this.cbthfc = cbthfc;
15 }
16
17 // Instance method:
18 public void actionPerformed(ActionEvent e) {
19
20 cbthfc.fcSaveFile(1);
21 }
22 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4
5 import cbthFileChooser.FileIO;
6
7 public class MenuItemSaveProjectListener implements ActionListener {
8
9 // Constructor:
10 public MenuItemSaveProjectListener() {
11 super();
12 }
13
14 // Instance method:
15 public void actionPerformed(ActionEvent e) {
16
17 FileIO.saveProject();
18 }
19 }
1 package listeners.menu;
2
3 import java.awt.event.*;
4
5 import javax.swing.*;
6
7 import model.CBTHSettingsList;
8 import model.CommonObjects;
9
10 public class MenuItemUserManualListener implements ActionListener {
11
12 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
13
14 // Constructor:
15 public MenuItemUserManualListener() {
16 super();
17 }
18
19 // Instance method:
20 public void actionPerformed(ActionEvent e) {
21
22 JFrame frame = cbthsl.createCubeThesisFrame("Concise user's manual");
23 String newLine = cbthsl.getString("newLine");
24 JTextArea ta_Manual = new JTextArea(15, 80);
25
26 ta_Manual.setLineWrap(false);
27 ta_Manual.setEditable(false);
28 ta_Manual.setFont(cbthsl.getFont("guiFont1"));
29 ta_Manual.setText("CUBETHESIS USER MANUAL" + newLine + "======================"
30 + newLine + "" + newLine + "CubeThesis' GUI mainly consists of three parts:"
31 + newLine + "- A menubar, on top of the window, where several general functions "
32 + "are to be found." + newLine
33 + "- A tabpane, located in the middle, with 5 tabs." + newLine
34 + "- A console, located on the bottom of the window." + newLine + "" + newLine
35 + "The menubar, provides menu's [FILE], [CONSOLE], [CBTH-SETTINGS] & " + "[HELP]."
36 + newLine + "" + newLine
37 + "From left to right the tabs are: [CAMERA], [IMAGE], [CUBE], "
38 + "[ALGORITHMIC SOLVER] & [AUTOMATIC MODE]." + newLine
39 + "These tabs allow to load a specific group of functions relevant for "
40 + "that item." + newLine
41 + "E.g.: On tab [IMAGE], the cropspinners are relevant buttons." + newLine + ""
42 + newLine + "Each tabpanel consists of a controlPanel on the left hand side & a "
43 + "windowPanel on the right hand side." + newLine
44 + "The leftpanel hosts the buttons and stuff, while the right panel "
45 + "yields for more information." + newLine
46 + "The idea is that the user chooses to work in manual/automatic mode:" + newLine
47 + "Manual mode: The user will loop manually through the first 4 "
48 + "panels from left to right." + newLine
49 + "Automatic mode: The user navigates to tab [AUTOMATIC MODE] &"
50 + " clicks \"Automatic routine\"." + newLine + "" + newLine
51 + "The console will keep record of the communication between CubeThesis "
52 + "and the user." + newLine
53 + "Feedback output as well as error-messages (\" > : \") are "
54 + "displayed in there to help the user." + newLine
55 + "Underneath the console, a bar was created by means of a commandprompt"
56 + newLine + "CubeThesis will react at some supported commands (these are listed "
57 + "in menu \"Commands...\")." + newLine
58 + "These commands and other input from the user is shown on the "
59 + "console preceded by (\" < : \")" + newLine
60 + "The text on the console in logged in two files, a general logfile "
61 + "& a project-logfile." + newLine + "" + newLine
62 + "For most common issues, the occurred error will be displayed in "
63 + "the console." + newLine
64 + "Rebooting the software, can be a general first hint." + newLine
65 + "The solution to some problems is elaborated in the Paper & Addendum "
66 + "of the" + newLine
1 package listeners.solv;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.io.File;
6 import java.io.IOException;
7
8 import model.CBTHSettingsList;
9 import model.CommonObjects;
10
11 public class B_SOLV_BlenderGUIListener implements ActionListener {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14
15 // Constructor:
16 public B_SOLV_BlenderGUIListener() {
17 super();
18 }
19
20 // Instance method:
21 public void actionPerformed(ActionEvent e) {
22
23 System.out.println("WARNING: The BlenderGUI only works on windows-pc's.");
24 String[] pathStructure = { "ExtLib", "BlenderGUICBTH", "BlenderGUICBTH.exe" };
25 String blenderGUIPath = cbthsl.makeSysIndepFilePath(pathStructure, 2);
26
27 try {
28 Runtime.getRuntime().exec(blenderGUIPath, null,
29 new File(blenderGUIPath).getParentFile());
30 System.out.println(
31 "Within a few moments, the BlenderGUI will launch, " + "be patient...");
32 } catch (IOException e1) {
33 System.err.println(
34 "ERROR: An IOException occurred. Our apologies " + "for the inconvenience.");
35 System.err.println(
36 "ERROR: DISCLAIMER: The Blender-GUI is only " + "supported for Windows-pc's.");
37 e1.printStackTrace();
38 }
39 }
40 }
1 package listeners.solv;
2
3 import java.awt.event.*;
4
5 import exceptions.NotAvailableException;
6 import model.CubeConfiguration;
7 import solver.solverJS.viewSolverJS.Cubie;
8
9 public class B_SOLV_CubeToSolverListener implements ActionListener {
10
11 private Cubie cubie;
12
13 // Constructor:
14 public B_SOLV_CubeToSolverListener(Cubie cubie) {
15
16 this.cubie = cubie;
17 }
18
19 // Instance methods:
20 public void actionPerformed(ActionEvent e) {
21 try {
22 cubeToSolver();
23 } catch (NotAvailableException nae) {
24 System.err.println(nae);
25 }
26 }
27
28 public void cubeToSolver() throws NotAvailableException {
29 int[] cubeletPerm = null;
30 int[] cubeletOri = null;
31 int[] faceOri = null;
32
33 cubeletPerm = CubeConfiguration.getStartCubeletPerm();
34 cubeletOri = CubeConfiguration.getStartCubeletOri();
35 faceOri = CubeConfiguration.getStartFaceOri();
36
37 if (cubeletPerm != null && cubeletOri != null && faceOri != null) {
38
39 int[] cubeletPerm2 = deepCopy(cubeletPerm);
40 int[] cubeletOri2 = deepCopy(cubeletOri);
41 int[] faceOri2 = deepCopy(faceOri);
42
43 cubie.cubieSetCube(cubeletPerm2, cubeletOri2, faceOri2);
44
45 System.out.println("Cube-configuration was sent to the solver.");
46 if (!cubie.getT()) {
47 System.err
48 .println("ERROR: The present cube-configuration " + "seems unsolvable.");
49 /*
50 * The "t"-variable from Cubie implies more or less, that the specified
51 * cube-configuration is solvable or not. DISCLAIMER: The t-variable
52 * should not be fully trusted, it can appear unchanged while the
53 * configuration is unsolvable, then Cubie crashes.
54 */
55 }
56 } else {
57 throw new NotAvailableException("cube-configuration", "See tab [CUBE].");
58 }
59 }
60
61 // Static method:
62 /** Deep copy instead of shallow copying. */
63 public static int[] deepCopy(int[] array1) {
64 int[] array2 = new int[array1.length];
65
66 for (int q = 0; q < array1.length; q++) {
67 array2[q] = array1[q];
68 }
69 return array2;
70 }
71 }
1 package listeners.solv;
2
3 import java.awt.event.*;
4
5 import model.CommandSeq;
6 import model.CommonObjects;
7 import solver.solverJS.viewSolverJS.Cubie;
8 import solver.solverJS.algorithm.MoveSequence;
9
10 public class B_SOLV_EnumerateMovesListener implements ActionListener {
11
12 private Cubie cubie;
13
14 // Constructor:
15 public B_SOLV_EnumerateMovesListener() {
16 this.cubie = CommonObjects.getCubie();
17 }
18
19 // Instance method:
20 public void actionPerformed(ActionEvent e) {
21
22 MoveSequence moveSeq = cubie.getMoveSeqGenerator();
23
24 if (moveSeq != null) {
25
26 CommandSeq.setSolutionCommandsMatrix(moveSeq.getMoves(), moveSeq.getAmount(),
27 moveSeq.getLength());
28
29 System.out.println(CommandSeq.solutionCommandsMatrixToString());
30 System.out.println("End of movesequence.");
31 }
32 }
33 }
1 package listeners.solv;
2
3 import java.awt.event.*;
4
5 import model.CommandSeq;
6 import model.CommonObjects;
7 import model.CBTHSettingsList;
8 import solver.solverJS.algorithm.*;
9 import solver.solverJS.viewSolverJS.Cubie;
10
11 public class B_SOLV_MoveSeqToRobotListener implements ActionListener {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private Cubie cubie;
15
16 // Constructor:
17 public B_SOLV_MoveSeqToRobotListener(Cubie cubie) {
18 this.cubie = cubie;
19 }
20
21 // Instance methods:
22 public void actionPerformed(ActionEvent e) {
23
24 moveSeqToRobot();
25 }
26
27 public void moveSeqToRobot() {
28 /*
29 * The movesequence, returning from Cubie, is arranged from solved state to
30 * the problem-situation. (Rather a generating than a solving sequence) Our
31 * logic will invert the sequence.
32 */
33 MoveSequence moveSeq = cubie.getMoveSeqGenerator();
34
35 if (moveSeq != null) {
36
37 int len = moveSeq.getLength();
38 int[] moves = moveSeq.getMoves();
39 int[] amount = moveSeq.getAmount();
40
41 CommandSeq.setSolutionCommandsMatrix(moves, amount, len);
42
43 if (cbthsl.getBoolean("updateVisualizationWithRobot")) {
44 // Synchronize Cubie's viewer with the startpostion of the robot:
45 CommandSeq.setRobotPositionHor(0);
46 CommandSeq.setRobotPositionVer(0);
47 cubie.viewerBackToBegin();
48 }
49 /*
50 * The robot has it's queue of instructions, and can take these commands
51 * at its own pace.
52 */
53 CommandSeq.addNewCommand(7);
54 CommandSeq.solutionCommandsMatrixToQueue();
55 CommandSeq.addNewCommand(7);
56 }
57 }
58 }
1 package main;
2
3 import java.io.*;
4 import java.lang.reflect.Field;
5 import javax.swing.*;
6
7 import cbthFileChooser.FileIO;
8 import exceptions.NotAvailableException;
9 import model.*;
10 import view.TransparentSplashScreen;
11 import view.ViewCubeThesis;
12
13 public class Main {
14
15 /**
16 * The main()-method is the first method that is invoked, when a Javaprogram
17 * is started. One could refer to the 'Big Bang' in space.
18 */
19 public static void main(String[] args) {
20
21 long startTime = System.currentTimeMillis();
22
23 /*
24 * The idea is to spawn the splashscreen as early as possible when booting
25 * the program. Nevertheless, first the CBTHSettingsList is created, because
26 * it's needed for the SplashScreen's creation.
27 */
28 CBTHSettingsList cbthsl = new CBTHSettingsList();
29
30 // Create & spawn Splashscreen:
31 TransparentSplashScreen tss = new TransparentSplashScreen(cbthsl,
32 new String[] { "img", "icon", "Splashscreen.png" });
33 tss.setVisible(true);
34
35 // Update CBTHSettings with textFile (if available):
36 cbthsl.importCBTHSettingsFromTXT();
37
38 // Will alter between the OS/Java-LookAndFeel, nothing but the
39 // general appearance of visual-things changes:
40 try {
41 if (cbthsl.getBoolean("cbthGUITakesOSLook")) {
42 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
43 } else {
44 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
45 }
46 } catch (Exception exp) {
47 System.err.println("ERROR: Unexpected error has occurred during modifying "
48 + "the UI-Manager. Our apologies for the inconvenience.");
49 }
50
51 // While the SplashScreen's active, further creation of objects
52 // is continued:
53 new CommonObjects(cbthsl);
54 CBTHImagesList imgl = new CBTHImagesList();
55 CubeFacesList cfl = new CubeFacesList();
56 new FileIO(imgl, cfl);
57
58 // Extra locations to seek for OS-dependent/native libraries are
59 // added to the default path:
60 try {
61 addLibrary(whichOSDepLibrary(cbthsl));
62 } catch (IOException ioe) {
63
64 }
65
66 // The visual main window will be created, but not yet shown to the user:
133
134 for (int i = 0; i < paths.length; i++) {
135 if (s.equals(paths[i])) {
136 return;
137 }
138 }
139
140 String[] tmp = new String[paths.length + 1];
141 System.arraycopy(paths, 0, tmp, 0, paths.length);
142 tmp[paths.length] = s;
143 field.set(null, tmp);
144 System.setProperty("java.library.path",
145 System.getProperty("java.library.path") + File.pathSeparator + s);
146
147 } catch (IllegalAccessException iae) {
148 throw new IOException("ERROR: Failed to get permissions to set " + "library path");
149 } catch (NoSuchFieldException nsfe) {
150 throw new IOException("ERROR: Failed to get field handle to set " + "library path");
151 }
152 }
153
154 /**
155 * This method will generate the location of the OpenCV-resources, by checking
156 * for OS-type and Java-bitness.
157 */
158 public static String whichOSDepLibrary(CBTHSettingsList cbthsl) {
159 // Source: http://stackoverflow.com/questions/18269570/
160 // how-to-package-opencv-java-in-a-jar
161 // visited the 3/11/2015
162
163 String libraryPath = null;
164 String osName = System.getProperty("os.name");
165 System.out.print("Computer OS: " + osName + " Bitness of running Java-version: ");
166
167 if (osName.startsWith("Windows")) {
168 int bitness = Integer.parseInt(System.getProperty("sun.arch.data.model"));
169 System.out.println(bitness);
170
171 if (bitness == 32) {
172 // System.out.println("32 bit detected");
173 String[] filePathComp = { "ExtLib", "OpenCV", "Windows", "x86" };
174 libraryPath = cbthsl.makeSysIndepFilePath(filePathComp, 2);
175 } else if (bitness == 64) {
176 // System.out.println("64 bit detected");
177 String[] filePathComp = { "ExtLib", "OpenCV", "Windows", "x64" };
178 libraryPath = cbthsl.makeSysIndepFilePath(filePathComp, 2);
179 } else {
180 // System.out.println("Unknown bit detected - trying with 32 bit");
181 String[] filePathComp = { "ExtLib", "OpenCV", "Windows", "x86" };
182 libraryPath = cbthsl.makeSysIndepFilePath(filePathComp, 2);
183 }
184 } else if (osName.equals("Mac OS X")) {
185 System.err.println("ERROR: Probably CubeThesis is running on an "
186 + "Apple-computer. The library responsible for camera-connection "
187 + "was not provided. Howerver all other functionality is supported. "
188 + "Our apologies for the inconvience.");
189 } else {
190 System.err.println("ERROR: Probably CubeThesis is not running from "
191 + "a Windows-computer, camera-connection is therefore not guaranteed."
192 + " All other functionality is supported. Our apologies for the "
193 + "inconvenience.");
194 }
195 return libraryPath;
196 }
197 }
1 package model;
2
3 import connection.conWithCamera.CamTakePicture;
4 import connection.conWithRobot.CommunicationRobotThread;
5 import exceptions.*;
6 import listeners.cam.T_CAM_LiveStreamItemListener;
7 import listeners.solv.*;
8 import solver.solverJS.viewSolverJS.Cubie;
9 import solver.solverJS.algorithm.CubieSettings;
10 import view.ViewTabPanel4Aut;
11
12 public class AutomaticRoutine extends Thread {
13
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15 private static volatile boolean[] subtasksNecessary = { true, true, true, true };
16 /*
17 * These subtasks are: - [1] Read cube - [2] Build virtual cube - [3] Solve
18 * algorithmic - [4] Send solution
19 */
20 private static volatile boolean routineNotAborted;
21 private CommunicationRobotThread comRobot;
22 private T_CAM_LiveStreamItemListener camLSIL;
23 private Cubie cubie;
24 private B_SOLV_CubeToSolverListener cubeToSolver;
25 private CBTHImagesList imgl;
26 private CubeFacesList cfl;
27 private ViewTabPanel4Aut vtpa;
28
29 // Constructor:
30 public AutomaticRoutine(CBTHImagesList imgl, CubeFacesList cfl, ViewTabPanel4Aut vtpa) {
31
32 this.imgl = imgl;
33 this.cfl = cfl;
34 this.vtpa = vtpa;
35
36 routineNotAborted = true;
37 comRobot = CommonObjects.getCommunicatieRobot();
38 camLSIL = CommonObjects.getCamLSIL();
39 cubie = CommonObjects.getCubie();
40 cubeToSolver = CommonObjects.getCubeToSolver();
41 }
42
43 // Setters:
44 public static void setSubTaskNecessary(int index, boolean necessary) {
45 subtasksNecessary[index] = necessary;
46 }
47
48 public static void setRoutineNotAborted(boolean continueOrStop) {
49 routineNotAborted = continueOrStop;
50
51 System.out.println("Boolean \"routineNotAborted\" was updated: " + continueOrStop);
52 }
53
54 /**
55 * This run-method implements the whole automatic process. It is coupled to
56 * the most powerful button in CubeThesis.
57 */
58 public void run() {
59
60 long startTime = System.currentTimeMillis();
61
62 // Setting the icons off at the beginning:
63 for (int index = 0; index < subtasksNecessary.length; index++) {
64 boolean onOff = true;
65 if (subtasksNecessary[index])
66 onOff = false;
67 vtpa.setLogoOnOffVtspa(index, onOff);
68 }
69
70 /*
71 * Start (if not already started) the communicationServer that handles the
72 * communication with the robotcontroller.
73 */
74 if (!comRobot.getLinkRobotEstablished()) {
75
76 if (!comRobot.isAlive()) {
77 comRobot.start();
78 }
79 comRobot.initializeCommunicationRobot();
80 }
81
82 /*
83 * At this point the procedure waits till connection with the intended
84 * robot-device was put up. "routineNotAborted" is passed to let the user
85 * stop the waiting.
86 */
87 while (!comRobot.getLinkRobotEstablished() && routineNotAborted) {
88 try {
89 Thread.sleep(500);// 1000 milliseconds is one second.
90 } catch (InterruptedException ex) {
91 Thread.currentThread().interrupt();
92 }
93 }
94
95 // PHASE [1]: Read cube
96 if (subtasksNecessary[0] && routineNotAborted) {
97
98 // Connect to the Camera-device:
99 if (!camLSIL.getLinkCamEstablished()) {
100 camLSIL.connectToCapDevice();
101 // Wait 3 seconds to let the camera accomodate:
102 // Omitting this would yield for discoloured images.
103 try {
104 Thread.sleep(3000);
105 } catch (InterruptedException ex) {
106 Thread.currentThread().interrupt();
107 }
108 }
109
110 /*
111 * Not every CBTHImage is suited to perform solid color-estimation. If the
112 * lowest confidence- level of the obtained CubeFace is below the
113 * "thresholdColorEstimation", a new CBTHImage will be processed. When the
114 * six mainCubeFaces got a reliable CubeFace, this task is considered
115 * accomplished. When 15 attempts fail to provide a proper CubeFace, the
116 * process is also halted, since there's another issue somewhere and
117 * further continuation makes no sense.
118 */
119
120 // This array knows how to 'topple' the cube, during reading in.
121 int[] toppleArray = cbthsl.getIntArray("cubeReadingToppleArray");
122 CBTHImage img = null;
123 CubeFace cf = null;
124 int attemptsForColorEstimation = 0;
125 double thresholdColorEstimation = cbthsl.getDouble("thresholdColorEstimation");
126
127 /*
128 * mainCubeFaceRotationArray: knows how to rotate the respective CubeFace
129 * before assignment to some mainCubeFace: 1 = 90° clockwise, -1 = 90°
130 * counterclockwise, 2 = 180° (counter)clockwise.
131 */
132 int[] mainCubeFaceRotationArray = cbthsl.getIntArray("cubeReadingMCFRotationArray");
133
134 /*
135 * The first processed face will be assigned to the mainCubeFace-index at
136 * the first field of the array below etc. These are the indexes of the
137 * mainCubeFaces: {0=LeftFace, 1=UpperFace, 2=FrontFace, 3=RightFace,
138 * 4=DownFace, 5=BackFace}. So if index 0 from the mainCubeFaceAssignArray
139 * contains 3, then the actual CubeFace is assigned to "RightFace" of the
140 * cube.
141 */
142 int[] mainCubeFaceAssignArray = cbthsl.getIntArray("cubeReadingMCFAssignArray");
143
144 int rotationToApply = 0;
145 int whichMainCubeFace = 0;
146 int originalAmountSamplesPerFacelet = cbthsl.getInt("amountOfSamplesPerFacelet");
147
148 try {
149 int i = 0;
150 while (i < 6 && routineNotAborted) {
151 // After a 'topple'-move, the attemptsForColorEstimation
152 // is reset.
153 attemptsForColorEstimation = 0;
154 do {
155 img = CamTakePicture.takePicture();
156 // Mainsamples are even incremented,
157 // if a bad Color-estimation preceeded:
158 cbthsl.setInt("amountOfSamplesPerFacelet",
159 (originalAmountSamplesPerFacelet + attemptsForColorEstimation));
160 cf = ColorEstimation.colorRecognition(img);
161 attemptsForColorEstimation++;
162
163 } while (!cf.confidenceLevelSufficient(thresholdColorEstimation)
164 && attemptsForColorEstimation < 15 && routineNotAborted);
165
166 // Reset the amountOfSamples, for the next CubeFace:
167 cbthsl.setInt("amountOfSamplesPerFacelet", (originalAmountSamplesPerFacelet));
168
169 if (i < 5) {
170 // New topple instruction is added to the robot's queue:
171 CommandSeq.addNewCommand(toppleArray[i]);
172
173 try {
174 Thread.sleep(1000); // 1 sec should be sufficient
175 // for the robotIsBusy-field to become true.
176 } catch (InterruptedException ex) {
177 Thread.currentThread().interrupt();
178 }
179
180 while (comRobot.getRobotIsBusy()) {
181 try {
182 Thread.sleep(250);
183 // To lose a minimum of time, the robot is
184 // checked at 4Hz.
185 } catch (InterruptedException ex) {
186 Thread.currentThread().interrupt();
187 }
188 }
189 }
190
191 if (cf != null) {
192
193 imgl.addCBTHImage(img);
194
195 // The acquired CubeFace is assigned to the right
196 // mainCubeFace with the right orientation.
197
198 // Four times 90° implies no move => syntax "%" used as
265 /*
266 * What is taken into account solving the cube: 1) Experience learned that
267 * asking Cubie for another solve, mostly yields for a shorter solution.
268 * 2) The time spent to solve the algorithm is restricted by the user, by
269 * means of the CBTHSetting: timeToSolveAlgorithm [sec]. 3) If the pc is
270 * too occupied, hence not reaching a single solution in the restricted
271 * time, we allow Cubie to calculate longer only for the first solution.
272 * 4) Some solvers of Cubie sense when they can't come up with any shorter
273 * solution by reporting number '3'. Further iterations to spend the
274 * timeToSolveAlgorithm won't make sense. This has nothing to do with the
275 * mathematical existence of a shorter solution!
276 *
277 * NOTE: It's not very clever to increase the timeToSolve severely, since
278 * Cubie will probably spend way more time solving for a shorter sequence,
279 * than the robot would spend to perform some extra moves.
280 */
281
282 try {
283 int timeToSolveAlgorithm = cbthsl.getInt("timeToSolveAlgorithm");
284 cubeToSolver.cubeToSolver();
285
286 CubieSettings cubieSettings = cubie.getSettings();
287 long startTimeSolving = System.currentTimeMillis();
288 long endTimeSolving = startTimeSolving;
289
290 // No matter the "timeToSolveAlgorithm",
291 // the process awaits at least one solution for the cube.
292 cubie.solve();
293 do {
294 try {
295 Thread.sleep(250);
296 } catch (InterruptedException ex) {
297 Thread.currentThread().interrupt();
298 }
299 /* Check wheter the solver is still running. */
300 } while (cubieSettings.solving &&
301 /* cubieSettings.lastOutputSolver != 4 && */ routineNotAborted);
302
303 /*
304 * cubieSettings.lastOutputSolver: 0 = Initialisation done 1 = Solution
305 * found 2 = Solver aborted by user 3 = Solver finished, no solution
306 * found 4 = Solver is solving
307 */
308
309 // If routineNotAborted has not interfered,
310 // CubeThesis now disposes of a cube-solution if
311 // the cube was solvable.
312 endTimeSolving = System.currentTimeMillis();
313 int solveAttempt = 2;
314
315 while ((endTimeSolving - startTimeSolving) < timeToSolveAlgorithm * 1000
316 && routineNotAborted && cubieSettings.lastOutputSolver != 3) {
317 System.out.println("There is still time left considering the "
318 + "\"timeToSolveAlgorithm\"-setting: "
319 + "Possibility of other solutions is checked..." + " [Attempt "
320 + solveAttempt + "] Time spent/" + "maxTimeAllowed: "
321 + (System.currentTimeMillis() - startTimeSolving + "/"
322 + timeToSolveAlgorithm * 1000 + " [ms/ms]."));
323 cubie.solve();
324
325 do {
326 try {
327 Thread.sleep(250);
328 // At "4Hz" this thread wonders whether the solver
329 // has finished.
330 } catch (InterruptedException ex) {
331 Thread.currentThread().interrupt();
332 }
333 endTimeSolving = System.currentTimeMillis();
334 } while (cubie.getSettings().solving
335 && (endTimeSolving - startTimeSolving) < timeToSolveAlgorithm * 1000
336 && routineNotAborted);
337
338 endTimeSolving = System.currentTimeMillis();
339 solveAttempt++;
340 }
341
342 /*
343 * The sourcecode cubie.solve() in the if(){} below seems not
344 * appropriate at first sight. However, the .solve() method stops all
345 * Cubie's solvers if some solver was busy. In manual mode, you click
346 * the solvebutton to stop a solver at runtime, but then the solvebutton
347 * shows the text "stop". But the same solve() method is invoked
348 * internally to stop the solvers.
349 */
350 if (cubie.getSettings().solving) {
351 cubie.solve();
352 }
353 vtpa.setLogoOnOffVtspa(2, true);
354
355 } catch (NotAvailableException nae) {
356 System.err.println(nae);
357 }
358 }
359
360 // PHASE [4]: Send solution
361 if (subtasksNecessary[3] && routineNotAborted) {
362 vtpa.updateSendSolutionSubPanel();
363 CommonObjects.getMoveSeqToRobot().moveSeqToRobot();
364 }
365
366 while (CommandSeq.getQueueSize() > 0) {
367 try {
368 Thread.sleep(500);// At "2Hz" this thread wonders whether
369 // the robot has finished.
370 } catch (InterruptedException ex) {
371 Thread.currentThread().interrupt();
372 }
373 }
374 vtpa.setLogoOnOffVtspa(3, true);
375
376 long endTime = System.currentTimeMillis();
377
378 // Close camera link:
379 if (camLSIL.getLinkCamEstablished()) {
380 camLSIL.disconnectFromCapDevice();
381 }
382
383 AutomaticRoutine.routineNotAborted = false;
384 System.out.println("De tasks of the automatic routine have been completed in: "
385 + (endTime - startTime) + "[ms].");
386 }
387 }
1 package model;
2
3 import java.awt.image.*;
4 import java.io.*;
5 import javax.imageio.ImageIO;
6
7 import cbthFileChooser.Utils;
8
9 public class CBTHImage {
10
11 private static int iDGenerator = 0;
12 private int iD;
13 private String imgName;
14 private BufferedImage imgOriginal;
15 private BufferedImage imgCropped;
16 private int croppedXPos;
17 private int croppedYPos;
18 private int croppedWidth;
19 private int croppedHeight;
20
21 /**
22 * Default-constructor, mere a formality since this one is of no pratical use.
23 */
24 public CBTHImage() {
25
26 this.iD = iDGenerator;
27 this.imgName = null;
28 this.imgOriginal = null;
29 this.imgCropped = null;
30
31 this.croppedXPos = 0;
32 this.croppedYPos = 0;
33 this.croppedWidth = 0;
34 this.croppedHeight = 0;
35
36 iDGenerator++;
37 }
38
39 /**
40 * This constructor is called for to create a new CBTHImage from the capture
41 * device's output.
42 *
43 * @param imgName
44 * The name of the image
45 * @param original
46 * The image itself
47 */
48 public CBTHImage(String imgName, BufferedImage original) {
49
50 this.iD = iDGenerator;
51 this.imgName = imgName;
52
53 try {
54 this.imgOriginal = original;
55
56 // The three lines of source code below show how to create a
57 // "deep-copy" of a BufferedImage, equivalent to
58 // "=imgOriginal.getSubImage
59 // (0,0,original.getWidth(),original.getHeight())".
60 ColorModel cm = imgOriginal.getColorModel();
61 boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
62 WritableRaster raster = imgOriginal.copyData(null);
63
64 this.imgCropped = new BufferedImage(cm, raster, isAlphaPremultiplied, null);
65
66 this.croppedXPos = 0;
67 this.croppedYPos = 0;
68 this.croppedWidth = imgOriginal.getWidth();
69 this.croppedHeight = imgOriginal.getHeight();
70
71 } catch (Exception e) {
72 System.err.println("ERROR: During creation of a new CBTHImage, "
73 + "an unexpected error occurred. Our apologies for the " + "inconvenience.");
74 }
75 iDGenerator++;
76 }
77
78 /**
79 * When images are loaded into the session, either from a CubeThesisProject or
80 * via the "Browse img..."-button; this constructor is called for.
81 *
82 * @param original
83 * By preference the original image is loaded because it allows for
84 * adjusting the cropframe to get a bigger image.
85 * @param cropped
86 * If the original data is lost, than the cropped image can be loaded
87 * if available. Further cropping is only possible by means of
88 * shrinking the image.
89 * @param x
90 * x-co of the crop-frame
91 * @param y
92 * y-co of the crop-frame
93 * @param w
94 * width of the crop-frame
95 * @param h
96 * height of the crop-frame
97 */
98 public CBTHImage(File original, File cropped, int x, int y, int w, int h) {
99
100 this.iD = iDGenerator;
101 try {
102
103 if (original != null && original.exists()) {
104 this.imgName = omitFileExtension(original.getName());
105 this.imgOriginal = ImageIO.read(original);
106 } else {
107 // We suppose cropped != null & exists...
108 this.imgName = omitFileExtension(cropped.getName());
109 this.imgOriginal = ImageIO.read(cropped);
110
111 // If no original file was supplied, original crop-parameters
112 // make no sense anymore.
113 x = 0;
114 y = 0;
115 w = imgOriginal.getWidth();
116 h = imgOriginal.getHeight();
117 }
118
119 this.croppedXPos = x;
120 this.croppedYPos = y;
121
122 this.croppedWidth = w;
123 this.croppedHeight = h;
124
125 this.imgCropped = this.imgOriginal.getSubimage(croppedXPos, croppedYPos,
126 croppedWidth, croppedHeight);
127
128 } catch (IOException ioe) {
129 System.err.println("ERROR: During creation "
130 + "of CBTHImage, some IOException occurred. Our apologies "
131 + "for the inconvenience.");
132 }
133
134 iDGenerator++;
135 }
136
137 // Getters:
138 public int getCroppedXPos() {
139 return croppedXPos;
140 }
141
142 public int getCroppedYPos() {
143 return croppedYPos;
144 }
145
146 public int getCroppedHeight() {
147 return croppedHeight;
148 }
149
150 public int getCroppedWidth() {
151 return croppedWidth;
152 }
153
154 public int getHeightOriginal() {
155 return imgOriginal.getHeight();
156 }
157
158 public int getID() {
159 return iD;
160 }
161
162 public static int getIDGenerator() {
163 return iDGenerator;
164 }
165
166 public BufferedImage getImgCropped() {
167 return imgCropped;
168 }
169
170 public BufferedImage getImgOriginal() {
171 return imgOriginal;
172 }
173
174 public String getName() {
175 return imgName;
176 }
177
178 public int getWidthOriginal() {
179 return imgOriginal.getWidth();
180 }
181
182 // Setter:
183 /** Will update the crop-parameters. */
184 public void setNewCropped(int a, int b, int c, int d) {
185
186 croppedXPos = a;
187 croppedYPos = b;
188 croppedWidth = c;
189 croppedHeight = d;
190
191 if ((a + c) <= imgOriginal.getWidth() && (b + d) <= imgOriginal.getWidth()) {
192 imgCropped = imgOriginal.getSubimage(a, b, c, d);
193 }
194 }
195
196 // Instance methods:
197 /**
198 * Saves the physical original/cropped-file of a CBTHImage.
199 *
200 * @param origLocation
201 * The location at which the original image is to be saved.
202 * @param croppedLocation
203 * The location at which the cropped image is to be saved.
204 * @throws IOException
205 */
206 public void cbthImageToImageFile(String origLocation, String croppedLocation)
207 throws IOException {
208
209 String fileName = this.getName() + "." + Utils.jpg;
210
211 ImageIO.write(this.imgOriginal, Utils.jpg, new File(origLocation + fileName));
212 ImageIO.write(this.imgCropped, Utils.jpg, new File(croppedLocation + fileName));
213 System.out.println("CBTHImage: " + this.getName() + " was properly saved.");
214 }
215
216 /**
217 * Saves a CBTHImage to the saveFile.
218 *
219 * @throws IOException
220 */
221 public void cbthImageToSaveFile(DataOutputStream dos, String folderImgOrig,
222 String folderImgCropped) throws IOException {
223
224 String nameImg = "null";
225 if (getImgOriginal() != null) {
226 nameImg = getName();
227 }
228 dos.writeUTF(folderImgOrig + nameImg + "." + Utils.jpg);
229 nameImg = "null";
230
231 if (getImgCropped() != null) {
232 nameImg = getName();
233 }
234 dos.writeUTF(folderImgCropped + nameImg + "." + Utils.jpg);
235 nameImg = "null";
236
237 dos.writeInt(getCroppedXPos());
238 dos.writeInt(getCroppedYPos());
239 dos.writeInt(getCroppedWidth());
240 dos.writeInt(getCroppedHeight());
241 }
242
243 @Override
244 /** Gives a textual representation of a CBTHImage */
245 public String toString() {
246
247 StringBuffer hulp = new StringBuffer();
248 hulp.append(iD + ". ");
249 hulp.append(this.imgName);
250
251 return hulp.toString();
252 }
253
254 // Static method:
255 public static String omitFileExtension(String s) {
256
257 int indexOfDot = s.indexOf(".");
258 return s.substring(0, indexOfDot);
259 }
260 }
1 package model;
2
3 import java.io.*;
4 import java.util.*;
5
6 import exceptions.NumberNotFoundException;
7 import model.CBTHImage;
8
9 public class CBTHImagesList extends Observable {
10
11 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
12 private ArrayList<CBTHImage> cbthImagesList;
13 private static String fS = cbthsl.getString("fileSeparator");
14
15 // Constructor:
16 public CBTHImagesList() {
17
18 cbthImagesList = new ArrayList<CBTHImage>();
19 }
20
21 // Getters:
22 public CBTHImage getCBTHImage(int i) {
23 return cbthImagesList.get(i);
24 }
25
26 public List<CBTHImage> getCBTHImages() {
27 return cbthImagesList;
28 }
29
30 public int getSize() {
31 return cbthImagesList.size();
32 }
33
34 // Instance methods:
35 public void addCBTHImage(CBTHImage img) {
36
37 if (img != null) {
38 cbthImagesList.add(img);
39 System.out.println(
40 "Image \"" + img.getName() + "\" was succesfully added to the cbthImagesList.");
41 updateCBTHImages();
42 }
43 }
44
45 public void cbthImagesListToImageFiles() throws IOException {
46 // If the saveToFolders would not exist anymore, they're recreated.
47 String origLocation = cbthsl.makeSysIndepFilePath(new String[] { "ImgOriginal", "" },
48 3);
49 String croppedLocation = cbthsl
50 .makeSysIndepFilePath(new String[] { "ImgCropped", "" }, 3);
51
52 new File(origLocation).mkdirs();
53 new File(croppedLocation).mkdirs();
54
55 for (CBTHImage img : cbthImagesList) {
56 img.cbthImageToImageFile(origLocation, croppedLocation);
57 }
58 }
59
60 public void cbthImagesListToSaveFile(DataOutputStream dos) throws IOException {
61
62 /*
63 * NOTE: To exchange CubeThesisFiles between computers of different OS,
64 * relative references to images may not be saved by use of a system
65 * dependent file-separator (Windows: '\'). By means of a workaround,
66 * file-separators are saved as a textual representation: "/FILESEPARATOR/".
67 */
68
69 String fileSeparatorToText = cbthsl.getString("fileSeparatorToText");
70 String folderImgOrig = fileSeparatorToText + "ImgOriginal" + fileSeparatorToText;
71 String folderImgCropped = fileSeparatorToText + "ImgCropped" + fileSeparatorToText;
72
73 for (CBTHImage img : cbthImagesList) {
74 // "For each image in cbthImagesList..."
75 img.cbthImageToSaveFile(dos, folderImgOrig, folderImgCropped);
76 }
77 }
78
79 public void deleteAllCBTHImages() {
80
81 cbthImagesList.clear();
82 updateCBTHImages();
83 }
84
85 public void deleteCBTHImage(int iD) throws NumberNotFoundException {
86
87 cbthImagesList.remove(searchImageOnID(iD));
88 updateCBTHImages();
89 }
90
91 public void cbthImagesListFromSaveFile(DataInputStream dis) throws IOException {
92
93 int amountOfImages = dis.readInt();
94 String fileNameOrig = null;
95 String fileNameCropped = null;
96 File fileOrig = null;
97 File fileCropped = null;
98 File currentProject = cbthsl.getCurrentProject();
99 CBTHImage img = null;
100
101 for (int j = 0; j < amountOfImages; j++) {
102 fileNameOrig = translateFileSeparator(dis.readUTF());
103 fileNameCropped = translateFileSeparator(dis.readUTF());
104
105 fileOrig = new File(currentProject + fileNameOrig);
106 fileCropped = new File(currentProject + fileNameCropped);
107
108 System.out.println("FileIO: import image from path " + fileOrig);
109 int x = -1, y = -1, w = -1, h = -1;
110
111 try {
112 x = dis.readInt();
113 y = dis.readInt();
114 w = dis.readInt();
115 h = dis.readInt();
116 } catch (Exception exc) {
117 System.err.println("ERROR: " + exc);
118 }
119
120 img = new CBTHImage(fileOrig, fileCropped, x, y, w, h);
121
122 // Reset temporary variables for next loop iteration.
123 fileNameOrig = null;
124 fileNameCropped = null;
125 fileOrig = null;
126 fileCropped = null;
127 if (img != null) {
128 addCBTHImage(img);
129 System.out.println("CBTHImage: " + img.getName() + " succesfully imported.");
130 }
131 img = null;
132 }
133 }
134
135 public int searchImageOnID(int iD) throws NumberNotFoundException {
136
137 CBTHImage cbthImage = null;
138 boolean alreadyFound = false;
139 int c = 0, s = cbthImagesList.size();
140
141 while (c < s && !alreadyFound) {
142 cbthImage = getCBTHImage(c);
143 if (iD == cbthImage.getID()) {
144 alreadyFound = true;
145 } else {
146 c++;
147 }
148 }
149 if (!alreadyFound) {
150 throw new NumberNotFoundException("the CBTHImagesList");
151 }
152 return c;
153 }
154
155 /**
156 * This method is part of the Observer-Observable technique. It will trigger
157 * its Observers.
158 */
159 public void updateCBTHImages() {
160 // At this point the view is refreshed upon changes in the model
161 // (CBTHImagesList).
162 setChanged();
163 notifyObservers();
164 }
165
166 // Static method:
167 /**
168 * This method will translate a path with the OS-independent file-separator to
169 * a path with a OS-dependent one to practically use the filepath.
170 *
171 * @param path
172 * The path that needs translation.
173 * @return The path with the altered file-separators.
174 */
175 public static String translateFileSeparator(String path) {
176
177 StringBuffer sb = new StringBuffer();
178 String fileSepToText = cbthsl.getString("fileSeparatorToText");
179 int runningIndex = 0, indexfS = path.indexOf(fileSepToText);
180
181 while (indexfS != -1) {
182 sb.append(path.substring(runningIndex, indexfS));
183 sb.append(fS);
184 runningIndex = indexfS + fileSepToText.length();
185 indexfS = path.indexOf(fileSepToText, runningIndex + 1);
186 }
187
188 sb.append(path.substring(runningIndex, path.length()));
189
190 return sb.toString();
191 }
192 }
1 package model;
2
3 import java.util.Observable;
4
5 import view.VisualCBTHSetting;
6
7 public class CBTHSetting extends Observable {
8
9 public static int iDGenerator = 0;
10 private int iD;
11 private String name;
12 private String labelText;
13 private String type;// int, float, double short, long, boolean,
14 // String, intArray, doubleArray, floatArray...
15 private String value;
16 private boolean editable;
17 private String info;
18
19 // Constructors:
20 public CBTHSetting() {
21
22 this.iD = iDGenerator;
23 this.name = null;
24 this.labelText = null;
25 this.type = "String";
26 this.value = "null";
27 this.editable = false;
28 this.info = null;
29
30 iDGenerator++;
31 }
32
33 public CBTHSetting(String name, String labelText, String type, String value,
34 boolean editable, String info) {
35
36 this.iD = iDGenerator;
37 this.name = name;
38 this.labelText = labelText;
39 this.type = type;
40 this.value = value;
41 this.editable = editable;
42 this.info = info;
43
44 iDGenerator++;
45 }
46
47 // Getters:
48 public boolean getEditable() {
49 return editable;
50 }
51
52 public int getiD() {
53 return iD;
54 }
55
56 public String getInfo() {
57 return info;
58 }
59
60 public String getLabelText() {
61 return labelText;
62 }
63
64 public String getName() {
65 return name;
66 }
67
68 public String getType() {
69 return type;
70 }
71
72 public String getValue() {
73 return value;
74 }
75
76 // Setters:
77 /*
78 * Several attribute setters are made private, to make no extern class can
79 * directly call them. The only way to externally adapt settings is by calling
80 * for .setAll() with the advantage of only updating the visualisationCBTHS
81 * once.
82 */
83 public void setAll(String name, String labelText, String type, String value,
84 String info) {
85
86 if (editable) {
87
88 // When the null-object is passed, these fields remain unchanged.
89 setName(name);
90 setLabelText(labelText);
91 setType(type);
92 setValue(value);
93 setInfo(info);
94
95 // Edit possibly several attributes at a time and update Observers
96 // just once!
97 updateVisualCBTHSetting();
98 }
99 }
100
101 private void setInfo(String info) {
102 if (info != null) {
103 this.info = info;
104 }
105 }
106
107 private void setLabelText(String labelText) {
108 if (labelText != null) {
109 this.labelText = labelText;
110 }
111 }
112
113 private void setName(String name) {
114 if (name != null) {
115 this.name = name;
116 }
117 }
118
119 private void setType(String type) {
120 if (type != null) {
121 this.type = type;
122 }
123 }
124
125 private void setValue(String value) {
126 if (value != null) {
127 this.value = value;
128 }
129 }
130
131 // Instance methods:
132 public boolean containsFragment(String textFragment) {
1 package model;
2
3 import java.awt.Dimension;
4 import java.awt.event.ActionListener;
5 import java.awt.Font;
6 import java.io.*;
7 import java.util.*;
8 import javax.swing.*;
9 import javax.swing.border.BevelBorder;
10
11 import comparators.*;
12 import exceptions.*;
13
14 public class CBTHSettingsList extends Observable {
15
16 private ArrayList<CBTHSetting> cbthSettingsList;
17 /* Another ArrayList for easy editing purposes: */
18 private ArrayList<CBTHSetting> cbthSettingSelection;
19 private String currentSettingsFilter;
20
21 // Tags to interact with CBTHSettingsFile
22 private static final String commentTag = "[Comment]";
23 private static final String settingTag = "[Setting]";
24
25 // Parameter that should be editable by program, but not by user.
26 private static CBTHSetting currentProject;
27
28 // Colordefinitions:
29 private static final String COLORRED = "Red";
30 private static final String COLORBLUE = "Blue";
31 private static final String COLORYELLOW = "Yellow";
32 private static final String COLORORANGE = "Orange";
33 private static final String COLORGREEN = "Green";
34 private static final String COLORWHITE = "White";
35 private static final String COLORNONE = "None";
36 private static final String[] CUBECOLORS = { COLORRED, COLORBLUE, COLORYELLOW,
37 COLORORANGE, COLORGREEN, COLORWHITE, COLORNONE };
38
39 // CBTHSettings, that have a local, easy addressable copy for internal use:
40 private static Font guiFont1Local;
41 private static Font guiFont2Local;
42 private static Font guiFont3Local;
43
44 // Constructor:
45 public CBTHSettingsList() {
46
47 // ArrayList gets initialized.
48 cbthSettingsList = new ArrayList<CBTHSetting>();
49 cbthSettingSelection = new ArrayList<CBTHSetting>();
50 currentSettingsFilter = null;
51
52 // For automatically creating sync-ing JTextfields... from
53 // CBTHSettings below, Fonts should be created first,
54 // since they're already applied at that point.
55 cbthSettingsList.add(
56 new CBTHSetting("guiFont1", "GUI-Font 1:", "Font", "Century Gothic, 0, 12", true,
57 "Font used for most buttons and labels in GUI. "
58 + "Second parameter: 0 = Plain text, 1 = Bold text, "
59 + "2 = Italic text."));
60 cbthSettingsList
61 .add(new CBTHSetting("guiFont2", "GUI-Font 2:", "Font", "Consolas, 0, 12", true,
62 "Font used for console and textfields in GUI. "
63 + "Second parameter: 0 = Plain text, 1 = Bold text, "
64 + "2 = Italic text."));
65 cbthSettingsList
66 .add(new CBTHSetting("guiFont3", "GUI-Font 3:", "Font", "Stencil, 0, 12", true,
199
200 // Settings that concern algorithmic solving process.
201 cbthSettingsList.add(new CBTHSetting("updateVisualizationWithRobot",
202 "Update visualization w robot:", "boolean", "true", true,
203 "Turn this \"true\" to make the algorimthmic solver's "
204 + "visualization run synchronously with the robot executing "
205 + "the tasks."));
206 cbthSettingsList
207 .add(new CBTHSetting("timeToSolveAlgorithm", "Time to solve algorithm:", "int",
208 "5", true, "Applying a timelimit to spend on solving the algorithm, "
209 + "in automatic mode."));
210 cbthSettingsList.add(new CBTHSetting("ipAddressRobot", "IP-Address robot:", "String",
211 "0.0.0.0", true, "Specify the cooperating robot by IP-Address "
212 + "(only for checking purposes) (use (hexa)decimal " + "notation)."));
213 cbthSettingsList
214 .add(new CBTHSetting("portNmbrServerSocket", "Port Serversocket Robotcom.", "int",
215 "8000", true, "This is the portnumber the serversocket hosted on this "
216 + "pc will use in communication witch the robotcontroller."));
217 cbthSettingsList.add(new CBTHSetting("noValidCommand", "Not valid command:", "int",
218 "0", true, "Robotcommand that is agreed not to be a " + "valid instruction."));
219
220 // Exceptions that are editable, but don't need to be added
221 // to the settingsList.
222 currentProject = new CBTHSetting("currentProject", "Current project:", "String",
223 new File(makeSysIndepFilePath(
224 new String[] { "CubeThesisProjects", "DefaultProject" }, 2))
225 .getAbsolutePath(),
226 true, "Restores the \"DefaultProject\" if not available.");
227 getCurrentProject().mkdirs();
228
229 // Make to start with, all CBTHSettings are selected.
230 cbthSettingSelection.addAll(cbthSettingsList);
231 }
232
233 // Getters:
234 public boolean getBoolean(String settingName) {
235
236 boolean value = false;
237 try {
238 CBTHSetting cbths = null;
239 cbths = seekCBTHSetting(settingName);
240 value = Boolean.parseBoolean(cbths.getValue());
241
242 } catch (NoSuchSettingFoundException nssfe) {
243 System.err.println(nssfe);
244 nssfe.printStackTrace();
245 }
246 return value;
247 }
248
249 public ArrayList<CBTHSetting> getCBTHSettingSelection() {
250 return cbthSettingSelection;
251 }
252
253 public String[] getCubeColors() {
254 return CUBECOLORS;
255 }
256
257 public File getCurrentProject() {
258 return new File(currentProject.getValue());
259 }
260
261 public double getDouble(String settingName) {
262
263 double value = 0.0;
264 try {
331 Integer.parseInt(stringComponents.get(2)));
332 // Second argument: 0 = Plain text, 1 = Bold text and 2 =
333 // Italic text.
334
335 } catch (NoSuchSettingFoundException nssfe) {
336 System.err.println(nssfe);
337 nssfe.printStackTrace();
338 }
339 return font;
340 }
341
342 public int getInt(String settingName) {
343
344 int value = 0;
345 try {
346 CBTHSetting cbths = null;
347 cbths = seekCBTHSetting(settingName);
348
349 try {
350 value = Integer.parseInt(cbths.getValue());
351 } catch (NumberFormatException nfe) {
352 System.err.println("ERROR: Value stored in CBTHSetting \"" + cbths.getName()
353 + "\" can't be resolved as [int].");
354 }
355
356 } catch (NoSuchSettingFoundException nssfe) {
357 System.err.println(nssfe);
358 nssfe.printStackTrace();
359 }
360 return value;
361 }
362
363 public int[] getIntArray(String settingName) {
364
365 int[] values = null;
366 try {
367 CBTHSetting cbths = null;
368 cbths = seekCBTHSetting(settingName);
369 ArrayList<String> stringComponents = splitStringByCommas(cbths.getValue(), 1, 1);
370 values = new int[stringComponents.size()];
371
372 for (int i = 0; i < stringComponents.size(); i++) {
373 values[i] = Integer.parseInt(stringComponents.get(i));
374 }
375
376 } catch (NoSuchSettingFoundException nssfe) {
377 System.err.println(nssfe);
378 nssfe.printStackTrace();
379 }
380 return values;
381 }
382
383 public String getString(String settingName) {
384
385 String value = "- No String stored -";
386 try {
387 CBTHSetting cbths = null;
388 cbths = seekCBTHSetting(settingName);
389 value = cbths.getValue();
390 } catch (NoSuchSettingFoundException nssfe) {
391 System.err.println(nssfe);
392 nssfe.printStackTrace();
393 }
394 return value;
395 }
396
397 // Setters.
398 public void setBoolean(String settingName, boolean value) {
399
400 String valueToString = "false";
401 try {
402 CBTHSetting cbths = null;
403 cbths = seekCBTHSetting(settingName);
404
405 if (!cbths.getType().equals("boolean")) {
406 throw new NoMatchingSettingTypeException(settingName, cbths.getType(), "boolean");
407 }
408
409 if (value) {
410 valueToString = "true";
411 }
412
413 cbths.setAll(null, null, null, valueToString, null);
414
415 } catch (NoSuchSettingFoundException nssfe) {
416 System.err.println(nssfe);
417 } catch (NoMatchingSettingTypeException nmste) {
418 System.err.println(nmste);
419 }
420 }
421
422 public void setCurrentProject(File f) {
423 currentProject.setAll(null, null, null, f.getAbsolutePath(), null);
424 }
425
426 public void setDouble(String settingName, double value) {
427 try {
428 CBTHSetting cbths = null;
429 cbths = seekCBTHSetting(settingName);
430
431 if (!cbths.getType().equals("double")) {
432 throw new NoMatchingSettingTypeException(settingName, cbths.getType(), "double");
433 }
434
435 cbths.setAll(null, null, null, value + "", null);
436
437 } catch (NoSuchSettingFoundException nssfe) {
438 System.err.println(nssfe);
439 } catch (NoMatchingSettingTypeException nmste) {
440 System.err.println(nmste);
441 }
442 }
443
444 public void setDoubleArray(String settingName, double[] values) {
445
446 try {
447 CBTHSetting cbths = null;
448 cbths = seekCBTHSetting(settingName);
449
450 if (!cbths.getType().equals("doubleArray")) {
451 throw new NoMatchingSettingTypeException(settingName, cbths.getType(),
452 "doubleArray");
453 }
454
455 StringBuffer sb = new StringBuffer();
456 int i;
457
458 sb.append("{");
459 for (i = 0; i < values.length - 1; i++) {
460 sb.append(values[i] + ", ");
461 }
462
661
662 public JToggleButton createJToggleButton(String knopTekst, String tooltip,
663 boolean reedsGeactiveerd) {
664 JToggleButton tb = new JToggleButton(knopTekst, reedsGeactiveerd);
665 tb.setToolTipText(tooltip);
666 tb.setFont(guiFont1Local);
667 return tb;
668 }
669
670 public void exportCBTHSettingsToTXT() {
671
672 FileWriter fw = null;
673 PrintWriter pw = null;
674
675 try {
676
677 String[] filepadComp = { "CBTHSettingsFile.txt" };
678 String pad = makeSysIndepFilePath(filepadComp, 2);
679 fw = new FileWriter(pad, false);
680 pw = new PrintWriter(fw);
681
682 pw.println(commentTag + "[This CBTHSettingsfile will be read by "
683 + "CubeThesis to initialize its settings. " + "User can make modifications.]");
684 pw.println();
685 pw.println(commentTag + "[Rule No 1: ][Modifications can be made, "
686 + "though not at runtime.]");
687 pw.println(commentTag + "[Rule No 2: ][All the data is to be wrapped "
688 + "in square brackets.]");
689 pw.println(commentTag + "[Rule No 3: ][ArrayTypes are additionally "
690 + "wrapped in curly brackets \"{\" & \"}\". Items are "
691 + "enumerated by comma's \",\"]");
692 pw.println(commentTag + "[Rule No 3: ][Not all possible settings "
693 + "should be listed below, if one agrees with the "
694 + "default he can simply omit that setting.]");
695 pw.println(commentTag + "[Rule No 4: ][The order in which the "
696 + "settings below are listed, doesn't matter.]");
697 pw.println(commentTag + "[Rule No 5: ][Within each record, "
698 + "(horizontal) order of tags should be respected.]");
699 pw.println(commentTag + "[Rule No 6: ][If some record isn't blanco, "
700 + "then the first tag should either be \"" + commentTag + "\" " + "or \""
701 + settingTag + "\".]");
702 pw.println(commentTag + "[Rule No 7: ][Without this file, "
703 + "CubeThesis recovers its factory settings. "
704 + "File will be auto-regenerated.]");
705 pw.println(commentTag + "[Rule No 8: ][Setting-name and -type "
706 + "are case sensitive, if they don't match an existing "
707 + "CBTHSetting, a new Setting will be created.]");
708 pw.println(commentTag + "[Structure: ][Setting][name][LabelText]"
709 + "[type][Value] \"some spaces added for readability\" " + "[Info]");
710 pw.println(commentTag + "[Available types: ][int, double, float,"
711 + " boolean, String, Font, intArray, doubleArray]");
712 pw.println();
713 pw.println();
714
715 CBTHSetting cbths = null;
716
717 for (int i = 0; i < cbthSettingsList.size(); i++) {
718 cbths = cbthSettingsList.get(i);
719 if (cbths.getEditable()) {
720 pw.print(settingTag);
721 pw.println(cbths.exportCBTHSetting());
722 }
723 }
724
725 pw.flush();
726
793
794 CBTHSetting cbths = null;
795
796 if (stringComponents.size() > 2) {
797 // Three strings detected would already mean a name,
798 // a type and a value.
799 // Read setting might already exist.
800 try {
801 cbths = seekCBTHSetting(stringComponents.get(0));
802
803 if (cbths.getEditable()) {
804 if (!cbths.getType().equals(stringComponents.get(2))) {
805 throw new NoMatchingSettingTypeException(cbths.getName(),
806 stringComponents.get(2), cbths.getType());
807 }
808
809 if (stringComponents.size() > 4) {
810 cbths.setAll(null, stringComponents.get(1), null, stringComponents.get(3),
811 stringComponents.get(4));
812 } else {
813 // WorkAround to make info-tag not required from
814 // the list.
815 cbths.setAll(null, stringComponents.get(1), null, stringComponents.get(3),
816 null);
817 }
818 }
819 } catch (NoMatchingSettingTypeException nmste) {
820 System.err.println(nmste);
821 } catch (NoSuchSettingFoundException nssfe) {
822 // Read setting might be a new setting, so a new
823 // CBTHSetting will be created.
824 cbthSettingsList.add(new CBTHSetting(stringComponents.get(0),
825 stringComponents.get(1), stringComponents.get(2), stringComponents.get(3),
826 true, stringComponents.get(4)));
827 }
828 }
829 }
830
831 public void importCBTHSettingsFromTXT() {
832
833 FileReader fr = null;
834 BufferedReader br = null;
835
836 try {
837 File cbthSettingsFile = new File(
838 makeSysIndepFilePath(new String[] { "CBTHSettingsFile.txt" }, 2));
839
840 if (!cbthSettingsFile.exists()) {
841 throw new NotAvailableException("CBTHSettingsFile.txt",
842 "Default settings will be loaded.");
843 }
844
845 fr = new FileReader(cbthSettingsFile);
846 br = new BufferedReader(fr);
847
848 String readLine = "";
849
850 while ((readLine = br.readLine()) != null) {
851
852 if (readLine.startsWith(settingTag)) {
853 importCBTHSettingFromLine(
854 readLine.substring(settingTag.length(), readLine.length()), "[", "]");
855 }
856 }
857
858 } catch (IOException ioe) {
859 System.err.println(ioe);
860 } catch (NotAvailableException nae) {
861 System.err.println(nae);
862 }
863
864 finally {
865 if (br != null) {
866 try {
867 br.close();
868 } catch (IOException ioe) {
869 System.err.println("ERROR: An IO-Exception occurred "
870 + "during attempt to close the BufferedReader "
871 + "of the CBTHSettingsFile. Our apologies for the " + "inconvenience.");
872 }
873 } else {
874 if (fr != null) {
875 try {
876 fr.close();
877 } catch (IOException ioe) {
878 System.err.println("ERROR: An IO-Exception occurred during attempt to "
879 + "close the FileReader of the CBTHSettingsFile."
880 + " Our apologies for the inconvenience.");
881 }
882 }
883 }
884 }
885 }
886
887 public String makeSysIndepFilePath(String[] pathStructure, int whatPrefix) {
888
889 StringBuffer sb = new StringBuffer();
890 String fS = getString("fileSeparator");
891
892 switch (whatPrefix) {
893 case 0:
894 ;
895 /* Nothing is added. */ break;
896 case 1:
897 sb.append(fS);
898 break;
899 case 2:
900 sb.append(getString("basicRelativePath"));
901 sb.append(fS);
902 break;
903 case 3:
904 sb.append(getCurrentProject());
905 sb.append(fS);
906 break;
907 default:
908 break;
909 }
910
911 // Adding the remaining pathstructure
912 int s;
913 for (s = 0; s < pathStructure.length - 1; s++) {
914 sb.append(pathStructure[s]);
915 sb.append(fS);
916 }
917
918 // Na het laatste item moet geen file separator meer komen, het
919 // laatste item kan immers een bestandsnaam zijn.
920 sb.append(pathStructure[s]);
921
922 return sb.toString();
923 }
924
1057 }
1058
1059 public String translateColorsIntToString(int k) {
1060
1061 if (k > -1 && k < 7) {
1062 return CUBECOLORS[k];
1063 } else {
1064 return CUBECOLORS[6];
1065 }
1066 }
1067
1068 public int translateColorsStringToInt(String str) {
1069
1070 switch (str) {
1071 case COLORRED:
1072 return 0;
1073 case COLORBLUE:
1074 return 1;
1075 case COLORYELLOW:
1076 return 2;
1077 case COLORORANGE:
1078 return 3;
1079 case COLORGREEN:
1080 return 4;
1081 case COLORWHITE:
1082 return 5;
1083 default:
1084 return 6;
1085 }
1086 }
1087
1088 /**
1089 * This method is part of the Observer-Observable technique. It will trigger
1090 * its Observers.
1091 */
1092 public void updateVisualCBTHSList() {
1093 setChanged();
1094 notifyObservers();
1095 }
1096
1097 // Static method:
1098 public static String omitSpaces(String text) {
1099
1100 String trimmed = text;
1101
1102 // Omit the spaces at the start.
1103 while (trimmed.startsWith(" ")) {
1104 trimmed = trimmed.substring(1, trimmed.length());
1105 }
1106
1107 // Omit the spaces at the end.
1108 while (trimmed.endsWith(" ")) {
1109 trimmed = trimmed.substring(0, trimmed.length() - 1);
1110 }
1111 return trimmed;
1112 }
1113 }
1 package model;
2
3 import java.awt.Color;
4 import java.awt.image.BufferedImage;
5 import java.util.Random;
6
7 import javax.swing.ImageIcon;
8 import javax.swing.JLabel;
9 import javax.swing.JOptionPane;
10
11 public class ColorEstimation {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private static BufferedImage[][] cells;
15 private static Random rand;
16
17 private static int minBrightWhite;
18 private static int maxSaturWhite;
19 private static int maxBrightBlack;
20 private static int distinctionRedOrange;
21 private static int distinctionOrangeYellow;
22 private static int distinctionYellowGreen;
23 private static int distinctionGreenBlue;
24 private static int distinctionBluePurple;
25 private static int distinctionPurpleRed;
26
27 private static boolean extensiveSampleOutprint;
28 private static int amountOfSamplesPerFacelet;
29 private static int amountOfSampleAveraging;
30
31 // Static methods:
32 public static CubeFace colorRecognition(CBTHImage currentCBTHImage) {
33
34 CubeFace cubeFace = null;
35 cells = new BufferedImage[3][3];
36 rand = new Random();
37
38 extensiveSampleOutprint = cbthsl.getBoolean("extensiveSampleOutprint");
39 amountOfSamplesPerFacelet = cbthsl.getInt("amountOfSamplesPerFacelet");
40 amountOfSampleAveraging = cbthsl.getInt("amountOfSampleAveraging");
41
42 BufferedImage cropped = currentCBTHImage.getImgCropped();
43
44 /*
45 * Color-data is retrieved once at the beginning of the procedure and reused
46 * for every facelet of the face.
47 */
48 minBrightWhite = cbthsl.getInt("minBrightnessWhite");
49 maxSaturWhite = cbthsl.getInt("maxSaturationWhite");
50 maxBrightBlack = cbthsl.getInt("maxBrightnessBlack");
51 distinctionRedOrange = cbthsl.getInt("distinctionRedOrange");
52 distinctionOrangeYellow = cbthsl.getInt("distinctionOrangeYellow");
53 distinctionYellowGreen = cbthsl.getInt("distinctionYellowGreen");
54 distinctionGreenBlue = cbthsl.getInt("distinctionGreenBlue");
55 distinctionBluePurple = cbthsl.getInt("distinctionBluePurple");
56 distinctionPurpleRed = cbthsl.getInt("distinctionPurpleRed");
57
58 int cropheightparam = cropped.getHeight() / 3,
59 cropwidthparam = cropped.getWidth() / 3,
60 averageHalfWidthFacelet = (cropwidthparam) / 2,
61 averageHalfHeightFacelet = (cropheightparam) / 2, centerPointX = 0,
62 centerPointY = 0;
63 double factor = .65;
64 int rgb = 0;
65 String str1 = null, str2 = null, str3 = null;
66
265 * are the blue value, 8-15 the green, and 16-23 the red, so each color
266 * occupies 8 bits. A .png imageformat supports an alpha channel, these bits
267 * occupy the bits 24-31.
268 *
269 * In what follows the last hexadecimal number (0xFF) represents 255; '&' =
270 * bitwise operation that retains the bits that occur at the same locations
271 * in both numbers; '>>' means the bits are shifted to the right with the
272 * specified amount places.
273 */
274
275 rgbArray[0] = (rgb >> 16) & 0xFF;// RED Channel: 16 places shifting.
276 rgbArray[1] = (rgb >> 8) & 0xFF;// Green Channel: 8 places shifting.
277 rgbArray[2] = (rgb) & 0xFF;// Blue Channel: no shifting.
278
279 /*
280 * NOTE: Calculating an average of 'packed' rgb-numbers is pointless. And:
281 * Some colors have more appearances: int rgb=-98830 & int rgb= 16678386
282 * yield for color R=254, G=125, B=242.
283 */
284
285 return rgbArray;
286 }
287
288 /**
289 * Counts the frequency of each color in the colorSamplesArray.
290 *
291 * @param colorSamplesArray
292 * input by means of a int[].
293 * @return An int[7] is returned, with the frequencies.
294 */
295 public static int[] histogramAnalysis(int[] colorSamplesArray) {
296
297 int[] hist = new int[7];
298 /* The array has a field for each color, including "None"-color. */
299
300 for (int j = 0; j < colorSamplesArray.length; j++) {
301 hist[colorSamplesArray[j]]++;
302 }
303 return hist;
304 }
305
306 /**
307 * Less important method: fakes a 'tab' mechanism by adding spaces instead of
308 * tabs. The advantage is: output is displayed in the same way in the console/
309 * notepad.
310 */
311 public static String numberOfSpaces(String str, int ref) {
312
313 StringBuffer sb = new StringBuffer(" "); // Add minimum 1x space.
314
315 for (int i = 0; i < (ref - str.length()); i++) {
316 sb.append(" ");
317 }
318 return sb.toString();
319 }
320
321 /**
322 * Will determine the color of a pixel given rgb-data.
323 *
324 * @param rRGB
325 * the red channel.
326 * @param gRGB
327 * the green channel.
328 * @param bRGB
329 * the blue channel.
330 * @return A int number representing the obtainded color.
331 */
332 public static int whatColorIsPixel(int rRGB, int gRGB, int bRGB) {
333
334 // Red, Green, Blue - channels => Hue, Saturation, Brightness - channels:
335 int colorSample = 6; // 6 = "None"-color.
336 float hsb[] = new float[3];
337 Color.RGBtoHSB(rRGB, gRGB, bRGB, hsb);
338
339 // The results are rescaled slightly:
340 hsb[0] *= 360;
341 hsb[1] *= 100;
342 hsb[2] *= 100;
343
344 if (extensiveSampleOutprint) {
345 String str4 = "[R,G,B]-value: [" + rRGB + ", " + gRGB + ", " + bRGB + "]";
346 System.out.print(str4 + numberOfSpaces(str4, 33));
347 String str5 = " = [H,S,B]-value: [" + Math.round(hsb[0]) + ", " + Math.round(hsb[1])
348 + ", " + Math.round(hsb[2]) + "]";
349 System.out.print(str5 + numberOfSpaces(str5, 34));
350 }
351
352 // Nested if(){}else{}-clauses to determine the color:
353
354 // First White and black are intercepted:
355 if (hsb[1] < maxSaturWhite && hsb[2] > minBrightWhite)
356 colorSample = 5;
357 else {
358 if (hsb[2] < maxBrightBlack)
359 colorSample = 6;
360 else {
361 float hue = hsb[0];
362
363 /*
364 * A bunch of nested if-else clauses is preferably avoided in Java, a no
365 * further elaborated alternative would be to work with a NavigableMap.
366 * It yields for the same functionality, only slightly more elegant.
367 * Another alternative would be to organize the 360 range as a 'tree',
368 * and than gradually descend to the colors lying within range.
369 */
370
371 // sample = Red
372 if (hue >= 0 && hue < distinctionRedOrange)
373 colorSample = 0;
374 // sample = Orange
375 else if (hue >= distinctionRedOrange && hue < distinctionOrangeYellow)
376 colorSample = 3;
377 // sample = Yellow
378 else if (hue >= distinctionOrangeYellow && hue < distinctionYellowGreen)
379 colorSample = 2;
380 // sample = Green
381 else if (hue >= distinctionYellowGreen && hue < distinctionGreenBlue)
382 colorSample = 4;
383 // sample = Blue
384 else if (hue >= distinctionGreenBlue && hue < distinctionBluePurple)
385 colorSample = 1;
386 // sample = None +- purple
387 else if (hue >= distinctionBluePurple && hue < distinctionPurpleRed)
388 colorSample = 6;
389 // sample = Red
390 else
391 colorSample = 0;
392
393 /*
394 * NOTE: Instead of checking for White/Black first, a alternative using
395 * more parameters and therefore a more advanced solution could use
396 * bounds for white/black for each color. The distinction between yellow
1 package model;
2
3 import java.io.*;
4 import java.util.*;
5
6 import solver.solverJS.viewSolverJS.Cubie;
7
8 public class CommandSeq {
9
10 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
11 private static int[] cubieSolMoves = null;
12 private static int[] cubieSolAmount = null;
13 private static int cubieSolLen = 0;
14 private static int[][] solutionCommandsMatrix = null;
15 private static int robotPositionHor = 0;
16 private static int robotPositionVer = 0;
17 // This is the "queue", a FIFO-system of handling the moves.
18 private volatile static Queue<Integer> commandQueue = new LinkedList<Integer>();
19
20 // Getters:
21 /**
22 * This method is for use within this class. It is also called to determine
23 * whether is time to update Cubie's visualization.
24 *
25 * @param syncingWithRobotPurpose
26 * boolean specifying the goal of calling this method.
27 */
28 public static int getNextMove(boolean syncingWithRobotPurpose) {
29 int command = cbthsl.getInt("noValidCommand");
30
31 if (solutionCommandsMatrix != null) {
32 if (robotPositionHor < solutionCommandsMatrix.length) {
33
34 command = solutionCommandsMatrix[robotPositionHor][robotPositionVer];
35
36 if (robotPositionVer + 1 < solutionCommandsMatrix[robotPositionHor].length) {
37 robotPositionVer++;
38 } else {
39
40 if (robotPositionHor < solutionCommandsMatrix.length) {
41 robotPositionHor++;
42 robotPositionVer = 0;
43 /*
44 * System.out.println("A new 'packed' move was performed"); At this
45 * point Cubie's visualization needs an update. '0' is returned in
46 * that case.
47 */
48
49 if (syncingWithRobotPurpose) {
50 command = 0;
51 }
52 }
53 }
54 }
55 }
56 return command;
57 }
58
59 public static int getQueueSize() {
60 return commandQueue.size();
61 }
62
63 /**
64 * Gets the robot's position in the 2-dim solutionCommandsMatrix. Horizontal,
65 * means the first index.
66 */
331 }
332 }
333 }
334 }
335
336 /** Will turn the moves to perform to a String. */
337 public static String solutionCommandsMatrixToString() {
338
339 String newLine = cbthsl.getString("newLine");
340 StringBuffer sb = new StringBuffer();
341
342 // Create a header:
343 String header = "COMMANDS CUBE-SOLUTION PROJECT "
344 + cbthsl.getCurrentProject().getName();
345
346 sb.append(header + newLine);
347
348 String lineEqualSign = "=";
349 for (int b = 0; b < header.length() - 1; b++) {
350 lineEqualSign += "=";
351 }
352
353 sb.append(lineEqualSign + newLine + newLine);
354
355 // Temporarily copy the actual robot position:
356 int tmpRobPosHor = robotPositionHor;
357 int tmpRobPosVer = robotPositionVer;
358
359 robotPositionHor = 0;
360 robotPositionVer = 0;
361
362 int counter = 0, noValidCommand = cbthsl.getInt("noValidCommand");
363 int move = getNextMove(false);
364 while (move != noValidCommand) {
365 if (move != 0) {
366 sb.append((counter + 1) + ":\t\t");
367 sb.append(move + newLine);
368 counter++;
369 }
370 move = getNextMove(false);
371 }
372
373 robotPositionHor = tmpRobPosHor;
374 robotPositionVer = tmpRobPosVer;
375
376 // Afsluiting.
377 sb.append(newLine);
378 sb.append(lineEqualSign + newLine);
379
380 return sb.toString();
381 }
382
383 /**
384 * The current queue is emptied at once, this is the fastest way to stop the
385 * robot move from the Java side: It will complete its last instruction.
386 */
387 public static void stopAsQuicklyAsPossile() {
388 commandQueue = new LinkedList<Integer>();
389 }
390
391 /**
392 * At the end of the queue, the robot will move aside and exit its program.
393 */
394 public static void terminateRobotProgram() {
395 addNewCommand(0);
396 }
397
398 /**
399 * The movesequence, returning from "Cubie", is arranged from solved state to
400 * the problem-situation. (Rather a generating than a solving sequence) The
401 * logic in this method will invert the sequence and translate the solution to
402 * mere quarter- and half-turns (instead of (anti)-slicemoves).
403 */
404 public static int[][] translateMoves(int[] moves, int[] amount, int len) {
405
406 int[][] tempCommandMatrix = null;
407
408 if (moves != null && amount != null && len > 0) {
409
410 /*
411 * The length of the solution "len" sometimes differs from the actual
412 * length of the moves/amount array. In other words: for some reason, some
413 * solvers add additional moves to the solution, which have nothing to do
414 * with the solving sequence. So the solving part of the solution
415 * stretches "len"-amount of fields. Each move is saved at an index in the
416 * moves-array and the amount[index] states whether the move is required
417 * normal, inverted or double.
418 */
419 int tempCommand = 0;
420
421 int q = 0;
422 int m = -1;
423 tempCommandMatrix = new int[len][];
424
425 /*
426 * m=0-5, normal turn m=6-8, middle layer turn m=9-11, cube turn m=12-14,
427 * slice move (2 opposing faces turn) m=15-17, anti-slice move (variant: 2
428 * opposing faces turn)
429 *
430 * These are the numbers that can be found in the moves-array. The goal is
431 * to translate all this moves to robot-commands: quarter- & half-turns
432 * are supported. These moves are stored in a 2-dim tempCommandMatrix. The
433 * first matrixdimension is as long as "len". For each 'packed' move from
434 * the solver, an array is provided, by means of the second dimension that
435 * mentions the translated move(s).
436 *
437 * The importance of preserving the link back to the packed
438 * (non-translated moves) by putting up a 2-dim. matrix instead of a 1-dim
439 * array (with all the translated moves sequenced), is for feedback
440 * purposes. Cubie's visualization only needs its update after a packed
441 * move, not after a 'sub'-move from the robot.
442 */
443
444 for (int index = 0; index < len; index++) {
445
446 /*
447 * [len-index-1] will loop through the solution from situation to solved
448 * state: q==3: inverted move q==2: double move
449 *
450 * The code-system agreed with the robot takes 2 to the power of the
451 * face that needs rotation. Adding a negative sign will result in a
452 * counterclockwise-turn of that particular face. If it concerns a
453 * double move, then the obtained number is multiplied with 10.
454 */
455
456 q = 4 - amount[len - index - 1];
457 m = moves[len - index - 1];
458
459 if (m < 6) {
460 tempCommand = codeMove(m);
461 if (q != 2) {
462 // It concerns a quarter-move:
529 }
530 }
531 return tempCommandMatrix;
532 }
533 }
1 package model;
2
3 import java.awt.BorderLayout;
4
5 import listeners.cam.T_CAM_LiveStreamItemListener;
6 import connection.conWithRobot.CommunicationRobotThread;
7 import solver.solverJS.viewSolverJS.Cubie;
8 import listeners.solv.B_SOLV_CubeToSolverListener;
9 import listeners.solv.B_SOLV_MoveSeqToRobotListener;
10
11 /**
12 * The request for a class like this arised when developing the automatic mode.
13 * Both manual and automatic mode needed to dispose of certain common objects.
14 * This class is mere a gathering, collection of such common objects. This
15 * workaround is probably not a very clean solution.
16 */
17 public class CommonObjects {
18
19 private static CBTHSettingsList cbthsl;
20
21 private static CommunicationRobotThread commRobot;
22 private static T_CAM_LiveStreamItemListener camLSIL;
23 private static Cubie cubie;
24 private static B_SOLV_CubeToSolverListener cubeToSolver;
25 private static B_SOLV_MoveSeqToRobotListener moveSeqToRobot;
26
27 // Constructor:
28 public CommonObjects(CBTHSettingsList cbthsl) {
29
30 // Assign already created object:
31 CommonObjects.cbthsl = cbthsl;
32
33 // Create other common objects, however order of creation is important:
34 camLSIL = null;
35 commRobot = new CommunicationRobotThread();
36 cubie = new Cubie(new BorderLayout(), cbthsl);
37 cubeToSolver = new B_SOLV_CubeToSolverListener(cubie);
38 moveSeqToRobot = new B_SOLV_MoveSeqToRobotListener(cubie);
39 }
40
41 // Getters:
42 public static T_CAM_LiveStreamItemListener getCamLSIL() {
43 return camLSIL;
44 }
45
46 public static CBTHSettingsList getCBTHSettingsList() {
47 return cbthsl;
48 }
49
50 public static CommunicationRobotThread getCommunicatieRobot() {
51 return commRobot;
52 }
53
54 public static Cubie getCubie() {
55 return cubie;
56 }
57
58 public static B_SOLV_CubeToSolverListener getCubeToSolver() {
59 return cubeToSolver;
60 }
61
62 public static B_SOLV_MoveSeqToRobotListener getMoveSeqToRobot() {
63 return moveSeqToRobot;
64 }
65
66 // Setter:
1 package model;
2
3 import java.io.*;
4
5 import exceptions.CubeletAlreadyAssignedException;
6 import exceptions.FaceletColorNoneException;
7 import exceptions.NonExistingCubeletException;
8 import solver.solverJS.algorithm.CubePosition;
9 import solver.solverJS.viewSolverJS.Cubie;
10
11 public class CubeConfiguration {
12
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private static int[] startCubeletPerm;
15 private static int[] startCubeletOri;
16 private static int[] startFaceOri;
17 private static int[] colorMapKey;
18
19 // Getters:
20 public static int[] getColorMapKey() {
21 return colorMapKey;
22 }
23
24 public static int[] getStartCubeletOri() {
25 return startCubeletOri;
26 }
27
28 public static int[] getStartCubeletPerm() {
29 return startCubeletPerm;
30 }
31
32 public static int[] getStartFaceOri() {
33 return startFaceOri;
34 }
35
36 // Setters:
37 public static void setColorMapKey(int[] colorMapKey) {
38 CubeConfiguration.colorMapKey = colorMapKey;
39 }
40
41 public static void setStartCubeletOri(int[] startCubeletOri) {
42 CubeConfiguration.startCubeletOri = startCubeletOri;
43 }
44
45 public static void setStartCubeletPerm(int[] startCubeletPerm) {
46 CubeConfiguration.startCubeletPerm = startCubeletPerm;
47 }
48
49 public static void setStartFaceOri(int[] startFaceOri) {
50 CubeConfiguration.startFaceOri = startFaceOri;
51 }
52
53 // Static methods:
54 /**
55 * Will translate a cubeconfiguration from a set of maincubefaces to the
56 * "virtal cube format" Cubie requires.
57 *
58 * @param mainCubeFaces
59 * A set of six mainCubeFaces, to be found at the
60 * <code>CubeFacesList</code>.
61 */
62 public static void buildVirtualCube(CubeFace[] mainCubeFaces)
63 throws FaceletColorNoneException, NonExistingCubeletException,
64 CubeletAlreadyAssignedException {
65
66 System.out.println("Procedure to build the virtual cube was started...");
67
68 System.out.println("-- VIRTUAL CUBE STAGE 1/7: Retrieving information "
69 + "upon the solver's cube-representation & extracting color-info "
70 + "from the main-cubefaces --");
71 int[][] cubelet2facelet = deepCopy(CubePosition.cubelet2facelet);
72 int[][] cubeletColors = deepCopy(CubePosition.cubeletColors);
73
74 int[][][] mainCubeFacesColors = new int[6][][];
75 for (int u = 0; u < mainCubeFacesColors.length; u++) {
76 mainCubeFacesColors[u] = mainCubeFaces[u].getColorsMatrix();
77 }
78
79 colorMapKey = null;
80
81 System.out.println("-- VIRTUAL CUBE STAGE 2/7: Checking main-cubefaces "
82 + "for the \"" + cbthsl.translateColorsIntToString(6) + "\" color --");
83 areAllFaceletsColored(mainCubeFaces);
84
85 int[] tempStartCubeletPerm = new int[26];
86
87 /* Initialize it on -1, since -1 is not a valid cubelet-id. */
88 for (int y = 0; y < tempStartCubeletPerm.length; y++) {
89 tempStartCubeletPerm[y] = -1;
90 }
91
92 int[] tempStartCubeletOri = new int[26];
93 int[] tempStartFaceOri = { 0, 0, 0, 0, 0, 0 };
94
95 System.out.println();
96 System.out.println("-- VIRTUAL CUBE STAGE 3/7: Linking facelet-colors "
97 + "to the appropriate cubelets --");
98
99 /*
100 * When a cube gets scrambled and randomly oriëntated, each faceletposition
101 * is even likely to show every color. In this stage, we imitate the
102 * cubeletColors-array, by retrieving the color that appears at each
103 * faceletposition. So the info yielded by the mainCubeFaces is framed here
104 * in a 2-dim array of the cubeletColors-type.
105 */
106 int[][] faceletColorsOfCubelets = new int[26][3];
107 int faceletID = -1;
108 for (int t = 0; t < cubelet2facelet.length; t++) {
109 // loop is executed 26x, for increasing cubelet-id.
110
111 for (int s = 0; s < cubelet2facelet[0].length; s++) {
112 faceletID = cubelet2facelet[t][s];
113 if (faceletID != -1) {
114 faceletColorsOfCubelets[t][s] = whatColorIsFacelet(mainCubeFacesColors,
115 faceletID);
116 } else {
117 faceletColorsOfCubelets[t][s] = -1;
118 }
119 }
120 }
121
122 String str1, str2, str3, str4;
123 str1 = " Array original cubelet-colors:";
124 System.out.print(str1 + amountOfSpaces(str1, 40));
125
126 for (int t = 0; t < cubeletColors.length; t++) {
127 str2 = "Cub. " + t + ": " + arrayPrint(cubeletColors[t], ", ");
128 System.out.print(str2 + amountOfSpaces(str2, 20));
129 }
130 System.out.println();
131
132 str3 = " Array detected cubelet-colors:";
199 System.out.println();
200 System.out.println(" Colormapkey-array: {" + arrayPrint(colorMapKey, ", ") + "}");
201
202 System.out.println();
203 System.out.println("-- VIRTUAL CUBE STAGE 5/7: Manipulating local "
204 + "copy of the cubeletcolors-matrix --");
205 int colorTemporary = -1;
206 // Achieved colorMapKey will now customize the cubeletColors-matrix.
207 int[][] newCubeletColors = new int[cubeletColors.length][cubeletColors[0].length];
208
209 for (int a = 0; a < newCubeletColors.length; a++) {
210 for (int b = 0; b < newCubeletColors[0].length; b++) {
211 colorTemporary = cubeletColors[a][b];
212 if (colorTemporary != -1) {
213 newCubeletColors[a][b] = colorMapKey[colorTemporary];
214 } else {
215 // Original fields containing '-1' shouldn't be
216 // translated, -1 is copied.
217 // Occurence of -1 means the actual cubelet isn't a
218 // corner-cubelet.
219 newCubeletColors[a][b] = -1;
220 }
221 }
222 }
223
224 /*
225 * NOTE: The middle-cubeletssection of the cubeletColors-matrix is also
226 * updated, however this was not strictly necessary. It won't cause any
227 * errors, since this is no longer needed.
228 */
229
230 str1 = " Array original cubeletcolors:";
231 System.out.print(str1 + amountOfSpaces(str1, 40));
232
233 for (int t = 0; t < cubeletColors.length; t++) {
234 str2 = "Blok " + t + ": " + arrayPrint(cubeletColors[t], ", ");
235 System.out.print(str2 + amountOfSpaces(str2, 20));
236 }
237 System.out.println();
238
239 /*
240 * Local copy of cubeletColors[][] is overwritten by the new info, yet a
241 * shallow copy would have been sufficient.
242 */
243 cubeletColors = deepCopy(newCubeletColors);
244
245 str1 = " Array manipulated cubeletcolors:";
246 System.out.print(str1 + amountOfSpaces(str1, 40));
247
248 for (int t = 0; t < cubeletColors.length; t++) {
249 str2 = "Blok " + t + ": " + arrayPrint(cubeletColors[t], ", ");
250 System.out.print(str2 + amountOfSpaces(str2, 20));
251 }
252 System.out.println();
253
254 System.out.println();
255 System.out.println("-- VIRTUAL CUBE STAGE 6/7: Identifying remaining "
256 + "corner- & edgecubelets with updated cubeletcolors-array. --");
257 // System.out.println(" ---------------------");
258
259 identifyPermOriCubeletsWithIdRange(alreadyAssigned, 0, 20, faceletColorsOfCubelets,
260 cubeletColors, tempStartCubeletPerm, tempStartCubeletOri);
261
262 System.out.println();
263 System.out.println("-- VIRTUAL CUBE STAGE 7/7: " + "Obtained cube-configuration --");
264 System.out.println();
265
266 // Finally update the "start"-VirtualCube-array's.
267 setStartCubeletPerm(tempStartCubeletPerm);
268 setStartCubeletOri(tempStartCubeletOri);
269 setStartFaceOri(tempStartFaceOri);
270
271 // Last step: Virtual cube will be written to the screen.
272 System.out.println(cubeConfigPrint());
273
274 System.out.println(
275 "The procedure got finished without errors, " + "a virtual cube was built.");
276 }
277
278 // Static auxillary-methods below are listed alphabetically:
279
280 /**
281 * Goal: Faking a [TAB]. When notepad opens a Logfile, it replaces the [TAB]
282 * by another number of spaces, the console does. This will make both
283 * consistent. Min. amount of returned spaces is 1.
284 */
285 public static String amountOfSpaces(String str, int ref) {
286
287 StringBuffer sb = new StringBuffer(" ");
288
289 for (int i = 0; i < (ref - str.length()); i++) {
290 sb.append(" ");
291 }
292 return sb.toString();
293 }
294
295 /**
296 * Checks whether all facelets are coloured.
297 *
298 * @param mainCubeFaces
299 * Those six CubeFace's are hosted in CubeFacesList.
300 * @throws FaceletColorNoneException
301 */
302 public static void areAllFaceletsColored(CubeFace[] mainCubeFaces)
303 throws FaceletColorNoneException {
304
305 int[][] tempColorMatrix = null;
306 String nameCubeFace = null;
307 int u = 0, v = 0;
308
309 int cubeFaceIndex = 0;
310
311 // The program loops through the six faces.
312 while (cubeFaceIndex < 6) {
313
314 tempColorMatrix = mainCubeFaces[cubeFaceIndex].getColorsMatrix();
315 nameCubeFace = mainCubeFaces[cubeFaceIndex].toString();
316
317 u = 0;
318 while (u < tempColorMatrix.length) {
319 v = 0;
320 while (v < tempColorMatrix[0].length) {
321 if (tempColorMatrix[u][v] == 6) {
322 throw new FaceletColorNoneException(nameCubeFace, u, v);
323 }
324 v++;
325 }
326 u++;
327 }
328 cubeFaceIndex++;
329 System.out.println(" Main-cubeface: \"" + nameCubeFace + "\" was checked for \""
330 + cbthsl.translateColorsIntToString(6) + "\" color facelets.");
331 }
332 }
333
334 /**
335 * Compares two int-array's. Returning false will request another shift of the
336 * faceletcolors.
337 *
338 * @param arrayA
339 * @param arrayB
340 * @return The returned boolean could be compared to the "errorsignal" in
341 * systemtheory.
342 */
343 public static boolean arrayComparision(int[] arrayA, int[] arrayB) {
344
345 boolean areEqual = false;
346
347 if (arrayA.length == arrayB.length) { // Als arrayA en arrayB al
348 // niet dezelfde lengte hebben, moet er niet meer verder worden
349 // gecontroleerd.
350 areEqual = true;
351 int index = 0;
352 while (index < arrayA.length && areEqual) {
353 if (arrayA[index] != arrayB[index]) {
354 areEqual = false;
355 }
356 index++;
357 }
358 }
359 return areEqual;
360 }
361
362 /**
363 * Returns the array without '-1'-fields at the end.
364 *
365 * @param array
366 * The input must be an int-array
367 * @return array that has length <= original.length
368 */
369 public static int[] arrayOmitMinusOne(int[] array) {
370
371 int[] arrayToReturn = null;
372 int timesMinOne = countTimesMinOne(array);
373
374 if (timesMinOne > 0) { // If true, we don't deal with a corner-cubelet.
375 arrayToReturn = new int[array.length - timesMinOne];
376
377 // A deep partial deep copy is organized till the returned array
378 // is filled.
379 for (int r = 0; r < arrayToReturn.length; r++) {
380 arrayToReturn[r] = array[r];
381 }
382 }
383
384 else { // We deal with a corner-cubelelt, there's no copying needed.
385 arrayToReturn = array;
386 }
387 return arrayToReturn;
388 }
389
390 /** Generates a textual representation of a 1-dim array. */
391 public static String arrayPrint(int[] array, String enumerationSign) {
392
393 int i = 0;
394 StringBuffer sb = new StringBuffer();
395
396 while (i < array.length - 1) {
661 /*
662 * The locations where the error occurred don't need extra intervention
663 * from the colorMapKey Attention to colorsLocation1/2 when
664 * middle-cubelets are involved: there's no recolouring done yet.
665 */
666 String colorsLocation1 = cubeletColorsToString(cubeletColors[twinPosition]);
667 String colorsLocation2 = cubeletColorsToString(cubeletColors[p]);
668
669 throw new CubeletAlreadyAssignedException(resultPerm, colorsDisputedCubelet,
670 colorsLocation1, colorsLocation2);
671 } else {
672 // If the actual cubelet is a middle-cubelet, then the oriëntation
673 // should not be retrieved.
674 if (resultPerm < 20) {
675 resultOri = retrieveCubeletOrientation(cubeletColors[resultPerm],
676 shallowCopyOfFaceletColors);
677 }
678 // Allocation to local arrays. Since everything went ok,
679 // set the concerned boolean in alreadyAssigned true.
680 tempStartCubeletPerm[p] = resultPerm;
681 tempStartCubeletOri[p] = resultOri;
682 alreadyAssigned[resultPerm] = true;
683 System.out.println(" Cubelet \"" + resultPerm
684 + "\" was succesfully identified & was allocated orientation \"" + resultOri
685 + "\".");
686 // System.out.println(" ---------------------");
687 }
688 }
689 }
690
691 /**
692 * Returns the first index of occurrence of the specified number. If the
693 * number wasn't found, -1 is returned.
694 *
695 * @param array
696 * @param numberToFind
697 * @return returns the first index of occurrence of the numberToFind.
698 */
699 public static int positionNumberInArray(int[] array, int numberToFind) {
700
701 boolean arrayContainsNumber = false;
702 int index = 0;
703 while (index < array.length && !arrayContainsNumber) {
704 if (array[index] == numberToFind) {
705 arrayContainsNumber = true;
706 } else {
707 index++;
708 }
709 }
710 if (!arrayContainsNumber) {
711 index = -1;
712 }
713 return index;
714 }
715
716 /**
717 * Retrieves the CubeletId by looping through the possibilities as efficient
718 * as possible.
719 *
720 * @param cubeletColors
721 * The modified color information from Cubie
722 * @param faceletColorsOfCubelet
723 * The actual colors detected at this cubeletPosition.
724 * @return returns the detected cubelet-iD, if nothing was detected '-1' was
725 * returned.
726 */
859
860 maximum = arrayB.length;
861
862 while (orientationToReturn < maximum && !orientationFound) {
863
864 if (arrayComparision(arrayA, arrayB)) {
865 orientationFound = true;
866 /*
867 * System.out.println("\tArray A\t| Array B"); for(int u=0;
868 * u<arrayA.length; u++){ System.out.println("\tA:"+arrayA[u]+"\t| B:"
869 * +arrayB[u]); }
870 */
871 } else {
872 orientationToReturn++;
873 arrayA = arrayShiftLeft(arrayA, 1);
874 }
875 }
876 /*
877 * Excessive orientations will invoke errors in Cubie. Though not strictly
878 * necessary, it's safe to pass the remainder of the division
879 * ori(..)turn/maximum...
880 */
881 return orientationToReturn % maximum;
882 }
883
884 /**
885 * Given a facelet-iD, and the mainCubeFaces-array, this method will return
886 * the color detected at that place.
887 *
888 * @param mainCubeFacesColors
889 * @param faceletID
890 * Facelet-Id of whom the color should be known.
891 * @return int value that represents color.
892 */
893 public static int whatColorIsFacelet(int[][][] mainCubeFacesColors, int faceletID) {
894
895 int a = -1, b = -1, c = -1, remaindr = -1;
896 a = faceletID / 9;
897 remaindr = faceletID % 9;
898 b = remaindr / 3;
899 c = remaindr % 3;
900
901 return mainCubeFacesColors[a][b][c];
902 }
903 }
1 package model;
2
3 import java.io.*;
4 import java.util.Observable;
5
6 import view.VisualCubeFace;
7
8 public class CubeFace extends Observable {
9
10 private int iD;
11 private String name;
12 private static int iDGenerator = 0;
13 private int[][] colorsMatrix;
14 private double[][] confidenceMatrix;
15 private int[][] noneColorsMatrix = { { 6, 6, 6 }, { 6, 6, 6 }, { 6, 6, 6 } };
16 private VisualCubeFace vcf;
17
18 // Constructors:
19 public CubeFace() {
20
21 this.iD = iDGenerator;
22 this.name = null;
23 this.colorsMatrix = new int[3][3];
24 this.confidenceMatrix = new double[3][3];
25 this.setCubeFaceDeepCopy(noneColorsMatrix, new double[3][3]);
26 this.vcf = createVCubeFace();
27
28 iDGenerator++;
29 }
30
31 public CubeFace(String name, int colorsMatrix[][], double confidenceMatrix[][]) {
32
33 iD = iDGenerator;
34 this.name = name;
35 this.colorsMatrix = new int[3][3];
36 this.confidenceMatrix = new double[3][3];
37
38 if (colorsMatrix != null && confidenceMatrix != null) {
39 this.setCubeFaceDeepCopy(colorsMatrix, confidenceMatrix);
40 }
41
42 else {
43 this.setCubeFaceDeepCopy(noneColorsMatrix, new double[3][3]);
44 }
45 this.vcf = createVCubeFace();
46 // System.out.println("A new CubeFace with iD: \""+iD+"\" was created.");
47 iDGenerator++;
48 }
49
50 // Getters:
51 public int[][] getColorsMatrix() {
52 return this.colorsMatrix;
53 }
54
55 public int getColorValue(int r, int k) {
56 return colorsMatrix[r][k];
57 }
58
59 public double[][] getConfidenceMatrix() {
60 return this.confidenceMatrix;
61 }
62
63 public int getID() {
64 return this.iD;
65 }
66
133 * Automatic routine calls for this method to check if the confidence level
134 * reaches the threshold.
135 */
136 public boolean confidenceLevelSufficient(double thresholdColorEstimation) {
137 boolean sufficient = true;
138 int i = 0, j = 0;
139
140 /*
141 * The use of while loops, allows to stop searching at the first occurrence
142 * of a facelet with low confidence level.
143 */
144 while (i < confidenceMatrix.length && sufficient) {
145 while (j < confidenceMatrix[0].length && sufficient) {
146 if (confidenceMatrix[i][j] < thresholdColorEstimation) {
147 sufficient = false;
148 }
149 j++;
150 }
151 i++;
152 }
153 return sufficient;
154 }
155
156 /**
157 * This method is needed for the constructors and for the
158 * color-recognitionprocess. But navigating on tab [CUBE] is done with
159 * getVisualCubeFace().
160 *
161 * @return VisualCubeFace Returns a new visual representation of the cubeface.
162 */
163 public VisualCubeFace createVCubeFace() {
164
165 VisualCubeFace visualCF = new VisualCubeFace(this);
166 this.addObserver(visualCF);
167
168 updateVisualCubeFace();
169
170 return visualCF;
171 }
172
173 public void cubeFaceToSaveFile(DataOutputStream dos) throws IOException {
174
175 boolean colorsMatrixDiffersFromNull = colorsMatrix != null;
176
177 dos.writeBoolean(colorsMatrixDiffersFromNull);
178
179 if (colorsMatrixDiffersFromNull) {
180
181 for (int r = 0; r < colorsMatrix.length; r++) {
182 for (int s = 0; s < colorsMatrix[0].length; s++) {
183 dos.writeInt(colorsMatrix[r][s]);
184 }
185 }
186 }
187
188 boolean confidenceMatrixDiffersFromNull = confidenceMatrix != null;
189
190 dos.writeBoolean(confidenceMatrixDiffersFromNull);
191
192 if (confidenceMatrixDiffersFromNull) {
193
194 for (int r = 0; r < confidenceMatrix.length; r++) {
195 for (int s = 0; s < confidenceMatrix[0].length; s++) {
196 dos.writeDouble(confidenceMatrix[r][s]);
197 }
198 }
199 }
200 }
201
202 /**
203 * Rotates the CubeFace see tab [CUBE]
204 *
205 * @param clockwise
206 * true=CLKW, false=CNTRCLKW
207 */
208 public void rotateCubeFace(boolean clockwise) {
209
210 int[][] tempColorsMatrix = new int[3][3];
211 double[][] tempConfidenceMatrix = new double[3][3];
212
213 if (clockwise) { // Clockwise 90°
214 for (int i = 0; i < tempColorsMatrix.length; i++) {
215 for (int j = 0; j < tempColorsMatrix[0].length; j++) {
216 tempColorsMatrix[i][j] = colorsMatrix[2 - j][i];
217 tempConfidenceMatrix[i][j] = confidenceMatrix[2 - j][i];
218 }
219 }
220 colorsMatrix = tempColorsMatrix;
221 confidenceMatrix = tempConfidenceMatrix;
222 } else { // Counterclockwise 90°
223 for (int i = 0; i < tempColorsMatrix.length; i++) {
224 for (int j = 0; j < tempColorsMatrix[0].length; j++) {
225 tempColorsMatrix[i][j] = colorsMatrix[j][2 - i];
226 tempConfidenceMatrix[i][j] = confidenceMatrix[j][2 - i];
227 }
228 }
229 colorsMatrix = tempColorsMatrix;
230 confidenceMatrix = tempConfidenceMatrix;
231 }
232 updateVisualCubeFace();
233 }
234
235 @Override
236 /** Textual representation */
237 public String toString() {
238 return this.iD + ". " + this.name;
239 }
240
241 /**
242 * This method is part of the Observer-Observable technique. It will trigger
243 * its Observers.
244 */
245 public void updateVisualCubeFace() {
246
247 setChanged();
248 notifyObservers();
249 }
250 }
1 package model;
2
3 import java.io.*;
4 import java.util.*;
5
6 import exceptions.NumberNotFoundException;
7 import model.CubeFace;
8
9 public class CubeFacesList extends Observable {
10
11 private static String[] mainCubeFacesNames = { "LeftFace", "UpperFace", "FrontFace",
12 "RightFace", "DownFace", "BackFace" };
13 private ArrayList<CubeFace> cubeFacesList;
14 private CubeFace[] mainCubeFacesList = new CubeFace[6];
15
16 // Constructor:
17 public CubeFacesList() {
18
19 cubeFacesList = new ArrayList<CubeFace>();
20 CubeFace cf;
21
22 for (int k = 0; k < mainCubeFacesNames.length; k++) {
23 cf = new CubeFace(mainCubeFacesNames[k], null, null);
24 mainCubeFacesList[k] = cf;
25 }
26 }
27
28 // Getters:
29 public CubeFace[] getAllMainCubeFaces() {
30 return mainCubeFacesList;
31 }
32
33 public CubeFace getCubeFace(int i) {
34 return cubeFacesList.get(i);
35 }
36
37 public List<CubeFace> getCubeFacesList() {
38 return cubeFacesList;
39 }
40
41 public CubeFace getMainCubeFace(int i) {
42 return mainCubeFacesList[i];
43 }
44
45 public int getSize() {
46 return cubeFacesList.size();
47 }
48
49 // Instance methods:
50 public void addCubeFace(CubeFace v) {
51
52 if (v != null) {
53 cubeFacesList.add(v);
54 System.out.println("Cubeface \"" + v.getID() + "\" was added to the "
55 + "cubeFacesList succesfully.");
56 updateCubeFaces();
57 }
58 }
59
60 public void cubeFacesFromSaveFile(DataInputStream dis) throws IOException {
61
62 int amountOfCubeFaces = dis.readInt();
63
64 int[][] newColorsMatrix = null;
65 double[][] newConfidenceMatrix = null;
66
133 }
134 }
135
136 public void resetMainCubeFaces() {
137
138 final int[][] noneColorsMatrix = { { 6, 6, 6 }, { 6, 6, 6 }, { 6, 6, 6 } };
139 double[][] tempConfidenceMatrix = new double[3][3];
140
141 for (int k = 0; k < mainCubeFacesList.length; k++) {
142 // No new CubeFace-objects are made, since we want to keep
143 // their names.
144 mainCubeFacesList[k].setCubeFaceDeepCopy(noneColorsMatrix, tempConfidenceMatrix);
145 }
146 }
147
148 /**
149 * ID is an attribute of the CubFace-object which is unique in one
150 * CubeThesis-session and stays coupled to the CubeFace-object. The index of
151 * the CubeFaces can alter, e.g. when removing items in the ArrayList.
152 */
153 public int searchIndexOfCubeFaceOnID(int nr) throws NumberNotFoundException {
154
155 CubeFace cf = null;
156 boolean alreadyFound = false;
157 int c = 0, a = cubeFacesList.size();
158
159 while (c < a && !alreadyFound) {
160 cf = getCubeFace(c);
161 if (nr == cf.getID()) {
162 alreadyFound = true;
163 } else {
164 c++;
165 }
166 }
167 if (!alreadyFound) {
168 throw new NumberNotFoundException("the cubefaceslist");
169 }
170 return c;
171 }
172
173 public static boolean singleCubeFaceFromSaveFile(DataInputStream dis,
174 int[][] colorsMatrix, double[][] confidenceMatrix) throws IOException {
175
176 boolean boola = false, boolb = false;
177 if (boola = dis.readBoolean()) {
178
179 for (int a = 0; a < colorsMatrix.length; a++) {
180 for (int b = 0; b < colorsMatrix[0].length; b++) {
181 colorsMatrix[a][b] = dis.readInt();
182 }
183 }
184 }
185
186 if (boolb = dis.readBoolean()) {
187
188 for (int a = 0; a < confidenceMatrix.length; a++) {
189 for (int b = 0; b < confidenceMatrix[0].length; b++) {
190 confidenceMatrix[a][b] = dis.readDouble();
191 }
192 }
193 }
194 return !boola && !boolb;
195 }
196
197 /**
198 * This method is part of the Observer-Observable technique. It will trigger
1 package solver.solverJS.algorithm;
2
3 public class CubePosition {
4
5 // These 3 array's represent the cube in the Cubie-applet:
6 public final int cubeletPerm[];
7 public final int cubeletOri[];
8 public final int faceOri[];
9
10 // Is used for Symmetry-tests.
11 static final int pceTypes[] = { 20, 26, 4, 0, 8, 3, 8, 20, 2 };
12
13 // conversion from move number to action on internal cube representation
14 // L U F R D B Lc Uc Fc
15 final int movePerm[][][] = {
16 // piece perm/ori, relabel perm/ori, color perm
17 { // L
18 { 0, 1, 3, 7, 4, 5, 2, 6, 8, 9, 15, 11, 12, 13, 10, 18, 16, 17, 14, 19, 20, 21,
19 22, 23, 24, 25 },
20 { 0, 0, 2, 1, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 3, 0, 0, 0, 0,
21 0 },
22 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
23 22, 23, 24, 25 },
24 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
25 0 },
26 { 0, 0, 0, 0, 0, 0 } },
27 { // U
28 { 3, 0, 1, 2, 4, 5, 6, 7, 11, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
29 22, 23, 24, 25 },
30 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
31 0 },
32 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
33 22, 23, 24, 25 },
34 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 0 },
36 { 0, 0, 0, 0, 0, 0 } },
37 { // F
38 { 0, 2, 6, 3, 4, 1, 5, 7, 8, 14, 10, 11, 12, 9, 17, 15, 16, 13, 18, 19, 20, 21,
39 22, 23, 24, 25 },
40 { 0, 2, 1, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
41 0 },
42 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
43 22, 23, 24, 25 },
44 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 0 },
46 { 0, 0, 0, 0, 0, 0 } },
47 { // R
48 { 1, 5, 2, 3, 0, 4, 6, 7, 13, 9, 10, 11, 8, 16, 14, 15, 12, 17, 18, 19, 20, 21,
49 22, 23, 24, 25 },
50 { 2, 1, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 0,
51 0 },
52 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
53 22, 23, 24, 25 },
54 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0 },
56 { 0, 0, 0, 0, 0, 0 } },
57 { // D
58 { 0, 1, 2, 3, 5, 6, 7, 4, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 16, 20, 21,
59 22, 23, 24, 25 },
60 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
61 0 },
62 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
63 22, 23, 24, 25 },
64 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0 },
66 { 0, 0, 0, 0, 0, 0 } },
67 { // B
68 { 4, 1, 2, 0, 7, 5, 6, 3, 8, 9, 10, 12, 19, 13, 14, 11, 16, 17, 18, 15, 20, 21,
69 22, 23, 24, 25 },
70 { 1, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 3 },
72 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
73 22, 23, 24, 25 },
74 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0 },
76 { 0, 0, 0, 0, 0, 0 } },
77 { // Lc
78 { 4, 0, 3, 7, 5, 1, 2, 6, 12, 11, 15, 19, 16, 8, 10, 18, 13, 9, 14, 17, 20, 25,
79 21, 23, 22, 24 },
80 { 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
81 0 },
82 { 1, 5, 6, 2, 0, 4, 7, 3, 13, 17, 14, 9, 8, 16, 18, 10, 12, 19, 15, 11, 20, 21,
83 22, 23, 24, 25 },
84 { 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
85 0 },
86 { 3, 2, 0, 1, 0, 2 } },
87 { // Uc
88 { 3, 0, 1, 2, 7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14, 19, 16, 17, 18, 22, 21,
89 23, 25, 24, 20 },
90 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0 },
92 { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12, 17, 18, 19, 16, 20, 21,
93 22, 23, 24, 25 },
94 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 0 },
96 { 0, 3, 0, 0, 1, 0 } },
97 { // Fc
98 { 3, 2, 6, 7, 0, 1, 5, 4, 10, 14, 18, 15, 11, 9, 17, 19, 8, 13, 16, 12, 24, 20,
99 22, 21, 23, 25 },
100 { 1, 2, 1, 2, 2, 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
101 0 },
102 { 4, 5, 1, 0, 7, 6, 2, 3, 16, 13, 8, 12, 19, 17, 9, 11, 18, 14, 10, 15, 20, 21,
103 22, 23, 24, 25 },
104 { 2, 1, 2, 1, 1, 2, 1, 2, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
105 0 },
106 { 3, 3, 3, 3, 3, 1 } } };
107
108 /*
109 * There are 54 facelets. In instellingen wordt dezelfde kleurlogica gebruikt
110 * als hier. 0 till 8 = red 9 till 17 = blue 18 till 26 = yellow 27 till 35 =
111 * orange 36 till 44 = green 45 till 53 = white
112 */
113
114 public int faceletColor[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
115 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5,
116 5, 5, 5, 5, 5, 5, 5 };
117 public int faceletOri[] = new int[54];
118
119 public static int faceletOriDiff[] = { 0, 0, 1, 3, 0, 1, 3, 2, 2, 0, 0, 1, 3, 0, 1, 3,
120 2, 2, 0, 0, 1, 3, 0, 1, 3, 2, 2, 0, 0, 1, 3, 0, 1, 3, 2, 2, 0, 0, 1, 3, 0, 1, 3, 2,
121 2, 0, 0, 1, 3, 0, 1, 3, 2, 2 };
122
123 public static int cubeletColors[][] = { // Default colors mapped to the
124 // cubelet.
125 { 1, 5, 3 }, { 1, 3, 2 }, { 1, 2, 0 }, { 1, 0, 5 }, // Corner-cubelets
126 { 4, 3, 5 }, { 4, 2, 3 }, { 4, 0, 2 }, { 4, 5, 0 }, // Corner-cubelets
127 { 1, 3, -1 }, { 1, 2, -1 }, { 1, 0, -1 }, { 1, 5, -1 }, // Edge-cubelets
128 { 3, 5, -1 }, { 3, 2, -1 }, { 0, 2, -1 }, { 0, 5, -1 }, // Edge-cubelets
129 { 4, 3, -1 }, { 4, 2, -1 }, { 4, 0, -1 }, { 4, 5, -1 }, // Edge-cubelets
130 { 0, -1, -1 }, { 1, -1, -1 }, { 2, -1, -1 }, { 3, -1, -1 }, { 4, -1, -1 },
131 { 5, -1, -1 } // Middle-cubelets
132 };
133
134 public static int cubelet2facelet[][] = { { 11, 45, 29 }, { 17, 27, 20 }, { 15, 18, 2 },
135 { 9, 0, 47 }, // Elke Cubelet krijgt in welbepaalde volgorde zijn facelets
136 // toegewezen.
137 { 44, 35, 51 }, { 38, 26, 33 }, { 36, 8, 24 }, { 42, 53, 6 }, { 14, 28, -1 },
138 { 16, 19, -1 }, { 12, 1, -1 }, { 10, 46, -1 }, { 32, 48, -1 }, { 30, 23, -1 },
139 { 5, 21, -1 }, { 3, 50, -1 }, { 41, 34, -1 }, { 37, 25, -1 }, { 39, 7, -1 },
140 { 43, 52, -1 }, { 4, -1, -1 }, { 13, -1, -1 }, { 22, -1, -1 }, { 31, -1, -1 },
141 { 40, -1, -1 }, { 49, -1, -1 } };
142
143 public CubePosition() {
144 // internal general cube representation
145 // Note that the last six are not really the centres. They actually indicate
146 // the
147 // colours used on the sides of the whole cube, and also of the other
148 // pieces. A
149 // permutation of them is hence a recolouring, not a spot pattern. Their
150 // orientation is given and used in supergroup solves (0 is solved ori).
151 // Genummerd van 0-> 25 = 26 blokjes (vanbinnen hoeft er geen voorgesteld te
152 // worden).
153 // Door de volgorde van de getallen in cubeletPerm, kan men blokjes op de
154 // kubus gaan verwisselen, de laatste 6 getallen komen overeen met
155 // kleurverandering.
156
157 int[] tempCubeletPerm = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
158 17, 18, 19, 20, 21, 22, 23, 24, 25 };
159
160 // Door hier een getal in te geven kan men een blokje ter plaatse roteren.
161
162 int[] tempCubeletOri = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
163 0, 0, 0, 0, 0, 0 };
164
165 // This is fixed orientation the supergroup markers are supposed to have,
166 // relative to the initial fixed choice made. Is used to adjust markers when
167 // cube turned
168 // and relabeled.
169 // Supergroupmarkers zijn die zwarte u-tjes die er kunnen bijkomen, om ook
170 // de orientatie van de middelste blokjes consistent juist te krijgen. Je
171 // kunt een checkbox aanvinken in de solvers om die supergroups zichtbaar te
172 // maken.
173
174 int[] tempFaceOri = { 0, 0, 0, 0, 0, 0 };
175
176 this.cubeletPerm = tempCubeletPerm;
177 this.cubeletOri = tempCubeletOri;
178 this.faceOri = tempFaceOri;
179
180 }
181
182 public CubePosition(int[] tempCubeletPerm, int[] tempCubeletOri, int[] tempFaceOri) {
183 this.cubeletPerm = tempCubeletPerm;
184 this.cubeletOri = tempCubeletOri;
185 this.faceOri = tempFaceOri;
186 }
187
188 // reset routines
189 // reset to start position
190 // note: does not reset the centre colours =middle pieces or their default
191 // markings
192 public void reset() {
193 int j;
194 for (j = 0; j < 20; j++) {
195 cubeletPerm[j] = j;
196 cubeletOri[j] = 0;
197 }
198 for (j = 0; j < 6; j++) {
265 // do permutation
266 perm[i] = p0[movePerm[m][0][i]];
267 ori[i] = o0[movePerm[m][0][i]];
268 if (ori[i] >= 0)
269 ori[i] += movePerm[m][1][i];
270 // relabel pieces - reorient cube
271 if (perm[i] >= 0) {
272 perm[i] = movePerm[m][2][perm[i]];
273 if (ori[i] >= 0)
274 ori[i] += movePerm[m][3][perm[i]];
275 }
276 if (ori[i] >= 0) {
277 if (i < 8) {
278 while (ori[i] > 2)
279 ori[i] -= 3; // Van de cornerCubelets wordt er van de orientatie 3
280 // afgetrokken tot de orientatie 0, 1 of 2 beterft.
281 } else if (i < 20) {
282 while (ori[i] > 1)
283 ori[i] -= 2; // Van de edgeCubelets wordt er van de orientatie 2
284 // afgetroeken tot de orienatatie 0 of 1 is.
285 } else {
286 while (ori[i] > 3)
287 ori[i] -= 4; // Van de middleCubelets, stelt de oriëntatie -4
288 // dezelfde oriëntatie voor.
289 }
290 }
291 }
292 for (i = 0; i < 6; i++) {
293 // Permute and adjust face base orientations
294 fc[i] = f0[movePerm[m][0][i + 20] - 20] + movePerm[m][4][i];
295 while (fc[i] > 3)
296 fc[i] -= 4;
297 }
298 // copy new position to current
299 for (i = 0; i < 26; i++) {
300 p0[i] = perm[i];
301 o0[i] = ori[i];
302 }
303 for (i = 0; i < 6; i++) {
304 f0[i] = fc[i];
305 }
306 }
307
308 public void doSequence(MoveSequence ms) {
309 doSequence(ms, ms.getLength());
310 }
311
312 public void doSequence(MoveSequence ms, int l) {
313 int i;
314 reset();
315 for (i = 0; i < l; i++) {
316 doMove(ms.getMoves()[i], ms.getAmount()[i], true);
317 }
318 }
319
320 public void editMove(int c1, int o1, int c2, int o2) {
321 int i;
322 if (c1 < 8 && c2 < 8) {
323 // swap corners
324 if (c1 == c2) {
325 // change orientation of piece c1;
326 cubeletOri[c1] += o1 + 3 - o2;
327 while (cubeletOri[c1] > 2)
328 cubeletOri[c1] -= 3;
329 } else {
330 i = cubeletPerm[c1];
727 }
728 }
729 if (i >= 20 && tryAgain)
730 return false;
731
732 // now check center orientation
733 // first get corner parity
734 if (centres) {
735 tryAgain = false;
736 for (i = 0; i < 8; i++) {
737 for (j = i + 1; j < 8; j++) {
738 if (p0[j] < p0[i])
739 tryAgain = !tryAgain;
740 }
741 }
742 for (i = 20; i < 26 && o0[i] >= 0; i++)
743 if ((o0[i] & 1) != 0)
744 tryAgain = !tryAgain;
745 if (i >= 26 && tryAgain)
746 return false;
747 }
748
749 // finally check for two colours per face
750 if (twoCol) {
751 int[] fc = new int[54], fo = new int[54];
752 getFaceletColors(p0, o0, f0, fc, fo);
753 // check each face
754 int[] lst = new int[7];
755 int ll;
756 for (i = 0; i < 54; i += 9) {
757 ll = 0;
758 for (j = i; j < i + 9; j++) {
759 if (fc[j] >= 0) {
760 for (k = 0; k < ll && lst[k] != fc[j]; k++)
761 ;
762 if (k >= ll)
763 lst[ll++] = fc[j];
764 }
765 }
766 if (ll > 2)
767 return false;
768 }
769 }
770 return true;
771 }
772
773 // convert internal cube representation to cube facelets colours
774 // and facelet marking orientation
775 public void getFaceletColors() {
776 getFaceletColors(cubeletPerm, cubeletOri, faceOri, faceletColor, faceletOri);
777 }
778
779 public void getFaceletColors(int[] p0, int[] o0, int[] f0, int[] fc, int[] fo) {
780 int i, j, k, o, c;
781
782 for (i = 0; i < 54; i++) {
783 fc[i] = -1;
784 } // In het totaal zijn er 54 facelets.
785 for (i = 0; i < 20; i++) { // Alle niet-middenste cubelets overlopen.
786 // get cubelet that is in position i
787 k = p0[i];
788 o = o0[i];
789 if (k >= 0 && o >= 0) {
790
791 for (j = 0; j < 3 && (j < 2 || i < 8); j++) {
792 // i is kleiner dan 8 zolang het over cornercubelets gaat.
793 // Als j 3 dreigt te worden, dan stopt de lus zeker. Als j=2 dreigt te
794 // worden of i 8
795 // dan stopt hij ook denk ik.
796
797 // get facelet color on each side
798 c = cubeletColors[k][o];
799 // color the correct cube facelet
800 fc[cubelet2facelet[i][j]] = c;
801
802 // get the orientation the facelet has in its home position
803 c = f0[c];
804 // adjust by movement to current position
805 c += faceletOriDiff[cubelet2facelet[k][o]]
806 - faceletOriDiff[cubelet2facelet[i][j]];
807 c &= 3;
808 // save the facelet orientation
809 fo[cubelet2facelet[i][j]] = c;
810
811 o = (o == 2 || (o == 1 && i >= 8)) ? 0 : o + 1;
812 }
813 }
814 }
815 for (i = 20; i < 26; i++) {
816 // get cubelet that is in position i
817 o = o0[i];
818
819 // color the centre facelet
820 fc[cubelet2facelet[i][0]] = i - 20;
821 if (o >= 0) {
822 // get the orientation the facelet should have
823 c = f0[i - 20];
824 // adjust by current orientation
825 c += o;
826 c &= 3;
827 // save the facelet orientation
828 fo[cubelet2facelet[i][0]] = c;
829 }
830 }
831 }
832 }
1 package solver.solverJS.algorithm;
2
3 public final class CubieSettings {
4 public int group = 0; // current cube group
5 public boolean superGroup = false; // set if centre orientation visible
6 public boolean solving = false; // set while some solver is busy
7 public volatile int lastOutputSolver = -1; //
8 public MoveSequence generator = null; // movesequence returned from solver
9 public boolean edit = false; // set when edit mode, else play mode.
10
11 public boolean lockViewer = false; // set by cubie to disable user interaction
12 // on viewer
13 // current cube position
14 public CubePosition cubePos = new CubePosition();
15 }
1 package solver.solverJS.algorithm;
2
3 public final class MoveSequence {
4 int len;
5 int moves[];
6 int amount[];
7
8 public MoveSequence() {
9 }
10
11 public MoveSequence(int l, int mvs[], int amt[]) {
12 // given a solution, create generating move sequence
13 int i;
14 len = l;
15 moves = new int[len];
16 amount = new int[len];
17 for (i = 0; i < l; i++) {
18 amount[i] = 4 - amt[l - 1 - i];
19 moves[i] = mvs[l - 1 - i];
20 }
21 simplify();
22 }
23
24 public int[] getMoves() {
25 return (moves);
26 }
27
28 public int[] getAmount() {
29 return (amount);
30 }
31
32 public int getLength() {
33 return (len);
34 }
35
36 public void setMoveSeqFromCBTH(int l, int mvs[], int amt[]) {
37 len = l;
38 moves = mvs;
39 amount = amt;
40 }
41
42 // m=0-5, normal turn
43 // m=6-8, middle layer turn
44 // m=9-11, cube turn
45 // m=12-14, slice move
46 // m=15-17, anti-slice move
47
48 public String toString(boolean inverse) {
49 return (toString(inverse, -1));
50 }
51
52 public String toString(boolean inverse, int pos) {
53 int i, j, m, di, qtm = 0, ftm = 0, stm = 0, q; // qtm = quartermove stm =
54 // slice move
55 StringBuffer sol = new StringBuffer();
56 if (len == 0)
57 return ("");
58 if (inverse) {
59 i = len - 1;
60 di = -1; // di= 'delta i', the sense of incrementation through the
61 // solution.
62 } else {
63 i = 0;
64 di = 1;
65 }
66
133 p++;
134 m = "LUFRDBTlufrdbt".indexOf(c);
135 if (m < 0)
136 continue; // ignore bogus character
137 if (m > 6)
138 m -= 7;
139 if (m == 6)
140 m = 1;
141 i++;
142 } else if (i == 1) { // parse type
143 t = "mcsaMCSA".indexOf(c);
144 if (t >= 4)
145 t -= 4;
146 if (t >= 0)
147 p++; // found type character, skip it.
148 i++;
149 } else if (i == 2) {
150 q = "1+23'-".indexOf(c);
151 if (q >= 0)
152 p++;
153 else
154 q = 1;
155 if (q > 3)
156 q = 3;
157 else if (q <= 1)
158 q = 1;
159
160 // choose canonical face (LUF) in abnormal moves
161 if (t >= 0 && m > 2) {
162 m -= 3;
163 if (t != 3)
164 q = 4 - q;
165 }
166 // append move to list
167 mv[ln] = (t < 0) ? m : m + 6 + 3 * t;
168 am[ln] = q;
169 ln++;
170 i = 0;
171 }
172 }
173
174 // save result
175 len = ln;
176 moves = new int[ln];
177 amount = new int[ln];
178 for (i = 0; i < ln; i++) {
179 moves[i] = mv[i];
180 amount[i] = am[i];
181 }
182
183 simplify();
184
185 if (inverse) {
186 // invert whole sequence
187 for (i = 0, t = len - 1; i < t; i++, t--) {
188 q = moves[i];
189 moves[i] = moves[t];
190 moves[t] = q;
191 q = amount[i];
192 amount[i] = 4 - amount[t];
193 amount[t] = 4 - q;
194 }
195 if (i == t)
196 amount[i] = 4 - amount[i];
197 }
198 }
199
200 private void simplify() {
201 int axis[] = new int[len];
202 int type[] = new int[len];
203 int i, j, k;
204 int turns[] = new int[3];
205 // create list of axes/movetypes
206 for (i = 0; i < len; i++) {
207 axis[i] = moves[i] % 3;
208 type[i] = (moves[i] - axis[i]) / 3;
209 }
210
211 // do simplification on each move
212 i = 0;
213 while (i < len) {
214 // collect moves on same axis as current move
215 turns[0] = turns[1] = turns[2] = 0;
216 for (j = i; j < len && axis[i] == axis[j]; j++) {
217 switch (type[j]) {
218 case 0: // normal, near face
219 turns[0] += amount[j];
220 break;
221 case 1: // normal, far face
222 turns[2] += amount[j];
223 break;
224 case 2: // mid slice
225 turns[1] += amount[j];
226 break;
227 case 3: // whole cube
228 turns[0] += amount[j];
229 turns[1] += amount[j];
230 turns[2] -= amount[j];
231 break;
232 case 4: // slice move
233 turns[0] += amount[j];
234 turns[2] -= amount[j];
235 break;
236 case 5: // anti-slice move
237 turns[0] += amount[j];
238 turns[2] += amount[j];
239 break;
240 }
241 }
242
243 // only one move on this axis, so just leave it
244 if (j <= i + 1) {
245 i++;
246 continue;
247 }
248
249 // simplify
250 turns[0] &= 3;
251 turns[1] &= 3;
252 turns[2] &= 3;
253 if (turns[0] == 0 && turns[1] == 0 && turns[2] == 0) {
254 // annihilation, ok
255 } else if (turns[0] == turns[1] && turns[0] + turns[2] == 4) {
256 // cube turn, ok
257 amount[i] = turns[0];
258 type[i] = 3;
259 moves[i] = 9 + axis[i];
260 i++;
261 } else if (turns[1] == 0 && turns[2] == 0) {
262 // normal, near face, ok
263 amount[i] = turns[0];
264 type[i] = 0;
331 type[i] = 3;
332 moves[i] = 9 + axis[i];
333 i++;
334 // anti-slice
335 amount[i] = (turns[0] - turns[1]) & 3;
336 type[i] = 5;
337 moves[i] = 15 + axis[i];
338 i++;
339 } else if (turns[0] == 0 || turns[1] == 0 || turns[2] == 0) {
340 // 2 layer turns
341 if (turns[0] != 0) {
342 // near
343 amount[i] = turns[0];
344 type[i] = 0;
345 moves[i] = axis[i];
346 i++;
347 }
348 if (turns[1] != 0) {
349 // middle
350 amount[i] = turns[1];
351 type[i] = 2;
352 moves[i] = 6 + axis[i];
353 i++;
354 }
355 if (turns[2] != 0) {
356 // far
357 amount[i] = turns[2];
358 type[i] = 1;
359 moves[i] = 3 + axis[i];
360 i++;
361 }
362 } else {
363 // 2 face turns + cube
364 // near
365 amount[i] = (turns[0] - turns[1]) & 3;
366 type[i] = 0;
367 moves[i] = axis[i];
368 i++;
369 // cube
370 amount[i] = turns[1];
371 type[i] = 3;
372 moves[i] = 9 + axis[i];
373 i++;
374 // far
375 amount[i] = (turns[1] + turns[2]) & 3;
376 type[i] = 1;
377 moves[i] = 3 + axis[i];
378 i++;
379 }
380
381 // remove used-up moves
382 len -= j - i;
383 for (k = i; k < len; k++) {
384 moves[k] = moves[k + j - i];
385 amount[k] = amount[k + j - i];
386 axis[k] = axis[k + j - i];
387 type[k] = type[k + j - i];
388 }
389 }
390 }
391
392 final int symPerm[][] = { { 3, 4, 5, 0, 1, 2 }, { 5, 1, 3, 2, 4, 0 },
393 { 0, 2, 1, 3, 5, 4 }, { 4, 3, 2, 1, 0, 5 }, { 2, 1, 0, 5, 4, 3 },
394 { 0, 5, 4, 3, 2, 1 }, { 1, 0, 2, 4, 3, 5 }, { 0, 4, 2, 3, 1, 5 },
395 { 3, 1, 2, 0, 4, 5 }, { 0, 1, 5, 3, 4, 2 }, { 2, 4, 3, 5, 1, 0 },
396 { 3, 2, 4, 0, 5, 1 }, { 4, 0, 5, 1, 3, 2 },
397
398 { 3, 1, 5, 0, 4, 2 }, { 0, 4, 5, 3, 1, 2 }, { 3, 4, 2, 0, 1, 5 },
399 { 5, 1, 0, 2, 4, 3 }, { 0, 5, 1, 3, 2, 4 }, { 1, 3, 2, 4, 0, 5 },
400 { 5, 0, 4, 2, 3, 1 }, { 1, 2, 0, 4, 5, 3 }, { 4, 5, 0, 1, 2, 3 },
401 { 5, 3, 1, 2, 0, 4 }, { 5, 4, 3, 2, 1, 0 }, { 3, 2, 1, 0, 5, 4 },
402 { 4, 3, 5, 1, 0, 2 }, { 2, 4, 0, 5, 1, 3 }, { 3, 5, 4, 0, 2, 1 },
403 { 1, 0, 5, 4, 3, 2 } };
404
405 public void doSym(int s) {
406 int q, m, t;
407 for (int i = 0; i < len; i++) {
408 q = amount[i];
409 m = moves[i];
410 if (s < 13)
411 q = 4 - q;
412 if (m < 6) {
413 m = symPerm[s][m];
414 } else {
415 t = (m - 6) / 3;
416 m = m % 3;
417 m = symPerm[s][m];
418 if (m > 2) {
419 m -= 3;
420 if (t < 3)
421 q = 4 - q;
422 }
423 m = 6 + 3 * t + m;
424 }
425 amount[i] = q;
426 moves[i] = m;
427 }
428 }
429 }
67 // will only ever be one listener to this, viz the main cubie applet.
68 String cm[] = { "a", "b", "c", "d", "e" };
69 ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, cm[t]);
70 main.actionPerformed(e);
71 }
72
73 // access function prepared flag
74 public boolean isPrepared() {
75 return (prepared);
76 }
77
78 public boolean isRunning() {
79 return (running);
80 }
81
82 // Set position to be solved - initialise search if new position
83 abstract public boolean setPosition(CubePosition cubePos, boolean test);
84
85 // Start/continue search
86 abstract protected boolean solve();
87
88 // initialise tables
89 abstract protected void init();
90
91 // mix cube within this cube group
92 abstract public void mix(CubePosition cubePos);
93
94 // convert movelist into string solution
95 abstract public MoveSequence getGenerator();
96
97 // --- General utilities ---
98 protected void swap(int pr[], int i, int j) {
99 int c = pr[i];
100 pr[i] = pr[j];
101 pr[j] = c;
102 }
103
104 protected void cycle(int pr[], int i, int j, int k, int l) {
105 int c = pr[i];
106 pr[i] = pr[j];
107 pr[j] = pr[k];
108 pr[k] = pr[l];
109 pr[l] = c;
110 }
111
112 // return true if permutation is odd
113 protected boolean parityOdd(int pieces[], int start, int len) {
114 int i, j;
115 boolean p = false;
116 for (i = 0; i < len; i++) {
117 for (j = 0; j < i; j++) {
118 p ^= (pieces[start + i] < pieces[start + j]);
119 }
120 }
121 return (p);
122 }
123
124 // Convert number to permutation
125 protected void num2perm(int pieces[], int start, int len, int pos) {
126 // convert number pos into permutation of 0..len-1 and put it
127 // in array pieces[start..start+len-1]
128 int i, r;
129 int w[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
130 for (i = 0; i < len; i++) {
131 r = pos % (len - i);
132 pos = (pos - r) / (len - i);
1 package solver.solverJS.algorithm;
2
3 // ----- Solver for the Anti-Slice group ----
4 import java.awt.event.*;
5
6 public final class SolverAntiSlice extends Solver {
7 int maxdepth; // current search depth
8 byte prune[][][][][];
9 byte pruneFace[];
10 int transFace[][];
11 final int transCorn[][] = { { 4, 0, 6, 2, 5, 1, 7, 3 }, // La
12 { 1, 2, 3, 0, 7, 4, 5, 6 }, // Ua
13 { 3, 5, 1, 7, 0, 6, 2, 4 } };// Fa
14
15 final int transEdge[][] = { { 4, 1, 6, 3, 8, 0, 10, 2, 5, 9, 7, 11 }, // La
16 { 1, 2, 3, 0, 4, 5, 6, 7, 11, 8, 9, 10 }, // Ua
17 { 0, 5, 2, 7, 3, 9, 1, 11, 8, 6, 10, 4 } };// Fa
18
19 final int transOri[][] = { { 2, 1, 0, 3 }, // La
20 { 0, 2, 1, 3 }, // Ua
21 { 0, 1, 3, 2 } };// Fa
22
23 public SolverAntiSlice(ActionListener m) {
24 super(m);
25 }
26
27 public MoveSequence getGenerator() {
28 int[] m = new int[sollen];
29 for (int i = 0; i < sollen; i++) {
30 m[i] = 15 + solmoves[i];
31 if (m[i] > 17)
32 m[i] -= 3;
33 }
34 return (new MoveSequence(sollen, m, solamount));
35 }
36
37 public void mix(CubePosition cubePos) {
38 int j;
39 // direct method, not random moves
40 cubePos.reset();
41
42 // edge orientation. 4 possibilities. face centres unaffected
43 j = (int) (4 * Math.random());
44 if (j == 1 || j == 3) {
45 cubePos.cubeletOri[12] = cubePos.cubeletOri[13] = cubePos.cubeletOri[14] =
46 cubePos.cubeletOri[15] = 1;
47 }
48 if (j > 1) {
49 cubePos.cubeletOri[8] = cubePos.cubeletOri[10] = cubePos.cubeletOri[16] =
50 cubePos.cubeletOri[18] = 1;
51 }
52 if (j == 1 || j == 2) {
53 cubePos.cubeletOri[9] = cubePos.cubeletOri[11] = cubePos.cubeletOri[17] =
54 cubePos.cubeletOri[19] = 1;
55 }
56
57 // set edges. first LR slice. 4 possibilities
58 j = (int) (4 * Math.random());
59 if (j < 2) {
60 swap(cubePos.cubeletPerm, 9, 11);
61 swap(cubePos.cubeletPerm, 17, 19);
62 swap(cubePos.cubeletPerm, 8, 10);
63 swap(cubePos.cubeletPerm, 16, 18);
64 // face centres unaffected
65 }
66 if (j == 1 || j == 3) {
67 swap(cubePos.cubeletPerm, 9, 17);
68 swap(cubePos.cubeletPerm, 11, 19);
69 swap(cubePos.cubeletPerm, 13, 14);
70 swap(cubePos.cubeletPerm, 12, 15);
71 // face centres unaffected
72 }
73
74 // now FB slice. 4 possibilities
75 j = (int) (4 * Math.random());
76 if (j < 2) {
77 swap(cubePos.cubeletPerm, 8, 10);
78 swap(cubePos.cubeletPerm, 16, 18);
79 swap(cubePos.cubeletPerm, 12, 14);
80 swap(cubePos.cubeletPerm, 13, 15);
81 // face centres unaffected by 2x2H pattern
82 }
83 if (j == 1 || j == 3) {
84 swap(cubePos.cubeletPerm, 8, 18);
85 swap(cubePos.cubeletPerm, 10, 16);
86 swap(cubePos.cubeletPerm, 13, 14);
87 swap(cubePos.cubeletPerm, 12, 15);
88 // face centres unaffected
89 }
90
91 // random position of corners. 4*3*4*2 positions
92 // Maybe swap U/D corners
93 j = (int) (2 * Math.random());
94 if (j == 1) {
95 cubePos.doMove(0);
96 cubePos.doMove(3);
97 cubePos.doMove(0);
98 cubePos.doMove(3);
99 }
100 // rotate around UD axis
101 j = (int) (4 * Math.random());
102 while (j > 0) {
103 cubePos.doMove(1);
104 cubePos.doMove(4);
105 j--;
106 }
107 // rotate corner 1 in place
108 j = (int) (3 * Math.random());
109 while (j > 0) {
110 cubePos.doMove(0);
111 cubePos.doMove(3);
112 cubePos.doMove(1);
113 cubePos.doMove(4);
114 j--;
115 }
116
117 // tetrad 1,3,4,6 has been set
118 // set remaining tetrad
119 j = (int) (4 * Math.random());
120 if (j == 0) {
121 cubePos.doMove(0);
122 cubePos.doMove(3);
123 cubePos.doMove(1);
124 cubePos.doMove(4);
125 cubePos.doMove(0);
126 cubePos.doMove(3);
127 cubePos.doMove(0);
128 cubePos.doMove(3);
129 cubePos.doMove(0);
130 cubePos.doMove(3);
131 cubePos.doMove(2);
132 cubePos.doMove(5);
133 cubePos.doMove(2);
134 cubePos.doMove(5);
135 cubePos.doMove(2);
136 cubePos.doMove(5);
137 } else if (j == 1) {
138 cubePos.doMove(1);
139 cubePos.doMove(4);
140 cubePos.doMove(2);
141 cubePos.doMove(5);
142 cubePos.doMove(1);
143 cubePos.doMove(4);
144 cubePos.doMove(1);
145 cubePos.doMove(4);
146 cubePos.doMove(1);
147 cubePos.doMove(4);
148 cubePos.doMove(0);
149 cubePos.doMove(3);
150 cubePos.doMove(0);
151 cubePos.doMove(3);
152 cubePos.doMove(0);
153 cubePos.doMove(3);
154 } else if (j == 2) {
155 cubePos.doMove(2);
156 cubePos.doMove(5);
157 cubePos.doMove(0);
158 cubePos.doMove(3);
159 cubePos.doMove(2);
160 cubePos.doMove(5);
161 cubePos.doMove(2);
162 cubePos.doMove(5);
163 cubePos.doMove(2);
164 cubePos.doMove(5);
165 cubePos.doMove(1);
166 cubePos.doMove(4);
167 cubePos.doMove(1);
168 cubePos.doMove(4);
169 cubePos.doMove(1);
170 cubePos.doMove(4);
171 }
172 }
173
174 public boolean setPosition(CubePosition cubePos, boolean test) {
175 int i, j;
176
177 // check corner orientation
178 // corners must have alternating orientation
179 for (i = 0; i < 7; i++) {
180 if (i == 3) {
181 j = cubePos.cubeletOri[0] + cubePos.cubeletOri[4];
182 } else {
183 j = cubePos.cubeletOri[i] + cubePos.cubeletOri[i + 1];
184 }
185 if (j != 0 && j != 3)
186 return (false);
187 }
188
189 // check edge orientation
190 // each slice must have same orientations
191 if (cubePos.cubeletOri[8] != cubePos.cubeletOri[10]
192 || cubePos.cubeletOri[8] != cubePos.cubeletOri[16]
193 || cubePos.cubeletOri[8] != cubePos.cubeletOri[18])
194 return (false);
195 if (cubePos.cubeletOri[9] != cubePos.cubeletOri[11]
196 || cubePos.cubeletOri[9] != cubePos.cubeletOri[17]
197 || cubePos.cubeletOri[9] != cubePos.cubeletOri[19])
198 return (false);
331 if (perm[i] != i)
332 return (false);
333 if (cubieSettings.superGroup) {
334 for (i = 20; i < 23; i++)
335 if (perm[i] != 0)
336 return (false);
337 }
338
339 if (test)
340 return (true);
341 if (!prepared)
342 return (false);
343
344 // convert to numbers
345 for (i = 0; i < 8; i++) {
346 if (cubePos.cubeletPerm[i] == 0)
347 perm[0] = i;
348 }
349 for (i = 8; i < 20; i++) {
350 if (cubePos.cubeletPerm[i] == 8)
351 perm[1] = i - 8;
352 else if (cubePos.cubeletPerm[i] == 9)
353 perm[2] = i - 8;
354 else if (cubePos.cubeletPerm[i] == 12)
355 perm[3] = i - 8;
356 }
357 perm[4] = cubePos.cubeletOri[8] * 2 + cubePos.cubeletOri[9];
358 if (cubieSettings.superGroup) {
359 perm[5] = (cubePos.cubeletOri[20] << 4)
360 + (cubePos.cubeletOri[21] << 2)
361 + cubePos.cubeletOri[22];
362 } else {
363 perm[5] = -1;
364 }
365
366 if (positionlist == null) {
367 positionlist = new int[40][6];
368 maxdepth = sollen = 0;
369 solmoves[0] = -1;
370 solamount[0] = 3;
371 } else if (positionlist[0][0] != perm[0] || positionlist[0][1] != perm[1]
372 || positionlist[0][2] != perm[2] || positionlist[0][3] != perm[3]
373 || positionlist[0][4] != perm[4] || positionlist[0][5] != perm[5]) {
374 // clear out search history
375 maxdepth = sollen = 0;
376 solmoves[0] = -1;
377 solamount[0] = 3;
378 }
379 // set position
380 positionlist[0][0] = perm[0];
381 positionlist[0][1] = perm[1];
382 positionlist[0][2] = perm[2];
383 positionlist[0][3] = perm[3];
384 positionlist[0][4] = perm[4];
385 positionlist[0][5] = perm[5];
386 return (true);
387 }
388
389 // initialise tables
390 protected void init() {
391 int i1, i2, i3, i4, i5, k, m, q, j1, j2, j3, j4, j5;
392 transFace = new int[3][64];
393 prune = new byte[8][12][12][12][4];
394 pruneFace = new byte[64];
395
396 // calculate transition/pruning table for face centres
397 k = 0;
398 for (i1 = 0; i1 < 4; i1++)
399 for (i2 = 0; i2 < 4; i2++)
400 for (i3 = 0; i3 < 4; i3++) {
401 transFace[0][k] = (((i1 + 3) & 3) << 4) + (i2 << 2) + i3;
402 transFace[1][k] = (i1 << 4) + (((i2 + 3) & 3) << 2) + i3;
403 transFace[2][k] = (i1 << 4) + (i2 << 2) + ((i3 + 3) & 3);
404 pruneFace[k] = 1;
405 if (i1 != 0)
406 pruneFace[k]++;
407 if (i2 != 0)
408 pruneFace[k]++;
409 if (i3 != 0)
410 pruneFace[k]++;
411 k++;
412 }
413
414 // calculate pruning tables
415 int l = 1;
416 prune[0][0][1][4][0] = 1;
417 do {
418 k = 0;
419 for (i1 = 0; i1 < 8; i1++)
420 for (i2 = 0; i2 < 12; i2++)
421 for (i3 = 0; i3 < 12; i3++)
422 for (i4 = 0; i4 < 12; i4++)
423 for (i5 = 0; i5 < 4; i5++) {
424 if (prune[i1][i2][i3][i4][i5] == l) {
425 for (m = 0; m < 3; m++) {
426 j1 = i1;
427 j2 = i2;
428 j3 = i3;
429 j4 = i4;
430 j5 = i5;
431 for (q = 0; q < 3; q++) {
432 j1 = transCorn[m][j1];
433 j2 = transEdge[m][j2];
434 j3 = transEdge[m][j3];
435 j4 = transEdge[m][j4];
436 j5 = transOri[m][j5];
437 if (prune[j1][j2][j3][j4][j5] == 0) {
438 prune[j1][j2][j3][j4][j5] = (byte) (l + 1);
439 k++;
440 }
441 }
442 }
443 }
444 }
445 l++;
446 } while (k != 0);
447 }
448
449 // solve a position
450 protected boolean solve() {
451 // do IDA* - search depth first for each maxdepth.
452 while (!search()) {
453 if (wanttostop)
454 return (false);
455 maxdepth++;
456 }
457 return (true);
458 }
459
460 private boolean search() {
461 // do a depth search through all positions at depth maxdepth.
462 // return false if no solution, or break out with true if solved.
529 if (wanttostop)
530 return (false);
531 // loop back to shift to next move sequence
532 }
533 // reset for next search
534 solmoves[0] = -1;
535 solamount[0] = 3;
536 sollen = 0;
537 return (false);
538 }
539 }
1 package solver.solverJS.algorithm;
2
3 // ----- Solver for the full group, kociemba 2-phase ----
4 import java.awt.event.*;
5
6 public final class SolverKociemba extends Solver {
7 // position = cornerperm 40320, cornerori 2187, edgeori 2048,
8 // midslicefull 11880=12!/8! for all three slices
9 // in phase 2 two slices become one set 40320.
10 // centresori 4096 (redundancy factor of 2)
11 // Pruning:
12 // phase 1. orientations 2^11=2048, 3^7=2187, slicechoice:12C4=495
13 // phase 2. corners 8!=40320, edgesUD 8!=40320, edgesM 4!=24
14 int transEdgeOri[][];
15 int transCornOri[][];
16 int transCornPerm[][];
17 int transSliceFull[][];
18 int transEdgePerm[][];
19 int transSlicePerm[][];
20 int transChoice[][];
21 int transFace[][];
22
23 byte pruneEdgeOri[];
24 byte pruneCornOri[];
25 byte pruneChoice[];
26 byte pruneCornPerm[];
27 byte pruneEdgePerm[];
28 byte pruneSlicePerm[];
29 byte pruneFace1[];
30 byte pruneFace2[];
31 int phase1len = 0; // current search depth for phase1
32 int phase2len = 0; // current search depth for phase2
33 int maxdepth = 25; // length of best solution found (phase1+phase2)
34
35 public SolverKociemba(ActionListener m) {
36 super(m);
37 }
38
39 public MoveSequence getGenerator() {
40 // sollen = solutionLength ...
41 return (new MoveSequence(sollen, solmoves, solamount));
42 }
43
44 public void mix(CubePosition cubePos) {
45 int i;
46 // direct method, not random moves
47 cubePos.reset();
48 do {
49 num2perm(cubePos.cubeletPerm, 0, 8, (int) (40320 * Math.random()));
50 num2perm(cubePos.cubeletPerm, 8, 12, (int) (479001600 * Math.random()));
51 for (i = 8; i < 20; i++)
52 cubePos.cubeletPerm[i] += 8;
53 } while (parityOdd(cubePos.cubeletPerm, 0, 20));
54
55 num2ori(cubePos.cubeletOri, 0, 8, 3, (int) (2187 * Math.random()));
56 num2ori(cubePos.cubeletOri, 8, 12, 2, (int) (2048 * Math.random()));
57 num2ori(cubePos.cubeletOri, 20, 6, 4, (int) (1024 * Math.random()));
58 if (Math.random() < .5)
59 cubePos.cubeletOri[25] ^= 2;
60 if (parityOdd(cubePos.cubeletPerm, 0, 8))
61 cubePos.cubeletOri[25] ^= 1;
62 }
63
64 public boolean setPosition(CubePosition cubePos, boolean test) {
65 int i, j = 0;
66 for (i = 0; i < 8; i++) {
67 j += cubePos.cubeletOri[i];
68 if (j > 2)
69 j -= 3;
70 }
71 if (j != 0)
72 return (false);
73 j = 0;
74 for (i = 8; i < 20; i++) {
75 j += cubePos.cubeletOri[i];
76 if (j > 1)
77 j -= 2;
78 }
79 if (j != 0)
80 return (false);
81 if (cubieSettings.superGroup) {
82 boolean f = parityOdd(cubePos.cubeletPerm, 0, 8);
83 for (i = 20; i < 26; i++) {
84 if ((cubePos.cubeletOri[i] & 1) != 0)
85 f = !f;
86 }
87 if (f)
88 return (false);
89 }
90 if (parityOdd(cubePos.cubeletPerm, 0, 20))
91 return (false);
92
93 if (test)
94 return (true);
95 if (!prepared)
96 return (false);
97
98 // convert position to numbers
99 int newpos[] = new int[8];
100 newpos[0] = 0;
101 for (i = 10; i >= 0; i--)
102 newpos[0] = newpos[0] * 2 + cubePos.cubeletOri[8 + i];
103 newpos[1] = 0;
104 for (i = 6; i >= 0; i--)
105 newpos[1] = newpos[1] * 3 + cubePos.cubeletOri[i];
106 newpos[2] = perm2num(cubePos.cubeletPerm, 0, 8);
107 newpos[3] = partperm2num(cubePos.cubeletPerm, 12, 8, 8, 4);
108 newpos[4] = partperm2num(cubePos.cubeletPerm, 12, 8, 12, 4);
109 newpos[5] = partperm2num(cubePos.cubeletPerm, 12, 8, 16, 4);
110 newpos[6] = 0;
111 for (i = 10; i >= 0; i--)
112 newpos[6] = newpos[6] * 2
113 +((cubePos.cubeletPerm[8 + i] >= 12
114 && cubePos.cubeletPerm[8 + i] < 16) ? 1
115 : 0);
116 if (cubieSettings.superGroup) {
117 newpos[7] = 0;
118 for (i = 20; i < 26; i++)
119 newpos[7] = newpos[7] * 4 + cubePos.cubeletOri[i];
120 } else {
121 newpos[7] = -1;
122 }
123
124 // clear search history if are using a different position
125 if (positionlist == null) {
126 positionlist = new int[40][10];
127 sollen = phase1len = phase2len = 0;
128 maxdepth = 25;
129 solmoves[0] = -1;
130 solamount[0] = 3;
131 } else if (positionlist[0][0] != newpos[0]
132 || positionlist[0][1] != newpos[1]
265 }
266 // reset for next search
267 solmoves[0] = -1;
268 solamount[0] = 3;
269 sollen = 0;
270 return (false);
271 }
272
273 private boolean solve2() {
274 // should not search further if last phase1 move
275 // could have been done in phase 2
276 if (sollen > 0) {
277 if (solamount[sollen - 1] == 2 || solmoves[sollen - 1] == 1
278 || solmoves[sollen - 1] == 4)
279 return (false);
280 }
281 // quick prune on corners before doing position conversion
282 if(phase1len + pruneCornPerm[positionlist[phase1len][2]] > maxdepth + 1
283 || (cubieSettings.superGroup
284 && phase1len + pruneFace2[positionlist[phase1len][9]] >
285 maxdepth + 1)) {
286 return (false);
287 }
288
289 // get depth to start phase 2 search with
290 phase2len = sollen - phase1len;
291 if (sollen > maxdepth) {
292 phase2len = maxdepth - phase1len;
293 }
294
295 // if just finished phase1, then convert phase1 end position
296 // to phase2 start position
297 if (phase2len == 0) {
298 // check if already finished
299 if(positionlist[phase1len][2] == 0 && positionlist[phase1len][3] == 0
300 && positionlist[phase1len][4] == 5860
301 && positionlist[phase1len][5] == 11720
302 && positionlist[phase1len][9] <= 0)
303 return (true);
304
305 // convert edge pos numbers into full edge permutation
306 int edges[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
307 num2partperm(edges, 0, 12, 4, 0, positionlist[phase1len][3]);
308 num2partperm(edges, 0, 12, 4, 4, positionlist[phase1len][4]);
309 num2partperm(edges, 0, 12, 4, 8, positionlist[phase1len][5]);
310
311 // check that face centres can be solved given this middle slice
312 if (cubieSettings.superGroup) {
313 boolean par = parityOdd(edges, 4, 4);
314 if ((positionlist[phase1len][9] & 2) != 0)
315 par = !par;
316 if ((positionlist[phase1len][9] & 32) != 0)
317 par = !par;
318 if ((positionlist[phase1len][9] & 128) != 0)
319 par = !par;
320 if ((positionlist[phase1len][9] & 2048) != 0)
321 par = !par;
322 if (par)
323 return (false);
324 }
325
326 // convert middle slice to number
327 positionlist[phase1len][8] = perm2num(edges, 4, 4);
328 edges[4] = edges[8];
329 edges[5] = edges[9];
330 edges[6] = edges[10];
529 }
530 }
531 }
532 }
533 }
534 l++;
535 } while (k != 0);
536
537 // slice choice pruning
538 l = 1;
539 pruneChoice[240] = 1;
540 do {
541 k = 0;
542 for (i = 0; i < 2048; i++) {
543 if (pruneChoice[i] == l) {
544 for (m = 0; m < 6; m++) {
545 p = i;
546 for (q = 0; q < 3; q++) {
547 p = transChoice[p][m];
548 if (pruneChoice[p] == 0) {
549 pruneChoice[p] = (byte) (l + 1);
550 k++;
551 }
552 }
553 }
554 }
555 }
556 l++;
557 } while (k != 0);
558
559 // corner perm pruning
560 l = 1;
561 pruneCornPerm[0] = 1;
562 do {
563 k = 0;
564 for (i = 0; i < 40320; i++) {
565 if (pruneCornPerm[i] == l) {
566 for (m = 0; m < 6; m++) {
567 p = i;
568 for (q = 0; q < 3; q++) {
569 p = transCornPerm[p][m];
570 if (m == 1 || m == 4 || q == 1) {
571 if (pruneCornPerm[p] == 0) {
572 pruneCornPerm[p] = (byte) (l + 1);
573 k++;
574 }
575 }
576 }
577 }
578 }
579 }
580 l++;
581 } while (k != 0);
582
583 // edge perm pruning
584 l = 1;
585 pruneEdgePerm[0] = 1;
586 do {
587 k = 0;
588 for (i = 0; i < 40320; i++) {
589 if (pruneEdgePerm[i] == l) {
590 for (m = 0; m < 6; m++) {
591 p = i;
592 for (q = 0; q < 3; q++) {
593 p = transEdgePerm[p][m];
594 if (pruneEdgePerm[p] == 0) {
661 // do move L U F R D B
662 if (m == 3) {
663 cycle(edges, 0, 5, 8, 4);
664 edges[0] ^= 1;
665 edges[5] ^= 1;
666 edges[8] ^= 1;
667 edges[4] ^= 1;
668 } else if (m == 2) {
669 cycle(edges, 1, 6, 9, 5);
670 } else if (m == 0) {
671 cycle(edges, 2, 7, 10, 6);
672 edges[2] ^= 1;
673 edges[7] ^= 1;
674 edges[10] ^= 1;
675 edges[6] ^= 1;
676 } else if (m == 5) {
677 cycle(edges, 3, 4, 11, 7);
678 } else if (m == 1) {
679 cycle(edges, 3, 2, 1, 0);
680 } else if (m == 4) {
681 cycle(edges, 8, 9, 10, 11);
682 }
683 // convert back to number
684 return (ori2num(edges, 0, 12, 2));
685 }
686
687 private int gettransCornOri(int pos, int m) {
688 // convert pos number into permutation
689 int corners[] = new int[8];
690 num2ori(corners, 0, 8, 3, pos);
691
692 // do move L U F R D B
693 if (m == 3) {
694 cycle(corners, 0, 1, 5, 4);
695 corners[0] += 2;
696 corners[1]++;
697 corners[5] += 2;
698 corners[4]++;
699 } else if (m == 2) {
700 cycle(corners, 1, 2, 6, 5);
701 corners[1] += 2;
702 corners[2]++;
703 corners[6] += 2;
704 corners[5]++;
705 } else if (m == 0) {
706 cycle(corners, 2, 3, 7, 6);
707 corners[2] += 2;
708 corners[3]++;
709 corners[7] += 2;
710 corners[6]++;
711 } else if (m == 5) {
712 cycle(corners, 3, 0, 4, 7);
713 corners[3] += 2;
714 corners[0]++;
715 corners[4] += 2;
716 corners[7]++;
717 } else if (m == 1) {
718 cycle(corners, 3, 2, 1, 0);
719 } else if (m == 4) {
720 cycle(corners, 4, 5, 6, 7);
721 }
722 // convert back to number
723 return (ori2num(corners, 0, 8, 3));
724 }
725
726 private int gettransCornPerm(int pos, int m) {
793 } else if (m == 1) {
794 cycle(edges, 3, 2, 1, 0);
795 } else if (m == 4) {
796 cycle(edges, 8, 9, 10, 11);
797 }
798 // convert back to number
799 pos = 0;
800 for (i = 3; i >= 0; i--) {
801 r = 0;
802 for (j = 0; j < 12 && edges[j] != i + 1; j++) {
803 if (edges[j] == 0 || edges[j] > i + 1)
804 r++;
805 }
806 pos = pos * (12 - i) + r;
807 }
808 return (pos);
809 }
810
811 private int gettransSlicePerm(int pos, int m) {
812 // convert pos number into permutation
813 int edges[] = new int[4];
814 num2perm(edges, 0, 4, pos);
815 // do move L U F R D B
816 if (m == 3) {
817 swap(edges, 0, 1);
818 } else if (m == 2) {
819 swap(edges, 1, 2);
820 } else if (m == 0) {
821 swap(edges, 2, 3);
822 } else if (m == 5) {
823 swap(edges, 3, 0);
824 }
825 // convert back to number
826 return (perm2num(edges, 0, 4));
827 }
828
829 private int gettransChoice(int pos, int m) {
830 // convert pos number into orientation
831 int edges[] = new int[12];
832 num2ori(edges, 0, 12, 2, pos);
833
834 // do move L U F R D B
835 if (m == 3) {
836 cycle(edges, 0, 5, 8, 4);
837 } else if (m == 2) {
838 cycle(edges, 1, 6, 9, 5);
839 } else if (m == 0) {
840 cycle(edges, 2, 7, 10, 6);
841 } else if (m == 5) {
842 cycle(edges, 3, 4, 11, 7);
843 } else if (m == 1) {
844 cycle(edges, 3, 2, 1, 0);
845 } else if (m == 4) {
846 cycle(edges, 8, 9, 10, 11);
847 }
848 // convert back to number
849 return (ori2num(edges, 0, 12, 2));
850 }
851 }
1 package solver.solverJS.algorithm;
2
3 // ----- Solver for the Slice group ----
4 import java.awt.event.*;
5
6 public final class SolverSlice extends Solver {
7 int maxdepth; // current search depth
8 byte prune[][][][];
9 byte prune2[][][][][];
10 final int transCorn[][] = { { 1, 5, 6, 2, 0, 4, 7, 3 }, // Ls
11 { 1, 2, 3, 0, 5, 6, 7, 4 }, // Us
12 { 4, 5, 1, 0, 7, 6, 2, 3 } };// Fs
13
14 final int transEdge[][] = { { 5, 1, 6, 3, 0, 8, 10, 2, 4, 9, 7, 11 }, // Ls
15 { 1, 2, 3, 0, 4, 5, 6, 7, 9, 10, 11, 8 }, // Us
16 { 0, 5, 2, 4, 11, 9, 1, 3, 8, 6, 10, 7 } };// Fs
17
18 int transOri[][];
19
20 public SolverSlice(ActionListener m) {
21 super(m);
22 }
23
24 public MoveSequence getGenerator() {
25 int[] m = new int[sollen];
26 int[] a = new int[sollen];
27 for (int i = 0; i < sollen; i++) {
28 m[i] = 12 + solmoves[i];
29 a[i] = solamount[i];
30 if (m[i] > 14) {
31 m[i] -= 3;
32 a[i] = 4 - a[i];
33 }
34 }
35 return (new MoveSequence(sollen, m, a));
36 }
37
38 public void mix(CubePosition cubePos) {
39 int j;
40 // direct method, not random moves
41 cubePos.reset();
42 // random position of corners
43 // choose one of the three axes to go UD
44 j = (int) (3 * Math.random());
45 if (j == 1) {
46 cubePos.doMove(0);
47 cubePos.doMove(3);
48 cubePos.doMove(3);
49 cubePos.doMove(3);
50 } else if (j == 2) {
51 cubePos.doMove(2);
52 cubePos.doMove(5);
53 cubePos.doMove(5);
54 cubePos.doMove(5);
55 }
56 // maybe swap over UD axis
57 j = (int) (2 * Math.random());
58 if (j != 0) {
59 cubePos.doMove(0);
60 cubePos.doMove(0);
61 cubePos.doMove(3);
62 cubePos.doMove(3);
63 }
64 // rotate around UD axis
65 j = (int) (4 * Math.random());
66 while (j > 0) {
67 cubePos.doMove(1);
68 cubePos.doMove(4);
69 cubePos.doMove(4);
70 cubePos.doMove(4);
71 j--;
72 }
73
74 // now mix edges
75 j = (int) (4 * Math.random());
76 while (j > 0) {
77 // two 4-cycles of slice edges
78 cubePos.doMove(0);
79 cubePos.doMove(3);
80 cubePos.doMove(3);
81 cubePos.doMove(3);
82 cubePos.doMove(1);
83 cubePos.doMove(4);
84 cubePos.doMove(4);
85 cubePos.doMove(4);
86 cubePos.doMove(2);
87 cubePos.doMove(5);
88 cubePos.doMove(5);
89 cubePos.doMove(5);
90 cubePos.doMove(4);
91 cubePos.doMove(1);
92 cubePos.doMove(1);
93 cubePos.doMove(1);
94 j--;
95 }
96 j = (int) (4 * Math.random());
97 while (j > 0) {
98 // two 4-cycles of slice edges
99 cubePos.doMove(1);
100 cubePos.doMove(4);
101 cubePos.doMove(4);
102 cubePos.doMove(4);
103 cubePos.doMove(2);
104 cubePos.doMove(5);
105 cubePos.doMove(5);
106 cubePos.doMove(5);
107 cubePos.doMove(0);
108 cubePos.doMove(3);
109 cubePos.doMove(3);
110 cubePos.doMove(3);
111 cubePos.doMove(2);
112 cubePos.doMove(2);
113 cubePos.doMove(2);
114 cubePos.doMove(5);
115 j--;
116 }
117 j = (int) (2 * Math.random());
118 if (j != 0) {
119 // 4-H pattern
120 swap(cubePos.cubeletPerm, 12, 14);
121 swap(cubePos.cubeletPerm, 13, 15);
122 }
123 // do face centres
124 j = (int) (4 * Math.random());
125 cubePos.cubeletOri[20] = j;
126 cubePos.cubeletOri[23] = (4 - j) & 3;
127 j = (int) (4 * Math.random());
128 cubePos.cubeletOri[21] = j;
129 cubePos.cubeletOri[24] = (4 - j) & 3;
130 j = (int) (2 * Math.random());
131 cubePos.cubeletOri[22] = j + j;
132 if (cubePos.cubeletPerm[1] == 0 || cubePos.cubeletPerm[3] == 0
199
200 // solve corners
201 // align UD axis
202 if (cubePos.cubeletOri[0] == 1) { // do Fs'
203 cycle(perm, 0, 4, 7, 3);
204 cycle(perm, 1, 5, 6, 2);
205 cycle(perm, 9, 13, 17, 14);
206 cycle(perm, 11, 12, 19, 15);
207 swap(ori, 1, 2);
208 } else if (cubePos.cubeletOri[0] == 2) { // do Rs'
209 cycle(perm, 0, 1, 5, 4);
210 cycle(perm, 3, 2, 6, 7);
211 cycle(perm, 8, 13, 16, 12);
212 cycle(perm, 10, 14, 18, 15);
213 i = ori[0];
214 ori[0] = 1 - ori[2];
215 ori[2] = 1 - i;
216 }
217 // flip UD axis if necessary to bring 0 up
218 if (perm[4] == 0 || perm[5] == 0 || perm[6] == 0 || perm[7] == 0) {
219 // do Fs2
220 swap(perm, 0, 7);
221 swap(perm, 4, 3);
222 swap(perm, 1, 6);
223 swap(perm, 5, 2);
224 swap(perm, 11, 19);
225 swap(perm, 12, 15);
226 swap(perm, 9, 17);
227 swap(perm, 13, 14);
228 }
229 // turn 0 into position
230 while (perm[0] != 0) { // do Us'
231 cycle(perm, 0, 1, 2, 3);
232 cycle(perm, 4, 5, 6, 7);
233 cycle(perm, 8, 9, 10, 11);
234 cycle(perm, 16, 17, 18, 19);
235 swap(ori, 0, 1);
236 }
237 // corners should be solved now.
238 for (i = 0; i < 8; i++)
239 if (perm[i] != i)
240 return (false);
241
242 // solve LR slice
243 if (perm[9] != 9 && perm[11] != 9 && perm[17] != 9 && perm[19] != 9)
244 return (false);
245 while (perm[9] != 9) {
246 cycle(perm, 9, 17, 19, 11);
247 cycle(perm, 12, 13, 14, 15);
248 ori[1] = 1 - ori[1];
249 ori[2] = 1 - ori[2];
250 }
251 if (ori[1] != 0 || perm[11] != 11 || perm[17] != 17 || perm[19] != 19)
252 return (false);
253 // solve FB slice
254 if (perm[8] != 8 && perm[10] != 8 && perm[16] != 8 && perm[18] != 8)
255 return (false);
256 while (perm[8] != 8) {
257 cycle(perm, 8, 16, 18, 10);
258 cycle(perm, 12, 13, 14, 15);
259 ori[0] = 1 - ori[0];
260 ori[2] = 1 - ori[2];
261 }
262 if (ori[0] != 0 || perm[10] != 10 || perm[16] != 16 || perm[18] != 18)
263 return (false);
264 // solve UD slice
397 l++;
398 } while (k != 0);
399
400 }
401
402 // solve a position
403 protected boolean solve() {
404 // do IDA* - search depth first for each maxdepth.
405 while (!search()) {
406 if (wanttostop)
407 return (false);
408 maxdepth++;
409 }
410 return (true);
411 }
412
413 private boolean search() {
414 // do a depth search through all positions at depth maxdepth.
415 // return false if no solution, or break out with true if solved.
416 int m, nxt;
417
418 // do check for solved position with null solution.
419 if (maxdepth == 0 && sollen == 0 && positionlist[0][0] == 0
420 && positionlist[0][1] == 0
421 && positionlist[0][2] == 1 && positionlist[0][3] == 4
422 && (!cubieSettings.superGroup || positionlist[0][4] == 0))
423 return (true);
424
425 while (sollen >= 0) {
426 // at this point positionlist[0..sollen] are visited positions
427 // and solmoves[0..sollen-1] are moves performed.
428 // Note solmoves[sollen] is last tried (rejected) next move
429 nxt = sollen + 1;
430 // add extra quarter turn to last move
431 m = solmoves[sollen];
432 if (m >= 0) { // ignore dummy -1 move
433 positionlist[nxt][0] = transCorn[m][positionlist[nxt][0]];
434 positionlist[nxt][1] = transEdge[m][positionlist[nxt][1]];
435 positionlist[nxt][2] = transEdge[m][positionlist[nxt][2]];
436 positionlist[nxt][3] = transEdge[m][positionlist[nxt][3]];
437 if (cubieSettings.superGroup) {
438 positionlist[nxt][4] = transOri[positionlist[nxt][4]][m];
439 }
440 } else {
441 positionlist[nxt][0] = positionlist[sollen][0];
442 positionlist[nxt][1] = positionlist[sollen][1];
443 positionlist[nxt][2] = positionlist[sollen][2];
444 positionlist[nxt][3] = positionlist[sollen][3];
445 positionlist[nxt][4] = positionlist[sollen][4];
446 }
447 solamount[sollen]++;
448 // if done full turn, then move to next face
449 if (solamount[sollen] > 3) {
450 // next face, 0 turns yet
451 solamount[sollen] = 0;
452 do {
453 solmoves[sollen]++;
454 } while (sollen != 0 && solmoves[sollen] == solmoves[sollen - 1]);
455 if (solmoves[sollen] >= 3) {
456 // done all faces. backtrack
457 sollen--;
458 continue;
459 }
460 continue; // loop back to do a quarter turn of this new face
461 }
462
1 package solver.solverJS.algorithm;
2
3 // ----- Solver for the Square group ----
4 import java.awt.event.*;
5
6 public final class SolverSquare extends Solver {
7 int transEdge[][][];
8 int transCorn[][];
9 int transCorn2[][];
10 byte pruneEdge[][][];
11 byte pruneCorn[];
12 byte pruneCorn2[];
13 int maxdepth; // current search depth
14 final int orbits[][] = {
15 // UR,DR,DL,UL RB,RF,LF,LB UF,DF,DB,UB
16 { 8, 16, 18, 10 }, { 12, 13, 14, 15 }, { 9, 17, 19, 11 },
17 // UBR,UFL,DFR,DBL, URF,ULB,DRB,DLF
18 { 0, 2, 5, 7 }, { 1, 3, 4, 6 } };
19
20 public SolverSquare(ActionListener m) {
21 super(m);
22 }
23
24 public MoveSequence getGenerator() {
25 int[] a = new int[sollen];
26 for (int i = 0; i < sollen; i++) {
27 a[i] = 2;
28 }
29 return (new MoveSequence(sollen, solmoves, a));
30 }
31
32 public void mix(CubePosition cubePos) {
33 int i, j;
34 // direct method, not random moves
35 cubePos.reset();
36 // put random corner at position 2
37 j = (int) (4 * Math.random());
38 if (j != 3) {
39 cubePos.doMove(j);
40 cubePos.doMove(j);
41 }
42 // put random corner at 5
43 j = (int) (3 + 3 * Math.random());
44 if (j != 5) {
45 cubePos.doMove(j);
46 cubePos.doMove(j);
47 }
48 // put random corner at 0/7
49 j = (int) (2 * Math.random());
50 if (j != 0) {
51 cubePos.doMove(5);
52 cubePos.doMove(5);
53 }
54 // randomly twist other tetrad
55 j = (int) (4 * Math.random());
56 if (j == 0) {
57 cubePos.doMove(2);
58 cubePos.doMove(2);
59 cubePos.doMove(3);
60 cubePos.doMove(3);
61 cubePos.doMove(1);
62 cubePos.doMove(1);
63 cubePos.doMove(3);
64 cubePos.doMove(3);
65 } else if (j == 1) {
66 cubePos.doMove(3);
67 cubePos.doMove(3);
68 cubePos.doMove(1);
69 cubePos.doMove(1);
70 cubePos.doMove(2);
71 cubePos.doMove(2);
72 cubePos.doMove(1);
73 cubePos.doMove(1);
74 } else if (j == 2) {
75 cubePos.doMove(1);
76 cubePos.doMove(1);
77 cubePos.doMove(2);
78 cubePos.doMove(2);
79 cubePos.doMove(3);
80 cubePos.doMove(3);
81 cubePos.doMove(2);
82 cubePos.doMove(2);
83 }
84 // corners are now in place.
85 // randomly place edges
86 int order[] = new int[4];
87 for (i = 0; i < 3; i++) {
88 num2perm(order, 0, 4, (int) (4 * Math.random()));
89 for (j = 0; j < 4; j++) {
90 cubePos.cubeletPerm[orbits[i][j]] = orbits[i][order[j]];
91 }
92 }
93 // ensure edges have even permutation
94 if (parityOdd(cubePos.cubeletPerm, 8, 12)) {
95 // swap two edges to fix it.
96 swap(cubePos.cubeletPerm, 8, 10);
97 }
98
99 // convert orbits
100 int perm[] = new int[20];
101 int k, c = 0;
102 for (i = 0; i < 5; i++) {
103 for (j = 0; j < 4; j++) {
104 for (k = 0; k < 4; k++) {
105 if (cubePos.cubeletPerm[orbits[i][j]] == orbits[i][k])
106 break;
107 }
108 perm[c++] = k;
109 }
110 }
111
112 // do face centres. First ensure solvable
113 j = 0;// 210:LUF
114 for (i = 0; i < 6; i++)
115 cubePos.cubeletOri[20 + i] = 0;
116 if (parityOdd(perm, 12, 4))
117 j ^= 7;
118 if (parityOdd(perm, 0, 4))
119 j ^= 6;
120 if (parityOdd(perm, 4, 4))
121 j ^= 5;
122 if (parityOdd(perm, 8, 4))
123 j ^= 3;
124 if ((j & 4) != 0)
125 cubePos.cubeletOri[20] = 2;
126 if ((j & 2) != 0)
127 cubePos.cubeletOri[21] = 2;
128 if ((j & 1) != 0)
129 cubePos.cubeletOri[22] = 2;
130
131 // randomize face centres
132 j = (int) (8 * Math.random());
199 if (j != 0)
200 return (false);
201 }
202
203 // convert to numbers
204 int newpos[] = new int[4];
205 newpos[0] = perm2num(perm, 0, 4);
206 newpos[1] = perm2num(perm, 4, 4);
207 newpos[2] = perm2num(perm, 8, 4);
208 newpos[3] = perm2num(perm, 12, 4);
209 for (k = 0; k < 4; k++) {
210 if (cubePos.cubeletPerm[orbits[4][k]] == orbits[4][0])
211 break;
212 }
213 newpos[3] = newpos[3] * 4 + k;
214 if (cubieSettings.superGroup) {
215 j = 0;
216 if (cubePos.cubeletOri[20] != 0)
217 j ^= 4;
218 if (cubePos.cubeletOri[21] != 0)
219 j ^= 2;
220 if (cubePos.cubeletOri[22] != 0)
221 j ^= 1;
222 newpos[3] = (newpos[3] << 3) + j;
223 }
224
225 // do permutations to solve corners.
226
227 // solve corner 0 of first orbit
228 if (perm[13] == 0) {
229 swap(perm, 12, 13);
230 swap(perm, 14, 15);
231
232 } else if (perm[14] == 0) {
233 swap(perm, 12, 14);
234 swap(perm, 13, 15);
235 } else if (perm[15] == 0) {
236 swap(perm, 12, 15);
237 swap(perm, 13, 14);
238 }
239 // solve corner 1 of first orbit
240 if (perm[14] == 1) { // F
241 swap(perm, 13, 14);
242 swap(perm, 16, 19);
243 } else if (perm[15] == 1) { // L
244 swap(perm, 13, 15);
245 swap(perm, 17, 19);
246 }
247 // solve corners 2,3 of first orbit
248 // UBR,UFL,DFR,DBL, URF,ULB,DRB,DLF
249 if (perm[15] == 2) { // D
250 swap(perm, 14, 15);
251 swap(perm, 18, 19);
252 }
253 // solve corners 0 of second orbit
254 // UBR,UFL,DFR,DBL, URF,ULB,DRB,DLF
255 if (perm[17] == 0) {
256 swap(perm, 16, 17);
257 swap(perm, 18, 19);
258 } else if (perm[18] == 0) {
259 swap(perm, 16, 18);
260 swap(perm, 17, 19);
261 } else if (perm[19] == 0) {
262 swap(perm, 16, 19);
263 swap(perm, 17, 18);
264 }
397 }
398 }
399 for (i = 0; i < 96; i++) { // each corner position
400 for (m = 0; m < 6; m++) { // each move
401 transCorn[i][m] = gettransCorn(i, m);
402 }
403 }
404 for (i = 0; i < 768; i++) { // each corner position
405 for (m = 0; m < 6; m++) { // each move
406 transCorn2[i][m] = gettransCorn2(i, m);
407 }
408 }
409
410 // calculate pruning tables. First corners
411 int l = 1;
412 pruneCorn[0] = 1;
413 do {
414 k = 0;
415 for (i = 0; i < 96; i++) {
416 if (pruneCorn[i] == l) {
417 for (m = 0; m < 6; m++) {
418 if (pruneCorn[transCorn[i][m]] == 0) {
419 pruneCorn[transCorn[i][m]] = (byte) (l + 1);
420 k++;
421 }
422 }
423 }
424 }
425 l++;
426 } while (k != 0);
427 // calculate pruning tables. First corners
428 l = 1;
429 pruneCorn2[0] = 1;
430 do {
431 k = 0;
432 for (i = 0; i < 768; i++) {
433 if (pruneCorn2[i] == l) {
434 for (m = 0; m < 6; m++) {
435 if (pruneCorn2[transCorn2[i][m]] == 0) {
436 pruneCorn2[transCorn2[i][m]] = (byte) (l + 1);
437 k++;
438 }
439 }
440 }
441 }
442 l++;
443 } while (k != 0);
444
445 // Now edge pruning table
446 l = 1;
447 int i2, i3;
448 pruneEdge[0][0][0] = 1;
449 do {
450 k = 0;
451 for (i = 0; i < 24; i++) {
452 for (i2 = 0; i2 < 24; i2++) {
453 for (i3 = 0; i3 < 24; i3++) {
454 if (pruneEdge[i][i2][i3] == l) {
455 for (m = 0; m < 6; m++) {
456 if (pruneEdge[transEdge[0][i][m]][transEdge[1][i2][m]]
457 [transEdge[2][i3][m]] == 0) {
458 pruneEdge[transEdge[0][i][m]][transEdge[1][i2][m]]
459 [transEdge[2][i3][m]] = (byte) (l + 1);
460 k++;
461 }
462 }
463 }
464 }
465 }
466 }
467 l++;
468 } while (k != 0);
469 }
470
471 private int gettransEdge(int slice, int pos, int m) {
472 // convert pos number into permutation
473 // UR,DR,DL,UL RB,RF,LF,LB UF,DF,DB,UB
474 int edges[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
475 num2perm(edges, slice * 4, 4, pos);
476 // do move L U F R D B Lc Uc Fc
477 if (m == 0) {
478 swap(edges, 2, 3);
479 swap(edges, 6, 7);
480 } else if (m == 1) {
481 swap(edges, 0, 3);
482 swap(edges, 8, 11);
483 } else if (m == 2) {
484 swap(edges, 5, 6);
485 swap(edges, 8, 9);
486 } else if (m == 3) {
487 swap(edges, 0, 1);
488 swap(edges, 4, 5);
489 } else if (m == 4) {
490 swap(edges, 1, 2);
491 swap(edges, 9, 10);
492 } else if (m == 5) {
493 swap(edges, 4, 7);
494 swap(edges, 10, 11);
495 }
496 // convert back to number
497 return (perm2num(edges, slice * 4, 4));
498 }
499
500 private int gettransCorn(int pos, int m) {
501 // convert pos number into permutation
502 // UBR,UFL,DFR,DBL, URF,ULB,DRB,DLF
503 int corners[] = { 0, 1, 2, 3, 0, 0, 0, 0 };
504 num2perm(corners, 0, 4, pos >> 2);
505 corners[4 + (pos & 3)] = 1;
506 // do move L U F R D B Lc Uc Fc
507 if (m == 0) {
508 swap(corners, 1, 3);
509 swap(corners, 5, 7);
510 } else if (m == 1) {
511 swap(corners, 0, 1);
512 swap(corners, 4, 5);
513 } else if (m == 2) {
514 swap(corners, 1, 2);
515 swap(corners, 4, 7);
516 } else if (m == 3) {
517 swap(corners, 0, 2);
518 swap(corners, 4, 6);
519 } else if (m == 4) {
520 swap(corners, 2, 3);
521 swap(corners, 6, 7);
522 } else if (m == 5) {
523 swap(corners, 0, 3);
524 swap(corners, 5, 6);
525 }
526 // convert back to number
527 return (perm2num(corners, 0, 4) * 4 + corners[5]
528 + corners[6] * 2 + corners[7] * 3);
529 }
530
531 private int gettransCorn2(int pos, int m) {
532 int c;
533 // convert pos number into permutation
534 // UBR,UFL,DFR,DBL, URF,ULB,DRB,DLF
535 int corners[] = { 0, 1, 2, 3, 0, 0, 0, 0 };
536 num2perm(corners, 0, 4, pos >> 5);
537 corners[4 + ((pos >> 3) & 3)] = 1;
538 c = pos & 7;
539 // do move L U F R D B Lc Uc Fc
540 if (m == 0) {
541 swap(corners, 1, 3);
542 swap(corners, 5, 7);
543 c ^= 4;
544 } else if (m == 1) {
545 swap(corners, 0, 1);
546 swap(corners, 4, 5);
547 c ^= 2;
548 } else if (m == 2) {
549 swap(corners, 1, 2);
550 swap(corners, 4, 7);
551 c ^= 1;
552 } else if (m == 3) {
553 swap(corners, 0, 2);
554 swap(corners, 4, 6);
555 } else if (m == 4) {
556 swap(corners, 2, 3);
557 swap(corners, 6, 7);
558 } else if (m == 5) {
559 swap(corners, 0, 3);
560 swap(corners, 5, 6);
561 }
562 // convert back to number
563 return ((perm2num(corners, 0, 4) << 5)
564 + ((corners[5] + corners[6] * 2 + corners[7] * 3) << 3) + c);
565 }
566 }
1 package solver.solverJS.algorithm;
2
3 // ----- Solver for the Two-Generator group ----
4 import java.awt.event.*;
5
6 public final class SolverTwoGen extends Solver {
7 int maxdepth; // current search depth
8 int transCorn[][];
9 int transEdge[][];
10 int transOri[][];
11 int transOri2[][];
12 byte pruneCorn[];
13 byte pruneEdge[];
14 byte pruneOri[];
15 byte pruneOri2[];
16
17 public SolverTwoGen(ActionListener m) {
18 super(m);
19 }
20
21 public MoveSequence getGenerator() {
22 int[] m = new int[sollen];
23 for (int i = 0; i < sollen; i++) {
24 m[i] = solmoves[i] * 2 + 1;
25 }
26 return (new MoveSequence(sollen, m, solamount));
27 }
28
29 public void mix(CubePosition cubePos) {
30 int i, j;
31 // direct method, not random moves
32 cubePos.reset();
33 // first mix corners
34 // corner 5
35 j = (int) (6 * Math.random());
36 if (j == 4)
37 cubePos.doMove(3);
38 else if (j < 4) {
39 while (j > 0) {
40 cubePos.doMove(1);
41 j--;
42 }
43 cubePos.doMove(3);
44 cubePos.doMove(3);
45 }
46 // corner 4
47 j = (int) (5 * Math.random());
48 if (j < 4) {
49 while (j > 0) {
50 cubePos.doMove(1);
51 j--;
52 }
53 cubePos.doMove(3);
54 cubePos.doMove(3);
55 cubePos.doMove(3);
56 cubePos.doMove(1);
57 cubePos.doMove(3);
58 }
59 // corners 0-3
60 j = (int) (4 * Math.random());
61 while (j > 0) {
62 cubePos.doMove(1);
63 j--;
64 }
65
66 // corner orientation
265 p = transEdge[p][m];
266 if (pruneEdge[p] == 0) {
267 pruneEdge[p] = (byte) (l + 1);
268 k++;
269 }
270 }
271 }
272 }
273 }
274 l++;
275 } while (k != 0);
276
277 // Now corner pruning table
278 l = 1;
279 pruneCorn[0] = 1;
280 do {
281 k = 0;
282 for (i = 0; i < 720; i++) {
283 if (pruneCorn[i] == l) {
284 for (m = 0; m < 2; m++) {
285 p = i;
286 for (q = 0; q < 3; q++) {
287 p = transCorn[p][m];
288 if (pruneCorn[p] == 0) {
289 pruneCorn[p] = (byte) (l + 1);
290 k++;
291 }
292 }
293 }
294 }
295 }
296 l++;
297 } while (k != 0);
298
299 // Now corner orientation pruning table
300 l = 1;
301 pruneOri[0] = 1;
302 do {
303 k = 0;
304 for (i = 0; i < 243; i++) {
305 if (pruneOri[i] == l) {
306 for (m = 0; m < 2; m++) {
307 p = i;
308 for (q = 0; q < 3; q++) {
309 p = transOri[p][m];
310 if (pruneOri[p] == 0) {
311 pruneOri[p] = (byte) (l + 1);
312 k++;
313 }
314 }
315 }
316 }
317 }
318 l++;
319 } while (k != 0);
320 // Now corner+centre orientation pruning table
321 l = 1;
322 pruneOri2[0] = 1;
323 do {
324 k = 0;
325 for (i = 0; i < 3888; i++) {
326 if (pruneOri2[i] == l) {
327 for (m = 0; m < 2; m++) {
328 p = i;
329 for (q = 0; q < 3; q++) {
330 p = transOri2[p][m];
331 if (pruneOri2[p] == 0) {
332 pruneOri2[p] = (byte) (l + 1);
333 k++;
334 }
335 }
336 }
337 }
338 }
339 l++;
340 } while (k != 0);
341 }
342
343 private int gettransEdge(int pos, int m) {
344 // convert pos number into edge permutation
345 int edges[] = new int[7];
346 num2perm(edges, 0, 7, pos);
347 // do move U,R
348 if (m == 0) {// U
349 cycle(edges, 0, 3, 2, 1);
350 } else if (m == 1) { // R
351 cycle(edges, 0, 5, 6, 4);
352 }
353 // convert back to number
354 return (perm2num(edges, 0, 7));
355 }
356
357 private int gettransCorn(int pos, int m) {
358 // convert pos number into corner permutation
359 int corn[] = new int[6];
360 num2perm(corn, 0, 6, pos);
361 // do move U,R
362 if (m == 0) {// U
363 cycle(corn, 0, 3, 2, 1);
364 } else if (m == 1) { // R
365 cycle(corn, 0, 1, 5, 4);
366 }
367 // convert back to number
368 return (perm2num(corn, 0, 6));
369 }
370
371 private int gettransOri(int pos, int m) {
372 // convert pos number into permutation
373 int corn[] = new int[6];
374 num2ori(corn, 0, 6, 3, pos);
375
376 // do move L U F R D B
377 if (m == 0) {// U
378 cycle(corn, 0, 3, 2, 1);
379 } else if (m == 1) { // R
380 cycle(corn, 0, 1, 5, 4);
381 corn[0] += 2;
382 corn[1]++;
383 corn[5] += 2;
384 corn[4]++;
385 }
386 // convert back to number
387 return (ori2num(corn, 0, 6, 3));
388 }
389
390 private int gettransOri2(int pos, int m) {
391 // convert pos number into permutation
392 int corn[] = new int[8];
393 num2ori(corn, 0, 6, 3, pos >> 4);
394 corn[6] = pos & 3;
395 corn[7] = (pos >> 2) & 3;
396
397 // do move L U F R D B
398 if (m == 0) {// U
399 cycle(corn, 0, 3, 2, 1);
400 corn[6] = (corn[6] + 3) & 3;
401 } else if (m == 1) { // R
402 cycle(corn, 0, 1, 5, 4);
403 corn[0] += 2;
404 corn[1]++;
405 corn[5] += 2;
406 corn[4]++;
407 corn[7] = (corn[7] + 3) & 3;
408 }
409 // convert back to number
410 return ((ori2num(corn, 0, 6, 3) << 4) + (corn[7] << 2) + corn[6]);
411 }
412
413 // solve a position
414 protected boolean solve() {
415 // do IDA* - search depth first for each maxdepth.
416 while (!search()) {
417 if (wanttostop)
418 return (false);
419 maxdepth++;
420 }
421 return (true);
422 }
423
424 private boolean search() {
425 // do a depth search through all positions at depth maxdepth.
426 // return false if no solution, or break out with true if solved.
427 int m, nxt;
428
429 // do check for solved position with null solution.
430 if (maxdepth == 0 && sollen == 0 && positionlist[0][0] == 0 && positionlist[0][1] == 0
431 && positionlist[0][2] == 0)
432 return (true);
433
434 while (sollen >= 0) {
435 // at this point positionlist[0..sollen] are visited positions
436 // and solmoves[0..sollen-1] are moves performed.
437 // Note solmoves[sollen] is last tried (rejected) next move
438 nxt = sollen + 1;
439 // add extra half turn to last move
440 m = solmoves[sollen];
441 if (m >= 0) { // ignore dummy -1 move
442 positionlist[nxt][0] = transCorn[positionlist[nxt][0]][m];
443 positionlist[nxt][1] = transEdge[positionlist[nxt][1]][m];
444 if (cubieSettings.superGroup) {
445 positionlist[nxt][2] = transOri2[positionlist[nxt][2]][m];
446 } else {
447 positionlist[nxt][2] = transOri[positionlist[nxt][2]][m];
448 }
449 } else {
450 positionlist[nxt][0] = positionlist[sollen][0];
451 positionlist[nxt][1] = positionlist[sollen][1];
452 positionlist[nxt][2] = positionlist[sollen][2];
453 }
454 solamount[sollen]++;
455 // if done full turn, then move to next face
456 if (solamount[sollen] > 3) {
457 // next face, 0 turns yet
458 solamount[sollen] = 0;
459 do {
460 solmoves[sollen]++;
461 } while (sollen != 0 && solmoves[sollen] == solmoves[sollen - 1]);
462 if (solmoves[sollen] >= 2) {
67 JCheckBox normal;
68 JCheckBox square;
69 JCheckBox slice;
70 JCheckBox antiSlice;
71 JCheckBox twogenerator;
72
73 // CheckboxGroup cubeGroup = new CheckboxGroup();
74 ButtonGroup buttonGroup1;
75
76 JCheckBox groupRadioBox[];
77
78 Solver solvers[] = { new SolverKociemba(this), new SolverSquare(this),
79 new SolverSlice(this), new SolverAntiSlice(this), new SolverTwoGen(this) };
80
81 JCheckBox symTwoColBox;
82 SymButton symButton[];
83 SymButton symAllImage;
84 SymButton symCurrentImage;
85 JButton symResetBut;
86
87 Color colors[] = { new Color(255, 0, 0), // unprepared
88 new Color(192, 192, 192), // prepared, ready, controls background color
89 new Color(0, 255, 0), // Running solver
90 new Color(160, 160, 160), // viewer background color
91 };
92 boolean solution = true;
93 boolean symTwoCol = false;
94 MoveSequence generator;
95 int seqPos = 0;
96 boolean playFw = true;
97 boolean moveInProgress = false;
98
99 private boolean t;
100
101 // applet control
102 boolean isPlaying = false;
103
104 public Cubie(BorderLayout bdrl, CBTHSettingsList cbthsl) {
105 super(bdrl);
106
107 this.cbthsl = cbthsl;
108
109 rightPanel = new JPanel();
110
111 mixBut = cbthsl.createJButton("Mix", "Scrambles cube at random", this);
112 mixBut.setOpaque(true);
113 mixBut.setBackground(colors[3]);
114 resetBut = cbthsl.createJButton("Reset", "Resets the cube-configuration.", this);
115 resetBut.setOpaque(true);
116 resetBut.setBackground(colors[3]);
117 editBut = cbthsl.createJButton("Edit",
118 "User can graphically edit the cube, disclaimer: changes are NOT reflected in rest of
119 CubeThesis.",
120 this);
121 editBut.setOpaque(true);
122 editBut.setBackground(colors[3]);
123 solveBut = cbthsl.createJButton("Solve",
124 "Solves the current cube-configuration with selected solver.", this);
125 solveBut.setOpaque(true);
126 solveBut.setBackground(colors[3]);
127
128 viewBut = cbthsl.createJButton("Change view",
129 "Press, to choose different cube visualization.", this);
130 viewBut.setOpaque(true);
131 viewBut.setBackground(colors[3]);
132 viewResetBut = cbthsl.createJButton("Reset view",
133 "Resets the view angle in case 3D view was selected.", this);
134 viewResetBut.setOpaque(true);
135 viewResetBut.setBackground(colors[3]);
136
137 solPlayContr = new JPanel();
138 boxPanel = new JPanel(new BorderLayout());
139 solverPanel = new JPanel(new BorderLayout());
140 gensolBut = cbthsl.createJButton("Solution",
141 "Toggle to switch between generating or solving sequence.", this);
142 textBox = cbthsl.createJTextField("", true, null);
143 textBox.setHorizontalAlignment(JTextField.LEFT);
144
145 playBut = new JButton();
146 revBut = new JButton();
147 stepBut = new JButton();
148 backBut = new JButton();
149 endBut = new JButton();
150 beginBut = new JButton();
151
152 groupCheckBox = new JCheckBox[NUMGROUPS];
153 superBox = cbthsl.createJCheckBox("Supergroup", false, null);
154
155 normal = cbthsl.createJCheckBox("Normal - Kociemba", true, null);
156 square = cbthsl.createJCheckBox("Square", false, null);
157 slice = cbthsl.createJCheckBox("Slice", false, null);
158 antiSlice = cbthsl.createJCheckBox("Anti-Slice", false, null);
159 twogenerator = cbthsl.createJCheckBox("2-generator", false, null);
160
161 buttonGroup1 = new ButtonGroup();
162
163 symTwoColBox = cbthsl.createJCheckBox("2 col.", false,
164 "Restrict generator to only two colors per face.");
165 symButton = new SymButton[29];
166 symAllImage = new SymButton(null, 0);
167 symCurrentImage = new SymButton(null, 0);
168 symResetBut = cbthsl.createJButton("Clear", "Clears the selected symmetry.", this);
169
170 this.init();
171 }
172
173 public void init() {
174 int i;
175
176 final int vw = VIEWWIDTH, vh = VIEWHEIGHT;
177
178 // build main applet panel
179
180 setBackground(colors[3]);
181
182 for (i = 0; i < NUMVIEWS; i++) {
183 boxPanel.add(cubeViewers[i], BorderLayout.CENTER);
184 cubeViewers[i].setBounds(0, 0, vw, vh);
185 cubeViewers[i].setVisible(i == 0);
186 cubeViewers[i].setBackground(colors[3]);
187 cubeViewers[i].setOpaque(false);
188 }
189
190 boxPanel.setPreferredSize(new Dimension(VIEWWIDTH, VIEWHEIGHT));
191
192 this.solPlayContr.setLayout(new GridLayout(1, 6));
193
194 // build right panel
195 rightPanel.setLayout(new BorderLayout());
196 rightPanel.setBackground(colors[3]);
197 rightPanel.setOpaque(true);
198
331 updateStatus(false);
332
333 }
334
335 public void stop() {
336 // tell thread to stop
337 if (isPlaying) {
338 isPlaying = false;
339 while (moveInProgress) {
340 try {
341 Thread.sleep(50);
342 } catch (Exception ignored) {
343 }
344 }
345 cubieSettings.lockViewer = false;
346 }
347 }
348
349 public void run() {
350 int f, q;
351 isPlaying = true;
352 cubieSettings.lockViewer = true;
353 do {
354 if (playFw) {
355 f = generator.getMoves()[seqPos];
356 q = generator.getAmount()[seqPos];
357 if (cubeViewers[viewer].showMove(f, q)) {
358 moveInProgress = (viewer == 0);
359 seqPos++;
360 }
361 if (seqPos >= generator.getLength())
362 isPlaying = false;
363 } else {
364 seqPos--;
365 f = generator.getMoves()[seqPos];
366 q = generator.getAmount()[seqPos];
367 if (!cubeViewers[viewer].showMove(f, 4 - q)) {
368 seqPos++;
369 } else {
370 moveInProgress = (viewer == 0);
371 }
372 if (seqPos <= 0)
373 isPlaying = false;
374 }
375
376 textBox.setText(generator.toString(solution, seqPos));
377 if (isPlaying) {
378 try {
379 Thread.sleep(500);
380 } catch (Exception ignored) {
381 }
382 do {
383 try {
384 Thread.sleep(50);
385 } catch (Exception ignored) {
386 }
387 } while (moveInProgress);
388 }
389 } while (isPlaying);
390 cubieSettings.lockViewer = false;
391 }
392
393 private void updateStatus(boolean changed) {
394 // Update status of current tab and solver buttons
395 if (tabSet.getSelectedIndex() == 0) {
396 boolean currentSolvable = false;
463
464 public void actionPerformed(ActionEvent e) {
465 int i;
466 Object src = e.getSource();
467 if (src == mixBut) {
468 if (!cubieSettings.solving) {
469 stop();// stop any animation
470 if (tabSet.getSelectedIndex() == 0) {
471 // Mixing can happen, based on what the selected solver can solve:
472 solvers[cubieSettings.group].mix(cubieSettings.cubePos);
473 } else {
474 // Mixing a cubestate can also be restricted by symmetry-condiditons,
475 // on tabpanel [Symmetry].
476 cubieSettings.cubePos.mix(symType, cubieSettings.superGroup, symTwoCol);
477 }
478 setSequencePosition(-1);
479 updateStatus(true);
480 cubeViewers[viewer].repaint();
481 }
482 } else if (src == resetBut) {
483 if (!cubieSettings.solving) {
484 stop();// stop any animation
485 cubieSettings.cubePos.reset();
486 setSequencePosition(-1);
487 updateStatus(true);
488 cubeViewers[viewer].repaint();
489 }
490 } else if (src == solveBut) {
491 stop();// stop any animation
492 solve();
493 } else if (src == gensolBut) {
494 solution = !solution;
495 gensolBut.setText(solution ? "Solution" : "Generator");
496 if (generator == null) {
497 textBox.setText("");
498 } else {
499 textBox.setText(generator.toString(solution, seqPos));
500 }
501 } else if (src == viewBut) {
502 viewer++;
503 if (viewer >= NUMVIEWS)
504 viewer = 0;
505 for (i = 0; i < NUMVIEWS; i++) {
506 cubeViewers[i].setVisible(i == viewer);
507 }
508 } else if (src == viewResetBut) {
509 cubieSettings.cubePos.resetView();
510 for (i = 0; i < NUMVIEWS; i++) {
511 cubeViewers[i].reset();
512 }
513 updateStatus(false);
514 } else if (src == editBut) {
515 cubieSettings.edit = !cubieSettings.edit;
516 editBut.setText(cubieSettings.edit ? "Play" : "Edit");
517 seqPos = -1;
518 } else if (src == textBox) {
519 // change focus, forcing focus event to be processed
520 groupRadioBox[cubieSettings.group].requestFocus();
521 } else if (src == beginBut) {
522 viewerBackToBegin();
523 } else if (src == backBut) {
524 if (solution)
525 stepForward();
526 else
527 stepBackward();
528 } else if (src == revBut) {
529 if (solution)
530 playForward();
531 else
532 playBackward();
533 } else if (src == playBut) {
534 if (solution)
535 playBackward();
536 else
537 playForward();
538 } else if (src == stepBut) {
539 if (solution)
540 stepBackward();
541 else
542 stepForward();
543 } else if (src == endBut) {
544 stop();
545 setSequencePosition((generator == null || solution)
546 ? 0 : generator.getLength());
547 cubeViewers[viewer].repaint();
548 } else if (src == symResetBut) {
549 // reset all buttons
550 for (i = 0; i < 29; i++)
551 symButton[i].setPressed(false);
552 symType = 0;
553 symAllImage.setType(symType);
554 } else if (src == tabSet) {
555 updateStatus(true);
556 } else {
557 // check for viewer actions
558 for (i = 0; i < NUMVIEWS; i++) {
559 if (src == cubeViewers[i]) {
560 updateStatus(true);
561 if (e.getActionCommand() == "user") {
562 seqPos = -1;
563 if (generator != null)
564 textBox.setText(generator.toString(solution, seqPos));
565 } else {
566 moveInProgress = false;
567 }
568 return;
569 }
570 }
571
572 /*
573 * check for solver actions: 0 = a Initialisation done 1 = b Solution
574 * found 2 = c Solver aborted by user 3 = d Solver finished, no solution
575 * found 4 = e Solver is solving
576 */
577
578 for (i = 0; i < NUMGROUPS; i++) {
579 if (src == solvers[i]) {
580 String nameSolver = solvers[i].getClass().getSimpleName();
581 switch (e.getActionCommand()) {
582 case "a":
583 /*
584 * System.out.println(Solver \""+nameSolver+"\" was initialized.");
585 */cubieSettings.lastOutputSolver = 0;
586 break;
587 case "b":
588 stoppedSolving();
589 System.out.println("Solver [" + nameSolver + "]: Solution found!");
590 generator = cubieSettings.generator;
591
592 // Line below was commented so the available solution will not be
593 // directly reset after finding it;
594 // cubieSettings.generator=null;
595
596 seqPos = generator.getLength();
597 textBox.setText(generator.toString(solution, seqPos));
598 cubieSettings.cubePos.doSequence(generator);
599
600 cubieSettings.lastOutputSolver = 1;
601 break;
602 case "c":
603 stoppedSolving();
604 System.out.println("Solver [" + nameSolver + "]: Was cancelled.");
605 cubieSettings.lastOutputSolver = 2;
606 break; // aborted solve
607 case "d":
608 stoppedSolving();
609 System.out.println("Solver [" + nameSolver
610 + "]: Stopped abruptly. It is likely that this "
611 + "solver won't achieve any shorter solution.");
612 cubieSettings.lastOutputSolver = 3;
613 break; // ended solve
614 case "e":
615 System.out.println("Solver [" + nameSolver + "]: Started...");
616 cubieSettings.lastOutputSolver = 4;
617 break; // started solve
618 }
619
620 updateStatus(false);
621 return;
622 }
623 }
624
625 // check for symbutton actions
626 for (i = 0; i < 29; i++) {
627 if (src == symButton[i]) {
628 if (e.getActionCommand() != "") { // perform ref/rot
629 if (!cubieSettings.lockViewer) {
630 if (seqPos >= 0 && generator != null) {
631 generator.doSym(i);
632 textBox.setText(generator.toString(solution, seqPos));
633 }
634 cubieSettings.cubePos.doSym(i, e.getActionCommand() == "c");
635 updateStatus(true);
636 cubeViewers[viewer].repaint();
637 }
638 } else {
639 if (!symButton[i].isPressed()) {
640 symType |= 1 << i;
641 symButton[i].setPressed(true);
642 } else {
643 symType &= ~(1 << i);
644 symButton[i].setPressed(false);
645 }
646 symAllImage.setType(symType);
647 }
648 return;
649 }
650 }
651 }
652 }
653
654 // enable all buttons
655 void stoppedSolving() {
656 cubieSettings.lockViewer = false;
657 textBox.setEnabled(true);
658 mixBut.setEnabled(true);
659 resetBut.setEnabled(true);
660 superBox.setEnabled(true);
661
662 playBut.setEnabled(true);
663 revBut.setEnabled(true);
664 stepBut.setEnabled(true);
665 backBut.setEnabled(true);
666 endBut.setEnabled(true);
667 beginBut.setEnabled(true);
668 }
669
670 // disable all buttons
671 void startSolving() {
672 cubieSettings.lockViewer = true;
673 textBox.setEnabled(false);
674 mixBut.setEnabled(false);
675 resetBut.setEnabled(false);
676 superBox.setEnabled(false);
677
678 playBut.setEnabled(false);
679 revBut.setEnabled(false);
680 stepBut.setEnabled(false);
681 backBut.setEnabled(false);
682 endBut.setEnabled(false);
683 beginBut.setEnabled(false);
684 }
685
686 private void stepForward() {
687 if (isPlaying) {
688 stop();
689 } else if (generator != null && seqPos < generator.getLength()) {
690 if (seqPos < 0)
691 setSequencePosition(0);
692 int f = generator.getMoves()[seqPos];
693 int q = generator.getAmount()[seqPos];
694 if (cubeViewers[viewer].showMove(f, q))
695 seqPos++;
696 textBox.setText(generator.toString(solution, seqPos));
697 }
698 }
699
700 public void stepBackward() {
701 if (isPlaying) {
702 stop();
703 } else if (generator != null) {
704 if (seqPos < 0)
705 setSequencePosition(generator.getLength());
706 if (seqPos > 0) {
707 seqPos--;
708 int f = generator.getMoves()[seqPos];
709 int q = generator.getAmount()[seqPos];
710 if (!cubeViewers[viewer].showMove(f, 4 - q))
711 seqPos++;
712 textBox.setText(generator.toString(solution, seqPos));
713 }
714 }
715 }
716
717 private void playForward() {
718 if (isPlaying) {
719 stop();
720 } else if (generator != null && seqPos < generator.getLength()) {
721 if (seqPos < 0)
722 setSequencePosition(0);
723 playFw = true;
724 new Thread(this).start();
725 }
726 }
727
728 private void playBackward() {
729 if (isPlaying) {
730 stop();
731 } else if (generator != null) {
732 if (seqPos < 0)
733 setSequencePosition(generator.getLength());
734 if (seqPos > 0) {
735 playFw = false;
736 new Thread(this).start();
737 }
738 }
739 }
740
741 private void setSequencePosition(int p) {
742 if (generator == null) {
743 textBox.setText("");
744 seqPos = -1;
745 } else {
746 if (p > generator.getLength())
747 p = generator.getLength();
748 seqPos = p;
749 if (p >= 0)
750 cubieSettings.cubePos.doSequence(generator, p);
751 textBox.setText(generator.toString(solution, seqPos));
752 updateStatus(true);
753 }
754 }
755
756 public void itemStateChanged(ItemEvent e) {
757 int i;
758 Object src = e.getSource();
759 if (src == superBox) {
760 cubieSettings.superGroup = !cubieSettings.superGroup;
761 // now set box to reflect actual choice of group
762 superBox.setSelected(cubieSettings.superGroup);
763 // update group solvability flags
764 updateStatus(true);
765 // update view
766 cubeViewers[viewer].repaint();
767 return;
768 } else if (src == symTwoColBox) {
769 symTwoCol = !symTwoCol;
770 // set box to reflect actual choice
771 symTwoColBox.setSelected(symTwoCol);
772 return;
773 }
774 for (i = 0; i < NUMGROUPS; i++) {
775 if (src == groupRadioBox[i]) {
776 cubieSettings.group = i;
777 // now set box to reflect actual choice of group
778
779 // OPGELET: dit nog aanpassen!!
780 // cubeGroup.setSelectedCheckbox(groupRadioBox[cubieSettings.group]);
781 // update (group solvability flags and) solve button
782 updateStatus(false);
783 return;
784 }
785 }
786 }
787
788 public void focusLost(FocusEvent e) {
789 Object src = e.getSource();
790 if (src == textBox) {
791 textChanged();
792 }
793 }
794
795 public void focusGained(FocusEvent e) {
796 }
797
798 private void textChanged() {
799 if (!cubieSettings.solving) {
800 if (generator == null)
801 generator = new MoveSequence();
802 generator.parse(textBox.getText(), solution);
803 seqPos = generator.getLength();
804 textBox.setText(generator.toString(solution, seqPos));
805 cubieSettings.cubePos.doSequence(generator);
806 updateStatus(true);
807 cubeViewers[viewer].repaint();
808 }
809 }
810
811 // Has something to do with the solvability of the represented cube.
812 public boolean getT() {
813 return t;
814 }
815
816 public CubieSettings getSettings() {
817 return cubieSettings;
818 }
819
820 public void cubieSetCube(int[] tempCubeletPerm, int[] tempCubeletOri,
821 int[] tempFaceOri) {
822
823 // Do the same as resetting:
824 if (!cubieSettings.solving) {
825 stop();// stop any animation
826 cubieSettings.cubePos.reset();
827 setSequencePosition(-1);
828 updateStatus(true);
829 cubeViewers[viewer].repaint();
830 }
831
832 cubieSettings.cubePos = new CubePosition(tempCubeletPerm, tempCubeletOri,
833 tempFaceOri);
834
835 updateStatus(true);
836 cubeViewers[viewer].repaint();
837 cubeViewers[viewer].revalidate();
838
839 }
840
841 /**
842 * [WIP] Cubie sets it solutionbar, to what he gets from the CBTHSaveFile, but
843 * it's not working yet.
844 *
845 * @param solMoves
846 * solutionMoves from the CommandSeq Class.
847 * @param solAmount
848 * solutionAmount from the CommandSeq Class.
849 * @param solLen
850 * solutionLength from the CommandSeq Class.
851 * @param robotPositionHor
852 * robots position from the CommandSeq Class.
853 */
854 public void cubieSetMoveSeq(int[] solMoves, int[] solAmount, int solLen,
855 int robotPositionHor) {
856
857 // [WIP]: This did not quite work:
858
859 /*
860 * cubieSettings.generator = new MoveSequence(solLen, solMoves, solAmount);
861 * //Update visualization to robotPositionHor
862 *
863 * stop(); solution = true; seqPos = robotPositionHor; setSequencePosition(
864 * robotPositionHor); cubeViewers[viewer].repaint();
865 *
866 * updateStatus(true);
867 */
868 }
869
870 public MoveSequence getMoveSeqGenerator() {
871 return cubieSettings.generator;
872 }
873
874 public void viewerBackToBegin() {
875 stop();
876 setSequencePosition((generator != null && solution) ? generator.getLength() : 0);
877 cubeViewers[viewer].repaint();
878 }
879 }
1 package solver.solverJS.viewSolverJS;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6
7 // SymButton
8 // This is a kind button with cube symmetry picture on it.
9 // Button can remain depressed or not, depending on setPressed(boolean) state
10 // When clicked, an ActionEvent is passed to single ActionListener, with
11 // name 's' if shift key pressed during click or '' otherwise.
12 // If disabled then no longer a button, just the picture.
13
14 public final class SymButton extends JButton implements MouseListener {
15
16 private static final long serialVersionUID = 1L;
17 private Image offImage;
18 private Graphics offGraphics;
19 private ActionListener main;
20 private boolean pressed;
21 private int centx, centy, width, height;
22 private int vec[][];
23 private int type;
24 private Color colors[] = { new Color(0, 0, 0), // drawing colour
25 new Color(64, 64, 64), // shadowed edge outside
26 new Color(128, 128, 128), // shadowed edge inside
27 new Color(224, 224, 224), // highlighted edge inside
28 new Color(255, 255, 255), // highlighted edge outside
29 new Color(255, 0, 0), // m colour
30 new Color(255, 128, 128), // mc colour
31 new Color(255, 0, 255), // r2 colour
32 new Color(0, 255, 255), // r3 colour
33 new Color(0, 0, 255), // r4 colour
34 };
35
36 public SymButton(ActionListener m, int t) {
37 main = m;
38 pressed = false;
39 type = t;
40 addMouseListener(this);
41 }
42
43 public boolean isPressed() {
44 return (pressed);
45 }
46
47 public void setPressed(boolean p) {
48 pressed = p;
49 repaint();
50 }
51
52 void setType(int t) {
53 type = checkSym(t);
54 repaint();
55 }
56
57 void initialise() {
58 width = getSize().width;
59 height = getSize().height;
60
61 offImage = createImage(width, height); // Double buffer
62 offGraphics = offImage.getGraphics();
63
64 centx = (width - 1) / 2;
65 centy = (height - 1) / 2;
66 int rad = (int) ((centx - 1) / .866);
331 // order 6
332 0x07080000, 0x0A900000, 0x11A00000, 0x1C400000, // r3r2
333 0x00080001, 0x00100001, 0x00200001, 0x00400001, // mc r3
334 0x00080062, 0x00100054, 0x00200038, 0x0040000E, // me r3
335 // order 8
336 0x0481E000, 0x0902E000, 0x1204E000, // r4r2
337 0x04802093, 0x09004125, 0x12008249, // mc r2e r2e
338 0x04802700, 0x09004A80, 0x12009180, // mf r2e r2e
339 0x0000E381, // mf r2f r2f
340 0x0000E412, 0x0000E824, 0x0000F048, // me r2f r2f
341 0x00012481, 0x00024901, 0x00049201, // mc r4
342 0x00012312, 0x000242A4, 0x000481C8, // me r4
343 // order 12
344 0x0078E000, // r3r2r2
345 0x07080063, 0x0A900055, 0x11A00039, 0x1C40000F, // mr3r2
346 // order 16
347 0x0481E793, 0x0902EBA5, 0x1204F3C9, // mr4r2
348 // order 24
349 0x1FFFE000, // r4r3r2
350 0x0078E381, // mfr3r2r2
351 0x0078FC7E, // mer3r2r2
352 // order 48
353 0x1FFFFFFF,// mr4r3r2
354 };
355
356 if (t == 0)
357 return 0;
358 int i = 0;
359 while ((t & s[i]) != t)
360 i++;
361 return s[i];
362 }
363
364 public void update(Graphics g) {
365 paint(g);
366 }
367
368 public void mouseClicked(MouseEvent e) {
369 }
370
371 public void mouseEntered(MouseEvent e) {
372 }
373
374 public void mouseExited(MouseEvent e) {
375 }
376
377 public void mouseReleased(MouseEvent e) {
378 }
379
380 public void mousePressed(MouseEvent e) {
381 boolean shift = e.isShiftDown() || e.isAltDown();
382 boolean ctrl = e.isControlDown();
383 repaint();
384 e.consume();
385
386 // Pass on an event to main applet, to signify change
387 if (main != null) {
388 ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
389 shift ? "s" : ctrl ? "c" : "");
390 main.actionPerformed(ae);
391 }
392 }
393 }
67 }
68 if (f == false)
69 return;
70 f = false;
71 for (o2 = 0; o2 < 3; o2++) {
72 for (c2 = 0; c2 < 26; c2++) {
73 if (CubePosition.cubelet2facelet[c2][o2] == f2) {
74 f = true;
75 break;
76 }
77 }
78 if (f)
79 break;
80 }
81 if (f == false)
82 return;
83 cubieSettings.cubePos.editMove(c1, o1, c2, o2);
84 doEvent(true);
85 repaint();
86 }
87
88 public boolean showMove(int face, int qu) {
89 cubieSettings.cubePos.doMove(face, qu, true);
90 repaint();
91 doEvent(false);
92 return (true);
93 }
94
95 // --- mouse routines ---
96 int lastX, lastY, lastF = -1;
97 int keys = 0;
98 boolean moved = false;
99 final int sensitivityDrag = 40;
100 final int sensitivityMove = 12;
101
102 public void mousePressed(MouseEvent e) {
103 addMouseMotionListener(this);
104 lastX = e.getX();
105 lastY = e.getY();
106 lastF = getFacelet(lastX, lastY);
107 keys = e.isShiftDown() ? 1 : 0;
108 keys += e.isControlDown() ? 2 : 0;
109 keys += e.isAltDown() ? 4 : 0;
110 moved = false;
111 e.consume();
112 }
113
114 public void mouseReleased(MouseEvent e) {
115 removeMouseMotionListener(this);
116 if (cubieSettings.edit && lastF >= 0) {
117 editMove(lastF, getFacelet(e.getX(), e.getY()));
118 } else if (!moved) {
119 checkMouseMove(e.getX(), e.getY(), sensitivityMove);
120 }
121 e.consume();
122 }
123
124 public void mouseDragged(MouseEvent e) {
125 if ((!cubieSettings.edit || lastF < 0) && !moved)
126 checkMouseMove(e.getX(), e.getY(), sensitivityDrag);
127 e.consume();
128 }
129
130 public void mouseMoved(MouseEvent e) {
131 }
132
199 }
200
201 void doMove(int m, int q) {
202 if (cubieSettings.lockViewer)
203 return;
204 cubieSettings.cubePos.doMove(m, q, true);
205 repaint();
206 doEvent(true);
207 }
208
209 void doEvent(boolean user) {
210 // dispatch action event that move performed.
211 // two event types: usermove and automove. First is a move done
212 // by user acting on viewer via mouse. Second is move initiated from
213 // a function call from Cubie.
214 // I did not bother to implement an addActionListener method as there
215 // will only ever be one listener to this, viz the main cubie applet.
216 ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
217 user ? "user" : "auto");
218 main.actionPerformed(e);
219 }
220
221 // -- display routines ---
222 public void update(Graphics g) {
223 paint(g);
224 }
225 }
1 package solver.solverJS.viewSolverJS;
2
3 import java.awt.*;
4 import java.awt.event.*;
5
6 import solver.solverJS.algorithm.*;
7
8 final class Viewer3D extends Viewer implements Runnable {
9 // --- Display routines ---
10
11 private static final long serialVersionUID = 1L;
12 // graphical representation data
13 int OFFSETX, OFFSETY;
14 int radius;
15 Color fgColor[][] = new Color[8][20];
16 // coordinate system wrt users view
17 float eye[][] = new float[3][3];
18 // orthogonal axes vectors
19 final float coordVec[][] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 },
20 { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 }, };
21 // rotated orthogonal axes for animation
22 final int numAnimSteps = 16;
23 float animVec[][][][] = new float[6][numAnimSteps + numAnimSteps + 1][3][3];
24 // facelets (in LUFRDB order) of each cubelet. Er zijn 54 [0..53] facelets te
25 // benoemen.
26 final int facelets[][] = { { 0, 9, -1, -1, -1, 47 }, // ULB
27 { -1, 10, -1, -1, -1, 46 }, // UB
28 { -1, 11, -1, 29, -1, 45 }, // UR
29 { 1, 12, -1, -1, -1, -1 }, // UL
30 { -1, 13, -1, -1, -1, -1 }, // U
31 { -1, 14, -1, 28, -1, -1 }, // UR
32 { 2, 15, 18, -1, -1, -1 }, // ULF
33 { -1, 16, 19, -1, -1, -1 }, // UF
34 { -1, 17, 20, 27, -1, -1 }, // UFR
35
36 { 3, -1, -1, -1, -1, 50 }, { -1, -1, -1, -1, -1, 49 },
37 { -1, -1, -1, 32, -1, 48 }, { 4, -1, -1, -1, -1, -1 },
38 { -1, -1, -1, -1, -1, -1 }, { -1, -1, -1, 31, -1, -1 },
39 { 5, -1, 21, -1, -1, -1 }, { -1, -1, 22, -1, -1, -1 },
40 { -1, -1, 23, 30, -1, -1 },
41
42 { 6, -1, -1, -1, 42, 53 }, { -1, -1, -1, -1, 43, 52 },
43 { -1, -1, -1, 35, 44, 51 }, { 7, -1, -1, -1, 39, -1 },
44 { -1, -1, -1, -1, 40, -1 }, { -1, -1, -1, 34, 41, -1 },
45 { 8, -1, 24, -1, 36, -1 }, { -1, -1, 25, -1, 37, -1 },
46 { -1, -1, 26, 33, 38, -1 } };
47 Polygon faceletsO[] = new Polygon[54];
48 float moveDirs[][] = new float[54][4];
49 boolean eventType = true;
50
51 public Viewer3D(int x, int y, CubieSettings s, ActionListener m) {
52 super(x, y, s, m);
53 int i, j;
54 OFFSETX = x / 2;
55 OFFSETY = y / 2;
56 radius = x * 3 / 16;
57 if (y < x)
58 radius = y * 3 / 16;
59 for (j = 0; j < 20; j++) {
60 i = (40 - j) * j / 20;
61 // Functie stelt bergparabool voor door oorsprong
62 // met top in (20,20)
63 //Waarschijnlijk heeft i hier
64 // iets te maken met orientatie, anders blijven de
65 // kleuren onveranderd. Van elk kleur worden er als
66 // het ware 20 schakeringen opgeslaan.
133 animVec[1][i][1][1] = 1;
134 animVec[1][i][1][2] = 0;
135 vecProd(animVec[1][i][2], animVec[1][i][0], animVec[1][i][1]);
136
137 normalize(animVec[2][i][0]);
138 animVec[2][i][2][0] = 0;
139 animVec[2][i][2][1] = 0;
140 animVec[2][i][2][2] = 1;
141 vecProd(animVec[2][i][1], animVec[2][i][2], animVec[2][i][0]);
142
143 normalize(animVec[3][i][1]);
144 animVec[3][i][0][0] = 1;
145 animVec[3][i][0][1] = 0;
146 animVec[3][i][0][2] = 0;
147 vecProd(animVec[3][i][2], animVec[3][i][0], animVec[3][i][1]);
148
149 normalize(animVec[4][i][0]);
150 animVec[4][i][1][0] = 0;
151 animVec[4][i][1][1] = 1;
152 animVec[4][i][1][2] = 0;
153 vecProd(animVec[4][i][2], animVec[4][i][0], animVec[4][i][1]);
154
155 normalize(animVec[5][i][0]);
156 animVec[5][i][2][0] = 0;
157 animVec[5][i][2][1] = 0;
158 animVec[5][i][2][2] = 1;
159 vecProd(animVec[5][i][1], animVec[5][i][2], animVec[5][i][0]);
160 }
161 reset();
162 }
163
164 public void reset() {
165 eye[0][0] = 0.9f;
166 eye[0][1] = 0;
167 eye[0][2] = -0.4359f;
168 eye[1][0] = 0.19f;
169 eye[1][1] = 0.9f;
170 eye[1][2] = 0.3923f;
171 vecProd(eye[2], eye[0], eye[1]);
172 repaint();
173 }
174
175 boolean twisting = false;
176 int twistMove, twistDir;
177
178 public void run() {
179 // run animation
180 animCube(twistMove, twistDir);
181 // do actual move
182 cubieSettings.cubePos.doMove(twistMove, twistDir, false);
183 repaint();
184 doEvent(eventType);
185 eventType = true;
186 twisting = false;
187 }
188
189 float animEye[][][] = new float[3][3][3];
190 int anim = 0;
191 int axisOrder[] = { 0, 1, 2 };
192
193 public void animCube(int m, int q) {
194 int i, j, k, d;
195 int animDir[] = { 0, 0, 0 };
196 int animStep[] = { 0, 0, 0 };
197 int animAmount[] = { 0, 0, 0 };
198 d = 0;
199 if (q < 0) {
200 q = -q;
201 d = 3;
202 }
203 // initialise animation variables
204 for (i = 0; i < 3; i++) {
205 for (j = 0; j < 3; j++)
206 for (k = 0; k < 3; k++)
207 animEye[i][j][k] = eye[j][k];
208 animAmount[i] = animStep[i] = animDir[i] = 0;
209 }
210
211 // m=6-8, middle layer turn
212 // m=9-11, cube turn
213 // m=12-14, slice move
214 // m=15-17, anti-slice move
215
216 if (m < 3) {// face move LUF
217 animStep[0] = q;
218 animDir[0] = m + d;
219 axisOrder[0] = m;
220 } else if (m < 6) {// face move RDB
221 animStep[2] = q;
222 animDir[2] = m - d;
223 axisOrder[0] = m - 3;
224 } else if (m < 9) {// midslice move
225 animStep[1] = q;
226 animDir[1] = m - 6 + d;
227 axisOrder[0] = m - 6;
228 } else if (m < 12) {// whole cube move
229 axisOrder[0] = m - 9;
230 animStep[0] = animStep[1] = animStep[2] = q;
231 animDir[0] = animDir[1] = animDir[2] = m - 9 + d;
232 } else if (m < 15) {// slice move
233 axisOrder[0] = m - 12;
234 animStep[0] = animStep[2] = q;
235 animDir[0] = m - 12 + d;
236 animDir[2] = m - 12 + d;
237 } else if (m < 18) {// anti-slice move
238 axisOrder[0] = m - 15;
239 animStep[0] = animStep[2] = q;
240 animDir[0] = m - 15 + d;
241 animDir[2] = m - 15 + 3 - d;
242 }
243
244 // set order of axes - main axis first
245 if (axisOrder[0] == 0) {
246 axisOrder[0] = 0;
247 axisOrder[1] = 1;
248 axisOrder[2] = 2;
249 } else if (axisOrder[0] == 1) {
250 axisOrder[0] = 1;
251 axisOrder[1] = 2;
252 axisOrder[2] = 0;
253 } else {
254 axisOrder[0] = 2;
255 axisOrder[1] = 0;
256 axisOrder[2] = 1;
257 i = animStep[0];
258 animStep[0] = animStep[2];
259 animStep[2] = i;
260 i = animDir[0];
261 animDir[0] = animDir[2];
262 animDir[2] = i;
263 }
264
529 }
530
531 private void addpnt(float corn[], float d1[], float d2[], float vw[][], int i,
532 float x, float y) {
533 // get facelet corner coordinate
534 vr[0] = corn[0] + x * d1[0] + y * d2[0];
535 vr[1] = corn[1] + x * d1[1] + y * d2[1];
536 vr[2] = corn[2] + x * d1[2] + y * d2[2];
537 // project onto viewer plane
538 rectx[i] = OFFSETX + (int) (dotProd(vr, vw[0]) * radius);
539 recty[i] = OFFSETY + (int) (dotProd(vr, vw[1]) * radius);
540 }
541
542 // normalize vetor, i.e. scale it to length 1
543 private void normalize(float v[]) {
544 float l = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
545 v[0] /= l;
546 v[1] /= l;
547 v[2] /= l;
548 }
549
550 // dot (inner vector) product
551 private float dotProd(float v[], float w[]) {
552 return (v[0] * w[0] + v[1] * w[1] + v[2] * w[2]);
553 }
554
555 // cross (outer vector) product
556 private void vecProd(float u[], float v[], float w[]) {
557 u[0] = v[1] * w[2] - v[2] * w[1];
558 u[1] = v[2] * w[0] - v[0] * w[2];
559 u[2] = v[0] * w[1] - v[1] * w[0];
560 }
561
562 // Consider Eye coords along new axes v[] and return new eye in old coords
563 private void rotateVecs(float res[][], float v[][]) {
564 int i, j;
565 for (i = 0; i < 3; i++) {
566 for (j = 0; j < 3; j++) {
567 res[i][j] = v[0][j] * eye[i][0] + v[1][j] * eye[i][1]
568 + v[2][j] * eye[i][2];
569 }
570 }
571 }
572
573 // --- mouse routines ---
574 // conversion from facelet mouse move to internal move number
575 final int moves[][] = {
576 { -2, -2, -2, -8, -11, -8, 5, 5, 5, -6, -6, -6, 9, 12, 9, 3, 3, 3, -2, -2,
577 -2, -8, -11, -8, 5, 5, 5, -2, -2, -2, -8, -11, -8, 5, 5, 5, -3, -3,
578 -3, -9, -12, -9, 6, 6, 6, -2, -2, -2, -8, -11, -8, 5, 5, 5 },
579 { -6, 9, 3, -6, 12, 3, -6, 9, 3, -1, -7, 4, -1, -10, 4, -1, -7, 4, -1, -7,
580 4, -1, -10, 4, -1, -7, 4, -3, -9, 6, -3, -12, 6, -3, -9, 6, -1, -7, 4,
581 -1, -10, 4, -1, -7, 4, -4, 7, 1, -4, 10, 1, -4, 7, 1 },
582 { 2, 2, 2, 8, 11, 8, -5, -5, -5, 6, 6, 6, -9, -12, -9, -3, -3, -3, 2, 2,
583 2, 8, 11, 8, -5, -5, -5, 2, 2, 2, 8, 11, 8, -5, -5, -5, 3, 3, 3, 9,
584 12, 9, -6, -6, -6, 2, 2, 2, 8, 11, 8, -5, -5, -5 },
585 { 6, -9, -3, 6, -12, -3, 6, -9, -3, 1, 7, -4, 1, 10, -4, 1, 7, -4, 1, 7,
586 -4, 1, 10, -4, 1, 7, -4, 3, 9, -6, 3, 12, -6, 3, 9, -6, 1, 7, -4, 1,
587 10, -4, 1, 7, -4, 4, -7, -1, 4, -10, -1, 4, -7, -1 } };
588
589 // return facelet number belonging to coordinate x,y
590 protected int getFacelet(int x, int y) {
591 for (int k = 0; k < 54; k++) {
592 if (faceletsO[k] != null && faceletsO[k].contains(x, y)) {
593 return (k);
594 }
595 }
596 return (-1);
597 }
598
599 // perform move of facelet f in direction x,y
600 private void executeMouseMove(int f, int x, int y) {
601 int d = -1, m;
602 // compare x,y with the stored vectors
603 if (f < 0)
604 return;
605 float f1 = x * moveDirs[f][1] - y * moveDirs[f][0];
606 float f2 = x * moveDirs[f][3] - y * moveDirs[f][2];
607 if (f1 > f2 && f1 > -f2)
608 d = 0;
609 else if (f1 < f2 && f1 < -f2)
610 d = 2;
611 else if (f2 > f1 && f2 > -f1)
612 d = 1;
613 else if (f2 < f1 && f2 < -f1)
614 d = 3;
615 if (d >= 0 && f >= 0) {
616 m = moves[d][f];
617 if (m < 0) {
618 tryMove(-m - 1, -1);
619 } else {
620 tryMove(m - 1, 1);
621 }
622 }
623 }
624
625 void doMove(int m, int q) {
626 if (!cubieSettings.lockViewer)
627 doMove2(m, q);
628 }
629
630 void doMove2(int m, int q) {
631 if (!twisting) {
632 twisting = true;
633 twistMove = m;
634 twistDir = q;
635 new Thread(this).start();
636 }
637 }
638
639 public boolean showMove(int face, int qu) {
640 if (twisting)
641 return (false);
642 if (qu > 2)
643 qu -= 4;
644 eventType = false; // set flag to show this is not initiated by user
645 doMove2(face, qu);
646 return (true);
647 }
648
649 // Check if mouse move to coord x,y is far enough to trigger a move.
650 protected void checkMouseMove(int x, int y, int d) {
651 if (lastF < 0) { // mousepress was not on a facelet
652 // rotate whole cube
653 int dx = x - lastX;
654 int dy = y - lastY;
655 lastX = x;
656 lastY = y;
657 float f = (float) dx / radius / 2;
658 eye[0][0] += f * eye[2][0];
659 eye[0][1] += f * eye[2][1];
660 eye[0][2] += f * eye[2][2];
661 normalize(eye[0]);
662 vecProd(eye[2], eye[0], eye[1]);
663 f = (float) dy / radius / 2;
664 eye[1][0] += f * eye[2][0];
665 eye[1][1] += f * eye[2][1];
666 eye[1][2] += f * eye[2][2];
667 normalize(eye[1]);
668 vecProd(eye[2], eye[0], eye[1]);
669 repaint();
670 } else { // haven't yet moved
671 int dx, dy;
672 dx = x - lastX; // horizontal shift
673 dy = y - lastY; // vertical shift
674 if (dx * dx + dy * dy > d) {
675 executeMouseMove(getFacelet(lastX, lastY), dx, dy);
676 moved = true;
677 }
678 }
679 }
680 }
1 package solver.solverJS.viewSolverJS;
2
3 import java.awt.*;
4 import java.awt.event.*;
5
6 import solver.solverJS.algorithm.*;
7
8 final class ViewerBox extends Viewer {
9 // --- Display routines ---
10
11 private static final long serialVersionUID = 1L;
12 // graphical representation data
13 int CELL, BORD, OFFSETX, OFFSETY;
14 Polygon faceletsI[];
15 Polygon faceletsO[];
16 Polygon faceOriMarks[][];
17
18 public ViewerBox(int x, int y, CubieSettings s, ActionListener m) {
19 super(x, y, s, m);
20 int i, j, c;
21 CELL = x / 16;
22 BORD = y / 16;
23 if (BORD < CELL)
24 CELL = BORD;
25 BORD = 2;
26 OFFSETX = (x - 16 * CELL) / 2;
27 OFFSETY = (y - 16 * CELL) / 2;
28 faceletsI = new Polygon[54];
29 faceletsO = new Polygon[54];
30 faceOriMarks = new Polygon[54][4];
31
32 for (c = 0; c < 54; c++) {
33 faceletsI[c] = new Polygon();
34 faceletsO[c] = new Polygon();
35 for (i = 0; i < 4; i++)
36 faceOriMarks[c][i] = new Polygon();
37 }
38 c = 0;
39 // L
40 for (j = 0; j < 3; j++)
41 for (i = 0; i < 3; i++) {
42 doFacelet(CELL * (4 - i), CELL * (4 - i) + (CELL * (8 + 2 * i) * j) / 3,
43 CELL * (5 - i), CELL * (5 - i) + (CELL * (6 + 2 * i) * j) / 3,
44 CELL * (5 - i), CELL * (5 - i) + (CELL * (6 + 2 * i) * (j + 1)) / 3,
45 CELL * (4 - i), CELL * (4 - i) + (CELL * (8 + 2 * i) * (j + 1)) / 3,
46 BORD, 2 * BORD * (3 - j) / 3, -BORD, 2 * BORD * j / 3, -BORD,
47 2 * BORD * (j - 2) / 3, BORD, -2 * BORD * (j + 1) / 3, c);
48 c++;
49 }
50 // U
51 for (j = 0; j < 3; j++)
52 for (i = 0; i < 3; i++) {
53 doFacelet(CELL * (5 - j) + (CELL * (6 + 2 * j) * (i + 1)) / 3,
54 CELL * (5 - j), CELL * (5 - j) + (CELL * (6 + 2 * j) * i) / 3,
55 CELL * (5 - j), CELL * (4 - j) + (CELL * (8 + 2 * j) * i) / 3,
56 CELL * (4 - j), CELL * (4 - j) + (CELL * (8 + 2 * j) * (i + 1)) / 3,
57 CELL * (4 - j), 2 * BORD * (i - 2) / 3, -BORD, 2 * BORD * i / 3,
58 -BORD, 2 * BORD * (3 - i) / 3, BORD, -2 * BORD * (i + 1) / 3, BORD,
59 c);
60 c++;
61 }
62 // F
63 faceletsO[c].addPoint(0, 0);
64 faceletsO[c].addPoint(6 * CELL, 0);
65 faceletsO[c].addPoint(6 * CELL, 2 * CELL);
66 faceletsO[c].addPoint(2 * CELL, 2 * CELL);
331 }
332 g.drawImage(offImage, 0, 0, this);
333 }
334
335 // --- mouse routines ---
336 // conversion from facelet mouse move to internal move number
337 final int moves[][] = {
338 { 2, 2, 2, 8, 11, 8, -5, -5, -5, -6, -6, -6, 9, 12, 9, 3, 3, 3, -2, -2,
339 -2, -8, -11, -8, 5, 5, 5, 2, 2, 2, 8, 11, 8, -5, -5, -5, -3, -3, -3,
340 -9, -12, -9, 6, 6, 6, 2, 2, 2, 8, 11, 8, -5, -5, -5 },
341 { 6, -9, -3, 6, -12, -3, 6, -9, -3, -1, -7, 4, -1, -10, 4, -1, -7, 4, 1,
342 7, -4, 1, 10, -4, 1, 7, -4, 3, 9, -6, 3, 12, -6, 3, 9, -6, -1, -7, 4,
343 -1, -10, 4, -1, -7, 4, 4, -7, -1, 4, -10, -1, 4, -7, -1 },
344 { -2, -2, -2, -8, -11, -8, 5, 5, 5, 6, 6, 6, -9, -12, -9, -3, -3, -3, 2,
345 2, 2, 8, 11, 8, -5, -5, -5, -2, -2, -2, -8, -11, -8, 5, 5, 5, 3, 3, 3,
346 9, 12, 9, -6, -6, -6, -2, -2, -2, -8, -11, -8, 5, 5, 5 },
347 { -6, 9, 3, -6, 12, 3, -6, 9, 3, 1, 7, -4, 1, 10, -4, 1, 7, -4, -1, -7, 4,
348 -1, -10, 4, -1, -7, 4, -3, -9, 6, -3, -12, 6, -3, -9, 6, 1, 7, -4, 1,
349 10, -4, 1, 7, -4, -4, 7, 1, -4, 10, 1, -4, 7, 1 } };
350
351 // Check if mouse move to coord x,y is far enough to trigger a move.
352 protected void checkMouseMove(int x, int y, int d) {
353 if (!moved) {
354 int dx, dy;
355 dx = x - lastX; // horizontal shift
356 dy = y - lastY; // vertical shift
357 if (dx * dx + dy * dy > d) {
358 executeMouseMove(getFacelet(lastX, lastY), dx, dy);
359 moved = true;
360 }
361 }
362 }
363
364 // return facelet number belonging to coordinate x,y
365 protected int getFacelet(int x, int y) {
366 for (int k = 0; k < 54; k++) {
367 if (faceletsO[k].contains(x, y)) {
368 return (k);
369 }
370 }
371 return (-1);
372 }
373
374 // perform move of facelet f in direction x,y
375 private void executeMouseMove(int f, int x, int y) {
376 int d = -1, m;
377 if (x > y && x > -y)
378 d = 0;
379 else if (x < y && x < -y)
380 d = 2;
381 else if (y > x && y > -x)
382 d = 1;
383 else if (y < x && y < -x)
384 d = 3;
385 if (d >= 0 && f >= 0) {
386 m = moves[d][f];
387 if (m < 0) {
388 tryMove(-m - 1, -1);
389 } else {
390 tryMove(m - 1, 1);
391 }
392 }
393 }
394 }
1
1 package solver.solverJS.viewSolverJS;
2
3 import java.awt.*;
4 import java.awt.event.*;
5
6 import solver.solverJS.algorithm.*;
7
8 final class ViewerDiag extends Viewer {
9 // --- Display routines ---
10
11 private static final long serialVersionUID = 1L;
12 // graphical representation data
13 Polygon faceletsI[] = new Polygon[54];
14 Polygon faceletsO[] = new Polygon[54];
15 Polygon faceOriMarks[][] = new Polygon[54][4];
16 Polygon cubeBack[] = new Polygon[4];
17
18 public ViewerDiag(int x, int y, CubieSettings s, ActionListener m) {
19 super(x, y, s, m);
20 int i, c;
21 int FACEH, CELLH, FACEV, CELLV, FACEL, CELLL, OFFSETX, OFFSETY;
22 // vert : 8.5*CELLV+5.5*CELLL == 21.15*CELLV
23 // FACEL/FACEV=2.3, vert=2*FACEL+3*FACEV
24 // FACEH/FACEV=2
25 CELLV = (int) ((double) y / 21.15);
26 i = x / 22;
27 if (i < CELLV)
28 CELLV = i;
29 CELLH = CELLV * 2;
30 CELLL = (int) (2.3 * CELLV);
31 FACEH = 3 * CELLH;
32 FACEL = 3 * CELLL;
33 FACEV = 3 * CELLV;
34
35 OFFSETX = (x - 11 * CELLH) / 2;
36 OFFSETY = (y + y - 11 * CELLL - 17 * CELLV) / 4;
37 for (c = 0; c < 54; c++) {
38 faceletsI[c] = new Polygon();
39 faceletsO[c] = new Polygon();
40 for (i = 0; i < 4; i++)
41 faceOriMarks[c][i] = new Polygon();
42 }
43 double b = 7. / FACEL;
44
45 // get the correct shape of each face
46 dopoly(FACEH, 0, -FACEH, FACEV, 0, FACEL, 0, b);// L
47 dopoly(FACEH * 2 - CELLH / 2, FACEL - FACEV - (CELLL - CELLV) / 2, FACEH,
48 FACEV, -FACEH, FACEV, 9, b);// U
49 dopoly(FACEH - CELLH / 2, FACEL - (CELLL - CELLV) / 2, FACEH, FACEV, 0,
50 FACEL, 18, b);// F
51 dopoly(FACEH * 2 - CELLH / 2, FACEL + FACEV - (CELLL - CELLV) / 2, FACEH,
52 -FACEV, 0, FACEL, 27, b);// R
53 dopoly(FACEH - CELLH / 2, FACEV * 2 + FACEL * 2 - (CELLL + CELLV) / 2,
54 FACEH, FACEV, FACEH, -FACEV, 36, b);// D
55 dopoly(FACEH * 4 - CELLH, FACEV, -FACEH, -FACEV, 0, FACEL, 45, b);// B
56
57 // shift into position
58 for (c = 0; c < 54; c++) {
59 faceletsI[c].translate(OFFSETX, OFFSETY);
60 faceletsO[c].translate(OFFSETX, OFFSETY);
61 for (i = 0; i < 4; i++)
62 faceOriMarks[c][i].translate(OFFSETX, OFFSETY);
63 }
64
65 // get background of the cube, the areas to be filled black.
66 for (c = 0; c < 4; c++)
133 faceOriMarks[c][0].addPoint(
134 (int) ((i - b / 2 + .75) * dx1 / 3 + (j + .5) * dx2 / 3),
135 (int) ((i - b / 2 + .75) * dy1 / 3 + (j + .5) * dy2 / 3));
136 faceOriMarks[c][0].addPoint(
137 (int) ((i + b / 2 + .25) * dx1 / 3 + (j + .5) * dx2 / 3),
138 (int) ((i + b / 2 + .25) * dy1 / 3 + (j + .5) * dy2 / 3));
139 faceOriMarks[c][0].translate(x0, y0);
140 // build right marker
141 faceOriMarks[c][3].addPoint(
142 (int) ((i + .5) * dx1 / 3 + (j + b / 2 + .25) * dx2 / 3),
143 (int) ((i + .5) * dy1 / 3 + (j + b / 2 + .25) * dy2 / 3));
144 faceOriMarks[c][3].addPoint(
145 (int) ((i + 1) * dx1 / 3 + (j + b / 2 + .25) * dx2 / 3),
146 (int) ((i + 1) * dy1 / 3 + (j + b / 2 + .25) * dy2 / 3));
147 faceOriMarks[c][3].addPoint(
148 (int) ((i + 1) * dx1 / 3 + (j - b / 2 + .75) * dx2 / 3),
149 (int) ((i + 1) * dy1 / 3 + (j - b / 2 + .75) * dy2 / 3));
150 faceOriMarks[c][3].addPoint(
151 (int) ((i + .5) * dx1 / 3 + (j - b / 2 + .75) * dx2 / 3),
152 (int) ((i + .5) * dy1 / 3 + (j - b / 2 + .75) * dy2 / 3));
153 faceOriMarks[c][3].translate(x0, y0);
154 // build bottom marker
155 faceOriMarks[c][2].addPoint(
156 (int) ((i + b / 2 + .25) * dx1 / 3 + (j + .5) * dx2 / 3),
157 (int) ((i + b / 2 + .25) * dy1 / 3 + (j + .5) * dy2 / 3));
158 faceOriMarks[c][2].addPoint(
159 (int) ((i - b / 2 + .75) * dx1 / 3 + (j + .5) * dx2 / 3),
160 (int) ((i - b / 2 + .75) * dy1 / 3 + (j + .5) * dy2 / 3));
161 faceOriMarks[c][2].addPoint(
162 (int) ((i - b / 2 + .75) * dx1 / 3 + (j + 1) * dx2 / 3),
163 (int) ((i - b / 2 + .75) * dy1 / 3 + (j + 1) * dy2 / 3));
164 faceOriMarks[c][2].addPoint(
165 (int) ((i + b / 2 + .25) * dx1 / 3 + (j + 1) * dx2 / 3),
166 (int) ((i + b / 2 + .25) * dy1 / 3 + (j + 1) * dy2 / 3));
167 faceOriMarks[c][2].translate(x0, y0);
168 // build left marker
169 faceOriMarks[c][1].addPoint(
170 (int) ((i) * dx1 / 3 + (j + b / 2 + .25) * dx2 / 3),
171 (int) ((i) * dy1 / 3 + (j + b / 2 + .25) * dy2 / 3));
172 faceOriMarks[c][1].addPoint(
173 (int) ((i + .5) * dx1 / 3 + (j + b / 2 + .25) * dx2 / 3),
174 (int) ((i + .5) * dy1 / 3 + (j + b / 2 + .25) * dy2 / 3));
175 faceOriMarks[c][1].addPoint(
176 (int) ((i + .5) * dx1 / 3 + (j - b / 2 + .75) * dx2 / 3),
177 (int) ((i + .5) * dy1 / 3 + (j - b / 2 + .75) * dy2 / 3));
178 faceOriMarks[c][1].addPoint(
179 (int) ((i) * dx1 / 3 + (j - b / 2 + .75) * dx2 / 3),
180 (int) ((i) * dy1 / 3 + (j - b / 2 + .75) * dy2 / 3));
181 faceOriMarks[c][1].translate(x0, y0);
182
183 c++;
184 }
185 }
186
187 public void paint(Graphics g) {
188 int i;
189 if (offImage == null) {
190 initialise();
191 }
192 offGraphics.setColor(getBackground()); // Clear drawing buffer
193 offGraphics.fillRect(0, 0, width, height);
194 // draw cube
195 cubieSettings.cubePos.getFaceletColors();
196
197 offGraphics.setColor(baseColor); // draw facelet base
198 for (i = 1; i < 4; i++)
199 offGraphics.fillPolygon(cubeBack[i]);
200
201 for (i = 0; i < 9; i++) { // do L face
202 offGraphics.setColor(colors[cubieSettings.cubePos.cubeletPerm[20
203 + cubieSettings.cubePos.faceletColor[i]] - 20]); // draw facelet
204 offGraphics.fillPolygon(faceletsI[i]);
205 if (cubieSettings.superGroup) {
206 offGraphics.setColor(baseColor);
207 offGraphics
208 .fillPolygon(faceOriMarks[i][cubieSettings.cubePos.faceletOri[i]]);
209 }
210 }
211 for (i = 36; i < 54; i++) { // do R,D faces
212 offGraphics.setColor(colors[cubieSettings.cubePos.cubeletPerm[20
213 + cubieSettings.cubePos.faceletColor[i]] - 20]); // draw facelet
214 offGraphics.fillPolygon(faceletsI[i]);
215 if (cubieSettings.superGroup) {
216 offGraphics.setColor(baseColor);
217 offGraphics
218 .fillPolygon(faceOriMarks[i][cubieSettings.cubePos.faceletOri[i]]);
219 }
220 }
221
222 offGraphics.setColor(baseColor); // draw cube base
223 offGraphics.fillPolygon(cubeBack[0]);
224
225 for (i = 9; i < 36; i++) { // do R,D faces
226 offGraphics.setColor(colors[cubieSettings.cubePos.cubeletPerm[20
227 + cubieSettings.cubePos.faceletColor[i]] - 20]); // draw facelet
228 offGraphics.fillPolygon(faceletsI[i]);
229 if (cubieSettings.superGroup) {
230 offGraphics.setColor(baseColor);
231 offGraphics
232 .fillPolygon(faceOriMarks[i][cubieSettings.cubePos.faceletOri[i]]);
233 }
234 }
235
236 g.drawImage(offImage, 0, 0, this);
237 }
238
239 // --- mouse routines ---
240 // conversion from facelet mouse move to internal move number
241 final int moves[][] = {
242 { -2, -2, -2, -8, -11, -8, 5, 5, 5, -6, -6, -6, 9, 12, 9, 3, 3, 3, -2, -2,
243 -2, -8, -11, -8, 5, 5, 5, 2, 2, 2, 8, 11, 8, -5, -5, -5, -3, -3, -3,
244 -9, -12, -9, 6, 6, 6, 2, 2, 2, 8, 11, 8, -5, -5, -5 },
245 { 6, -9, -3, 6, -12, -3, 6, -9, -3, -1, -7, 4, -1, -10, 4, -1, -7, 4, 1,
246 7, -4, 1, 10, -4, 1, 7, -4, 3, 9, -6, 3, 12, -6, 3, 9, -6, 1, 7, -4,
247 1, 10, -4, 1, 7, -4, 4, -7, -1, 4, -10, -1, 4, -7, -1 },
248 { 2, 2, 2, 8, 11, 8, -5, -5, -5, 6, 6, 6, -9, -12, -9, -3, -3, -3, 2, 2,
249 2, 8, 11, 8, -5, -5, -5, -2, -2, -2, -8, -11, -8, 5, 5, 5, 3, 3, 3, 9,
250 12, 9, -6, -6, -6, -2, -2, -2, -8, -11, -8, 5, 5, 5 },
251 { -6, 9, 3, -6, 12, 3, -6, 9, 3, 1, 7, -4, 1, 10, -4, 1, 7, -4, -1, -7, 4,
252 -1, -10, 4, -1, -7, 4, -3, -9, 6, -3, -12, 6, -3, -9, 6, -1, -7, 4,
253 -1, -10, 4, -1, -7, 4, -4, 7, 1, -4, 10, 1, -4, 7, 1 } };
254
255 // Check if mouse move to coord x,y is far enough to trigger a move.
256 protected void checkMouseMove(int x, int y, int d) {
257 if (!moved) {
258 int dx, dy;
259 dx = x - lastX; // horizontal shift
260 dy = y - lastY; // vertical shift
261 if (dx * dx + dy * dy > d) {
262 executeMouseMove(getFacelet(lastX, lastY), dx, dy);
263 moved = true;
264 }
265 }
266 }
267
268 // return facelet number belonging to coordinate x,y
269 protected int getFacelet(int x, int y) {
270 int k;
271 for (k = 9; k < 54; k++) {
272 if (faceletsO[k].contains(x, y))
273 return (k);
274 }
275 for (k = 0; k < 9; k++) {
276 if (faceletsO[k].contains(x, y))
277 return (k);
278 }
279 return (-1);
280 }
281
282 // perform move of facelet f in direction x,y
283 private void executeMouseMove(int f, int x, int y) {
284 int d = -1, m;
285 if ((f >= 9 && f < 18) || (f >= 36 && f < 45)) { // U/D facelet
286 if (x > 0 && y > 0)
287 d = 0;
288 else if (x < 0 && y < 0)
289 d = 2;
290 else if (x > 0 && y < 0)
291 d = 1;
292 else if (x < 0 && y > 0)
293 d = 3;
294 } else if ((f >= 18 && f < 27) || (f >= 45 && f < 54)) { // F/B facelet
295 if (x + y + y > 0 && 3 * x > 2 * y)
296 d = 0;
297 else if (x + y + y < 0 && 3 * x < 2 * y)
298 d = 2;
299 else if (x + y + y > 0 && 3 * x < 2 * y)
300 d = 1;
301 else if (x + y + y < 0 && 3 * x > 2 * y)
302 d = 3;
303 } else if ((f >= 0 && f < 9) || (f >= 27 && f < 36)) { // L/R facelet
304 if (y + y > x && 2 * y + 3 * x < 0)
305 d = 0;
306 else if (y + y < x && 2 * y + 3 * x > 0)
307 d = 2;
308 else if (y + y > x && 2 * y + 3 * x > 0)
309 d = 1;
310 else if (y + y < x && 2 * y + 3 * x < 0)
311 d = 3;
312 }
313 if (d >= 0 && f >= 0) {
314 m = moves[d][f];
315 if (m < 0) {
316 tryMove(-m - 1, -1);
317 } else {
318 tryMove(m - 1, 1);
319 }
320 }
321 }
322 }
1 package solver.solverJS.viewSolverJS;
2
3 import java.awt.*;
4 import java.awt.event.*;
5
6 import solver.solverJS.algorithm.*;
7
8 final class ViewerFlat extends Viewer {
9 private static final long serialVersionUID = 1L;
10 // --- Display routines ---
11
12 // graphical representation data
13 int FACE, CELL, BORD, OFFSETX, OFFSETY;
14 int facecoordX[];
15 int facecoordY[];
16
17 public ViewerFlat(int x, int y, CubieSettings s, ActionListener m) {
18 super(x, y, s, m);
19 CELL = x / 12;
20 FACE = y / 9;
21 if (FACE < CELL)
22 CELL = FACE;
23 FACE = CELL * 3;
24 BORD = 2;
25 OFFSETX = (x - 4 * FACE) / 2;
26 OFFSETY = (y - 3 * FACE) / 2;
27 facecoordX = new int[6];
28 facecoordY = new int[6];
29 facecoordX[0] = OFFSETX + 0;
30 facecoordY[0] = OFFSETY + FACE;
31 facecoordX[1] = OFFSETX + FACE;
32 facecoordY[1] = OFFSETY + 0;
33 facecoordX[2] = OFFSETX + FACE;
34 facecoordY[2] = OFFSETY + FACE;
35 facecoordX[3] = OFFSETX + 2 * FACE;
36 facecoordY[3] = OFFSETY + FACE;
37 facecoordX[4] = OFFSETX + FACE;
38 facecoordY[4] = OFFSETY + 2 * FACE;
39 facecoordX[5] = OFFSETX + 3 * FACE;
40 facecoordY[5] = OFFSETY + FACE;
41 }
42
43 public void paint(Graphics g) {
44 int i, j, k, c;
45 if (offImage == null) {
46 initialise();
47 }
48 offGraphics.setColor(getBackground()); // Clear drawing buffer
49 offGraphics.fillRect(0, 0, width, height);
50 // draw cube
51 cubieSettings.cubePos.getFaceletColors();
52 c = 0;
53 for (k = 0; k < 6; k++) { // each face
54 offGraphics.setColor(baseColor); // first draw cube colour
55 offGraphics.fillRect(facecoordX[k], facecoordY[k], FACE, FACE);
56 for (i = 0; i < 3; i++) { // each row
57 for (j = 0; j < 3; j++) { // each facelet
58 offGraphics.setColor(colors[cubieSettings.cubePos.cubeletPerm[20
59 + cubieSettings.cubePos.faceletColor[c]] - 20]); // draw facelet
60 offGraphics.fillRect(facecoordX[k] + BORD + j * CELL,
61 facecoordY[k] + BORD + i * CELL, CELL - 2 * BORD,
62 CELL - 2 * BORD);
63 if (cubieSettings.superGroup) {
64 offGraphics.setColor(baseColor);
65 if (cubieSettings.cubePos.faceletOri[c] == 0) {
66 offGraphics.fillRect(
133 }
134
135 // perform move of facelet f in direction x,y
136 private void executeMouseMove(int f, int x, int y) {
137 int d = -1, m;
138 if (x > y && x > -y)
139 d = 0;
140 else if (x < y && x < -y)
141 d = 2;
142 else if (y > x && y > -x)
143 d = 1;
144 else if (y < x && y < -x)
145 d = 3;
146 if (d >= 0 && f >= 0) {
147 m = moves[d][f];
148 if (m < 0) {
149 tryMove(-m - 1, -1);
150 } else {
151 tryMove(m - 1, 1);
152 }
153 }
154 }
155 }
1 package view.scrollImageView;
2
3 import java.awt.*;
4 import javax.swing.*;
5
6 public class Corner extends JComponent {
7 // Source https://docs.oracle.com/javase/tutorial/uiswing/examples/components/
8 // ScrollDemo visited the 20/10/2015.
9 private static final long serialVersionUID = 1L;
10
11 // Instance method:
12 protected void paintComponent(Graphics g) {
13
14 g.setColor(new Color(50, 25, 0));
15 g.fillRect(0, 0, getWidth(), getHeight());
16 }
17 }
1 package view.scrollImageView;
2
3 import java.awt.*;
4 import javax.swing.*;
5
6 public class Ruler extends JComponent {
7 // Source https://docs.oracle.com/javase/tutorial/uiswing/examples/components/
8 // ScrollDemo visited the 20/10/2015.
9 private static final long serialVersionUID = 1L;
10 public static final int INCH = Toolkit.getDefaultToolkit()
11 .getScreenResolution();
12 public static final int HORIZONTAL = 0;
13 public static final int VERTICAL = 1;
14 public static final int SIZE = 35;
15
16 public int orientation;
17 public boolean isMetric;
18 private int increment;
19 private int units;
20
21 // Constructors:
22 public Ruler(int o, boolean m) {
23 orientation = o;
24 isMetric = m;
25 setIncrementAndUnits();
26 }
27
28 // Getters:
29 public int getIncrement() {
30 return increment;
31 }
32
33 // Setters:
34 public void setIsMetric(boolean isMetric) {
35 this.isMetric = isMetric;
36 setIncrementAndUnits();
37 repaint();
38 }
39
40 private void setIncrementAndUnits() {
41 if (isMetric) {
42 units = (int) ((double) INCH / (double) 2.54); // dots per centimeter
43 increment = units;
44 } else {
45 units = INCH;
46 increment = units / 2;
47 }
48 }
49
50 public void setPreferredHeight(int ph) {
51 setPreferredSize(new Dimension(SIZE, ph));
52 }
53
54 public void setPreferredWidth(int pw) {
55 setPreferredSize(new Dimension(pw, SIZE));
56 }
57
58 // Instance methods:
59 public boolean isMetric() {
60 return this.isMetric;
61 }
62
63 protected void paintComponent(Graphics g) {
64 Rectangle drawHere = g.getClipBounds();
65
66 // Color clipping area.
1 package view.scrollImageView;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6
7 import model.CommonObjects;
8
9 public class ScrollablePicture extends JLabel
10 implements Scrollable, MouseMotionListener {
11 // Source https://docs.oracle.com/javase/tutorial/uiswing/examples/components/
12 // ScrollDemo visited the 20/10/2015.
13 private static final long serialVersionUID = 1L;
14 private int maxUnitIncrement = 1;
15 private boolean missingPicture = false;
16
17 // Constructors:
18 public ScrollablePicture(int m) {
19 super(new ImageIcon());
20 missingPicture = true;
21 setText("There is no image selected to display.");
22 setFont(CommonObjects.getCBTHSettingsList().getFont("guiFont1"));
23 setForeground(Color.DARK_GRAY);
24 setHorizontalAlignment(CENTER);
25 setOpaque(true);
26 setBackground(Color.white);
27
28 maxUnitIncrement = m;
29
30 // Let the user scroll by dragging to outside the window.
31 setAutoscrolls(true); // enable synthetic drag events
32 addMouseMotionListener(this); // handle mouse drags
33 }
34
35 public ScrollablePicture(ImageIcon i, int m) {
36 // Deze constructor wordt waarschijnlijk niet meer gebruikt.
37 super(i);
38
39 maxUnitIncrement = m;
40
41 // Let the user scroll by dragging to outside the window.
42 setAutoscrolls(true); // enable synthetic drag events
43 addMouseMotionListener(this); // handle mouse drags
44 }
45
46 // Getters:
47 public Dimension getPreferredScrollableViewportSize() {
48 return getPreferredSize();
49 }
50
51 public Dimension getPreferredSize() {
52 if (missingPicture) {
53 return new Dimension(636, 340);
54 } else {
55 return super.getPreferredSize();
56 }
57 }
58
59 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
60 int direction) {
61 if (orientation == SwingConstants.HORIZONTAL) {
62 return visibleRect.width - maxUnitIncrement;
63 } else {
64 return visibleRect.height - maxUnitIncrement;
65 }
66 }
67
68 public boolean getScrollableTracksViewportHeight() {
69 return false;
70 }
71
72 public boolean getScrollableTracksViewportWidth() {
73 return false;
74 }
75
76 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
77 int direction) {
78
79 // Get the current position.
80 int currentPosition = 0;
81 if (orientation == SwingConstants.HORIZONTAL) {
82 currentPosition = visibleRect.x;
83 } else {
84 currentPosition = visibleRect.y;
85 }
86
87 // Return the number of pixels between currentPosition
88 // and the nearest tick mark in the indicated direction.
89 if (direction < 0) {
90 int newPosition = currentPosition
91 - (currentPosition / maxUnitIncrement) * maxUnitIncrement;
92 return (newPosition == 0) ? maxUnitIncrement : newPosition;
93 } else {
94 return ((currentPosition / maxUnitIncrement) + 1) * maxUnitIncrement
95 - currentPosition;
96 }
97 }
98
99 // Setters:
100 public void setMaxUnitIncrement(int pixels) {
101 maxUnitIncrement = pixels;
102 }
103
104 // Instance methods:
105 // Methods required by the MouseMotionListener interface:
106 public void mouseDragged(MouseEvent e) {
107 // The user is dragging us, so scroll!
108 Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
109 scrollRectToVisible(r);
110 }
111
112 public void mouseMoved(MouseEvent e) {
113 }
114 }
1 package view.scrollImageView;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import java.awt.image.*;
6 import javax.swing.*;
7
8 public class ScrollImageJPanel extends JPanel implements ItemListener {
9 // Source https://docs.oracle.com/javase/tutorial/uiswing/examples/components/
10 // ScrollDemo visited the 20/10/2015.
11 private static final long serialVersionUID = 1L;
12 private Ruler columnView;
13 private Ruler rowView;
14 private JToggleButton isMetric;
15 private ScrollablePicture picture;
16 private JScrollPane pictureScrollPane;
17
18 // Constructors:
19 public ScrollImageJPanel(BufferedImage bi) {
20 super();
21 this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
22
23 // Create the row and column headers.
24
25 columnView = new Ruler(Ruler.HORIZONTAL, true);
26 rowView = new Ruler(Ruler.VERTICAL, true);
27
28 ImageIcon pic = null;
29 pic = maakImageIcon(bi);
30
31 if (pic != null) {
32 columnView.setPreferredWidth(pic.getIconWidth());
33 rowView.setPreferredHeight(pic.getIconHeight());
34 } else {
35 columnView.setPreferredWidth(665);
36 rowView.setPreferredHeight(340);
37 }
38
39 // Create the corners.
40 JPanel buttonCorner = new JPanel(); // use FlowLayout
41 isMetric = new JToggleButton("cm/in", true);
42 isMetric.setFont(new Font("Arial Narrow", Font.PLAIN, 12));
43 isMetric.setMargin(new Insets(2, 2, 2, 2));
44 isMetric.addItemListener(this);
45 buttonCorner.add(isMetric);
46
47 // Set up the scroll pane.
48 if (pic != null) {
49 picture = new ScrollablePicture(pic, columnView.getIncrement());
50 } else {
51 picture = new ScrollablePicture(columnView.getIncrement());
52 }
53
54 pictureScrollPane = new JScrollPane(picture);
55
56 pictureScrollPane.setPreferredSize(new Dimension(300, 250));
57 pictureScrollPane
58 .setViewportBorder(BorderFactory.createLineBorder(Color.black));
59
60 pictureScrollPane.setColumnHeaderView(columnView);
61 pictureScrollPane.setRowHeaderView(rowView);
62
63 // Set the corners.
64 // In theory, to support internationalization you would change
65 // UPPER_LEFT_CORNER to UPPER_LEADING_CORNER,
66 // LOWER_LEFT_CORNER to LOWER_LEADING_CORNER, and
1 package view;
2
3 import java.awt.Dimension;
4 import java.awt.Graphics;
5 import java.awt.Image;
6 import java.awt.Toolkit;
7 import javax.swing.ImageIcon;
8 import javax.swing.JWindow;
9
10 import model.CBTHSettingsList;
11
12 //Source: http://java2everyone.blogspot.be/2009/03/java-transparent-splash-screen.html visited
13 //13/3/2016.
14 public class TransparentSplashScreen extends JWindow {
15 // transparent splashscreen.
16
17 private static final long serialVersionUID = 1L;
18 private Image bi;
19
20 // Constructor:
21 public TransparentSplashScreen(CBTHSettingsList cbthsl,
22 String[] stringComponents) {
23
24 // Get a partly transparent image that will be used as splash screen image.
25 this.bi = Toolkit.getDefaultToolkit()
26 .getImage(cbthsl.makeSysIndepFilePath(stringComponents, 2));
27 ImageIcon ii = new ImageIcon(bi);
28
29 try {
30 int iconWidth = ii.getIconWidth();
31 int iconHeight = ii.getIconHeight();
32
33 // Retrieve the screensize to precisely position the splashscreen.
34 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
35 int screenWidth = (int) screenSize.getWidth();
36 int screenHeight = (int) screenSize.getHeight();
37
38 // To center rounded rectangle on the screen, the splashscreen should be
39 // moved horizontally for an adittional 35px.
40 this.setBounds((screenWidth - iconWidth) / 2 + 35,
41 (screenHeight - iconHeight) / 2, iconWidth, iconHeight);
42
43 } catch (Exception exception) {
44 exception.printStackTrace();
45 }
46 }
47
48 /** Paint transparent image onto JWindow */
49 public void paint(Graphics g) {
50 g.drawImage(bi, 0, 0, this);
51 }
52 }
1 package view;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6 import javax.swing.border.*;
7
8 import cbthFileChooser.CBTHFileChooser;
9 import connection.conWithRobot.CommunicationRobotThread;
10 import console.ConsoleCommands;
11 import console.ViewConsolePanel;
12 import listeners.cam.T_CAM_LiveStreamItemListener;
13 import listeners.menu.*;
14 import model.*;
15
16 public class ViewCubeThesis extends JFrame {
17
18 private static final long serialVersionUID = 1L;
19 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
20
21 // Declaration of swing components: JPanel
22 private JPanel p_MainJPanel;
23 private JPanel p_PanelUpTabs;
24 private ViewConsolePanel p_PanelDownConsole;
25
26 private ViewTabPanel0Cam p_tabPanelCam;
27 private ViewTabPanel1Img p_tabPanelAfb;
28 private ViewTabPanel2Cub p_tabPanelKub;
29 private ViewTabPanel3Sol p_tabPanelOpl;
30 private ViewTabPanel4Aut p_tabPanelAut;
31
32 // Declaration of swing components: JSplitPane
33 private JSplitPane sp_splitTabsFromConsole;
34
35 // Declaration of swing components: JMenuBar
36 private JMenuBar menuBar;
37
38 // Declaration of swing components: JMenu
39 private JMenu menu_File;
40 private JMenu menu_Console;
41 private JMenu menu_CBTHSettings;
42 private JMenu menu_Help;
43
44 // Declaration of swing components: JMenuItem
45 private JMenuItem menuItem_NewProject;
46 private JMenuItem menuItem_OpenProject;
47 private JMenuItem menuItem_SaveProject;
48 private JMenuItem menuItem_SaveProjectAs;
49 private JMenuItem menuItem_Exit;
50 private JMenuItem menuItem_ClearConsole;
51 private JMenuItem menuItem_ListCommands;
52 private JMenuItem menuItem_CustomizeCBTHSettings;
53 private JMenuItem menuItem_ImportSettingsFromText;
54 private JMenuItem menuItem_ExportSettingsToText;
55 private JMenuItem menuItem_RestoreFactorySettings;
56 private JMenuItem menuItem_About;
57 private JMenuItem menuItem_Manual;
58 private JMenuItem menuItem_OpenJavaDoc;
59
60 // Declaration of swing components: JTabbedPane
61 private JTabbedPane tp_tabbedPane;
62
63 // Declaration of a CBTHFileChooser & a ConsoleCommands.
64 private CBTHFileChooser cbthfc;
65 private ConsoleCommands cc;
66
67 // Constructor:
68 /**
69 * This constructor build the main Window of CubeThesis.
70 *
71 * @param imgl
72 * The current CBTHImagesList is passed.
73 * @param cfl
74 * The current CubeFacesList is passed.
75 */
76 public ViewCubeThesis(CBTHImagesList imgl, CubeFacesList cfl) {
77
78 this.setLayout(new BorderLayout());
79 this.setTitle("CUBETHESIS 2015-2016");
80
81 String[] iconPath1Comp = { "img", "icon", "RubiksCube220x210.png" };
82 ImageIcon frameCubeThesisLogo = new ImageIcon(
83 cbthsl.makeSysIndepFilePath(iconPath1Comp, 2));
84
85 this.setIconImage(frameCubeThesisLogo.getImage());
86
87 // One object from CBTHFileChooser, will serve for both open/save purposes.
88 this.cbthfc = new CBTHFileChooser();
89
90 // The console panel is created:
91 p_PanelDownConsole = new ViewConsolePanel();
92
93 // To make CubeThesis react on input from the commandPrompt:
94 cc = new ConsoleCommands(imgl, cfl, cbthfc, p_PanelDownConsole);
95
96 p_MainJPanel = new JPanel(new BorderLayout());
97 p_MainJPanel.setBorder(BorderFactory.createTitledBorder(
98 BorderFactory.createLineBorder(Color.GRAY, 1),
99 "© THESIS SIMON DESCHUYTTER & PIETER DEPAMELAERE", TitledBorder.RIGHT,
100 TitledBorder.BELOW_BOTTOM));
101
102 p_PanelUpTabs = new JPanel(new GridLayout());
103 tp_tabbedPane = new JTabbedPane();
104
105 String[] iconPath2Comp = { "img", "icon", "WDLogo30x30OFF.png" };
106 ImageIcon tabicon = new ImageIcon(
107 cbthsl.makeSysIndepFilePath(iconPath2Comp, 2));
108
109 // TabPanels are created, as creating Objects from other ViewClasses.
110 // Some of these constructors are passed model related objects).
111
112 p_tabPanelCam = new ViewTabPanel0Cam(imgl);
113
114 p_tabPanelAfb = new ViewTabPanel1Img(cbthfc, imgl, cfl);
115 imgl.addObserver(p_tabPanelAfb);
116
117 p_tabPanelKub = new ViewTabPanel2Cub(cfl);
118 cfl.addObserver(p_tabPanelKub);
119
120 p_tabPanelOpl = new ViewTabPanel3Sol();
121
122 p_tabPanelAut = new ViewTabPanel4Aut(imgl, cfl);
123
124 // Adding the tabs to the tabbedPane:
125 tp_tabbedPane.addTab("CAMERA", tabicon, p_tabPanelCam, "Tabpanel [CAMERA]");
126 tp_tabbedPane.addTab("IMAGE", tabicon, p_tabPanelAfb, "Tabpanel [IMAGE]");
127 tp_tabbedPane.addTab("CUBE", tabicon, p_tabPanelKub, "Tabpanel [CUBE]");
128 tp_tabbedPane.addTab("ALGORITHMIC SOLVER", tabicon, p_tabPanelOpl,
129 "Tabpanel [ALGORITHMIC SOLVER]");
130 tp_tabbedPane.addTab("AUTOMATIC MODE", tabicon, p_tabPanelAut,
131 "Tabpanel [AUTOMATIC MODE]");
132
133 // Make sure the tabs can be browsed by little arrowkeys, when the screen
134 // get's to narrow:
135 tp_tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
136
137 // Adding the tabbedPane to the p_PanelUpTabs:
138 p_PanelUpTabs.add(tp_tabbedPane);
139
140 // Splitting the screen vertically, between p_PanelUpTabs &
141 // p_PanelDownConsole.
142 sp_splitTabsFromConsole = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
143 p_PanelUpTabs, p_PanelDownConsole);
144 sp_splitTabsFromConsole.setDividerLocation(425);
145
146 // Create the menuBar with its components:
147 menuBar = new JMenuBar();
148
149 menu_File = new JMenu("File");
150 menu_File.setMnemonic(KeyEvent.VK_F);
151
152 menu_Console = new JMenu("Console");
153 menu_Console.setMnemonic(KeyEvent.VK_C);
154
155 menu_CBTHSettings = new JMenu("CBTH-Settings");
156 menu_CBTHSettings.setMnemonic(KeyEvent.VK_S);
157
158 menu_Help = new JMenu("Help");
159 menu_Help.setMnemonic(KeyEvent.VK_H);
160
161 menuItem_NewProject = new JMenuItem("New project...");
162 menuItem_NewProject.addActionListener(
163 new MenuItemNewProjectListener(imgl, cfl, p_PanelDownConsole));
164
165 menuItem_OpenProject = new JMenuItem("Open project...");
166 menuItem_OpenProject.addActionListener(
167 new MenuItemOpenProjectListener(cbthfc, p_PanelDownConsole));
168
169 menuItem_SaveProject = new JMenuItem("Save project");
170 menuItem_SaveProject.addActionListener(new MenuItemSaveProjectListener());
171
172 menuItem_SaveProjectAs = new JMenuItem("Save project as...");
173 menuItem_SaveProjectAs
174 .addActionListener(new MenuItemSaveAsProjectListener(cbthfc));
175
176 menuItem_Exit = new JMenuItem("Save & exit");
177 menuItem_Exit
178 .addActionListener(new MenuItemExitListener(p_PanelDownConsole));
179
180 menuItem_ClearConsole = new JMenuItem("Flush & Clear");
181 menuItem_ClearConsole.addActionListener(
182 new MenuItemConsoleClearListener(p_PanelDownConsole));
183
184 menuItem_ListCommands = new JMenuItem("Commands...");
185 menuItem_ListCommands.addActionListener(
186 new MenuItemListCommandsListener(p_PanelDownConsole));
187
188 menuItem_CustomizeCBTHSettings = new JMenuItem("Customize settings...");
189 menuItem_CustomizeCBTHSettings
190 .addActionListener(new MenuItemCustomizeSettingsListener());
191
192 menuItem_ImportSettingsFromText = new JMenuItem(
193 "Import settings \u2190 text");
194 menuItem_ImportSettingsFromText
195 .addActionListener(new MenuItemImportSettingsFromText());
196
197 menuItem_ExportSettingsToText = new JMenuItem(
198 "Export settings \u2192 text");
199 menuItem_ExportSettingsToText
200 .addActionListener(new MenuItemExportSettingsToText());
201
202 menuItem_RestoreFactorySettings = new JMenuItem("Restore factory settings");
203 menuItem_RestoreFactorySettings
204 .setToolTipText("Restores the situation of Simon & Pieter 2015-2016");
205 menuItem_RestoreFactorySettings
206 .addActionListener(new MenuItemRestoreFactorySettings());
207
208 menuItem_About = new JMenuItem("About CubeThesis...");
209 menuItem_About.addActionListener(new MenuItemAboutListener());
210
211 menuItem_OpenJavaDoc = new JMenuItem("Browse JavaDoc...");
212 menuItem_OpenJavaDoc.addActionListener(new MenuItemJavaDocListener());
213 menuItem_OpenJavaDoc.setToolTipText(
214 "The JavaDoc yields an interactive summary of CubeThesis' source code.");
215
216 menuItem_Manual = new JMenuItem("Manual...");
217 menuItem_Manual.addActionListener(new MenuItemUserManualListener());
218
219 // Assembling the menuBar:
220 menu_File.add(menuItem_NewProject);
221 menu_File.add(menuItem_OpenProject);
222 menu_File.add(menuItem_SaveProject);
223 menu_File.add(menuItem_SaveProjectAs);
224 menu_File.addSeparator();
225 menu_File.add(menuItem_Exit);
226
227 menu_Console.add(menuItem_ClearConsole);
228 menu_Console.add(menuItem_ListCommands);
229
230 menu_CBTHSettings.add(menuItem_CustomizeCBTHSettings);
231 menu_CBTHSettings.addSeparator();
232 menu_CBTHSettings.add(menuItem_ImportSettingsFromText);
233 menu_CBTHSettings.add(menuItem_ExportSettingsToText);
234 menu_CBTHSettings.addSeparator();
235 menu_CBTHSettings.add(menuItem_RestoreFactorySettings);
236
237 menu_Help.add(menuItem_Manual);
238 menu_Help.add(menuItem_OpenJavaDoc);
239 menu_Help.addSeparator();
240 menu_Help.add(menuItem_About);
241
242 menuBar.add(menu_File);
243 menuBar.add(menu_Console);
244 menuBar.add(menu_CBTHSettings);
245 menuBar.add(menu_Help);
246
247 // Add the menuBar to the JFrame:
248 this.setJMenuBar(menuBar);
249
250 // Will allow the content to stretch to the available space.
251 p_MainJPanel.add(sp_splitTabsFromConsole, BorderLayout.CENTER);
252 this.add(p_MainJPanel, BorderLayout.CENTER);
253
254 // Elaborated procedure to precisely position the window in the middle of
255 // the screen.
256 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
257 int screenWidth = (int) screenSize.getWidth();
258 int screenHeight = (int) screenSize.getHeight();
259 int minimumWindowWidth = screenWidth / 4;
260 int minimumWindowHeight = 400;
261 int preferredWindowWidth = 1000;// (1000/620 +- golden ratio)
262 int preferredWindowHeight = 620;
263
264 this.setMinimumSize(new Dimension(minimumWindowWidth, minimumWindowHeight));
265 this.setPreferredSize(
266 new Dimension(preferredWindowWidth, preferredWindowHeight));
267
268 this.setBounds((screenWidth - preferredWindowWidth) / 2,
269 (screenHeight - preferredWindowHeight) / 2, 1000, 620);
270
271 // Disable the closing, when user clicks closebutton, but spawn warning:
272 this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
273 this.addWindowListener(new WindowAdapter() {
274 public void windowClosing(WindowEvent e) {
275 handleClosing();
276 }
277 });
278
279 // The command below will not spawn the window, that is done in the
280 // main-method.
281 this.pack();
282 }
283
284 // Getter:
285 public CBTHFileChooser getCBTHFileChooser() {
286 return this.cbthfc;
287 }
288
289 // Instance methods:
290 /** Here the user's answer on the warning dialog on closing is evaluated. */
291 public void handleClosing() {
292
293 int answer = showWarningMessage();
294
295 switch (answer) {
296 case JOptionPane.YES_OPTION:
297
298 CommunicationRobotThread comRobot = CommonObjects.getCommunicatieRobot();
299 T_CAM_LiveStreamItemListener camLSIL = CommonObjects.getCamLSIL();
300
301 // Communication with the robot is stopped if necessary:
302 if (comRobot.getLinkRobotEstablished()) {
303 comRobot.stopCommunicationRobot();
304 }
305
306 /*
307 * Connection with the camera device is closed. Not correctly closing the
308 * connection leads to the generation of a hs_err_pidxxx.log file.
309 */
310 if (camLSIL.getLinkCamEstablished()) {
311 camLSIL.disconnectFromCapDevice();
312 }
313
314 if (cbthsl.getBoolean("saveCBTHSettingsOnExit")) {
315 // If true, CBTHSettings are exported at this point.
316 cbthsl.exportCBTHSettingsToTXT();
317 }
318
319 // Remaining info is flushed to the LogFiles and footers are written.
320 p_PanelDownConsole.updateLogFilesByFlushConsole(false, true);
321
322 // Exit the program:
323 System.exit(0);
324
325 break;
326
327 case JOptionPane.CLOSED_OPTION:
328 break;
329
330 case JOptionPane.NO_OPTION:
331 break;
332 }
333 }
334
335 private int showWarningMessage() {
336 String[] buttonLabels = new String[] { "Yes", "No" };
337 String defaultOption = buttonLabels[1];
338 Icon icon = null;
339
340 return JOptionPane.showOptionDialog(this,
341 "Are you sure you want to quit? " + cbthsl.getString("newLine")
342 + "Unsaved progress will be lost.",
343 "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, icon,
344 buttonLabels, defaultOption);
345 }
346 }
1 package view;
2
3 import java.awt.*;
4 import javax.swing.*;
5
6 import exceptions.NoSuchSettingFoundException;
7 import model.CBTHImagesList;
8 import model.CBTHSetting;
9 import model.CBTHSettingsList;
10 import model.CommonObjects;
11 import listeners.cam.*;
12 import listeners.aut.B_AUT_CommandToRobotListener;
13
14 public class ViewTabPanel0Cam extends JPanel {
15
16 private static final long serialVersionUID = 1L;
17 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
18 private JSplitPane sp_split;
19 private JPanel p_ControlPanelLeft;
20 private JPanel p_WindowPanelRight;
21 private JPanel p_CBTHSettingsPanel;
22 private JPanel[] p_columnPanel = { new JPanel(new GridLayout(0, 1, 15, 5)),
23 new JPanel(new GridLayout(0, 1, 15, 5)) };;
24
25 private JButton b_CAMERA_ConnectCam;
26 private JToggleButton t_CAMERA_LiveStreamCam;
27 private JButton b_CAMERA_TakePicture;
28 private JButton b_CAMERA_ConnectRobot;
29 private JButton b_CAMERA_CommandToRobot;
30
31 private volatile JLabel l_cameraView;
32
33 // Constructor:
34 public ViewTabPanel0Cam(CBTHImagesList imgl) {
35
36 super(new BorderLayout());
37
38 // Create JComponents:
39 p_ControlPanelLeft = new JPanel();
40 p_ControlPanelLeft
41 .setLayout(new BoxLayout(p_ControlPanelLeft, BoxLayout.PAGE_AXIS));
42
43 p_WindowPanelRight = new JPanel(new BorderLayout());
44
45 l_cameraView = cbthsl.createJLabel(
46 " Toggle \"Camera livestream\" to retrieve a "
47 + "videostream from CaptureDevice.",1);
48 String[] iconPathComp = { "img", "icon", "CAMdfk23g445.png" };
49 l_cameraView
50 .setIcon(new ImageIcon(cbthsl.makeSysIndepFilePath(iconPathComp, 2)));
51
52 p_CBTHSettingsPanel = new JPanel(new BorderLayout());
53
54 String[] cbthSettingNames = { "captureDevice", "ipAddressCamera",
55 "ipAddressRobot", "portNmbrServerSocket" };
56 CBTHSetting cbths = null;
57 VisualCBTHSetting viscbths = null;
58 for (int i = 0; i < cbthSettingNames.length; i++) {
59 try {
60 cbths = cbthsl.seekCBTHSetting(cbthSettingNames[i]);
61 viscbths = cbths.createVCBTHSetting();
62
63 p_columnPanel[0].add(viscbths.getL_CBTHSLabel());
64 p_columnPanel[1].add(viscbths.getTF_CBTHSValue());
65
66 } catch (NoSuchSettingFoundException nssfe) {
67 System.err.println(nssfe);
68 }
69 }
70
71 p_CBTHSettingsPanel.add(p_columnPanel[0], BorderLayout.CENTER);
72 p_CBTHSettingsPanel.add(p_columnPanel[1], BorderLayout.LINE_END);
73
74 b_CAMERA_ConnectCam = cbthsl.createJButton("Connect to camera",
75 "Adjusts the capture-device's index.", new B_CAM_ConnectCamListener());
76
77 t_CAMERA_LiveStreamCam = cbthsl.createJToggleButton("Camera livestream",
78 "Tries to open livestream from camera.", false);
79 t_CAMERA_LiveStreamCam.setToolTipText(
80 "Opent een LiveStream van de camera in het rechtervenster.");
81 T_CAM_LiveStreamItemListener lsil = new T_CAM_LiveStreamItemListener(
82 l_cameraView);
83 CommonObjects.setCamLSIL(lsil);
84 t_CAMERA_LiveStreamCam.addItemListener(lsil);
85
86 b_CAMERA_TakePicture = cbthsl.createJButton("Take one picture",
87 "When livestream is toggled, a snapshot is taken.",
88 new B_CAM_TakeAPictureListener(imgl, lsil));
89 b_CAMERA_ConnectRobot = cbthsl.createJButton("Connect to robot",
90 "PC (server tries to establish connection with the robot (client).",
91 new B_CAM_ConnectRobotListener());
92 b_CAMERA_CommandToRobot = cbthsl.createJButton("Command \u2192 robot",
93 "User manually adds commands to robot's instruction-queue.",
94 new B_AUT_CommandToRobotListener());
95
96 // Assembling the p_ControlPanelLeft:
97 p_ControlPanelLeft.add(b_CAMERA_ConnectCam);
98 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
99 p_ControlPanelLeft.add(t_CAMERA_LiveStreamCam);
100 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
101 p_ControlPanelLeft.add(b_CAMERA_TakePicture);
102 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
103 p_ControlPanelLeft.add(b_CAMERA_ConnectRobot);
104 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
105 p_ControlPanelLeft.add(b_CAMERA_CommandToRobot);
106 p_ControlPanelLeft.add(new JLabel("––––––––––––––––––"));
107 p_CBTHSettingsPanel.setMaximumSize(new Dimension(Short.MAX_VALUE,
108 (int) p_CBTHSettingsPanel.getMinimumSize().getHeight()));
109 p_CBTHSettingsPanel.setAlignmentX(LEFT_ALIGNMENT);
110 p_ControlPanelLeft.add(p_CBTHSettingsPanel);
111 p_ControlPanelLeft.add(Box.createVerticalGlue()); // Fill blank space
112
113 p_WindowPanelRight.add(l_cameraView, BorderLayout.CENTER);
114
115 // Making a horizontal JSplitPane between p_ControlPanelLeft and
116 // p_WindowPanelRight.
117 sp_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
118 new JScrollPane(p_ControlPanelLeft,
119 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
120 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
121 new JScrollPane(p_WindowPanelRight));
122 sp_split.setDividerLocation(325);
123
124 this.add(sp_split, BorderLayout.CENTER);
125 }
126
127 // Getter:
128 public JLabel getLabelCamBeeld() {
129 return l_cameraView;
130 }
131 }
1 package view;
2
3 import java.awt.*;
4 import java.awt.image.*;
5 import java.util.Observable;
6 import java.util.Observer;
7 import javax.swing.*;
8
9 import cbthFileChooser.CBTHFileChooser;
10 import exceptions.NoSuchSettingFoundException;
11 import listeners.img.*;
12 import model.*;
13 import view.scrollImageView.*;
14
15 public class ViewTabPanel1Img extends JPanel implements Observer {
16
17 private static final long serialVersionUID = 1L;
18 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
19 private static Font guiFont1;
20 private CBTHImagesList imgl;
21 private CBTHImage imgTemporary;
22
23 private JSplitPane sp_split;
24 private JPanel p_ControlPanelLeft;
25 private JPanel p_WindowPanelRight;
26
27 private JPanel p_InputImagePanel;
28 private JPanel p_DeleteSavePanel;
29 private JPanel p_CropSpinnersPanel;
30 private JPanel p_CBTHSettingsPanel;
31
32 private JButton b_IMG_BrowseImage;
33 private JButton b_IMG_SaveImages;
34 private JButton b_IMG_DeleteImage;
35 private JButton b_IMG_ColorEstimation;
36 private JButton b_IMG_UpdateCropParams;
37 private JButton b_IMG_ColorCalibration;
38
39 private JComboBox<Object> cb_ImageDropDown;
40
41 private VisualCBTHSetting[] visualCBTHSettingsArray;
42
43 private Object[] cbthImagesList;
44 private S_IMG_CropSpinnersListener cropSpin;
45
46 // Spinners that are being used for the cropping:
47 private JSpinner s_IMG_X_CO;
48 private JSpinner s_IMG_Y_CO;
49 private JSpinner s_IMG_Width;
50 private JSpinner s_IMG_Height;
51
52 // Constructor:
53 public ViewTabPanel1Img(CBTHFileChooser cbthFC, CBTHImagesList imgl,
54 CubeFacesList cfl) {
55
56 super(new BorderLayout());
57
58 guiFont1 = cbthsl.getFont("guiFont1");
59
60 // Create JComponents:
61 p_ControlPanelLeft = new JPanel();
62 p_ControlPanelLeft
63 .setLayout(new BoxLayout(p_ControlPanelLeft, BoxLayout.PAGE_AXIS));
64 p_InputImagePanel = new JPanel(new BorderLayout());
65 p_DeleteSavePanel = new JPanel(new GridLayout(1, 2));
66 p_CropSpinnersPanel = new JPanel();
67 p_CropSpinnersPanel
68 .setLayout(new BoxLayout(p_CropSpinnersPanel, BoxLayout.PAGE_AXIS));
69 p_CBTHSettingsPanel = new JPanel(new GridLayout(0, 1, 15, 5));
70 p_WindowPanelRight = new JPanel(new BorderLayout());
71
72 // ImagesList is set the subject of the cb_ImageDropDown-ComboBox:
73 cbthImagesList = imgl.getCBTHImages().toArray();
74 cb_ImageDropDown = new JComboBox<Object>(cbthImagesList);
75 cb_ImageDropDown.setFont(guiFont1);
76 cb_ImageDropDown.setEditable(false);
77 cb_ImageDropDown
78 .addItemListener(new Co_IMG_CBTHImagesListDropdownListener(this));
79
80 // WindowPanelRight always remains, but new ScrollImageJPanel-instances
81 // could be added.
82 p_WindowPanelRight.add(new ScrollImageJPanel(null), BorderLayout.CENTER);
83
84 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
85 int screenWidth = (int) screenSize.getWidth();
86 p_InputImagePanel.setMaximumSize(new Dimension(screenWidth, 25));
87 this.imgl = imgl;
88
89 // Creation of JButtons:
90 b_IMG_BrowseImage = cbthsl.createJButton("Browse img...",
91 "Launches pop-up to browse for img-files.",
92 new B_IMG_BrowseImageListener(cbthFC, imgl));
93 b_IMG_SaveImages = cbthsl.createJButton("Save images",
94 "Images from combobox are saved to original/cropped folders "
95 + "in the current project.",
96 new B_IMG_SaveImagesListener());
97 b_IMG_DeleteImage = cbthsl.createJButton("Delete image",
98 "Deletes selected image", new B_IMG_DeleteImageListener(this, imgl));
99 b_IMG_UpdateCropParams = cbthsl.createJButton("Update crop-parameters",
100 "Will update automatic crop-parameters for future snapshots.",
101 new B_IMG_UpdateCropParamListener(this));
102 b_IMG_ColorCalibration = cbthsl.createJButton("Color calibration",
103 "Will adapt color-estimation ranges based on camera-input.",
104 new B_IMG_ColorCalibrationListener());
105 b_IMG_ColorEstimation = cbthsl.createJButton("Color estimation",
106 "Partitions the image in 9 pieces, then performs colors estimation on those facelets.",
107 new B_IMG_ColorEstimationListener(this, cfl));
108
109 // Create crop-spinners:
110 String[] cropSpinToolTips = { "X-co cropped image", "Y-co cropped image",
111 "Width cropped image", "Height cropped image" };
112 s_IMG_X_CO = createCropSpinner(cropSpinToolTips[0]);
113 s_IMG_Y_CO = createCropSpinner(cropSpinToolTips[1]);
114 s_IMG_Width = createCropSpinner(cropSpinToolTips[2]);
115 s_IMG_Height = createCropSpinner(cropSpinToolTips[3]);
116
117 p_CropSpinnersPanel.add(s_IMG_X_CO);
118 p_CropSpinnersPanel.add(s_IMG_Y_CO);
119 p_CropSpinnersPanel.add(s_IMG_Width);
120 p_CropSpinnersPanel.add(s_IMG_Height);
121
122 // Initialize crop-spinners:
123 updateImgCropSpinners(null);
124
125 // Arrangement of some CBTHSettings on this tab:
126 visualCBTHSettingsArray = new VisualCBTHSetting[4];
127
128 try {
129 visualCBTHSettingsArray[0] = cbthsl
130 .seekCBTHSetting("thresholdColorEstimation").createVCBTHSetting();
131 visualCBTHSettingsArray[1] = cbthsl
132 .seekCBTHSetting("extensiveSampleOutprint").createVCBTHSetting();
199 p_ControlPanelLeft.add(b_IMG_ColorEstimation);
200 p_ControlPanelLeft.add(Box.createVerticalGlue()); // Fill blank space
201
202 this.add(sp_split, BorderLayout.CENTER);
203 }
204
205 // Getters:
206 public CBTHImage getImgCombo() {
207 return (CBTHImage) cb_ImageDropDown.getSelectedItem();
208 }
209
210 public CBTHImage getImgTemporary() {
211 return imgTemporary;
212 }
213
214 public JSpinner getS_IMG_Height() {
215 return s_IMG_Height;
216 }
217
218 public JSpinner getS_IMG_Width() {
219 return s_IMG_Width;
220 }
221
222 public JSpinner getS_IMG_X_CO() {
223 return s_IMG_X_CO;
224 }
225
226 public JSpinner getS_IMG_Y_CO() {
227 return s_IMG_Y_CO;
228 }
229
230 // Instance methods:
231 /**
232 * This method is part of the Observer-Observable technique. It gets triggered
233 * when the CBTHImagesList wants to. (Normally when changes occur.) Will
234 * update the combobox or images-dropdownlist, when new CBTHImages appear/get
235 * deleted.
236 */
237 public void update(Observable arg0, Object arg1) {
238 cb_ImageDropDown.removeAllItems();
239
240 int i, k = imgl.getSize();
241
242 for (i = 0; i < k; i++) {
243 cb_ImageDropDown.addItem(imgl.getCBTHImage(i));
244 }
245
246 /*
247 * After an update, the dropdown will show the most recent Image. "i-1" is
248 * needed because the
249 */
250 if (k > 0) {
251 cb_ImageDropDown.setSelectedItem(imgl.getCBTHImage(i - 1));
252 }
253 }
254
255 /**
256 * Is used to update the cropspinners with newly selected image from the
257 * dropdown. When an image was deleted, this method is also invoked.
258 */
259 public void updateImgCropSpinners(CBTHImage img) {
260
261 imgTemporary = img;
262
263 // Remove the listeners of the spinners:
264 try {
265 s_IMG_X_CO.removeChangeListener(cropSpin);
266 } catch (NullPointerException npe) {
267 }
268 try {
269 s_IMG_Y_CO.removeChangeListener(cropSpin);
270 } catch (NullPointerException npe) {
271 }
272 try {
273 s_IMG_Width.removeChangeListener(cropSpin);
274 } catch (NullPointerException npe) {
275 }
276 try {
277 s_IMG_Height.removeChangeListener(cropSpin);
278 } catch (NullPointerException npe) {
279 }
280
281 // Create a new S_IMG_CropSpinnersListener:
282 cropSpin = new S_IMG_CropSpinnersListener(this, img, s_IMG_X_CO, s_IMG_Y_CO,
283 s_IMG_Width, s_IMG_Height);
284
285 if (img != null) {
286 s_IMG_X_CO.setModel(new SpinnerNumberModel(img.getCroppedXPos(), 0,
287 img.getWidthOriginal(), 1));
288 s_IMG_Y_CO.setModel(new SpinnerNumberModel(img.getCroppedYPos(), 0,
289 img.getHeightOriginal(), 1));
290 s_IMG_Width.setModel(new SpinnerNumberModel(img.getCroppedWidth(), 1,
291 img.getWidthOriginal(), 1));
292 s_IMG_Height.setModel(new SpinnerNumberModel(img.getCroppedHeight(), 1,
293 img.getHeightOriginal(), 1));
294 // Width & height have to be >= 1.
295
296 updateImgWindow(img);
297 }
298
299 else {
300 s_IMG_X_CO.setModel(new SpinnerNumberModel(0, 0, 100, 1));
301 s_IMG_Y_CO.setModel(new SpinnerNumberModel(0, 0, 100, 1));
302 s_IMG_Width.setModel(new SpinnerNumberModel(1, 1, 100, 1));
303 s_IMG_Height.setModel(new SpinnerNumberModel(1, 1, 100, 1));
304 }
305
306 s_IMG_X_CO.addChangeListener(cropSpin);
307 s_IMG_Y_CO.addChangeListener(cropSpin);
308 s_IMG_Width.addChangeListener(cropSpin);
309 s_IMG_Height.addChangeListener(cropSpin);
310
311 p_CropSpinnersPanel.repaint();
312 p_CropSpinnersPanel.revalidate();
313
314 /*
315 * Not necessary: this.repaint(); this.revalidate();
316 */
317 }
318
319 /**
320 * This method is responsible for the refreshment of the (cropped) image on
321 * the p_WindowPanelRight.
322 */
323 public void updateImgWindow(CBTHImage img) {
324
325 // Old content of p_WindowPanelRight is removed:
326 p_WindowPanelRight.removeAll();
327 p_WindowPanelRight.repaint();
328 p_WindowPanelRight.revalidate();
329
330 // New content is added:
1 package view;
2
3 import java.awt.*;
4 import javax.swing.*;
5 import java.util.Observable;
6 import java.util.Observer;
7
8 import listeners.cube.*;
9 import model.*;
10
11 public class ViewTabPanel2Cub extends JPanel implements Observer {
12
13 private static final long serialVersionUID = 1L;
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15 private JSplitPane sp_split1;
16 private JSplitPane sp_split2;
17
18 private JPanel p_ControlPanelLeft;
19 private JPanel p_CubeFacePanelUp;
20 private JPanel p_CubeFacePanelDown;
21 private JPanel p_RotateAndNavigatePanel;
22
23 private JButton b_CUBE_AssignToMainCubeFace;
24 private JButton b_CUBE_DeleteCubeFace;
25 private JButton b_CUBE_RotateCubeFaceLeft;
26 private JButton b_CUBE_RotateCubeFaceRight;
27 private JButton b_CUBE_NavigateNextCubeFace;
28 private JButton b_CUBE_NavigatePreviousCubeFace;
29 private JButton b_CUBE_BuildVirtualCube;
30
31 private JComboBox<CubeFace> cb_MainCubeFacesCombo;
32 private CubeFace[] mainCubeFacesArray;
33 private VisualCubeFace[] visualMainCubeFaces;
34 private CubeFace currentCubeFace;
35 private CubeFacesList cfl;
36
37 // Constructor:
38 public ViewTabPanel2Cub(CubeFacesList cfl) {
39 super(new BorderLayout());
40
41 Font guiFont1 = cbthsl.getFont("guiFont1");
42
43 // Create JComponents:
44 p_ControlPanelLeft = new JPanel();
45 p_ControlPanelLeft
46 .setLayout(new BoxLayout(p_ControlPanelLeft, BoxLayout.PAGE_AXIS));
47
48 p_CubeFacePanelUp = new JPanel();
49 p_CubeFacePanelDown = new JPanel();
50
51 this.cfl = cfl;
52 currentCubeFace = null;
53
54 mainCubeFacesArray = cfl.getAllMainCubeFaces();
55 visualMainCubeFaces = new VisualCubeFace[mainCubeFacesArray.length];
56 for (int i = 0; i < mainCubeFacesArray.length; i++) {
57 visualMainCubeFaces[i] = mainCubeFacesArray[i].createVCubeFace();
58 }
59
60 cb_MainCubeFacesCombo = new JComboBox<CubeFace>(mainCubeFacesArray);
61 cb_MainCubeFacesCombo.setFont(guiFont1);
62 Co_CUBE_MainCFacesDropdownListener mcfdl = new Co_CUBE_MainCFacesDropdownListener(
63 this);
64 cb_MainCubeFacesCombo.addItemListener(mcfdl);
65
66 // Create JButtons:
67 b_CUBE_AssignToMainCubeFace = cbthsl.createJButton(
68 "Assign cubeface \u2191",
69 "Will assign the cubeface from below to the selected maincubeface.",
70 new B_CUBE_AssignToMainCubeFaceListener(this));
71 b_CUBE_BuildVirtualCube = cbthsl.createJButton("Build virtual cube",
72 "Will build a virtual cube according to the maincubefaces.",
73 new B_CUBE_BuildVirtualCubeListener(cfl));
74 b_CUBE_DeleteCubeFace = cbthsl.createJButton("Delete cubeface",
75 "Will remove the selected cubeface from the list below.",
76 new B_CUBE_DeleteCubeFaceListener(this, cfl));
77 b_CUBE_RotateCubeFaceLeft = cbthsl.createJButton("\u21BA",
78 "Will rotate the current cubeface 90° counterclockwise.",
79 new B_CUBE_TurnCFace90Degrees(this, false));
80 b_CUBE_RotateCubeFaceRight = cbthsl.createJButton("\u21BB",
81 "Will rotate the current cubeface 90° counterclockwise.",
82 new B_CUBE_TurnCFace90Degrees(this, true));
83
84 b_CUBE_RotateCubeFaceLeft
85 .setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 20));
86 b_CUBE_RotateCubeFaceRight
87 .setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 20));
88
89 String[] iconPathCompNextButton = { "img", "icon", "Play-icon.png" };
90 String[] iconPathCompPreviousButton = { "img", "icon",
91 "ReversePlay-icon.png" };
92
93 b_CUBE_NavigatePreviousCubeFace = cbthsl.createJButton(null,
94 "Navigates to the previous cubeface in the list.",
95 new B_CUBE_PreviousCubeFaceListener(this, cfl));
96 b_CUBE_NavigatePreviousCubeFace.setIcon(new ImageIcon(
97 cbthsl.makeSysIndepFilePath(iconPathCompPreviousButton, 2)));
98
99 b_CUBE_NavigateNextCubeFace = cbthsl.createJButton(null,
100 "Navigates to the next cubeface in the list.",
101 new B_CUBE_NextCubeFaceListener(this, cfl));
102 b_CUBE_NavigateNextCubeFace.setIcon(
103 new ImageIcon(cbthsl.makeSysIndepFilePath(iconPathCompNextButton, 2)));
104
105 // Assembling the p_ControlPanelLeft:
106 cb_MainCubeFacesCombo.setAlignmentX(LEFT_ALIGNMENT);
107 cb_MainCubeFacesCombo
108 .setMaximumSize(cb_MainCubeFacesCombo.getMinimumSize());
109 p_ControlPanelLeft.add(cb_MainCubeFacesCombo);
110 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
111 p_ControlPanelLeft.add(b_CUBE_AssignToMainCubeFace);
112 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
113 p_ControlPanelLeft.add(b_CUBE_DeleteCubeFace);
114 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
115
116 p_RotateAndNavigatePanel = new JPanel(new GridLayout(2, 2));
117 p_RotateAndNavigatePanel.add(b_CUBE_RotateCubeFaceLeft);
118 p_RotateAndNavigatePanel.add(b_CUBE_RotateCubeFaceRight);
119 p_RotateAndNavigatePanel.add(b_CUBE_NavigatePreviousCubeFace);
120 p_RotateAndNavigatePanel.add(b_CUBE_NavigateNextCubeFace);
121
122 Dimension d = p_RotateAndNavigatePanel.getMinimumSize();
123 Dimension e = p_RotateAndNavigatePanel.getMaximumSize();
124
125 p_RotateAndNavigatePanel.setMaximumSize(new Dimension(e.width, d.height));
126 p_RotateAndNavigatePanel.setAlignmentX(LEFT_ALIGNMENT);
127 p_ControlPanelLeft.add(p_RotateAndNavigatePanel);
128 p_ControlPanelLeft.add(Box.createRigidArea(new Dimension(0, 10)));
129
130 p_ControlPanelLeft.add(b_CUBE_BuildVirtualCube);
131
132 // Making a vertical JSplitPane for the CubeFaces-array's.
1 package view;
2
3 import java.awt.BorderLayout;
4 import java.awt.Dimension;
5 import java.awt.FlowLayout;
6
7 import javax.swing.*;
8
9 import exceptions.NoSuchSettingFoundException;
10 import listeners.solv.*;
11 import model.CBTHSettingsList;
12 import model.CommonObjects;
13
14 public class ViewTabPanel3Sol extends JPanel {
15
16 private static final long serialVersionUID = 1L;
17 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
18
19 private JSplitPane split;
20 private JPanel p_ControlPanelLeft;
21 private JPanel p_WindowPanelRight;
22 private JPanel p_OneSettingPanel;
23
24 private JButton b_SOLV_CubeToSolver;
25 private JButton b_SOLV_SolutionToRobot;
26 private JButton b_SOLV_EnumerateMoves;
27 private JButton b_SOLV_BlenderGUI;
28
29 private VisualCBTHSetting vcbthsUpdateVisWithRobot;
30
31 // Constructor:
32 public ViewTabPanel3Sol() {
33
34 super(new BorderLayout());
35
36 // Create JComponents:
37 p_ControlPanelLeft = new JPanel();
38 p_ControlPanelLeft
39 .setLayout(new BoxLayout(p_ControlPanelLeft, BoxLayout.PAGE_AXIS));
40
41 b_SOLV_CubeToSolver = cbthsl.createJButton("Cube \u2192 solver",
42 "Virtual cube will be loaded to the solver.",
43 CommonObjects.getCubeToSolver());
44 b_SOLV_SolutionToRobot = cbthsl.createJButton("Solution \u2192 robot",
45 "Will add the solution to the robot's instruction-queue.",
46 CommonObjects.getMoveSeqToRobot());
47 b_SOLV_EnumerateMoves = cbthsl.createJButton(
48 "Enumerate solution-commands.",
49 "This function will print out the solution commands if calculated.",
50 new B_SOLV_EnumerateMovesListener());
51 b_SOLV_BlenderGUI = cbthsl.createJButton("BlenderGUI",
52 "Will show a visualization upon Cubie's internal cube representation.",
53 new B_SOLV_BlenderGUIListener());
54
55 String[] iconPathComp = { "img", "icon", "Blender-icon22x23.png" };
56 b_SOLV_BlenderGUI
57 .setIcon(new ImageIcon(cbthsl.makeSysIndepFilePath(iconPathComp, 2)));
58
59 try {
60 vcbthsUpdateVisWithRobot = cbthsl
61 .seekCBTHSetting("updateVisualizationWithRobot").createVCBTHSetting();
62
63 } catch (NoSuchSettingFoundException nssfe) {
64 System.err.println(nssfe);
65 }
66
1 package view;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Dimension;
6 import java.awt.GridLayout;
7 import javax.swing.*;
8
9 import exceptions.NoSuchSettingFoundException;
10 import model.*;
11 import listeners.aut.*;
12
13 public class ViewTabPanel4Aut extends JPanel {
14
15 private static final long serialVersionUID = 1L;
16 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
17 private static String[][] textSubTasks = {
18 { "[1] Read cube", "[2] Build virtual cube", "[3] Solve algorithmic",
19 "[4] Send solution" },
20 { "Dient aangevinkt te worden indien automatische werking de kubus nog moet inlezen.",
21 "Dient aangevinkt te worden indien de virtuele kubus nog moet worden opgebouwd tijdens
22 automatische werking.",
23 "Dient aangevinkt te worden indien de solver van Jaap Scherphuis de oplossing nog moet
24 berekenen.",
25 "Dient te worden aangevinkt als men de Robot wil aansturen met oplossings commando's." } };
26
27 private JSplitPane sp_split;
28 private JPanel p_ControlPanelLeft;
29 private JPanel p_WindowPanelRight;
30
31 private JToggleButton[] toggleIncludeTasks;
32 private JButton b_AUT_CommandToRobot;
33 private JButton b_AUT_AutomaticRoutine;
34 private JButton b_AUT_StopAutoRoutine;
35
36 private ViewTabSubPanelAut[] vtspa;
37
38 private JLabel l_IncludeTasks;
39
40 private JTextArea ta_CubeConfig;
41 private JTextArea ta_CommandsToRobot;
42
43 // Constructor:
44 public ViewTabPanel4Aut(CBTHImagesList imgl, CubeFacesList cfl) {
45
46 super(new BorderLayout());
47
48 // Create JComponents:
49 p_ControlPanelLeft = new JPanel();
50 p_ControlPanelLeft
51 .setLayout(new BoxLayout(p_ControlPanelLeft, BoxLayout.PAGE_AXIS));
52
53 toggleIncludeTasks = new JToggleButton[4];
54 for (int i = 0; i < toggleIncludeTasks.length; i++) {
55 toggleIncludeTasks[i] = cbthsl.createJToggleButton(textSubTasks[0][i],
56 textSubTasks[1][i], true);
57 toggleIncludeTasks[i].addItemListener(new T_AUT_SubTasksItemListener(i));
58 }
59
60 b_AUT_AutomaticRoutine = cbthsl.createJButton("Automatic routine",
61 "Will perform the one-click automatic routine.",
62 new B_AUT_AutomaticRoutineListener(imgl, cfl, this));
63 b_AUT_StopAutoRoutine = cbthsl.createJButton("Stop auto. routine",
64 "Will stop the automatic procedure as quickly as possible.",
65 new B_AUT_StopAutoRoutineListener());
66 b_AUT_CommandToRobot = cbthsl.createJButton("Command \u2192 robot",
133 * labeltexts from the CBTHSetting, while the right column will provide a
134 * sync-ing JTextField.
135 */
136 panel.setLayout(new GridLayout(0, 2, 15, 5));
137
138 String[][] cbthSettingsToBeListed = {
139 { "captureDevice", "xCoCrop", "yCoCrop", "widthCrop", "heightCrop" },
140 { "amountOfSamplesPerFacelet", "amountOfSampleAveraging",
141 "thresholdColorEstimation", "extensiveSampleOutprint" },
142 { "cubeReadingToppleArray", "cubeReadingMCFRotationArray",
143 "cubeReadingMCFAssignArray" } };
144 JLabel[] interjectionLabels = {
145 cbthsl.createJLabel("––––––––––––––––––", 1),
146 cbthsl.createJLabel("WARNING! ADVANCED SETTINGS:", 3) };
147
148 for (int i = 0; i < cbthSettingsToBeListed.length; i++) {
149 addSettingsToSubPanel(panel, cbthSettingsToBeListed[i]);
150 if (i < cbthSettingsToBeListed.length - 1) {
151 panel.add(interjectionLabels[i]);
152 panel.add(new JPanel());
153 }
154 }
155 return panel;
156 }
157
158 public JPanel makeSendSolutionSubPanel() {
159 JPanel panel = new JPanel(new BorderLayout());
160 ta_CommandsToRobot = new JTextArea(7, 20);
161 ta_CommandsToRobot.setEditable(false);
162 ta_CommandsToRobot.setFont(cbthsl.getFont("guiFont2"));
163 String newLine = cbthsl.getString("newLine");
164 ta_CommandsToRobot.setText(newLine + newLine
165 + "<Solution sequence will be displayed here, once available.>");
166
167 panel.add(
168 new JScrollPane(ta_CommandsToRobot,
169 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
170 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS),
171 BorderLayout.CENTER);
172 return panel;
173 }
174
175 public JPanel makeSolveAlgorithmicSubPanel() {
176 JPanel panel = new JPanel();
177 panel.setLayout(new GridLayout(0, 2, 15, 5));
178
179 String[] cbthSettingsToBeListed = { "timeToSolveAlgorithm" };
180
181 addSettingsToSubPanel(panel, cbthSettingsToBeListed);
182
183 return panel;
184 }
185
186 public JPanel makeVirtualCubeSubPanel() {
187 JPanel panel = new JPanel(new BorderLayout());
188 ta_CubeConfig = new JTextArea(7, 20);
189 ta_CubeConfig.setEditable(false);
190 ta_CubeConfig.setFont(cbthsl.getFont("guiFont2"));
191 String newLine = cbthsl.getString("newLine");
192 ta_CubeConfig.setText(newLine + newLine
193 + "<Virtual cube will be displayed here, once available.>");
194
195 panel.add(
196 new JScrollPane(ta_CubeConfig,
197 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
198 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS),
199 BorderLayout.CENTER);
200 return panel;
201 }
202
203 /**
204 * Controls the green Logo's on the ViewTabSubpanelAut's: whether they should
205 * highlight or not.
206 *
207 * @param indexSubtask
208 * Which subtask needs to be highlighted.
209 * @param onOff
210 * To toggle the logo on/off.
211 */
212 public void setLogoOnOffVtspa(int indexSubtask, boolean onOff) {
213 vtspa[indexSubtask].setOnOff(onOff);
214 }
215
216 /** Will update the solution textArea on the tab [AUTOMATIC MODE] */
217 public void updateSendSolutionSubPanel() {
218 ta_CommandsToRobot.setText(CommandSeq.solutionCommandsMatrixToString());
219 }
220
221 /** Will update the virtual cube textArea on the tab [AUTOMATIC MODE] */
222 public void updateVirtCubeSubPanel() {
223 ta_CubeConfig.setText(CubeConfiguration.cubeConfigPrint());
224 }
225
226 // Static method:
227 /**
228 * This method will add CBTHSettings to some JPanel
229 *
230 * @param panel
231 * The JPanel where the settings need te
232 * @param cbthSettingsToBeListed
233 * Array of Strings with CBTHSetting-names.
234 */
235 public static void addSettingsToSubPanel(JPanel panel,
236 String[] cbthSettingsToBeListed) {
237 CBTHSetting cbths = null;
238 VisualCBTHSetting viscbths = null;
239
240 for (int j = 0; j < cbthSettingsToBeListed.length; j++) {
241 try {
242 cbths = cbthsl.seekCBTHSetting(cbthSettingsToBeListed[j]);
243 viscbths = cbths.createVCBTHSetting();
244
245 panel.add(viscbths.getL_CBTHSLabel());
246 panel.add(viscbths.getTF_CBTHSValue());
247
248 } catch (NoSuchSettingFoundException nssfe) {
249 System.err.println(nssfe);
250 }
251 }
252 }
253 }
1 package view;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import javax.swing.*;
6
7 import model.CBTHSettingsList;
8 import model.CommonObjects;
9
10 public class ViewTabSubPanelAut extends JPanel {
11
12 private static final long serialVersionUID = 1L;
13 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
14 private static String[] iconPathCompON = { "img", "icon",
15 "WDLogo30x30ON.png" };
16 private static String[] iconPathCompOFF = { "img", "icon",
17 "WDLogo30x30OFF.png" };
18 private static String iconPathON = cbthsl.makeSysIndepFilePath(iconPathCompON,
19 2);
20 private static String iconPathOFF = cbthsl
21 .makeSysIndepFilePath(iconPathCompOFF, 2);
22 private static final ImageIcon cbthIconON = new ImageIcon(iconPathON);
23 private static final ImageIcon cbthIconOFF = new ImageIcon(iconPathOFF);
24
25 private JLabel titleLabel;
26 private String title;
27 private JPanel content;
28 private BorderLayout borderLayout;
29
30 // Constructor:
31 public ViewTabSubPanelAut(String title, boolean active, JPanel content) {
32
33 this.title = title;
34 this.titleLabel = cbthsl.createJLabel(this.title, 1);
35 titleLabel.setForeground(Color.GREEN);
36 titleLabel.setBackground(new Color(60, 30, 6));
37 titleLabel.setOpaque(true);
38
39 if (active) {
40 titleLabel.setIcon(cbthIconON);
41 } else {
42 titleLabel.setIcon(cbthIconOFF);
43 }
44
45 this.content = content;
46
47 this.borderLayout = new BorderLayout();
48 this.setLayout(borderLayout);
49
50 this.add(titleLabel, BorderLayout.PAGE_START);
51 if (content != null) {
52 this.add(this.content, BorderLayout.CENTER);
53 }
54 }
55
56 // Setters:
57 /**
58 * Sets content-panel.
59 *
60 * @param newContent
61 * A JPanel is passed.
62 */
63 public void setContent(JPanel newContent) {
64 this.content = newContent;
65
66 this.revalidate();
67 this.repaint();
68 }
69
70 /**
71 * Will put logo on/off
72 *
73 * @param onOff
74 * Boolean On = true
75 */
76 public void setOnOff(boolean onOff) {
77
78 if (onOff) {
79 titleLabel.setIcon(cbthIconON);
80 } else {
81 titleLabel.setIcon(cbthIconOFF);
82 }
83 this.revalidate();
84 this.repaint();
85 }
86 }
1 package view;
2
3 import java.util.Observable;
4 import java.util.Observer;
5 import javax.swing.*;
6
7 import listeners.cbthsettings.TF_VisualCBTHSettingListener;
8 import model.CBTHSetting;
9 import model.CBTHSettingsList;
10 import model.CommonObjects;
11
12 public class VisualCBTHSetting implements Observer {
13
14 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
15 private CBTHSetting cbths;
16 private JTextField tf_CBTHSValue;
17 private JLabel l_CBTHSLabel;
18
19 // Constructors:
20 public VisualCBTHSetting() {
21 super();
22 this.cbths = null;
23 }
24
25 public VisualCBTHSetting(CBTHSetting cbths) {
26 super();
27 this.cbths = cbths;
28
29 this.tf_CBTHSValue = cbthsl.createJTextField(cbths.getValue(),
30 cbths.getEditable(), cbths.getInfo());
31
32 if (cbths.getEditable()) {
33 // ActionListener/DocumentListener is added to register updates from user.
34 tf_CBTHSValue
35 .addActionListener(new TF_VisualCBTHSettingListener(cbths, this));
36 }
37
38 this.l_CBTHSLabel = cbthsl.createJLabel(cbths.getLabelText(), 1);
39 this.l_CBTHSLabel.setToolTipText(cbths.getName());
40 }
41
42 // Getters:
43 public JLabel getL_CBTHSLabel() {
44 return l_CBTHSLabel;
45 }
46
47 public JTextField getTF_CBTHSValue() {
48 return tf_CBTHSValue;
49 }
50
51 // Instance method:
52 /**
53 * This method is part of the Observer-Observable technique. It gets triggered
54 * when the CBTHSetting wants to. (Normally when changes occur.)
55 */
56 public void update(Observable arg0, Object arg1) {
57
58 // Optional: To also refresh the label, each time the value changes.
59 /*
60 * l_CBTHSLabel.setText(cbths.getLabelText()); l_CBTHSLabel.repaint();
61 */
62
63 tf_CBTHSValue.setText(cbths.getValue());
64 tf_CBTHSValue.setToolTipText(cbths.getInfo());
65 }
66 }
1 package view;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.awt.GridLayout;
7 import java.util.ArrayList;
8 import java.util.Observable;
9 import java.util.Observer;
10 import javax.swing.*;
11
12 import listeners.cbthsettings.TF_SettingsCustomizerDocumentListener;
13 import model.CommonObjects;
14 import model.CBTHSetting;
15 import model.CBTHSettingsList;
16
17 public class VisualCBTHSettingsCustomizer extends JPanel implements Observer {
18
19 private static final long serialVersionUID = 1L;
20 private CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
21 private JPanel p_CBTHSettingSelection;
22
23 private JTextField tf_DynamicSearchBar;
24 private JScrollPane sp_ScrollPane;
25
26 // Constructor:
27 public VisualCBTHSettingsCustomizer() {
28
29 super(new BorderLayout());
30
31 p_CBTHSettingSelection = new JPanel();
32 p_CBTHSettingSelection
33 .setLayout(new BoxLayout(p_CBTHSettingSelection, BoxLayout.PAGE_AXIS));
34
35 // Listen for changes in the text
36 String s_DynamicFilterBar =
37 "Dynamic filterbar: Specify fragment of CBTHSetting's [name] "
38 + "or [labeltext] to filter.";
39 tf_DynamicSearchBar = cbthsl.createJTextField(s_DynamicFilterBar, true,
40 s_DynamicFilterBar);
41 tf_DynamicSearchBar.getDocument().addDocumentListener(
42 new TF_SettingsCustomizerDocumentListener(tf_DynamicSearchBar));
43 tf_DynamicSearchBar.selectAll();
44
45 sp_ScrollPane = new JScrollPane(p_CBTHSettingSelection,
46 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
47 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
48 sp_ScrollPane.setMaximumSize(sp_ScrollPane.getMinimumSize());
49
50 update(null, null);
51
52 this.add(tf_DynamicSearchBar, BorderLayout.PAGE_START);
53
54 sp_ScrollPane.setPreferredSize(new Dimension(500, 400));
55
56 this.add(sp_ScrollPane, BorderLayout.CENTER);
57 this.add(new JLabel(), BorderLayout.PAGE_END);
58
59 this.repaint();
60 }
61
62 // Instance method:
63 /**
64 * This method is part of the Observer-Observable technique. It gets triggered
65 * when the CBTHSettingsList wants to. (Normally when changes occur, here when
66 * a new fragment is filtered.)
67 */
68 public void update(Observable arg0, Object arg1) {
69
70 p_CBTHSettingSelection.removeAll();
71
72 ArrayList<CBTHSetting> arrayListSelection = cbthsl
73 .getCBTHSettingSelection();
74 VisualCBTHSetting vcbths;
75
76 for (CBTHSetting cbths : arrayListSelection) {
77
78 JPanel p_OneSettingPanel = new JPanel(new GridLayout(0, 2, 20, 0));
79 p_OneSettingPanel.setMaximumSize(new Dimension(Short.MAX_VALUE,
80 (int) p_OneSettingPanel.getMinimumSize().getHeight()));
81 vcbths = cbths.createVCBTHSetting();
82
83 vcbths.getL_CBTHSLabel().setAlignmentX(Component.LEFT_ALIGNMENT);
84 p_OneSettingPanel.add(vcbths.getL_CBTHSLabel());
85
86 vcbths.getTF_CBTHSValue().setAlignmentX(Component.LEFT_ALIGNMENT);
87 p_OneSettingPanel.add(vcbths.getTF_CBTHSValue());
88
89 p_CBTHSettingSelection.add(p_OneSettingPanel);
90 p_CBTHSettingSelection.add(Box.createRigidArea(new Dimension(0, 5)));
91 }
92
93 // Create stretchable blank space:
94 p_CBTHSettingSelection.add(Box.createVerticalGlue());
95
96 sp_ScrollPane.setViewportView(p_CBTHSettingSelection);
97 sp_ScrollPane.repaint();
98 }
99 }
1 package view;
2
3 import java.awt.Color;
4 import java.awt.Font;
5 import java.awt.GridLayout;
6 import java.util.Observable;
7 import java.util.Observer;
8 import javax.swing.*;
9
10 import listeners.cube.Co_CUBE_ColorsOnCubeFaceDropdownListener;
11 import model.CBTHSettingsList;
12 import model.CommonObjects;
13 import model.CubeFace;
14
15 public class VisualCubeFace extends JPanel implements Observer {
16
17 private static final long serialVersionUID = 1L;
18 private static CBTHSettingsList cbthsl = CommonObjects.getCBTHSettingsList();
19 private static String[] kubusKleuren = cbthsl.getCubeColors();
20 private static Font guiFont1 = cbthsl.getFont("guiFont1");
21 private CubeFace cf;
22 private JComboBox[][] comboBoxMatrix;
23 private Co_CUBE_ColorsOnCubeFaceDropdownListener[][] dropdownListenerMatrix;
24 private JLabel[][] labelMatrix;
25
26 // Constructor:
27 public VisualCubeFace(CubeFace cf) {
28
29 super();
30 this.cf = cf;
31
32 this.setLayout(new GridLayout(3, 6));
33
34 comboBoxMatrix = new JComboBox[3][3];
35 JComboBox<String> comBox = null;
36 dropdownListenerMatrix = new Co_CUBE_ColorsOnCubeFaceDropdownListener[3][3];
37
38 labelMatrix = new JLabel[3][3];
39 JLabel label = null;
40
41 for (int r = 0; r < comboBoxMatrix.length; r++) {
42
43 for (int s = 0; s < comboBoxMatrix[0].length; s++) {
44
45 // Prepare 3 colums of comboboxes:
46 comBox = new JComboBox<String>(kubusKleuren);
47 comBox.setEditable(false);
48 comBox.setSelectedItem(cbthsl.translateColorsIntToString(6));
49 comBox.setFont(guiFont1);
50 comBox.setMaximumSize(comBox.getMinimumSize());
51
52 dropdownListenerMatrix[r][s] = new Co_CUBE_ColorsOnCubeFaceDropdownListener(
53 cf, r, s);
54 comBox.addItemListener(dropdownListenerMatrix[r][s]);
55
56 comboBoxMatrix[r][s] = comBox;
57 this.add(comBox);
58 comBox = null;
59 }
60
61 for (int t = 0; t < labelMatrix[0].length; t++) {
62
63 // Prepare 3 columns of labels.
64 label = cbthsl.createJLabel("0.0%", 1);
65 label.setOpaque(true);
66 label.setMaximumSize(label.getMinimumSize());
67
68 labelMatrix[r][t] = label;
69 this.add(label);
70 }
71 }
72 }
73
74 // Instance methods:
75 public void comboboxesActive(boolean active) {
76
77 for (int i = 0; i < comboBoxMatrix.length; i++) {
78 for (int j = 0; j < comboBoxMatrix[0].length; j++) {
79 dropdownListenerMatrix[i][j].setActive(active);
80 }
81 }
82 }
83
84 /**
85 * This method is part of the Observer-Observable technique. It gets triggered
86 * when the CubeFace wants to. (Normally when changes occur.)
87 */
88 public void update(Observable arg0, Object arg1) {
89
90 int[][] colorsMatrix = cf.getColorsMatrix();
91 double[][] confidencesMatrix = cf.getConfidenceMatrix();
92
93 double thresholdColorEstimation = cbthsl
94 .getDouble("thresholdColorEstimation");
95
96 if (colorsMatrix != null) {
97 JLabel labelTemp = null;
98 /*
99 * Avoid them updating all the time while refreshing. There's a problem
100 * that the listeners applied to the comboBoxes trigger all the time when
101 * the combo- BoxMatrix[][] gets its new items in this method. To save all
102 * the extra effort, they're made inactive.
103 */
104 comboboxesActive(false);
105
106 for (int r = 0; r < colorsMatrix.length; r++) {
107 for (int s = 0; s < colorsMatrix[0].length; s++) {
108 comboBoxMatrix[r][s]
109 .setSelectedItem(kubusKleuren[(colorsMatrix[r][s])]);
110 }
111 }
112 comboboxesActive(true);
113
114 for (int r = 0; r < colorsMatrix.length; r++) {
115 for (int t = 0; t < confidencesMatrix[0].length; t++) {
116
117 labelTemp = labelMatrix[r][t];
118 labelTemp.setText(confidencesMatrix[r][t] + "%");
119
120 if (confidencesMatrix[r][t] == 100) {
121 labelTemp.setBackground(Color.GREEN);
122 labelTemp.setForeground(Color.BLACK);
123 } else {
124 if (confidencesMatrix[r][t] > thresholdColorEstimation
125 && confidencesMatrix[r][t] < 100) {
126 // Certaintylevel is above threshold but less than 100%.
127 labelTemp.setBackground(new Color(255, 140, 0));// Orange
128 labelTemp.setForeground(Color.BLACK);
129 } else {
130 // Certaintylevel is below threshold.
131 labelTemp.setBackground(Color.RED);
132 labelTemp.setForeground(Color.WHITE);
133 }
134 }
135 }
136 }
137 // This lines below have been added to make sure the panel updates within
138 // the pop-up window.
139 this.revalidate();
140 this.repaint();
141 }
142 }
143 }