diff --git a/P/Sda1/Vaadin/Sudoku/.gitignore b/P/Sda1/Vaadin/Sudoku/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..660be2a5fdb9e3019ef8fc737d47fba56fc32ff3 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/.gitignore @@ -0,0 +1,5 @@ +.project +.classpath +/.settings/ +/target/ +A1.log \ No newline at end of file diff --git a/P/Sda1/Vaadin/Sudoku/pom.xml b/P/Sda1/Vaadin/Sudoku/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..749d5375fa7743d7a81425a028bf88d0c41f7c40 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/pom.xml @@ -0,0 +1,89 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.hdm-stuttgart.mi</groupId> + <artifactId>lecturenotes-pom</artifactId> + <version>1.0</version> + + <relativePath>../../../pom.xml</relativePath> + </parent> + + <groupId>de.hdm-stuttgart.mi.sda1</groupId> + <artifactId>sudoku</artifactId> + <packaging>jar</packaging> + + <name>Sudoku</name> + <url>http://www.mi.hdm-stuttgart.de/freedocs</url> + + <properties> + <vaadin.version>7.5.0</vaadin.version> + </properties> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>2.5.2</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>2.5</version> + </plugin> + + <plugin> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-maven-plugin</artifactId> + <version>9.3.0.v20150612</version> + <configuration> + <scanIntervalSeconds>1</scanIntervalSeconds> + </configuration> + </plugin> + + </plugins> + + </build> + <repositories> + <repository> + <id>vaadin-addons</id> + <url>http://maven.vaadin.com/vaadin-addons</url> + </repository> + <repository> + <id>vaadin-snapshots</id> + <name>Vaadin snapshot repository</name> + <url>http://oss.sonatype.org/content/repositories/vaadin-snapshots/</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-server</artifactId> + <version>${vaadin.version}</version> + </dependency> + <dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-client-compiled</artifactId> + <version>${vaadin.version}</version> + </dependency> + <dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-themes</artifactId> + <version>${vaadin.version}</version> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + + </dependencies> + + <version>0.9</version> +</project> diff --git a/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerBuffer.java b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..fdc381ab6f629bd1e8d25eace3aef6d8c7115fed --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerBuffer.java @@ -0,0 +1,41 @@ +package de.hdm_stuttgart.mi.sudoku.model; + +import java.util.Optional; + +import com.vaadin.data.Property; + +public class IntegerBuffer implements Property<Integer>{ + + private static final long serialVersionUID = 8674877251186847351L; + + final boolean isReadonly; + Optional<Integer> value; + + public IntegerBuffer(final boolean isReadonly, final Integer value) { + this.value = Optional.ofNullable(value); + this.isReadonly = isReadonly; + } + + @Override + public void setValue(Integer value) + throws ReadOnlyException { + if (isReadonly) { + throw new ReadOnlyException("Read only integer property value=" + value); + } + } + @Override + public Integer getValue() { + return value.orElse(null); + } + @Override + public Class<? extends Integer> getType() { + return Integer.class; + } + @Override + public boolean isReadOnly() { + return isReadonly; + } + @Override + public void setReadOnly(boolean newStatus) { + } +} diff --git a/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerConverter.java b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..366a3d817b905114a786818ca70a59ed9ade0b6c --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/IntegerConverter.java @@ -0,0 +1,65 @@ +package de.hdm_stuttgart.mi.sudoku.model; + +import java.util.Locale; + +import com.vaadin.data.util.converter.Converter; + +public class IntegerConverter implements Converter <String, Integer> { + + final SudokuBoard sudokuBoard; + final int xCoord; + final int yCoord; + private static final long serialVersionUID = 4897340072093396209L; + + public IntegerConverter(final SudokuBoard sudokuBoard, final int yCoord, final int xCoord){ + this.sudokuBoard = sudokuBoard; + this.yCoord = yCoord; + this.xCoord = xCoord; + } + + @Override + public Integer convertToModel(String value, + Class<? extends Integer> targetType, Locale locale) + throws ConversionException { + if (null == value || 0 == value.trim().length()) { + return new Integer(0); + } else { + try { + final int v = Integer.parseInt(value); + if (1 <= v && v <= 10) { + final String errMsg = sudokuBoard.checkValue(v, yCoord, xCoord); + if (null == errMsg) { + return Integer.parseInt(value); + } else { + throw new ConversionException(errMsg); + } + } else { + throw new ConversionException("Must be 1,2,... or 9"); + } + } catch (NumberFormatException e) { + throw new ConversionException("Must be 1,2,... or 9"); + } + } + } + + @Override + public String convertToPresentation(Integer value, + Class<? extends String> targetType, Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + if (null == value || value == 0) { + return ""; + } else { + return value.toString(); + } + } + + @Override + public Class<Integer> getModelType() { + return Integer.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } +} diff --git a/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/SudokuBoard.java b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/SudokuBoard.java new file mode 100644 index 0000000000000000000000000000000000000000..06f3e11fb9d8671cc614e2fffac23f012d5f5ed6 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/model/SudokuBoard.java @@ -0,0 +1,121 @@ +package de.hdm_stuttgart.mi.sudoku.model; + +import java.util.HashSet; +import java.util.Set; + + +public class SudokuBoard { + + static public final String + ERRMSG_3CELL_DUPLICATE = "3x3 cell has duplicate", + ERRMSG_ROW_DUPLICATE = "duplicate in row", + ERRMSG_COL_DUPLICATE = "duplicate in COLUMN" + ; + + static public final int size = 9; + + static private final String data = + /**/ "000" + "260" + "701" + + "680" + "070" + "090" + + "190" + "004" + "500" + + //----+-------+-------+ + "820" + "100" + "040" + + "004" + "602" + "900" + + "050" + "003" + "028" + + //----+-------+-------+ + "009" + "300" + "074" + + "040" + "050" + "036" + + "703" + "018" + "000"; + + final IntegerBuffer [][] parseData() { + + final IntegerBuffer[][] cells = new IntegerBuffer[size][]; + for (int y = 0; y < size; y++) { + final IntegerBuffer[] row = new IntegerBuffer[size]; + cells[y] = row; + for (int x = 0; x < size; x++) { + final Integer intVal = new Integer(data.charAt(x + y * size) - '0'); + + if (0 == intVal) { + row[x] = new IntegerBuffer(false, null);// "free" sudoku position, set null ==> will later be editable + } else { + row[x] = new IntegerBuffer(true, intVal); // preset sudoku position ==> is not editable + } + } + } + return cells; + } + + public String checkValue(final int value, final int yCoordinate, final int xCoordinate) { + + + // Check values in 3 x 3 subwindow + final Set<Integer> checkDuplicates = new HashSet<Integer>(); + final int + xSubwinBase = (xCoordinate / 3) * 3, + ySubwinBase = (yCoordinate / 3) * 3; + + for (int y = ySubwinBase; y < ySubwinBase + 3; y++) { + for (int x = xSubwinBase; x < xSubwinBase + 3; x++) { + if (x != xCoordinate || y != yCoordinate) { + cells[y][x].value.ifPresent(checkDuplicates::add); + } + } + } + if (checkDuplicates.contains(value)) { + return ERRMSG_3CELL_DUPLICATE; + } + + // check for y - row + checkDuplicates.clear(); + for (int x = 0; x < size; x++) { + if (x != xCoordinate) { + cells[yCoordinate][x].value.ifPresent(checkDuplicates::add); + } + } + if (checkDuplicates.contains(value)) { + return ERRMSG_ROW_DUPLICATE; + } + + // check for x - column + checkDuplicates.clear(); + for (int y = 0; y < size; y++) { + if (y != yCoordinate) { + cells[y][xCoordinate].value.ifPresent(checkDuplicates::add); + } + } + if (checkDuplicates.contains(value)) { + return ERRMSG_COL_DUPLICATE; + } + return null; + } + + public final IntegerBuffer[][] cells = parseData(); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/ui/HelloUi.java b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/ui/HelloUi.java new file mode 100644 index 0000000000000000000000000000000000000000..ac4fdd1ec51aa607e760c5f9fb0cfa98e7958ef5 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/main/java/de/hdm_stuttgart/mi/sudoku/ui/HelloUi.java @@ -0,0 +1,76 @@ +package de.hdm_stuttgart.mi.sudoku.ui; + +import javax.servlet.annotation.WebServlet; + +import com.vaadin.annotations.Theme; +import com.vaadin.annotations.Title; +import com.vaadin.annotations.VaadinServletConfiguration; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinServlet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Table; +import com.vaadin.ui.TextField; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +import de.hdm_stuttgart.mi.sudoku.model.IntegerConverter; +import de.hdm_stuttgart.mi.sudoku.model.SudokuBoard; + +/** + * Playing Sudoku. Inspired by http://www.sudoku-solutions.com/ + * + */ +@Title("Intro") +@Theme("valo") +public class HelloUi extends UI { + + private static final long serialVersionUID = -307591917714387247L; + + @Override + protected void init(VaadinRequest request) { + + final VerticalLayout mainLayout = new VerticalLayout(); + setContent(mainLayout); // Attach to the UI + + final Table table = new Table("Sudoku"); + table.setColumnHeaderMode(Table.ColumnHeaderMode.HIDDEN); + mainLayout.addComponent(table); + + table.setEditable(true); + table.setImmediate(true); + + + for (int x = 0; x < SudokuBoard.size; x++) { + final String colProperty = "p" + x; + table.addContainerProperty (colProperty, AbstractComponent.class, ""); + } + + final SudokuBoard board = new SudokuBoard(); + + for (int y = 0; y < SudokuBoard.size; y++) { + final AbstractComponent tf[] = new AbstractComponent[SudokuBoard.size]; + for (int x = 0; x < SudokuBoard.size; x++) { + final TextField t = new TextField(); + tf[x] = t; + + t.setWidth("4ex"); + t.setConversionError("{1}"); // See https://vaadin.com/forum/#!/thread/3625631 + t.setConverter(new IntegerConverter(board, y, x)); + t.setImmediate(true); + t.setPropertyDataSource(board.cells[y][x]); + } + + table.addItem(tf, y); + } + + } + + /** Deployment description . + * + */ + @WebServlet(urlPatterns = "/*") + @VaadinServletConfiguration(ui = HelloUi.class, productionMode = false) + public static class MyUIServlet extends VaadinServlet { + private static final long serialVersionUID = -2771410633323765889L; + } +} diff --git a/P/Sda1/Vaadin/Sudoku/src/main/resources/log4j2.xml b/P/Sda1/Vaadin/Sudoku/src/main/resources/log4j2.xml new file mode 100644 index 0000000000000000000000000000000000000000..eda4f3b0d781b09217fb4218285c39adf8d3c9c0 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.sda1.catalog2sax.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="debug"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/Sda1/Vaadin/Sudoku/src/test/java/de/hdm_stuttgart/mi/sudoku/test/InitBoard.java b/P/Sda1/Vaadin/Sudoku/src/test/java/de/hdm_stuttgart/mi/sudoku/test/InitBoard.java new file mode 100644 index 0000000000000000000000000000000000000000..aad015cb612efed1d979cf4d341899b715952e81 --- /dev/null +++ b/P/Sda1/Vaadin/Sudoku/src/test/java/de/hdm_stuttgart/mi/sudoku/test/InitBoard.java @@ -0,0 +1,32 @@ +package de.hdm_stuttgart.mi.sudoku.test; + +import org.junit.Assert; +import org.junit.Test; + +import de.hdm_stuttgart.mi.sudoku.model.SudokuBoard; + +public class InitBoard { + + @Test + public void createBoard() { + final SudokuBoard board = new SudokuBoard(); + + Assert.assertEquals(null, board.checkValue(3, 0, 0)); + Assert.assertEquals(SudokuBoard.ERRMSG_3CELL_DUPLICATE, board.checkValue(6, 0, 0)); + Assert.assertEquals(SudokuBoard.ERRMSG_3CELL_DUPLICATE, board.checkValue(8, 0, 0)); + + Assert.assertEquals(null, board.checkValue(8, 1, 1)); + Assert.assertEquals(null, board.checkValue(3, 1, 1)); + + Assert.assertEquals(SudokuBoard.ERRMSG_3CELL_DUPLICATE, board.checkValue(6, 1, 1)); + + Assert.assertEquals(null, board.checkValue(3, 6, 3)); + Assert.assertEquals(SudokuBoard.ERRMSG_ROW_DUPLICATE, board.checkValue(4, 6, 3)); + Assert.assertEquals(SudokuBoard.ERRMSG_COL_DUPLICATE, board.checkValue(5, 3, 6)); + Assert.assertEquals(SudokuBoard.ERRMSG_ROW_DUPLICATE, board.checkValue(1, 3, 6)); + + + + } + +} diff --git a/P/pom.xml b/P/pom.xml index e243a0927915a8e75c8469dd023dfcf2ef46987f..b708ea3ba960cb93bd2538b4ed72b19d15d6dfb7 100644 --- a/P/pom.xml +++ b/P/pom.xml @@ -114,6 +114,7 @@ <module>Sda1/Jpa/rdbms2catalog/solution</module> <module>Sda1/Vaadin/IntegerSet</module> + <module>Sda1/Vaadin/Sudoku</module> <module>Sda1/Vaadin/IntegerSetSkeleton</module> <module>Sda1/VerifyImgAccess</module>